神经网络包使用

Torch 中的神经网络模块,包含大部分的神经网络功能,支持构造各种复杂的网络结构。 这个实验中,主要使用Linear包配合各种激活函数、Loss Function以及优化算法等构造基础的神经网络。


In [1]:
local _ = require('nn')

构造一个简单2维点阵分类的应用

1. 构造样本


In [2]:
trainSamples = {}
trainSamples.x = {}
trainSamples.y = {}

for i = 1, 128 do
  -- 构造随机坐标,-2.5, +2.5
  local x = torch.rand(2)
  x = (x - 0.5) * 3
  local y = torch.Tensor(1)

  -- 对训练样本进行分类
  y[1] = 1
  if ( (math.cos(x[1] - 0.5) - 0.5)< x[2] ) then
    y[1] = 0
  end

  trainSamples.x[#trainSamples.x+1] = x
  trainSamples.y[#trainSamples.y+1] = y
end

2. 编写一个现实数据的程序


In [3]:
Plot = require('itorch.Plot');

showData = function(samples, lables)

  local l0_x = {}
  local l0_y = {}
  local l1_x = {}
  local l1_y = {}
  for i=1, #samples do
    if ( lables[i][1] == 0) then
      table.insert(l0_x, samples[i][1])
      table.insert(l0_y, samples[i][2])    
    else
      table.insert(l1_x, samples[i][1])
      table.insert(l1_y, samples[i][2])            
    end
  end

  plot = Plot():circle(l0_x, l0_y, 'red', 'hi'):circle(l1_x, l1_y, 'blue', 'bye'):draw()

  plot:title('样本分布'):redraw()
  
  return plot
end

In [4]:
local _ = showData(trainSamples.x, trainSamples.y )


3. 构造网络

单隐层结构,


In [5]:
model = nn.Sequential()
model:add ( nn.Linear(2,5))
model:add ( nn.ReLU() )
model:add ( nn.Linear(5,1))
model:add ( nn.Sigmoid() )
print(model)


Out[5]:
nn.Sequential {
  [input -> (1) -> (2) -> (3) -> (4) -> output]
  (1): nn.Linear(2 -> 5)
  (2): nn.ReLU
  (3): nn.Linear(5 -> 1)
  (4): nn.Sigmoid
}
{
  gradInput : DoubleTensor - empty
  modules : 
    {
      1 : 
        nn.Linear(2 -> 5)
        {
          gradBias : DoubleTensor - size: 5
Out[5]:
          weight : DoubleTensor - size: 5x2
          gradWeight : DoubleTensor - size: 5x2
          gradInput : DoubleTensor - empty
          bias : DoubleTensor - size: 5
          output : DoubleTensor - empty
        }
      2 : 
        nn.ReLU
        {
          inplace : false
          threshold : 0
          val : 0
          output : DoubleTensor - empty
          gradInput : DoubleTensor - empty
        }
      3 : 
        nn.Linear(5 -> 1)
        {
          gradBias : DoubleTensor - size: 1
          weight : DoubleTensor - size: 1x5
          gradWeight : DoubleTensor - size: 1x5
          gradInput : DoubleTensor - empty
          bias : DoubleTensor - size: 1
          output : DoubleTensor - empty
        }
      4 : 
        nn.Sigmoid
        {
          gradInput : DoubleTensor - empty
          output : DoubleTensor - empty
        }
    }
  output : DoubleTensor - empty
}

4. 构造Loss Function


In [6]:
criterion = nn.BCECriterion()
print(criterion)


Out[6]:
nn.BCECriterion
{
  gradInput : DoubleTensor - empty
  sizeAverage : true
  output : 0
}

5. 构造训练函数


In [7]:
-- 纪录模型的参数
parameters,gradParameters = model:getParameters()
tindex = 1
doTrain = function(x)
  -- get new parameters
  if x ~= parameters then
    parameters:copy(x)
  end
  -- reset gradients
  gradParameters:zero()
  
  local yout = model:forward(trainSamples.x[tindex])
  local f = criterion:forward(yout, trainSamples.y[tindex])
    
  local dyout = criterion:backward(yout, trainSamples.y[tindex])
  model:backward(trainSamples.x[tindex], dyout)
  
  return f, gradParameters
end

6. 执行训练


In [8]:
require('optim')
state = {
   learningRate = 0.1,
   momentum = 0.5
}

local errRecord = {  --纪录每次训练的error输出
  seq = {},
  value = {}
}

model:training()
for ep = 1,100 do
   local errSum = 0.0
   for i=1, #trainSamples.x do
       tindex = i
       local _, err = optim.sgd(doTrain, parameters, state)
       errSum = errSum + err[1]
   end
   errSum = errSum / #trainSamples.x
   
   errRecord.value[ep] = errSum
   errRecord.seq[ep] = ep
end

Plot = require 'itorch.Plot'
local plot = Plot()
plot:line(errRecord.seq, errRecord.value,'black', 'yolo'):draw()
plot:title("训练过程"):redraw()


7. 验证效果


In [9]:
local marginLineX = {}
local marginLineY = {}
local singleSample = torch.Tensor(2)

for x1=-1.5, 1.5, 0.03 do
    for x2=-1.5, 1.5, 0.03 do
        singleSample[1] = x1
        singleSample[2] = x2
        
        local y = model:forward(singleSample)
        if ( torch.abs(y[1] - 0.5) < 0.1) then
           marginLineX[#marginLineX+1] = x1
           marginLineY[#marginLineY+1] = x2 
        end
    end
end


plot = showData(trainSamples.x, trainSamples.y )
plot:line(marginLineX,marginLineY,'black', 'yolo'):redraw()



In [ ]:


In [ ]: