天天看點

不可思議的遞歸神經網絡

看了Andrej Karpathy寫的文章“The Unreasonable Effectiveness of Recurrent Neural Networks”。用RNN來學習某些作者的文章,然後用學習好的哦RNN網絡來Generate句子,最後出來的結果看起來還挺有道理。再想想Theano tutorial中提供的elman RNN實作(在句子層次将Word Embedding和Classification一起做),覺得Recurrent Neural Networks模型真的很強大。(該文還說道用RNN來識别街景的文字,這不是搶CNN的飯碗嗎)

Andrej Karpathy提供了源代碼char-rnn,不過是用Torch+Lua寫的。機器學習山頭林立,架構衆多,讓我們這些追随者都有點不知所措了。最開始是VB,然後是C++,然後Matlab,等自己覺得 I can speak matlab之後,Python+Theano又來了。Theano學得差不多了,這幫人又搞了一個Torch+Lua,實在學不動了。(目前感興趣的分布式平台scala都沒有時間看) 從文章來看,應該是一個雙層的RNN網絡,決定用Theano來實作一下。

1 參考一下代碼

char-rnn的基本架構應該是這樣,即兩層疊加的RNN:

y1 = rnn1.step(x)
y = rnn2.step(y1)
           

雖然不懂Lua,但是看起來和Python還是比較像。(還有if … end這種結構,看起來比Python好。) 分析一下主執行檔案,主執行檔案應該是這個:https://github.com/karpathy/char-rnn/blob/master/train.lua

require 'torch'  # = import torch
require 'nn'     #  = import nn
local LSTM = require 'model.LSTM'  # 使用LSTM,最常見的RNN
cmd = torch.CmdLine()  # 獲得command line
cmd:text()  #  =  print ''
cmd:text('Train a character-level language model')
cmd:option('-rnn_size', , 'size of LSTM internal state')  # 預設的RNN internal 大小為128
cmd:option('-num_layers', , 'number of layers in the LSTM')  #兩層的LSTM
local vocab_size = loader.vocab_size # 字元個數 
protos.rnn = LSTM.lstm(vocab_size, opt.rnn_size, opt.num_layers, opt.dropout)  # 構造兩層 LSTM
protos.criterion = nn.ClassNLLCriterion() # 大概是目标函數
           

再看看https://github.com/karpathy/char-rnn/blob/master/model/LSTM.lua,我了解這是LSTM的類。

function LSTM.lstm(input_size, rnn_size, n, dropout)  # n是層數,沒有輸出大小。這個例子應該輸入大小和輸出大小一緻。
-- there will be 2*n+1 inputs
  local inputs = {}
  table.insert(inputs, nn.Identity()()) -- x #第一層的輸入也需要前一層?
  for L = ,n do
    table.insert(inputs, nn.Identity()()) -- prev_c[L]
    table.insert(inputs, nn.Identity()()) -- prev_h[L]
  end  #  内部狀态和輸入,初始化為機關矩陣?

if L ==  then  # 如果是第一層,input_size就是X的大小
      x = OneHot(input_size)(inputs[])
      input_size_L = input_size
    else   # 如果是第其他層,input_size就是内部狀态的大小
      x = outputs[(L-)*] 
      input_size_L = rnn_size
    end
           

第一個層RNN的輸出是否需要argmax一下再到下一層RNN?從代碼來看似乎不需要。

2 用Theano來實作

使用Theano_lstm庫來實作一個兩層的LSTM RNN網絡。使用的資料集是

input.txt

,裡面是若幹Shakespear寫的劇本。

lstm_shake.py

檔案構造一個基于字元的序列的模型,該通過學習Shakespear的劇本,希望能像Shakespear一樣寫劇本。

  • lstm_shake.py
  • input.txt

3 測試運作

運作little shakespear的例子。每50個Epoch,輸入’T’作為首字母,然後采樣輸出的結果。

epoch , error=
TPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
epoch , error=
epoch , error=
epoch , error=
epoch , error=
epoch , error=
T I I It t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t
 t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t
 t t t t t t t t t t t t t t t t t t t t
epoch , error=
epoch , error=
epoch , error=
epoch , error=
epoch , error=
T Ih tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt
tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt
 tt tt tt tt tt tt tt tt tt tt tt tt tt t
epoch , error=
epoch , error=
           

隻有CPU,非常慢。而且沒有進行優化處理,句子長短不一,非常浪費。沒有使用minibatch,記憶體占用非常高。另外,CPU的使用率也不高。

學習的效果似乎也不好,完全沒法和Shakespear比。

繼續閱讀