本系列笔记为莫烦PyTorch视频教程笔记 github源码
PyTorch的安装十分简单,根据PyTorch官网,对系统选择和安装方式等灵活选择即可。这里新建一个Python3的虚拟环境后,然后在虚拟环境下用pip安装,如下图所示
PyTorch 会安装两个模块, 一个是 torch, 一个 torchvision, torch 是主模块, 用来搭建神经网络的, torchvision 是辅模块, 有数据库, 还有一些已经训练好的神经网络等着你直接用, 比如 (VGG, AlexNet, ResNet).
pytorch是使用GPU和CPU优化的深度张量库,torch中最重要的一个数据类型就是Tensor(张量)
Tensor是PyTorch的计算单元,可以理解为:N-dim数组,跟Numpy类似。举栗如下:
常数,如:a1 = 1,为0阶Tensor;
向量,如:a2 = [2,1,5,1.1,2.3,1,5,1.1],为1阶Tensor(也可以说一个维度);
二阶矩阵为2阶Tensor(2个维度),如:a3 =
下面演示其中一些操作,PyTorch的Tensor全部运算,参见这里
import torch
import numpy as np
from torch.autograd import Variable
import torch.nn.functional as F # activation function
import matplotlib.pyplot as plt # python 的可视化模块,画图用
%matplotlib inline
x1 = torch.rand(5,3) # 创建一个5*3的随机矩阵
print(x1)
0.3658 0.7387 0.0901
0.4840 0.6414 0.1183
0.4703 0.8766 0.9165
0.7749 0.5472 0.4456
0.5532 0.4522 0.1290
[torch.FloatTensor of size 5x3]
x2 = torch.ones(5,3) # 创建 5*3 的全1矩阵
print(x2)
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
[torch.FloatTensor of size 5x3]
y1 = x1 + x2 # 两个矩阵相加
print(y1)
1.3658 1.7387 1.0901
1.4840 1.6414 1.1183
1.4703 1.8766 1.9165
1.7749 1.5472 1.4456
1.5532 1.4522 1.1290
[torch.FloatTensor of size 5x3]
Torch自称为神经网络界的Numpy,因为它能将torch产生的Tensor放在GPU中加速运算,就像Numpy的array可以在CPU中加速运算,且numpy array和torch tensor可以相互转换
所有numpy上关于ndarray的运算都可以运用于Tensor
从numpy到tensor的转换:torch.from_numpy(np_data)
从tensor到numpy的转换:np_data.numpy()
tensor与numpy的最大不同是:tensor可以在GPU上运算
np_data = np.arange(4).reshape(2,2)
torch_data = torch.from_numpy(np_data)
tensor2array = torch_data.numpy()
print(
'numpy array: \n', np_data,
'\n=================\n',
'\ntorch tensor: ', torch_data,
'\n==================\n',
'tensor to array: \n ', tensor2array
)
numpy array:
[[0 1]
[2 3]]
=================
torch tensor:
0 1
2 3
[torch.LongTensor of size 2x2]
==================
tensor to array:
[[0 1]
[2 3]]
Torch tensor的运算和Numpy array类似,详细参考,下面演示一些
# abs 绝对值计算
data = [-1, -2, 1, 2]
tensor = torch.FloatTensor(data) # 转换成32位浮点 tensor
print(
'numpy abs: ', np.abs(data),
'\ntorch abs: ', torch.abs(tensor)
)
# sin 三角函数
print(
'\nnumpy sin: ', np.sin(data),
'\ntorch sin: ', torch.sin(tensor)
)
# mean 均值
print(
'\nnumpy mean: ', np.mean(data),
'\ntorch mean: ', torch.mean(tensor)
)
numpy abs: [1 2 1 2]
torch abs:
1
2
1
2
[torch.FloatTensor of size 4]
numpy sin: [-0.84147098 -0.90929743 0.84147098 0.90929743]
torch sin:
-0.8415
-0.9093
0.8415
0.9093
[torch.FloatTensor of size 4]
numpy mean: 0.0
torch mean: 0.0
# matrix multiply
data = [[1,2], [3,4]]
tensor = torch.FloatTensor(data)
# correct
print(
'numpy matmul: ', np.matmul(data, data),
'\ntorch matmul: ', torch.mm(tensor, tensor)
)
numpy matmul: [[ 7 10]
[15 22]]
torch matmul:
7 10
15 22
[torch.FloatTensor of size 2x2]
在 Torch 中的 Variable 就是一个存放会变化的值的地理位置. 里面的值会不停的变化. 就像一个裝鸡蛋的篮子, 鸡蛋数会不停变动. 那谁是里面的鸡蛋呢, 自然就是 Torch 的 Tensor 咯. 如果用一个 Variable 进行计算, 那返回的也是一个同类型的 Variable.
如上图,一个Variable里面包含着三个属性,data,grad和creator,其中creator表示得到这个Variabel的操作,比如乘法或者加法等等,grad表示方向传播的梯度,data表示取出这个Variabel里面的数据
本质上 Variable 和 Variable 没有区别,不过 Variabel 会放入一个计算图,然后进行前向传播,反向传播以及自动求导, Variable 在计算同时,会把计算路径记录下来,在内存中构造一个计算图
# 先产生鸡蛋
tensor = torch.FloatTensor([[1,2], [3,4]])
# 把鸡蛋放到篮子中,requires_grad 参不参与反向传播,要不要计算梯度
variable = Variable(tensor, requires_grad=True)
print("tensor: ", tensor)
print("\n variable:", variable)
tensor:
1 2
3 4
[torch.FloatTensor of size 2x2]
variable: Variable containing:
1 2
3 4
[torch.FloatTensor of size 2x2]
# 对比 tensor 和 variable 的计算
t_out = torch.mean(tensor*tensor)
v_out = torch.mean(variable*variable)
print("tensor mean: ", t_out)
print("\n variable mean: ", v_out)
tensor mean: 7.5
variable mean: Variable containing:
7.5000
[torch.FloatTensor of size 1]
到目前为止, 我们看不出什么不同, 但是时刻记住, Variable 计算时, 它在背景幕布后面一步步默默地搭建着一个庞大的系统, 叫做计算图, computational graph.
这个图是用来干嘛的? 原来是将所有的计算步骤 (节点) 都连接起来, 最后进行误差反向传递的时候, 一次性将所有 variable 里面的修改幅度 (梯度) 都计算出来, 而 tensor 就没有这个能力啦.
v_out = torch.mean(variable*variable) 就是在计算图中添加的一个计算步骤, 计算误差反向传递的时候有他一份功劳, 我们就来举个例子:
v_out.backward() # 模拟 v_out 的误差反向传递
# 下面两步看不懂没关系, 只要知道 Variable 是计算图的一部分, 可以用来传递误差就好.
# v_out = 1/4 * sum(variable*variable) 这是计算图中的 v_out 计算步骤
# 针对于 v_out 的梯度就是, d(v_out)/d(variable) = 1/4*2*variable = variable/2
print(variable.grad) # 初始 variable 的梯度
Variable containing:
0.5000 1.0000
1.5000 2.0000
[torch.FloatTensor of size 2x2]
print(variable) # Variable 形式
print(variable.data) # tensor 形式
print(variable.data.numpy()) # numpy 形式
Variable containing:
1 2
3 4
[torch.FloatTensor of size 2x2]
1 2
3 4
[torch.FloatTensor of size 2x2]
[[ 1. 2.]
[ 3. 4.]]
从上面的动画,可以看出,PyTorch的计算图是在 forward 运行过程中被定义生成的。
Torch 中的激励函数(activation function)有很多,如:relu、sigmoid、tanh、softplus,
x = torch.linspace(-5, 5, 200) # x data(tensor), shape(100,1)
x = Variable(x)
x_np = x.data.numpy() # 转成 numpy array,出图时用
# 几种常用的激励函数
y_relu = F.relu(x).data.numpy()
y_sigmoid = F.sigmoid(x).data.numpy()
y_tanh = F.tanh(x).data.numpy()
y_softplus = F.softplus(x).data.numpy()
# y_softmax = F.softmax(x).data.numpy softmax 比较特殊,不能直接显示,用于多分类
# 画图
plt.figure(1, figsize=(8, 6)) # 作用新建绘画窗口,独立显示绘画的图片
plt.subplot(221)
plt.plot(x_np, y_relu, c='red', label='relu')
plt.ylim(-1, 5) # 设置 y 轴范围
plt.legend(loc="best") # 显示图例,best 为自适应
plt.subplot(222)
plt.plot(x_np, y_sigmoid, c='red', label='sigmoid')
plt.ylim(-0.2, 1.2)
plt.legend(loc="best")
plt.subplot(223)
plt.plot(x_np, y_tanh, c='red', label='tanh')
plt.ylim(-1.2, 1.2)
plt.legend(loc="best")
plt.subplot(224)
plt.plot(x_np, y_softplus, c='red', label='softplus')
plt.ylim(-0.2, 6)
plt.legend(loc="best")
plt.show()