机器学习西瓜书笔记(三) 第三章 线性模型 + 算法代码

第3章 线性模型

3.1 基本形式

给定由d个属性描述的示例x=(x1;x2;…;xd),其中xi是x的第i个属性上的取值,线性模型(linear model)试图学得一个通过属性的线性组合来进行预测的函数,即:
f ( x ) = w 1 x 1 + w 2 x 2 + . . . + w d x d + b f(x) = w_1x_1 + w_2x_2+...+w_dx_d +b f(x)=w1x1+w2x2+...+wdxd+b

一般用向量写成: f ( x ) = w T x + b f(x)=w^Tx+b f(x)=wTx+b, w = ( w 1 ; w 2 ; . . . ; w d ) w=(w_1;w_2;...;w_d) w=(w1;w2;...;wd)

线性模型形式简单、易于建模,但却蕴涵着机器学习中一些重要的基本思想许多功能更为强大的非线性模型(nonlinear model)可在线性模型的基础上 通过引入层级结构或高维映射而得。此外,由于w直观表达了各属性在预测中的重要性,因此线性模型有很好的可解释性(comprehensibility).例如若在西瓜问题中学得 " f好瓜 (x)=0.2x色泽+0.5X根蒂+0.3X敲声+1",则意味着可 通过综合考虑色泽、 根蒂和敲声来判断瓜好不好,其中根蒂最要紧,而敲声比色泽更重要。
本章主要介绍几种经典的线性模型。先从回归任务开始,然后讨论三分类和多分类任务。

3.2 线性回归

给定数据集 D = ( x 1 , y 1 ) , ( x 2 , y 2 ) , … , ( x m , y m ) D = {(x_1,y_1),(x_2,y_2),…,(x_m,y_m)} D=(x1,y1),(x2,y2),,(xm,ym),其中 x i = ( x i 1 ; x i 2 ; … ; x i d ) x_i = (x_{i1};x_{i2};…;x_{id}) xi=(xi1;xi2;;xid),线性回归试图学得一个线性模型以尽可能准确地预测实值,输出标记。即线性回归试图学得: f ( x i ) = w x i + b f(x_i)=wx_i+b f(xi)=wxi+b,使得 f ( x i ) ≈ y i f(x_i) \approx y_i f(xi)yi,可见关键在于确定w和b,也就是衡量f(x)与y之间的差别。而之前介绍过,均方误差是回归任务中最常用的性能度量,因此我们可试图让均方误差最小化,即: ( w ∗ , b ∗ ) = a r g m i n ( w , b ) ∑ i = 1 m ( f ( x i ) − y i ) 2 = a r g m i n ( w , b ) ∑ i = 1 m ( y i − w x i − b ) 2 (w^*,b^*)=argmin_{(w,b)}\sum_{i=1}^{m}(f(x_i)-y_i)^2=argmin_{(w,b)}\sum_{i=1}^{m}(y_i-wx_i-b)^2 (w,b)=argmin(w,b)i=1m(f(xi)yi)2=argmin(w,b)i=1m(yiwxib)2

均方误差有非常好的几何意义,它对应了常用的欧几里得距离。而基于均方误差最小化求解模型的方法被称为最小二乘法(least square method),在线性回归中,最小二乘法就是试图找到一条直线,使所有样本到直线上的欧式距离之和最小。
求解w和b使得上式最小化的过程,被称为线性回归模型的最小二乘参数估计(parameter estimation)。我们可将上式(记为 E ( w , b ) E(w,b) E(w,b))分别对 w w w b b b求导,得到:
∂ E ( w , b ) ∂ w = 2 ( w ∑ i = 1 m x i 2 − ∑ i = 1 m ( y i − b ) x i ) \frac{\partial E(w,b)}{\partial w}=2(w\sum_{i=1}^{m}x_i^2-\sum_{i=1}^{m}(y_i-b)x_i) wE(w,b)=2(wi=1mxi2i=1m(yib)xi)
∂ E ( w , b ) ∂ b = 2 ( m b − ∑ i = 1 m ( y i − w x i ) ) \frac{\partial E(w,b)}{\partial b} = 2(mb - \sum_{i=1}^m(y_i-wx_i)) bE(w,b)=2(mbi=1m(yiwxi)),即可得到w和b的最优解的闭式(closed-form)解。

更一般的情形如开头的数据集D,样本由d个属性描述,需要学习, f ( x i ) = w T x i + b f(x_i)=w^Tx_i+b f(xi)=wTxi+b,使得 f ( x i ) ≈ y i f(x_i) \approx y_i f(xi)yi此时被称为多元线性回归。此处依然可以用最小二乘法来求解,不同的是把w和b吸收入向量形式定义为 w ^ = ( w ; b ) \hat{w}=(w;b) w^=(w;b),把数据集D表示为一个 m × ( d + 1 ) m×(d+1) m×(d+1)大小的矩阵X,每行对应一个示例,则有如下:
在这里插入图片描述

同理把标记也写成向量模式, y = ( y 1 ; y 2 ; . . . ; y m ) y=(y_1;y_2;...;y_m) y=(y1;y2;...;ym),则有 w ^ ∗ = a r g m i n w ^ ( y − X w ^ ) T ( y − X w ^ ) \hat{w}^* = argmin_{\hat{w}} (y-X\hat{w})^T(y-X\hat{w}) w^=argminw^(yXw^)T(yXw^)

E w ^ = ( y − X w ^ ) T ( y − X w ^ ) E_{\hat{w}}=(y-X\hat{w})^T(y-X\hat{w}) Ew^=(yXw^)T(yXw^),对 w ^ \hat{w} w^求导则有: ∂ E w ^ ∂ w ^ = 2 X T ( X w ^ − y ) \frac{\partial E_{\hat{w}}}{\partial \hat{w}} = 2X^T(X\hat{w}-y) w^Ew^=2XT(Xw^y),上式为零即可得到最优解的闭式解。

如果 X T X X^TX XTX为满秩矩阵或者正定矩阵,那么令上式为零可有: w ^ ∗ = ( X T X ) − 1 X T y \hat{w}^*=(X^TX)^{-1}X^Ty w^=(XTX)1XTy,即可轻易得到多元线性回归模型。
然而现实中 X T X X^TX XTX往往不是满秩矩阵,许多任务中会遇到变量的数目超过样例数的情况,导致X的列数多于行数,显然不满秩,此时会解出多个 w ^ \hat{w} w^满足均方误差最小的条件,选择哪一个作为输出就是问题,常见的做法是引入正则化项。

假设认为示例所对应的输出标记是在指数尺度上变化的,那就可以将输出标记的对数作为线性模型逼近的目标,即: l n y = w T x + b lny = w^Tx+b lny=wTx+b,就是对数线性回归(log-linear regression),在形式上虽然仍然是线性回归,但实质是在求取输入空间到输出空间的非线性函数映射。如图所示:在这里插入图片描述

对数线性回归是让 y = l n y y=ln y y=lny,而如果令y变换为其他的形式,可以得到更多的线性回归函数。我们统称为"广义线性模型"。

总结

线性回归是一种统计学方法,用于建模和分析两个变量之间的关系:一个因变量和一个或多个自变量。它试图找到自变量和因变量之间的线性关系,这种关系通常用一个方程来表示,这个方程通常被称为线性回归方程。

线性回归的一般形式可以表示为:
y = W T x + b + ε y=W^Tx+b+ε y=WTx+b+ε
其中:y是因变量,即试图预测或估计的变量;X(向量)是自变量,即影响因变量的变量;b是截距项,即当所有自变量为零时,因变量的期望值;W^T(向量)是系数,表示自变量每变化一个单位时,因变量变化的量;ε是误差项,表示模型无法解释的随机变异。
线性回归模型的参数(系数和截距)通常通过最小化实际观测值与模型预测值之间的差异来估计,这个过程称为最小二乘法。

线性回归可以进一步分为:

  • 简单线性回归:只涉及一个自变量和一个因变量。
  • 多元线性回归:涉及两个或更多自变量。

线性回归是许多领域中常用的预测和分析工具,包括经济学、生物学、工程学等。然而,线性回归模型假设变量之间存在线性关系,如果这种假设不成立,模型的预测能力可能会受到影响。

3.3 对数几率回归

针对分类任务需找一个单调可微函数,将分类任务的真实标记y与线性回归模型的预测值联系起来。以二分类任务为例,输出标记为 y ∈ 0 , 1 y∈{0,1} y0,1,而线性回归模型产生的预测值 z = w T x + b z = w^Tx+b z=wTx+b是实值,故需将z转换为0/1值,于是想到单位阶跃函数:
在这里插入图片描述

即若预测值z大于零就判为正例;小于零则判为反例;预测值为临界值零则可任意判别。具体图示如下图所示:
在这里插入图片描述

