DL&ML基础学习五

CNN应用在NLP自然语言处理上面,基本原理是输入是一句话,将一句话分词,每个词表示成一个向量,作为矩阵的一行,所以一句话形成一个矩阵,这个矩阵就类似于图片的像素点矩阵作为输入。该矩阵作为CNN的输入数据。此时CNN的卷积核的特点在于其每个卷积核的宽度都和输入数据的长度相同,宽度仍然是超参。其他原理相同。CNN的优势一个是快速,他可以并行运算,而且前后不具有依赖性。他的表示效果更有效。CNN的卷积核的作用类比于NLP中的n-gram模型,但是要比NLP的n-gram模型要更加紧凑。但是CNN的卷积和池化操作丢失掉了局部内容的次序,这导致CNN在某些应用中不是很好。但是CNN在NLP中的包括情感分析、主题分类、上下文检测、关系提取、关系分类、信息检索。CNN应用于NLP时输入的数据可以是based-on-word、bases-on-character的,输入矩阵可能经过也可能没有经过pre-trained。CNN中超参的影响中,最大池化一般都比平均池化效果好,卷积核尺度很重要但是依赖于任务,正则化并没有起到多大的作用等。不同类型的CNN适用于不同量级的数据集。

BN层的解释:Batch Normalization层的出发点在于对每层的输入数据做归一化并且不希望改变数据分布特征因为每一层想要学到的就是数据的分布特征,因为对数据进行归一化处理可以加速训练过程。原始的BN核心的公式是y(k)=γ(k)*x(k)'+β(k),γ和β是需要学习的参数,x是经过了零均值化和方差归一化处理的x,公式可以保证数据的分布特性,仅仅个人认为,核心公式是在对归一化之后的数据进行线性的调整,具体调整幅度取决于学习到的参数,同时该公式导致反向传播时可求导。

RNN的Encoder-Decoder框架:编码-解码模型,用于自然语言处理、机器翻译等和语言相关的领域。大体分为两个阶段encode与decode。在encode阶段,输入可能是有文字词语组成的序列,每一时刻的输入是单词对应的向量,共T时刻,模型采用RNN系列,最后的结果是固定长度的编码向量,之所以是固定长度的是因为取最后一个时刻的中间隐藏层的向量或者所有时刻的隐藏层的向量加和求平均值作为编码向量,所以encode可以实现无论输入序列的长度编码之后的向量长度都是固定长度的,当然结果长度取决于中间隐藏层设定的神经元数目,这实际是一个有损压缩阶段。decode阶段,有多种方式,因为此时没有了原始输入数据,有的只是编码向量,所以将该向量作为每一时刻的输入向量数据,就是说解码时每一时刻的输入数据都是编码向量,每一时刻的输出都是解码出来的每一个词语代表的向量,也可能是该向量作为decoder模型的初始隐藏层状态向量。另一种解码方式,是解码时编码向量作为第一时刻的输入数据,之后的输入数据是该编码向量和上一时刻的输出向量的融合。另一种解码方式是解码时编码向量作为第一时刻的输入数据,之后的时刻的输入数据是上一个时刻的输出向量。第四种解码模型加入了注意力机制。单词向量化可以采用one-hot向量或者用destributed vector借助于word2vector来实现,句子向量化借助于RNN取得中间隐藏层值即encoder-decoder之间的context向量。迄今为止我见过的解释encoder-decoder最清楚的一段是:

Here we will feed in the input sequence into the encoder which will generate a final hidden state that we will feed into a decoder. The final hidden state from the encoder is the new initial state for the decoder. We will use the decoder outputs with softmax and compare it to the targets to calculate our loss.

