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

标签 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) 的索引数组,其中每个单词都被在 tokenizer.word_index.items() 中找到的索引替换

  1. 正在加载 glove 100d词向量

    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),
    

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

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

    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 20000 个单词中的每个单词有 100 个维度。

架构如下:

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))

我明白为什么我们需要 model_glove.add(Dropout(0.5)) ,这是为了关闭一些概率为0.5的隐藏单元,避免模型过于复杂。但我不知道为什么我们需要 Conv1D(64, 5, activation='relu') , MaxPooling1D(pool_size=4)以及这如何进入我的 model_glove.add(LSTM(100))单位..

最佳答案

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

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

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

最大池不是“学习”的;这只是一个简单的算术计算。这就是参数数量为零的原因。 dropout 也是如此。

LSTM 需要形状为 (样本数、时间步数、特征数) 的三维输入。执行之前的卷积和最大池化步骤后,您已将初始嵌入的表示形式减少到 number of timesteps = 11number of features = 64。第一个值 number of samples = None 是您计划使用的 batch size 的占位符。通过使用 100 个单元(也称为 隐藏状态)初始化 LSTM,您正在参数化 LSTM“内存”的大小:本质上是其输入、输出的累积忘记时间之门。

关于python - 了解用于 NLP 文本分类的 LSTM 和 RNN 中的词嵌入、卷积层和最大池化层,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53623432/

相关文章:

python - 将列表的列表变成可以转换为Json的字典

使用 argparse 的组之间的 Python 依赖关系

python - Xlsx Writer 不创建 excel 文件但也不创建错误

python - 使用 gensim 库的 doc2vec 的相似度结果不准确

python - 来自 tfhub 的 BERT 速度慢并且不使用 GPU

python - 如何发送带有标题/文本的 Telegram 媒体组

python - 输入 'ref' 在构建 NodeDef 时传递了 int32 预期的引用类型

tensorflow - colab 中的 TPU 训练,自定义模型,数据来 self 自己的 GCP 帐户 : Cell just seems to hang, 没有进展或错误消息

python - 确定 tf.data.Dataset Tensorflow 中的记录数

nlp - 用 NLTK 检查英语语法