前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Torch深度学习入门

Torch深度学习入门

作者头像
bear_fish
发布2018-09-19 12:10:23
6390
发布2018-09-19 12:10:23
举报

lua和torch的安装官网都有,lua的语法基础知识网上有很多。请看本文前自行学习。本文简单介绍了torch做深度学习模型的简单用法,并给出了CIFAR-10的分类例子和代码。

简单概念概述

torch中有神经网络(Neural Networks)的包‘nn’。

在torch中,模块(Module)是构建神经网络的基石。模块本身也是神经网络,它可以和其他网络借助容器(Container)构建更复杂的神经网络。

我们借助经典的手写体识别(mnist)的例子,如图是个简单的LeNet5前向反馈网络。 

LeNet5
LeNet5
代码语言:text
复制
下面一段代码就是堆上图中网络的定义描述,结合注释应该可以看得比较清楚。
net = nn.Sequential()
net:add(nn.SpatialConvolution(1, 6, 5, 5)) -- 1 input image channel, 6 output channels, 5x5 convolution kernel
net:add(nn.ReLU())                       -- non-linearity 
net:add(nn.SpatialMaxPooling(2,2,2,2))     -- A max-pooling operation that looks at 2x2 windows and finds the max.
net:add(nn.SpatialConvolution(6, 16, 5, 5))
net:add(nn.ReLU())                       -- non-linearity 
net:add(nn.SpatialMaxPooling(2,2,2,2))
net:add(nn.View(16*5*5))                    -- reshapes from a 3D tensor of 16x5x5 into 1D tensor of 16*5*5
net:add(nn.Linear(16*5*5, 120))             -- fully connected layer (matrix multiplication between input and weights)
net:add(nn.ReLU())                       -- non-linearity 
net:add(nn.Linear(120, 84))
net:add(nn.ReLU())                       -- non-linearity 
net:add(nn.Linear(84, 10))                   -- 10 is the number of outputs of the network (in this case, 10 digits)
net:add(nn.LogSoftMax())                     -- converts the output to a log-probability. Useful for classification problems

print('Lenet5\n' .. net:__tostring());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

关于反向传输算法这里也不赘述,每个神经元模块都有forward(input)和backward(input,gradient)方法,通过BP传递梯度来更新权重。  下面一段代码展示了前向和后向传输的用法:

