了解LSTM和RNN中用于NLP文本分类的词嵌入,卷积层和最大池化层

时间:2018-12-05 00:28:43

标签: python tensorflow nlp lstm word-embedding

这是我的输入数据:

data['text'].head()

0    process however afforded means ascertaining di...
1          never occurred fumbling might mere mistake 
2    left hand gold snuff box which capered hill cu...
3    lovely spring looked windsor terrace sixteen f...
4    finding nothing else even gold superintendent ...
Name: text, dtype: object

这是一个热编码标签(多类别分类,其中类别数= 3)

[[1 0 0]
 [0 1 0]
 [1 0 0]
 ...
 [1 0 0]
 [1 0 0]
 [0 1 0]]

这是我认为逐步发生的事情,如果我错了,请纠正我:

  1. 将我的输入文本data['text']转换为一包索引(序列)

    vocabulary_size = 20000
    
    tokenizer = Tokenizer(num_words = vocabulary_size)
    tokenizer.fit_on_texts(data['text'])
    sequences = tokenizer.texts_to_sequences(data['text'])
    
    data = pad_sequences(sequences, maxlen=50)
    

发生了什么事,我的data['text'].shape的形状为(19579, )被转换为形状为(19579, 50)的索引数组,其中每个单词都被{中找到的索引替换{1}}

  1. 加载tokenizer.word_index.items()单词向量

    glove 100d

