Creación de un Tensor

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 torchtorch.cuda  y en la clase torch.Tensor. En los próximos tutoriales continuaremos aprendiendo de los tensores.
Referencias

0 comentarios

Dejar un comentario

¿Quieres unirte a la conversación?
Siéntete libre de contribuir

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *