kaggle

本文介绍了参加Kaggle的Plant Seedlings Classification比赛,内容涉及数据预处理(包括图像处理和归一化),训练集和测试集划分,数据增强,训练模型(包含卷积和全连接层),以及学习率调整和模型保存。通过ImageDataGenerator进行数据增强,并使用ReduceLROnPlateau回调函数调整学习率。最后,对test数据集进行预处理并得到预测结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Kaggle Plant Seedlings Classification

比赛内容

搭建一个模型区分十二类植物。比赛地址

在这里插入图片描述

数据

traintest train里面有十二个文件夹,每一个文件夹代表一类植物样本。

数据预处理

在搭建模型前,我们要对数据进行处理,这部分意义重大!

获取train样本中的label

通过python中的glob 获得train目录下文件名和路径名的列表,再通过切割字符串获得对应的文件名(即label)。

import cv
from glob import glob
import numpy as np
from matplotlib import pyplot as  plt
import math 
import pandas as pd

 ImageSize = 70 #图像导入尺寸
 Path = './train/*/*.png'
"""
../ 代表当前文件所在目录的上一级目录
./ 代表当前目录
/ 代表当前的根目录
"""
files = glob(path) #files现在是一个列表,里面包含train里面所有照片的存储地址
#files 里面格式'./train\\Black-grass\\0050f38b3.png'
trainImg = []
trainLabel = []
j = 1 
num = len(files)
for img in files:  
    print(str(j) + "/" + str(num), end="\r")
    trainLabel.append(img.split('\\')[-2])
    trainImg.append(cv2.resize(cv2.imread(img),(ImgSize,ImgSize)))
    j +=1 
trainImg = np.asarray(trainImg)
trainLabel = pd.DatatFrame(trainLabel)

现在查看一下样本

在这里插入图片描述

对图像进行处理

因为这里只需要叶子的形状,因此要进行一些处理将叶子外的背景全部消失掉影响

clearTrainImg = []
examples = []
getEx = True
for img in trainImg:
    blurImg = cv2.GaussianBlur(img,(5,5),0)  #使用高斯模糊滤波 (5,5)是卷积尺寸,0是标准差
    hsv = cv2.cvtColor(blurImg,cv2.COLOR_BGR2HSV) #BGR图像转化为HSV图像
    lower_green = (25,40,50)
    upper_green = (75,255,255)
    mask = cv2.inRange(hsvImg,lower_green,upper_green) #cv2.inRange(img,low,high),函数会将位于两个区域间的值置为255,位于区间外的值置为0
    #cv2.getStructuringElement函数可用于构造一个特定大小和形状的结构元素 
    #cv2.MORPH_ELLIPSE 椭圆形状(核)
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11, 11))
    #开运算是先腐蚀再膨胀 闭运算是先膨胀在腐蚀
    mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) #闭运算
    bMask = mask > 0  #Create bool mask  bmask和mask其实一直都是绿叶部分
    clear = np.zeros_like(img, np.uint8) # Create empty image 一副全黑图
    clear[bMask] = img[bMask] # Apply boolean mask to the origin image
    clearTrainImg.append(clear) # Append image without backgroung

查看每次处理后的变化
在这里插入图片描述

归一化处理图片

归一化目的是使得网络训练速度更快些
归一化

稍微再处理一下

我们先看看十二类的比例,将label进行one-hot

from keras.utils import np_utils  #one-hot
from sklearn import preprocessing 
import matplotlib as plt

#sklearn.preprocessing.LabelEncoder():标准化标签,标签统一转换成 rang(标签类别总数)
le = preprocessing.LabelEncoder()
le.fit(trainLabel[0])
#transform 将标签转换为 [0,0,1,1,,,,,,11,11] 每个下标代表每个样本 一共4748个样本
encodeTrainLabels = le.transform(trainLabel[0])
#np_utils.to_categorical 将类别向量(从0到nb_classes的整数向量)映射为二值类别矩阵
#例如第一类样本标签为 [1,0,0,0,0,0,0,0,0,0,0,0]
clearTrainLabel = np_utils.to_categorical(encodeTrainLabels)
num_clases = clearTrainLabel.shape[1]
trainLabel[0].value_counts().plot(kind='bar')

