使用 categorial_crossentropy 在 keras 中训练模型

数据挖掘 机器学习 Python 深度学习 喀拉斯
2022-03-09 02:19:12

我是机器学习的新手。我正在关注这个Keras 博客来使用 Keras 训练图像分类器。尽管此博客仅演示了如何使用 binary_crossentropy 仅训练两个类,但我希望使用我自己的自定义多类 (6) 图像数据集使用 categorial_crossentropy 和一个热编码向量来训练模型。所以,这是我到目前为止所尝试的:

import os
import numpy as np
from keras import applications
from keras import Model
from keras.models import Sequential
from keras.layers import Activation, Dropout, Flatten, Dense
from keras.layers import Input
from keras.preprocessing.image import ImageDataGenerator, img_to_array, load_img
from keras import optimizers
import cv2


img_width, img_height = 150, 150

class_indics = 'class_indices.npy'
bottleneck_train_path = 'bottleneck_features_train.npy'
bottleneck_validation_path = 'bottleneck_features_validation.npy'
top_model_weights_path = 'bottleneck_fc_model.h5'
train_data_dir = 'data/train'
validation_data_dir = 'data/validation/'

nb_train_samples = 4800
nb_validation_samples = 1200

epochs = 50
batch_size = 15


def generate_class_indics():
    datagen = ImageDataGenerator(rescale=1. / 255)

    generator_top = datagen.flow_from_directory(train_data_dir,
                                                    target_size=(img_width, img_height),
                                                    batch_size=batch_size,
                                                    class_mode='categorical',
                                                    shuffle=False)

    # save the class indices to use later in predictions
    np.save(class_indics, generator_top.class_indices)

