首页 > 解决方案 > keras 分类器错误评估而学习很棒

问题描述

有小数据集

找到属于 2 个类别的 1836 张图像。找到属于 2 个类别的 986 个图像。

模型的标准架构


image_generator = ImageDataGenerator(
        rescale=1./255,
        validation_split=0.35
    )
    train_data_gen = image_generator.flow_from_directory(
        directory=directory,
        target_size=(IMG_SHAPE, IMG_SHAPE),
        subset='training',
    )
    val_data_gen = image_generator.flow_from_directory(
        directory=directory,
        target_size=(IMG_SHAPE, IMG_SHAPE),
        subset='validation',
    )

---

model = tf.keras.models.Sequential([
                tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(IMG_SHAPE, IMG_SHAPE, 3)),
                tf.keras.layers.MaxPooling2D(2, 2),

                tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
                tf.keras.layers.MaxPooling2D(2, 2),

                tf.keras.layers.Conv2D(128, (3, 3), activation='relu'),
                tf.keras.layers.MaxPooling2D(2, 2),

                tf.keras.layers.Conv2D(128, (3, 3), activation='relu'),
                tf.keras.layers.MaxPooling2D(2, 2),

                tf.keras.layers.Flatten(),
                tf.keras.layers.Dense(512, activation='relu'),
                tf.keras.layers.Dense(2, activation='softmax'),
            ])

            model.compile(
                optimizer='adam',
                loss='categorical_crossentropy',
                metrics=['accuracy']
            )

            BATCH_SIZE = 128
            EPOCHS = 7
           
            total_train, total_val = train_data_gen.samples, val_data_gen.samples

            steps_per_epoch = int(np.ceil(total_train / float(BATCH_SIZE)))
            validation_freq = int(np.ceil(total_val / float(BATCH_SIZE)))

            history = model.fit(
                train_data_gen,
                epochs=EPOCHS,
                steps_per_epoch=steps_per_epoch,
                validation_data=val_data_gen,
                validation_freq=validation_freq
            )

获得完美的指标

Epoch 1/7
15/15 [==============================] - 66s 4s/step - loss: 1.0809 - accuracy: 0.4917
Epoch 2/7
15/15 [==============================] - 56s 4s/step - loss: 0.3475 - accuracy: 0.8729
Epoch 3/7
15/15 [==============================] - 60s 4s/step - loss: 0.1113 - accuracy: 0.9583
Epoch 4/7
15/15 [==============================] - 58s 4s/step - loss: 0.1987 - accuracy: 0.9109
Epoch 5/7
15/15 [==============================] - 59s 4s/step - loss: 0.1127 - accuracy: 0.9438
Epoch 6/7
15/15 [==============================] - 60s 4s/step - loss: 0.0429 - accuracy: 0.9854
Epoch 7/7
15/15 [==============================] - 49s 3s/step - loss: 0.0542 - accuracy: 0.9812

但是在我评估它之后,我完全偏向于一流的结果

它仅在我运行 1 个 epoch 时才有效,但缺乏准确性

评估代码

def make_pred(model, labled_dataset, IMG_SHAPE, img_path) -> LabelName:
    def make_image(img_path):
        # img = img_path.resize((IMG_SHAPE, IMG_SHAPE), Image.ANTIALIAS)
        img = image.load_img(img_path, target_size=(IMG_SHAPE, IMG_SHAPE))
        img = image.img_to_array(img)
        return np.expand_dims(img, axis=0)

    pred_id: List[List] = np.argmax(model.predict(make_image(img_path)), axis=1)
    all_labels = list(labled_dataset.class_indices.keys())
    return all_labels[int(pred_id)]

它有什么问题?

我应该在评估之前缩小源图像吗?

标签: pythontensorflowmachine-learningkerasdeep-learning

解决方案


我相信你需要做两件事。一种是调整您希望预测的图像的大小,然后像对训练图像所做的那样重新调整图像的大小。我还建议您设置 validation_freq=1 以便您可以设置验证损失和准确性的趋势。这使您可以查看模型相对于过度拟合等的表现。如果训练损失继续下降,但在以后的时期您的验证损失开始增加,您可以检测模型是否过度拟合。如果您看到过度拟合,请在密集的 512 节点密集层之后添加一个 Dropout 层。文档在这里。预测准确度应该接近最后一个时期的验证准确度。我还建议您考虑使用 keras 回调 ModelCheckpoint。文档在这里。将其设置为监控验证损失并保存具有最低验证损失的模型。然后加载保存的模型进行预测。最后,我发现使用可调整的学习率是有效的。keras 回调 ReduceLROnPlateau 使这很容易做到。文档在这里。设置它以监控验证丢失。如果在(参数耐心)耐心的 epoch 数之后验证损失未能减少,回调将自动将学习率降低一个因子(参数因子)。我使用因子=.5 和耐心=1。这允许您最初使用较大的学习率,并根据需要降低学习率,这样收敛速度会更快。在您的 val_data_gen 中设置 shuffle=False 中的另一件事,因此每次都以相同的顺序处理验证图像。


推荐阅读