一、PyTorch介绍
1、说明
PyTorch
是Torch
在Python
上的衍生(Torch
是一个使用Lua
语言的神经网络库)- 和
tensorflow
比较PyTorch
建立的神经网络是动态的Tensorflow
是建立静态图Tensorflow
的高度工业化, 它的底层代码是很难看懂的.PyTorch
好那么一点点, 如果你深入API
, 你至少能比看Tensorflow
多看懂一点点PyTorch
的底层在干嘛.
2、安装PyTorch
- 官网:http://pytorch.org/
- 进入官网之后可以选择对应的安装选项
- 目前只支持
Linux
和MacOS
版本(2017-05-06
) - 执行下面对应的安装命令即可
- 目前只支持
- 安装
PyTorch
会安装两个模块- 一个是
torch
, 一个torchvision
,torch
是主模块, 用来搭建神经网络的, torchvision
是辅模块,有数据库,还有一些已经训练好的神经网络等着你直接用, 比如 (VGG, AlexNet, ResNet
).
- 一个是
- 上面在
ubuntu14
下自带的python2.7
安装没有问题,在CentOS6.5
下的python3.5
中安装可能报错- 安装
python3.5
时的配置:
- 安装
|
|
- 然后运行
python
可能报loading shared libraries: libpython3.5m.so.1.0: cannot open shared object file: No such file or directory
的错误,拷贝一份libpython3.5m.so.1.0
到/usr/lib64
目录下即可
|
|
二、基础知识
1、和Numpy
相似之处
(1) 数据转换
- 导入包:
import torch
- 将
numpy
数据转为torch
数据
|
|
- 将
torch
数据转为numpy
数据
|
|
(2) Torch
中的运算
- API:http://pytorch.org/docs/torch.html#math-operations
torch
中tensor
的运算和numpy array
运算很相似,比如np.abs() --> torch.abs()
np.sin() --> torch.sin()
等
- 矩阵相乘:
Variable
就是一个存放会变化的值的位置- 这里变化的值就是tensor数据
(2) 使用
导入包
12import torchfrom torch.autograd import Variable # torch 中 Variable 模块定义
tensor
:tensor = torch.FloatTensor([[1,2],[3,4]])
- 将
tensor
放入Variable
:variable = Variable(tensor, requires_grad=True)
requires_grad
是参不参与误差反向传播, 要不要计算梯度print(variable)
会输出,(多出Variable containing:
,表明是Variable
)
|
|
(3) 计算梯度
v_out = torch.mean(variable*variable) # x^2
v_out.backward() # 模拟 v_out 的误差反向传递
print(variable.grad) # 显示 Variable 的梯度
- 输出结果如下
- 因为
torch.mean(variable*variable)
是1/4*x^2
,导数就是1/2x
120.5000 1.00001.5000 2.0000
(4) Variable里面的数据
- 直接
print(variable)
只会输出Variable
形式的数据, 在很多时候是用不了的(比如想要用plt
画图), 所以我们要转换一下, 将它变成tensor
形式. - 获取
tensor
数据:print(variable.data) # tensor 形式
- 导入包:
import torch.nn.functional as F # 激励函数都在这
- 平时要用到的就这几个.
relu, sigmoid, tanh, softplus
- 激励函数
x
是Variable
数据,F.relu(x)
也是返回Variable
数据,然后.data
获取tensor
数据1234# 做一些假数据来观看图像x = torch.linspace(-5, 5, 200) # x data (tensor), shape=(100, 1)x = Variable(x)x_np = x.data.numpy() # 换成 numpy array, 出图时用
|
|
softplus
的公式为:f(x)=ln(1+ex)
三、建立基础的神经网络
1、回归问题
(1) 准备工作
- 导入包
|
|
制造假数据
torch.unsqueeze
是转成2维的数据[[]]
,加上一个假的维度12x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1) # x data (tensor), shape=(100, 1)y = x.pow(2) + 0.2*torch.rand(x.size()) # noisy y data (tensor), shape=(100, 1)
定义
Variable
:x, y = torch.autograd.Variable(x), Variable(y)
(2) 建立神经网络
使用类的方式class
- 继承
torch.nn.Module
- 这里只包含一个隐层,
__init__
只是定义了几个层 forward
进行传播,也就是整个网络的搭建,因为是预测,最后一层不需要激励函数123456789101112class Net(torch.nn.Module): # 继承 torch 的 Moduledef __init__(self, n_feature, n_hidden, n_output):super(Net, self).__init__() # 继承 __init__ 功能# 定义每层用什么样的形式self.hidden = torch.nn.Linear(n_feature, n_hidden) # 隐藏层线性输出self.predict = torch.nn.Linear(n_hidden, n_output) # 输出层线性输出def forward(self, x): # 这同时也是 Module 中的 forward 功能# 正向传播输入值, 神经网络分析出输出值x = F.relu(self.hidden(x)) # 激励函数(隐藏层的线性值)x = self.predict(x) # 输出值return x
- 继承
使用:
net = Net(n_feature=1, n_hidden=10, n_output=1)
- 输出:
print(net)
,结果为
|
|
(3) 训练网络
- 定义优化器:
optimizer = torch.optim.SGD(net.parameters(), lr=0.5) # 传入 net 的所有参数, 学习率lr
- 定义损失函数:
loss_func = torch.nn.MSELoss() # 预测值和真实值的误差计算公式 (均方差)
- 训练
|
|
2、分类问题
(1) 准备工作
- 导入包
|
|
制造假数据
x0
是一个类别的x1,x2
y0
就是对应这个类别的label
,这里是0
- 然后将
x0,x1
,y0,y1
合并在一起123456789# 假数据n_data = torch.ones(100, 2) # 数据的基本形态x0 = torch.normal(2*n_data, 1) # 类型0 x data (tensor), shape=(100, 2)y0 = torch.zeros(100) # 类型0 y data (tensor), shape=(100, 1)x1 = torch.normal(-2*n_data, 1) # 类型1 x data (tensor), shape=(100, 1)y1 = torch.ones(100) # 类型1 y data (tensor), shape=(100, 1)# 注意 x, y 数据的数据形式是一定要像下面一样 (torch.cat 是在合并数据)x = torch.cat((x0, x1), 0).type(torch.FloatTensor) # FloatTensor = 32-bit floatingy = torch.cat((y0, y1), ).type(torch.LongTensor) # LongTensor = 64-bit integer
定义Variable:
x, y = Variable(x), Variable(y)
(2) 建立网络
与上面回归的例子类似
- 使用
relu
激励函数 - 这里最后一层并没有使用激励函数或是
softmax
,因为下面使用了CrossEntropyLoss
,这个里面默认会调用log_softmax
函数(nll_loss(log_softmax(input), target, weight, size_average)
) - 当然这里也可以最后返回
F.softmax(x)
, 那么下面的损失函数就是loss = F.nll_loss(out, y)
1234567891011class Net(torch.nn.Module): # 继承 torch 的 Moduledef __init__(self, n_feature, n_hidden, n_output):super(Net, self).__init__() # 继承 __init__ 功能self.hidden = torch.nn.Linear(n_feature, n_hidden) # 隐藏层线性输出self.out = torch.nn.Linear(n_hidden, n_output) # 输出层线性输出def forward(self, x):# 正向传播输入值, 神经网络分析出输出值x = F.relu(self.hidden(x)) # 激励函数(隐藏层的线性值)x = self.out(x) # 输出值, 但是这个不是预测值, 预测值还需要再另外计算return x
- 使用
建立网络:
net = Net(n_feature=2, n_hidden=10, n_output=2) # 几个类别就几个 output
(3) 训练网络
- 优化器:
optimizer = torch.optim.SGD(net.parameters(), lr=0.02) # 传入 net 的所有参数, 学习率
- 损失函数:
loss_func = torch.nn.CrossEntropyLoss()
- 训练:
|
|
- 预测:
- 输出至最大的那个(概率最大的)坐标12# 过了一道 softmax 的激励函数后的最大概率才是预测值prediction = torch.max(F.softmax(out), 1)[1]
- 输出至最大的那个(概率最大的)坐标
3、快速搭建神经网络
- 使用
torch.nn.Sequential
|
|
- 输出:
print(net2)
- 相比我们之前自己定义的类,激励函数也显示出来了12345Sequential ((0): Linear (1 -> 10)(1): ReLU ()(2): Linear (10 -> 1))
- 相比我们之前自己定义的类,激励函数也显示出来了
4、保存和提取
(1) 保存(两种方法)
- 保存整个网络
torch.save(net1, 'net.pkl')
# 保存整个网络,net1
就是定义的网络
- 只保存网络中的参数
- 提取整个网络:
net2 = torch.load('net.pkl')
prediction = net2(x)
- 只提取网络参数
- 上面我们虽然是
torch.optim.SGD
进行优化,但是还是将所有数据放进去训练(1) DataLoader
- 是
torch
用来包装你的数据(tensor
)的工具 - 导入包:
import torch.utils.data as Data
将tensor数据转为
torch
能识别的Dataset
1torch_dataset = Data.TensorDataset(data_tensor=x, target_tensor=y)把 dataset 放入 DataLoader
BATCH_SIZE
是我们定义的batch
大小123456loader = Data.DataLoader(dataset=torch_dataset, # torch TensorDataset formatbatch_size=BATCH_SIZE, # mini batch sizeshuffle=True, # 要不要打乱数据 (打乱比较好)num_workers=2, # 多线程来读数据)
就可以得到
batch
数据了12345678for epoch in range(3): # 训练所有!整套!数据 3 次for step, (batch_x, batch_y) in enumerate(loader): # 每一步 loader 释放一小批数据用来学习# 假设这里就是你训练的地方...# 打出来一些数据print('Epoch: ', epoch, '| Step: ', step, '| batch x: ',batch_x.numpy(), '| batch y: ', batch_y.numpy())这里还是
tensor
数据,真正训练时还要放到Variable
中
|
|
6、优化器 optimizer
SGD
- 就是随机梯度下降
momentum
- 动量加速
- 在
SGD
函数里指定momentum
的值即可
RMSprop
- 指定参数
alpha
- 指定参数
Adam
- 参数
betas=(0.9, 0.99)
1234opt_SGD = torch.optim.SGD(net_SGD.parameters(), lr=LR)opt_Momentum = torch.optim.SGD(net_Momentum.parameters(), lr=LR, momentum=0.8)opt_RMSprop = torch.optim.RMSprop(net_RMSprop.parameters(), lr=LR, alpha=0.9)opt_Adam = torch.optim.Adam(net_Adam.parameters(), lr=LR, betas=(0.9, 0.99))
- 参数
四、高级神经网络
1、卷积神经网络 CNN
- 使用mnist数据集
- 导入包
|
|
- 下载数据集
|
|
处理数据
- 使用
DataLoader
进行batch
训练 - 将测试数据放到
Variable
里,并加上一个维度(在第二维位置dim=1),因为下面训练时是(batch_size, 1, 28, 28)
12345train_loader = Data.DataLoader(dataset=train_data, batch_size=128, shuffle=True)# shape from (total_size, 28, 28) to (total_size, 1, 28, 28)test_x = Variable(torch.unsqueeze(test_data.test_data, dim=1), volatile=True).type(torch.FloatTensor)/255.0test_y = test_data.test_labels
- 使用
建立计算图模型
|
|
- 定义优化器
optimizer
和损失
|
|
- 进行batch训练
|
|
Reference
- 本文链接: http://lawlite.me/2017/05/10/PyTorch/
- 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议 。转载请注明出处!