Creación de un Tensor en Pytorch
Autor: Andrea Mercuri
Al igual que los otros Framework para el deep learning, también en PyTorch son absolutamente esenciales los tensores. Cuando representamos los cálculos que son efectuados por una red neuronal como operaciones tensoriales obtenemos dos ventajas: utilizamos un código matemático compacto y permitimos que la CPU haga cálculos paralelos.
Los tensores pueden residir en la RAM principal de la computadora y ser procesados por la CPU o RAM de una tarjeta de video y procesados por una GPU. Estos últimos se identifican por una series de diferencias de los primeros. A continuación veremos una lista de todos los tipos de tensores presentes en PyTorch.
Tipo | Tensores CPU | Tensores GPU |
32-bit coma flotante | torch.FloatTensor | torch.cuda.FloatTensor |
64-bit coma flotante | torch.DoubleTensor | torch.cuda.DoubleTensor |
16-bit coma flotante | torch.HalfTensor | torch.cuda.HalfTensor |
8-bit entero (sin signo) | torch.ByteTensor | torch.cuda.ByteTensor |
8-bit entero (con signo) | torch.CharTensor | torch.cuda.CharTensor |
16-bit entero (con signo) | torch.ShortTensor | torch.cuda.ShortTensor |
32-bit entero (con signo) | torch.IntTensor | torch.cuda.IntTensor |
64-bit entero (con signo) | torch.LongTensor | torch.cuda.LongTensor |
En primer lugar importamos PyTorch.
import torch
Podemos crear un tensor estos siempre siempre tienen que inicializarlos llamando al constructor de uno de los tipos enumerados anteriormente.
x = torch.FloatTensor(3, 2) print(x)
1.00000e-25 * &nbsp&nbsp9.9872 0.0000 &nbsp&nbsp9.9872 0.0000 &nbsp&nbsp0.0000 0.0000 &nbsp&nbsp[torch.FloatTensor of size 3x2]
En este caso, el tensor se crea en la RAM principal. Si queremos crear un tensor en la GPU corriente, tenemos que usar uno de los tipos CUDA.
x = torch.cuda.FloatTensor(3, 2) print(x)
nan nan nan nan nan nan [torch.cuda.FloatTensor of size 3x2 (GPU 0)]
En este caso, nos enteramos que el tensor se encuentra en la primera GPU. Las GPU que están presentes en la máquina están enumeradas con números enteros a partir de 0.
Podemos crear tensores a partir de las listas de Python
torch.FloatTensor([[1,2,3],[4,5,6]])
1 2 3 4 5 6 [torch.FloatTensor of size 2x3]
o de array numpy.
x_np = np.array([1,2,3,4], dtype=np.float32) x = torch.FloatTensor(x_np)
Obtenemos el mismo resultado con el método from_numpy.
x = torch.from_numpy(x_np)
Notemos que el array numpy y el tensor PyTorch comparten los datos. Si cambiamos uno de los dos, el otro sufre los mismos cambios.
x[0] = 0 print(x_np)
[ 0., 2., 3., 4.]
print(x)
0 2 3 4 [torch.FloatTensor of size 4]
Podemos crear tensores desde otros tensores.
y = torch.FloatTensor(x) print(y)
0 2 3 4 [torch.FloatTensor of size 4]
Incluso en este caso, el tensor creado comparte los datos con el tensor original.
Podemos crear tensores desde cero.
torch.zeros(3,2)
0 0 0 0 0 0 [torch.FloatTensor of size 3x2]
Podemos crear tensores de números aleatorios extraídos de una determinada distribución, por ejemplo, espaciadas dentro el intervalo [0,1].
torch.rand(2, 3)
0.1256 0.0406 0.2072 0.2479 0.0515 0.093 [torch.FloatTensor of size 2x3]
Cada tensor vive en la memoria principal o en una tarjeta de video. Dos tensores pueden ser operandos de la misma operación solo si residen en la misma memoria ( en este caso el resultado aún reside en la misma memoria). Si tratamos de combinar (por ejemplo, sumando) un tensor que reside en la RAM principal y uno que está en una tarjeta de video (o dos tensores en dos tarjetas de video diferentes) será una excepción.
xcpu = torch.FloatTensor(3,2) xgpu = torch.cuda.FloatTensor(3,2) xcpu + xgpu
TypeError Traceback (most recent call last) in () ----> 1 xcpu + xgpu …
Si queremos obtener una copia de un tensor x en la primera GPU, podemos usar el método cuda.
y = x.cuda(device=0)
Si el tensor ya está en la primera GPU regresa el tensor original .En lugar de obtener una copia de un tensor x en la RAM principal, usamos el método cpu.
y = x.cpu()
Podemos convertir un tensor a otro tipo diferente pasando del método de type al tipo de destinacion.
y = x.type(torch.ByteTensor)
Obtenemos el mismo resultado al inserir un método específico de conversión.
y = x.byte()
Si además de cambiar el tipo queremos copiar el tensor en la GPU ,tenemos que pasar del método type a un tipo cuda.
y = x.type(torch.cuda.ByteTensor)
o escribir
y = x.byte().cuda()
Para usar la segunda GPU usamos set_device.
torch.cuda.set_device(1)
Si ahora escribimos
torch.cuda.current_device()
obtenemos 1 como valor de retorno. Esto significa que ahora la GPU actual es la segunda y no la primera y, por ejemplo, cuando usamos el método cuda en un tensor creamos una copia en la segunda GPU en lugar de la primera.
También se puede usar un context manager para cambiar temporalmente la GPU actual.
Por ejemplo, escribiendo
with torch.cuda.device(1): &nbsp&nbspx1 = torch.cuda.FloatTensor(2,3) x2 = torch.cuda.FloatTensor(2,3)
cuando en la GPU el índice es 0,x1 viene creado en la segunda GPU un (índice 1), x2 y en la primera (índice 0).
Todas las funciones relativas a las creaciónes de tensores están incluidas en los package torch, torch.cuda y en la clase torch.Tensor. En los próximos tutoriales continuaremos aprendiendo de los tensores.
Referencias
- http://pytorch.org/ (sitio oficial de PyTorch)
- http://pytorch.org/docs/master/ (documentacion)
- http://pytorch.org/tutorials/ (tutorial)
- https://github.com/pytorch (repository GitHub)