theano学习指南

阅读: 评论:0

theano学习指南

theano学习指南

欢迎fork我的github:

最近在学习Git,所以正好趁这个机会,把学习到的知识实践一下~ 看完DeepLearning的原理,有了大体的了解,但是对于theano的代码,还是自己撸一遍印象更深 所以照着deeplearning上的代码,重新写了一遍,注释部分是原文翻译和自己的理解。 感兴趣的小伙伴可以一起完成这个工作哦~ 有问题欢迎联系我 Email: zhaoyuafeu@gmail QQ: 3062984605


概述

本教程中,你将会学到:

  • 词向量
  • 循环神经网络架构
  • 文本窗口

从而实现Semantic Parsing / Slot-Filling(自然语言的理解)。

代码—引用—联系方式

代码

实验代码见github repository。

论文

如果使用本教程,请引用下列文献:

  • Grégoire Mesnil, Xiaodong He, Li Deng and Yoshua Bengio. Investigation of Recurrent-Neural-Network Architectures and Learning Methods for Spoken Language Understanding. Interspeech, 2013.
  • Gokhan Tur, Dilek Hakkani-Tur and Larry Heck. What is left to be understood in ATIS?
  • Christian Raymond and Giuseppe Riccardi. Generative and discriminative algorithms for spoken language understanding. Interspeech, 2007.
  • Christian Raymond and Giuseppe Riccardi. Generative and discriminative algorithms for spoken language understanding. Interspeech, 2007.
  • Bergstra, James, Breuleux, Olivier, Bastien, Frédéric, Lamblin, Pascal, Pascanu, Razvan, Desjardins, Guillaume, Turian, Joseph, Warde-Farley, David, and Bengio, Yoshua. Theano: a CPU and GPU math expression compiler. In Proceedings of the Python for Scientific Computing Conference (SciPy), June 2010.

谢谢!

联系方式

有问题请联系 Grégoire Mesnil (first-add-a-dot-last-add-at-gmail-add-a-dot-com)。我们很乐意收到您的反馈。

任务

Slot-Filling (Spoken Language Understanding)是对给定的句子中每个单词标定标签。这是一个分类问题。

数据集

数据集是DARPA的一个小型数据集:ATIS (Airline Travel Information System)。这里的语句例子使用Inside Outside Beginning (IOB)表示 。

input(words)showflightsfromBostontoNewYorktoday
Output(labels)OOOB-deptOB-arrI-arrB-date

ATIS 包含单词4978个,句子893个,测试集合包含单词56590个,句子9198个(平均句子长度为15)。类的数量(不同的slots)为128,其中包括O标签(NULL)。
在论文 Microsoft Research people,对于只出现一次的单词,标记为,运用同样的方法标记未出现的单词。在论文Ronan Collobert and colleagues中,用数字表示字符串,例如1984表示DIGITDIGITDIGITDIGIT。
我们将训练集合分为训练集和验证集,分别包含80%和20%的训练语句。 Significant performance improvement difference has to be greater than 0.6% in F1 measure at the 95% level due to the small size of the dataset。为了验证效果,实验中定义了三个矩阵:

  • Precision
  • Recall
  • F1 score

这里使用conlleval文本验证模型效果。

循环神经网络模型

原始输入编码

一个token对应一个单词。ATIS中词汇表对应的每个token都有相应的索引。每个语句是索引的数组(int32)。其次,每个集合(训练集、验证集、测试集)是索引数组的列表。定义python字典将索引映射到单词。

>>> sentence
array([383, 189,  13, 193, 208, 307, 195, 502, 260, 539,7,  60,  72, 8, 350, 384], dtype=int32)
>>> map(lambda x: index2word[x], sentence)
['please', 'find', 'a', 'flight', 'from', 'miami', 'florida','to', 'las', 'vegas', '<UNK>', 'arriving', 'before', 'DIGIT', "o'clock", 'pm']

对于标签,采用同样的方法:

>>> labels
array([126, 126, 126, 126, 126,  48,  50, 126,  78, 123,  81, 126,  15,14,  89,  89], dtype=int32)
>>> map(lambda x: index2label[x], labels)
['O', 'O', 'O', 'O', 'O', 'B-fromloc.city_name', 'B-fromloc.state_name','O', 'B-toloc.city_name', 'I-toloc.city_name', 'B-toloc.state_name','O', 'B-arrive_time.time_relative', 'B-arrive_time.time','I-arrive_time.time', 'I-arrive_time.time']

文本窗

给定语句:索引的数组,窗口大小:1,3,5,…。现在需要将语句中每个词根据文本窗选定该词周围的词。具体实现如下:

def contextwin(l, win):'''win :: int corresponding to the size of the windowgiven a list of indexes composing a sentencel :: array containing the word indexesit will return a list of list of indexes correspondingto context windows surrounding each word in the sentence'''assert (win % 2) == 1assert win >= 1l = list(l)lpadded = win // 2 * [-1] + l + win // 2 * [-1]out = [lpadded[i:(i + win)] for i in range(len(l))]assert len(out) == len(l)return out

PADDING索引中的-1插在语句的开始/结束位置。
例子如下:

