基于字符的NLP

阅读: 评论:0

基于字符的NLP

基于字符的NLP

背景

以往基于单词的NLP,一般是为要处理的词建立词向量空间,然后再对词向量进行NLP。这个处理会带来两个方面的问题是:

  • 对于出现频率比较低的词,建立的词向量有可能不准确
  • 无法处理不在单词表中的单词。比如网络上经常会出现一些新词,比如不明觉厉之类,英文的社交网络,还会出现比如loooooooooooooook之类的词。
  • 有些语言还会有合成词。比如德语就会有大量的合成词,如Lebensversicherungsgesellschaftsangestellter=Leben versicherung gesellschaft angestellter:寿险公司的雇员。而该合成词中的每个词都有可能会在词表里,但是合成词不身却不在词表。
  • 对于中文来说,要进行单词的NLP,还需要对其进行分词。而不同的分词器,分出的单词组合也不同。部分分词器对于人名之类的词也会分错。

于是,就有人提出为每个字符建立向量空间,再对其进行NLP。07年和13年的都有相应的论文进行了相应的尝试,但是不尽人意。15年之后的论文开始有比较好性能的字符级NLP。有些算法是直接将原单词级的神经网络直接替换为字符,有些比如只是在decoder端进行替换,还有些只是将单词切成segment,对每个segment建立向量空间。

基本结构

这里以英文NLP为例,介绍一个混合字符和单词、用于自动翻译的神经网络。该神经网络由斯坦福大学于2016年提出。

神经网络具体结构如图

其基本思想是基本结构仍然采用基于word级的encoder-decoder的LSTM。只不过进行了两处变化。

  • encoder:原输入端是直接在encoder的各个LSTM cell输入词向量。而该做法则是在输入词向量之前,先把词拆成一个个的字符,输入的是字符向量,通过神经网络,由字符向量算出词向量之后,再将词向量加到各个LSTM cell上。
  • decoder:在decoder端,原来的做法是产生一个个单词,如果该单词不在单词表中的话,用<unk>表示。而该做法是,如果某个LSTM cell输出了<unk>,则将该输出再接到另一个神经网络,逐个产生相应的字符,再将该神经网络产生的字符组成对应的单词。

基于word级的RNN的机器翻译技术在前文已经有介绍,这里不再重复叙述。这里重点介绍encoder和decoder处的变化。

Encoder

首先要对输入文本进行预处理,有以下步骤:

  1. 首先对输入的所有文本,计算其每句话的长度(单词个数),得到最大的长度 N N N。将所有没有到最大长度的句子加上<pad>。(确保word的Encoder端LSTM Cell数量是一定的)
  2. 设定每个单词的最大长度 m w o r d m_{word} mword​。对于没有达到最大长度的单词,也全部加上<pad>。(确保处理字符的LSTM Cell数量是一定的)。
    然后再逐句输入到Encoder端,输入到Encoder端的tensor的shape为 ( N , b , m w o r d ) (N, b, m_{word}) (N,b,mword​),其中 b b b为batch的大小(即句子的数量)。
    Encoder端的处理字符向量的模块如图所示。

    对于单个单词,首先要确定每个字符在字典中的位置,即
    x p a d d e d = ( c 1 , c 2 , . . . , c m w o r d ) ∈ Z m w o r d mathbf x_{padded} = (c_1,c_2,...,c_{m_{word}}) in mathbb Z^{m_{word}} xpadded​=(c1​,c2​,...,cmword​​)∈Zmword​
    其中 c i c_i ci​为单词 x x x的第 i i i个字符在字典中的位置。这样根据 x p a d d e d mathbf x_{padded} xpadded​,就可以建立字符向量
    x e m b e d = C h a r E m b e d d i n g ( x p a d d e d ) ∈ R m w o r d × e c h a r mathbf x_{embed} = CharEmbedding(mathbf x_{padded}) in mathbb R^{m_{word} times e_{char}} xembed​=CharEmbedding(xpadded​)∈Rmword​×echar​
    其中, e c h a r e_{char} echar​为字符向量的长度。

在神经网络实现框架里,都有Embedding的函数,用于建立输入变量的向量空间,初始值随机。这样,模型训练时,向量可以跟着一起进行训练。如果直接用gensim之类的word2vec,而且不用Embedding,向量就不会训练。

