首页 > 分享 > 第3章(下)基于Softmax回归完成鸢尾花分类任务

第3章(下)基于Softmax回归完成鸢尾花分类任务

文章目录 3.3 实践:基于Softmax回归完成鸢尾花分类任务3.3.1 数据处理3.3.1.1 数据集介绍3.3.1.2 数据清洗3.3.1.3 数据读取 3.3.2 模型构建3.3.3 模型训练3.3.4 模型评价3.3.5 模型预测 3.4 小结3.5 实验拓展

3.3 实践:基于Softmax回归完成鸢尾花分类任务

在本节,我们用入门深度学习的基础实验之一“鸢尾花分类任务”来进行实践,使用经典学术数据集Iris作为训练数据,实现基于Softmax回归的鸢尾花分类任务。

实践流程主要包括以下7个步骤:数据处理、模型构建、损失函数定义、优化器构建、模型训练、模型评价和模型预测等,

数据处理:根据网络接收的数据格式,完成相应的预处理操作,保证模型正常读取;模型构建:定义Softmax回归模型类;训练配置:训练相关的一些配置,如:优化算法、评价指标等;组装Runner类:Runner用于管理模型训练和测试过程;模型训练和测试:利用Runner进行模型训练、评价和测试。

说明:

使用深度学习进行实践时的操作流程基本一致,后文不再赘述。

本实践的主要配置如下:

数据:Iris数据集;模型:Softmax回归模型;损失函数:交叉熵损失;优化器:梯度下降法;评价指标:准确率。 3.3.1 数据处理 3.3.1.1 数据集介绍

Iris数据集,也称为鸢尾花数据集,包含了3种鸢尾花类别(Setosa、Versicolour、Virginica),每种类别有50个样本,共计150个样本。其中每个样本中包含了4个属性:花萼长度、花萼宽度、花瓣长度以及花瓣宽度,本实验通过鸢尾花这4个属性来判断该样本的类别。

鸢尾花属性

属性1属性2属性3属性4sepal_lengthsepal_widthpetal_lengthpetal_width花萼长度花萼宽度花瓣长度花瓣宽度

鸢尾花类别

英文名中文名标签Setosa Iris狗尾草鸢尾0Versicolour Iris杂色鸢尾1Virginica Iris弗吉尼亚鸢尾2

鸢尾花属性类别对应预览

sepal_lengthsepal_widthpetal_lengthpetal_widthspecies5.13.51.40.2setosa4.931.40.2setosa4.73.21.30.2setosa…………… 3.3.1.2 数据清洗 缺失值分析

对数据集中的缺失值或异常值等情况进行分析和处理,保证数据可以被模型正常读取。代码实现如下:

from sklearn.datasets import load_iris import pandas import numpy as np iris_features = np.array(load_iris().data, dtype=np.float32) iris_labels = np.array(load_iris().target, dtype=np.int32) print(pandas.isna(iris_features).sum()) print(pandas.isna(iris_labels).sum()) 12345678

0 0 12

iris = pandas.read_csv('/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/sklearn/datasets/data/iris.csv') iris.head() 12 1504setosaversicolorvirginica05.13.51.40.2014.93.01.40.2024.73.21.30.2034.63.11.50.2045.03.61.40.20

从输出结果看,鸢尾花数据集中不存在缺失值的情况。

异常值处理

通过箱线图直观的显示数据分布,并观测数据中的异常值。

import matplotlib.pyplot as plt #可视化工具 %matplotlib inline # 箱线图查看异常值分布 def boxplot(features): feature_names = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width'] # 连续画几个图片,subplots_adjust为子图调整,wspace, hspace:子图之间的横向间距、纵向间距分别与子图平均宽度、平均高度的比值。 plt.figure(figsize=(3, 3), dpi=200) plt.subplots_adjust(wspace=0.6) # 每个特征画一个箱线图 for i in range(4): plt.subplot(2, 2, i+1) # 画箱线图 plt.boxplot(features[:, i], showmeans=True, # 均值显示 meanprops={"markersize":1}, # 设置均值的属性,如点的大小、颜色等; whiskerprops={"color":"#E20079", "linewidth":0.4, 'linestyle':"--"}, # 设置垂直虚线的属性,如颜色、粗细、线的类型等 flierprops={"markersize":0.4}) # 设置异常值属性,点的形状、填充色和边框色 # 图名,fontdict:控制标题文本的外观,pad:标题与轴顶部的距离 plt.title(feature_names[i], fontdict={"size":5}, pad=2) # y方向刻度,fontsize:刻度值的大小,pad:刻度线与刻度值之间的距离 plt.yticks(fontsize=4) plt.tick_params(pad=0.5) # x方向刻度 plt.xticks([]) plt.savefig('ml-vis.pdf') plt.show() boxplot(iris_features)

123456789101112131415161718192021222324252627282930

png

从输出结果看,数据中基本不存在异常值,所以不需要进行异常值处理。

3.3.1.3 数据读取

本实验中将数据集划分为了三个部分:

训练集:用于确定模型参数;验证集:与训练集独立的样本集合,用于使用提前停止策略选择最优模型;测试集:用于估计应用效果(没有在模型中应用过的数据,更贴近模型在真实场景应用的效果)。

在本实验中,将 80 % 80% 80%的数据用于模型训练, 10 % 10% 10%的数据用于模型验证, 10 % 10% 10%的数据用于模型测试。代码实现如下:

import copy import paddle import warnings warnings.filterwarnings("ignore") # 加载数据集 def load_data(shuffle=True): """ 加载鸢尾花数据 输入: - shuffle:是否打乱数据,数据类型为bool 输出: - X:特征数据,shape=[150,4] - y:标签数据, shape=[150] """ # 加载原始数据 X = np.array(load_iris().data, dtype=np.float32) y = np.array(load_iris().target, dtype=np.int32) X = paddle.to_tensor(X) y = paddle.to_tensor(y) # 数据归一化,最大最小值归一化 X_min = paddle.min(X, axis=0) X_max = paddle.max(X, axis=0) X = (X-X_min) / (X_max-X_min) # 如果shuffle为True,随机打乱数据,randperm会生成一维的0 ~ X.shape[0]-1的乱序数组作为索引 if shuffle: idx = paddle.randperm(X.shape[0]) X = X[idx] y = y[idx] return X, y # 固定随机种子 paddle.seed(102) num_train = 120 num_dev = 15 num_test = 15 X, y = load_data(shuffle=True) print("X shape: ", X.shape, "y shape: ", y.shape) X_train, y_train = X[:num_train], y[:num_train] X_dev, y_dev = X[num_train:num_train + num_dev], y[num_train:num_train + num_dev] X_test, y_test = X[num_train + num_dev:], y[num_train + num_dev:]

12345678910111213141516171819202122232425262728293031323334353637383940414243444546

X shape: [150, 4] y shape: [150] 1

# 打印X_train和y_train的维度 print("X_train shape: ", X_train.shape, "y_train shape: ", y_train.shape) 12

X_train shape: [120, 4] y_train shape: [120] 1

# 打印前5个数据的标签 print(y_train[:5]) 12

Tensor(shape=[5], dtype=int32, place=CPUPlace, stop_gradient=True, [0, 1, 1, 0, 1]) 12 3.3.2 模型构建

使用Softmax回归模型进行鸢尾花分类实验,将模型的输入维度定义为4,输出维度定义为3。代码实现如下:

from nndl import op # 输入维度,类别数,实例化模型 input_dim = 4 output_dim = 3 model = op.model_SR(input_dim=input_dim, output_dim=output_dim) 123456 3.3.3 模型训练

实例化RunnerV2类,使用训练集和验证集进行模型训练,共训练80个epoch,其中每隔10个epoch打印训练集上的指标,并且保存准确率最高的模型作为最佳模型。代码实现如下:

from nndl import op, metric, opitimizer, RunnerV2 # 学习率 lr = 0.2 # 梯度下降法,交叉熵损失,准确率,实例化RunnerV2 optimizer = opitimizer.SimpleBatchGD(init_lr=lr, model=model) loss_fn = op.MultiCrossEntropyLoss() metric = metric.accuracy runner = RunnerV2(model, optimizer, metric, loss_fn) # 启动训练 runner.train([X_train, y_train], [X_dev, y_dev], num_epochs=200, log_epochs=10, save_path="best_model.pdparams") 12345678910111213