由于阶跃函数不连续,故不能用作广义线性模型,故使用对数几率函数Sigmoid函数来代替阶跃函数。将对数几率函数代入之前所讲y中,有: y = 1 1 + e − ( w T x + b ) y = \frac{1}{1+e^{-(w^Tx+b)}} y=1+e(wTx+b)1,即 l n y 1 − y = w T x + b ln\frac{y}{1-y}=w^Tx+b ln1yy=wTx+b。由此看出,实际上是在用线性回归模型的预测结果去逼近真实标记的对数几率,因此,其对应的模型称为"对数几率回归"(logistic regression)。虽然名字是回归,但实际上是一种分类学习的方法。

那么上式的w和b如何确定呢?若将y视为后验概率估计,则上式可以重写为:
l n p ( y = 1 ∣ x ) p ( y = 0 ∣ x ) = w T x + b ln\frac{p(y=1|x)}{p(y=0|x)}=w^Tx+b lnp(y=0∣x)p(y=1∣x)=wTx+b,显然可以得到: p ( y = 1 ∣ x ) = e w T x + b 1 + e w T x + b p(y=1|x)=\frac{e^{w^Tx+b}}{1+e^{w^Tx+b}} p(y=1∣x)=1+ewTx+bewTx+b

利用最大似然法(maximum likelihood method)来估计w和b。此时对率回归模型最大化"对数似然"(log-likelihood),即令每个样本属于其真实标记的概率越大越好。:
l ( w , b ) = ∑ i = 1 m l n p ( y i ∣ x i ; w , b ) l(w,b)=\sum_{i=1}^{m}lnp(y_i|x_i;w,b) l(w,b)=i=1mlnp(yixi;w,b)

β = ( w ; b ) \beta =(w; b) β=(w;b), x ^ =( x ; 1 ) \hat{x}=(x;1) x^=(x;1),则 w T x + b w^Tx+b wTx+b可简写为 β T x ^ \beta^T\hat{x} βTx^,令 p 1 ( x ^ ; β ) = p ( y = 1 ∣ x ^ ; β ) p_1(\hat{x};\beta)=p(y=1|\hat{x};\beta) p1(x^;β)=p(y=1∣x^;β) p 0 ( x ^ ; β ) = p ( y = 0 ∣ x ^ ; β ) = 1 − p 1 ( x ^ ; β ) p_0(\hat{x};\beta)=p(y=0|\hat{x};\beta) = 1 - p_1(\hat{x};\beta) p0(x^;β)=p(y=0∣x^;β)=1p1(x^;β),则似然项重写为 l n p ( y i ∣ x i ; w , b ) = y i p 1 ( x ^ ; β ) + ( 1 − y i ) p 0 ( x ^ ; β ) lnp(y_i|x_i;w,b) = y_ip_1(\hat{x};\beta)+(1-y_i)p_0(\hat{x};\beta) lnp(yixi;w,b)=yip1(x^;β)+(1yi)p0(x^;β)。此时,最大化似然等价于最小化 l ( β ) = ∑ i = 1 m ( − y i β T x ^ i + l n ( 1 + e β T x ^ i ) ) l(\beta)=\sum_{i=1}^{m}(-y_i\beta^T\hat{x}_i+ln(1+e^{\beta^T\hat{x}_i})) l(β)=i=1m(yiβTx^i+ln(1+eβTx^i)),其最优解为 β ∗ = a r g m i n β l ( β ) \beta^* = argmin_{\beta}l(\beta) β=argminβl(β)。并可采用牛顿法、梯度下降法等方法迭代求解。

总结:
对数几率回归(Logistic Regression),又称逻辑回归,是一种广义线性模型,专门用于处理因变量为二分类问题的情况。在二分类问题中,因变量通常表示为0和1,分别代表两个不同的类别或结果。

对数几率回归的核心是使用逻辑斯蒂函数(Logistic Function),也称为Sigmoid函数,将线性回归模型的输出映射到0和1之间,以表示概率。逻辑斯蒂函数的公式为:
σ ( z ) = 1 1 + e − z \sigma(z) = \frac{1}{1 + e^{-z}} σ(z)=1+ez1
其中, z z z 是模型的线性组合,即 z = w T x + b z =w^Tx+b z=wTx+b

在对数几率回归中,我们试图预测的是发生某个事件(如类别1)的概率,这个概率可以表示为:
P ( Y = 1 ) = σ ( w T x + b ) P(Y=1) = \sigma (w^Tx+b) P(Y=1)=σ(wTx+b),其中,P(Y=1)是因变量取值为1的概率。

