2021 科大讯飞开发者大赛 (农作物生长情况识别挑战赛)初赛满分低资源解决方案

1 赛题概要

通过作物不同生长时期的特点可以对作物的生长情况进行识别,给出合理的作物生长阶段。本次大赛提供了大量草莓植株在营养生长阶段的生长情况图片作为样本,参赛选手需基于提供的样本构建模型,对草莓样本生长态势进行检测,判断其生长情况,并将生长情况在csv文件中对应标定出来,给出草莓图像对应的生长阶段。

初赛一阶段:6月21日到8月18日。

初赛二阶段:8月19日到8月20日。系统将在8月19日00:00更换测试数据,参赛队伍需要再次下载数据。

复赛阶段:8月21日到9月20日。

赛题地址:赛题地址链接

评分规则:识别准确率。

举办方:中国农业大学
在这里插入图片描述

2 数据分析

2.1 数据概览

2.1.1 文件目录

在这里插入图片描述

2.1.2 训练数据概览

图2-1 训练集样本

2.1.3 测试数据概览

图2-2 测试集样本

2.1.4 小结

根据以上分析,对数据集有了初步的了解,首先,本赛题是一个典型的图像分类问题,其次,图像尺寸并不统一,需要预处理。

2.2 数据探索

2.2.1 数据分布情况

导入基础包:

import os, gc
import pandas as pd
import numpy as np

读取数据:

df_train = pd.read_csv('../train.csv')
print(df_train.label.value_counts())
df_train.head()

在这里插入图片描述在这里插入图片描述

Conclusion:在train.csv文件中存放的是训练集图片ID及对应的标签,并按照ID标号升序排列,标签一共有4类,分布较为均匀。

2.2.2 提交文件样例

submit_sample = pd.read_csv('../submit_sample.csv')
submit_sample.head()

在这里插入图片描述

2.2.3 读取数据+预处理

import re
import tensorflow as tf
 
def Image_Reader(directory_name):
    with tf.Session() as sess:
        data, filenames  = [], []
        directory_list = os.listdir(directory_name)
        # 利用正则提取训练样本ID中的数字标号,并安装严格升序重新排列训练样本
        directory_list.sort(key=lambda x: int(re.sub("\D","",x))) 
    
        for filename in directory_list:
            image_raw_data = tf.gfile.FastGFile(directory_name + "/" + filename,'rb').read()
            img_data = tf.image.decode_jpeg(image_raw_data)
            resized = tf.image.resize_images(img_data, [299, 299], method=0)
            resized = np.asarray(resized.eval(),dtype='uint8')
            data.append(resized)
            filenames.append(filename)
 
        data = np.array(data)
        return data, filenames

读取训练集和测试集数据

train_x, train_id = Image_Reader(train_dir)
test_x, test_id = Image_Reader(test_dir)
print(train_x.shape, test_x.shape)

out : (557, 299, 299, 3) (230, 299, 299, 3)

训练集样本557,测试集样本230,已经转换成标准Tensor形式。

# 像素值归一化
train_x = train_x/255.0
test_x = test_x/255.0

# 标签 one-hot 编码
from keras.utils import to_categorical

train_y = to_categorical(df_train.label.values)
train_x.shape,train_y.shape,test_x.shape

out : ((557, 299, 299, 3), (557, 4), (230, 299, 299, 3))

2.2.4 小结

经过以上处理,已经将数据转换成神经网络可训练的形式,接下来就是模型的选择问题,以及训练策略。

3 模型选择及训练(keras版)

TIPS: 考虑到本题所提供的数据量较少,容易导致模型过拟合,惯用的解决方法有数据增强、迁移学习、正则化策略等。本文采用迁移学习的方法。

3.1 迁移学习特征抽取

from keras.applications.inception_v3 import InceptionV3

# 加载预训练模型
base_model = InceptionV3(weights='imagenet',
                        input_shape=(299,299,3),
                        include_top=True)
#base_model.summary()

参数说明:include_top=True意味着保留了顶层网络,通常情况下设置为False,考虑到本题数据与预训练数据相似度高(别问我为什么,盲猜的!!!),因此,将图片尺寸也与InceptionV3输入标准尺寸保存一致。

# 利用预训练模型提取特征
from keras.models import Model

feature_model = Model(inputs=base_model.input,outputs=base_model.get_layer('avg_pool').output)

X_train = feature_model.predict(train_x)
X_test = feature_model.predict(test_x)
print(X_train.shape, X_test.shape)

out : (557, 2048) (230, 2048)
time: 7min 58s(2核8G CPU环境)
这一步相对耗时,所以我只想跑一次,如果算力资源充沛就无此顾及了。。。

3.2 搭建适配的分类器并训练

# 添加分类层神经网络
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.optimizers import Adam
from keras.callbacks import ReduceLROnPlateau

# 定义分类模型
model = Sequential()
model.add(Dropout(0.6))
model.add(Dense(4, activation='softmax',input_dim = X_train.shape[1]))


model.compile(loss='categorical_crossentropy', 
              optimizer=Adam(lr=0.01), 
              metrics=['accuracy'])

# 设置学习率衰减策略
reduce_lr = ReduceLROnPlateau(monitor='loss',
                              factor=0.7,patience=1,
                              verbose=0)

history = model.fit(X_train, train_y, 
                    epochs=50,shuffle=True,
                    batch_size=32,verbose=0,
                    callbacks=[reduce_lr])

没错!,分类模型就是这么简单!!!
在这里插入图片描述
50个Epochs 6秒跑完,别忘了这是2核8G的CPU环境!!!

Notes(初赛满分策略):
1. Dropout 正则化,抑制模型过拟合
2. 学习率衰减策略,使得收敛效果更好

3.3 可视化训练过程

import matplotlib.pyplot as plt
%matplotlib inline

def plot_curve(history):
    acc, loss, lr = history.history['acc'], history.history['loss'], history.history['lr']
    epochs = range(1,len(acc)+1)
    plt.figure(figsize=(10,4))
    plt.subplot(121)
    plt.plot(epochs, acc,  label='Training acc')
    plt.plot(epochs, loss, label='Training loss')
    plt.title('Training acc and loss')
    plt.legend()

    plt.subplot(122)
    plt.plot(epochs, lr, label='Learning rate')
    plt.title('Learning rate')
    plt.legend()
    plt.show()

plot_curve(history)

在这里插入图片描述

3.4 预测测试集并生成提交文件

pred = model.predict_classes(X_test)
data = {'image':test_id,'label':pred}
submit = pd.DataFrame(data) 
print(submit.label.value_counts())
submit.head()

在这里插入图片描述在这里插入图片描述
保存提交文件

submit.to_csv('submit.csv', index=False)

提交分数
在这里插入图片描述
备注:本题相对简单,截止2021年7月28日,一共469支参赛队伍,前60名的团队都达到了满分。

4 总结

针对《农作物生长情况识别挑战赛》初赛,本文提供了一个满分解决方案,但显然凭此并不能走到最后,可用上分策略:数据增强、Fine-tune 、尝试其他预训练模型、模型融合。
声明:本人刚大四毕业,初次写此类文章,水平有限,如有错误之处,还请指正,感谢支持!

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值