>>> x
array([0, 1, 2, 3, 4], dtype=int32)
>>> contextwin(x, 3)
[[-1, 0, 1],[ 0, 1, 2],[ 1, 2, 3],[ 2, 3, 4],[ 3, 4,-1]]
>>> contextwin(x, 7)
[[-1, -1, -1, 0, 1, 2, 3],[-1, -1,  0, 1, 2, 3, 4],[-1,  0,  1, 2, 3, 4,-1],[ 0,  1,  2, 3, 4,-1,-1],[ 1,  2,  3, 4,-1,-1,-1]]

总的来说,输入为一个索引的数组,输出为索引的矩阵。每行是指定单词的文本窗。

词向量

将语句转换成文本窗:索引的矩阵,下一步需要将索引转换为词向量。使用Theano。代码如下:

import theano, numpy
from theano import tensor as T# nv :: size of our vocabulary
# de :: dimension of the embedding space
# cs :: context window size
nv, de, cs = 1000, 50, 5embeddings = theano.shared(0.2 * numpy.random.uniform(-1.0, 1.0, (nv+1, de)).fig.floatX)) # add one for PADDING at the endidxs = T.imatrix() # as many columns as words in the context window and as many lines as words in the sentence
x    = b[idxs].reshape((idxs.shape[0], de*cs))

符号变量x表示矩阵的维度(语句中单词数量,文本窗的长度)。
下面开始编译theano函数:

>>> sample
array([0, 1, 2, 3, 4], dtype=int32)
>>> csample = contextwin(sample, 7)
[[-1, -1, -1, 0, 1, 2, 3],[-1, -1,  0, 1, 2, 3, 4],[-1,  0,  1, 2, 3, 4,-1],[ 0,  1,  2, 3, 4,-1,-1],[ 1,  2,  3, 4,-1,-1,-1]]
>>> f = theano.function(inputs=[idxs], outputs=x)
>>> f(csample)
array([[-0.08088442,  0.08458307,  0.05064092, ...,  0.06876887,-0.06648078, -0.15192257],[-0.08088442,  0.08458307,  0.05064092, ...,  0.11192625,0.08745284,  0.04381778],[-0.08088442,  0.08458307,  0.05064092, ..., -0.00937143,0.10804889,  0.1247109 ],[ 0.11038255, -0.10563177, -0.18760249, ..., -0.00937143,0.10804889,  0.1247109 ],[ 0.18738101,  0.14727569, -0.069544  , ..., -0.00937143,0.10804889,  0.1247109 ]], dtype=float32)
>>> f(csample).shape
(5, 350)

我们现在得到了文本窗词向量的一个序列(长度为5,表示语句长度),该词向量非常适用循环神经网络。

Elman循环神经网络

Elman循环神经网络(E-RNN)的输入为当前输入(t时刻)和之前隐层状态(t-1时刻)。然后重复该步骤。
在之前章节中,我们构造输入为时序结构。在上述矩阵中,第0行表示t=0时刻,第1行表示t=1时刻,如此等等。
E-RNN中需要学习的参数如下:

  • 词向量(真实值矩阵)
  • 初始隐藏状态(真实值矢量)
  • 作用于线性过程的t时刻输入和t-1时刻隐层状态的两个矩阵
  • (优化)偏置。建议:不使用
  • 顶层的softmax分类器

整个网络的超参数如下:

  • 词向量的维度
  • 词汇表的数量
  • 隐层单元的数量
  • 类的数量
  • 用于初始化模型的随机种子

代码如下:

class RNNSLU(object):''' elman neural net model '''def __init__(self, nh, nc, ne, de, cs):'''nh :: dimension of the hidden layernc :: number of classesne :: number of word embeddings in the vocabularyde :: dimension of the word embeddingscs :: word window context size'''# parameters of b = theano.shared(name='embeddings',value=0.2 * numpy.random.uniform(-1.0, 1.0,(ne+1, de))# add one for padding at the end.fig.floatX))self.wx = theano.shared(name='wx',value=0.2 * numpy.random.uniform(-1.0, 1.0,(de * cs, nh)).fig.floatX))self.wh = theano.shared(name='wh',value=0.2 * numpy.random.uniform(-1.0, 1.0,(nh, nh)).fig.floatX))self.w = theano.shared(name='w',value=0.2 * numpy.random.uniform(-1.0, 1.0,(nh, nc)).fig.floatX))self.bh = theano.shared(name='bh',value&#s(nh,dtype&#fig.floatX))self.b = theano.shared(name='b',value&#s(nc,dtype&#fig.floatX))self.h0 = theano.shared(name='h0',value&#s(nh,dtype&#fig.floatX))# bundleself.params = [b, self.wx, self.wh, self.w,self.bh, self.b, self.h0]

以下代码构造词矩阵的输入:

 idxs = T.imatrix()x = b[idxs].reshape((idxs.shape[0], de*cs))y_sentence = T.ivector('y_sentence')  # labels

调用scan函数实现递归,效果很神奇:

