精华内容
下载资源
问答
  • cnn用于自然语言处理

    千次阅读 2018-09-01 20:56:59
    所周知,卷积神经网络(CNN)在计算机视觉领域取得了极大的进展,但是除此之外CNN也逐渐在自然语言处理(NLP)领域攻城略地。本文主要以文本分类为例,介绍卷积神经网络在NLP领域的一个基本使用方法,由于本人是初学...

    转自:https://blog.csdn.net/diye2008/article/details/53105652

     

    所周知,卷积神经网络(CNN)在计算机视觉领域取得了极大的进展,但是除此之外CNN也逐渐在自然语言处理(NLP)领域攻城略地。本文主要以文本分类为例,介绍卷积神经网络在NLP领域的一个基本使用方法,由于本人是初学者,而且为了避免东施效颦,所以下面的理论介绍更多采用非数学化且较为通俗的方式解释。

     

    0.文本分类

    所谓文本分类,就是使用计算机将一篇文本分为a类或者b类,属于分类问题的一种,同时也是NLP中较为常见的任务。

     

    一.词向量

            提到深度学习在NLP中的应用就不得不提到词向量,词向量(Distributed Representation)在国内也经常被翻译为词嵌入等等,关于词向量的介绍的文章已经有很多,比如这位大神的博客:http://blog.csdn.net/zhoubl668/article/details/23271225 本文则用较为通俗的语言帮助大家了解词向量。

           所谓词向量就是通过神经网络来训练语言模型,并在训练过程钟生成一组向量,这组向量将每个词表示为一个n维向量。举个例子,假如我们要将"北京"表示为一个2维向量,可能的一种结果如 北京=(1.1,2.2),在这里北京这个词就被表示为一个2维的向量。但是除了将词表示为向量以外,词向量还要保证语义相近的词在词向量表示方法中的空间距离应当是相近的。比如 '中国' -  '北京'  ≈ '英国' - '伦敦' 。上述条件可在下列词向量分布时满足,'北京'=(1.1,2.2),'中国'=(1.2,2.3) ,'伦敦'=(1.5,2.4),'英国'=(1.6,2.5)。 一般训练词向量可以使用google开源word2vec程序。

     

            二.卷积神经网络与词向量的结合

    有关CNN的博客非常之多,如果不了解CNN的基本概念可以参见这位大神的博客如下:http://blog.csdn.net/zhoubl668/article/details/23271225 这里就不在赘述。

    通常卷积神经网络都是用来处理类似于图像这样的二维(不考虑rgb)矩阵,比如一张图片通常都可以表示为一个2维数组比如255*255,这就表示该图片是一张255像素宽,255像素高的图片。那么如何将CNN应用到文本中呢,答案就是词向量。

    我们刚刚介绍了词向量的概念,下面介绍下如何将文本通过词向量的方式转换成一个类图像类型的格式。一般来说一篇文本可以被视为一个词汇序列的组合,比如有篇文本内容是 '书写代码,改变世界'。可以将其转换为('书写','代码','改变','世界')这样一个文本序列,显然这个序列是一个一维的向量,不能直接使用cnn进行处理。

    但是如果使用词向量的方式将其展开,假设在某词向量钟 '书写' =(1.1,2.1),'代码' = (1.5,2.9),'改变' = (2.7,3.1) ,'世界' = (2.9,3.5),那么('书写','代码','改变','世界')这个序列就可以改写成((1.1,2.1),(1.5,2.9),(2.7,3.1),(2.9,3.5)),显然原先的文本序列是4*1的向量,改写之后的文本可以表示为一个4*2的矩阵。 推而广之任何以文本序列都可以表示为m*d的数组,m维文本序列的词数,d维词向量的维数。

     

            三.用于文本分类的神经网络结构设计

    本文前面介绍了词向量、卷积神经网络等概念,并提出可以将文本转换成一个由词序列和词向量嵌套而成的二维矩阵,并通过CNN对其进行处理,下面以文本分类任务为例,举例说明如何设计该神经网络的样式。

             3.1 文本预处理部分的流程

             这部分主要是分3步,共4种状态。1.将原始文本分词并转换成以词的序列 2.将词序列转换成以词编号(每个词表中的词都有唯一编号)为元素的序列 3.将词的编号序列中的每个元素(某个词)展开为词向量的形式。下面通过一张图(本人手画简图。。。。囧)来表示这个过程,如下图所示:

    上述图片,以'书写代码,改变世界' 这一文本为例,介绍了将其转换成词向量为元素的序列表示,最后得到了一个2维矩阵,该矩阵可用于后续神经网络的训练等操作。

             3.2 神经网络模块的设计

             本文关于神经网络设计的思想来自于以下博文:

     http://www.wildml.com/2015/12/implementing-a-cnn-for-text-classification-in-tensorflow/  由于该文章是纯英文的,某些读者可能还不习惯阅读这类文献,我下面结合一张神经网络设计图,来说明本文中所使用的神经网络,具体设计图(又是手画图,囧)如下:

    简要介绍下上面的图,第一层数据输入层,将文本序列展开成词向量的序列,之后连接 卷积层、激活层、池化层 ,这里的卷积层因为卷积窗口大小不同,平行放置了三个卷积层,垂直方向则放置了三重(卷积层、激活层、池化层的组合)。之后连接全脸阶层和激活层,激活层采用softmax并输出 该文本属于某类的概率。

     

            3.3 编程实现所需要的框架和数据集等

     

            3.3.1 框架:本文采用keras框架来编写神经网络,关于keras的介绍请参见莫言大神翻译的keras中文文档:http://keras-cn.readthedocs.io/en/latest/ 。 

            3.3.2 数据集:文本训练集来自20_newsgroup,该数据集包括20种新闻文本,下载地址如下:http://www.qwone.com/~jason/20Newsgroups/

            3.3.3 词向量:虽然keras框架已经有embedding层,但是本文采用glove词向量作为预训练的词向量,glove的介绍和下载地址如下(打开会比较慢):

    http://nlp.stanford.edu/projects/glove/

     

            3.4 代码和相应的注释

            在3.2部分已经通过一张图介绍了神经网络的设计部分,但是考虑到不够直观,这里还是把所使用的代码,罗列如下,采用keras编程,关键部分都已经罗列注释,代码有部分是来源自keras文档 中的example目录下的:pretrained_word_embeddings.py,但是该程序我实际运行时出现了无法训练的bug,所以做了诸多改变,最主要的是我把原文中的激活层从relu改成了tanh,整体的设计结构也有了根本性的改变。对keras原始demo有兴趣的可以参见:

    http://keras-cn.readthedocs.io/en/latest/blog/word_embedding/

     

             下面就是本文中所使用的文本分类代码:

     

     

     
    1. '''本程序将训练得到一个20类的文本分类器,数据来源是 20 Newsgroup dataset

    2. GloVe词向量的下载地址如下:

    3. http://nlp.stanford.edu/data/glove.6B.zip

    4.  
    5. 20 Newsgroup数据集来自于:

    6. http://www.cs.cmu.edu/afs/cs.cmu.edu/project/theo-20/www/data/news20.html

    7. '''

    8.  
    9. from __future__ import print_function

    10. import os

    11. import numpy as np

    12. np.random.seed(1337)

    13.  
    14. from keras.preprocessing.text import Tokenizer

    15. from keras.preprocessing.sequence import pad_sequences

    16. from keras.utils.np_utils import to_categorical

    17. from keras.layers import Dense, Input, Flatten

    18. from keras.layers import Conv1D, MaxPooling1D, Embedding

    19. from keras.models import Model

    20. from keras.optimizers import *

    21. from keras.models import Sequential

    22. from keras.layers import Merge

    23. import sys

    24.  
    25. BASE_DIR = '.' # 这里是指当前目录

    26. GLOVE_DIR = BASE_DIR + '/glove.6B/' # 根据实际目录名更改

    27. TEXT_DATA_DIR = BASE_DIR + '/20_newsgroup/' # 根据实际目录名更改

    28. MAX_SEQUENCE_LENGTH = 1000 # 每个文本的最长选取长度,较短的文本可以设短些

    29. MAX_NB_WORDS = 20000 # 整体词库字典中,词的多少,可以略微调大或调小

    30.  
    31. EMBEDDING_DIM = 50 # 词向量的维度,可以根据实际情况使用,如果不了解暂时不要改

    32.  
    33. VALIDATION_SPLIT = 0.4 # 这里用作是测试集的比例,单词本身的意思是验证集

    34.  
    35. # first, build index mapping words in the embeddings set

    36. # to their embedding vector 这段话是指建立一个词到词向量之间的索引,比如 peking 对应的词向量可能是(0.1,0,32,...0.35,0.5)等等。

    37.  
    38. print('Indexing word vectors.')

    39.  
    40. embeddings_index = {}

    41.  
    42. f = open(os.path.join(GLOVE_DIR, 'glove.6B.50d.txt')) # 读入50维的词向量文件,可以改成100维或者其他

    43. for line in f:

    44. values = line.split()

    45. word = values[0]

    46. coefs = np.asarray(values[1:], dtype='float32')

    47. embeddings_index[word] = coefs

    48. f.close()

    49.  
    50. print('Found %s word vectors.' % len(embeddings_index))

    51.  
    52. # second, prepare text samples and their labels

    53. print('Processing text dataset') # 下面这段代码,主要作用是读入训练样本,并读入相应的标签,并给每个出现过的单词赋一个编号,比如单词peking对应编号100

    54.  
    55. texts = [] # 存储训练样本的list

    56. labels_index = {} # 词到词编号的字典,比如peking对应100

    57. labels = [] # 存储训练样本,类别编号的文本,比如文章a属于第1类文本

    58. for name in sorted(os.listdir(TEXT_DATA_DIR)):

    59. path = os.path.join(TEXT_DATA_DIR, name)

    60. if os.path.isdir(path):

    61. label_id = len(labels_index)

    62. labels_index[name] = label_id

    63. for fname in sorted(os.listdir(path)):

    64. if fname.isdigit():

    65. fpath = os.path.join(path, fname)

    66. if sys.version_info < (3,):

    67. f = open(fpath)

    68. else:

    69. f = open(fpath, encoding='latin-1')

    70. texts.append(f.read())

    71. f.close()

    72. labels.append(label_id)

    73.  
    74. print('Found %s texts.' % len(texts)) # 输出训练样本的数量

    75.  
    76. # finally, vectorize the text samples into a 2D integer tensor,下面这段代码主要是将文本转换成文本序列,比如 文本'我爱中华' 转化为[‘我爱’,'中华'],然后再将其转化为[101,231],最后将这些编号展开成词向量,这样每个文本就是一个2维矩阵,这块可以参加本文‘二.卷积神经网络与词向量的结合’这一章节的讲述

    77. tokenizer.fit_on_texts(texts)

    78. sequences = tokenizer.texts_to_sequences(texts)

    79.  
    80. word_index = tokenizer.word_index

    81. print('Found %s unique tokens.' % len(word_index))

    82.  
    83. data = pad_sequences(sequences, maxlen=MAX_SEQUENCE_LENGTH)

    84.  
    85. labels = to_categorical(np.asarray(labels))

    86. print('Shape of data tensor:', data.shape)

    87. print('Shape of label tensor:', labels.shape)

    88.  
    89. # split the data into a training set and a validation set,下面这段代码,主要是将数据集分为,训练集和测试集(英文原意是验证集,但是我略有改动代码)

    90. indices = np.arange(data.shape[0])

    91. np.random.shuffle(indices)

    92. data = data[indices]

    93. labels = labels[indices]

    94. nb_validation_samples = int(VALIDATION_SPLIT * data.shape[0])

    95.  
    96. x_train = data[:-nb_validation_samples] # 训练集

    97. y_train = labels[:-nb_validation_samples]# 训练集的标签

    98. x_val = data[-nb_validation_samples:] # 测试集,英文原意是验证集

    99. y_val = labels[-nb_validation_samples:] # 测试集的标签

    100.  
    101. print('Preparing embedding matrix.')

    102.  
    103. # prepare embedding matrix 这部分主要是创建一个词向量矩阵,使每个词都有其对应的词向量相对应

    104. nb_words = min(MAX_NB_WORDS, len(word_index))

    105. embedding_matrix = np.zeros((nb_words + 1, EMBEDDING_DIM))

    106. for word, i in word_index.items():

    107. if i > MAX_NB_WORDS:

    108. continue

    109. embedding_vector = embeddings_index.get(word)

    110. if embedding_vector is not None:

    111. # words not found in embedding index will be all-zeros.

    112. embedding_matrix[i] = embedding_vector # word_index to word_embedding_vector ,<20000(nb_words)

    113.  
    114. # load pre-trained word embeddings into an Embedding layer

    115. # 神经网路的第一层,词向量层,本文使用了预训练glove词向量,可以把trainable那里设为False

    116. embedding_layer = Embedding(nb_words + 1,

    117. EMBEDDING_DIM,

    118. input_length=MAX_SEQUENCE_LENGTH,

    119. weights=[embedding_matrix],

    120. trainable=True)

    121.  
    122. print('Training model.')

    123.  
    124. # train a 1D convnet with global maxpoolinnb_wordsg

    125.  
    126. #left model 第一块神经网络,卷积窗口是5*50(50是词向量维度)

    127. model_left = Sequential()

    128. #model.add(Input(shape=(MAX_SEQUENCE_LENGTH,), dtype='int32'))

    129. model_left.add(embedding_layer)

    130. model_left.add(Conv1D(128, 5, activation='tanh'))

    131. model_left.add(MaxPooling1D(5))

    132. model_left.add(Conv1D(128, 5, activation='tanh'))

    133. model_left.add(MaxPooling1D(5))

    134. model_left.add(Conv1D(128, 5, activation='tanh'))

    135. model_left.add(MaxPooling1D(35))

    136. model_left.add(Flatten())

    137.  
    138. #right model 第二块神经网络,卷积窗口是4*50

    139.  
    140. model_right = Sequential()

    141. model_right.add(embedding_layer)

    142. model_right.add(Conv1D(128, 4, activation='tanh'))

    143. model_right.add(MaxPooling1D(4))

    144. model_right.add(Conv1D(128, 4, activation='tanh'))

    145. model_right.add(MaxPooling1D(4))

    146. model_right.add(Conv1D(128, 4, activation='tanh'))

    147. model_right.add(MaxPooling1D(28))

    148. model_right.add(Flatten())

    149.  
    150. #third model 第三块神经网络,卷积窗口是6*50

    151. model_3 = Sequential()

    152. model_3.add(embedding_layer)

    153. model_3.add(Conv1D(128, 6, activation='tanh'))

    154. model_3.add(MaxPooling1D(3))

    155. model_3.add(Conv1D(128, 6, activation='tanh'))

    156. model_3.add(MaxPooling1D(3))

    157. model_3.add(Conv1D(128, 6, activation='tanh'))

    158. model_3.add(MaxPooling1D(30))

    159. model_3.add(Flatten())

    160.  
    161.  
    162. merged = Merge([model_left, model_right,model_3], mode='concat') # 将三种不同卷积窗口的卷积层组合 连接在一起,当然也可以只是用三个model中的一个,一样可以得到不错的效果,只是本文采用论文中的结构设计

    163. model = Sequential()

    164. model.add(merged) # add merge

    165. model.add(Dense(128, activation='tanh')) # 全连接层

    166. model.add(Dense(len(labels_index), activation='softmax')) # softmax,输出文本属于20种类别中每个类别的概率

    167.  
    168. # 优化器我这里用了adadelta,也可以使用其他方法

    169. model.compile(loss='categorical_crossentropy',

    170. optimizer='Adadelta',

    171. metrics=['accuracy'])

    172.  
    173. # =下面开始训练,nb_epoch是迭代次数,可以高一些,训练效果会更好,但是训练会变慢

    174. model.fit(x_train, y_train,nb_epoch=3)

    175.  
    176. score = model.evaluate(x_train, y_train, verbose=0) # 评估模型在训练集中的效果,准确率约99%

    177. print('train score:', score[0])

    178. print('train accuracy:', score[1])

    179. score = model.evaluate(x_val, y_val, verbose=0) # 评估模型在测试集中的效果,准确率约为97%,迭代次数多了,会进一步提升

    180. print('Test score:', score[0])

    181. print('Test accuracy:', score[1])

    上述代码和注释较为详细的描述了该神经网络的结构,但是实际使用代码时最好去除中文注释部分,否则可能会有一些编码问题。

     

     

            四.总结

    本文描述了如何使用深度学习和keras框架构建一个文本分类器的全过程,并给出了相应的代码实现,为了方便大家使用,下面给出本文代码的下载地址一(简单版):

    https://github.com/894939677/deeplearning_by_diye/blob/master/pretrain_text_class_by_diye.py   

    下面给出本文代码的下载地址二(完整版):

    https://github.com/894939677/deeplearning_by_diye/blob/master/pre_merge_3.py

     

    五.后记

    本文描述的是使用类似于googlenet的网络结构,实际上也可以使用类似与resnet的网络结构来做这个事情

     

     

     

     

     

    展开全文
  • 卷积神经网络(Convolutional Neural Network)最早是应用在计算机视觉当中,而如今CNN也早已应用于自然语言处理(Natural Language Processing)的各种任务。本文主要以CMU CS 11-747(Neur...

    转载出处:https://blog.csdn.net/qq_40027052/article/details/78331816
    640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1

    作者 | 卞书青

    卷积神经网络(Convolutional Neural Network)最早是应用在计算机视觉当中,而如今CNN也早已应用于自然语言处理(Natural Language Processing)的各种任务。本文主要以CMU CS 11-747(Neural Networks for NLP)课程中Convolutional Networks for Text这一章节的内容作为主线进行讲解。

    本文主要包括了对如下几块内容的讲解,第一部分是对于常见的语言模型在进行文本表示时遇到的问题以及引入卷积神经网络的意义,第二部分是对于卷积神经网络模块的介绍,第三部分主要是介绍一些卷积神经网络应用于自然语言处理中的论文,第四部分主要是对这一篇综述进行总结。

    引例

    我们首先来看这么一个问题,假设我们需要对句子做情感上的分类。

    0?wx_fmt=jpeg

    传统的词袋模型或者连续词袋模型都可以通过构建一个全连接的神经网络对句子进行情感标签的分类,但是这样存在一个问题,我们通过激活函数可以让某些结点激活(例如一个句子里”not”,”hate”这样的较强的特征词),但是由于在这样网络构建里,句子中词语的顺序被忽略,也许同样两个句子都出现了not和hate但是一个句子(I do not hate this movie)表示的是good的情感,另一个句子(I hate this movie and will not choose it)表示的是bad的情感。其实很重要的一点是在刚才上述模型中我们无法捕获像not hate这样由连续两个词所构成的关键特征的词的含义。

    0?wx_fmt=jpeg0?wx_fmt=jpeg

    在语言模型里n-gram模型是可以用来解决,想法其实就是将连续的两个词作为一个整体纳入到模型中,这样确实能够解决我们刚才提出的问题,加入bi-gram,tri-gram可以让我们捕捉到例如“don’t love”,“not the best”。但是问题又来了,如果我们使用多元模型,实际训练时的参数是一个非常大的问题,因为假设你有20000个词,加入bi-gram实际上你就要有400000000个词,这样参数训练显然是爆炸的。另外一点,相似的词语在这样的模型中不能共享例如参数权重等,这样就会导致相似词无法获得交互信息。

    0?wx_fmt=jpeg0?wx_fmt=jpeg

    卷积神经网络结构的认识

    利用卷积神经网络实际上是可以解决上述的两个问题。在讲卷积神经网络前,我们先来看两个简单的例子。

    0?wx_fmt=jpeg

    假设我去识别出左边这个方框里的猫,实际上在一张图片中猫所处的位置并不重要,它在左边,在右边,还是在底部,其实对于猫来说,它的特征是不变的,我需要在这一部分位置学习的特征也能用在另一部分位置上,所以对于这个图像上的所有位置,我们都能使用同样的学习特征。而在右边的例子中,假设一句话中是谈论猫咪的,猫咪这个词的意义是否会随它在第一句话还是第二句话而发生改变呢,大部分情况是不变的,所以我们当我们使用一个文本网络时,网络能够学习到什么是猫咪并且可以重复使用,而不是每一次见到它就要重新学习。

    接下来我们先来介绍卷积神经网络中各个重要的环节。

    卷积

    所以这里我们首先去理解卷积神经网络中卷积的运算。这里我们以图像作为输入。比较容易理解卷积的方法是把卷积想象成作用于矩阵的一个滑动窗口函数。如下面这张图的表示。

    0?wx_fmt=jpeg

    滑动窗口又称作卷积核、滤波器或是特征检测器。图中使用3x3的卷积核,将卷积核与矩阵对应的部分逐元素相乘,然后求和。对于卷积的运算可以看下面这幅图的解释。

    0?wx_fmt=jpeg

    在不改变卷积核权重的情况下,就像拿着一只刷子一样对整个图水平垂直滑动进行卷积运算,这样输出就是经过卷积运算后的输出层。这里有一个对卷积操作的动画演示,可以加深对其的理解(CS231n Convolutional Neural Networks for Visual Recognition)

    什么是卷积神经网络

    卷积神经网络其实就是多层卷积运算,然后对每层的卷积输出用非线性激活函数做转换(后面会讲到)。卷积过程中每块局部的输入区域与输出的一个神经元相连接。对每一层应用不同的卷积核,每一种卷积核其实可以理解为对图片的一种特征进行提取,然后将多种特征进行汇总,以下面这幅图为例,原始的input为一幅图片,第一层卷积过后输出层变为6@28*28,所以这里的卷积核实际上用了6个,6个卷积核代表了对这一张原始图片的六种不同角度的特征提取(例如提取图片左上方的边缘线条,右下方的边缘线条等等)。feature map实际上的含义就是特征通道(或者理解为一个图片的不同特征),也可以说就是输出层的深度,这里就是6,然后后面每一次做卷积操作是都是要对所有的特征通道进行卷积操作以便提取出更高级的特征。这里也涉及到池化层,在下一小节进行讲解。在训练阶段,卷积神经网络会基于你想完成的任务自动学习卷积核的权重值。

    0?wx_fmt=jpeg

    例如,在上面这幅图中,第一层CNN模型也许学会从原始像素点中检测到一些边缘线条,然后根据边缘线条在第二层检测出一些简单的形状(例如横线条,左弯曲线条,竖线条等),然后基于这些形状检测出更高级的特征,比如一个A字母的上半部分等。最后一层则是利用这些组合的高级特征进行分类。

    卷积神经网络中的卷积计算实际上体现了:位置不变性和组合性。位置不变性是因为卷积核是在全图范围内平移,所以并不用关心猫究竟在图片的什么位置。组合性是指每个卷积核对一小块局部区域的低级特征组合形成更高级的特征表示。当然这两点对于句子的建模也是很多的帮助,我们会在后面的例子中提到。

    卷积是如何应用到自然语言处理中

    在图像中卷积核通常是对图像的一小块区域进行计算,而在文本中,一句话所构成的词向量作为输入。每一行代表一个词的词向量,所以在处理文本时,卷积核通常覆盖上下几行的词,所以此时卷积核的宽度与输入的宽度相同,通过这样的方式,我们就能够捕捉到多个连续词之间的特征,并且能够在同一类特征计算时中共享权重。下面这张图很好地诠释了刚才的讲解。

    0?wx_fmt=jpeg图片引用自《A Sensitivity Analysis of (and Practitioners’ Guide to) ConvolutionalNeural Networks for Sentence Classification》Ye Zhang, Byron Wallace

    池化层

    卷积神经网络的一个重要概念就是池化层,一般是在卷积层之后。池化层对输入做降采样。池化的过程实际上是对卷积层分区域求最大值或者对每个卷积层求最大值。例如,下图就是2x2窗口的最大值池化(在自然语言处理中,我们通常对整个输出做池化,每个卷积层只有一个输出值)。

    0?wx_fmt=jpeg图片来自于http://cs231n.github.io/convolutional-networks/#pool

    为什么要进行池化操作?

    池化首先是可以输出一个固定大小的矩阵,这对于自然语言处理当中输入句子的长度不一有非常大的作用。例如,如果你用了200个卷积核,并对每个输出使用最大池化,那么无论卷积核的尺寸是多大,也无论输入数据的维度或者单词个数如何变化,你都将得到一个200维的输出。这让你可以应对不同长度的句子和不同大小的卷积核,但总是得到一个相同维度的输出结果,用作最后的分类。

    另外池化层在降低数据维度的同时还能够保留显著的特征。每一种卷积核都是用来检测一种特定的特征。在以句子分类中,每一种卷积核可以用来检测某一种含义的词组,如果这种类型的含义的词语出现了,该卷积核的输出值就会非常大,通过池化过程就能够尽可能地将该信息保留下来。

    关于池化层几种池化方式会在下面的内容里讲解。

    激活函数

    有关激活函数很多细节的讲述在最后的总结会提到。

    0?wx_fmt=jpeg

    卷积神经网络结构在NLP的应用

    首先我们来介绍第一篇论文《Natural Language Processing (almost) from Scratch》,该论文主要是针对原来那种man-made 的输入特征和人工特征,利用神经网络的方法自动抽取出文本句子更高级的特征用来处理自然语言处理里的各项任务,例如本文中输入是一个句子序列,输出是对句子中各个词的词性的预测。该文提出了两种方法,一种是滑动窗口的方法(window approach),另一种就是将整个句子作为输入(sentence approach)的方法,两种方法就分别对应着局部和全局的特征。模型结构如下图所示:

    0?wx_fmt=jpegwindow approach

    0?wx_fmt=jpegsentence approach

    window approach 是根据某一个单词以及其附近固定长度范围内的单词对应的词向量来为单词预测标签。需要注意的是,当处理到一个句子的开始或者结尾的单词的时候,其前后窗口或许不包含单词,这时候我们需要填充技术,为前面或者后面填充象征开始或者结束的符号。

    实际上基于窗口的方法已经可以解决很多常见的任务,但是如果一个单词如果非常依赖上下文的单词,且当时这个单词并不在窗口中,这时就需要sentence approach,这里所使用的卷积操作与卷积神经网络中的卷积操作基本相同。这里需要对句子中的每一个单词进行一次卷积操作,这里池化过程选择最大池化,这里认为句子中大部分的词语对该单词的意义不会有影响。

    刚才这篇论文实际上是在池化层中直接选择了最大池化,接下来的这篇论文《A Convolutional Neural Network for Modelling Sentences》对句子级别特征的池化过程进行了改进并且提出了DCNN动态卷积网络(Dynamic Convolutional Neural Network),在介绍该论文前首先先来介绍一下常见的几种池化方式。

    0?wx_fmt=jpeg

    Max-pooling最为常见,最大池化是取整个区域的最大值作为特征,在自然语言处理中常用于分类问题,希望观察到的特征是强特征,以便可以区分出是哪一个类别。Average-pooling通常是用于主题模型,常常是一个句子不止一个主题标签,如果是使用Max-pooling的话信息过少,所以使用Average的话可以广泛反映这个区域的特征。最后两个K-max pooling是选取一个区域的前k个大的特征。Dynamic pooling是根据网络结构动态调整取特征的个数。最后两个的组合选取,就是该篇论文的亮点。

    该论文的亮点首先对句子语义建模,在底层通过组合邻近的词语信息,逐步向上传递,上层则又组合新的语义信息,从而使得句子中相离较远的词语也有交互行为(或者某种语义联系)。从直观上来看,这个模型能够通过词语的组合,再通过池化层提取出句子中重要的语义信息。

    0?wx_fmt=jpeg

    另一个亮点就是在池化过程中,该模型采用动态k-Max池化,这里池化的结果不是返回一个最大值,而是返回k组最大值,这些最大值是原输入的一个子序列。池化中的参数k可以是一个动态函数,具体的值依赖于输入或者网络的其他参数。该模型的网络结构如下图所示:

    0?wx_fmt=jpeg

    这里重点介绍k-max池化和动态k-max池化。K-max的好处在于,既提取除了句子中不止一个重要信息,同时保留了它们的顺序。同时,这里取k的个数是动态变化的,具体的动态函数如下。

    0?wx_fmt=png

    这里需要注意的是s代表的是句子长度,L代表总的卷积层的个数,l代表的是当前是在几个卷积层,所以可以看出这里的k是随着句子的长度和网络深度而改变,我们的直观的感受也能看出初始的句子层提取较多的特征,而到后面提取的特征将会逐渐变少,同时由于 0?wx_fmt=png 代表最顶层的卷积层需要提取的个数。

    这里的网络结构大多与通常的卷积网络层,但需要注意的是这里有一个Folding层(折叠操作层)。这里考虑相邻的两行之间的某种联系,将两行的词向量相加。

    该模型亮点很多,总结如下,首先它保留了句子中词序和词语之间的相对位置,同时考虑了句子中相隔较远的词语之间的语义信息,通过动态k-max pooling较好地保留句子中多个重要信息且根据句子长度动态变化特征抽取的个数。

    刚才这篇论文是对池化过程进行改进,接下来的两篇论文是对卷积层进行了改进。第三篇论文是《Neural Machine Translation in Linear Time》,该论文提出了扩张卷积神经网络(Dilated Convolution)应用于机器翻译领域。Dilated convolution实际上要解决的问题是池化层的池化会损失很多信息(无论该信息是有用还是无用)。Dilated convolution的主要贡献就是,如何在去掉池化操作的同时,而不降低网络的感受野。下图理解起来更加容易,卷积的输入像素的间距由1-2-4-8,虽然没有池化层,但是随着层数越深覆盖的原始输入信息依旧在增加。也就是我们通常卷积核与输入的一个区域的维度大小保持一致,但是去掉池化层后,我们随着深度增加,卷积核的所能覆盖的输入区域扩展一倍。

    0?wx_fmt=jpeg

    在该模型中,句子建模时输入是以句子的字符级别开始的,之后随着卷积核所能覆盖的范围扩展,不断地去交互信息,同时还能够保证原始的输入信息不被丢失。

    0?wx_fmt=jpeg

    之前的论文中主要是对卷积层和池化层从本身结构上进行改造,下面的这篇论文主要考虑到了本身句子已有依存句法树信息,将其融入到句子的建模中来。论文《Dependency-based Convolutional Neural Networks for Sentence Embedding》便是提出这一想法,模型的想法是,不仅仅是利用句子中相邻的词信息作为特征信息,一个依存句法树的实际上将句子的语义信息关系真正地提取出来,由于整个卷积的过程,句子的语序关系仍然会丢失,通过将依存句法树中父子节点的语序信息和兄弟语序信息一起作为输入,可以更加有效地抽取句子的特征。

    0?wx_fmt=jpeg0?wx_fmt=jpeg

    最后要介绍的一篇论文是有关于句子匹配(Sentence Matching)的问题,基础问题仍然是句子建模。首先,文中提出了一种基于CNN的句子建模网络,卷积的作用是从句子中提取出局部的语义组合信息,而多个Feature Map则是从多种角度进行提取,也就是保证提取的语义组合的多样性。分别单独地对两个句子进行建模(使用上文中的句子模型),从而得到两个相同且固定长度的向量,然后,将这两个向量作为一个多层感知机(MLP)的输入,最后计算匹配的分数。

    0?wx_fmt=jpeg

    这个模型比较简单,但是有一个较大的缺点,两个句子在建模过程中是完全独立的,没有任何交互行为,一直到最后生成抽象的向量表示后才有交互行为,这样做使得句子在抽象建模的过程中会丧失很多语义细节,因此,推出了第二种模型结构。

    0?wx_fmt=jpeg

    这种结构提前了两个句子间的交互行为,第一层中,首先取一个固定的卷积窗口

    0?wx_fmt=png,然后遍历0?wx_fmt=png中所有组合的二维矩阵进行卷积,每一个二维矩阵输出一个值,构成Layer-2,然后进行2×2的Max-pooling,后续的卷积层均是传统的二维卷积操作。

    总结/Q&A

    本篇综述中具体介绍了卷积神经网络的结构以及应用于自然语言处理中的场景,最后再做一个简单地归纳总结。

    0?wx_fmt=jpeg

    还有一些有关卷积神经网络细节上的问题与答案,与大家分享。

    • 卷积层和池化层有什么区别?

      首先可以从结构上可以看出,卷积之后输出层的维度减小,深度变深。但池化层深度不变。同时池化可以把很多数据用最大值或者平均值代替。目的是降低数据量。降低训练的参数。对于输入层,当其中像素在邻域发生微小位移时,池化层的输出是不变的,从而能提升鲁棒性。而卷积则是把数据通过一个卷积核变化成特征,便于后面的分离。

    • 采用宽卷积的好处有什么?

      通过将输入边角的值纳入到滑窗中心进行计算,以便损失更少的信息。

    • 卷积输出的深度与哪个部件的个数相同?

      输出深度(通道)与卷积核(过滤器)的个数相等。

    • 激活函数通常放在卷积神经网络的那个操作之后?

      通常放在卷积层之后。

    • 为什么激活函数通常都是采用非线性的函数?

      如果网络中都采用线性函数的组合,那么线性的组合还是线性,那么使用多次线性组合就等同于使用了一次线性函数。因此采用非线性函数可以来逼近任意函数。

    • 非线性激活函数中sigmod函数存在哪些不足?

      Sigmod函数存在饱和状态,尤其是值过大时,当进入饱和状态时,进行梯度下降计算时,很容易出现梯度消失的情况,求导的精确值不能保证。

    • ReLU和SoftPlus激活函数有哪些优势?

      与sigmod相比,不存在指数计算,求导计算量变小,同时缓解了过拟合的情况,一部分输出为0,减少了参数的相互依存。

    参考文献:

    《Neural Machine Translation in Linear Time》阅读笔记

    https://zhuanlan.zhihu.com/c_51425207

    卷积神经网络(CNN)在句子建模上的应用

    http://www.jeyzhang.com/cnn-apply-on-modelling-sentence.html

    卷积神经网络在自然语言处理的应用

    https://zhuanlan.zhihu.com/p/30268946

    相关参考资料链接:

    1. 一个很好的卷积操作的动画演示

    http://cs231n.github.io/convolutional-networks/

    1. 宽/窄卷积的动画演示

    http://deeplearning.net/software/theano_versions/dev/tutorial/conv_arithmetic.html

    1. Udacity deep learning 课程

    https://cn.udacity.com/course/deep-learning--ud730

    1. Github上一个有关深度学习入门的教程/代码

    https://github.com/CreatCodeBuild/TensorFlow-and-DeepLearning-Tutorial

    **作者简介:**卞书青,2017级研究生,目前研究方向为信息抽取、深度学习,来自中国人民大学大数据管理与分析方法研究北京市重点实验室。

    **来源:**https://zhuanlan.zhihu.com/p/30268946


    10 月 28 日(本周六),**SDCC 2017“人工智能技术实战线上峰会”**************将在CSDN学院以直播互动的方式举行。

    作为SDCC系列技术峰会的一部分,来自阿里巴巴、微软、商汤科技、第四范式、微博、出门问问、菱歌科技的AI专家,将针对机器学习平台、系统架构、对话机器人、芯片、推荐系统、Keras、分布式系统、NLP等热点话题进行分享。

    先行者们正在关注哪些关键技术?如何从理论跨越到企业创新实践?你将从本次峰会找到答案。每个演讲时段均设有答疑交流环节,与会者和讲师可零距离互动。

    扫描下方二维码,入群交流 0?wx_fmt=png

    640?wx_fmt=png

    展开全文
  • 自然语言处理CNN模型几种常见的Max Pooling操作

    万次阅读 多人点赞 2016-04-07 19:00:02
    /* 版权声明:可以任意转载,转载时请标明文章原始出处和作者信息 .*/    author: 张俊林    (想更系统地学习深度学习知识?请参考:深度学习枕边书...CNN是目前自然语言处理中和RNN并驾齐驱的两种最...

     

    /* 版权声明:可以任意转载,转载时请标明文章原始出处和作者信息 .*/

     

                                                         author: 张俊林

     

                                     (想更系统地学习深度学习知识?请参考:深度学习枕边书

    CNN是目前自然语言处理中和RNN并驾齐驱的两种最常见的深度学习模型。图1展示了在NLP任务中使用CNN模型的典型网络结构。一般而言,输入的字或者词用Word Embedding的方式表达,这样本来一维的文本信息输入就转换成了二维的输入结构,假设输入X包含m个字符,而每个字符的Word Embedding的长度为d,那么输入就是m*d的二维向量。

                                                               1 自然语言处理中CNN模型典型网络结构

     

     

    这里可以看出,因为NLP中的句子长度是不同的,所以CNN的输入矩阵大小是不确定的,这取决于m的大小是多少。卷积层本质上是个特征抽取层,可以设定超参数F来指定设立多少个特征抽取器(Filter),对于某个Filter来说,可以想象有一个k*d大小的移动窗口从输入矩阵的第一个字开始不断往后移动,其中k是Filter指定的窗口大小,d是Word Embedding长度。对于某个时刻的窗口,通过神经网络的非线性变换,将这个窗口内的输入值转换为某个特征值,随着窗口不断往后移动,这个Filter对应的特征值不断产生,形成这个Filter的特征向量。这就是卷积层抽取特征的过程。每个Filter都如此操作,形成了不同的特征抽取器。Pooling 层则对Filter的特征进行降维操作,形成最终的特征。一般在Pooling层之后连接全联接层神经网络,形成最后的分类过程。

     

    可见,卷积和Pooling是CNN中最重要的两个步骤。下面我们重点介绍NLP中CNN模型常见的Pooling操作方法。

     

    |CNN中的Max Pooling Over Time操作

     

    MaxPooling Over Time是NLP中CNN模型中最常见的一种下采样操作。意思是对于某个Filter抽取到若干特征值,只取其中得分最大的那个值作为Pooling层保留值,其它特征值全部抛弃,值最大代表只保留这些特征中最强的,而抛弃其它弱的此类特征。

     

    CNN中采用Max Pooling操作有几个好处:首先,这个操作可以保证特征的位置与旋转不变性,因为不论这个强特征在哪个位置出现,都会不考虑其出现位置而能把它提出来。对于图像处理来说这种位置与旋转不变性是很好的特性,但是对于NLP来说,这个特性其实并不一定是好事,因为在很多NLP的应用场合,特征的出现位置信息是很重要的,比如主语出现位置一般在句子头,宾语一般出现在句子尾等等,这些位置信息其实有时候对于分类任务来说还是很重要的,但是Max Pooling 基本把这些信息抛掉了。

     

    其次,MaxPooling能减少模型参数数量,有利于减少模型过拟合问题。因为经过Pooling操作后,往往把2D或者1D的数组转换为单一数值,这样对于后续的Convolution层或者全联接隐层来说无疑单个Filter的参数或者隐层神经元个数就减少了。

     

     再者,对于NLP任务来说,Max Pooling有个额外的好处;在此处,可以把变长的输入X整理成固定长度的输入。因为CNN最后往往会接全联接层,而其神经元个数是需要事先定好的,如果输入是不定长的那么很难设计网络结构。前文说过,CNN模型的输入X长度是不确定的,而通过Pooling 操作,每个Filter固定取1个值,那么有多少个Filter,Pooling层就有多少个神经元,这样就可以把全联接层神经元个数固定住(如图2所示),这个优点也是非常重要的。

                                                   2. Pooling层神经元个数等于Filters个数

     

     

    但是,CNN模型采取MaxPooling Over Time也有一些值得注意的缺点:首先就如上所述,特征的位置信息在这一步骤完全丢失。在卷积层其实是保留了特征的位置信息的,但是通过取唯一的最大值,现在在Pooling层只知道这个最大值是多少,但是其出现位置信息并没有保留;另外一个明显的缺点是:有时候有些强特征会出现多次,比如我们常见的TF.IDF公式,TF就是指某个特征出现的次数,出现次数越多说明这个特征越强,但是因为Max Pooling只保留一个最大值,所以即使某个特征出现多次,现在也只能看到一次,就是说同一特征的强度信息丢失了。这是Max Pooling Over Time典型的两个缺点。

     

    其实,我们常说“危机危机”,对这个词汇乐观的解读是“危险就是机遇”。同理,发现模型的缺点是个好事情,因为创新往往就是通过改进模型的缺点而引发出来的。那么怎么改进Pooling层的机制能够缓解上述问题呢?下面两个常见的改进Pooling机制就是干这个事情的。

     

     

    |K-Max Pooling

     

    K-MaxPooling的意思是:原先的Max Pooling Over Time从Convolution层一系列特征值中只取最强的那个值,那么我们思路可以扩展一下,K-Max Pooling可以取所有特征值中得分在Top –K的值,并保留这些特征值原始的先后顺序(图3是2-max Pooling的示意图),就是说通过多保留一些特征信息供后续阶段使用。

                                      3 .2-max pooling

     

     

    很明显,K-Max Pooling可以表达同一类特征出现多次的情形,即可以表达某类特征的强度;另外,因为这些Top K特征值的相对顺序得以保留,所以应该说其保留了部分位置信息,但是这种位置信息只是特征间的相对顺序,而非绝对位置信息。

     

    |Chunk-Max Pooling

     

    Chunk-MaxPooling的思想是:把某个Filter对应的Convolution层的所有特征向量进行分段,切割成若干段后,在每个分段里面各自取得一个最大特征值,比如将某个Filter的特征向量切成3个Chunk,那么就在每个Chunk里面取一个最大值,于是获得3个特征值。(如图4所示,不同颜色代表不同分段)

                                  4. Chunk-Max Pooling示意图

     

     

    乍一看Chunk-Max Pooling思路类似于K-Max Pooling,因为它也是从Convolution层取出了K个特征值,但是两者的主要区别是:K-Max Pooling是一种全局取Top K特征的操作方式,而Chunk-Max Pooling则是先分段,在分段内包含特征数据里面取最大值,所以其实是一种局部Top K的特征抽取方式。

     

    至于这个Chunk怎么划分,可以有不同的做法,比如可以事先设定好段落个数,这是一种静态划分Chunk的思路;也可以根据输入的不同动态地划分Chunk间的边界位置,可以称之为动态Chunk-Max方法(这种称谓是我随手命名的,非正式称谓,请注意)。

     

    Chunk-Max Pooling很明显也是保留了多个局部Max特征值的相对顺序信息,尽管并没有保留绝对位置信息,但是因为是先划分Chunk再分别取Max值的,所以保留了比较粗粒度的模糊的位置信息;当然,如果多次出现强特征,则也可以捕获特征强度。

     

    Event Extraction via Dynamic Multi-Pooling Convolutional Neural Networks这篇论文提出的是一种ChunkPooling的变体,就是上面说的动态Chunk-Max Pooling的思路,实验证明性能有提升。Local Translation Prediction with Global Sentence Representation 这篇论文也用实验证明了静态Chunk-Max性能相对MaxPooling Over Time方法在机器翻译应用中对应用效果有提升。

     

    如果思考一下,就会发现,如果分类所需要的关键特征的位置信息很重要,那么类似Chunk-Max Pooling这种能够粗粒度保留位置信息的机制应该能够对分类性能有一定程度的提升作用;但是对于很多分类问题,估计Max-Pooling over time就足够了。

     

    比如我们拿情感分类来说,估计用Chunk-max策略应该有帮助,因为对于这种表达模式:

     

    “Blablabla….表扬了你半天,BUT…..你本质上就是个渣”

     

    与这种表达模式

     

    “虽然说你是个渣,但是…..Blablabla…..欧巴我还是觉得你最好,因为你最帅”

     

    明显位置信息对于判别整体情感倾向是有帮助作用的,所以引入位置信息应该有帮助。

     

    所以,你分析下你手头的问题,看看位置是不是重要特征,如果是,那么套用一下Chunk-Max策略,估计性能会有提升,比如上面举的情感分类问题估计效果会有提升。

     

     

    扫一扫关注微信号:“布洛卡区” ,深度学习在自然语言处理等智能应用的技术研讨与科普公众号

    展开全文
  • CNN也能理解语言_#4.3_(莫烦PythonNLP_自然语言处理教学)
  • CNN视角看在自然语言处理上的应用.pdf
  • 参考博文: CNN自然语言处理上的详细解析与应用
    展开全文
  • 深度学习与自然语言处理之四:卷积神经网络模型(CNN
  • 说到CNN,大家自然想到图像处理。 说到NLP,大家自然想到LSTM,RNN。 但是,去年的斯坦福论文表明,CNN照样可以应用于NLP,并且效果可能更好。博主做了实验,爬取了各类新闻并对新闻进行分类。这样的分类问题,RNN...
  • 简略介绍卷积神经网络(CNN, Convolutional Neural Network)处理文本信息的过程 使用CNN进行文本分类任务,并对代码进行注释 本文代码【https://github.com/540117253/Chinese-Text-Classification 】 一、CNN概述...
  • 文章是...本次文章将介绍CNN的基本原理,并使用Keras搭建一个CNN模型处理Kaggle的一个工资预测,第一次自己搭碰到很多坑,我会在第七步搭建过程中介绍一下这些坑。 一 文本分类...
  • 自然语言处理(二) 1.Task1 数据集探索 1.1下载数据集 1.2数据集的描述 1.3 数据的预处理 1.4 CNN卷积神经网络 1.5 训练与验证 2.IMDB 2.1下载 IMDB 数据集 2.2 探索数据 2.3将整数转换回字词 2.4准备数据 2.5构建...
  • 卷积神经网络(Convolutional Neural Network)最早是应用在计算机视觉当中,而如今CNN也早已应用于自然语言处理(Natural Language Processing)的各种任务。本文主要以CMU CS 11-747(Neural Networks for NLP)...
  • 本文参考自Convolutional Neural Networks for Sentence Classification,结尾处放上传送门。 用传统方法进行文本分类任务时,通常将一篇...而CNN对文本数据建模时,输入变长的字符串,然后通过滑动窗口加池化的方...
  • 自然语言处理

    2021-06-29 14:06:39
    自然语言处理
  • 自然语言处理(NLP)学习路线总结

    万次阅读 多人点赞 2019-03-20 21:01:53
    自然语言处理概述 自然语言处理入门基础 自然语言处理的主要技术范畴 自然语言处理基本点 特征处理 模型选择 NLP常用工具 NLP语言模型 快速入门NLP方法 自然语言处理...
  • 使用Keras进行深度学习:(三)使用text-CNN处理自然语言(上) 使用Keras进行深度学习:(四)使用text-CNN处理自然语言(下) 使用Keras进行深度学习:(五)RNN和双向RNN讲解及实践 使用Keras进...
  • 使用Keras进行深度学习:(三)使用text-CNN处理自然语言(上) 使用Keras进行深度学习:(四)使用text-CNN处理自然语言(下) 使用Keras进行深度学习:(五)RNN和双向RNN讲解及实践 使用Keras进...
  • 为什么需要在自然语言处理中引入卷积神经网络? 什么是卷积? 单层的卷积 多通道(Multi-channel) 在完成卷积之后,如何进行分类任务? 2、训练技巧 3、CNN的一些变体应用 4、模型比较 一、卷积神经网络...
  • 由于可以有效地进行特征提取,卷积神经网络(CNN)已经被广泛地应用于计算机视觉、自然语言处理等领域。之前仅在图像的分类和识别中用过CNN,且对CNN的理解较为浅显。现在重新学习卷积神经网络,并重点学习其在NLP...
  • 来自  ...Instead of image pixels, the input to most NLP...把每个单词用word embeddings 处理成向量,然后一个句子拼成一张图。下图中第二列的彩色图像为卷积核。下面模型用来解决一个分类问题。
  • 放弃幻想,全面拥抱Transformer:自然语言处理三大特征抽取器(CNN/RNN/TF)比较 一个是Bert这种两阶段的模式(预训练+Finetuning)必将成为NLP领域研究和工业应用的流行方法; 第二个是从NLP领域的特征抽取器角度...
  • 一、什么是自然语言处理(NLP)   首先先了解一下什么是自然语言,自然语言是人类社会发展过程中自然产生的语言,是最能体现人类智慧和文明的产物,也是大猩猩与人的区别(2019斯坦福cs224n,lesson1)。它是一种...
  • 使用TensorFlow进行自然语言处理 这是发布的进行的代码库。 它包含从头到尾完成本书所必需的所有支持项目文件。 关于这本书 自然语言处理(NLP)提供了可用于深度学习应用程序的大多数数据,而TensorFlow是当前可用...
  • 自然语言处理综述

    千次阅读 2018-12-25 11:08:16
    本文从两篇论文出发先简要介绍了自然语言处理的基本分类和基本概念,再向读者展示了深度学习中的 NLP。这两篇论文都是很好的综述性入门论文,希望详细了解自然语言处理的读者可以进一步阅读这两篇论文。 第一部分...
  • python用于自然语言处理的图书

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 20,968
精华内容 8,387
关键字:

cnn自然语言处理