看了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比。