Lasagne简单教程

<u>版权所有,转载请注明出处</u>


参考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数据集的字符识别为例。
整个过程分为以下几个部分:

下面分别介绍这几个部分

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')

这两个变量作为训练函数的自变量,在实际训练时只需要将真实的训练数据带入了函数中即可。

prediction = lasagne.layers.get_output(network)
loss = lasagne.objectives.categorical_crossentropy(prediction, target_var)
loss = loss.mean()

这里的network是前面定义的网络模型,prediction表示网络模型的输出表达式。这里的的损失函数采用的是categorical_crossentropy
验证集和测试集上的定义与此类似,只是我们需要更改deterministicdeterministic=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,主要包括:

<div align = center>-END-</div>


<u>版权所有,转载请注明出处</u>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容