Bahdanau类型注意力机制的原理:原始的encoder-decoder实际对于编码向量的做法过于粗糙,序列变长由于梯度消失问题导致效果不好,隐形的表示所有位置的原始数据对于最后decoder生成的内容作用权重相同。如果在decoder的不同时刻能够输入不同的编码向量就会提升表达能力。attention-based中用aij表示Encoder中第j阶段的hj和解码时第i阶段的相关性,最终Decoder中第i阶段的输入向量ci就是所有的hj和aij的加权和,a代表重要程度,a的求解来源于e(ij)的softmax归一化,而e实际s是衡量s_i-1和h_j的匹配程度,可能是使用神经网络来计算或者cosin距离或者两者dot值来计算,是在学习encoder的hj与decoder的s(i-1)之间的对应程度或者说匹配程度。 aij同样是从模型中学出的,它实际和Decoder的第i-1阶段的隐状态、Encoder第j个阶段的隐状态有关。对于seq2seq的decoder,它在训练阶段和预测阶段对rnn的输出的处理可能是不一样的,比如在训练阶段可能对rnn的输出不处理,直接用target的序列作为下时刻的输入。而预测阶段会将rnn的输出当成是下一时刻的输入,因为此时已经没有target序列可以作为输入。RNN训练的时候是要让p(x)=∏p(xt|x1,...,xt−1)尽可能大,原理是用最大似然估计。encoder-decoder的一条记录的条件概率为p(y1,...,yT‘|x1,...,xT) = ∏p(yt|v,y1,...,yt−1),v代表编码向量也就代表x输入数据序列,训练目标是使所有样本的p(y1,...,yT‘|x1,...,xT)概率之和最大,对应的对数似然条件概率函数为,∑log(yn|xn,θ),使之最大化,θ则是待确定的模型参数。

实现的时候,一般minibatch形式处理所以输入到RNN的输入数据的shape为(batch_size, time_steps, wordvec_len)我怀疑这个wordvec_len=vocab_size,中间隐藏层指定的维度就变为(batch_size, num_units),RNN输入层的神经元数目是wordvec_len,输入层到中间层的参数w的shape是(wordvec_size,num_size),b的shape是(num_size),从中间层到输出层的参数w的shape是(num_size, vocan_size),与理论不同的是实际是指定固定最大处理长度num_steps的因为长度不固定不容易优化,encoder的初始中间层采用全0初始化,训练阶段需要先把输入单词转化为word embedding,对于训练语料可能提前转作了词向量了就可以直接输入进encoder但是对于测试时给定的输入就需要按照字在词库中的编号位置来取得其词向量了所以还需要提前准备词库和词向量库,encoder的每一时刻的输出没有用到,每一时刻的h层需要保存下来之后计算context vector。decoder则是初始中间层采用全0初始化,训练阶段输入的x是target seq,前面加上<GO>开始符最后加上<EOS>结束符如果不够长度则使用<PAD>来填充剩余位置,target seq的每一个字也是需要做成word embedding,每一时刻的c_i和targetseq_i作为输入,当然还有上一个时刻的中间状态s_i-1来得出该时刻的s_i和输出output,在测试阶段由于没有target所以不再有targetseq_i而是上一个时刻的输出y_i-1。得到decoder的每一时刻的y_i还需要将其依据词向量和词库转化为对应的单词进行输出。对于数据的预处理,需要将文本数据集中每句话分词转化为tokens(英文可能是根据空字符而中文需要分词jieba),并依据这些tokens来建立一个词库vocab_dict,每一个tokens都有其在词库的编号ids,建立token-ids和ids_token的对应序列便于之后对应转化。在词库中额外添加<GO>1/<EOS>2/<PAD>0符号。之后用<PAD>把source_seq和target_seq填充到max_length,target_seq还需要在结尾处添加<EOS>终止符,再对target_seq添加<GO>才能作为decoder_input输入进去,此时能够得到的是用来表示encoder_input和decoder_input的一系列ids编号序列,正如:

      

