理解Keras层形状

我在阅读这个链接,试图理解用于文本分类的多通道CNN模型。

代码基于这个教程

我已经理解了大部分内容,但是我无法理解Keras如何定义某些层的输出形状。

这是代码:

定义一个模型,该模型具有三个输入通道,用于处理电影评论文本的4-gram、6-gram和8-gram。

#Skipped keras imports# 加载一个干净的数据集def load_dataset(filename):    return load(open(filename, 'rb'))# 拟合一个分词器def create_tokenizer(lines):    tokenizer = Tokenizer()    tokenizer.fit_on_texts(lines)    return tokenizer# 计算最大文档长度def max_length(lines):    return max([len(s.split()) for s in lines])# 编码一组行def encode_text(tokenizer, lines, length):    # 整数编码    encoded = tokenizer.texts_to_sequences(lines)    # 填充编码序列    padded = pad_sequences(encoded, maxlen=length, padding='post')    return padded# 定义模型def define_model(length, vocab_size):    # 通道1    inputs1 = Input(shape=(length,))    embedding1 = Embedding(vocab_size, 100)(inputs1)    conv1 = Conv1D(filters=32, kernel_size=4, activation='relu')(embedding1)    drop1 = Dropout(0.5)(conv1)    pool1 = MaxPooling1D(pool_size=2)(drop1)    flat1 = Flatten()(pool1)    # 通道2    inputs2 = Input(shape=(length,))    embedding2 = Embedding(vocab_size, 100)(inputs2)    conv2 = Conv1D(filters=32, kernel_size=6, activation='relu')(embedding2)    drop2 = Dropout(0.5)(conv2)    pool2 = MaxPooling1D(pool_size=2)(drop2)    flat2 = Flatten()(pool2)    # 通道3    inputs3 = Input(shape=(length,))    embedding3 = Embedding(vocab_size, 100)(inputs3)    conv3 = Conv1D(filters=32, kernel_size=8, activation='relu')(embedding3)    drop3 = Dropout(0.5)(conv3)    pool3 = MaxPooling1D(pool_size=2)(drop3)    flat3 = Flatten()(pool3)    # 合并    merged = concatenate([flat1, flat2, flat3])    # 解释    dense1 = Dense(10, activation='relu')(merged)    outputs = Dense(1, activation='sigmoid')(dense1)    model = Model(inputs=[inputs1, inputs2, inputs3], outputs=outputs)    # 编译    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])    # 总结    print(model.summary())    plot_model(model, show_shapes=True, to_file='multichannel.png')    return model# 加载训练数据集trainLines, trainLabels = load_dataset('train.pkl')# 创建分词器tokenizer = create_tokenizer(trainLines)# 计算最大文档长度length = max_length(trainLines)# 计算词汇量大小vocab_size = len(tokenizer.word_index) + 1print('最大文档长度: %d' % length)print('词汇量大小: %d' % vocab_size)# 编码数据trainX = encode_text(tokenizer, trainLines, length)print(trainX.shape)# 定义模型model = define_model(length, vocab_size)# 拟合模型model.fit([trainX,trainX,trainX], array(trainLabels), epochs=10, batch_size=16)# 保存模型model.save('model.h5')

运行代码:

运行示例首先打印了准备好的训练数据集的摘要。最大文档长度: 1380词汇量大小: 44277(1800, 1380)

____________________________________________________________________________________________________层 (类型)                     输出形状          参数数     连接到====================================================================================================input_1 (InputLayer)             (None, 1380)          0____________________________________________________________________________________________________input_2 (InputLayer)             (None, 1380)          0____________________________________________________________________________________________________input_3 (InputLayer)             (None, 1380)          0____________________________________________________________________________________________________embedding_1 (Embedding)          (None, 1380, 100)     4427700     input_1[0][0]____________________________________________________________________________________________________embedding_2 (Embedding)          (None, 1380, 100)     4427700     input_2[0][0]____________________________________________________________________________________________________embedding_3 (Embedding)          (None, 1380, 100)     4427700     input_3[0][0]____________________________________________________________________________________________________conv1d_1 (Conv1D)                (None, 1377, 32)      12832       embedding_1[0][0]____________________________________________________________________________________________________conv1d_2 (Conv1D)                (None, 1375, 32)      19232       embedding_2[0][0]____________________________________________________________________________________________________conv1d_3 (Conv1D)                (None, 1373, 32)      25632       embedding_3[0][0]____________________________________________________________________________________________________dropout_1 (Dropout)              (None, 1377, 32)      0           conv1d_1[0][0]____________________________________________________________________________________________________dropout_2 (Dropout)              (None, 1375, 32)      0           conv1d_2[0][0]____________________________________________________________________________________________________dropout_3 (Dropout)              (None, 1373, 32)      0           conv1d_3[0][0]____________________________________________________________________________________________________max_pooling1d_1 (MaxPooling1D)   (None, 688, 32)       0           dropout_1[0][0]____________________________________________________________________________________________________max_pooling1d_2 (MaxPooling1D)   (None, 687, 32)       0           dropout_2[0][0]____________________________________________________________________________________________________max_pooling1d_3 (MaxPooling1D)   (None, 686, 32)       0           dropout_3[0][0]____________________________________________________________________________________________________flatten_1 (Flatten)              (None, 22016)         0           max_pooling1d_1[0][0]____________________________________________________________________________________________________flatten_2 (Flatten)              (None, 21984)         0           max_pooling1d_2[0][0]____________________________________________________________________________________________________flatten_3 (Flatten)              (None, 21952)         0           max_pooling1d_3[0][0]____________________________________________________________________________________________________concatenate_1 (Concatenate)      (None, 65952)         0           flatten_1[0][0]                                                                   flatten_2[0][0]                                                                   flatten_3[0][0]____________________________________________________________________________________________________dense_1 (Dense)                  (None, 10)            659530      concatenate_1[0][0]____________________________________________________________________________________________________dense_2 (Dense)                  (None, 1)             11          dense_1[0][0]====================================================================================================总参数: 14,000,337可训练参数: 14,000,337不可训练参数: 0____________________________________________________________________________________________________

