#python #keras #deep-learning #conv-neural-network
#python #keras #глубокое обучение #conv-нейронная сеть
Вопрос:
Я выполняю многоклассовую классификацию текста с помощью сверточной нейронной сети, я применил приведенный ниже код к своим весам для встраивания перчаток, я получил хороший результат, но у меня есть вопрос о форме CONV2D: почему в CONV2D 1 мы получаем conv_1 (None, 407, 1, 64) и соответственно в conv_2: None, 406, 1, 64) и в conv_2:405 ?
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_18 (InputLayer) (None, 409) 0
__________________________________________________________________________________________________
embedding_17 (Embedding) (None, 409, 100) 1766600 input_18[0][0]
__________________________________________________________________________________________________
reshape_10 (Reshape) (None, 409, 100, 1) 0 embedding_17[0][0]
__________________________________________________________________________________________________
conv_1 (Conv2D) (None, 407, 1, 64) 19264 reshape_10[0][0]
__________________________________________________________________________________________________
conv_2 (Conv2D) (None, 406, 1, 64) 25664 reshape_10[0][0]
__________________________________________________________________________________________________
conv_3 (Conv2D) (None, 405, 1, 64) 32064 reshape_10[0][0]
__________________________________________________________________________________________________
max_pooling2d_16 (MaxPooling2D) (None, 1, 1, 64) 0 conv_1[0][0]
__________________________________________________________________________________________________
max_pooling2d_17 (MaxPooling2D) (None, 1, 1, 64) 0 conv_2[0][0]
__________________________________________________________________________________________________
max_pooling2d_18 (MaxPooling2D) (None, 1, 1, 64) 0 conv_3[0][0]
__________________________________________________________________________________________________
concatenate_6 (Concatenate) (None, 3, 1, 64) 0 max_pooling2d_16[0][0]
max_pooling2d_17[0][0]
max_pooling2d_18[0][0]
__________________________________________________________________________________________________
flatten_5 (Flatten) (None, 192) 0 concatenate_6[0][0]
__________________________________________________________________________________________________
dropout_11 (Dropout) (None, 192) 0 flatten_5[0][0]
__________________________________________________________________________________________________
dense_11 (Dense) (None, 3) 579 dropout_11[0][0]
==================================================================================================
Total params: 1,844,171
Trainable params: 1,844,171
Non-trainable params: 0
__________________________________________________________________________________________________
None
from keras.layers import Dense, Input, GlobalMaxPooling1D
from keras.layers import Conv1D, MaxPooling1D, Embedding
from keras.models import Model
from keras.layers import Input, Dense, Embedding, Conv2D, MaxPooling2D, Dropout,concatenate
from keras.layers.core import Reshape, Flatten
from keras.callbacks import EarlyStopping
from keras.optimizers import Adam
from keras.models import Model
from keras import regularizers
sequence_length = 409
filter_sizes = [3,4,5]
num_filters = 64
drop = 0.5
EMBEDDING_DIM=100
embedding_layer = Embedding(len(tokenizer.word_index) 1,
EMBEDDING_DIM,
weights=[embedding_matrix],
trainable=True)
inputs = Input(shape=(sequence_length,))
embedding = embedding_layer(inputs)
reshape = Reshape((sequence_length,EMBEDDING_DIM,1))(embedding)
conv_0 = Conv2D(num_filters, (filter_sizes[0], EMBEDDING_DIM),activation='relu',kernel_regularizer=regularizers.l2(0.01),name='conv_1')(reshape)
conv_1 = Conv2D(num_filters, (filter_sizes[1], EMBEDDING_DIM),activation='relu',kernel_regularizer=regularizers.l2(0.01),name='conv_2')(reshape)
conv_2 = Conv2D(num_filters, (filter_sizes[2], EMBEDDING_DIM),activation='relu',kernel_regularizer=regularizers.l2(0.01),name='conv_3')(reshape)
maxpool_0 = MaxPooling2D((sequence_length - filter_sizes[0] 1, 1), strides=(1,1))(conv_0)
maxpool_1 = MaxPooling2D((sequence_length - filter_sizes[1] 1, 1), strides=(1,1))(conv_1)
maxpool_2 = MaxPooling2D((sequence_length - filter_sizes[2] 1, 1), strides=(1,1))(conv_2)
merged_tensor = concatenate([maxpool_0, maxpool_1, maxpool_2], axis=1)
flatten = Flatten()(merged_tensor)
reshape = Reshape((3*num_filters,))(flatten)
dropout = Dropout(drop)(flatten)
output = Dense(units=3, activation='softmax',kernel_regularizer=regularizers.l2(0.01))(dropout)
# this creates a model that includes
model = Model(inputs, output)
adam = Adam(lr=1e-3)
model.compile(loss='categorical_crossentropy',
optimizer=adam,
metrics=['acc'])
print(model.summary())
Ответ №1:
Об этом не о чем беспокоиться. Это основная проблема с любой операцией свертки с ядрами. Размер ядер, свертываемых по изображению, приведет к тому, что несколько пикселей будут пропущены. Вот ссылка, описывающая проблему более подробно.
Предполагая , что входная форма равна 𝑛ℎ×𝑛𝑤
и форма ядра свертки 𝑘ℎ×𝑘𝑤
равна , тогда выходная форма будет (𝑛ℎ−𝑘ℎ 1)×(𝑛𝑤−𝑘𝑤 1)
Один из способов справиться с этим — установить padding
параметр в слое как 'same'
.
tf.keras.layers.Conv2D(
filters, kernel_size, strides=(1, 1), padding='same', data_format=None,
dilation_rate=(1, 1), groups=1, activation=None, use_bias=True,
kernel_initializer='glorot_uniform', bias_initializer='zeros',
kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None,
kernel_constraint=None, bias_constraint=None, **kwargs
)
С заполнением = ‘действительный’
> input_shape = (4, 28, 28, 3)
> x = tf.random.normal(input_shape)
> y = tf.keras.layers.Conv2D(2, 3, activation='relu', input_shape=input_shape[1:])(x)
> print(y.shape)
(4, 26, 26, 3)
С заполнением = ‘то же самое’
> input_shape = (4, 28, 28, 3)
> x = tf.random.normal(input_shape)
> y = tf.keras.layers.Conv2D(2, 3, activation='relu', padding="same", input_shape=input_shape[1:])(x)
> print(y.shape)
(4, 28, 28, 3)
РЕДАКТИРОВАТЬ: вам лучше использовать conv1d для текстовых / временных данных вместо многократного изменения формы для использования conv2d. Вот ваша архитектура модели с 1D свертками.
Однако я не совсем понимаю, почему вы делаете то, что делаете для слоев maxpooling. Я в основном пытался сохранить те же самые прямые вычисления, но вы должны посмотреть на эти слои и посмотреть, имеют ли они смысл.
from tensorflow.keras import layers, Model, regularizers
vocab_size = 1000
inp = layers.Input(shape=(409,))
emb = layers.Embedding(vocab_size, 100)(inp)
conv1 = layers.Conv1D(64, 3, padding='same')(emb)
conv2 = layers.Conv1D(64, 4, padding='same')(emb)
conv3 = layers.Conv1D(64, 5, padding='same')(emb)
max1 = layers.MaxPool1D(409, strides=1)(conv1)
max2 = layers.MaxPool1D(409, strides=1)(conv2)
max3 = layers.MaxPool1D(409, strides=1)(conv3)
conc = layers.concatenate([max1, max2, max3])
flat = layers.Flatten()(conc)
drop = layers.Dropout(0.5)(flat)
out = layers.Dense(3, activation='softmax', kernel_regularizer='l2')(drop)
model = Model(inp,out)
model.summary()
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_21 (InputLayer) [(None, 409)] 0
__________________________________________________________________________________________________
embedding_20 (Embedding) (None, 409, 100) 100000 input_21[0][0]
__________________________________________________________________________________________________
conv1d_50 (Conv1D) (None, 409, 64) 19264 embedding_20[0][0]
__________________________________________________________________________________________________
conv1d_51 (Conv1D) (None, 409, 64) 25664 embedding_20[0][0]
__________________________________________________________________________________________________
conv1d_52 (Conv1D) (None, 409, 64) 32064 embedding_20[0][0]
__________________________________________________________________________________________________
max_pooling1d_39 (MaxPooling1D) (None, 1, 64) 0 conv1d_50[0][0]
__________________________________________________________________________________________________
max_pooling1d_40 (MaxPooling1D) (None, 1, 64) 0 conv1d_51[0][0]
__________________________________________________________________________________________________
max_pooling1d_41 (MaxPooling1D) (None, 1, 64) 0 conv1d_52[0][0]
__________________________________________________________________________________________________
concatenate_11 (Concatenate) (None, 1, 192) 0 max_pooling1d_39[0][0]
max_pooling1d_40[0][0]
max_pooling1d_41[0][0]
__________________________________________________________________________________________________
flatten_5 (Flatten) (None, 192) 0 concatenate_11[0][0]
__________________________________________________________________________________________________
dropout_4 (Dropout) (None, 192) 0 flatten_5[0][0]
__________________________________________________________________________________________________
dense_3 (Dense) (None, 3) 579 dropout_4[0][0]
==================================================================================================
Total params: 177,571
Trainable params: 177,571
Non-trainable params: 0
Комментарии:
1. спасибо, когда я добавляю padding=»то же самое», ошибка: общий размер нового массива должен быть неизменным
2. Не имеет значения, текст это или изображение, это просто естественная вещь, которая происходит со свертками. Кроме того, я вижу, что вы используете conv2d, но все еще свертываетесь в одном измерении. Почему бы просто не использовать conv1d? Это то, что обычно используется при классификации текста.
3. Кроме того, проблема, с которой вы столкнулись, больше связана с немного странной формой ядра, используемой здесь.
4. Вместо изменения формы и добавления нового измерения просто используйте conv1d. Это привело бы к свертке над внедрением, аналогичной тому, что вы сейчас делаете.
5. большое вам спасибо, можете ли вы помочь мне, как это реализовать? Я новичок в python и cnn..