keras预测总是在多分类中输出相同的值

Sun*_*gke 6 python machine-learning neural-network deep-learning keras

这是我的代码.我想使用Keras进行多分类.训练时vcl_acc更好,但预测值总是相同的值.我很困惑,请帮助我

train.py

# coding: UTF-8
# author: Sun Yongke (sunyongke@gmail.com)
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import EarlyStopping
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.optimizers import SGD


# Dense(64) is a fully-connected layer with 64 hidden units.
# in the first layer, you must specify the expected input data shape:
# here, 20-dimensional vectors.

# dimensions of our images.
img_width, img_height = 300, 300
nb_epoch=20

train_data_dir = '../picture/samples_300_2/train'
validation_data_dir = '../picture/samples_300_2/validation'
# this is the augmentation configuration we will use for training
train_datagen = ImageDataGenerator(
    rescale=1./255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)

# this is the augmentation configuration we will use for testing:
# only rescaling
test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_width, img_height),
    batch_size=40000,
    color_mode='grayscale',
    save_format="jpg",
    save_to_dir="after/train",
    class_mode='categorical')

validation_generator = test_datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_width, img_height),
    batch_size=500,
    color_mode='grayscale',
    save_format="jpg",
    save_to_dir="after/test",
    class_mode='categorical')

model = Sequential()
# input: 100x100 images with 3 channels -> (3, 100, 100) tensors.
# this applies 32 convolution filters of size 3x3 each.
model.add(Convolution2D(32, 3, 3, border_mode='valid', input_shape=(img_width, img_height,1)))
model.add(Activation('relu'))
model.add(Convolution2D(32, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Convolution2D(64, 3, 3, border_mode='valid'))
model.add(Activation('relu'))
model.add(Convolution2D(64, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Flatten())
# Note: Keras does automatic shape inference.
model.add(Dense(256))
model.add(Activation('relu'))
model.add(Dropout(0.5))

model.add(Dense(14))
model.add(Activation('softmax'))

sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd)

nb_train_samples=len(train_generator.filenames)
nb_validation_samples=len(validation_generator.filenames)

early_stopping = EarlyStopping(monitor='val_loss', patience=2)

model.fit_generator(
    train_generator,
    samples_per_epoch=nb_train_samples,
    nb_epoch=nb_epoch,
    validation_data=validation_generator,
    nb_val_samples=nb_validation_samples, callbacks=[early_stopping])
#save model
model.save("sykm.2.h5")
Run Code Online (Sandbox Code Playgroud)

培训产出如下

Epoch 2/50
3005/3005 [==============================] - 270s - loss: 0.2227 - acc: 0.9294 - val_loss: 0.1985 - val_acc: 0.9316
Epoch 3/50
3005/3005 [==============================] - 269s - loss: 0.2105 - acc: 0.9310 - val_loss: 0.1858 - val_acc: 0.9338
Epoch 4/50
3005/3005 [==============================] - 271s - loss: 0.1964 - acc: 0.9333 - val_loss: 0.3572 - val_acc: 0.9160
Epoch 5/50
3005/3005 [==============================] - 268s - loss: 0.1881 - acc: 0.9349 - val_loss: 0.1513 - val_acc: 0.9413
Epoch 6/50
3005/3005 [==============================] - 268s - loss: 0.1935 - acc: 0.9342 - val_loss: 0.1581 - val_acc: 0.936
Run Code Online (Sandbox Code Playgroud)

predict.py

# coding: UTF-8
# author: Sun Yongke (sunyongke@gmail.com)
from keras.models import load_model
model = load_model('sykm.2.h5')
img_width, img_height = 300, 300


from keras.preprocessing.image import ImageDataGenerator
test_datagen = ImageDataGenerator(rescale=1./255)
validation_data_dir = 'samples_300/validation'
validation_generator = test_datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_width, img_height),
    batch_size=32,
    class_mode='categorical')
nb_validation_samples=len(validation_generator.filenames)



out=model.predict_generator(validation_generator,nb_validation_samples)

print "out"
print out
Run Code Online (Sandbox Code Playgroud)

输出总是相同的,即使我使用不同的图片测试如下

