Используйте keras.layers.Reshape для стыковки между произвольными слоями разных размеров.

задняя часть

1. Представьте

Keras предоставляет нам множество различных слоев, таких как Dense, Dropout, Flatten, Activation, BatchNormalization, GlobalAveragePooling2D, Conv2D, MaxPooling2D, ZeroPadding2D, LSTM и так далее. Мы используем эти слои и связываем их слой за слоем, как строительные блоки, для реализации модели глубокого обучения.

Однако все слои, предоставляемые keras, являются традиционными слоями. Есть несколько новых слоев, которые keras не может предоставить нам так быстро. Так что для некоторых специальных слоев мы все же отправимся на github, чтобы найти то, что написали другие разработчики, и использовать их.

Затем возникает проблема: когда эти сторонние слои и слои, предоставляемые keras, соединяются вместе, часто сообщается об ошибках. В большинстве случаев этот слой прямой стыковки получит следующую ошибку: ValueError: Размеры должны быть равны.

Причина ошибки в том, что сторонний слой, возможно, был написан так, чтобы требовать 2D-ввода, но размерность данных слоя, выводимых нашим keras, может быть 3D, поэтому размеры не совпадают.

Итак, как нам правильно соединить разные типы слоев, чтобы сформировать модель? использоватьkeras.layers.Reshapeможет очень хорошо решить эту проблему. Реальный случай описан ниже.

2. Кейсы

  1. цель дела

Наша цель здесь — использовать keras для построения модели, которая соединяет слой Attention с обратной стороной слоя CNN. То есть реализовать стыковку слоя Attention с любым положением модели.

  1. Attention

Слой Attention использует сторонний инструментарий:furskin.org/project/guest…

  1. тренировочные данные

Используйте numpy random для генерации случайных обучающих данных:

import numpy as np

num_classes = 6 # classification number
x_train = np.random.randn(100, 15, 20, 3) # x_train.shape = (100, 15, 20, 3)
y_train = np.random.randint(1, size=(100,num_classes)) # y_train.shape = (100, 6)
input_shape = x_train.shape[-3:]# (15, 20, 3)

См. комментарии в коде для размеров данных.

  1. Построить модель

Сначала создайте модель CNN, а затем добавьте слой SeqSelfAttention после CNN. Конкретный код выглядит следующим образом:

from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras_self_attention import SeqSelfAttention
import keras

model = Sequential()
model.add(Conv2D(32, (2,11), activation='relu', padding='same', input_shape=input_shape))
model.add(Conv2D(32, (2,11), activation='relu', padding='same'))
model.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 1)))
model.add(Conv2D(128, (2,7), activation='relu', padding='same'))
model.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 1)))
model.add( SeqSelfAttention( attention_type=SeqSelfAttention.ATTENTION_TYPE_MUL) )
model.add(Flatten())
model.add(Dense(440, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam')
model.summary()                            
  1. сообщить об ошибке

Приведенный выше код сообщит об ошибке, и модель не может быть построена напрямую таким образом. Сообщение об ошибке выглядит следующим образом:

    ValueError: Dimensions must be equal, but are 128 and 16 for '{{node seq_self_attention/MatMul}} = MatMul[T=DT_FLOAT, transpose_a=false, transpose_b=false](seq_self_attention/Reshape, seq_self_attention/Reshape_1)' with input shapes: [?,128], [16,16].

Анализ: ошибка такого рода обычно вызвана несоответствием размеров нескольких вычисляемых матриц. Например, умножение двух матриц должно соответствовать определенным требованиям размерности.

Мы также можем видеть, что конкретное место ошибки — это строка кода, которая добавляет внимание после CNN:

---> 23 model.add( SeqSelfAttention( attention_type=SeqSelfAttention.ATTENTION_TYPE_MUL) )

3. Используйте keras.layers.Reshape для хорошей стыковки разных слоев

В соответствии с приведенной выше ошибкой (и расположением ошибки) видно, что размерность выходных данных верхнего уровня SeqSelfAttention не соответствует размерности входных данных, требуемой SeqSelfAttention. Таким образом, вам нужно сделать Reshape, прежде чем позволить данным войти в SeqSelfAttention.

Измените код в разделе модели на:

model = Sequential()
model.add(Conv2D(32, (2,11), activation='relu', padding='same', input_shape=input_shape))
model.add(Conv2D(32, (2,11), activation='relu', padding='same'))
model.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 1)))
model.add(Conv2D(128, (2,7), activation='relu', padding='same'))
model.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 1)))
model.add( keras.layers.Reshape((5,128)) )
model.add( SeqSelfAttention( attention_type=SeqSelfAttention.ATTENTION_TYPE_MUL) )
model.add(Flatten())
model.add(Dense(440, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam')
model.summary()

Что касается конкретной формы keras.layers.Reshape, сначала установите значение случайно, вот (5,128). Запускаем программу и получаем следующую ошибку:

ValueError: total size of new array must be unchanged, input_shape = [3, 16, 128], output_shape = [5, 128]

Из этой ошибки мы можем узнать, что размерность данных входного Reshape равна [3, 16, 128], поэтому размерность данных после Reshape также должна быть равна 3x16x128. А мы просто поставили (5,128), 5х128 не равно 3х16х128.

Замените (5 128) на (48 128), и модель успешно построена. Полный код, который корректно работает после модификации, выглядит следующим образом:

from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras_self_attention import SeqSelfAttention
import keras
import numpy as np

num_classes = 6 # classification number
x_train = np.random.randn(100, 15, 20, 3) # x_train.shape = (100, 15, 20, 3)
y_train = np.random.randint(1, size=(100,num_classes)) # y_train.shape = (100, 6)
input_shape = x_train.shape[-3:]# (15, 20, 3)


model = Sequential()
model.add(Conv2D(32, (2,11), activation='relu', padding='same', input_shape=input_shape))
model.add(Conv2D(32, (2,11), activation='relu', padding='same'))
model.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 1)))
model.add(Conv2D(128, (2,7), activation='relu', padding='same'))
model.add(MaxPooling2D(pool_size=(3, 3), strides=(2, 1)))
model.add( keras.layers.Reshape((48,128)) )
model.add( SeqSelfAttention( attention_type=SeqSelfAttention.ATTENTION_TYPE_MUL) )
model.add(Flatten())
model.add(Dense(440, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam')
model.summary()                            

4. Резюме

Эта статья предоставляет способ, технически, использоватьkeras.layers.ReshapeРеализовать стыковку разных слоев кераса. Но следует отметить, что это все-таки изменяет размерность данных, а также изменяет состав данных, что может иметь влияние на последующую идентификацию. Это влияние необходимо анализировать в каждом конкретном случае.

5. Ссылка

  1. Доступно на ras.io/this/layers/from…
  2. stackoverflow.com/questions/4…
  3. blog.CSDN.net/U014535666/…

Оригинальная статья, первоначально опубликованная:blog.CSDN.net/общее желание/AR…