房价预测
销售额预测
贷款额度预测
线性关系举例:
线性回归(Linear regression)是利用回归方程(函数)对一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方式。
特点:只有一个自变量的情况称为单变量回归,多于一个自变量情况的叫做多元回归。
通用公式
h ( w ) = w 1 x 1 + w 2 x 2 + w 3 x 3 + . . . + b = w T x + b h(w)=w{_1}x{_1}+w{_2}x{_2}+w{_3}x{_3}+...+b=w^Tx+b h(w)=w1x1+w2x2+w3x3+...+b=wTx+b
其中w x可以理解为矩阵:
w = ( b w 1 w 2 ⋮ ) w= \begin{pmatrix} b \\ w{_1} \\ w{_2} \\ \vdots \end{pmatrix} w=⎝⎜⎜⎜⎛bw1w2⋮⎠⎟⎟⎟⎞
x = ( 1 x 1 x 2 ⋮ ) x= \begin{pmatrix} 1 \\ x{_1} \\ x{_2}\\\vdots \end{pmatrix} x=⎝⎜⎜⎜⎛1x1x2⋮⎠⎟⎟⎟⎞
线性回归用矩阵表示举例 { 1 × x 1 + x 2 = 2 0 × x 1 + x 2 = 2 2 × x 1 + x 2 = 3 \begin{cases}1 \times x{_1} + x{_2} = 2 \\ 0 \times x{_1} + x{_2} = 2 \\ 2 \times x{_1} + x{_2} = 3 \end{cases} ⎩⎪⎨⎪⎧1×x1+x2=20×x1+x2=22×x1+x2=3
写成矩阵形式: { 1 × x 1 + x 2 = 2 0 × x 1 + x 2 = 2 2 × x 1 + x 2 = 3 \begin{cases}1 \times x{_1} + x{_2} = 2 \\ 0 \times x{_1} + x{_2} = 2 \\ 2 \times x{_1} + x{_2} = 3 \end{cases} ⎩⎪⎨⎪⎧1×x1+x2=20×x1+x2=22×x1+x2=3
从列的角度看:
KaTeX parse error: No such environment: split at position 8: \begin{̲s̲p̲l̲i̲t̲}̲ &\begin{bmatri…
那么怎么理解呢?我们来看几个例子
上面两个例子,我们看到特征值与目标值之间建立了一个关系,这个关系可以理解为线性模型。
线性回归当中主要有两种模型,**一种是线性关系,另一种是非线性关系。**在这里我们只能画一个平面更好去理解,所以都用单个特征或两个特征举例子。
线性关系
多变量线性关系
注释:单特征与目标值的关系呈直线关系,或者两个特征与目标值呈现平面的关系
更高维度的我们不用自己去想,记住这种关系即可
非线性关系
注释:为什么会这样的关系呢?原因是什么?
如果是非线性关系,那么回归方程可以理解为:
w 1 x 1 + w 2 x 2 2 + w 3 x 3 2 w_1x_1+w_2x_2^2+w_3x_3^2 w1x1+w2x22+w3x32
from sklearn.linear_model import LinearRegression
x = [[80, 86],
[82, 80],
[85, 78],
[90, 90],
[86, 82],
[82, 90],
[78, 80],
[92, 94]]
y = [84.2, 80.6, 80.1, 90, 83.2, 87.6, 79.4, 93.4]
# 实例化API
estimator = LinearRegression()
# 使用fit方法进行训练,得到模型
estimator.fit(x,y)
# 打印回归系数(每个特征列前的系数)
estimator.coef_
# 打印截距
estimator.intercept_
# 利用训练的模型进行预测
estimator.predict([[100, 80]])
导数(Derivative),也叫导函数值。又名微商,是微积分中的重要基础概念。
导数是函数的局部性质。一个函数在某一点的导数描述了这个函数在这一点附近的变化率。
不是所有的函数都有导数,一个函数也不一定在所有的点上都有导数。
对于可导的函数f(x),x↦f’(x)也是一个函数,称作f(x)的导函数(简称导数)。寻找已知的函数在某点的导数或其导函数的过程称为求导
公式 | 例子 |
---|---|
( C ) ′ = 0 (C)^\prime=0 (C)′=0 | ( 5 ) ′ = 0 \left(5\right)^\prime=0 (5)′=0 ( 10 ) ′ = 0 \left(10\right)^\prime=0 (10)′=0 |
( x α ) ′ = α x α − 1 \left(x^\alpha\right)^\prime=\alpha x^{\alpha-1} (xα)′=αxα−1 | ( x 3 ) ′ = 3 x 2 \left(x^3\right)^\prime=3 x^{2} (x3)′=3x2 ( x 5 ) ′ = 5 x 4 \left(x^5\right)^\prime=5 x^{4} (x5)′=5x4 |
( a x ) ′ = a x ln a \left(a^x\right)^\prime=a^{x}\ln{a} (ax)′=axlna | ( 2 x ) ′ = 2 x ln 2 \left(2^x\right)^\prime=2^x\ln{2} (2x)′=2xln2 ( 7 x ) ′ = 7 x ln 7 \left(7^x\right)^\prime=7^x\ln{7} (7x)′=7xln7 |
( e x ) ′ = e x \left(e^x\right)^\prime=e^{x} (ex)′=ex | ( e x ) ′ = e x \left(e^x\right)^\prime=e^{x} (ex)′=ex |
( log a x ) ′ = 1 x ln a \left(\log{_a}x\right)^\prime=\frac{1}{x\ln{a}} (logax)′=xlna1 | ( log 10 x ) ′ = 1 x ln 10 \left(\log{_{10}}x\right)^\prime=\frac{1}{x\ln{10}} (log10x)′=xln101 ( log 6 x ) ′ = 1 x ln 6 \left(\log{_{6}}x\right)^\prime=\frac{1}{x\ln{6}} (log6x)′=xln61 |
( ln x ) ′ = 1 x \left(\ln{x}\right)^\prime=\frac{1}{x} (lnx)′=x1 | ( ln x ) ′ = 1 x \left(\ln{x}\right)^\prime=\frac{1}{x} (lnx)′=x1 |
( sin x ) ′ = cos x \left(\sin{x}\right)^\prime=\cos{x} (sinx)′=cosx | ( sin x ) ′ = cos x \left(\sin{x}\right)^\prime=\cos{x} (sinx)′=cosx |
( cos x ) ′ = − sin x \left(\cos{x}\right)^\prime=-\sin{x} (cosx)′=−sinx | ( cos x ) ′ = − sin x \left(\cos{x}\right)^\prime=-\sin{x} (cosx)′=−sinx |
公式 | 例子 |
---|---|
[ u ( x ) ± v ( x ) ] ′ = u ′ ( x ) ± v ′ ( x ) \left[u(x)\pm v(x)\right]^\prime=u^\prime(x) \pm v^\prime(x) [u(x)±v(x)]′=u′(x)±v′(x) | ( e x + 4 ln x ) ′ = ( e x ) ′ + ( 4 ln x ) ′ = e x + 4 x (e^x+4\ln{x})^\prime=(e^x)^\prime+(4\ln{x})^\prime=e^x+\frac{4}{x} (ex+4lnx)′=(ex)′+(4lnx)′=ex+x4 |
[ u ( x ) ⋅ v ( x ) ] ′ = u ′ ( x ) ⋅ v ( x ) + u ( x ) ⋅ v ′ ( x ) \left[u(x)\cdot v(x)\right]^\prime=u^\prime(x) \cdot v(x) + u(x) \cdot v^\prime(x) [u(x)⋅v(x)]′=u′(x)⋅v(x)+u(x)⋅v′(x) | ( sin x ⋅ ln x ) ′ = cos x ⋅ ln x + sin x ⋅ 1 x (\sin{x}\cdot\ln{x})^\prime=\cos{x}\cdot\ln{x}+\sin{x}\cdot\frac{1}{x} (sinx⋅lnx)′=cosx⋅lnx+sinx⋅x1 |
[ u ( x ) v ( x ) ] ′ = u ′ ( x ) ⋅ v ( x ) − u ( x ) ⋅ v ′ ( x ) v 2 ( x ) \left[\frac{u(x)}{v(x)}\right]^\prime=\frac{u^\prime(x) \cdot v(x) - u(x) \cdot v^\prime(x)}{v^2(x)} [v(x)u(x)]′=v2(x)u′(x)⋅v(x)−u(x)⋅v′(x) | ( e x cos x ) ′ = e x ⋅ cos x − e x ⋅ ( − sin x ) c o s 2 ( x ) \left(\frac{e^x}{\cos{x}}\right)^\prime=\frac{e^x\cdot\cos{x}-e^x\cdot(-\sin{x})}{cos^2(x)} (cosxex)′=cos2(x)ex⋅cosx−ex⋅(−sinx) |
{ g [ h ( x ) ] } ′ = g ′ ( h ) ∗ h ′ ( x ) \{g[h(x)]\}^\prime=g^\prime(h)*h^\prime(x) {g[h(x)]}′=g′(h)∗h′(x) | ( sin 2 x ) ′ = cos 2 x ⋅ ( 2 x ) ′ = 2 cos ( 2 x ) (\sin{2x})^\prime=\cos{2x}\cdot(2x)^\prime=2\cos(2x) (sin2x)′=cos2x⋅(2x)′=2cos(2x) |
y = x 3 − 2 x 2 + s i n x y = x^3-2x^2+sinx y=x3−2x2+sinx,求 f ′ ( x ) f^\prime(x) f′(x)
( e x + 4 l n x ) ′ (e^x+4lnx)^\prime (ex+4lnx)′
( s i n x ∗ l n x ) ′ (sinx*lnx)^\prime (sinx∗lnx)′
( e x c o s x ) ′ (\frac{e^x}{cosx})^\prime (cosxex)′
y = sin 2 x y=\sin2x y=sin2x, 求 d y d x \frac{dy}{dx} dxdy
( e 2 x ) ′ (e^{2x})^\prime (e2x)′
答案:
y ′ = ( x 3 − 2 x 2 + sin x ) ′ = ( x 3 ) ′ − ( 2 x 2 ) ′ + ( sin x ) ′ = 3 x 2 − 4 x + cos x y^\prime=(x^3-2x^2+\sin{x})^\prime=(x^3)^\prime-(2x^2)^\prime+(\sin{x})^\prime = 3x^2-4x+\cos{x} y′=(x3−2x2+sinx)′=(x3)′−(2x2)′+(sinx)′=3x2−4x+cosx
( e x + 4 l n x ) ′ = ( e x ) ′ + ( 4 ln x ) ′ = e x + 4 x (e^x+4lnx)^\prime=(e^x)^\prime+(4\ln{x})^\prime=e^x+\frac{4}{x} (ex+4lnx)′=(ex)′+(4lnx)′=ex+x4
( s i n x ∗ l n x ) ′ = ( sin x ) ′ ⋅ ln x + sin x ⋅ ( ln x ) ′ = cos x ⋅ ln x + sin x ⋅ 1 x (sinx*lnx)^\prime=(\sin{x})^\prime\cdot\ln{x}+\sin{x}\cdot(\ln{x})^\prime=\cos{x}\cdot\ln{x}+\sin{x}\cdot\frac{1}{x} (sinx∗lnx)′=(sinx)′⋅lnx+sinx⋅(lnx)′=cosx⋅lnx+sinx⋅x1
( e x cos x ) ′ = ( e x ) ′ ⋅ cos x − e x ⋅ ( cos x ) ′ cos 2 x = e x ⋅ cos x − e x ⋅ ( − sin x ) cos 2 ( x ) \left(\frac{e^x}{\cos{x}}\right)^\prime=\frac{(e^x)^\prime\cdot\cos{x}-e^x\cdot(\cos{x})\prime}{\cos^2{x}}=\frac{e^x\cdot\cos{x}-e^x\cdot(-\sin{x})}{\cos^2(x)} (cosxex)′=cos2x(ex)′⋅cosx−ex⋅(cosx)′=cos2(x)ex⋅cosx−ex⋅(−sinx)
( sin 2 x ) ′ = cos 2 x ⋅ ( 2 x ) ′ = 2 cos ( 2 x ) (\sin{2x})^\prime=\cos{2x}\cdot(2x)^\prime=2\cos(2x) (sin2x)′=cos2x⋅(2x)′=2cos(2x)
( e 2 x ) ′ = e 2 x ⋅ ( 2 x ) ′ = 2 e 2 x (e^{2x})^\prime=e^{2x}\cdot(2x)^\prime=2e^{2x} (e2x)′=e2x⋅(2x)′=2e2x
总损失定义为:
J ( w ) = ( h ( x 1 ) − y 1 ) 2 + ( h ( x 2 ) − y 2 ) 2 + . . . + ( h ( x m ) − y m ) 2 = ∑ i = 1 m ( h ( x i ) − y i ) 2 \begin{aligned}J(w)&=(h(x_{1})-y_{1})^2+(h(x_{2})-y_{2})^2+...+(h(x_{m})-y_{m})^2 \\ &=\sum_{i=1}^m(h(x_{i})-y_{i})^2\end{aligned} J(w)=(h(x1)−y1)2+(h(x2)−y2)2+...+(h(xm)−ym)2=i=1∑m(h(xi)−yi)2
如何去减少这个损失,使我们预测的更加准确些?既然存在了这个损失,我们一直说机器学习有自动学习的功能,在线性回归这里更是能够体现。这里可以通过一些优化方法去优化(其实是数学当中的求导功能)回归的总损失!!!
如何去求模型当中的W,使得损失最小?(目的是找到最小损失对应的W值)
w = ( X T X ) − 1 X T y w=(X^TX)^{-1}X^Ty w=(XTX)−1XTy
理解:X为特征值矩阵,y为目标值矩阵。直接求到最好的结果
缺点:当特征过多过复杂时,求解速度太慢并且得不到结果
以下表示数据为例:
即:
运用正规方程方法求解参数:
梯度下降法的基本思想可以类比为一个下山的过程。
假设这样一个场景:
一个人被困在山上,需要从山上下来(i.e. 找到山的最低点,也就是山谷)。但此时山上的浓雾很大,导致可视度很低。
因此,下山的路径就无法确定,他必须利用自己周围的信息去找到下山的路径。这个时候,他就可以利用梯度下降算法来帮助自己下山。
具体来说就是,以他当前的所处的位置为基准,寻找这个位置最陡峭的地方,然后朝着山的高度下降的地方走,(同理,如果我们的目标是上山,也就是爬到山顶,那么此时应该是朝着最陡峭的方向往上走)。然后每走一段距离,都反复采用同一个方法,最后就能成功的抵达山谷。
梯度下降的基本过程就和下山的场景很类似。
首先,我们有一个可微分的函数。这个函数就代表着一座山。
我们的目标就是找到这个函数的最小值,也就是山底。
根据之前的场景假设,最快的下山的方式就是找到当前位置最陡峭的方向,然后沿着此方向向下走,对应到函数中,就是找到给定点的梯度 ,然后朝着梯度相反的方向,就能让函数值下降的最快!因为梯度的方向就是函数值变化最快的方向。
所以,我们重复利用这个方法,反复求取梯度,最后就能到达局部的最小值,这就类似于我们下山的过程。而求取梯度就确定了最陡峭的方向,也就是场景中测量方向的手段。
梯度是微积分中一个很重要的概念
在单变量的函数中,梯度其实就是函数的微分,代表着函数在某个给定点的切线的斜率;
在多变量函数中,梯度是一个向量,向量有方向,梯度的方向就指出了函数在给定点的上升最快的方向;
这也就说明了为什么我们需要千方百计的求取梯度!我们需要到达山底,就需要在每一步观测到此时最陡峭的地方,梯度就恰巧告诉了我们这个方向。梯度的方向是函数在给定点上升最快的方向,那么梯度的反方向就是函数在给定点下降最快的方向,这正是我们所需要的。所以我们只要沿着梯度的反方向一直走,就能走到局部的最低点!
我们假设有一个单变量的函数 : J ( θ ) = θ 2 J(\theta) = \theta^2 J(θ)=θ2
函数的微分: J ′ ( θ ) = 2 θ J^\prime(\theta) = 2\theta J′(θ)=2θ
初始化,起点为(已知的起始位置): θ 0 = 1 \theta^0 = 1 θ0=1
学习率(步长): α = 0.4 \alpha = 0.4 α=0.4
我们开始进行梯度下降的迭代计算过程:
KaTeX parse error: No such environment: eqnarray at position 15: \large \begin{̲e̲q̲n̲a̲r̲r̲a̲y̲}̲ \theta^0 &=& 1…
如图,经过四次的运算,也就是走了四步,基本就抵达了函数的最低点,也就是山底
我们假设有一个目标函数 : J ( θ ) = θ 1 2 + θ 2 2 J(\theta) = \theta_{1}^{2} + \theta_{2}^{2} J(θ)=θ12+θ22
现在要通过梯度下降法计算这个函数的最小值。我们通过观察就能发现最小值其实就是 (0,0)点。但是接下
来,我们会从梯度下降算法开始一步步计算到这个最小值!
我们假设初始的起点为: θ 0 = ( 1 , 3 ) \theta^{0} = (1, 3) θ0=(1,3)
初始的学习率(步长): α = 0.1 \alpha = 0.1 α=0.1
函数的梯度为: Δ J ( θ ) = < 2 θ 1 , 2 θ 2 > \Delta J(\theta) =< 2\theta_{1} ,2\theta_{2}> ΔJ(θ)=<2θ1,2θ2>
进行多次迭代:
$$
\begin{eqnarray}
\Theta^0 &=& (1, 3) \
\Theta^1 &=& \Theta^0-\alpha\Delta J(\Theta)\
&=&(1,3)-0.1(2,6)\
&=&(0.8, 2.4)\
\Theta^2 &=& (0.8, 2.4)-0.1(1.6, 4.8)\
&=&(0.64, 1.92)\
\Theta^3 &=& (0.512, 1.536)\
\Theta^4 &=& (0.4096, 1.2288)\
\vdots\
\Theta^{10} &=& (0.10737418240000003, 0.32212254720000005)\
\vdots\
\Theta^{50} &=& (1.1417981541647683e^{-5}, 3.425394462494306e^{-5})\
\vdots\
\Theta^{100} &=& (1.6296287810675902e^{-10}, 4.888886343202771e^{-10})\
\end{eqnarray}
$$
我们发现,已经基本靠近函数的最小值点
θ i + 1 = θ i − α ∂ ∂ θ i J ( θ ) \Large \theta_{i+1} = \theta_{i} - \alpha\frac{\partial}{\partial\theta_{i}}J(\theta) θi+1=θi−α∂θi∂J(θ)
α \alpha α在梯度下降算法中被称作为学习率或者步长,意味着我们可以通过α来控制每一步走的距离,控制参数不要走太快,错过了使损失函数取最小值的点。同时也要保证不要走的太慢,导致太阳下山了,还没有走到山下。所以α的选择在梯度下降法中往往是很重要的!α不能太大也不能太小,太小的话,可能导致迟迟走不到最低点,太大的话,会导致错过最低点!
梯度前加一个负号,就意味着朝着梯度相反的方向前进!我们在前文提到,梯度的方向实际就是函数在此点上升最快的方向!而我们需要朝着下降最快的方向走,自然就是负的梯度的方向,所以此处需要加上负号
我们通过两个图更好理解梯度下降的过程
所以有了梯度下降这样一个优化算法,回归就有了"自动学习"的能力
梯度下降 | 正规方程 |
---|---|
需要选择学习率 | 不需要 |
需要迭代求解 | 一次运算得出 |
特征数量较大(超过10000个)可以使用 | 需要计算方程,时间复杂度高O(n3) |
经过前面的介绍,我们发现最小二乘法适用简洁高效,比梯度下降这样的迭代法似乎方便很多。但是这里我们就聊聊最小二乘法的局限性。
首先,我们来看一下,常见的梯度下降算法有:
它们都是为了正确地调节权重向量,通过为每个权重计算一个梯度,从而更新权值,使目标函数尽可能最小化。其差别在于样本的使用方式不同。
批量梯度下降法,是梯度下降法最常用的形式,具体做法也就是在更新参数时使用所有的样本来进行更新。
计算训练集所有样本误差,对其求和再取平均值作为目标函数。
权重向量沿其梯度相反的方向移动,从而使当前目标函数减少得最多。
其是在整个训练数据集上计算损失函数关于参数 θ \theta θ 的梯度:
θ i + 1 = θ i − α ∑ j = 0 m ( h θ ( x 0 ( j ) , x 1 ( j ) , ⋯ , x n ( j ) ) − y j ) x i ( j ) \large \theta_{i+1} = \theta_i - \alpha\sum_{j=0}^{m}(h_{\theta}(x_0^{(j)},x_1^{(j)},\cdots,x_n^{(j)})-y_j)x_i^{(j)} θi+1=θi−αj=0∑m(hθ(x0(j),x1(j),⋯,xn(j))−yj)xi(j)
由于我们有m个样本,这里求梯度的时候就用了所有m个样本的梯度数据。
注意:
因为在执行每次更新时,我们需要在整个数据集上计算所有的梯度,所以批梯度下降法的速度会很慢,同时,全梯度下降法无法处理超出内存容量限制的数据集。
全梯度下降法同样也不能在线更新模型,即在运行的过程中,不能增加新的样本。
由于FG每迭代更新一次权重都需要计算所有样本误差,而实际问题中经常有上亿的训练样本,故效率偏低,且容易陷入局部最优解,因此提出了随机梯度下降算法。
其每轮计算的目标函数不再是全体样本误差,而仅是单个样本误差,即每次只代入计算一个样本目标函数的梯度来更新权重,再取下一个样本重复此过程,直到损失函数值停止下降或损失函数值小于某个可以容忍的阈值。
此过程简单,高效,通常可以较好地避免更新迭代收敛到局部最优解。其迭代形式为
θ i + 1 = θ i − α ( h θ ( x 0 ( j ) , x 1 ( j ) , ⋯ , x n ( j ) ) − y j ) x i ( j ) \large \theta_{i+1}=\theta_i-\alpha(h_{\theta}(x_0^{(j)},x_1^{(j)},\cdots,x_n^{(j)})-y_j)x_i^{(j)} θi+1=θi−α(hθ(x0(j),x1(j),⋯,xn(j))−yj)xi(j)
但是由于,SG每次只使用一个样本迭代,若遇上噪声则容易陷入局部最优解。
小批量梯度下降算法是FG和SG的折中方案,在一定程度上兼顾了以上两种方法的优点。
每次从训练样本集上随机抽取一个小样本集,在抽出来的小样本集上采用FG迭代更新权重。
被抽出的小样本集所含样本点的个数称为batch_size,通常设置为2的幂次方,更有利于GPU加速处理。
特别的,若batch_size=1,则变成了SG;若batch_size=n,则变成了FG.其迭代形式为
θ i + 1 = θ i − α ∑ j = t t + x − 1 ( h θ ( x 0 ( j ) , x 1 ( j ) , ⋯ , x n ( j ) ) − y j ) x i ( j ) \large \theta_{i+1}=\theta_i-\alpha\sum_{j=t}^{t+x-1}(h_{\theta}(x_0^{(j)},x_1^{(j)},\cdots,x_n^{(j)})-y_j)x_i^{(j)} θi+1=θi−αj=t∑t+x−1(hθ(x0(j),x1(j),⋯,xn(j))−yj)xi(j)
上式中,也就是我们从m个样本中,选择x个样本进行迭代(1
在SG方法中,虽然避开了运算成本大的问题,但对于大数据训练而言,SG效果常不尽如人意,因为每一轮梯度更新都完全与上一轮的数据和梯度无关。
随机平均梯度算法克服了这个问题,在内存中为每一个样本都维护一个旧的梯度,随机选择第i个样本来更新此样本的梯度,其他样本的梯度保持不变,然后求得所有梯度的平均值,进而更新了参数。
如此,每一轮更新仅需计算一个样本的梯度,计算成本等同于SG,但收敛速度快得多。
其迭代形式为:
θ i + 1 = θ i − α n ( h θ ( x 0 ( j ) , x 1 ( j ) , . . . x n ( j ) ) − y j ) x i ( j ) \large \theta_{i+1}=\theta _i-\frac{\alpha }{n}(h_\theta (x^{(j)}_0,x^{(j)}_1,...x^{(j)}_n)-y_j)x_i^{(j)} θi+1=θi−nα(hθ(x0(j),x1(j),...xn(j))−yj)xi(j)
sklearn提供给我们两种实现的API, 可以根据选择使用
给定的这些特征,是专家们得出的影响房价的结果属性。我们此阶段不需要自己去探究特征是否有用,只需要使用这些特征。到后面量化很多特征需要我们自己去寻找
回归当中的数据大小不一致,是否会导致结果影响较大。所以需要做标准化处理。
均方误差(Mean Squared Error, MSE)评价机制:
M S E = 1 m ∑ i = 1 m ( y i − y ^ ) 2 \Large MSE = \frac{1}{m}\sum_{i=1}^{m}(y^i-\hat{y})^2 MSE=m1i=1∑m(yi−y^)2
注: y i y^i yi为预测值, y ^ \hat{y} y^ 为真实值
导包
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
from sklearn.linear_model import SGDRegressor
from sklearn.linear_model import LinearRegression
正规方程
# 1.获取数据
data = load_boston()
# 2.数据集划分
x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, random_state=22)
# 3.特征工程-标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 4.机器学习-线性回归(正规方程)
estimator = LinearRegression()
estimator.fit(x_train, y_train)
# 5.模型评估
# 5.1 获取系数等值
y_predict = estimator.predict(x_test)
print("预测值为:\n", y_predict)
print("模型中的系数为:\n", estimator.coef_)
print("模型中的偏置为:\n", estimator.intercept_)
# 5.2 评价
# 均方误差
error = mean_squared_error(y_test, y_predict)
print("误差为:\n", error)
梯度下降法
# 1.获取数据
data = load_boston()
# 2.数据集划分
x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, random_state=22)
# 3.特征工程-标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.fit_transform(x_test)
# 4.机器学习-线性回归(特征方程)
estimator = SGDRegressor(max_iter=1000)
estimator.fit(x_train, y_train)
# 5.模型评估
# 5.1 获取系数等值
y_predict = estimator.predict(x_test)
print("预测值为:\n", y_predict)
print("模型中的系数为:\n", estimator.coef_)
print("模型中的偏置为:\n", estimator.intercept_)
# 5.2 评价
# 均方误差
error = mean_squared_error(y_test, y_predict)
print("误差为:\n", error)
我们也可以尝试去修改学习率
estimator = SGDRegressor(max_iter=1000,learning_rate="constant",eta0=0.1)
此时我们可以通过调参数,找到学习率效果更好的值。
正规方程
梯度下降法
线性回归性能评估【知道】
过拟合:一个假设在训练数据上能够获得比其他假设更好的拟合, 但是在测试数据集上却不能很好地拟合数据(体现在准确率下降),此时认为这个假设出现了过拟合的现象。(模型过于复杂)
欠拟合:一个假设在训练数据上不能获得更好的拟合,并且在测试数据集上也不能很好地拟合数据,此时认为这个假设出现了欠拟合的现象。(模型过于简单)
过拟合和欠拟合的区别:
通过代码认识过拟合和欠拟合
绘制数据
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(666)
# np.random.uniform() 在[-3,3)范围内随机生成100个数
x = np.random.uniform(-3,3,size = 100)
# 转换成二维数组,变成一列
X = x.reshape(-1,1)
# np.random.normal() 生成100个符合正态分布的数,均值为0,标准差为1
y = 0.5* x**2 + x+2 + np.random.normal(0,1,size = 100)
from sklearn.linear_model import LinearRegression
estimator = LinearRegression()
estimator.fit(X,y)
y_predict = estimator.predict(X)
plt.scatter(x,y)
plt.plot(x,y_predict,color = 'r')
plt.show()
#计算均方误差
from sklearn.metrics import mean_squared_error
mean_squared_error(y,y_predict)
#3.0750025765636577
添加二次项,绘制图像
# 添加二次项
X2 = np.hstack([X,X**2])
estimator2 = LinearRegression()
estimator2.fit(X2,y)
y_predict2 = estimator2.predict(X2)
plt.scatter(x,y)
plt.plot(np.sort(x),y_predict2[np.argsort(x)],color = 'r')
plt.show()
#计算均方误差和准确率
from sklearn.metrics import mean_squared_error
mean_squared_error(y,y_predict2)
#1.0987392142417858
再次加入高次项,绘制图像,观察均方误差结果
X5 = np.hstack([X2,X**3,X**4,X**5,X**6,X**7,X**8,X**9,X**10])
estimator3 = LinearRegression()
estimator3.fit(X5,y)
y_predict5 = estimator3.predict(X5)
plt.scatter(x,y)
plt.plot(np.sort(x),y_predict5[np.argsort(x)],color = 'r')
plt.show()
error = mean_squared_error(y, y_predict5)
error
#1.0508466763764157
通过上述观察发现,随着加入的高次项越来越多,拟合程度越来越高,均方误差也随着加入越来越小。说明已经不再欠拟合了。
问题:如何判断出现过拟合呢?
将数据集进行划分:对比X、X2、X5的测试集的均方误差
X的测试集均方误差
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state = 5)
estimator = LinearRegression()
estimator.fit(X_train,y_train)
y_predict = estimator.predict(X_test)
mean_squared_error(y_test,y_predict)
#3.153139806483088
X2的测试集均方误差
X_train,X_test,y_train,y_test = train_test_split(X2,y,random_state = 5)
estimator = LinearRegression()
estimator.fit(X_train,y_train)
y_predict = estimator.predict(X_test)
mean_squared_error(y_test,y_predict)
#1.111873885731967
X5的测试集的均方误差
X_train,X_test,y_train,y_test = train_test_split(X5,y,random_state = 5)
estimator = LinearRegression()
estimator.fit(X_train,y_train)
y_predict = estimator.predict(X_test)
mean_squared_error(y_test,y_predict)
#1.4145580542309835
在解决回归过拟合中,我们选择正则化。但是对于其他机器学习算法如分类算法来说也会出现这样的问题,除了一些算法本身作用之外(决策树、神经网络),我们更多的也是去自己做特征选择,包括之前说的删除、合并一些特征
如何解决?
在学习的时候,数据提供的特征有些影响模型复杂度或者这个特征的数据点异常较多,所以算法在学习的时候尽量减少这个特征的影响(甚至删除某个特征的影响),这就是正则化
注:调整时候,算法并不知道某个特征影响,而是去调整参数得出优化的结果
X10 = np.hstack([X2,X**3,X**4,X**5,X**6,X**7,X**8,X**9,X**10])
estimator3 = LinearRegression()
estimator3.fit(X10,y)
y_predict3 = estimator3.predict(X10)
plt.scatter(x,y)
plt.plot(np.sort(x),y_predict3[np.argsort(x)],color = 'r')
plt.show()
# 打印回归系数
estimator3.coef_
## 展示结果
array([ 1.32292089e+00, 2.03952017e+00, -2.88731664e-01, -1.24760429e+00,
8.06147066e-02, 3.72878513e-01, -7.75395040e-03, -4.64121137e-02,
1.84873446e-04, 2.03845917e-03])
from sklearn.linear_model import Lasso # L1正则
from sklearn.linear_model import Ridge # 岭回归 L2正则
X10 = np.hstack([X2,X**3,X**4,X**5,X**6,X**7,X**8,X**9,X**10])
estimator_l1 = Lasso(alpha=0.005,normalize=True) # 调整alpha 正则化强度 查看正则化效果 normalize=True 数据标准化
estimator_l1.fit(X10,y)
y_predict_l1 = estimator_l1.predict(X10)
plt.scatter(x,y)
plt.plot(np.sort(x),y_predict_l1[np.argsort(x)],color = 'r')
plt.show()
estimator_l1.coef_ # Lasso 回归 L1正则 会将高次方项系数变为0
array([ 0.97284077, 0.4850203 , 0. , 0. , -0. ,
0. , -0. , 0. , -0. , 0. ])
X10 = np.hstack([X2,X**3,X**4,X**5,X**6,X**7,X**8,X**9,X**10])
estimator_l2 = Ridge(alpha=0.005,normalize=True) # 调整alpha 正则化强度 查看正则化效果
estimator_l2.fit(X10,y)
y_predict_l2 = estimator_l2.predict(X10)
plt.scatter(x,y)
plt.plot(np.sort(x),y_predict_l2[np.argsort(x)],color = 'r')
plt.show()
estimator_l2.coef_ # l2 正则不会将系数变为0 但是对高次方项系数影响较大
array([ 9.91283840e-01, 5.24820573e-01, 1.57614237e-02, 2.34128982e-03,
7.26947948e-04, -2.99893698e-04, -8.28333499e-05, -4.51949529e-05,
-4.21312015e-05, -8.22992826e-07])
Ridge方法相当于SGDRegressor(penalty=‘l2’, loss=“squared_loss”),只不过SGDRegressor实现了一个普通的随机梯度下降学习,推荐使用Ridge(实现了SAG)
class _BaseRidgeCV(LinearModel):
def __init__(self, alphas=(0.1, 1.0, 10.0),
fit_intercept=True, normalize=False,scoring=None,
cv=None, gcv_mode=None,
store_cv_values=False):
# 1.获取数据
data = load_boston()
# 2.数据集划分
x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, random_state=22)
# 3.特征工程-标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 4.机器学习-线性回归(岭回归)
estimator = Ridge(alpha=1)
# estimator = RidgeCV(alphas=(0.1, 1, 10))
estimator.fit(x_train, y_train)
# 5.模型评估
# 5.1 获取系数等值
y_predict = estimator.predict(x_test)
print("预测值为:\n", y_predict)
print("模型中的系数为:\n", estimator.coef_)
print("模型中的偏置为:\n", estimator.intercept_)
# 5.2 评价
# 均方误差
error = mean_squared_error(y_test, y_predict)
print("误差为:\n", error)
sklearn.externals.joblib
,新版本需要安装joblibpip install joblib
,import joblib
# 1.获取数据
data = load_boston()
# 2.数据集划分
x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, random_state=22)
# 3.特征工程-标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 4.机器学习-线性回归(岭回归)
# 4.1 模型训练
estimator = Ridge(alpha=1)
estimator.fit(x_train, y_train)
# 4.2 模型保存
joblib.dump(estimator, "./data/test.pkl")
# 4.3 模型加载
estimator = joblib.load("./data/test.pkl")
# 5.模型评估
# 5.1 获取系数等值
y_predict = estimator.predict(x_test)
print("预测值为:\n", y_predict)
print("模型中的系数为:\n", estimator.coef_)
print("模型中的偏置为:\n", estimator.intercept_)
# 5.2 评价
# 均方误差
error = mean_squared_error(y_test, y_predict)
print("误差为:\n", error)
销售额预测分析
import pandas as pd
#数据读取#
#index_col=0 ,数据的第一列是索引,指定索引列
store=pd.read_csv('data/store_rev.csv',index_col=0)
#数据的基本信息
#发现local_tv有50多个空值
#发现event是object,即类别型变量
store.info()
#统计各个列哪些是空值
#发现local_tv有56个空值
store.isnull().sum()
'''
revenue 0
reach 0
local_tv 56
online 0
instore 0
person 0
event 0
dtype: int64
'''
#了解数据的分布
#判断数据是否符合业务场景
store.describe()
#了解event的具体值
store.event.unique()
#array(['non_event', 'special', 'cobranding', 'holiday'], dtype=object)
#这些类别对应的revenue(销售额)是怎样的
store.groupby(['event'])['revenue'].describe()
#这几个类别对应的local_tv(本地电视广告投入)是怎样的
store.groupby(['event'])['local_tv'].describe()
#所有变量,任意两个变量相关分析
#local_tv,person,instore是比较好的指标,与revenue相关度高
store.corr()
#其他变量与revenue的相关分析
#sort_values 将revenue排序,ascending默认升序,False为降序排列
#看到前3个相关变量为local_tv,person,instore
store.corr()[['revenue']].sort_values('revenue',ascending=False)
'''
revenue
revenue 1.000000
local_tv 0.602114
person 0.559208
instore 0.311739
online 0.171227
event_special 0.033752
event_cobranding -0.005623
event_holiday -0.016559
event_non_event -0.019155
reach -0.155314
'''
#可视化分析
import seaborn as sns
import matplotlib.pyplot as plt
#线性关系可视化
#斜率与相关系数有关
sns.regplot(x='local_tv',y='revenue',data=store)
#线性关系可视化
sns.regplot(x='person',y='revenue',data=store)
sns.regplot(x='instore',y='revenue',data=store)
#删除缺失值,数据有缺失,不处理会报错,需要处理缺失值
store.dropna(inplace=True)
#或者填充缺失值
#缺失值处理,填充0
store=store.fillna(0)
#缺失值处理,均值填充
store=store.fillna(store.local_tv.mean())
store.info()
'''
Int64Index: 985 entries, 845 to 26
Data columns (total 10 columns):
revenue 985 non-null float64
reach 985 non-null int64
local_tv 985 non-null float64
online 985 non-null int64
instore 985 non-null int64
person 985 non-null int64
event_cobranding 985 non-null uint8
event_holiday 985 non-null uint8
event_non_event 985 non-null uint8
event_special 985 non-null uint8
dtypes: float64(2), int64(4), uint8(4)
memory usage: 57.7 KB
'''
#设定自变量和因变量
y=store['revenue']
#第一次三个
x=store[['local_tv','person','instore']]
#第二次四个
#x=store[['local_tv','person','instore','online']]
#数据标准化处理
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
x1 = scaler.fit_transform(x)
from sklearn.linear_model import LinearRegression
# 实例化api
model=LinearRegression()
# 训练模型
model.fit(x1,y)
# LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None, normalize=False)
# 自变量系数
model.coef_
# array([41478.6429907 , 48907.03909284, 26453.89791677])
# 模型的截距
model.intercept_
# -17641.46438435701
# 最后得到x和y的关系为:y=41478*local_tv + 48907*person + 26453*instore - 17641
# 模型的评估,x为'local_tv','person','instore'
y_predict=model.predict(x)#计算y预测值
from sklearn.metrics import mean_squared_error
mean_squared_error(y,y_predict)
# 1.9567577917634842e+18
注意应用回归模型时研究自变量是否产生变化
回归算法按照自变量的个数分为一元回归和多元回归,按照影响是否是线性分为线性回归和非线性回归。在面对不同回归方法的选择时,注意参考以下因素: