Q: Ошибка значения Keras ожидала, что conv2d_14_input будет иметь форму (3, 12, 1), но получила массив с формой (3, 12, 6500)?

#keras #multidimensional-array #numpy-ndarray #conv-neural-network #numpy-slicing

#keras #многомерный массив #numpy-ndarray #conv-нейронная сеть #numpy-нарезка

Вопрос:

Я создаю CNN для данных, не относящихся к изображению, в Keras 2.1.0 в Window 10.

Мой входной объект представляет собой матрицу неотрицательного числа 3×12, а мой вывод представляет собой двоичный вектор с несколькими метками длиной 6×1

И я столкнулся с этой ошибкой ожидал, что conv2d_14_input будет иметь форму (3, 12, 1), но получил массив с формой (3, 12, 6500)

Вот мой код ниже

 import tensorflow as tf
from scipy.io import loadmat
import numpy as np
from tensorflow.keras.layers import BatchNormalization
import matplotlib.pyplot as plt
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Activation, Dropout
from tensorflow.keras.layers import Conv2D, MaxPool2D, Flatten


reshape_channel_train = loadmat('reshape_channel_train')
reshape_channel_test = loadmat('reshape_channel_test.mat')
reshape_label_train = loadmat('reshape_label_train')
reshape_label_test = loadmat('reshape_label_test')

X_train = reshape_channel_train['store_train']
X_test = reshape_channel_test['store_test']

X_train = np.expand_dims(X_train,axis = 0)
X_test  = np.expand_dims(X_test, axis = 0)

Y_train = reshape_label_train['label_train']
Y_test = reshape_label_test['label_test']

classifier = Sequential()
classifier.add(Conv2D(8, kernel_size=(3,3) , input_shape=(3, 12, 1), padding="same"))
classifier.add(BatchNormalization())
classifier.add(Activation('relu'))

classifier.add(Conv2D(8, kernel_size=(3,3), input_shape=(3, 12, 1), padding="same"))
classifier.add(BatchNormalization())
classifier.add(Activation('relu'))

classifier.add(Flatten())
classifier.add(Dense(8, activation='relu'))
classifier.add(Dense(6, activation='sigmoid'))
classifier.compile(optimizer='nadam', loss='binary_crossentropy', metrics=['accuracy'])

history = classifier.fit(X_train, Y_train, batch_size = 32, epochs=100,
                         validation_data=(X_test, Y_test), verbose=2)
  

После некоторого поиска я использовал трюк с расширением размеров, но, похоже, он не работает

 X_train = np.expand_dims(X_train,axis = 0)
X_test  = np.expand_dims(X_test, axis = 0)
  

Переменная X_train, содержащая 6500 обучающих экземпляров, загружена из файла Matlab .mat размером 3x12x6500.

Где каждый обучающий экземпляр представляет собой матрицу 3×12.

Перед использованием трюков expand_dim k-й обучающий образец мог быть вызван X_train[:,:,k] и X_train [:,:,k].форма вернет (3,12). Также X_train.shape вернет (3, 12, 6500)

После использования трюков с expand_dim команда X_train[:,:,k].форма вернет (1, 3, 6500)

Пожалуйста, помогите мне с этим! Спасибо

Ответ №1:

вы неправильно управляете своими данными. Conv2D Слой принимает данные в этом формате (n_sample, height, width, channels) , который в вашем случае (для вашего X_train) стал (6500,3,12,1) . вам нужно просто восстановить этот случай

 # create data as in your matlab data
n_class = 6
n_sample = 6500
X_train = np.random.uniform(0,1, (3,12,n_sample)) # (3,12,n_sample)
Y_train = tf.keras.utils.to_categorical(np.random.randint(0,n_class, n_sample)) # (n_sample, n_classes)

# reshape your data for conv2d
X_train = X_train.transpose(2,0,1) # (n_sample,3,12)
X_train = np.expand_dims(X_train, -1) # (n_sample,3,12,1)

classifier = Sequential()
classifier.add(Conv2D(8, kernel_size=(3,3) , input_shape=(3, 12, 1), padding="same"))
classifier.add(BatchNormalization())
classifier.add(Activation('relu'))

classifier.add(Conv2D(8, kernel_size=(3,3), padding="same"))
classifier.add(BatchNormalization())
classifier.add(Activation('relu'))

classifier.add(Flatten())
classifier.add(Dense(8, activation='relu'))
classifier.add(Dense(n_class, activation='softmax'))
classifier.compile(optimizer='nadam', loss='categorical_crossentropy', metrics=['accuracy'])

history = classifier.fit(X_train, Y_train, batch_size = 32, epochs=2, verbose=2)

# get predictions
pred = np.argmax(classifier.predict(X_train), 1)
  

Я также использую softmax активацию с categorical_crossentropy , которая больше подходит для многоклассовой задачи, но вы также можете изменить это. не забудьте применить те же манипуляции с данными и к вашим тестовым данным

Комментарии:

1. О, большое вам спасибо, на самом деле моя проблема заключается в нескольких метках, а не в нескольких классах. Но означает ли это, что я должен подготовить свой набор данных так, чтобы форма была 6500x3x12 (правильная) вместо 3x12x6500 (неправильная)?

2. хорошо, многоклассовый или с несколькими метками не имеет значения (вы можете соответствующим образом изменить сеть). да, ваши данные должны быть (6500x3x12x1)… не забудьте добавить также последнюю размерность с расширением dims, как я сделал в коде … не забудьте проголосовать и принять это 😉

Ответ №2:

вам нужно передать аргумент data_format=»channels_last», потому что ваши каналы наконец

вы пытаетесь это:

 x_train=x_train.reshape((6500,3,12,1))
x_test=x_test.reshape((-1,3,12,1))


and in each of conv2d layer conv2D(<other args>, data_format="channels_last")