我是 DL 的新手,我正在尝试使用 FER2013 数据集通过 VGG16 预训练网络执行情感识别任务,但是当我尝试预测结果时,我收到此错误:
“ValueError: Input 0 of layer block1_conv1 与层不兼容:输入形状的预期轴 -1 具有值 3 但接收到形状为 (None, 48, 48, 1) 的输入”
代码如下:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sn
import skimage.io
import keras.backend as K
import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.applications import VGG16
from tensorflow.keras.layers import Dense, Flatten, Dropout,BatchNormalization ,Activation
from tensorflow.keras.models import Model, Sequential
from keras.applications.nasnet import NASNetLarge
from tensorflow.keras.callbacks import ReduceLROnPlateau, ModelCheckpoint, EarlyStopping
from tensorflow.keras.optimizers import Adam
from google.colab import drive
drive.mount("/content/drive")
from zipfile import ZipFile
!unzip -q "/content/drive/MyDrive/archive.zip"
train_datagen = ImageDataGenerator(rescale = 1./255,
validation_split = 0.2,
rotation_range=5,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
#zoom_range=0.2,
horizontal_flip=True,
vertical_flip=True,
fill_mode='nearest')
valid_datagen = ImageDataGenerator(rescale = 1./255,
validation_split = 0.2)
test_datagen = ImageDataGenerator(rescale = 1./255
)
train_dir='train'
train_dataset = train_datagen.flow_from_directory(train_dir,
target_size = (48,48),
class_mode = 'categorical',
subset = 'training',
batch_size = 64)
valid_dataset = valid_datagen.flow_from_directory(train_dir,
target_size = (48,48),
class_mode = 'categorical',
subset = 'validation',
batch_size = 64)
test_dir='test'
test_dataset = test_datagen.flow_from_directory(test_dir,
target_size = (48,48),
class_mode = 'categorical',
batch_size = 64)
base_model = tf.keras.applications.VGG16(input_shape=(48,48,3),include_top=False,weights="imagenet")
# Freezing Layers
for layer in base_model.layers[:-4]:
layer.trainable=False
# Building Model
model=Sequential()
model.add(base_model)
model.add(Dropout(0.5))
model.add(Flatten())
model.add(BatchNormalization())
model.add(Dense(32,kernel_initializer='he_uniform'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(32,kernel_initializer='he_uniform'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(32,kernel_initializer='he_uniform'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Dense(7,activation='softmax'))
# Model Summary
model.summary()
from tensorflow.keras.utils import plot_model
from IPython.display import Image
plot_model(model, to_file='convnet.png', show_shapes=True,show_layer_names=True)
Image(filename='convnet.png')
def f1_score(y_true, y_pred): #taken from old keras source code
true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
precision = true_positives / (predicted_positives + K.epsilon())
recall = true_positives / (possible_positives + K.epsilon())
f1_val = 2*(precision*recall)/(precision+recall+K.epsilon())
return f1_val
METRICS = [
tf.keras.metrics.BinaryAccuracy(name='accuracy'),
tf.keras.metrics.Precision(name='precision'),
tf.keras.metrics.Recall(name='recall'),
tf.keras.metrics.AUC(name='auc'),
f1_score,
]
lrd = ReduceLROnPlateau(monitor = 'val_loss',patience = 20,verbose = 1,factor = 0.50, min_lr = 1e-10)
mcp = ModelCheckpoint('model.h5')
es = EarlyStopping(verbose=1, patience=20)
model.compile(optimizer='Adam', loss='categorical_crossentropy',metrics=METRICS)
history=model.fit(train_dataset,validation_data=valid_dataset,epochs = 5,verbose = 1,callbacks=[lrd,mcp,es])
model.save('vgg-16.h5')
import keras
model = keras.models.load_model('vgg-16.h5', compile = False)
METRICS = [
tf.keras.metrics.BinaryAccuracy(name='accuracy'),
tf.keras.metrics.Precision(name='precision'),
tf.keras.metrics.Recall(name='recall'),
tf.keras.metrics.AUC(name='auc'),
f1_score,
]
model.compile(optimizer='Adam', loss='categorical_crossentropy',metrics=METRICS)
from keras.preprocessing import image
img = image.load_img("test/happy/PrivateTest_1140198.jpg",target_size = (48,48),color_mode = "grayscale")
img = np.array(img)
plt.imshow(img)
print(img.shape) #prints (48,48) that is the shape of our image
label_dict = {0:'Angry',1:'Disgust',2:'Fear',3:'Happy',4:'Neutral',5:'Sad',6:'Surprise'}
img = np.expand_dims(img,axis = 0) #makes image shape (1,48,48)
img = img.reshape(1,48,48,1)
result = model.predict(img)
答案 0 :(得分:0)
这个预训练的 VGG16 网络被设置为接收形状为 (48, 48, 3) 的输入图像,3 个通道对应于图像的 RGB 颜色。
在这一行:
img = image.load_img("test/happy/PrivateTest_1140198.jpg",target_size = (48,48),color_mode = "grayscale")
您使用 color_mode="grayscale"
加载图像,返回 1 通道图像。
要适合模型的预期输入形状,您需要设置 color_mode="rgb"
,这会生成 3 通道 RGB 图像。
然后,在将图像传递到模型之前将其重塑为 img = img.reshape(1,48,48,3)
。