对数几率回归的参数估计通常通过最大似然估计(MLE)来完成。模型的似然函数是所有观测数据点的联合概率的乘积,而最大似然估计则是找到参数值,使得这个似然函数最大化。

对数几率回归的模型形式可以表示为:
$ \log\left(\frac{P(Y=1)}{1 - P(Y=1)}\right) = w^Tx+b $
这里的 $ \log\left(\frac{P(Y=1)}{1 - P(Y=1)}\right) $称为对数几率(Log Odds),也就是逻辑斯蒂函数的输入。

对数几率回归的优点包括:

  • 模型简单,易于理解和实现。
  • 可以给出分类结果的概率解释。
  • 通过最大似然估计,可以自然地进行参数的估计和模型的拟合。

然而,对数几率回归也有一些局限性:

  • 它假设数据是线性可分的,即在特征空间中,两个类别可以通过一个线性超平面分开。
  • 对于非线性问题,可能需要更复杂的模型或特征工程来提高性能。

在实际应用中,对数几率回归通常作为分类问题的基线模型,与其他更复杂的机器学习模型进行比较。

3.4 线性判别分析

线性判别分析(Linear Discriminant Analysis,简称LDA)是一种经典的线性学习方法,由于其最早被Fisher提出,故又名"Fisher判别分析"。
LDA 的思想非常朴素: 给定训练样例集,设法将样例投影到一条直线上,使得同类样例的投影点尽可能接近、异类样例的投影点尽可能远离;在对新样本进行分类时,将其投影到同样的这条直线上,再根据投影点的位置来确定新样本的类别。
在这里插入图片描述

给定数据集 D = ( x i , y i ) i = 1 m D={(x_i,y_i)}_{i=1}^m D=(xi,yi)i=1m,令 X i 、 µ i 、 ∑ i X_i、µ_i、\sum_i Xiµii分别表示第 i ∼ 0 , 1 i\sim {0,1} i0,1类示例的集合、均值向量、协方差矩阵。若将数据投影到直线w上,则两类样本的中心在直线上的投影分别为 w T µ 0 w^Tµ_0 wTµ0 w T µ 1 w^Tµ_1 wTµ1。若将所有样本点都投影到直线上,则两类样本的协方差分别为 w T ∑ 0 w w^T\sum_0w wT0w w T ∑ 1 w w^T\sum_1w wT1w。由于直线是一维空间,因此 w T µ 0 w^Tµ_0 wTµ0 w T µ 1 w^Tµ_1 wTµ1 w T ∑ 0 w w^T\sum_0w wT0w w T ∑ 1 w w^T\sum_1w wT1w均为实数。

欲使同类样例的投影点尽可能接近,可以让同类样例投影点的协方差尽可能小,即 w T ∑ 0 w + w T ∑ 1 w w^T\sum_0w+w^T\sum_1w wT0w+wT1w尽可能小;而欲使异类样例的投影点尽可能远离,可以让类中心之间的距离尽可能大,即 ∣ ∣ w T µ 0 − w T µ 1 ∣ ∣ 2 2 ||w^Tµ_0-w^Tµ_1||_2^2 ∣∣wTµ0wTµ122尽可能大。同时考虑二者,则可得到欲最大化的目标
J = ∣ ∣ w T µ 0 − w T µ 1 ∣ ∣ 2 2 w T ∑ 0 w + w T ∑ 1 w = w T ( µ 0 − µ 1 ) ( µ 0 − µ 1 ) T w w T ( ∑ 0 + ∑ 1 ) w J=\frac{||w^Tµ_0-w^Tµ_1||_2^2}{w^T\sum_0w+w^T\sum_1w} = \frac{w^T(µ_0-µ_1)(µ_0-µ_1)^Tw}{w^T(\sum_0+\sum_1)w} J=wT0w+wT1w∣∣wTµ0wTµ122=wT(0+1)wwT(µ0µ1)(µ0µ1)Tw