将字符向量送入到卷积核为 k k k,进行数量 f f f个卷积,就可以得到
x c o n v = c o n v 1 D ( k , f ) ( x e m b e d T ) ∈ R f × ( m w o r d − k + 1 ) mathbf x_{conv} = conv1D(k, f)(mathbf x_{embed}^T) in mathbb R^{f times (m_{word}-k+1)} xconv​=conv1D(k,f)(xembedT​)∈Rf×(mword​−k+1)
令 f = e w o r d f=e_{word} f=eword​,其中 e w o r d e_{word} eword​为词向量的长度。这样,进行maxpool和Relu就可以得到
x c o n v _ o u t = M a x P o o l ( R e L U ( x c o n v ) ) ∈ R f = R e w o r d mathbf x_{conv_out}=MaxPool(ReLU(mathbf x_{conv} )) in mathbb R^{f}=mathbb R^{e_{word}} xconv_out​=MaxPool(ReLU(xconv​))∈Rf=Reword​
然后将 x c o n v _ o u t mathbf x_{conv_out} xconv_out​经过一个highway network,其中
x p r o j = R e L U ( W p r o j x c o n v _ o u t + b p r o j ) ∈ R e w o r d x g a t e = σ ( W g a t e x c o n v _ o u t + b g a t e ) ∈ R e w o r d x h i g h w a y = x g a t e ⊙ x p r o j + ( 1 − x g a t e ) ⊙ x c o n v _ o u t ∈ ∈ R e w o r d begin{aligned} mathbf x_{proj} &= ReLU(mathbf W_{proj} mathbf x_{conv_out} + mathbf b_{proj} ) in mathbb R^{e_{word}}\ mathbf x_{gate} &= sigma(mathbf W_{gate}mathbf x_{conv_out} + mathbf b_{gate} ) in mathbb R^{e_{word}}\ mathbf x_{highway} &= mathbf x_{gate} odot mathbf x_{proj} + (1-mathbf x_{gate}) odot mathbf x_{conv_out} in in mathbb R^{e_{word}} end{aligned} xproj​xgate​xhighway​​=ReLU(Wproj​xconv_out​+bproj​)∈Reword​=σ(Wgate​xconv_out​+bgate​)∈Reword​=xgate​⊙xproj​+(1−xgate​)⊙xconv_out​∈∈Reword​​
其中 W p r o j , W g a t e ∈ R e w o r d × e w o r d mathbf W_{proj}, mathbf W_{gate} in mathbb R^{e_{word} times e_{word}} Wproj​,Wgate​∈Reword​×eword​, b p r o j , b g a t e ∈ R e w o r d mathbf b_{proj}, mathbf b_{gate} in mathbb R^{e_{word}} bproj​,bgate​∈Reword​, ⊙ odot ⊙表示逐元素相乘。经过Dropout就可以得到输出的词向量:
x w o r d _ e m b = D r o p o u t ( x h i g h w a y ) ∈ R e w o r d mathbf x_{word_emb} = Dropout(mathbf x_{highway}) in mathbb R^{e_{word}} xword_emb​=Dropout(xhighway​)∈Reword​。
注意到在上述过程中,总共需要的参数有
V c h a r × e c h a r + ( e c h a r × k + 1 ) × e w o r d + 2 ( e w o r d × e w o r d + e w o r d ) + e w o r d V_{char} times e_{char} + (e_{char} times k + 1) times e_{word} + 2(e_{word} times e_{word} + e_{word}) + e_{word} Vchar​×echar​+(echar​×k+1)×eword​+2(eword​×eword​+eword​)+eword​
其中第一项表示字符词典参数数量,第二项表示卷积的参数数量,第三项表示highway network的参数数量,第四项是Dropout的参数数量。而如果直接采用词向量,所需的参数数量为
V w o r d × e w o r d V_{word} times e_{word} Vword​×eword​
对于英语而言,字符数(包括标点符号) V c h a r V_{char} Vchar​一般不超过100个,而牛津英语词典的单词数 V w o r d V_{word} Vword​就达到170000+,而 e c h a r e_{char} echar​一般也就取20多,而 e w o r d e_{word} eword​经常要取到200多,因此后者的参数数量是远大于前者的。而对于汉字,一般 e w o r d e_{word} eword​和 e c h a r e_{char} echar​基本相当,以最新版的新华词典为例, V c h a r V_{char} Vchar​约为8500, V w o r d V_{word} Vword​约为52000,但即便如此,前者的参数数量仍然是小于后者的。

