农作物生长情况识别挑战赛
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.3 测试数据概览
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 、尝试其他预训练模型、模型融合。
声明:本人刚大四毕业,初次写此类文章,水平有限,如有错误之处,还请指正,感谢支持!