还有

轮次 6/101800/1800 [==============================] - 30s - 损失: 9.9093e-04 - 准确率: 1.0000轮次 7/101800/1800 [==============================] - 29s - 损失: 5.1899e-04 - 准确率: 1.0000轮次 8/101800/1800 [==============================] - 28s - 损失: 3.7958e-04 - 准确率: 1.0000轮次 9/101800/1800 [==============================] - 29s - 损失: 3.0534e-04 - 准确率: 1.0000轮次 10/101800/1800 [==============================] - 29s - 损失: 2.6234e-04 - 准确率: 1.0000

我对层和输出形状的理解如下:请帮助我确认这些是否正确,因为我在多维度上感到迷惑。

input_1 (InputLayer) (None, 1380) : —> 1380 是每个数据点的特征总数(即1380个输入神经元)。1800 是文档或数据点的总数。

embedding_1 (Embedding) (None, 1380, 100) 4427700 —-> 嵌入层是:1380作为特征(词),每个特征是一个100维的向量。

这里的参数数目是4427700是怎么计算的?

conv1d_1 (Conv1D) (None, 1377, 32) 12832 ——> Conv1d的kernel size=4。它是1*4的滤波器,使用了32次。那么维度怎么变成了(None, 1377, 32),参数数目是12832

max_pooling1d_1 (MaxPooling1D) (None, 688, 32) 使用MaxPooling1D(pool_size=2)维度怎么变成了(None, 688, 32)flatten_1 (Flatten) (None, 22016) 这是688和32的乘积吗?

** 每个轮次是否一次训练1800个数据点?**

请告诉我如何计算输出维度。任何参考或帮助都将不胜感激。


回答:

请查看下面的答案:

input_1 (InputLayer) (None, 1380) : —> 1380 是每个数据点的特征总数(即1380个输入神经元)。1800 是文档或数据点的总数。

是的。model.fit([trainX,trainX,trainX], array(trainLabels), epochs=10, batch_size=16) 表示,你希望网络在整个训练数据集上训练10次(10个轮次),每次以16为批次大小。

这意味着,每16个数据点,反向传播算法就会启动并且权重会更新。这将发生1800/16次,称为一个轮次。

1380 是第一层的neurons数目。

embedding_1 (Embedding) (None, 1380, 100) | 4427700 —-> 嵌入层是:1380作为特征(词),每个特征是一个100维的向量。

1380 是输入的大小(前一层的neurons数目),100 是嵌入向量的长度(大小)。

这里的参数数目是vocabulary_size * 100,因为对于每个v in vocabulary,你需要训练100个参数。嵌入层实际上是由词汇量大小的100维向量构成的矩阵,每一行代表词汇中每个词的向量表示。

conv1d_1 (Conv1D) (None, 1377, 32) | 12832 ——> Conv1d的kernel size=4。它是1*4的滤波器,使用了32次。那么维度怎么变成了(None, 1377, 32),参数数目是12832

1380 变为 1377 是由于kernel的大小。想象一下以下输入(为了简化,取大小为10)以及kernel大小为4的情况:

0123456789 #输入KKKK456789 0KKKK56789 12KKKK6789 123KKKK789 1234KKKK89 12345KKKK9123456KKKK

看,Kernel无法再向右移动,因此对于输入大小10和Kernel大小4,输出形状将是7。一般来说,对于输入形状n和kernel形状k,输出形状将是n - k + 1,所以对于n=1380, k=4结果是1377

参数数目等于12832,因为参数数目等于output_channels * (input_channels * window_size + 1)。在你的情况下是32*(100*4 + 1)

max_pooling1d_1 (MaxPooling1D) (None, 688, 32) with MaxPooling1D(pool_size=2) 维度怎么变成了(None, 688, 32)

max_pooling 每两个连续的数取最大值,因此你最终会得到original_size/pool_size个值。

flatten_1 (Flatten) (None, 22016) 这是688和32的乘积吗?

是的,这是688和32的乘积。因为,flatten操作做的是以下事情:

12345678   -> 1234567890129012

所以它将所有维度的值放入一个一维向量中。

每个轮次是否一次训练1800个数据点?

不是。它以16为批次大小来处理数据,正如第一个答案中指出的那样。每个轮次以随机顺序处理1800个数据点,每次处理16个数据点。一个轮次是一个时间段,之后我们将重新开始读取数据。

编辑:

我将澄清1d卷积层应用于嵌入层的地方。

你应该将嵌入层的输出解释为宽度为1380和100个通道的向量。

类似于2d图像,你有一个输入的RGB图像,有三个通道,它的形状是(width, height, 3),当你应用由32个滤波器构成的卷积层时(滤波器大小不相关),卷积操作同时应用于所有通道,输出形状将是(new_width, new_height, 32)。注意输出形状与滤波器数量相同。

回到你的例子。将嵌入层的输出形状视为(width, channels)。因此,1d卷积层具有32个滤波器且kernel大小等于4,应用于宽度1380和深度100的向量。结果,你将得到形状为(1377, 32)的输出。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注