Encoder剩下的部分就和基于word的LSTM encoder完全一样了,不再详述。

Decoder

Train阶段

在训练阶段时,可以在每个Word LSTM Decoder Cell上都加上Char Decoder(这些Char Decoder均共享同一参数),将该LSTM Cell输出的 o mathbf o o(见前文基于RNN的自动翻译的技术介绍-seq2seq+attention模型)作为该Char Decoder的初始化的状态,即 h 0 = c 0 = o mathbf h_0 = mathbf c_0 = mathbf o h0​=c0​=o,而将LSTM Decoder Cell本应输出的(注意不是实际输出的)单词对应的字符Char Decoder的输入。比如如果单词是music,那么字符 ( x 1 , . . . , x n ) = ( < s > , m , u , s , i , c ) (x_1,...,x_n) = (<s>, m, u, s, i, c) (x1​,...,xn​)=(<s>,m,u,s,i,c)则作为char decoder的输入, ( x 2 , . . . , x n + 1 ) = ( m , u , s , i , c , < e > ) (x_2,...,x_{n+1})=(m,u,s,i,c,<e>) (x2​,...,xn+1​)=(m,u,s,i,c,<e>)作为char decoder的输出。
这样
h t , c t = c h a r D e c o d e r L S T M ( x t , h t − 1 , c t − 1 ) , h t , c t ∈ R h mathbf h_t, mathbf c_t = charDecoderLSTM(mathbf x_t, mathbf h_{t-1}, mathbf c_{t-1}), mathbf h_t, mathbf c_t in mathbb R^h ht​,ct​=charDecoderLSTM(xt​,ht−1​,ct−1​),ht​,ct​∈Rh
其中, x t mathbf x_t xt​是字符 x t x_t xt​对应的向量。注意, x t x_t xt​对应的字符向量是可以不同于Encoder端的字符向量的
对于每个hidden state,可以经过全连接层得到
s t = W d e c h t + b d e c ∈ R V c h a r mathbf s_t = mathbf W_{dec} mathbf h_t + mathbf b_{dec} in mathbb R^{V_{char}} st​=Wdec​ht​+bdec​∈RVchar​
其中, W d e c ∈ R V c h a r × h mathbf W_{dec} in mathbb R^{V_{char} times h} Wdec​∈RVchar​×h以及 b d e c ∈ R V c h a r mathbf b_{dec} in mathbb R^{V_{char}} bdec​∈RVchar​。这样经过softmax后,计算loss为
l o s s = − ∑ t = 1 n C r o s s E n t r o p y ( s o f t m a x ( s t ) , x t + 1 ) loss=-sum_{t=1}^n CrossEntropy(softmax(mathbf s_t), mathbf x_{t+1}) loss=−t=1∑n​CrossEntropy(softmax(st​),xt+1​)
然后再将loss叠加到word decoder的loss上,作为总的loss函数。

Test阶段

在Test阶段,可以只考虑Word Decoder输出为<unk>的LSTM Cell上,加上char decoder。Char decoder初始的 h 0 , c 0 mathbf h_0, mathbf c_0 h0​,c0​取值仍为该word decoder LSTM Cell上对应的 o mathbf o o,并在第一个char decoder LSTM Cell上输入单词的开始标志<s>。其后续的输入,输出的计算和Train阶段相同。
得到 s o f t m a x ( s t ) softmax(mathbf s_t) softmax(st​)后,判断究竟是哪个字符,可以采用Beam Search的方法。(见前文基于RNN的自动翻译的技术介绍-seq2seq+attention模型),直到LSTM Cell上输出结尾标志<e>或者达到最大单词长度 m w o r d m_{word} mword​。

分析

从结果看,由字符向量得到的词向量,相似度高的词往往是拼写和构词上相似的词。而word2vec得到的词向量,相似度高的词往往是语义上接近的词。比如前者的结果为

后者的结果为

但是字符向量的好处处理时态变位能力比词向量强。比如某些单词的时态变位不在词典里,普通的词向量级的NLP就无法识别;而字符向量则往往能识别和解码出来。

另外,针对中文汉字级别的NLP,去年已经有文章Is Word Segmentation Necessary for Deep Learning of Chinese Representations?提出其性能要优于基于分词后的NLP,这个也是可以在进一步研究的地方。

本文发布于:2024-01-29 09:55:31,感谢您对本站的认可!

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

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

标签:字符   NLP
留言与评论(共有 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