stud-ai/1-intro/1_tensor_tutorial.ipynb

16 KiB
Raw Blame History

%matplotlib inline

What is PyTorch?

Its 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 NumPys ndarrays, with the addition being that Tensors can also be used on a GPU to accelerate computing.

from __future__ import print_function
import torch

Note

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.

Construct a 5x3 matrix, uninitialized:

x = torch.empty(5, 3)
print(x)
tensor([[-1.7501e-10,  4.5822e-41, -1.7501e-10],
        [ 4.5822e-41, -9.8701e-38,  4.5822e-41],
        [-9.8892e-38,  4.5822e-41, -9.8700e-38],
        [ 4.5822e-41, -9.8702e-38,  4.5822e-41],
        [-9.8701e-38,  4.5822e-41, -9.8703e-38]])

Construct a randomly initialized matrix:

x = torch.rand(5, 3)
print(x)
tensor([[0.8525, 0.7922, 0.2553],
        [0.2792, 0.6800, 0.7858],
        [0.4438, 0.6987, 0.0985],
        [0.7342, 0.1807, 0.5665],
        [0.0847, 0.8206, 0.6820]])

Construct a matrix filled zeros and of dtype long:

x = torch.zeros(5, 3, dtype=torch.long)
print(x)
tensor([[0, 0, 0],
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]])

Construct a tensor directly from data:

x = torch.tensor([5.5, 3])
print(x)
tensor([5.5000, 3.0000])

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

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
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], dtype=torch.float64)
tensor([[ 1.0131,  1.4739, -0.2482],
        [-1.8965, -1.6178,  0.4807],
        [ 0.1839,  0.3258, -0.6664],
        [-0.9516, -1.7041,  1.1624],
        [-0.4448, -1.1328, -0.5092]])

Get its size:

print(x.size())
torch.Size([5, 3])

Note

``torch.Size`` is in fact a tuple, so it supports all tuple operations.

Operations ^^^^^^^^^^ There are multiple syntaxes for operations. In the following example, we will take a look at the addition operation.

Addition: syntax 1

y = torch.rand(5, 3)
print(x + y)
tensor([[ 1.6789,  1.8680, -0.0202],
        [-1.2243, -1.5905,  0.8047],
        [ 0.5959,  0.7308, -0.1883],
        [-0.6292, -0.7051,  1.8369],
        [-0.0381, -0.2377, -0.1590]])

Addition: syntax 2

print(torch.add(x, y))
tensor([[ 1.6789,  1.8680, -0.0202],
        [-1.2243, -1.5905,  0.8047],
        [ 0.5959,  0.7308, -0.1883],
        [-0.6292, -0.7051,  1.8369],
        [-0.0381, -0.2377, -0.1590]])

Addition: providing an output tensor as argument

result = torch.empty(5, 3)
torch.add(x, y, out=result)
print(result)
tensor([[ 1.6789,  1.8680, -0.0202],
        [-1.2243, -1.5905,  0.8047],
        [ 0.5959,  0.7308, -0.1883],
        [-0.6292, -0.7051,  1.8369],
        [-0.0381, -0.2377, -0.1590]])

Addition: in-place

# adds x to y
y.add_(x)
print(y)
tensor([[ 1.6789,  1.8680, -0.0202],
        [-1.2243, -1.5905,  0.8047],
        [ 0.5959,  0.7308, -0.1883],
        [-0.6292, -0.7051,  1.8369],
        [-0.0381, -0.2377, -0.1590]])

Note

Any operation that mutates a tensor in-place is post-fixed with an ``_``. For example: ``x.copy_(y)``, ``x.t_()``, will change ``x``.

You can use standard NumPy-like indexing with all bells and whistles!

print(x[:, 1])
tensor([ 1.4739, -1.6178,  0.3258, -1.7041, -1.1328])

Resizing: If you want to resize/reshape tensor, you can use torch.view:

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())
torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])

If you have a one element tensor, use .item() to get the value as a Python number

x = torch.randn(1)
print(x)
print(x.item())
tensor([-0.8622])
-0.8622472882270813

Read later:

100+ Tensor operations, including transposing, indexing, slicing, mathematical operations, linear algebra, random numbers, etc., are described here <https://pytorch.org/docs/torch>_.

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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

a = torch.ones(5)
print(a)
tensor([1., 1., 1., 1., 1.])
b = a.numpy()
print(b)
[1. 1. 1. 1. 1.]

See how the numpy array changed in value.

a.add_(1)
print(a)
print(b)
tensor([2., 2., 2., 2., 2.])
[2. 2. 2. 2. 2.]

Converting NumPy Array to Torch Tensor

See how changing the np array changed the Torch Tensor automatically

import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out=a)
print(a)
print(b)
[2. 2. 2. 2. 2.]
tensor([2., 2., 2., 2., 2.], dtype=torch.float64)

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.

# let us run this cell only if CUDA is available
# We will use ``torch.device`` objects to move tensors in and out of GPU
print(torch.__version__)
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!
    
1.7.0
/usr/local/lib/python3.6/dist-packages/torch/cuda/__init__.py:81: UserWarning: 
    Found GPU0 GeForce GTX 760 which is of cuda capability 3.0.
    PyTorch no longer supports this GPU because it is too old.
    The minimum cuda capability that we support is 3.5.
    
  warnings.warn(old_gpu_warn % (d, name, major, capability[1]))
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-20-9fca8bb14c5b> in <module>
      4 if torch.cuda.is_available():
      5     device = torch.device("cuda")          # a CUDA device object
----> 6     y = torch.ones_like(x, device=device)  # directly create a tensor on GPU
      7     x = x.to(device)                       # or just use strings ``.to("cuda")``
      8     z = x + y

RuntimeError: CUDA error: no kernel image is available for execution on the device