PyTorch
Table of Contents
1 PyTorch
PyTorch 和 Numpy 的数组和相似,PyTorch 的数据类型大多数是叫 Tensor,并且 Tensor 可以在 GPU 上进行计算,用于提高计算效率
import torch import torch.nn as nn import torch.nn.functional as F import torchvision import torchvision.transforms as transforms import numpy as np torch.set_printoptions(linewidth=200)
2 基础运算
2.1 初始化、数据类型
x0 = torch.zeros(2, 3) x1 = torch.ones(3, 2) x2 = torch.zeros(2, 3, dtype=torch.long) # dtype: int32 int64 float32 float64 x3 = torch.tensor([1.1, 3.0]) print(x1) print(x2) print(x3)
tensor([[1., 1.], [1., 1.], [1., 1.]]) tensor([[0, 0, 0], [0, 0, 0]]) tensor([1.1000, 3.0000])
获取默认创建的数据类型
print(torch.get_default_dtype())
torch.float32
2.2 获取形状
获取 Tensor 的形状和元素数量
x1 = torch.tensor([1.1, 3.0]) print(x1.size()) print(x1.numel()) # number of elements x2 = torch.tensor([[1.1, 3.0, 3.3], [3, 4, 5]]) print(x2.size()) print(x2.numel())
torch.Size([2]) 2 torch.Size([2, 3]) 6
2.3 Tensor 和 ndarray 数据类型互转
t1 = torch.randn((2, 3)) # normal distribution with shape (2,3) a1 = t1.numpy() print(t1) print(a1) a2 = np.random.normal(0, 0.01, 6) t2 = torch.from_numpy(a2) print(a2) print(t2)
tensor([[-0.0652, -0.3537, 1.3550], [-0.6979, -0.7713, -0.5261]]) [[-0.0652356 -0.35367048 1.3549587 ] [-0.6978578 -0.7712709 -0.5261264 ]] [-0.0092347 -0.00012146 -0.00581832 -0.00620685 -0.00119326 -0.00189925] tensor([-0.0092, -0.0001, -0.0058, -0.0062, -0.0012, -0.0019], dtype=torch.float64)
PyTorch 和 Numpy 数据关系包含两种关系:share vs. copy
a = np.array([1, 2, 3]) print(a) t1 = torch.Tensor(a) t2 = torch.tensor(a) t3 = torch.as_tensor(a) t4 = torch.from_numpy(a) a[0] = 0 a[1] = 0 print(t1) print(t2) print(t3) print(t4)
[1 2 3] tensor([1., 2., 3.]) tensor([1, 2, 3]) tensor([0, 0, 3]) tensor([0, 0, 3])
3 形状变换
3.1 变形
如果想要 resize 或 reshape 一个 tensor,可以使用 view 方法。如果需要 copy,用 clone, 如果需要源数据,用 view, reshape 这玩意不好控制,则没那么可控,他的执 行结果可能是源数据的一个 copy,也可能不是,最好少用
x1 = torch.randn(24) x2 = x1.view(2, 3, 4) x3 = x1.view(4, -1) print(x2) print(x3)
tensor([[[-0.0513, 1.5727, 1.4737, 0.3913], [ 2.2639, 0.4963, 0.3401, -0.2731], [-1.4023, 1.7182, 0.9297, 0.1243]], [[-0.4909, -0.5568, 1.9808, 0.7490], [ 0.1885, 0.4245, 0.0027, -0.8911], [-0.7410, 1.0522, -0.8816, -2.5483]]]) tensor([[-0.0513, 1.5727, 1.4737, 0.3913, 2.2639, 0.4963], [ 0.3401, -0.2731, -1.4023, 1.7182, 0.9297, 0.1243], [-0.4909, -0.5568, 1.9808, 0.7490, 0.1885, 0.4245], [ 0.0027, -0.8911, -0.7410, 1.0522, -0.8816, -2.5483]])
如果 tensor 里只有一个数字,item 方法可以把里面的 value 变成 Python 数值
x = torch.randn(1) print(x) print(x.item())
tensor([-0.4755]) -0.47550874948501587
修改矩阵的形状,转置,交换维度等操作
x = torch.arange(12).view(2, 3, 2) print(x) print(x.transpose(1, 0)) print(x.permute(1, 0, 2))
tensor([[[ 0, 1], [ 2, 3], [ 4, 5]], [[ 6, 7], [ 8, 9], [10, 11]]]) tensor([[[ 0, 1], [ 6, 7]], [[ 2, 3], [ 8, 9]], [[ 4, 5], [10, 11]]]) tensor([[[ 0, 1], [ 6, 7]], [[ 2, 3], [ 8, 9]], [[ 4, 5], [10, 11]]])
压扁给定的维度为 1 的维度值
x = torch.arange(6).view(1, -1) print(x.shape) print(x) a1 = x.squeeze(0) print(a1.shape) print(a1) a2 = a1.unsqueeze(0) print(a2)
torch.Size([1, 6]) tensor([[0, 1, 2, 3, 4, 5]]) torch.Size([6]) tensor([0, 1, 2, 3, 4, 5]) tensor([[0, 1, 2, 3, 4, 5]])
定义一个 flatten 函数,将输入数据扁平化
def flatten(t): t = t.view(1, -1) t = t.squeeze() return t x1 = torch.tensor([1, 2, 3, 4, 5, 6], dtype=torch.float32).reshape(2, 3) print(x1) print(flatten(x1))
tensor([[1., 2., 3.], [4., 5., 6.]]) tensor([1., 2., 3., 4., 5., 6.])
3.2 拼接
将多个张量合并拼接成一个向量
t1 = torch.tensor([[1, 2], [3, 4]]) t2 = torch.tensor([[5, 6], [7, 8]]) x1 = torch.cat((t1, t2), dim=0) print(x1) x2 = torch.cat((t1, t2), dim=1) print(x2)
tensor([[1, 2], [3, 4], [5, 6], [7, 8]]) tensor([[1, 2, 5, 6], [3, 4, 7, 8]])
4 CUDA 技术
Tensor 可以放在 CUDA 显卡上进行计算
x = torch.randn(2, 3) if torch.cuda.is_available(): device = torch.device("cuda:0") # 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! else: print("gpu is not available")
gpu is not available
5 定义模型
PyTorch 构造模型时主要包含两个步骤:
- 继承
nn.Module
类 - 实现
forward()
方法
import torch import torch.nn as nn class Network(nn.Module): def __init__(self): super(Network, self).__init__() def forward(self, in_data): out_data = in_data return out_data
5.1 实验代码
完整的定义网络模型的代码参考如下代码
import torch import torch.nn as nn import torch.nn.functional as F import torchvision import torchvision.transforms as transforms torch.set_printoptions(linewidth=200) class Network(nn.Module): def __init__(self): super().__init__() self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5) self.conv2 = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=5) self.fc1 = nn.Linear(in_features=12 * 4 * 4, out_features=120) self.fc2 = nn.Linear(in_features=120, out_features=60) self.out = nn.Linear(in_features=60, out_features=10) def forward(self, t): t = F.relu(self.conv1(t)) t = F.max_pool2d(t, kernel_size=2, stride=2) t = F.relu(self.conv2(t)) t = F.max_pool2d(t, kernel_size=2, stride=2) t = F.relu(self.fc1(t.view(-1, 12 * 4 * 4))) t = F.relu(self.fc2(t)) t = self.out(t) return t train_set = torchvision.datasets.FashionMNIST( root='./data', train=True, download=True, transform=transforms.Compose([transforms.ToTensor()]) ) network = Network() sample = next(iter(train_set)) image, label = sample image.unsqueeze(0).shape pred = network(image.unsqueeze(0)) print(pred) print(pred.argmax(dim=1))
tensor([[ 0.0885, 0.1149, 0.0712, 0.0994, -0.0972, 0.0525, -0.0515, 0.0867, 0.1027, 0.0180]], grad_fn=<AddmmBackward>) tensor([1])
6 附录
安装 PyTorch 之前最好是配合 Anaconda3 发行版一起安装,安装好 Anaconda 过后直接 使用下面命令安装
conda install pytorch torchvision -c pytorch
也可以使用 pip 安装对应的 wheel 包
pip3 install torch torchvision