最优化方法Python计算:无约束优化应用——线性回归分类器

发布于:2025-05-07 ⋅ 阅读:(31) ⋅ 点赞:(0)

一、线性回归分类器

假设样本数据为 ( x i , y i ) (\boldsymbol{x}_i, y_i) (xi,yi),其中 i = 1 , 2 , … , m i = 1, 2, \dots, m i=1,2,,m。标签 y i y_i yi 取值于 k k k 个整数 { 1 , 2 , … , k } \{1, 2, \dots, k\} {1,2,,k},从而构成一个 k k k-分类问题。线性回归分类器与线性回归预测器的测试评估指标不同,当我们用训练数据得到模型参数 w 0 \boldsymbol{w}_0 w0 后,可以利用测试数据集评估模型性能。设测试数据集为 { ( x i , y i ) ∣ i = 1 , 2 , ⋯   , m } \{(\boldsymbol{x}_i, y_i)|i=1,2,\cdots,m\} {(xi,yi)i=1,2,,m},其中 x i \boldsymbol{x}_i xi 为特征向量, y i y_i yi 为真实标签。定义测试数据矩阵:
X t e s t = ( x 1 ⊤ 1 x 2 ⊤ 1 ⋮ ⋮ x m ⊤ 1 ) , Y t e s t = ( y 1 y 2 ⋮ y m ) , \boldsymbol{X}_{test} = \begin{pmatrix} \boldsymbol{x}_1^\top & 1 \\ \boldsymbol{x}_2^\top & 1 \\ \vdots & \vdots \\ \boldsymbol{x}_m^\top & 1 \end{pmatrix}, \quad \boldsymbol{Y}_{test} = \begin{pmatrix} y_1 \\ y_2 \\ \vdots \\ y_m \end{pmatrix}, Xtest= x1x2xm111 ,Ytest= y1y2ym ,
其中, X t e s t \boldsymbol{X}_{test} Xtest 的最后一列全为 1,用于引入偏置项。用线性回归方法计算预测值:
( y 1 ′ y 2 ′ ⋮ y m ′ ) = Y ′ = round ( X t e s t w 0 ) . \begin{pmatrix} y_1' \\ y_2' \\ \vdots \\ y_m' \end{pmatrix} = \boldsymbol{Y}' = \text{round}(\boldsymbol{X}_{test} \boldsymbol{w}_0). y1y2ym =Y=round(Xtestw0).
其中, round ( ⋅ ) \text{round}(\cdot) round() 表示逐元素取整操作。
m ′ m' m Y t e s t \boldsymbol{Y}_{test} Ytest Y ′ \boldsymbol{Y}' Y y i = y i ′ y_i=y_i' yi=yi i = 1 , 2 , ⋯   , m i=1,2,\cdots,m i=1,2,,m的个数(即预测值与真实标签值相等的样本数),则测试评估指标定义为准确率:
score = m ′ m × 100 % . \text{score}=\frac{m'}{m}\times100\%{}. score=mm×100%.
其中, m m m 为测试样本总数。准确率反映了模型预测正确的比例。下列代码实现线性回归分类器。

import numpy as np
class Classification():					#分类模型
    def score(self, x, y):				#测试函数
        return np.mean(self.predict(x) == y)
class LinearClassifier(Classification,LineModel):	#线性分类模型
    def __init__(self):
        self.tagVal=np.round

程序中

  • 第2~4行定义了用于表示分类模型的Classification。其中,第3~4行定义了分类器的测试函数score。第4行调用predict函数对表示特征数据的参数x计算预测值并于表示标签数据的参数y比较,算得相等即预测正确的均值,计算正确率并返回。
  • 第5~7行将线性分类模型类LinearClassifier定义成Classification和LineModel(见博文《最优化方法Python计算:无约束优化应用——线性回归模型》)的子类。该类拥有其两个父类Classification和LineModel的所有数据和方法。其中,第6~7行定义的构造函数将tagVal函数设置为Numpy的舍入函数round,使得预测值
    self.tagVal(yp * (self.ymax - self.ymin) + self.ymin) \text{self.tagVal(yp * (self.ymax - self.ymin) + self.ymin)} self.tagVal(yp * (self.ymax - self.ymin) + self.ymin)
    (见博文《最优化方法Python计算:无约束优化应用——线性回归模型》中predict函数的定义)

二、综合案例

文件iris.csv(来自UC Irvine Machine Learning Repository)是统计学家R. A. Fisher在1936年采集的一个小型经典数据集,这是用于评估分类方法的最早的已知数据集之一。该数据集含有150例3种鸢尾花:setosa、versicolour和virginica的数据

Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
⋯ \cdots ⋯ \cdots ⋯ \cdots ⋯ \cdots ⋯ \cdots ⋯ \cdots
51 7 3.2 4.7 1.4 versicolor
52 6.4 3.2 4.5 1.5 versicolor
53 6.9 3.1 4.9 1.5 versicolor
⋯ \cdots ⋯ \cdots ⋯ \cdots ⋯ \cdots ⋯ \cdots ⋯ \cdots
148 6.5 3 5.2 2 virginica
149 6.2 3.4 5.4 2.3 virginica
150 5.9 3 5.1 1.8 virginica

五个数据属性的意义分别为

  • Sepal.Length:花萼长度;
  • Sepal.Width:花萼宽度;
  • Petal.Length:花瓣长度;
  • Petal.Width:花瓣宽度;
  • Species:种类。

下列代码从文件中读取数据,将花的种类数字化。

import numpy as np										#导入numpy
data = np.loadtxt('iris.csv', delimiter=',', dtype=str)	#读取数据文件
X = np.array(data)										#转换为数组
X = X[:, 1:]											#去掉编号
title = X[0, :4]										#读取特征名称
X = X[1:, :]											#去掉表头
Y = X[:, 4]												#读取标签数据
X = X[:, :4].astype(float)
m = X.shape[0]											#读取样本个数
print('共有%d个数据样本'%m)
print('鸢尾花特征数据:')
print(X)
Y = np.array([0 if y == 'setosa' else					#类别数值化
              1 if y == 'versicolor' else
              2 for y in Y])
print('鸢尾花种类数据:')
print(Y)

运行程序,输出

共有150个数据样本
鸢尾花特征数据:
[[5.1 3.5 1.4 0.2]
 [4.9 3.  1.4 0.2]
 [4.7 3.2 1.3 0.2]
...
 [6.5 3.  5.2 2. ]
 [6.2 3.4 5.4 2.3]
 [5.9 3.  5.1 1.8]]
鸢尾花种类数据:
[0 0 0 ... 2 2 2]

花萼的长度、宽度,花瓣的长度、宽度对鸢尾花的种类有明显的相关性。接下来我们要从数据集中随机选取一部分作为训练数据,训练LinearRegressor分类模型,然后用剩下的数据进行测试,评价训练效果。在前面的程序后添加以下代码

……
a = np.arange(m)									#数据项下标
np.random.seed(1248)
train = np.random.choice(a,m//3,replace=False)		#50个随机下标
test = np.setdiff1d(a,train)						#测试数据下标
iris = LinearRegressor()							#创建模型
print('随机抽取%d个样本作为训练数据。'%(m//3))
iris.fit(X[train],Y[train])							#训练模型
accuracy = iris.score(X[test],Y[test])				#测试
print('对其余%d个数据测试,分类正确率为%.2f'%(m-m//3,accuracy)+'%')

运行程序输出

………
随机抽取50个样本作为训练数据。
训练中...,稍候
9次迭代后完成训练。
对其余100个数据测试,分类正确率为100.00%

第1行的省略号表示前一程序的输出。从测试结果可见训练效果效果不错!

写博不易,敬请支持:
如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!


网站公告

今日签到

点亮在社区的每一天
去签到