def recurrence(x_t, h_tm1):h_t = T.nnet.sigmoid(T.dot(x_t, self.wx)+ T.dot(h_tm1, self.wh) + self.bh)s_t = T.nnet.softmax(T.dot(h_t, self.w) + self.b)return [h_t, s_t][h, s], _ = theano.scan(fn=recurrence,sequences=x,outputs_info=[self.h0, None],n_steps=x.shape[0])p_y_given_x_sentence = s[:, 0, :]y_pred = T.argmax(p_y_given_x_sentence, axis=1)

Theano会自动的计算所有梯度用于最大最小化似然概率:

lr = T.scalar('lr')sentence_nll = -T.mean(T.log(p_y_given_x_sentence)[T.arange(x.shape[0]), y_sentence])
sentence_gradients = T.grad(sentence_nll, self.params)
sentence_updates = OrderedDict((p, p - lr*g)for p, g inzip(self.params, sentence_gradients))

然后编译函数:

self.classify = theano.function(inputs=[idxs], outputs=y_pred)
self.sentence_train = theano.function(inputs=[idxs, y_sentence, lr],outputs=sentence_nll,updates=sentence_updates)

在每次更新之后,需要将词向量正则化:

        alize = theano.function(inputs=[],updates={b /T.sqrt((b**2).sum(axis=1)).dimshuffle(0, 'x')})

这就是所有的工作!

评估

根据之前定义的函数,你可以比较预测标签和真实标签,并计算相关矩阵。在这个github仓库,封装了conlleval文本。计算关于Inside Outside Beginning (IOB)的矩阵是十分必要的。如果词起始、词中间、词末端预测都是正确的,那么就认为该预测是正确的。需要注意的是,文本后缀是txt,而计算过程中需要将其转换为pl。

训练

更新

对于随机梯度下降法(SGD)的更新,我们将整句作为一个mini-batch,并对每句执行一次更新。对于纯SGD(不同于mini-batch),每个单词执行一次更新。
每次循环/更新之后,需要正则化词向量,保证它们有统一的单位。

停止引用

在验证集上提前结束是一种常规技术:训练集运行一定的代数,每代在验证集上计算F1得分,并保留最好的模型。

超参数选择

尽管已经有关于超参数选择的研究/代码,这里我们使用KISS随机搜索。
以下参数是一些建议值:

  • 学习率:uniform([0.05,0.01])
  • 窗口大小:集合{3,…,19}的随机数
  • 隐层单元数量:{100,200}之间的随机数
  • 词向量维度:{50,100}之间的随机数

运行程序

使用download.sh命令下载数据文件后,可以调用以下命令运行程序:

python code/rnnslu.py('NEW BEST: epoch', 25, 'valid F1', 96.84, 'best test F1', 93.79)
[learning] epoch 26 >> 100.00% completed in 28.76 (sec) <<
[learning] epoch 27 >> 100.00% completed in 28.76 (sec) <<
...
('BEST RESULT: epoch', 57, 'valid F1', 97.23, 'best test F1', 94.2, 'with the model', 'rnnslu')

时间

使用github仓库中的代码测试ATIS数据集,每代少于40秒。实验平台为:n i7 CPU 950 @ 3.07GHz using less than 200 Mo of RAM。

[learning] epoch 0 >> 100.00% completed in 34.48 (sec) <<

进行若干代之后,F1得分下降为94.48% 。

NEW BEST: epoch 28 valid F1 96.61 best test F1 94.19
NEW BEST: epoch 29 valid F1 96.63 best test F1 94.42
[learning] epoch 30 >> 100.00% completed in 35.04 (sec) <<
[learning] epoch 31 >> 100.00% completed in 34.80 (sec) <<
[...]
NEW BEST: epoch 40 valid F1 97.25 best test F1 94.34
[learning] epoch 41 >> 100.00% completed in 35.18 (sec) <<
NEW BEST: epoch 42 valid F1 97.33 best test F1 94.48
[learning] epoch 43 >> 100.00% completed in 35.39 (sec) <<
[learning] epoch 44 >> 100.00% completed in 35.31 (sec) <<
[...]

词向量近邻

我们可以对学习到的词向量进行K近邻检查。L2距离和cos距离返回结果相同,所以我们画出词向量的cos距离。

atlantabackap80butaircraftbusinessaaugustactuallycheap
phoenixliveap57ifplanecoachpeopleseptemberprovideweekday
denverlivesapupservicefirstdojanuarypricesweekdays
tacomabothconnectionsaairplanefourthbutjunestopam
columbushowtomorrownowseatingthriftnumbersdecembernumberearly
seattlemebeforeamountstandtenthabbreviationnovemberflightsfo
minneapolisoutearliestmorethatsecondifapriltheremilwaukee
pittsburghotherconnectabbreviationonfifthupjulyservingjfk
ontarioplanethriftrestrictionsturbopropthirdservejfkthankshortest
montrealservicecoachmeanmeantwelfthdatabaseoctoberticketbwi
philadelphiafaretodayinterestedamountsixthpassengersmayarelastest

可以看出,较少的词汇表(大约500单词)可以较少计算量。根据人为识别,发现有些分类效果好,有些则较差。

本文发布于:2024-01-31 05:42:36,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170665095725966.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:Theano
标签:学习指南   theano
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23