在这里插入图片描述

训练集和测试集划分

用到了sklearn.model_selection里面的train_test_split

from sklearn.model_selection import trian_test_split

trainX,testX,trainY,testY = train_test_split(clearTrainImg,clearTrainLabel,test_size=0.1,
                            random_state=seed,stratify=clearTrainLabel)

test_size = 0.1 表示测试集占clearTrain中的0.1
stratify = clearTrainLabel 表示训练集,测试集都是安装样本的类别比例划分。
例如 a :b :c = 1:2:3 则划分的每一个集都是按照该比例

数据增强处理

这里用到了keras.preprocessing.image 里面的 ImageDataGenerator

from keras.preprocessing.image import ImageDataGenerator
datatgen = ImageDataGenerator(
                              rotation_range = 180,zoom_range = 0.1,
                              width_shift_range=0.1,height_shift_range=0.1,
                              horizontal_flip=True,vertical_flip=True
                               )
 datagen.fit(trainX)

ImageDataGenerator

训练模型

6个卷积层,3个全连接层,还有一个Flatten层

Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。Flatten不影响batch的大小。

 import numpy
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers import BatchNormalization

numpy.random.seed(seed)  # Fix seed
model = Sequential()

model.add(Conv2D(filters=64, kernel_size=(5, 5), input_shape=(ImageSize, ImageSize, 3), activation='relu'))
model.add(BatchNormalization(axis=3))
model.add(Conv2D(filters=64, kernel_size=(5, 5), activation='relu'))
model.add(MaxPooling2D((2, 2)))
model.add(BatchNormalization(axis=3))
model.add(Dropout(0.1))

model.add(Conv2D(filters=128, kernel_size=(5, 5), activation='relu'))
model.add(BatchNormalization(axis=3))
model.add(Conv2D(filters=128, kernel_size=(5, 5), activation='relu'))
model.add(MaxPooling2D((2, 2)))
model.add(BatchNormalization(axis=3))
model.add(Dropout(0.1))

model.add(Conv2D(filters=256, kernel_size=(5, 5), activation='relu'))
model.add(BatchNormalization(axis=3))
model.add(Conv2D(filters=256, kernel_size=(5, 5), activation='relu'))
model.add(MaxPooling2D((2, 2)))
model.add(BatchNormalization(axis=3))
model.add(Dropout(0.1))

model.add(Flatten())

model.add(Dense(256, activation='relu'))
model.add(BatchNormalization())
model.add(Dropout(0.5))

model.add(Dense(256, activation='relu'))
model.add(BatchNormalization())
model.add(Dropout(0.5))

model.add(Dense(num_clases, activation='softmax'))

#打印出模型概况
model.summary()
#compile 函数编译模型以供训练,loss:损失函数 ,optimizer:优化器,
#metrics:列表,包含评估模型在训练和测试时的性能的指标
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

learning rate reduction & fit model

当评价指标不再提升时,减少学习率。我们使用回调函数(类)Callbacks里面的ReduceLROnPlateau函数。

keras.callbacks.ReduceLROnPlateau(monitor=‘val_loss’, factor=0.1, patience=10, verbose=0, mode=‘auto’, epsilon=0.0001, cooldown=0, min_lr=0)
monitor:被监测的量
factor:每次减少学习率的因子,学习率将以lr = lr*factor的形式被减少
patience:当patience个epoch过去而模型性能不提升时,学习率减少的动作会被触发
mode:‘auto’,‘min’,‘max’之一,在min模式下,如果检测值触发学习率减少。在max模式下,当检测值不再上升则触发学习率减少。
epsilon:阈值,用来确定是否进入检测值的“平原区”
cooldown:学习率减少后,会经过cooldown个epoch才重新进行正常操作
min_lr:学习率的下限

将每个epoch后的模型保存到filepath。我们使用回调函数(类)Callbacks里面的ModelCheckpoint函数。