定义"类内散度矩阵"(within-class scatter matrix) S w = ∑ 0 + ∑ 1 = ∑ x ∼ X 0 ( x − µ 0 ) ( x − µ 0 ) T + ∑ x ∼ X 1 ( x − µ 1 ) ( x − µ 1 ) T S_w=\sum_0+\sum_1=\sum_{x\sim X_0}(x-µ_0)(x-µ_0)^T+\sum_{x\sim X_1}(x-µ_1)(x-µ_1)^T Sw=0+1=xX0(xµ0)(xµ0)T+xX1(xµ1)(xµ1)T
和"类间散度矩阵"(between-class scatter matrix) S b = ( µ 0 − µ 1 ) ( µ 0 − µ 1 ) T S_b=(µ_0-µ_1)(µ_0-µ_1)^T Sb=(µ0µ1)(µ0µ1)T,则上式重写为: J = w T S b w w T S w w J=\frac{w^TS_bw}{w^TS_ww} J=wTSwwwTSbw,这就是LDA欲最大化的目标,即 S b S_b Sb S w S_w Sw的"广义瑞利商"。

关键在于w的确定,由于上式分子与分母都是关于w的二次项,故其的解与w的长度无关,只与其方向有关,不防令 w T S w w w^TS_ww wTSww = 1,则上式等价于: m i n w − w T S b w , s . t . w T S w w = 1 min_w -w^TS_bw, s.t. w^TS_ww=1 minwwTSbw,s.t.wTSww=1。由拉格朗日乘子法,上式等价于: S b w = λ S w w S_bw=\lambda S_ww Sbw=λSww
λ是拉格朗日乘子,由于 S b w S_bw Sbw的方向恒为 μ 0 − μ 1 μ_0-μ_1 μ0μ1,故不妨令 S b w = λ ( μ 0 − μ 1 ) S_bw=\lambda(μ_0-μ_1) Sbw=λ(μ0μ1),代入式中可以得到: w = S w − 1 ( μ 0 − μ 1 ) w=S_w^{-1}(μ_0-μ_1) w=Sw1(μ0μ1),由此即得到了w的具体计算方法。

可以将LDA推广到多分类任务中。假定存在N个类且第i类示例数为 m i m_i mi,先定义"全局散度矩阵", S t = S b + S w = ∑ i = 1 m ( x i − μ ) ( x i − μ ) T S_t=S_b+S_w=\sum_{i=1}^{m}(x_i-\mu)(x_i-\mu)^T St=Sb+Sw=i=1m(xiμ)(xiμ)T,其中μ是所有示例的均值向量。将类内散度矩阵 S w S_w Sw重定义为每个类别的散度矩阵之和,即 S w = ∑ i = 1 N S w i S_w=\sum_{i=1}^{N}S_{w_i} Sw=i=1NSwi,其中 S w i = ∑ x ∼ X i ( x − μ i ) ( x − μ i ) T S_{w_i}=\sum_{x\sim X_i}(x-\mu_i)(x-\mu_i)^T Swi=xXi(xμi)(xμi)T S b = S t − S w = ∑ i = 1 N m i ( μ i − μ ) ( μ i − μ ) T S_b=S_t - S_w=\sum_{i=1}^{N}m_i(\mu_i-\mu)(\mu_i-\mu)^T Sb=StSw=i=1Nmi(μiμ)(μiμ)T。可见使用以上三个散度矩阵的任意两个,都可以多分类实现LDA。对于多分类任务,常见的一种实现是采用优化目标: m a x W t r ( W T S b W ) t r ( W T S w W ) max_W\frac{tr(W^TS_bW)}{tr(W^TS_wW)} maxWtr(WTSwW)tr(WTSbW),其中 W ∈ R d ( N − 1 ) W \in R^{d(N-1)} WRd(N1),tr表示矩阵的迹。上式可以用下式广义特征值问题求解: S b W = λ S w W S_bW=\lambda S_wW SbW=λSwW。W的闭式解其实是 S w − 1 S b S_w^{-1}S_b Sw1Sb的N-1个最大广义特征值所对应的特征向量组成的矩阵。
若将W视为一个投影矩阵,则LDA将样本投影到了N-1维空间上,N-1往往远小于数据原有的属性数,于是,LDA也常被视为一种经典的监督降维技术。

3.5 多分类学习

在现实中,所遇到的大多数问题其实是多分类学习任务。考虑N个类别 C 1 … C N C_1…C_N C1CN,多分类学习的基本思路是"拆解法",即将多分类任务拆为若干个二分类任务求解。最经典的拆分策略有三种:“一对一”(one vs. one ,OvO),“一对其余”(One vs. Rest, OvR),和"多对多"(Many vs. Many, MvM)。
一对一的基本思想如下:将数据集中的N个类别两两配对,产生N(N-1)/2个二分类任务。在测试时,把新样本同时交给所有分类器,于是得到N(N-1)/2个分类结果,最终结果可以通过投票产生;即把被预测的最多的类别别作为最终结果。
一对其余的思想如下:每次将一个类的样例作为正类,其他都作为反类来训练N个分类器。在测试时若只有一个分类器预测为正类,则对应的类别标记为最终结果,若有多个分类器预测为正类,则考虑各分类器的预测置信度,选择置信度最大的类别标记作为分类结果。下图为OvO和OvR简单的示意图:
在这里插入图片描述

