Theano官方LSTM代码解析
本文内容纯属个人观点,有误的地方敬请指正批评。
阅读本文需要一定的python,lstm和Theano的基础知识。
Theano是一种符号语言,它的优点在与它的自动求导机制以及GPU的透明性,缺点在于调试时极为不便。
基于Theano开发的Deep Learning代码一般分为四个部分:数据准备,模型建立,预训练和训练,测试。代码按照这个顺序进行分析。
Theano的LSTM代码见https://github.com/lisa-lab/DeepLearningTutorials
其中LSTM的代码见lstm.py和imdb.py,数据集为imdb.pkl。
代码如下:
If __name__ = ‘__main__’:
train_lstm(max_epochs=100,test_size=500,)
/*我们从主函数下手开始分析,__main__函数调用了train_lstm()函数,LSTM的整个过程都是从这个函数开始。*/
def train_lstm(
dim_proj=128, /*word embedding的维数和隐藏层的维数,用默认值。(word embedding是一种将一个词转成一个向量的过程,这里不去深究)*/
patience=10, /*该参数用于earlystop,如果10轮迭代的误差没有降低,就进行earlystop*/
max_epochs=5000,/*迭代次数(将训练集迭代一轮位一个epoch)*/
diapFreq=10,/*每更新10次显示训练过程,即显示训练、验证和测试误差*/
decay_c=0, /*参数U的正则权重,U为隐藏层ht到输出层的参数*/
lrate=0.0001, /*sgd用的学习率*/
n_words=10000, /*词典大小,用于数据预处理部分,将词用该词在词典中的ID表示,超过10000的用1表示,仅仅用于数据,不做深究*/
optimizer=adadelta, /*优化方法,代码提供了sgd,adadelta和rmsprop三种方法,采用了adadelta*/
encoder='lstm', /*一个标识符,可以去掉,但是必须是lstm*/
saveto='lstm_model.npz', /*保存最好模型的文件,保存训练误差,验证误差和测试误差等等*/
validFreq=370,/*验证频率*/
saveFreq=1110,/*保存频率*/
maxlen=100,/*序列的最大长度,超出长度的数据被抛弃,见数据处理部分*/
batch_size=16,/*训练的batch大小*/
valid_batch_size=64,/*验证集用的*batch大小*/
dataset='imdb',/*用于数据预处理的参数,全局变量datasets的key'imdb'的value为两个处理数据的函数*/
noise_std=0.,/*后边好像没有出现过,恕我无知,我也不知道这是什么鬼*/!!!
use_dropout=True,/*控制dropout,不用dropout的话运行速度较快,但是效果不好,dropout不太好解释,以一定的概率随机丢弃模型中的一些节点,这样可以综合多种模型的结果,进行投票。需要自行补充deeplearning的知识*/
reload_model=None,/*加载模型参数的文件,用于已训练好的模型,或保存的中间结果*/
test_size=-1,/*测试集大小,如果为正,就只用这么多测试样本*/
):
model_options = locals().copy()
print("model options", model_options)
/*首先将当先的函数局部作用于的参数copy到字典model_options中,后面的很多函数就以model_options作为参数进行参数传递。*/
load_data, prepare_data = get_dataset(dataset)# dataset=‘imdb’
print('Loading data')
train, valid, test = load_data(n_words=n_words,valid_portion=0.05,
maxlen=maxlen)
/*获取处理数据的函数,定义在全局作用域的get_dataset函数中
调用以下代码:*/
datasets = {'imdb':(imdb.load_data, imdb.prepare_data)}
defget_dataset(name):
return datasets[name][0], datasets[name][1]
/*返回了两个函数:load_data,prepare_data这两个函数定义在imdb.py中*/
/*数据已经事先存在了imdb.pkl中,这里用pickle方法load进来,第一项为训练数据,第二项为测试数据;
load_data函数将数据集读入,舍弃长度超过maxlen的数据,并按照参数valid_portion的比例将一部分训练集划为验证集。
而第二个函数prepare_data负责数据的转换,在训练和测试的时候先将训练数据和测试数据的横轴和纵轴调换,并使数据维度保持一致,后面详细讲*/
if test_size > 0:
# The testset is sorted by size, but we want to keep random
# sizeexample. So we must select a randomselection of the
# examples.
idx =numpy.arange(len(test[0]))
numpy.random.shuffle(idx)
idx =idx[:test_size]
test =([test[0][n] for n in idx], [test[1][n] for n in idx])
/*如果我们设置了test_size的大小,这个步骤就是从测试集中随机找test_size个作为测试数据,如果没有设置test_size,会用所有的测试集数据做测试。原来的测试数据是根据长度排列的(imdb数据自身特点),这里做了一次打散*/
ydim = numpy.max(train[1]) + 1
model_options['ydim'] = ydim
/*ydim为标签y的维数,因为是从0开始的,所以后面+1,并将它加入模型参数中*/
print('Building model')
# This create the initial parameters as numpy ndarrays.
# Dict name (string) -> numpy ndarray
params = init_params(model_options)
/*模型建立阶段,首先初始化各种参数,调用了全局作用域的函数init_params()*/
definit_params(options):
"""
Global (not LSTM) parameter. For the embedingand the classifier.
"""
/*根据源代码的注释,embedding,claffier和lstm层的参数不是一起初始化的,这里先初始化embedding,claffier的参数*/
params = OrderedDict()