我正在通过此链接来了解用于文本分类的多通道CNN模型。
该代码基于本教程。
我已经了解了大多数事情,但是我不明白Keras如何定义某些图层的输出形状。
这是代码:
定义一个具有三个输入通道的模型,用于处理4克,6克和8克电影评论文本。
#Skipped keras imports
# load a clean dataset
def load_dataset(filename):
return load(open(filename, 'rb'))
# fit a tokenizer
def create_tokenizer(lines):
tokenizer = Tokenizer()
tokenizer.fit_on_texts(lines)
return tokenizer
# calculate the maximum document length
def max_length(lines):
return max([len(s.split()) for s in lines])
# encode a list of lines
def encode_text(tokenizer, lines, length):
# integer encode
encoded = tokenizer.texts_to_sequences(lines)
# pad encoded sequences
padded = pad_sequences(encoded, maxlen=length, padding='post')
return padded
# define the model
def define_model(length, vocab_size):
# channel 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)
# channel 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)
# channel 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)
# merge
merged = concatenate([flat1, flat2, flat3])
# interpretation
dense1 = Dense(10, activation='relu')(merged)
outputs = Dense(1, activation='sigmoid')(dense1)
model = Model(inputs=[inputs1, inputs2, inputs3], outputs=outputs)
# compile
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
# summarize
print(model.summary())
plot_model(model, show_shapes=True, to_file='multichannel.png')
return model
# load training dataset
trainLines, trainLabels = load_dataset('train.pkl')
# create tokenizer
tokenizer = create_tokenizer(trainLines)
# calculate max document length
length = max_length(trainLines)
# calculate vocabulary size
vocab_size = len(tokenizer.word_index) + 1
print('Max document length: %d' % length)
print('Vocabulary size: %d' % vocab_size)
# encode data
trainX = encode_text(tokenizer, trainLines, length)
print(trainX.shape)
# define model
model = define_model(length, vocab_size)
# fit model
model.fit([trainX,trainX,trainX], array(trainLabels), epochs=10, batch_size=16)
# save the model
model.save('model.h5')
运行代码:
首先运行示例将打印准备好的训练数据集的摘要。最大文档长度:1380词汇量:44277(1800,1380)
____________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
====================================================================================================
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]
====================================================================================================
Total params: 14,000,337
Trainable params: 14,000,337
Non-trainable params: 0
____________________________________________________________________________________________________
和
Epoch 6/10
1800/1800 [==============================] - 30s - loss: 9.9093e-04 - acc: 1.0000
Epoch 7/10
1800/1800 [==============================] - 29s - loss: 5.1899e-04 - acc: 1.0000
Epoch 8/10
1800/1800 [==============================] - 28s - loss: 3.7958e-04 - acc: 1.0000
Epoch 9/10
1800/1800 [==============================] - 29s - loss: 3.0534e-04 - acc: 1.0000
Epoch 10/10
1800/1800 [==============================] - 29s - loss: 2.6234e-04 - acc: 1.0000
我对“层”和输出形状的解释如下:请帮助我理解它是否正确,因为我在多维中迷失了方向。
input_1(InputLayer)(无,1380):--->1380
是每个数据点的特征总数(即1380个输入神经元)。1800
是文档或数据点的总数。
embedding_1(Embedding)(None,1380,100)4427700 ---->嵌入层是:1380作为要素(单词),每个要素都是尺寸为100的向量。
这里的参数数量是多少4427700
?
conv1d_1(Conv1D)(无,1377,32)12832 ------> Conv1d是的kernel size=4
。它1*4
是使用过的过滤器32
。那么如何尺寸变得(None, 1377, 32)
与12832
参数?
使用MaxPooling1D(pool_size = 2)的max_pooling1d_1(MaxPooling1D)(None, 688,32)尺寸如何变为(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
是第一层中的神经元数量。
embedding_1 (Embedding) (None, 1380, 100) | 4427700
---->嵌入层是:1380个特征(单词),每个特征是一个尺寸为100的向量。
1380是输入的大小(上一层中神经元的数量),100是嵌入向量的大小(长度)。
这里的参数数量与您需要训练100个参数的vocabulary_size * 100
每个v in vocabulary
参数的数量相同。嵌入层实际上是一个矩阵,其大小为100的vocabulary_size向量,其中每一行代表该词汇表中每个单词的向量表示。
conv1d_1 (Conv1D) (None, 1377, 32) | 12832
------> Conv1d的内核大小为4。是1 * 4过滤器,使用了32次。然后,尺寸如何变成具有12832个参数的(无,1377、32)?
由于内核的大小,1380变为1377。想象以下输入(为了简化,将大小设为10),内核大小为4:
0123456789 #input
KKKK456789
0KKKK56789
12KKKK6789
123KKKK789
1234KKKK89
12345KKKK9
123456KKKK
看,内核不能再向右移动,因此对于输入大小10和内核大小4,输出形状将为7。通常,对于n的输入形状和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操作执行以下操作:
1234
5678 -> 123456789012
9012
因此它将所有维度的所有值都放入一维向量中。
是否每个时代都训练1800个数据点?
否。如第一个答案所指出的那样,它们需要分16批进行。每个时期以16个数据点为批次,以随机顺序获取1800个数据点。时期是一个术语,表示一段时间,之后我们将再次开始读取数据。
编辑:
我将阐明将1d卷积层应用于嵌入层的位置。
您应该将“嵌入”层的输出解释为宽度为1380和100通道的向量。
类似于2d图像,在该图像中输入中具有三个通道的RGB图像,当您应用由32个滤镜构建的卷积层(滤镜大小无关)时,其形状为(宽度,高度,3),同时进行卷积运算到所有通道,输出形状将为(new_width,new_height,32)。请注意,输出形状与过滤器的数量相同。
回到您的示例。将嵌入层的输出形状视为(宽度,通道)。因此,将具有32个滤镜且内核大小等于4的1d卷积层应用于矢量1380和深度100。结果,将得到形状的输出(1377,32)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句