容易看出,OvR只需训练N个分类器,而OvO需训练N(N-1)/2个分类器,因此,OvO的存储开销和测试时间开销通常比OvR更大。但在训练时,OvR的每个分类器均使用全部训练样例,而OvO的每个分类器仅用到两个类的样例,因此,在类别很多时。OvO的训练时间开销通常比OvR更小,至于预测性能,则取决于具体的数据分布,在多数情形下两者差不多。

MvM是每次将若干个类作为正类,若干个其他类作为反类。显然,OvO和OvR是MvM的特例。MvM的正、反类构造必须有特殊的设计,不能随意选取。一种最常用的MvM技术:“纠错输出码、”(Error Correcting Output Codes,简称ECOC),其思想引入类别拆分,并尽可能在解码过程中具有容错性。ECOC工作过程主要分为两步:

编码:对N个类别做M次划分,每次划分将一部分类别划为正类,一部分划为反类从而形成一个二分类训练集;这样一共产生M个训练集,可训练出M个分类器

解码:M个分类器分别对测试样本进行预测,这些预测标记组成一个编码。将这个预测编码与每个类别各自的编码进行比较,返回其中距离最小的类别作为最终预测结果。

类别划分通过"编码矩阵" (coding matrix)指定,常见的主要有二元码和三元码。前者将每个类别分别指定为正类和反类,后者在正、反类之外,还可指定"停用类",示意图中,分类器f2将C1类和C3类的样例作为正例,Q类和C4类的样例作为反例; 在图3.5(b)中,分类器f4将C1类和C4类的样例作为正例,C3类的样例作为反例。在解码阶段,各分类器的预测结果联合起来形成了测试示例的编码,该编码与各类所对应的编码进行比较,将距离最小的编码所对应的类别作为预测结果。图中,若基于欧氏距离,预测结果将是C3。

在这里插入图片描述

3.6 类别不平衡问题

前面所述分类学习方法都有一个共同的基本假设:不同类别的训练样例数目相同。类别不平衡(class-imbalance)就是指分类任务中不同类别的训练样例数目差别很大的情况。

本文假设反例数目远大于正例,原本类别平衡时,以二分类为例,分类临界是正:反=1:1得到的0.5。但类别不平衡时,比如3:7,这时预测临界应当是0.7。但原本分类器的临界还是0.5,这时需要对预测进行"再缩放"(rescaling),将正例和反例的分类结果与反例样本数:正例样本数的比值象处理,以平衡掉原本类别不平衡带来的预测偏差。

目前有三类做法:
直接对训练集的反类样例进行"欠采样",即去除一些反例使得正反例数目接近。
对训练集的正例进行"过采样",即增加一些正例使得正反例数目相似。
第三类则是基于原始训练集进行学习,在用训练好的分类器进行预测时再进行其他操作。

3.7 代码

线性回归

import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets, linear_model
from sklearn.metrics import mean_squared_error, r2_score

# Load the diabetes dataset
diabetes_X, diabetes_y = datasets.load_diabetes(return_X_y=True)

# Use only one feature
diabetes_X = diabetes_X[:, np.newaxis, 2]

# Split the data into training/testing sets
diabetes_X_train = diabetes_X[:-20]
diabetes_X_test = diabetes_X[-20:]

# Split the targets into training/testing sets
diabetes_y_train = diabetes_y[:-20]
diabetes_y_test = diabetes_y[-20:]

# Create linear regression object
regr = linear_model.LinearRegression()

# Train the model using the training sets
regr.fit(diabetes_X_train, diabetes_y_train)

# Make predictions using the testing set
diabetes_y_pred = regr.predict(diabetes_X_test)

# The coefficients
print('Coefficients: \n', regr.coef_)
# The mean squared error
print('Mean squared error: %.2f'
      % mean_squared_error(diabetes_y_test, diabetes_y_pred))
# The coefficient of determination: 1 is perfect prediction
print('Coefficient of determination: %.2f'
      % r2_score(diabetes_y_test, diabetes_y_pred))