keras.callbacks.ModelCheckpoint(filepath, monitor=‘val_loss’, verbose=0, save_best_only=False, save_weights_only=False, mode=‘auto’, period=1)
filename:字符串,保存模型的路径
monitor:需要监视的值
verbose:信息展示模式,0或1
save_best_only:当设置为True时,将只保存在验证集上性能最好的模型
mode:‘auto’,‘min’,‘max’之一,在save_best_only=True时决定性能最佳模型的评判准则,例如,当监测值为val_acc时,模式应为max,当检测值为val_loss时,模式应为min。在auto模式下,评价准则由被监测值的名字自动推断。
save_weights_only:若设置为True,则只保存模型权重,否则将保存整个模型(包括模型结构,配置信息等)
period:CheckPoint之间的间隔的epoch数

from keras.callbacks import  ModelCheckpoint,ReduceLROnPlateau

learning_rate_reduction = ReduceLROnPlateau(monitor="val_acc",
                                            patience=3,
                                            verbose=1,
                                            factor=0.4,
                                            min_lr=0.00001)
#每个epoch后保存模型,保存验证集上性能最好的模型
filepath=  "./PlantReco_mode/weights.best_{epoch:02d}-{val_acc:.2f}.hdf5"
checkpoint = ModelCheckpoint(filepath,monitor="val_acc",verbose=1,
                             save_best_only=True,mode="max")     
                                   
#保存全部模型的参数
filepath= "./PlantReco_mode/weights.last_auto4.hdf5"
checkpoint_all = ModelCheckpoint(filepath,monitor="val_acc",verbose=1,
                             save_best_only=False,mode="max")     
#all callbacks
callbacks_list = [checkpoint, learning_rate_reduction, checkpoint_all]

#fit model 
#fit_generator()生成器与模型并执行,提搞效率。(减少内存)
his = model.fit_generator(datagen.flow(trainX,trainY,batch_size=75),
                          epochs=25,validation_data=(testX,testY),
                          steps_per_epoch=trainX.shape[0],callbacks=callbacks_list)

补充1

图片生成器ImageDataGenerator的方法函数flow
flow(self, X, y, batch_size=32, shuffle=True, seed=None, save_to_dir=None, save_prefix=’’, save_format=‘jpeg’):接收numpy数组和标签为参数,生成经过数据提升或标准化后的batch数据,并在一个无限循环中不断的返回batch数据
X:样本数据,秩应为4.在黑白图像的情况下channel轴的值为1,在彩色图像情况下值为3
y:标签
batch_size:整数,默认32
shuffle:布尔值,是否随机打乱数据,默认为True
save_to_dir:None或字符串,该参数能让你将提升后的图片保存起来,用以可视化
save_prefix:字符串,保存提升后图片时使用的前缀, 仅当设置了save_to_dir时生效
save_format:“png"或"jpeg"之一,指定保存图片的数据格式,默认"jpeg”
yields:形如(x,y)的tuple,x是代表图像数据的numpy数组.y是代表标签的numpy数组.该迭代器无限循环.
seed: 整数,随机数种子

训练情况
在这里插入图片描述

调用模型 和 对test数据集进行预处理

test数据集这里也要和train一样进行同样的处理

model.load_weights("./PlantReco_mode/weights.last_auto4.hdf5") #导入训练好的模型参数
path = './test/*.png'
files = glob(path)
testImg = []
testId = []
j = 1
num = len(files)
testImg = np.asarray(testImg)  # Train images set
for i in range(8):
    plt.subplot(2, 4, i + 1)
    plt.imshow(testImg[i])

在这里插入图片描述
接下来同对train图像处理一样的操作,对test图像进行处理

得到预测结果

clearTestImg = clearTestImg / 255 #归一化

pred = model.predict(clearTestImg)

#Write result to file
predNum = np.argmax(pred, axis=1) #np.argmax 取出值最大的索引
predStr = le.classes_[predNum] #le = preprocessing.LabelEncoder() le.classes_获取标签值

res = {'file': testId, 'species': predStr}
res = pd.DataFrame(res)
res.to_csv("res3.csv", index=False)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值