Pytorch简介

Pytorch是一个基于Python的深度学习框架,可以代替Numpy在GPU上进行科学计算。

什么是Tensor

Tensor即张量,类似于Numpy的ndarrays,tensor可以在GPU上使用以加速计算。

Pytorch创建张量的常用方法

  1. 创建一个未初始化的张量,其值不确定:
# 初始化值不确定,由所分配内存的当前值决定
x = torch.empty(5, 3)
print(x)

运行后结果如下,可以看到元素的值是随机的,再次运行元素的值也会发生变化。

pytorch创建张量 pytorch张量赋值_共享内存

  1. 创建一个随机初始化的张量,元素值在0到1之间:
# 随机初始化矩阵,各元素的值在0到1之间
x = torch.rand(5, 3)
print(x)

运行结果如下。

pytorch创建张量 pytorch张量赋值_pytorch创建张量_02


3. 用0初始化创建张量,并设置元素类型为long:

# 用0初始化创建一个矩阵,并设置元素类型为long
x = torch.zeros((5, 3), dtype=torch.long)
print(x)

运行结果如下。

pytorch创建张量 pytorch张量赋值_python_03


4. 直接用数据构建张量:

# 直接从数据构造张量
x = torch.tensor([[5.5, 3], [1.2, 3.99]])
print(x)

运行结果如下。

pytorch创建张量 pytorch张量赋值_数据类型_04


5. 利用已有张量创建新张量,若未指定新的dtype,则dtype与已有张量相同:

# 利用已有张量创建新张量
x = x.new_ones((5, 3), dtype=torch.double)  # new_ 方法会改变对象大小
print(x)
x = torch.randn_like(x, dtype=torch.float)
print(x)

这里的x是已经创建过的张量,即一个实例化的对象,对象的new_方法会重置对象大小。运行结果如下。

pytorch创建张量 pytorch张量赋值_pytorch创建张量_05

查看Tensor的size

查看张量维度可以使用张量对象的size()方法:

# 查看张量维度
print(x.size())

结果如下。

pytorch创建张量 pytorch张量赋值_深度学习_06


Note:torch.Size类型实际是一个元组类型,因此它支持各种元组操作。

基本运算操作

加法操作要求两个张量的维度相同。

## 加法
y = torch.rand((5, 3))

print(x + y)  # 方法一
print(torch.add(x, y))  # 方法二

result = torch.empty((5, 3))
torch.add(x, y, out=result)  # 方法三,用out参数指定输出存储位置
print(result)

y.add_(x)   # 方法四,将x加到y上
print(y)

Note:当对象需要就地更改时,使用对象的_方法,如y.add_()将直接把结果保存至y。

索引操作类似Numpy,可以使用所有附加的功能。

## 索引操作
print(x)
print(x[:, 1])  # 取第二列

当Tensor只有一个元素时,可用item()方法取出元素。

## 取单个元素
x = torch.randn(1)
print(x)
print(x.item())  # 取元素

张量对象的view()方法可以重置张量维度。

## resize操作
x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8)  # 当设置-1时,该维度的值由其余维度的值来确定
print(x.size(), y.size(), z.size())

执行结果如下。

pytorch创建张量 pytorch张量赋值_pytorch创建张量_07

Tensor与Numpy的转换

tensor转换numpy可以调用.numpy()方法,但应当注意的是,torch tensor和numpy数组将共享基础内存位置(如果torch tensor在CPU上),并且当一个发生改时,另一个也会发生改变。

## tensor转换numpy
a = torch.ones(5)
print(a)
b = a.numpy()
print(b)
a.add_(1)
print(a)
print(b)

运行结果如下。

pytorch创建张量 pytorch张量赋值_共享内存_08


除了CharTensor之外,CPU上的所有Tensor都支持转换为NumPy并返回。

## numpy转换tensor
a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out=a)
print(a)
print(b)

运行结果如下。

pytorch创建张量 pytorch张量赋值_深度学习_09


Note:Numpy数组默认类型是float64,而Tensor数据的默认类型是float64,采用from_numpy()方法或torch.tensor()方法得到的tensor数据类型与numpy一致,即原先的numpy是float64,则得到的tensor也是float64;若采用torch.Tensor()方法(注意这里的T是大写),则得到的tensor为float32。此外,使用from_numpy()方法会共享内存;使用torch.tensor()方法只复制数据,不共享内存;使用torch.Tensor()方法当数据类型一致时,共享内存,不一致时,复制数据,不共享内存。测试代码如下:

当使用默认数据类型时:

# 测试数据类型
a = np.zeros(5)
b = torch.Tensor(a)
c = torch.tensor(a)
d = torch.from_numpy(a)
print("a:" + str(a.dtype), "\nb:" + str(b.dtype), "\nc:" + str(c.dtype), "\nd:" + str(d.dtype))
# 测试是否共享内存
a[2] = 100
print("a:", a)
print("b:", b)
print("c:", c)
print("d:", d)

执行结果:

pytorch创建张量 pytorch张量赋值_python_10


当修改numpy数据类型为float32后:

a = np.zeros(5, dtype=np.float32)   # 修改numpy数据类型为float32
b = torch.Tensor(a)
c = torch.tensor(a)
d = torch.from_numpy(a)
print("a:" + str(a.dtype), "\nb:" + str(b.dtype), "\nc:" + str(c.dtype), "\nd:" + str(d.dtype))
# 测试是否共享内存
a[2] = 100
print("a:", a)
print("b:", b)
print("c:", c)
print("d:", d)

执行结果:

pytorch创建张量 pytorch张量赋值_深度学习_11


总结如下表:

方法

是否保持数据类型

是否共享内存

from_numpy()



torch.tensor()



torch.Tensor()


仅数据类型一致时共享内存

在GPU上使用Tensor

如果存在可用的CUDA,使用.to()方法可以让Tensor在指定设备上进行计算。

# 在GPU上使用tensor
if torch.cuda.is_available():
    device = torch.device("cuda")  # 一个CUDA设备对象
    y = torch.ones_like(x, device=device)  # 直接在GPU上创建tensor
    x = x.to(device)  # 或者使用 x = x.to("cuda")
    z = x + y
    print(z)
    print(z.to("cpu", torch.double))    # .to 方法也可以同时改变dtype

运行结果如下。

pytorch创建张量 pytorch张量赋值_python_12