# Plot outputs
plt.scatter(diabetes_X_test, diabetes_y_test,  color='black')
plt.plot(diabetes_X_test, diabetes_y_pred, color='blue', linewidth=3)

plt.xticks(())
plt.yticks(())

plt.show()

在这里插入图片描述

对数几率回归

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.linear_model import LogisticRegression

# make 3-class dataset for classification
centers = [[-5, 0], [0, 1.5], [5, -1]]
X, y = make_blobs(n_samples=1000, centers=centers, random_state=40)
transformation = [[0.4, 0.2], [-0.4, 1.2]]
X = np.dot(X, transformation)

for multi_class in ('multinomial', 'ovr'):#多类分割 或者 one vs rest分割
    clf = LogisticRegression(solver='sag', max_iter=100, random_state=42,
                             multi_class=multi_class).fit(X, y)

    # print the training scores
    print("training score : %.3f (%s)" % (clf.score(X, y), multi_class))

    # create a mesh to plot in
    h = .02  # step size in the mesh
    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                         np.arange(y_min, y_max, h))

    # Plot the decision boundary. For that, we will assign a color to each
    # point in the mesh [x_min, x_max]x[y_min, y_max].
    Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
    # Put the result into a color plot
    Z = Z.reshape(xx.shape)
    plt.figure()
    plt.contourf(xx, yy, Z, cmap=plt.cm.Paired)
    plt.title("Decision surface of LogisticRegression (%s)" % multi_class)
    plt.axis('tight')

    # Plot also the training points
    colors = "bry"
    for i, color in zip(clf.classes_, colors):
        idx = np.where(y == i)
        plt.scatter(X[idx, 0], X[idx, 1], c=color, cmap=plt.cm.Paired,
                    edgecolor='black', s=20)

    # Plot the three one-against-all classifiers
    xmin, xmax = plt.xlim()
    ymin, ymax = plt.ylim()
    coef = clf.coef_
    intercept = clf.intercept_

    def plot_hyperplane(c, color):
        def line(x0):
            return (-(x0 * coef[c, 0]) - intercept[c]) / coef[c, 1]
        plt.plot([xmin, xmax], [line(xmin), line(xmax)],
                 ls="--", color=color)

    for i, color in zip(clf.classes_, colors):
        plot_hyperplane(i, color)

plt.show()

在这里插入图片描述

线性判别分析

from scipy import linalg
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mapl
from matplotlib import colors

from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis

# #############################################################################
# Colormap
cmap = colors.LinearSegmentedColormap(
    'red_blue_classes',
    {'red': [(0, 1, 1), (1, 0.7, 0.7)],
     'green': [(0, 0.7, 0.7), (1, 0.7, 0.7)],
     'blue': [(0, 0.7, 0.7), (1, 1, 1)]})
plt.cm.register_cmap(cmap=cmap)


# #############################################################################
# Generate datasets
def dataset_fixed_cov():
    '''Generate 2 Gaussians samples with the same covariance matrix'''
    n, dim = 300, 2
    np.random.seed(0)
    C = np.array([[0., -0.23], [0.83, .23]])
    X = np.r_[np.dot(np.random.randn(n, dim), C),
              np.dot(np.random.randn(n, dim), C) + np.array([1, 1])]
    y = np.hstack((np.zeros(n), np.ones(n)))
    return X, y


def dataset_cov():
    '''Generate 2 Gaussians samples with different covariance matrices'''
    n, dim = 300, 2
    np.random.seed(0)
    C = np.array([[0., -1.], [2.5, .7]]) * 2.
    X = np.r_[np.dot(np.random.randn(n, dim), C),
              np.dot(np.random.randn(n, dim), C.T) + np.array([1, 4])]
    y = np.hstack((np.zeros(n), np.ones(n)))
    return X, y


