版权所有,转载请注明出处
参考Lasagne官网tutorial进行总结而来。
一、简介
Lasagne is a lightweight library to build and train neural networks in Theano.
Lasagen是一个基于Theano的轻量级的神经网络库。其实就是对Theano库的上层封装,使其用起来更简单,但是相应的灵活性下降。
Lasagne设计的六个原则是简洁、透明、模块化、实用、聚焦和专注。
官网地址:http://lasagne.readthedocs.io/en/latest/index.html
GitHub: https://github.com/Lasagne/Lasagne
二、安装
本质上来说Lasagne还是个python库,所以它的安装还是很简单的,通过pip就可以安装了。整个安装就两步:安装依赖包和安装Lasagen.
官网有很详细的安装教程。
- 稳定版安装
执行下面两条命令即可:
pip install -r https://raw.githubusercontent.com/Lasagne/Lasagne/v0.1/requirements.txt
pip install Lasagne==0.1
- Bleeding-edge version
执行下面两条命令:
pip install --upgrade https://github.com/Theano/Theano/archive/master.zip
pip install --upgrade https://github.com/Lasagne/Lasagne/archive/master.zip
- 开发版安装
执行下面命令
git clone https://github.com/Lasagne/Lasagne.git
cd Lasagne
pip install -r requirements.txt
pip install --editable
这里建议安装Bleeding-edge version,功能相对比较新,而版本也相对稳定。
三、Tutorial
教程还是以经典的mnist数据集的字符识别为例。
整个过程分为以下几个部分:
- Loading data/加载数据
- Building the model/建立模型
- Training the model/训练模型
下面分别介绍这几个部分
1.加载数据
这个和其它库的数据加载方法差不多,都是采用python语法处理数据,没有太多特殊之处,这里就不详细介绍了,具体的可以查阅源代码mnist.py
2.建立模型
和所有的框架一样,非常重要的一个环节就是进行网络模型的定义。Lasagne的网络模型建立方法和torch比较相似,都是对各种常用网络层(layer)进行了封装,我们只需要调用相应的网络层函数并把它们搭接在一起就可以了,就像盖房子一样。
下面以建立多层感知机、卷积神经网络等模型为例进行介绍。
- 多层感知机(Multi-Layer Perceptron, MLP)
这里以构建一个两个隐藏层的多层感知机为例,并对输入增加20%的dropout、隐藏层增加50%的dropout。
实际上,我们网络模型就由输入层+两个隐藏层+输出层组成,只需要对其分别进行定义即可。
** 输入层 **
输入层采用InputLayer
进行定义,InputLayer
只用于接收数据,不对数据做任何处理,类似于tensorfolw里的placeholder功能。定义方法如下:
l_in = lasagne.layers.InputLayer(shape=(None, 1, 28, 28), input_var=input_var)
shape里对应的四个参数分别表示:(batchsize, channels, rows, columns)
,input_var
表示需要连接到网络输入层的theano变量,默认为none
。
然后对输入数据加以20%的dropout,采用DropoutLayer
进行定义:
l_in_drop = lasagne.layers.DropoutLayer(l_in, p=0.2)
p=0.2
表示dropout的比例。DropoutLayer
也属于layers
里的一个组件,也可以简写为dropout
** 隐藏层 **
这里的隐藏层由全连接层、激活层、dropout层组成。Lasagne将全连接层和激活层封装到一个函数里了,即DenseLayer
,定义如下:
l_hid1 = lasagne.layers.DenseLayer(
l_in_drop, num_units=800,
nonlinearity=lasagne.nonlinearities.rectify,
W=lasagne.init.GlorotUniform())
num_units
表示全连接层的单元数目,nonlinearity
用以定义激活层函数,激活层函数封装在lasagne.nonlinearities
中,这里选择的是ReLU函数,而网络参数的初始化封装在lasagne.init
里,只需要分别进行调用就可以了。
之后添加50%的dropou:
l_hid1_drop = lasagne.layers.DropoutLayer(l_hid1, p=0.5)
第二个隐藏层的定义与此类似,这里就不赘述了。
** 输出层 **
输出层依然是一个全连接网络,只是不同的是这里是做分类任务,所以需要将非线性函数/激活函数修改为softmax
,如下:
l_out = lasagne.layers.DenseLayer(
l_hid2_drop, num_units=10,
nonlinearity=lasagne.nonlinearities.softmax)
这样就得到了一个含两个隐藏层的多层感知机了。当然,我们也可以像官网一样将一些网络设置参数作为函数变量输入,创建可自定义的多层感知机。
- 卷积神经网络(Convolutional Neural Network, CNN)
这里以建立一个含两个卷积层的神经网络为例。网络模型的具体组成包括输入层、两个卷积层、全连接层、输出层。
** 输入层 **
输入层的定义和前面一样,不再赘述。
** 卷积层 **
卷积层采用Conv2DLayer
进行定义,定义如下:
network = lasagne.layers.Conv2DLayer(
network, num_filters=32, filter_size=(5, 5),
nonlinearity=lasagne.nonlinearities.rectify,
W=lasagne.init.GlorotUniform())
num_filters
表示卷积核的数目,filter_size
表示卷积核的大小,激活函数和参数初始化和DenseLayer
类似。当然,我们还可以定义padding、stride等参数,具体方法可以查看Conv2DLayer
的帮助。
值得注意的是lasagne默认采用的是theano的卷积实现方法,如果配置了gpu就会调用Nvidia提供的cuDNN实现。lasagne也提供了一些其它的实现方法:
lasagne.layers.dnn.Conv2DDNNLayer to enforce cuDNN, lasagne.layers.corrmm.Conv2DMMLayer to enforce the gemm-based one, lasagne.layers.cuda_convnet.Conv2DCCLayer for Krizhevsky’s cuda-convnet.
一般情况,我们会在卷积层后加上pooling
层,其中maxpool采用函数MaxPool2DLayer
进行定义:
network = lasagne.layers.MaxPool2DLayer(network, pool_size=(2, 2))
pool_size
表示pooling的大小。当然我们也可以采用Pool2DLayer
定义meanPool等。
之后的第二个卷积层、全连接层、输出层的定义与前面类似,此处不再赘述。
通过前面mlp和cnn的定义可以发现,在lasagne里定义网络,只需要在lasagne.layers
里调用对应的网络层函数然后按照一定的结构组装起来即可。
关于lasagne.layers的详细使用可以查阅官方文档lasagne.layers
3.训练模型
和一般的深度学习框架类似,我们还需要定义训练模型,包括:损失函数、更新/优化函数等。在Lasagne里,或者更准确的说是在Theano里,一般是将网络模型、训练模型整合在一块儿定义一个function,然后再将训练数据/测试数据作为函数的自变量输入到函数中,而输入数据通过tensor
来进行定义,网络参数通过shared
来更新并保存。tensorflow和这个其实是有点类似,tensorflow是将网络模型、训练模型等等整合成一个计算图,定义一个placeholder接收数据,而网络参数通过Variable
来保持。
下面,通过代码来进行说明。
- 数据准备
通过Theano里的tensor
进行定义:
# Prepare Theano variables for inputs and targets
input_var = T.tensor4('inputs')
target_var = T.ivector('targets')
这两个变量作为训练函数的自变量,在实际训练时只需要将真实的训练数据带入了函数中即可。
- 损失和更新函数定义
通过调用lasagne.objectives
里的损失函数来定义不同的损失函数:
prediction = lasagne.layers.get_output(network)
loss = lasagne.objectives.categorical_crossentropy(prediction, target_var)
loss = loss.mean()
这里的network
是前面定义的网络模型,prediction
表示网络模型的输出表达式。这里的的损失函数采用的是categorical_crossentropy
。
验证集和测试集上的定义与此类似,只是我们需要更改deterministic
为deterministic=True
,这样会屏蔽掉所有的dropout层:
test_prediction = lasagne.layers.get_output(network, deterministic=True)
test_loss = lasagne.objectives.categorical_crossentropy(test_prediction,
target_var)
test_loss = test_loss.mean()
有了网络模型和损失函数的定义后,还需要定义网络训练与参数更新方法的表达式,一般采用梯度下降方法。更新方法通过调用lasagne.updates
里的更新函数来进行定义,这里采用的是Stochastic Gradient Descent (SGD) with Nesterov momentum,即nesterov_momentum
:
params = lasagne.layers.get_all_params(network, trainable=True)
updates = lasagne.updates.nesterov_momentum(
loss, params, learning_rate=0.01, momentum=0.9)
这里我们第一步需要先获取所有的网络参数,然后产生更新参数的更新表达式。
- Compilation
最后,就是基于前面的表达式定义一步训练函数:
train_fn = theano.function([input_var, target_var], loss, updates=updates)
这个函数是告诉Theano生成一个训练函数,接收两个输入input_var, target_var
,然后计算trainning loss并返回,之后利用updates表达式更新参数。
如果是用于验证和测试,我们就不需要进行网络参数的更新,这时这样定义:
val_fn = theano.function([input_var, target_var], [test_loss, test_acc])
对于测试精度,采用下面定义:
test_acc = T.mean(T.eq(T.argmax(test_prediction, axis=1), target_var),
dtype=theano.config.floatX)
前面的这么多定义,其实并没有进行正式的计算,就像是tensorflow里的计算图定义。其实就像是我们在高中的时候解一道数学题,往往都是先把最终的符号表达式推导出来,最后再把输入x代入表达式计算结果y。Theano的当初的诞生其实也是基于这个需求的,当时python的Numpy、Scipy等库主要用于数值计算,但是需要一种能够调用库就得到导数的符号表达式的库,所以就有了后来的Theano,所以本质上来说早期的Theano的定位是一个融合符号运算与数值计算的数学计算库。
- 循环训练
有了一步训练表达式后就可以将真实的数据输入到函数中进行循环训练了:
for epoch in range(num_epochs):
# In each epoch, we do a full pass over the training data:
train_err = 0
train_batches = 0
start_time = time.time()
for batch in iterate_minibatches(X_train, y_train, 500, shuffle=True):
inputs, targets = batch
train_err += train_fn(inputs, targets)
train_batches += 1
# And a full pass over the validation data:
val_err = 0
val_acc = 0
val_batches = 0
for batch in iterate_minibatches(X_val, y_val, 500, shuffle=False):
inputs, targets = batch
err, acc = val_fn(inputs, targets)
val_err += err
val_acc += acc
val_batches += 1
# Then we print the results for this epoch:
print("Epoch {} of {} took {:.3f}s".format(
epoch + 1, num_epochs, time.time() - start_time))
print(" training loss:\t\t{:.6f}".format(train_err / train_batches))
print(" validation loss:\t\t{:.6f}".format(val_err / val_batches))
print(" validation accuracy:\t\t{:.2f} %".format(
val_acc / val_batches * 100))
以上就是Lasagne的简单使用方法的,还是挺简单的,跟着教程走,基本上一个小时就搞定了。如果要学习Theano库的其它一些用法以及各种函数的具体使用方法,建议查询官方文档里的API,主要包括:
- all layers(
lasagne.layers
) - weight initializers (
lasagne.init
) - nonlinearities (
lasagne.nonlinearities
) - loss expressions (
lasagne.objectives
) - training methods (
lasagne.updates
) - regularizers (
lasagne.regularization
) lasagne.random
lasagne.utils
版权所有,转载请注明出处