由ids序列转化为word embedding,这里是我这些天一直头疼的问题,因为tensorflow有一个tensorflow.nn.embedding_lookup(embedding, intputs)它的返回值将会作为inputs输入数据真正输入进RNN中,在网上查了诸多资料也没有搞懂或者一知半解,幸运的是借助朋友的“科学空间”博客看到了希望。这里系统梳理一下:困惑在于明明之前用到了gensim来生成词向量为什么还需要在搭建encoder-decoder的时候还需要embedding?实际在rnn的输入层之前可以看作还有一个embedding层,这一层的工作是将以ids表示的词转化为其词向量的模式,而这个工作是由embedding_lookup()完成的,从名字看就可以猜到他是在lookup查找,查找什么?查找该词对应的词向量。如何查找?采用one_hot形式的向量与之前的词向量矩阵相乘,这实际上可以看作一层线性的神经网络(也就是说一个线性的神经网络层或者说单层的MLP可以视为查表操作,从这个角度理解又会对神经网络有所新的认识。),one_hot形式的向量是输入数据,词向量矩阵是参数但是这个参数可不是在这里要学习的它是之前通过语言模型得到的字向量表,相乘的结果是该层的输出也是该词对应的词向量,这个词向量会输入到RNN中进行处理。为什么这么做,实现一个模型或算法和理论上可能有很大出入,而这种出入的绝大部原因在于追求“快速”,这可以减少计算量,减少加法和乘法的计算次数从而加快速度,同时由于词向量维度比vocab_size小得多可以实现降维处理,同时减少了模型的训练参数。所以如果我们最原始的输入不是one_hot向量而是直接的对应的词向量则可以直接输入进去啊,可是对于测试的时候用户给出的词我们是可以根据之前建立的字库找到每一个字对应在字库中的位置编号作为one_hot输入进去转化为word_embedding的。需要声明一些东西,词向量是用向量的形式表示词或字,可能是one-hot类型或者distributed vector类型。语言模型是用来评判一个句子是自然语言的概率,简单说就是一个人类某一类别语言的模子,他是通过基于之前的出现的词来按照概率最大化的方法预测下一个可能出现的字,是一种条件概率分布,也可以看作属于贝叶斯学派的产物。然而语言模型的副产物就是“词向量”,我们对语言模型输入one hot,然后连接一个全连接层,然后再连接若干个层,最后接一个softmax分类器,就可以得到语言模型了,然后将大批量文本输入训练就行了,最后得到第一个全连接层的参数,就是字、词向量表,而word2vector贡献在于它通过新的结构加快了处理速度。所以我们需要的是什么?需要字库,词向量表,作为训练预料的关键字,网络模型。字库哪里来?可能来源于开源库,可能是来源于我们自己的训练语句一个字一个字组织起来的。字库的形式是什么?一般是ch2int和int2ch,也就是ch和int的对应item。得到关键字就可以通过ch2int得到该字在字库中对应的编号,就可以写作ont_hot向量了,有了词向量就可以得到该词向量对应的one_hot进而通过int2ch可以得到对应的到底是那个字了,事实上就是网络模型的最原始的输入和最末尾的输出。词向量表哪里来?wore2vector/gensim等开源实现。模型可能是rnn/lstm等。关键字可能是用户给出,可能从训练语句中提取,如何提取?英文可以直接按照空字符分离并去除stopwords得到,而中文需要利用jieba等分词工具进行分词,而这每一个开源工具实际上又是诸多的神经网络。当然对于序列模型的输入要考虑到开始符号<GO>终止符号<EOS>填充符号<PAD>等,另外还有更加容易晕的batch_size,因为加入了batch_size说明mini_batch Gradient Descent处理,那么如何实现这个批量处理?并行可以利用大规模硬件的优势,又可以加快速度。如何并行?按照batch_size每次建立多个相同的模型,每一个模型处理的不同的输入数据,因为在一个batch_size处理期间参数是不能改变的,直到该batch完事儿之后才会更新,所以batch内是可以并行的。可以构建模型的时候传递的参数中哪里需要传递说明batch_size呢?

这是我见过的最清晰的注意力机制图片:

   


参考:

http://www.wildml.com/2015/11/understanding-convolutional-neural-networks-for-nlp/

http://mp.weixin.qq.com/s/swLwla75RIQfyDDCPYynaw

http://blog.csdn.net/wangyangzhizhou/article/details/77883152?spm=a2c4e.11153940.blogcont241763.6.6cfed9a1MCEYl

https://sthsf.github.io/wiki/Algorithm/DeepLearning/Tensorflow%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/Tensorflow%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86---Senquence-to-Senquence%E8%AF%A6%E8%A7%A3.html

http://spaces.ac.cn/archives/4122/

https://www.cnblogs.com/bonelee/p/7904495.html

猜你喜欢

转载自blog.csdn.net/ingwfj/article/details/78916472
今日推荐