代码语言:c#
复制
input=torch.rand(1,32,32)
output=net:forward(input)
print(output)
net:zeroGradParameters() -- zero the internal gradient buffers of the network (will come to this later)
gradInput = net:backward(input, torch.rand(10))
print(#gradInput)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

损失函数

loss function是调整权重的准则,其重要性不言而喻,loss值越低往往标志着其模型越好(也可能有过拟合的情况,在此不讨论其泛化能力)。我们训练的目标也是为了找到使得损失函数较小的权重。  比如下面代码在torch中建立一个NLL(negative -loglikelihood)的准则:

代码语言:text
复制
criterion = nn.ClassNLLCriterion() -- a negative log-likelihood criterion for multi-class classification
criterion:forward(output, 3) -- let's say the groundtruth was class number: 3
gradients = criterion:backward(output, 3)
gradInput = net:backward(input, gradients)
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

神经网络层中并不都是可以学习的参数,卷积层根据输入数据和待解决的问题可以学习得到最佳的卷积核大小。但max-pooling层就没有可学习的参数,它只是找到局部最大窗口。

在torch中有可学习的权重都有.weight(可能有.bias)的属性。  比如:

代码语言:lua
复制
m = nn.SpatialConvolution(1,3,2,2) -- learn 3 2x2 kernels
print(m.weight) -- initially, the weights are randomly initialized
print(m.bias) -- The operation in a convolution layer is: output = convolution(input,weight) + bias
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

还有其他重要的属性,比如gradWeight和gradBias。

如何训练网络

我们用简单的随机梯度下降法(Stochastic Gradient Descent)来更新权值。在nn.StochasticGradient模块中,  里面有个train(dataset)的方法,直接调用就可以了。

输入数据格式

处理图像、文本、音频和视频数据时,可以用image.load或者audio.load把数据保存到torch.Tensor或者Lua table格式的变量中。  我们先用一下简单的CIFAR-10数据库来训练我们的模型吧。CIFAR-10是3通道的32*32的彩色图片集。有airplane,automobile,bird,cat,deer,dog,frog,horse,ship,truck共十类。总共有50000训练图片,10000测试图片。 

CIFAR-10
CIFAR-10

我们来总结一下用torch神经网络的几个步骤:

  1. 加载数据并对其预处理
  2. 定义神经网络模型
  3. 定义损失函数
  4. 在训练集上训练网络
  5. 在测试集上测试网络

下面就按照这5个步骤,实现一个小程序。

加载数据并对其预处理

因为有人已经事先把数据转换成4D的torch ByteTensor形式了。训练集是50000*3*32*32,测试集是10000*3*32*32。

代码语言:lua
复制
require 'paths'
if (not paths.filep("cifar10torchsmall.zip")) then
    os.execute('wget -c https://s3.amazonaws.com/torch7/data/cifar10torchsmall.zip')
    os.execute('unzip cifar10torchsmall.zip')
end
trainset = torch.load('cifar10-train.t7')
testset = torch.load('cifar10-test.t7')
classes = {'airplane', 'automobile', 'bird', 'cat','deer', 'dog', 'frog', 'horse', 'ship', 'truck'}
print(trainset)
print(#trainset.data)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

数据加载好了,我们还要使得数据满足train(dataset)的要求。

  1. 必须要要有size()方法
  2. dataset[i]是其第i个例子(lua是从1开始索引的)。

举个daset格式的例子:

代码语言:lua
复制
dataset={};
function dataset:size() return 100 end -- 100 examples
for i=1,dataset:size() do 
  local input = torch.randn(2);     -- normally distributed example in 2d
  local output = torch.Tensor(1);
  if input[1]*input[2]>0 then     -- calculate label for XOR function
    output[1] = -1;
  else
    output[1] = 1
  end
  dataset[i] = {input, output}
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

下面要使得我们的数据均值为0标准差为1。

代码语言:text
复制
mean = {} -- store the mean, to normalize the test set in the future
stdv  = {} -- store the standard-deviation for the future
for i=1,3 do -- over each image channel
    mean[i] = trainset.data[{ {}, {i}, {}, {}  }]:mean() -- mean estimation
    print('Channel ' .. i .. ', Mean: ' .. mean[i])
    trainset.data[{ {}, {i}, {}, {}  }]:add(-mean[i]) -- mean subtraction
    stdv[i] = trainset.data[{ {}, {i}, {}, {}  }]:std() -- std estimation
    print('Channel ' .. i .. ', Standard Deviation: ' .. stdv[i])
    trainset.data[{ {}, {i}, {}, {}  }]:div(stdv[i]) -- std scaling
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

定义神经网络模型

代码语言:text
复制
net = nn.Sequential()
net:add(nn.SpatialConvolution(3, 6, 5, 5)) -- 3 input image channels, 6 output channels, 5x5 convolution kernel
net:add(nn.ReLU())                       -- non-linearity 
net:add(nn.SpatialMaxPooling(2,2,2,2))     -- A max-pooling operation that looks at 2x2 windows and finds the max.
net:add(nn.SpatialConvolution(6, 16, 5, 5))
net:add(nn.ReLU())                       -- non-linearity 
net:add(nn.SpatialMaxPooling(2,2,2,2))
net:add(nn.View(16*5*5))                    -- reshapes from a 3D tensor of 16x5x5 into 1D tensor of 16*5*5
net:add(nn.Linear(16*5*5, 120))             -- fully connected layer (matrix multiplication between input and weights)
net:add(nn.ReLU())                       -- non-linearity 
net:add(nn.Linear(120, 84))
net:add(nn.ReLU())                       -- non-linearity 
net:add(nn.Linear(84, 10))                   -- 10 is the number of outputs of the network (in this case, 10 digits)
net:add(nn.LogSoftMax())                     -- converts the output to a log-probability. Useful for classification problems
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

定义损失函数

代码语言:text
复制
criterion = nn.ClassNLLCriterion()
  • 1
  • 1

训练网络

代码语言:text
复制
trainer = nn.StochasticGradient(net, criterion)
trainer.learningRate = 0.001
trainer.maxIteration = 5 -- just do 5 epochs of training.
trainer:train(trainset)
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

测试数据

代码语言:text
复制
testset.data = testset.data:double()   -- convert from Byte tensor to Double tensor
for i=1,3 do -- over each image channel
    testset.data[{ {}, {i}, {}, {}  }]:add(-mean[i]) -- mean subtraction    
    testset.data[{ {}, {i}, {}, {}  }]:div(stdv[i]) -- std scaling
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

在GPU上用CUDA训练做的改动

如何安装cuda这里就不详说了,网上一堆一堆教程。

  1. 包。require ‘cunn’;
  2. 网络。net=net:cuda()
  3. 标准。criterion = criterion:cuda()
  4. 数据。trainset.data = trainset.data:cuda()  trainset.label = trainset.label:cuda()

训练代码倒没什么改变:

代码语言:text
复制
trainer = nn.StochasticGradient(net, criterion)
trainer.learningRate = 0.001
trainer.maxIteration = 5 -- just do 5 epochs of training.
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

因为上面例子的迭代次数较少,结果并不是特别好。自己可以试试。我把代码放到这里。  在命令行中输入:

th cifar10.lua

这里写图片描述
这里写图片描述
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年02月15日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简单概念概述
  • 损失函数
  • 如何训练网络
  • 输入数据格式
    • 加载数据并对其预处理
      • 定义神经网络模型
        • 定义损失函数
          • 训练网络
            • 测试数据
            • 在GPU上用CUDA训练做的改动
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档