问题:
因此,当我尝试训练cnn时,会发生此错误。
ValueError: Error when checking target: expected dense_4 to have shape (32,) but got array with shape (1,)
我不知道这意味着什么。这个代码不是100%我的,我只是拿了一个CNN代码并对其进行了修改以使其适用于我的需求。 尽管我对CNN编码的知识非常有限,而且我也没有对Python编程的适当培训。
有人可以向我解释该错误是怎么回事,而我想知道是什么原因引起的。你们能告诉我到目前为止我对代码所做的是否正确吗?
我计划创建一个CNN,它将能够对图像进行分类,以包含性,暴力,恐怖和毒品内容。因此,这是具有图像输入的多类CNN,输出将对图像所属的类别进行分类。
以下是CNN代码的其余部分:
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Dense, Dropout, Flatten
from keras.callbacks import ModelCheckpoint
IMAGE_LENGHT = 300
EPOCH_COUNT = 10
MODEL_PATH = 'model.hdf5'
WEIGHTS_PATH = 'weights.hdf5'
model = Sequential()
model.add(Conv2D(32, (9, 9), input_shape = (IMAGE_LENGHT,IMAGE_LENGHT, 3), activation = 'relu'))
model.add(MaxPooling2D(pool_size = (2, 2)))
model.add(Conv2D(32, (9, 9), activation = 'relu'))
model.add(MaxPooling2D(pool_size = (2, 2)))
model.add(Conv2D(64, (9, 9), activation = 'relu'))
model.add(MaxPooling2D(pool_size = (2, 2)))
model.add(Flatten())
model.add(Dense(64, activation = 'relu'))
model.add(Dropout(rate = 0.5))
model.add(Dense(32, activation = 'softmax'))
model.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['binary_accuracy'])
from keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator()
test_datagen = ImageDataGenerator()
training_set = train_datagen.flow_from_directory(
'TRAIN_SET',
target_size = (IMAGE_LENGHT,IMAGE_LENGHT),
batch_size = 100,
class_mode = 'binary')
test_set = test_datagen.flow_from_directory(
'TEST_SET',
target_size = (IMAGE_LENGHT,IMAGE_LENGHT),
batch_size = 100,
class_mode = 'binary')
checkpoint = ModelCheckpoint(WEIGHTS_PATH, monitor='val_acc', verbose=1, save_best_only=True, mode='max')
model.fit_generator(
training_set,
steps_per_epoch=60,
epochs = EPOCH_COUNT,
validation_data = test_set,
validation_steps =20,
callbacks = [checkpoint])
model.save(MODEL_PATH, True, True)
任何帮助将不胜感激!谢谢!
答案 0 :(得分:0)
原因在这里
model.add(Dense(32, activation = 'softmax'))
在这里
class_mode = 'binary'
导致错误的原因是您的模型需要将输出形状设为(batch_size, 32)
,但是到class_mode = 'binary'
时,您只能得到(batch_size, 1)
。
首先,您需要知道图像是多少类,在这种情况下,TRAIN_SET
中有多少个文件夹,然后将其放入Dense()
中。就像您有7个班级一样
model.add(Dense(7, activation = 'softmax'))
,然后将class_mode = 'binary'
更改为class_mode = 'categorical'
。对于多类分类,您不能像0
是狗1
是猫2
是鸭子而3
是马一样标记,不能将鸭子切成两半得到一只猫或减去一匹马到一只狗。您需要使用one-hot
编码。
第二,关于binary
类,如果您的数据仅是2类,例如猫和狗,那么您可以让模型答案像“这张图片是狗吗”,那么如果是,那是狗还是是错的,是猫。
在这种情况下,您可以使用
model.add(Dense(1, activation = 'sigmoid')) # beware, it's 'sigmoid' here, not 'softmax'
model.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy']) # binary_crossentropy here, not categorical
和
class_mode = 'binary'
One hot就像,让我们定义毒品= 0,恐怖= 1,暴力= 2和性行为= 3,如果答案为violence
,则目标数据将为[0, 0, 1, 0]
。该模型将像[0.1, 0.05, 0.8, 0.05]
那样预测每个类别的概率,而不是实际的数字2。就像我说的那样,您不能将horror
与violence
相加并得到sexual
作为结果您需要分别定义它们,让模型预测这里最可能的类。
当您的每个图像都可以超过1个等级时,将使用二进制精度,例如Emma Watson既可以是女演员,也可以是男人或女人,而这两个等级都不对。输出可能像[1, 0, 1, 1, 0]
,总和不需要为1。但是在您的情况下,它是categorical classification
,而不是binary
,每个图像都是从flow_from_directory
生成的如果您希望它是多类的,则将其标记为categorical
,您仍然可以使用binary_accuracy
并获得相同的结果,但并非出于此目的,以后有人在阅读代码时可能会might头所以我认为在这里使用accuracy
是一个更好的主意。
答案 1 :(得分:0)
您的最后一层有32个单位,您正在使用softmax。因此,您应该拥有超过2个班级。神经网络期望目标为32维,因此您必须通过以下操作对目标形状(1,)进行一次热编码:
import pandas as pd
y_train=pd.get_dummies(target)
然后,通过运行以下命令检查数据维(类数):
y_train.shape[1]
此输出维是目标变量中具有的类数。这样您将拥有:
model.add(Dense(y_train.shape[1], activation = 'softmax'))
我也会更改:
metrics = ['accuracy']
如果您确实有二进制目标,则最后一层应该是:
model.add(Dense(2, activation = 'sigmoid'))
在这种情况下,您还应该将目标变量热编码为(batch_size,number_classes)
。