def save_bottleneck_features():
    print('Using of bottleneck feature on pretrained model started.')
    datagen = ImageDataGenerator(rescale=1. / 255)

    # build the VGG16 network
    model = applications.VGG16(include_top=False, weights='imagenet')

    generator = datagen.flow_from_directory(
        train_data_dir,
        target_size=(img_width, img_height),
        batch_size=batch_size,
        class_mode='categorical',
        shuffle=False)
    bottleneck_features_train = model.predict_generator(
        generator, nb_train_samples // batch_size)
    np.save(open(bottleneck_train_path, 'wb'),
            bottleneck_features_train)

    generator = datagen.flow_from_directory(
        validation_data_dir,
        target_size=(img_width, img_height),
        batch_size=batch_size,
        class_mode='categorical',
        shuffle=False)
    bottleneck_features_validation = model.predict_generator(
        generator, nb_validation_samples // batch_size)
    np.save(open(bottleneck_validation_path, 'wb'),
            bottleneck_features_validation)
    print('Using of bottleneck feature on pretrained model finished.')


def train_top_model():
    print('Training of top model started.')
    train_data = np.load(open(bottleneck_train_path, 'rb'))
    train_labels = np.array(
        [0] * (nb_train_samples // 2) + [1] * (nb_train_samples // 2))

    validation_data = np.load(open(bottleneck_validation_path, 'rb'))
    validation_labels = np.array(
        [0] * (nb_validation_samples // 2) + [1] * (nb_validation_samples // 2))

    class_dictionary = np.load('class_indices.npy').item()
    num_classes = len(class_dictionary)

    model = Sequential()
    model.add(Flatten(input_shape=train_data.shape[1:]))
    model.add(Dense(256, activation='relu'))
    model.add(Dropout(0.7))
    model.add(Dense(num_classes, activation='softmax')) #sigmoid

    model.compile(optimizer='rmsprop',
                  loss='categorical_crossentropy', metrics=['categorical_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)
    print('Training of top model completed & saved as: ',top_model_weights_path)


def fine_tune_pretrained_model():
    print('Fine tuning of pretrain model started.')
    # build the VGG16 network
    input_tensor = Input(shape=(150, 150, 3))

    base_model = applications.VGG16(weights='imagenet', include_top=False, input_tensor=input_tensor)

    class_dictionary = np.load('class_indices.npy').item()
    num_classes = len(class_dictionary)

    # build a classifier model to put on top of the convolutional model
    top_model = Sequential()
    top_model.add(Flatten(input_shape=base_model.output_shape[1:]))
    top_model.add(Dense(256, activation='relu'))
    top_model.add(Dropout(0.7))
    top_model.add(Dense(num_classes, activation='softmax')) #sigmoid

    # note that it is necessary to start with a fully-trained
    # classifier, including the top classifier,
    # in order to successfully do fine-tuning
    top_model.load_weights(top_model_weights_path)

    # add the model on top of the convolutional base
    model = Model(inputs=base_model.input, outputs=top_model(base_model.output))

    # set the first 25 layers (up to the last conv block)
    # to non-trainable (weights will not be updated)
    for layer in model.layers[:25]:
        layer.trainable = False

    # compile the model with a SGD/momentum optimizer
    # and a very slow learning rate.
    model.compile(loss='categorical_crossentropy',
                  optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
                  metrics=['categorical_accuracy'])

    # prepare data augmentation configuration
    train_datagen = ImageDataGenerator(
        rescale=1. / 255,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True)

    test_datagen = ImageDataGenerator(rescale=1. / 255)

    train_generator = train_datagen.flow_from_directory(
        train_data_dir,
        target_size=(img_height, img_width),
        batch_size=batch_size,
        class_mode='categorical')

    validation_generator = test_datagen.flow_from_directory(
        validation_data_dir,
        target_size=(img_height, img_width),
        batch_size=batch_size,
        class_mode='categorical')

    # fine-tune the model
    model.fit_generator(
        train_generator,
        steps_per_epoch=nb_train_samples // batch_size, # samples_per_epoch=nb_train_samples,
        epochs=epochs,
        validation_data=validation_generator,
        validation_steps=nb_validation_samples)

    print('Fine tuning of pretrain model completed.')

if __name__ == '__main__':

    if not os.path.exists(class_indics):
        generate_class_indics()

    if not os.path.exists(bottleneck_train_path):
        save_bottleneck_features()

    if not os.path.exists(top_model_weights_path):
        train_top_model()
        fine_tune_pretrained_model()

当我运行此代码save_bottleneck_features()train_top_model()正确执行时,但是当我尝试运行时,fine_tune_pretrained_model()它给了我这个错误:

回溯(最近一次调用最后):文件“/home/appsbee/PycharmProjects/fruit-classification-master/fruit-classification-master/fruit_classification_new.py”,第 266 行,在fine_tune_pretrained_model() 文件“/home/appsbee/PycharmProjects/ fruit-classification-master/fruit-classification-master/fruit_classification_new.py”,第 159 行,fine_tune_pretrained_model top_model.load_weights(top_model_weights_path) 文件“/usr/local/lib/python3.6/dist-packages/keras/engine/network .py”,第 1166 行,在 load_weights f,self.layers,reshape=reshape) 文件“/usr/local/lib/python3.6/dist-packages/keras/engine/saving.py”,第 1036 行,在 load_weights_from_hdf5_group str(len(filtered_layers)) + 'layers.') ValueError:您正在尝试将包含 3 层的权重文件加载到具有 2 层的模型中。

但我可以看到没有添加额外的图层fine_tune_pretrained_model()
那么,为什么我会收到此错误?任何帮助将不胜感激。

1个回答

您实际上不需要定义模型架构,然后使用model.load_weightsAPI 加载权重。您可以改为让 Keras 从您的 h5 文件中加载具有架构和权重的模型:

model = keras.models.load_model('bottleneck_fc_model.h5')

然后查看架构:

print(model.summary())

然后,您可以使用model.addAPI 在顶部添加更多层。

当然,只有在训练后使用model.save而不是model.save_weights之前保存模型时,才能使用它。