Using TensorFlow backend.
Found 60 images belonging to 2 classes.
out
[[ 0.06170857  0.06522226  0.06400252  0.08250671  0.07548683      0.07643672
0.07131153  0.07487586  0.07607967  0.04719007  0.07641899  0.08824327
0.05421595  0.08630092]
[ 0.06170857  0.06522226  0.06400252  0.08250671  0.07548683 0.07643672
0.07131153  0.07487586  0.07607967  0.04719007  0.07641899  0.08824327
0.05421595  0.08630092]
....]
Run Code Online (Sandbox Code Playgroud)

ASR*_*igo 9

好吧,在寻找解决方案的 1 个月后,我尝试了一切:降低学习率,更改优化器,使用更大的数据集,增加和减少模型复杂性,将输入形状更改为越来越小的图像,将导入从from keras import更改为from tensorflow.keras import和更进一步from tensorflow.python.keras import,改变每一层的激活函数,组合它们,尝试其他数据集等......没有任何帮助。即使我使用像 VGG16/19 这样的网络,我的结果也是一样的。但是,昨天,我正在阅读一本书(使用 Keras 进行深度学习 - Antonio Gulli,Sujit Pal),我意识到汽车人使用这样的导入:

from keras.layers.core import Dense, Flatten, Dropout
Run Code Online (Sandbox Code Playgroud)

而不是这样:

from keras.layers import Dense, Flatten, Dropout
Run Code Online (Sandbox Code Playgroud)

Conv 也是如此,我使用的是:

from keras.layers import Conv2D, MaxPooling2D, SeparableConv2D
Run Code Online (Sandbox Code Playgroud)

和汽车人使用:

from keras.layers.convolutional import Conv2D, MaxPooling2D, SeparableConv2D
Run Code Online (Sandbox Code Playgroud)

当我更改导入时,一切终于开始工作了!我不知道这是一个错误还是类似的东西,因为现在我的模型即使在预测同一类的数据集中也总是有效。所以现在我正在使用这样的导入,例如:

from keras.layers.core import Dense, Dropout, Flatten
from keras.layers.convolutional import Conv2D, MaxPooling2D, SeparableConv2D
Run Code Online (Sandbox Code Playgroud)

试试这个,如果不起作用,看看你的数据集是否平衡,例如,如果你的问题是对猫和狗的图像进行分类,并且你有 200 张猫图像和 800 张狗图像,请尝试使用一些不那么不同的图像因为它可能会导致问题:如果我说 10/10 图像是狗,你的模型可以“思考”好,所以我得到 80% 的准确率,但这不是我们想要的。您可以使用class_weight,如果你没有更多的图片来平衡你的数据集,一切都会好的,你可以如用数据增强。你也可以使用回调,比如ReduceLROnPlateau当你的损失没有降低时降低你的学习率。您可以增加您的batch_size,不要忘记对您的数据进行洗牌ImageDataGenerator并标准化您的图像,如下所示:

g2 = ImageDataGenerator(rescale=1./255)
Run Code Online (Sandbox Code Playgroud)

所有这些事情都非常重要,但没有什么能真正帮助我。唯一有效的是导入keras.layers.corekeras.layers.convolutional,这也可以帮助您!


Mar*_*jko 6

您的问题似乎是由数据集中的巨大类不平衡引起的.可以看出,0为每个示例分配一个类可以提供超过90%的准确性.为了解决这个问题,您可以使用以下策略:

  1. 重新平衡数据集:通过对较不频繁的类进行上采样或对较频繁的类进行下采样.

  2. 调整班级权重:通过为较不频繁的班级设置较高的班级权重,您将推广您的网络培训,以便更多地关注下采样班级.

  3. 增加培训时间:在许多情况下 - 经过较长时间的培训,网络开始更多地集中在不太频繁的课程上.

  • 我有一个完美平衡的数据集,但仍然遇到同样的问题。当我得到 80 的验证准确度时,它变得更加尴尬(考虑到它只预测一个类,数据大约为 %50 %50,但我以某种方式获得 %80 的准确度,这很尴尬)无法弄清楚为什么 https://stackoverflow.com /questions/57960757/为什么我的模型预测相同的标签 (2认同)