最佳精度模型已保存: 0.00000 --> 0.40000 [Train] epoch: 0, loss: 1.09861, score: 0.31667 [Dev] epoch: 0, loss: 1.08287, score: 0.40000 最佳精度模型已保存: 0.40000 --> 0.46667 最佳精度模型已保存: 0.46667 --> 0.66667 最佳精度模型已保存: 0.66667 --> 0.73333 [Train] epoch: 10, loss: 0.98697, score: 0.64167 [Dev] epoch: 10, loss: 0.97466, score: 0.73333 [Train] epoch: 20, loss: 0.90985, score: 0.65000 [Dev] epoch: 20, loss: 0.89974, score: 0.73333 [Train] epoch: 30, loss: 0.84734, score: 0.68333 [Dev] epoch: 30, loss: 0.83969, score: 0.73333 [Train] epoch: 40, loss: 0.79562, score: 0.72500 [Dev] epoch: 40, loss: 0.79042, score: 0.73333 [Train] epoch: 50, loss: 0.75237, score: 0.74167 [Dev] epoch: 50, loss: 0.74958, score: 0.73333 [Train] epoch: 60, loss: 0.71581, score: 0.78333 [Dev] epoch: 60, loss: 0.71535, score: 0.73333 最佳精度模型已保存: 0.73333 --> 0.80000 [Train] epoch: 70, loss: 0.68455, score: 0.80833 [Dev] epoch: 70, loss: 0.68637, score: 0.80000 最佳精度模型已保存: 0.80000 --> 0.86667 [Train] epoch: 80, loss: 0.65752, score: 0.81667 [Dev] epoch: 80, loss: 0.66154, score: 0.86667 [Train] epoch: 90, loss: 0.63390, score: 0.84167 [Dev] epoch: 90, loss: 0.64007, score: 0.86667 [Train] epoch: 100, loss: 0.61305, score: 0.84167 [Dev] epoch: 100, loss: 0.62130, score: 0.86667 [Train] epoch: 110, loss: 0.59449, score: 0.85833 [Dev] epoch: 110, loss: 0.60476, score: 0.86667 [Train] epoch: 120, loss: 0.57784, score: 0.85000 [Dev] epoch: 120, loss: 0.59004, score: 0.86667 [Train] epoch: 130, loss: 0.56279, score: 0.85833 [Dev] epoch: 130, loss: 0.57686, score: 0.86667 [Train] epoch: 140, loss: 0.54910, score: 0.86667 [Dev] epoch: 140, loss: 0.56497, score: 0.86667 [Train] epoch: 150, loss: 0.53658, score: 0.87500 [Dev] epoch: 150, loss: 0.55418, score: 0.86667 [Train] epoch: 160, loss: 0.52506, score: 0.88333 [Dev] epoch: 160, loss: 0.54432, score: 0.86667

12345678910111213141516171819202122232425262728293031323334353637383940

可视化观察训练集与验证集的准确率变化情况。

from nndl import plot plot(runner,fig_name='linear-acc3.pdf') 123 3.3.4 模型评价

使用测试数据对在训练过程中保存的最佳模型进行评价,观察模型在测试集上的准确率情况。代码实现如下:

# 加载最优模型 runner.load_model('best_model.pdparams') # 模型评价 score, loss = runner.evaluate([X_test, y_test]) print(f"[Test] score/loss: {score:.4f}/{loss:.4f}") 123456 3.3.5 模型预测

使用保存好的模型,对测试集中的数据进行模型预测,并取出1条数据观察模型效果。代码实现如下:

# 预测测试集数据,观察其中一条样本的预测结果,并获取该样本概率最大的类别 logits = runner.predict(X_test) pred = paddle.argmax(logits[0]).numpy() label = y_test[0].numpy() print(f"正确的分类是 {label[0]} 预测的类别是 {pred[0]}") 12345

3.4 小结

本节实现了Logistic回归和Softmax回归两种基本的线性分类模型。

3.5 实验拓展

为了加深对机器学习模型的理解,请自己动手完成以下实验:

尝试调整学习率和训练轮数等超参数,观察是否能够得到更高的精度;在解决多分类问题时,还有一个思路是将每个类别的求解问题拆分成一个二分类任务,通过判断是否属于该类别来判断最终结果。请分别尝试两种求解思路,观察哪种能够取得更好的结果;尝试使用《神经网络与深度学习》中的其他模型进行鸢尾花识别任务,观察是否能够得到更高的精度。

相关知识

神经网络与深度学习(五)前馈神经网络(3)鸢尾花分类
python鸢尾花数据集的分类问题 -- 逻辑回归问题研究
TensorFlow学习记录(八)
基于BP神经网络对鸢尾花的分类的研究
鸢尾花分类
计算智能课程设计(基于感知机的鸢尾花分类)
基于深度学习的花卉图像分类识别模型研究
逻辑回归分类、决策树分类、朴素贝叶斯分类及手写数字识别
《园林花卉学》第3章花卉品种分类
如何翻译和解释机器学习术语?请看 Google 官方答案 下

网址: 第3章(下)基于Softmax回归完成鸢尾花分类任务 https://m.huajiangbk.com/newsview387322.html

所属分类:花卉
上一篇: logier/鸢尾花插件
下一篇: 朴素贝叶斯分类(鸢尾花数据集)