PyTorch Notes

Updated on Nov 19,2019

0 Install

国内安装需要添加清华源加速

# 添加清华源
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/
conda config --set show_channel_urls yes
# 安装
conda install pytorch torchvision cudatoolkit=9.0

1 CrossEntropyLoss & Softmax

因为 PyTorch 在 CrossEntropyLoss 损失函数中整合了 Softmax 激活函数,所以对于多分类神经网络,最后一层不需要添加激活函数,只要设定神经元个数为类别个数即可。

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(3 * 32 * 32, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)
    def forward(self, x):
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        # the last layer needs no activation function
        x = self.fc3(x)
        return x
        
criterion = nn.CrossEntropyLoss()
net = Net()
outputs = net(inputs)
# calculate loss
loss = criterion(outputs, labels)
# predict
predicted = torch.max(outputs.data, 1)[1]

2 归一化

from torchvision import transforms
transform = transforms.Compose(
            [transforms.ToTensor(),transforms.Normalize((0.1307,), (0.3081,))])

PyTorch在数据预处理时使用参数 transform 来定义对数据的归一化方式,将原始值域为 $[0,255]$ 的 numpy.ndarray 转换为值域为 $[0,1]$ 的Tensor。

这里面有两个操作,第一个transforms.ToTensor()是 Min-Max 归一化;

第二个transforms.Normalize()则是 Z-score 归一化,两组参数均值与标准差需要计算后赋值,因为定义的是单通道图像所以均值与标准差各只有1个。

参见下面这段代码:

img = np.array([[0, 32], [128, 255]], np.uint8)
plt.imshow(img, cmap='gray')
plt.show()
# x' = x / 255
tensor = transforms.functional.to_tensor(img.reshape(2,2,1))
print(tensor)
'''
tensor([[[ 0.0000,  0.1255],
         [ 0.5020,  1.0000]]])
'''
# x' = (x - mean) / std
tensor = transforms.functional.normalize(tensor, (0.407,), (0.389,)) 
print(tensor)
'''
tensor([[[-1.0463, -0.7237],
         [ 0.2441,  1.5244]]])
'''

3 参数dim

PyTorch中的参数dim,就是NumPy中的参数axis,参考下面两个函数定义:

# pytorch
torch.max(input, dim, keepdim=False, out=None)
torch.squeeze(input, dim=None, out=None)
# numpy
numpy.max(a, axis=None, out=None)
numpy.squeeze(a, axis=None)

对于二维矩阵,dim = 0 则以行(0维度)为轴,对各列进行“压缩”;dim = 1 则以列(1维度)为轴对各行进行“压缩”。参见下面这段代码:

>>> a = torch.randint(0, 10, (2, 3))
>>> a
tensor([[ 5.,  2.,  9.],
        [ 7.,  3.,  2.]])
>>> b = torch.max(a, 0)
>>> b
(tensor([ 7.,  3.,  9.]), tensor([ 1,  1,  0]))
>>> c = torch.max(a, 1)
>>> c
(tensor([ 9.,  7.]), tensor([ 2,  0]))

4 TBC

人は運命にはさからえませんから。