zoukankan      html  css  js  c++  java
  • Kaggle比赛NCFM图像分类任务简介

    为了保护和监控海洋环境及生态平衡,大自然保护协会(The Nature Conservancy)邀请Kaggle社区的参赛者们开发能够出机器学习算法,自动分类和识别远洋捕捞船上的摄像头拍摄到的图片中鱼类的品种,例如不同种类的吞拿鱼和鲨鱼。大自然保护协会一共提供了3777张标注的图片作为训练集,这些图片被分为了8类,其中7类是不同种类的海鱼,剩余1类则是不含有鱼的图片,每张图片只属于8类中的某一类别。

    图片中待识别的海鱼所占整张图片的一小部分,这就给识别带来了很大的挑战性。此外,为了衡量算法的有效性,还提供了额外的1000张图片作为测试集,参赛者们需要设计出一种图像识别的算法,尽可能地识别出这1000张测试图片属于8类中的哪一类别。Kaggle平台为每一个竞赛都提供了一个榜单(Leaderboard),识别的准确率越高的竞赛者在榜单上的排名越靠前。

    split_train_val.py

    import os
    import numpy as np
    import shutil
    
    np.random.seed(2016)
    
    root_train = 'data\train_split'
    root_val = 'data\val_split'
    
    root_total = 'data\train'
    
    FishNames = ['ALB', 'BET', 'DOL', 'LAG', 'NoF', 'OTHER', 'SHARK', 'YFT']
    
    nbr_train_samples = 0
    nbr_val_samples = 0
    # 训练集所占比例
    split_proportion = 0.8
    
    for fish in FishNames:
        if not os.path.exists(root_train):
            os.mkdir(root_train)
        if not os.path.exists(root_val):
            os.mkdir(root_val)
    
        # 建立各个类别的文件夹
        if fish not in os.listdir(root_train):
            os.mkdir(os.path.join(root_train, fish))
        # 当前类别所有的图片
        total_images = os.listdir(os.path.join(root_total, fish))
        # 训练集中图片的数量
        nbr_train = int(len(total_images) * split_proportion)
        # 打乱数据集
        np.random.shuffle(total_images)
        # 划分出训练集
        train_images = total_images[:nbr_train]
        # 划分出测试集
        val_images = total_images[nbr_train:]
    
        for img in train_images:
            # 从train文件夹将图片拷贝至train_split文件夹下
            source = os.path.join(root_total, fish, img)
            target = os.path.join(root_train, fish, img)
            shutil.copy(source, target)
            nbr_train_samples += 1
    
        if fish not in os.listdir(root_val):
            os.mkdir(os.path.join(root_val, fish))
    
        for img in val_images:
            # 从train文件夹将图片拷贝至val_split文件夹下
            source = os.path.join(root_total, fish, img)
            target = os.path.join(root_val, fish, img)
            shutil.copy(source, target)
            nbr_val_samples += 1
    
    print('Finish splitting train and val images!')
    print('# training samples: {}, # val samples: {}'.format(nbr_train_samples, nbr_val_samples))
    
    

    ImageDataGenerator()是keras.preprocessing.image模块中的图片生成器,同时也可以在batch中对数据进行增强,扩充数据集大小,增强模型的泛化能力。比如进行旋转,变形,归一化等等。

    参数:

    • rescale: rescaling factor. Defaults to None.If None or 0, no rescaling is applied,otherwise we multiply the data by the value provided
    • featurewise_center: Boolean. 对输入的图片每个通道减去每个通道对应均值。
    • samplewise_center: Boolan. 每张图片减去样本均值, 使得每个样本均值为0。
    • featurewise_std_normalization(): Boolean()
    • samplewise_std_normalization(): Boolean()
    • zca_epsilon(): Default 12-6
    • zca_whitening: Boolean. 去除样本之间的相关性
    • rotation_range(): 旋转范围
    • width_shift_range(): 水平平移范围
    • height_shift_range(): 垂直平移范围
    • shear_range(): float, 透视变换的范围
    • zoom_range(): 缩放范围
    • fill_mode: 填充模式, constant, nearest, reflect
    • cval: fill_mode == 'constant'的时候填充值
    • horizontal_flip(): 水平反转
    • vertical_flip(): 垂直翻转
    • preprocessing_function(): user提供的处理函数
    • data_format(): channels_first或者channels_last
    • validation_split(): 多少数据用于验证集

    方法:

    • apply_transform(x, transform_parameters):根据参数对x进行变换
    • fit(x, augment=False, rounds=1, seed=None): 将生成器用于数据x,从数据x中获得样本的统计参数, 只有featurewise_center, featurewise_std_normalization或者zca_whitening为True才需要
    • flow(x, y=None, batch_size=32, shuffle=True, sample_weight=None, seed=None, save_to_dir=None, save_prefix='', save_format='png', subset=None) ):按batch_size大小从x,y生成增强数据
    • flow_from_directory()从路径生成增强数据,和flow方法相比最大的优点在于不用一次将所有的数据读入内存当中,这样减小内存压力,这样不会发生OOM,血的教训。
    • get_random_transform(img_shape, seed=None): 返回包含随机图像变换参数的字典
    • random_transform(x, seed=None): 进行随机图像变换, 通过设置seed可以达到同步变换。
    • standardize(x): 对x进行归一化

    train.py

    from keras.applications.inception_v3 import InceptionV3
    from keras.layers import Flatten, Dense, AveragePooling2D
    from keras.models import Model
    from keras.optimizers import RMSprop, SGD
    from keras.callbacks import ModelCheckpoint
    from keras.preprocessing.image import ImageDataGenerator
    
    # 超参数
    learning_rate = 0.0001
    img_width = 299
    img_height = 299
    nbr_train_samples = 3019
    nbr_validation_samples = 758
    # nbr_epochs = 25
    nbr_epochs = 1
    batch_size = 32
    
    # 训练集和测试集路径
    train_data_dir = 'data\train_split'
    val_data_dir = 'data\val_split'
    
    # 类别
    FishNames = ['ALB', 'BET', 'DOL', 'LAG', 'NoF', 'OTHER', 'SHARK', 'YFT']
    
    # 加载InceptionV3模型
    print('Loading InceptionV3 Weights ...')
    InceptionV3_notop = InceptionV3(include_top=False, weights='imagenet', input_tensor=None, input_shape=(299, 299, 3))
    # Note that the preprocessing of InceptionV3 is: (x / 255 - 0.5) x 2
    
    # 添加平均池化层和Softmax输出层
    print('Adding Average Pooling Layer and Softmax Output Layer ...')
    # Shape: (8, 8, 2048)
    output = InceptionV3_notop.get_layer(index=-1).output
    output = AveragePooling2D((8, 8), strides=(8, 8), name='avg_pool')(output)
    output = Flatten(name='flatten')(output)
    output = Dense(8, activation='softmax', name='predictions')(output)
    
    InceptionV3_model = Model(InceptionV3_notop.input, output)
    print(InceptionV3_model.summary())
    
    # 使用梯度下降优化模型
    optimizer = SGD(lr=learning_rate, momentum=0.9, decay=0.0, nesterov=True)
    # 模型编译
    InceptionV3_model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy'])
    # 自动保存最佳模型
    best_model_file = "./weights.h5"
    best_model = ModelCheckpoint(best_model_file, monitor='val_acc', verbose=1, save_best_only=True)
    
    # 训练集数据扩增配置
    train_datagen = ImageDataGenerator(
        rescale=1. / 255,
        shear_range=0.1,
        zoom_range=0.1,
        rotation_range=10.,
        width_shift_range=0.1,
        height_shift_range=0.1,
        horizontal_flip=True)
    
    # 验证集数据扩增配置
    val_datagen = ImageDataGenerator(rescale=1. / 255)
    
    train_generator = train_datagen.flow_from_directory(
        train_data_dir,
        target_size=(img_width, img_height),
        batch_size=batch_size,
        shuffle=True,
        classes=FishNames,
        class_mode='categorical')
    
    validation_generator = val_datagen.flow_from_directory(
        val_data_dir,
        target_size=(img_width, img_height),
        batch_size=batch_size,
        shuffle=True,
        classes=FishNames,
        class_mode='categorical')
    
    InceptionV3_model.fit_generator(
        train_generator,
        samples_per_epoch=nbr_train_samples,
        nb_epoch=nbr_epochs,
        validation_data=validation_generator,
        nb_val_samples=nbr_validation_samples,
        callbacks=[best_model])
    
    

    predict.py

    from keras.models import load_model
    import os
    from keras.preprocessing.image import ImageDataGenerator
    import numpy as np
    
    # 超参数
    img_width = 299
    img_height = 299
    batch_size = 32
    nbr_test_samples = 1000
    
    # 类别
    FishNames = ['ALB', 'BET', 'DOL', 'LAG', 'NoF', 'OTHER', 'SHARK', 'YFT']
    
    # 模型文件路径
    weights_path = os.path.join('weights.h5')
    
    # 测试集路径
    test_data_dir = os.path.join('data/test_stg1/')
    if not os.path.exists(test_data_dir):
        os.mkdir(test_data_dir)
    
    # 测试集数据生成器
    test_datagen = ImageDataGenerator(rescale=1. / 255)
    
    test_generator = test_datagen.flow_from_directory(
        test_data_dir,
        target_size=(img_width, img_height),
        batch_size=batch_size,
        shuffle=False,  # Important !!!
        classes=None,
        class_mode=None)
    
    test_image_list = test_generator.filenames
    
    # 加载模型
    print('Loading model and weights from training process ...')
    InceptionV3_model = load_model(weights_path)
    
    # 预测
    print('Begin to predict for testing data ...')
    predictions = InceptionV3_model.predict_generator(test_generator, nbr_test_samples)
    
    # 保存预测结果
    np.savetxt(os.path.join('predictions.txt'), predictions)
    
    # 写入提交文件
    print('Begin to write submission file ..')
    f_submit = open(os.path.join('submit.csv'), 'w')
    f_submit.write('image,ALB,BET,DOL,LAG,NoF,OTHER,SHARK,YFT
    ')
    for i, image_name in enumerate(test_image_list):
        pred = ['%.6f' % p for p in predictions[i, :]]
        if i % 100 == 0:
            print('{} / {}'.format(i, nbr_test_samples))
        f_submit.write('%s,%s
    ' % (os.path.basename(image_name), ','.join(pred)))
    
    f_submit.close()
    
    print('Submission file successfully generated!')
    
    

    predict_average_augmentation.py

    from keras.models import load_model
    import os
    from keras.preprocessing.image import ImageDataGenerator
    import numpy as np
    
    os.environ["CUDA_VISIBLE_DEVICES"] = "0"
    
    # 超参数
    img_width = 299
    img_height = 299
    batch_size = 32
    nbr_test_samples = 1000
    nbr_augmentation = 5
    
    # 类别
    FishNames = ['ALB', 'BET', 'DOL', 'LAG', 'NoF', 'OTHER', 'SHARK', 'YFT']
    
    # 模型文件路径
    weights_path = os.path.join('weights.h5')
    
    # 测试集文件路径
    test_data_dir = os.path.join('data/test_stg1/')
    
    # 测试集数据生成器
    test_datagen = ImageDataGenerator(
        rescale=1. / 255,
        shear_range=0.1,
        zoom_range=0.1,
        width_shift_range=0.1,
        height_shift_range=0.1,
        horizontal_flip=True)
    
    # 加载模型
    print('Loading model and weights from training process ...')
    InceptionV3_model = load_model(weights_path)
    
    for idx in range(nbr_augmentation):
        print('{}th augmentation for testing ...'.format(idx))
        random_seed = np.random.random_integers(0, 100000)
    
        test_generator = test_datagen.flow_from_directory(
            test_data_dir,
            target_size=(img_width, img_height),
            batch_size=batch_size,
            shuffle=False,  # Important !!!
            seed=random_seed,
            classes=None,
            class_mode=None)
    
        test_image_list = test_generator.filenames
        # print('image_list: {}'.format(test_image_list[:10]))
        print('Begin to predict for testing data ...')
        if idx == 0:
            predictions = InceptionV3_model.predict_generator(test_generator, nbr_test_samples)
        else:
            predictions += InceptionV3_model.predict_generator(test_generator, nbr_test_samples)
    
    # 同一个模型,平均多个测试样例
    predictions /= nbr_augmentation
    
    # 写入提交文件
    print('Begin to write submission file ..')
    f_submit = open(os.path.join('submit.csv'), 'w')
    f_submit.write('image,ALB,BET,DOL,LAG,NoF,OTHER,SHARK,YFT
    ')
    for i, image_name in enumerate(test_image_list):
        pred = ['%.6f' % p for p in predictions[i, :]]
        if i % 100 == 0:
            print('{} / {}'.format(i, nbr_test_samples))
        f_submit.write('%s,%s
    ' % (os.path.basename(image_name), ','.join(pred)))
    
    f_submit.close()
    
    print('Submission file successfully generated!')
    
    
  • 相关阅读:
    ACM学习历程—UESTC 1218 Pick The Sticks(动态规划)(2015CCPC D)
    ACM学习历程—UESTC 1217 The Battle of Chibi(递推 && 树状数组)(2015CCPC C)
    A*算法的实现
    codevs1011 数的计算 2001年NOIP全国联赛普及组
    一场ACM一场梦——我的一年
    HDU 4422 The Little Girl who Picks Mushrooms ( 模拟)
    HDU4277 USACO ORZ(dfs+set)
    HDU4272LianLianKan(dfs)
    HDU4268 Alice and Bob(贪心+multiset)
    hdu 5444 Elven Postman(二叉树)——2015 ACM/ICPC Asia Regional Changchun Online
  • 原文地址:https://www.cnblogs.com/chenxiangzhen/p/10599723.html
Copyright © 2011-2022 走看看