这是在tensorflow时代,不可能完成的任务。
tensorflow学的过程,简直就是从入门到“放弃”。学习曲线太过陡峭,很多面向工程而非researcher和学习的特性,非常不人性化。
终于pytorch来了。
pytorch也是出自名门facebook,同时纯python。Tensor说白了就是支持GPU的numpy的ndarray,对于python的忠粉,对于这样的框架,自然要上手。
pip安装有问题,但在anaconda环境下就很简单了,直接用conda安装(win环境不支持):
conda install pytorch torchvision -c soumith
测试一下是否安装成功。
import torch print(torch.__version__) 能够正常显示版本号即可。
下面介绍Tensor: x = torch.Tensor(5, 3) print(x)
直接得到一个5行3列的tensor,默认是FloatTensor,还有LongTensor,IntTensor。
c = torch.zeros((3,2)) print(c)
得到一个3X2的FloatTensor,元素都是0。
这个可以类比tensorflow的Constant常量,可以初始化维度或生成一些内容。但torch的tensor其实就是一个支持GPU的numpy矩阵,可以c[0,1]=100这样直接改变元素值,这个tf是绝对不可以的。
然后讲Variable,这是numpy里没有,是神经网络的概念,变量是支持自动求导,同时需要优化的超参数,在torch.autograd.Variable包内,有三个属性:data,grad,grad_fn。data是var包含里tensor的值,grad是反向传播梯度,grad_fn是得到这个variable的操作。
from torch.autograd import Variable a = Variable(torch.Tensor([1]),requires_grad=True) b = Variable(torch.Tensor([2]),requires_grad=True) c = Variable(torch.Tensor([3]),requires_grad=True)
y = a * b + c # y = a*b + c,用来初始化的值 y.backward() #对标量自动求导
print(a.grad)# 2 print(b.grad)# 1 print(c.grad)# 1
基础数据类型,torch就这么两个,tf还有placeholder, 还有variable,tf的Variable是需要额外feed它数据,另外tf的session,graph,尤其是variable的scope实在是太复杂,主要还是因为tf是静态图构建模式。
下面随机初始化一个5x3的张量:
x = torch.rand(5,3) print(x) print(x.size())
变量的自动求导:
from torch.autograd import Variable x = Variable(torch.ones(2,2),requires_grad=True) print(x) y = x + 2 print(y) print(y.grad_fn) z = y * y * 3 #out是x的函数 out=f(x)=(x+2)**2 *3/4 out = z.mean() print(z, out) #d out / d(x) = 3/2 (x+2) out.backward() #x=1时,导数=4.5 print(x.grad)
下面正式开始搭建神经网络mnist的CNN网络。nn.Module中包含着神经网络的层,同时forward(input)方法能够将output进行返回。
下面是一个典型的mnist的CNN卷积神经网络的图:
一个典型的神经网络的训练过程是这样的:
-
定义一个有着可学习的参数(或者权重)的神经网络
-
对着一个输入的数据集进行迭代:
-
通常使用简单的更新规则: weight = weight + learning_rate * gradient(在梯度的方向上,更新learning_rate)
-
用神经网络对输入进行处理
-
计算代价值loss (对输出值的修正到底有多少)
-
将梯度传播回神经网络的参数中
-
更新网络中的权重
-
我们来定义一个神经网络:
import torch import torch.nn as nn import torch.nn.functional as F from aipack.utils.pytorch_utils import Trainer from aipack.utils.data_utils import load_mnist class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(1, 10, kernel_size=5) self.conv2 = nn.Conv2d(10, 20, kernel_size=5) self.conv2_drop = nn.Dropout2d() self.fc1 = nn.Linear(320, 50) self.fc2 = nn.Linear(50, 10) def forward(self, x): #input=[N,1,28,28] x = F.relu(F.max_pool2d(self.conv1(x), 2))#conv1->[N,10,24,24]:max_pool->[N,10,12,12] x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))#conv2->[N,20,8,8]:max_pool->[N,20,4,4] x = x.view(-1, 320)#[N,320] x = F.relu(self.fc1(x))#[N,50] x = F.dropout(x, training=self.training) x = self.fc2(x)#[N,10] return F.log_softmax(x) train_loader,test_loader = load_mnist() trainer = Trainer(Net(),train_loader=train_loader,test_loader=test_loader) trainer.train()
非常清晰的网络搭建过程,pytorch真的带来太多的方便,尤其是学习过程,底层代码写得也很优雅且亲民,这个框架大有前途!!!
10个epoch的训练结果,99%的测试结果,任务达成!
Train Epoch: 10 [56960/60000 (95%)] Loss: 0.021683
Train Epoch: 10 [57600/60000 (96%)] Loss: 0.009014
Train Epoch: 10 [58240/60000 (97%)] Loss: 0.037256
Train Epoch: 10 [58880/60000 (98%)] Loss: 0.004855
Train Epoch: 10 [59520/60000 (99%)] Loss: 0.102320
Test set: Average loss: 0.0366, Accuracy: 9884/10000 (99%)
关于作者:魏佳斌,互联网产品/技术总监,北京大学光华管理学院(MBA),特许金融分析师(CFA),资深产品经理/码农。偏爱python,深度关注互联网趋势,人工智能,AI金融量化。致力于使用最前沿的认知技术去理解这个复杂的世界。
扫描下方二维码,关注:AI量化实验室(ailabx),了解AI量化最前沿技术、资讯。