我有一个与转学习和VGG16 NN相关的非常简单的问题。
这是我的代码:
import numpy as np
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Dropout, Flatten, Dense
from keras import applications
from keras import optimizers
from keras.applications.vgg16 import VGG16
from keras.applications.vgg16 import preprocess_input
img_width, img_height = 150, 150
top_model_weights_path = 'full_hrct_model_weights.h5'
train_dir = 'hrct_data_small/train'
validation_dir = 'hrct_data_small/validation'
nb_train_samples = 3000
nb_validation_samples = 600
epochs = 50
batch_size = 20
def save_bottleneck_features():
datagen = ImageDataGenerator(rescale=1. / 255)
# build the vgg16 model
model = applications.VGG16(include_top=False, weights='imagenet')
generator = datagen.flow_from_directory(
train_dir,
target_size=(img_width, img_height),
shuffle=False,
class_mode=None,
batch_size=batch_size
)
bottleneck_features_train = model.predict_generator(generator=generator, steps=nb_train_samples // batch_size)
np.save(file="bottleneck_features_train_ternary_class.npy", arr=bottleneck_features_train)
generator = datagen.flow_from_directory(
validation_dir,
target_size=(img_width, img_height),
shuffle=False,
class_mode=None,
batch_size=batch_size,
)
bottleneck_features_validation = model.predict_generator(generator, nb_validation_samples // batch_size)
np.save(file="bottleneck_features_validate_ternary_class.npy", arr=bottleneck_features_validation)
save_bottleneck_features()
"找到属于3个班级的3000张图片。"
"找到属于3个班级的600张图片。"
def train_top_model():
train_data = np.load(file="bottleneck_features_train_ternary_class.npy")
train_labels = np.array([0] * (nb_train_samples // 2) + [1] * (nb_train_samples // 2))
validation_data = np.load(file="bottleneck_features_validate_ternary_class.npy")
validation_labels = np.array([0] * (nb_validation_samples // 2) + [1] * (nb_validation_samples // 2))
model = Sequential()
model.add(Flatten(input_shape=train_data.shape[1:])) # don't need to tell batch size in input shape
model.add(Dense(256, activation='relu'))
model.add(Dense(3, activation='sigmoid'))
print(model.summary)
model.compile(optimizer='Adam', loss='binary_crossentropy', metrics=['accuracy'])
model.fit(train_data, train_labels,
epochs=epochs,
batch_size=batch_size,
validation_data=(validation_data, validation_labels))
model.save_weights(top_model_weights_path)
train_top_model()
我得到的错误是:
ValueError Traceback (most recent call last)
<ipython-input-52-33db5c28e162> in <module>()
2 epochs=epochs,
3 batch_size=batch_size,
----> 4 validation_data=(validation_data, validation_labels))
/Users/simonalice/anaconda/lib/python3.5/site-packages/keras/models.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, **kwargs)
854 class_weight=class_weight,
855 sample_weight=sample_weight,
--> 856 initial_epoch=initial_epoch)
857
858 def evaluate(self, x, y, batch_size=32, verbose=1,
/Users/simonalice/anaconda/lib/python3.5/site-packages/keras/engine/training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, **kwargs)
1427 class_weight=class_weight,
1428 check_batch_axis=False,
-> 1429 batch_size=batch_size)
1430 # Prepare validation data.
1431 if validation_data:
/Users/simonalice/anaconda/lib/python3.5/site-packages/keras/engine/training.py in _standardize_user_data(self, x, y, sample_weight, class_weight, check_batch_axis, batch_size)
1307 output_shapes,
1308 check_batch_axis=False,
-> 1309 exception_prefix='target')
1310 sample_weights = _standardize_sample_weights(sample_weight,
1311 self._feed_output_names)
/Users/simonalice/anaconda/lib/python3.5/site-packages/keras/engine/training.py in _standardize_input_data(data, names, shapes, check_batch_axis, exception_prefix)
137 ' to have shape ' + str(shapes[i]) +
138 ' but got array with shape ' +
--> 139 str(array.shape))
140 return arrays
141
ValueError: Error when checking target: expected dense_32 to have shape (None, 3) but got array with shape (3000, 1)
以下是模型摘要:
Layer (type) Output Shape Param #
=================================================================
flatten_16 (Flatten) (None, 8192) 0
_________________________________________________________________
dense_31 (Dense) (None, 256) 2097408
_________________________________________________________________
dropout_16 (Dropout) (None, 256) 0
_________________________________________________________________
dense_32 (Dense) (None, 3) 771
=================================================================
Total params: 2,098,179
Trainable params: 2,098,179
Non-trainable params: 0
我的困难突出了我怀疑的一个根本性的误解,但我需要一些非常直接的解释。我在这次培训中有3节课。 &#39; hrct_data_small /列车&#39;包含3个文件夹和&#39; hrct_data_small / validation&#39;包含3个文件夹。
首先:我认为顶级模型的最后一层是正确的:
model.add(Dense(3, activation='sigmoid'))
应该是&#34; 3&#34;因为我有3节课。
第二
我抓住了数据形状进行调查
train_data = np.load(file="bottleneck_features_train_ternary_class.npy")
train_labels = np.array([0] * (nb_train_samples // 2) + [1] * (nb_train_samples // 2))
validation_data =np.load(file="bottleneck_features_validate_ternary_class.npy")
validation_labels = np.array([0] * (nb_validation_samples // 2) + [1] * (nb_validation_samples // 2))
然后
print("Train data shape", train_data.shape)
print("Train_labels shape", train_labels.shape)
print("Validation_data shape", validation_labels.shape)
print("Validation_labels", validation_labels.shape)
结果是
Train data shape (3000, 4, 4, 512)
Train_labels shape (3000,)
Validation_data shape (600,)
Validation_labels (600,)
所以,如果&#34;训练数据形状&#34;变量形状(3000,3)。
我对这些基本问题表示道歉 - 如果我能够对此做一些清晰的思考,我将不胜感激。
编辑:感谢下面Naseem的建议,我解决了他的所有观点,除了:
train_data按顺序返回训练数据,因此第一类(1000)然后第二类(1000)和第三类(1000)。因此train_labels必须按顺序排列:
train_data = np.load(file="bottleneck_features_train_ternary_class.npy")
train_labels = np.array([0] * 1000 + [1] * 1000 + [2] * 1000)
validation_data = np.load(file="bottleneck_features_validate_ternary_class.npy")
validation_labels = np.array([0] * 400 + [1] * 400 + [2] * 400)
然后我按照这样修改了标签:
train_labels = np_utils.to_categorical(train_labels, 3)
validation_labels = np_utils.to_categorical(validation_labels, 3)
将标签设置为正确的形状并对其进行单热编码。我检查了前几个,他们是正确的。然后该模型起作用。
作为补充评论 - 所有答案都在Keras文档中。如果我花了更多的时间阅读并减少了剪切和粘贴代码的时间,我就会把它弄好。学过的知识。
答案 0 :(得分:5)
我不确定这会清除你的一切,但是我在你的代码中看到了一些错误:
您创建标签的方式对我来说非常奇怪。为什么你把一半数据作为0而另一半作为1:
train_labels = np.array([0] * (nb_train_samples // 2) + [1] * (nb_train_samples // 2))
这似乎不对。您需要更多地解释您想要预测的内容。通常你的标签应该用生成器生成并设置class_mode='categorical'
而不是class_mode=None
这将使生成器输出输入和目标,并且目标将是一个长度为3的热编码向量的系列。 / p>
您使用的损失是loss='binary_crossentropy'
。当您对可以分为多个类别的图像进行分类时,或者当您只有2种类的可能性时,可以使用此方法。这不是你的情况(如果我理解正确的话)。您应该使用:loss='categorical_crossentropy'
。这是当每个图像具有一个且不超过一个类作为目标时。
这与前一点相关联,即最后一层的激活:model.add(Dense(3, activation='sigmoid'))
。 sigmoid将允许您的输出为[1 1 0]或[1 1 1]或[0 0 0],这些是无效的,因为在您的情况下您只想预测一个类,您不希望您的图像被归类为属于3类。我们在这个分类案例中使用的是softmax。 softmax将对输出进行归一化,使它们总和为1.您现在可以将输出解释为概率:[0.1 0.2 0.7],图像有10%的概率属于第一类,20%属于第二类,70 %到第三个。所以我会改为:model.add(Dense(3, activation='softmax'))
总而言之,网络抱怨是因为对于每个图像,它期望您提供的目标是长度为3的单热矢量,编码图像所属的类。你目前正在喂它的只是一个数字0或1.
它更有意义吗?