zoukankan      html  css  js  c++  java
  • Keras 最新《面向小数据集构建图像分类模型》

    本文地址:http://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html

    本文作者:Francois Chollet

    • 按照官方的文章实现过程有一些坑,彻底理解代码细节实现,理解keras的api具体使用方法
    • 也有很多人翻译这篇文章,但是有些没有具体实现细节
    • 另外keres开发者自己有本书的jupyter:Companion Jupyter notebooks for the book "Deep Learning with Python"
    • 另外我自己实验三收敛的准确率并没有0.94+,可以参考前面这本书上的实现
    • 文章一共有三个实验:
        1. 第一个实验使用自定义的神经网络对数据集进行训练,三层卷积加两层全连接,训练并验证网络的准确率;
        2. 第二个实验使用VGG16网络对数据进行训练,为了适应自定义的数据集,将VGG16网络的全连接层去掉,作者称之为 “Feature extraction”, 再在上面添加自己实现的全连接层,然后训练并验证网络准确性;
        3. 第三个实验称为 “fine-tune” ,利用第二个实验的实验模型和weight,重新训练VGG16的最后一个卷积层和自定义的全连接层,然后验证网络准确性;
    • 实验二的代码:
    '''This script goes along the blog post
    "Building powerful image classification models using very little data"
    from blog.keras.io.
    It uses data that can be downloaded at:
    https://www.kaggle.com/c/dogs-vs-cats/data
    In our setup, we:
    - created a data/ folder
    - created train/ and validation/ subfolders inside data/
    - created cats/ and dogs/ subfolders inside train/ and validation/
    - put the cat pictures index 0-999 in data/train/cats
    - put the cat pictures index 1000-1400 in data/validation/cats
    - put the dogs pictures index 12500-13499 in data/train/dogs
    - put the dog pictures index 13500-13900 in data/validation/dogs
    So that we have 1000 training examples for each class, and 400 validation examples for each class.
    In summary, this is our directory structure:
    ```
    data/
        train/
            dogs/
                dog001.jpg
                dog002.jpg
                ...
            cats/
                cat001.jpg
                cat002.jpg
                ...
        validation/
            dogs/
                dog001.jpg
                dog002.jpg
                ...
            cats/
                cat001.jpg
                cat002.jpg
                ...
    ```
    '''
    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
    
    # dimensions of our images.
    img_width, img_height = 150, 150
    
    top_model_weights_path = 'bottleneck_fc_model.h5'
    
    
    data_root = 'M:/dataset/dog_cat/'
    train_data_dir =data_root+ 'data/train'
    validation_data_dir = data_root+'data/validation'
    nb_train_samples = 2000
    nb_validation_samples = 800
    epochs = 50
    batch_size = 16
    
    
    def save_bottlebeck_features():
        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=None,
            shuffle=False)
        bottleneck_features_train = model.predict_generator(
            generator, nb_train_samples // batch_size) #####2000//batch_size!!!!!!!!!!
        np.save('bottleneck_features_train.npy',
                bottleneck_features_train)
    
        generator = datagen.flow_from_directory(
            validation_data_dir,
            target_size=(img_width, img_height),
            batch_size=batch_size,
            class_mode=None,
            shuffle=False)
        bottleneck_features_validation = model.predict_generator(
            generator, nb_validation_samples // batch_size)
        np.save('bottleneck_features_validation.npy',
                bottleneck_features_validation)
    
    
    def train_top_model():
        train_data = np.load('bottleneck_features_train.npy')
        train_labels = np.array([0] * int(nb_train_samples / 2) + [1] * int(nb_train_samples / 2))
    
        validation_data = np.load('bottleneck_features_validation.npy')
        validation_labels = np.array([0] * int(nb_validation_samples / 2) + [1] * int(nb_validation_samples / 2))
    
        model = Sequential()
        model.add(Flatten(input_shape=train_data.shape[1:]))
        model.add(Dense(256, activation='relu'))
        model.add(Dropout(0.5))
        model.add(Dense(1, activation='sigmoid'))
    
        model.compile(optimizer='rmsprop',
                      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)
    
    
    #save_bottlebeck_features()
    train_top_model()
    • 实验三代码,自己添加了一些api使用方法,也是以后可以参考的:
    '''This script goes along the blog post
    "Building powerful image classification models using very little data"
    from blog.keras.io.
    It uses data that can be downloaded at:
    https://www.kaggle.com/c/dogs-vs-cats/data
    In our setup, we:
    - created a data/ folder
    - created train/ and validation/ subfolders inside data/
    - created cats/ and dogs/ subfolders inside train/ and validation/
    - put the cat pictures index 0-999 in data/train/cats
    - put the cat pictures index 1000-1400 in data/validation/cats
    - put the dogs pictures index 12500-13499 in data/train/dogs
    - put the dog pictures index 13500-13900 in data/validation/dogs
    So that we have 1000 training examples for each class, and 400 validation examples for each class.
    In summary, this is our directory structure:
    ```
    data/
        train/
            dogs/
                dog001.jpg
                dog002.jpg
                ...
            cats/
                cat001.jpg
                cat002.jpg
                ...
        validation/
            dogs/
                dog001.jpg
                dog002.jpg
                ...
            cats/
                cat001.jpg
                cat002.jpg
                ...
    ```
    '''
    
    # thanks sove bug @http://blog.csdn.net/aggresss/article/details/78588135
    
    from keras import applications
    from keras.preprocessing.image import ImageDataGenerator
    from keras import optimizers
    from keras.models import Sequential
    from keras.layers import Dropout, Flatten, Dense
    from keras.models import Model
    from keras.regularizers import l2
    
    # path to the model weights files.
    weights_path = '../keras/examples/vgg16_weights.h5'
    top_model_weights_path = 'bottleneck_fc_model.h5'
    # dimensions of our images.
    img_width, img_height = 150, 150
    
    data_root = 'M:/dataset/dog_cat/'
    train_data_dir =data_root+ 'data/train'
    validation_data_dir = data_root+'data/validation'
    
    nb_train_samples = 2000
    nb_validation_samples = 800
    epochs = 50
    batch_size = 16
    
    # build the VGG16 network
    base_model = applications.VGG16(weights='imagenet', include_top=False, input_shape=(150,150,3)) # train 指定训练大小
    print('Model loaded.')
    
    # 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:]))  # base_model.output_shape[1:])
    top_model.add(Dense(256, activation='relu',kernel_regularizer=l2(0.001),))
    top_model.add(Dropout(0.8))
    top_model.add(Dense(1, activation='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.add(top_model) # bug
    
    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[:15]:  # :25 bug
        layer.trainable = False
    
    # compile the model with a SGD/momentum optimizer
    # and a very slow learning rate.
    model.compile(loss='binary_crossentropy',
                  optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
                  metrics=['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='binary')
    
    validation_generator = test_datagen.flow_from_directory(
        validation_data_dir,
        target_size=(img_height, img_width),
        batch_size=batch_size,
        class_mode='binary')
    
    model.summary() # prints a summary representation of your model.
    # let's visualize layer names and layer indices to see how many layers
    # we should freeze:
    for i, layer in enumerate(base_model.layers):
        print(i, layer.name)
    
    
    from keras.utils import plot_model
    plot_model(model, to_file='model.png')
    
    from keras.callbacks import History
    from keras.callbacks import ModelCheckpoint
    import keras
    history = History()
    model_checkpoint = ModelCheckpoint('temp_model.hdf5', monitor='loss', save_best_only=True)
    tb_cb = keras.callbacks.TensorBoard(log_dir='log', write_images=1, histogram_freq=0)
    # 设置log的存储位置,将网络权值以图片格式保持在tensorboard中显示,设置每一个周期计算一次网络的
    # 权值,每层输出值的分布直方图
    callbacks = [
            history,
            model_checkpoint,
            tb_cb
        ]
    # model.fit()
    
    
    # fine-tune the model
    history=model.fit_generator(
        train_generator,
        steps_per_epoch=nb_train_samples // batch_size,
        epochs=epochs,
        callbacks=callbacks,
        validation_data=validation_generator,
        validation_steps=nb_validation_samples // batch_size,
        verbose = 2)
    
    model.save('fine_tune_model.h5')
    model.save_weights('fine_tune_model_weight')
    print(history.history)
    
    
    from matplotlib import pyplot as plt
    history=history
    plt.plot()
    plt.plot(history.history['val_acc'])
    plt.title('model accuracy')
    plt.ylabel('accuracy')
    plt.xlabel('epoch')
    plt.legend(['train', 'test'], loc='upper left')
    plt.show()
    # summarize history for loss
    plt.plot(history.history['loss'])
    plt.plot(history.history['val_loss'])
    plt.title('model loss')
    plt.ylabel('loss')
    plt.xlabel('epoch')
    plt.legend(['train', 'test'], loc='upper left')
    plt.show()
    
    import  numpy as np
    accy=history.history['acc']
    np_accy=np.array(accy)
    np.savetxt('save_acc.txt',np_accy)
    • result
    Model loaded.
    Found 2000 images belonging to 2 classes.
    Found 800 images belonging to 2 classes.
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    input_1 (InputLayer)         (None, 150, 150, 3)       0         
    _________________________________________________________________
    block1_conv1 (Conv2D)        (None, 150, 150, 64)      1792      
    _________________________________________________________________
    block1_conv2 (Conv2D)        (None, 150, 150, 64)      36928     
    _________________________________________________________________
    block1_pool (MaxPooling2D)   (None, 75, 75, 64)        0         
    _________________________________________________________________
    block2_conv1 (Conv2D)        (None, 75, 75, 128)       73856     
    _________________________________________________________________
    block2_conv2 (Conv2D)        (None, 75, 75, 128)       147584    
    _________________________________________________________________
    block2_pool (MaxPooling2D)   (None, 37, 37, 128)       0         
    _________________________________________________________________
    block3_conv1 (Conv2D)        (None, 37, 37, 256)       295168    
    _________________________________________________________________
    block3_conv2 (Conv2D)        (None, 37, 37, 256)       590080    
    _________________________________________________________________
    block3_conv3 (Conv2D)        (None, 37, 37, 256)       590080    
    _________________________________________________________________
    block3_pool (MaxPooling2D)   (None, 18, 18, 256)       0         
    _________________________________________________________________
    block4_conv1 (Conv2D)        (None, 18, 18, 512)       1180160   
    _________________________________________________________________
    block4_conv2 (Conv2D)        (None, 18, 18, 512)       2359808   
    _________________________________________________________________
    block4_conv3 (Conv2D)        (None, 18, 18, 512)       2359808   
    _________________________________________________________________
    block4_pool (MaxPooling2D)   (None, 9, 9, 512)         0         
    _________________________________________________________________
    block5_conv1 (Conv2D)        (None, 9, 9, 512)         2359808   
    _________________________________________________________________
    block5_conv2 (Conv2D)        (None, 9, 9, 512)         2359808   
    _________________________________________________________________
    block5_conv3 (Conv2D)        (None, 9, 9, 512)         2359808   
    _________________________________________________________________
    block5_pool (MaxPooling2D)   (None, 4, 4, 512)         0         
    _________________________________________________________________
    sequential_1 (Sequential)    (None, 1)                 2097665   
    =================================================================
    Total params: 16,812,353
    Trainable params: 9,177,089
    Non-trainable params: 7,635,264
    _________________________________________________________________
    0 input_1
    1 block1_conv1
    2 block1_conv2
    3 block1_pool
    4 block2_conv1
    5 block2_conv2
    6 block2_pool
    7 block3_conv1
    8 block3_conv2
    9 block3_conv3
    10 block3_pool
    11 block4_conv1
    12 block4_conv2
    13 block4_conv3
    14 block4_pool
    15 block5_conv1
    16 block5_conv2
    17 block5_conv3
    18 block5_pool
    Backend TkAgg is interactive backend. Turning interactive mode on.
  • 相关阅读:
    iPhone X 适配手机端 H5 页面通用解决方案
    创建cordova项目
    UltraEdit mac破解版
    ionic 和cordova的区别是什么
    还在为AndroidStudio的Gradle版本配置头疼?看看老司机的解决方法吧
    java final
    死锁产生的条件+排除死锁的方法
    String str=new String("a")和String str = "a"有什么区别?
    重载和覆盖的区别?(overload vs override)
    深拷贝和浅拷贝
  • 原文地址:https://www.cnblogs.com/ranjiewen/p/8024940.html
Copyright © 2011-2022 走看看