# #############################################################################
# Plot functions
def plot_data(lda, X, y, y_pred, fig_index):
    splot = plt.subplot(2, 2, fig_index)
    if fig_index == 1:
        plt.title('Linear Discriminant Analysis')
        plt.ylabel('Data with\n fixed covariance')
    elif fig_index == 3:
        plt.ylabel('Data with\n varying covariances')

    tp = (y == y_pred)  # True Positive
    tp0, tp1 = tp[y == 0], tp[y == 1]
    X0, X1 = X[y == 0], X[y == 1]
    X0_tp, X0_fp = X0[tp0], X0[~tp0]
    X1_tp, X1_fp = X1[tp1], X1[~tp1]

    # class 0: dots
    plt.scatter(X0_tp[:, 0], X0_tp[:, 1], marker='.', color='red')
    plt.scatter(X0_fp[:, 0], X0_fp[:, 1], marker='x',
                s=20, color='#990000')  # dark red

    # class 1: dots
    plt.scatter(X1_tp[:, 0], X1_tp[:, 1], marker='.', color='blue')
    plt.scatter(X1_fp[:, 0], X1_fp[:, 1], marker='x',
                s=20, color='#000099')  # dark blue

    # class 0 and 1 : areas
    nx, ny = 200, 100
    x_min, x_max = plt.xlim()
    y_min, y_max = plt.ylim()
    xx, yy = np.meshgrid(np.linspace(x_min, x_max, nx),
                         np.linspace(y_min, y_max, ny))
    Z = lda.predict_proba(np.c_[xx.ravel(), yy.ravel()])
    Z = Z[:, 1].reshape(xx.shape)
    plt.pcolormesh(xx, yy, Z, cmap='red_blue_classes',
                   norm=colors.Normalize(0., 1.), zorder=0)
    plt.contour(xx, yy, Z, [0.5], linewidths=2., colors='white')

    # means
    plt.plot(lda.means_[0][0], lda.means_[0][1],
             '*', color='yellow', markersize=15, markeredgecolor='grey')
    plt.plot(lda.means_[1][0], lda.means_[1][1],
             '*', color='yellow', markersize=15, markeredgecolor='grey')

    return splot


def plot_ellipse(splot, mean, cov, color):
    v, w = linalg.eigh(cov)
    u = w[0] / linalg.norm(w[0])
    angle1 = np.arctan(u[1] / u[0])
    angle1 = 180 * angle1 / np.pi  # convert to degrees
    # filled Gaussian at 2 standard deviation
    ell = mapl.patches.Ellipse(xy=mean, width=2 * v[0] ** 0.5, height=2 * v[1] ** 0.5,
                              angle= 180 + angle1, facecolor=color,
                              edgecolor='black', linewidth=2)
    ell.set_clip_box(splot.bbox)
    ell.set_alpha(0.2)
    splot.add_artist(ell)
    splot.set_xticks(())
    splot.set_yticks(())


def plot_lda_cov(lda, splot):
    plot_ellipse(splot, lda.means_[0], lda.covariance_, 'red')
    plot_ellipse(splot, lda.means_[1], lda.covariance_, 'blue')



plt.figure(figsize=(8, 8), facecolor='white')
for i, (X, y) in enumerate([dataset_fixed_cov(), dataset_cov()]):
    # Linear Discriminant Analysis
    lda = LinearDiscriminantAnalysis(solver="svd", store_covariance=True)
    y_pred = lda.fit(X, y).predict(X)
    splot = plot_data(lda, X, y, y_pred, fig_index=2 * i + 1)
    plot_lda_cov(lda, splot)
    plt.axis('tight')

plt.tight_layout()
plt.subplots_adjust(top=0.92)
plt.show()

在这里插入图片描述

总结

机器学习西瓜书第三章是关于线性模型的介绍,主要内容包括:

  1. 线性模型的基本形式:线性模型通过属性的线性组合来进行预测,通常表示为 f ( x ) = w T x + b f(x) = w^Tx + b f(x)=wTx+b,其中w是权重向量,b是偏置项。

  2. 线性模型的特点:形式简单,易于建模,具有很好的可解释性。权重w直观地表达了各属性在预测中的重要性。

  3. 线性回归:目标是学习一个线性模型以预测实值输出,使用数据集D进行训练。

  4. 对数几率回归:用于二分类问题,通过极大似然法估计权重w和偏置b,最大化对数似然函数。

  5. 线性判别分析(LDA):一种经典的方法,旨在找到一条直线,使得同类样本投影点尽可能接近,异类样本投影点尽可能远离。LDA可以推广到多分类任务,和降维任务。

  6. 多分类学习:介绍了两种多分类策略,One-vs-Rest(OvR)和One-vs-One(OvO),以及纠错输出码(ECOC)技术,用于提高分类器的容错性。

  7. ECOC:通过编码矩阵将类别划分为正类和反类,训练多个二分类器,然后在解码阶段根据预测编码与类别编码的距离来确定最终预测结果。

文档强调了线性模型的可理解性和在机器学习中的基础地位,同时介绍了几种经典的线性模型及其在分类任务中的应用。

  • 13
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我喝AD钙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值