<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Original Notebook
Introduction to PyTorch Tensor
Reference
Step1:  <div class="alert alert-info"><h4>Note</h4><p>An uninitialized matrix is declared,
    but does not contain definite known
    values before it is used. When an
    uninitialized matrix is created,
    whatever values were in the allocated
    memory at the time will appear as the initial values.</p></div>
Construct a 5x3 matrix, uninitialized
Step2:  Construct a randomly initialized matrix
Step3:  Construct a matrix filled zeros and of dtype long
Step4:  Construct a tensor directly from data
Step5:  or create a tensor based on an existing tensor. These methods
will reuse properties of the input tensor, e.g. dtype, unless
new values are provided by user
Step6:  Get its size
Step7:  <div class="alert alert-info"><h4>Note</h4><p>``torch.Size`` is in fact a tuple, so it supports all tuple operations.</p></div>
Operations
^^^^^^^^^^
There are multiple syntaxes for operations. In the following
example, we will take a look at the addition operation.
Addition
Step8:  Addition
Step9:  Addition
Step10:  Addition
Step11:  <div class="alert alert-info"><h4>Note</h4><p>Any operation that mutates a tensor in-place is post-fixed with an ``_``.
    For example
Step12:  Resizing
Step13:  If you have a one element tensor, use .item() to get the value as a
Python number
Step14:  Read later
Step15:  See how the numpy array changed in value.
Step16:  Converting NumPy Array to Torch Tensor
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
See how changing the np array changed the Torch Tensor automatically
Step17:  All the Tensors on the CPU except a CharTensor support converting to
NumPy and back.
CUDA Tensors
Tensors can be moved onto any device using the .to method.
<ASSISTANT_TASK:>
Python Code:
import torch
Explanation: Original Notebook
Introduction to PyTorch Tensor
Reference: "What is PyTorch?" by Soumith Chintala
What is PyTorch?
It’s a Python-based scientific computing package targeted at two sets of
audiences:
A replacement for NumPy to use the power of GPUs
a deep learning research platform that provides maximum flexibility
   and speed
Getting Started
Tensors
^^^^^^^
Tensors are similar to NumPy’s ndarrays, with the addition being that
Tensors can also be used on a GPU to accelerate computing.
End of explanation
x = torch.empty(5, 3)
print(x)
type(x)
Explanation: <div class="alert alert-info"><h4>Note</h4><p>An uninitialized matrix is declared,
    but does not contain definite known
    values before it is used. When an
    uninitialized matrix is created,
    whatever values were in the allocated
    memory at the time will appear as the initial values.</p></div>
Construct a 5x3 matrix, uninitialized:
End of explanation
x = torch.rand(5, 3)
print(x)
Explanation: Construct a randomly initialized matrix:
End of explanation
x = torch.zeros(5, 3, dtype=torch.long)
print(x)
Explanation: Construct a matrix filled zeros and of dtype long:
End of explanation
x = torch.tensor([5.5, 3])
print(x)
Explanation: Construct a tensor directly from data:
End of explanation
x = x.new_ones(5, 3, dtype=torch.double)      # new_* methods take in sizes
print(x)
x = torch.randn_like(x, dtype=torch.float)    # override dtype!
print(x)                                      # result has the same size
Explanation: or create a tensor based on an existing tensor. These methods
will reuse properties of the input tensor, e.g. dtype, unless
new values are provided by user
End of explanation
print(x.size())
Explanation: Get its size:
End of explanation
y = torch.rand(5, 3)
print(x + y)
Explanation: <div class="alert alert-info"><h4>Note</h4><p>``torch.Size`` is in fact a tuple, so it supports all tuple operations.</p></div>
Operations
^^^^^^^^^^
There are multiple syntaxes for operations. In the following
example, we will take a look at the addition operation.
Addition: syntax 1
End of explanation
print(torch.add(x, y))
Explanation: Addition: syntax 2
End of explanation
result = torch.empty(5, 3)
torch.add(x, y, out=result)
print(result)
Explanation: Addition: providing an output tensor as argument
End of explanation
# adds x to y
y.add_(x)
print(y)
Explanation: Addition: in-place
End of explanation
print(x[:, 1])
Explanation: <div class="alert alert-info"><h4>Note</h4><p>Any operation that mutates a tensor in-place is post-fixed with an ``_``.
    For example: ``x.copy_(y)``, ``x.t_()``, will change ``x``.</p></div>
You can use standard NumPy-like indexing with all bells and whistles!
End of explanation
x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8)  # the size -1 is inferred from other dimensions
print(x.size(), y.size(), z.size())
Explanation: Resizing: If you want to resize/reshape tensor, you can use torch.view:
End of explanation
x = torch.randn(1)
print(x)
print(x.item())
Explanation: If you have a one element tensor, use .item() to get the value as a
Python number
End of explanation
a = torch.ones(5)
print(a)
b = a.numpy()
print(b)
Explanation: Read later:
100+ Tensor operations, including transposing, indexing, slicing,
  mathematical operations, linear algebra, random numbers, etc.,
  are described
  here &lt;https://pytorch.org/docs/torch&gt;_.
NumPy Bridge
Converting a Torch Tensor to a NumPy array and vice versa is a breeze.
The Torch Tensor and NumPy array will share their underlying memory
locations (if the Torch Tensor is on CPU), and changing one will change
the other.
Converting a Torch Tensor to a NumPy Array
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
End of explanation
a.add_(1)
print(a)
print(b)
Explanation: See how the numpy array changed in value.
End of explanation
import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out=a)
print(a)
print(b)
Explanation: Converting NumPy Array to Torch Tensor
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
See how changing the np array changed the Torch Tensor automatically
End of explanation
# let us run this cell only if CUDA is available
# We will use ``torch.device`` objects to move tensors in and out of GPU
if torch.cuda.is_available():
    device = torch.device("cuda")          # a CUDA device object
    y = torch.ones_like(x, device=device)  # directly create a tensor on GPU
    x = x.to(device)                       # or just use strings ``.to("cuda")``
    z = x + y
    print(z)
    print(z.to("cpu", torch.double))       # ``.to`` can also change dtype together!
Explanation: All the Tensors on the CPU except a CharTensor support converting to
NumPy and back.
CUDA Tensors
Tensors can be moved onto any device using the .to method.
End of explanation
<END_TASK>