因此,我们现在有了100个维度的每个单词的单词向量。

  1. 使用手套词向量创建嵌入矩阵

    embeddings_index = dict()
    f = open('/Users/abhishekbabuji/Downloads/glove.6B/glove.6B.100d.txt')
    for line in f:
        values = line.split()
        word = values[0]
        coefs = np.asarray(values[1:], dtype='float32')
        embeddings_index[word] = coefs
    f.close()
    
    print(embedding_index)
        {'the': array([-0.038194, -0.24487 ,  0.72812 , -0.39961 ,  0.083172,  0.043953,
        -0.39141 ,  0.3344  , -0.57545 ,  0.087459,  0.28787 , -0.06731 ,
         0.30906 , -0.26384 , -0.13231 , -0.20757 ,  0.33395 , -0.33848 ,
        -0.31743 , -0.48336 ,  0.1464  , -0.37304 ,  0.34577 ,  0.052041,
         0.44946 , -0.46971 ,  0.02628 , -0.54155 , -0.15518 , -0.14107 ,
        -0.039722,  0.28277 ,  0.14393 ,  0.23464 , -0.31021 ,  0.086173,
         0.20397 ,  0.52624 ,  0.17164 , -0.082378, -0.71787 , -0.41531 ,
         0.20335 , -0.12763 ,  0.41367 ,  0.55187 ,  0.57908 , -0.33477 ,
        -0.36559 , -0.54857 , -0.062892,  0.26584 ,  0.30205 ,  0.99775 ,
        -0.80481 , -3.0243  ,  0.01254 , -0.36942 ,  2.2167  ,  0.72201 ,
        -0.24978 ,  0.92136 ,  0.034514,  0.46745 ,  1.1079  , -0.19358 ,
        -0.074575,  0.23353 , -0.052062, -0.22044 ,  0.057162, -0.15806 ,
        -0.30798 , -0.41625 ,  0.37972 ,  0.15006 , -0.53212 , -0.2055  ,
        -1.2526  ,  0.071624,  0.70565 ,  0.49744 , -0.42063 ,  0.26148 ,
        -1.538   , -0.30223 , -0.073438, -0.28312 ,  0.37104 , -0.25217 ,
         0.016215, -0.017099, -0.38984 ,  0.87424 , -0.72569 , -0.51058 ,
        -0.52028 , -0.1459  ,  0.8278  ,  0.27062 ], dtype=float32),
    

因此,对于每个20000个单词,我们现在有一个100个维度的vocabulary_size = 20000 embedding_matrix = np.zeros((vocabulary_size, 100)) for word, index in tokenizer.word_index.items(): if index > vocabulary_size - 1: break else: embedding_vector = embeddings_index.get(word) if embedding_vector is not None: embedding_matrix[index] = embedding_vector

这是架构:

vector

我知道

model_glove = Sequential()
model_glove.add(Embedding(vocabulary_size, 100, input_length=50, weights=[embedding_matrix], trainable=False))
model_glove.add(Dropout(0.5))
model_glove.add(Conv1D(64, 5, activation='relu')) 
model_glove.add(MaxPooling1D(pool_size=4))
model_glove.add(LSTM(100))
model_glove.add(Dense(3, activation='softmax'))
model_glove.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
print(model_glove.summary())

上述架构的输入将是训练数据

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_7 (Embedding)      (None, 50, 100)           2000000   
_________________________________________________________________
dropout_7 (Dropout)          (None, 50, 100)           0         
_________________________________________________________________
conv1d_7 (Conv1D)            (None, 46, 64)            32064     
_________________________________________________________________
max_pooling1d_7 (MaxPooling1 (None, 11, 64)            0         
_________________________________________________________________
lstm_7 (LSTM)                (None, 100)               66000     
_________________________________________________________________
dense_7 (Dense)              (None, 3)                 303       
=================================================================
Total params: 2,098,367
Trainable params: 98,367
Non-trainable params: 2,000,000
_________________________________________________________________

形状为array([[ 0, 0, 0, ..., 4867, 22, 340], [ 0, 0, 0, ..., 12, 327, 2301], [ 0, 0, 0, ..., 255, 388, 2640], ..., [ 0, 0, 0, ..., 17, 15609, 15242], [ 0, 0, 0, ..., 9517, 9266, 442], [ 0, 0, 0, ..., 3399, 379, 5927]], dtype=int32)

并将标签作为一种热门编码。

我的麻烦是要了解我的(19579, 50)在经历以下每一行时到底发生了什么:

(19579, 50)

我理解为什么我们需要model_glove = Sequential() model_glove.add(Embedding(vocabulary_size, 100, input_length=50, weights=[embedding_matrix], trainable=False)) model_glove.add(Dropout(0.5)) model_glove.add(Conv1D(64, 5, activation='relu')) model_glove.add(MaxPooling1D(pool_size=4)) ,这是为了以0.5的概率关闭一些隐藏的单元,以避免模型过于复杂。但是我不知道为什么我们需要model_glove.add(Dropout(0.5))Conv1D(64, 5, activation='relu'),以及它们如何进入我的MaxPooling1D(pool_size=4)单位。

1 个答案:

答案 0 :(得分:2)

理解convolution的最简单方法是将其视为一个映射,该映射告诉神经网络具有哪些特征(在图像识别的情况下,像素将使用2D卷积;或者在单词之前或在给定文字单词之后,您将在其中使用一维卷积的位置)。没有这个,网络就无法知道给定单词之前或之后的单词比远处的单词更相关。通常,它还导致信息以更加密集的格式呈现,从而大大减少了参数的数量(在您的情况下从200万减少到3万)。我发现此答案说明了其工作原理的技术性:https://stackoverflow.com/a/52353721/141789

Max pooling是一种对数据进行下采样的方法。它通常在卷积后直接使用,并实现两件事:

  1. 它再次减少了参数数量。在您的情况下,它将用一个值(四个值中的最大值)代表四个值。它通过采用前四个值,然后采用大小为“ 4”的“步幅”并采用后四个值等来实现此目的。换句话说,池之间不会有重叠。 (这是keras的默认设置,但是您也可以将跨度设置为2
  2. 第二,因为它采用max的值,所以从理论上讲,通过采用最大值而不是例如采用平均值来“磨合”池之间的对比度。

最大池化不是“学习”;这只是一个简单的算术计算。这就是为什么将参数数量指定为零的原因。 dropout也是一样。

一个LSTM需要一个形状为(number of samples, number of timesteps, number of features)的三维输入。执行了先前的卷积和最大池化步骤后,您已将初始嵌入的表示形式减少为number of timesteps = 11number of features = 64。第一个值number of samples = None是您计划使用的batch size的占位符。通过用100 units(也称为hidden states)初始化LSTM,就可以参数化LSTM“内存”的大小:本质上是其输入,输出和时间的门的累积。 >