#python #keras #conv-neural-network #transfer-learning
Вопрос:
Я пытаюсь сохранить модель CNN, которую я реализовал, и использовать ее для выполнения обучения передаче(TL) . Я хотел бы прояснить следующие четыре момента.
1.(код CNN) Является ли метод сохранения модели правильным или нет.
2.(Код TL) Является ли метод загрузки модели правильным или нет.
3.(Код TL) Как обычно устанавливается свойство «обучаемость» загруженной модели?
4.(Код TL) Правильно ли объединены модель предварительной подготовки и последующие слои (размер и т.д.)
Ниже приведена модельная часть CNN и код обучения передаче.
Обе они являются регрессионными моделями, которые предсказывают два числа. Входные данные-изображения ( контролируемые данные).
#CNN
input = Input(shape=(100,100,3))
conv_0 = Conv2D(32,kernel_size=3,activation='relu')(input)
pool_0 = MaxPooling2D(pool_size=(2,2))(conv_0)
pool_0 = Dropout(0.25)(pool_0)
conv_1 = Conv2D(64,kernel_size=3,activation='relu')(pool_0)
pool_1 = MaxPooling2D(pool_size=(2,2))(conv_1)
pool_1 = Dropout(0.25)(pool_1)
conv_2 = Conv2D(32,kernel_size=3,activation='relu')(pool_1)
pool_2 = MaxPooling2D(pool_size=(2,2))(conv_2)
pool_2 = Dropout(0.25)(pool_2)
conv_3 = Conv2D(16,kernel_size=3,activation='relu')(pool_2)
pool_3 = MaxPooling2D(pool_size=(2,2))(conv_3)
conv_4 = Conv2D(8,kernel_size=3,activation='relu')(pool_3)
pool_4 = MaxPooling2D(pool_size=(2,2))(conv_4)
flat = Flatten()(pool_4)
denseL = Dense(64,activation='relu')(flat)
denseL = Dropout(0.25)(denseL)
A_output = Dense(1,name="a")(denseL)
B_output = Dense(1,name="b")(denseL)
model = Model(inputs=input, outputs=[A_output,B_output])
model.compile(Adam(learning_rate=0.001),
loss = {'a':'mae','b':'mae'} ,
metrics = {'a':'mae','b':'mae'})
history = model.fit([np.array(Img_train)],[np.array(LabelA_train),np.array(LabelB_train)],
epochs=100, batch_size=16,
validation_data=([np.array(Img_test)],[np.array(LabelA_test),np.array(LabelB_test)]))
model.save('forTransferL.h5')
"""
Outputs for sumally()
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_1 (InputLayer) [(None, 100, 100, 3) 0
__________________________________________________________________________________________________
conv2d (Conv2D) (None, 98, 98, 32) 896 input_1[0][0]
__________________________________________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 49, 49, 32) 0 conv2d[0][0]
__________________________________________________________________________________________________
dropout (Dropout) (None, 49, 49, 32) 0 max_pooling2d[0][0]
__________________________________________________________________________________________________
conv2d_1 (Conv2D) (None, 47, 47, 64) 18496 dropout[0][0]
__________________________________________________________________________________________________
max_pooling2d_1 (MaxPooling2D) (None, 23, 23, 64) 0 conv2d_1[0][0]
__________________________________________________________________________________________________
dropout_1 (Dropout) (None, 23, 23, 64) 0 max_pooling2d_1[0][0]
__________________________________________________________________________________________________
conv2d_2 (Conv2D) (None, 21, 21, 32) 18464 dropout_1[0][0]
__________________________________________________________________________________________________
max_pooling2d_2 (MaxPooling2D) (None, 10, 10, 32) 0 conv2d_2[0][0]
__________________________________________________________________________________________________
dropout_2 (Dropout) (None, 10, 10, 32) 0 max_pooling2d_2[0][0]
__________________________________________________________________________________________________
conv2d_3 (Conv2D) (None, 8, 8, 16) 4624 dropout_2[0][0]
__________________________________________________________________________________________________
max_pooling2d_3 (MaxPooling2D) (None, 4, 4, 16) 0 conv2d_3[0][0]
__________________________________________________________________________________________________
conv2d_4 (Conv2D) (None, 2, 2, 8) 1160 max_pooling2d_3[0][0]
__________________________________________________________________________________________________
max_pooling2d_4 (MaxPooling2D) (None, 1, 1, 8) 0 conv2d_4[0][0]
__________________________________________________________________________________________________
flatten (Flatten) (None, 8) 0 max_pooling2d_4[0][0]
__________________________________________________________________________________________________
dense (Dense) (None, 64) 576 flatten[0][0]
__________________________________________________________________________________________________
dropout_3 (Dropout) (None, 64) 0 dense[0][0]
__________________________________________________________________________________________________
a (Dense) (None, 1) 65 dropout_3[0][0]
__________________________________________________________________________________________________
b (Dense) (None, 1) 65 dropout_3[0][0]
=========================================================================================
"""
#TL
model = load_model('forTransferL.h5')
model.layers[0].trainable = False
x = model.layers[10].output
# The following is the same as part of CNN model.
conv_3 = Conv2D(16,kernel_size=3,activation='relu')(x)
pool_3 = MaxPooling2D(pool_size=(2,2))(conv_3)
conv_4 = Conv2D(8,kernel_size=3,activation='relu')(pool_3)
pool_4 = MaxPooling2D(pool_size=(2,2))(conv_4)
flat = Flatten()(pool_4)
denseL = Dense(64,activation='relu')(flat)
denseL = Dropout(0.25)(denseL)
A_output = Dense(1,name="a")(denseL)
B_output = Dense(1,name="b")(denseL)
model=Model(inputs=model.input,outputs=[A_output,B_output])
На всякий случай я также включаю текст ошибки, который в настоящее время отображается ниже,
но я думаю, что понимание основной части реализации является более важным приоритетом, чем исправление ошибки.
Спасибо вам за сотрудничество.
#error message
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "c:/Users/userABC/OneDrive/Document/StudyAI/transferMymodel.py", line 158, in <module>
pool_m4 = MaxPooling2D(pool_size=(2,2))(conv_m4)
File "C:UsersuserABCanaconda3libsite-packageskerasenginebase_layer.py", line 1006, in __call__
outputs = call_fn(inputs, *args, **kwargs)
〜Omitted due to the limited number of characters.
ValueError: Negative dimension size caused by subtracting 2 from 1 for '{{node tf.compat.v1.nn.max_pool_1/MaxPool}} = MaxPool[T=DT_FLOAT, data_format="NHWC", explicit_paddings=[], ksize=[1, 2, 2, 1], padding="VALID", strides=[1, 2, 2, 1]](Placeholder)' with input shapes: [?,1,1,8].
Ответ №1:
Для пунктов 1 и 2 ваш код кажется достаточно правильным, хотя лично я предпочитаю загружать веса моделей вместо самой модели, когда речь заходит о моделях с пользовательскими слоями. Хотя на самом деле это не имеет значения для вашей ситуации.
По пунктам 3 см. https://keras.io/guides/transfer_learning/:
Если вы установите trainable = False для модели или любого слоя, имеющего подслои, все дочерние слои также станут необучаемыми.
Это означает, что в вашей ситуации установка «model.trainable = False» приведет к замораживанию всех весов загруженной части модели (предотвратит ее изменение).
Для пункта 4 предварительно обученная модель и более поздние слои выглядят правильно, но ошибка вызвана тем, что вы не установили заполнение= «то же самое» внутри слоев Conv2D (пример:
conv_3 = Conv2D(16,kernel_size=3,activation='relu', padding='same')(x)
Это важно, потому что не указание одинакового заполнения означает, что каждый слой Conv2D уменьшает высоту и ширину изображения на 2, и, учитывая, что выходная форма вашей предварительно подготовленной модели равна (8, 8, 16), первая свертка даст выходную форму (6, 6, 16), первый максимальный пул даст (3, 3, 16), вторая свертка даст (1, 1, 8), и на данный момент второй максимальный пул больше не может объединять объекты, так как высота и ширина меньше (2, 2).