理解机器学习中的线性回归与逻辑回归

1、线性回归

1.1 什么是线性回归?

我们先来看一个例子,如下图:给定x和y的关系

x357813
y3578?

求x=13时,y的值为多少?
在这里插入图片描述

这里,很容易想到方程为y=x ,然后解得y=13
这就是线性回归。
线性回归说白了,就是给我们一些数据,让我们找一条直线来拟合这些数据。

1.2 如何进行线性回归

1.2.1 拟合

但是,实际问题中,x,y的分布,可能是这样的

x357813
y26911?

这时,我们该如何计算y的值?
在这里插入图片描述

设此时的方程为y=kx+b
我们可能会找到很多方程,假设我们找到其中一条的方程的 k=0 ,b=4
当然我们也可能找 k=1 ,b= 3 的直线。
下图是 k=2,b= -5 时的拟合效果,即 y = 2 ∗ x − 5 y=2*x-5 y=2x5
在这里插入图片描述

那么,到底如何判断我们找的直线的拟合效果呢?

1.2.2 判断拟合效果

我们可以这样做:
计算所有点与该点的欧式距离 :

例如当x=3时 对应方程 y = 2 ∗ x − 5 y=2*x-5 y=2x5 的 y坐标为(3,1),
计算 (3,2) 与 (3,1) 点的距离 为 1
然后计算 x=5 时,(5,5) (5,6)两个点距离,
最后把所有点的距离相加
在这里插入图片描述

总距离 = ( 2 − 1 ) 2 + ( 6 − 5 ) 2 + ( 9 − 9 ) 2 + ( 11 − 11 ) 2 \sqrt{(2-1)^2}+\sqrt{(6-5)^2}+\sqrt{(9-9)^2}+\sqrt{(11-11)^2} (21)2 +(65)2 +(99)2 +(1111)2

我们以这个值的大小作为判断该曲线是否拟合的好
不过,数学家用 残差平方和(RSS) 来衡量:
即 刚刚的式子不开根号
RSS= ( 2 − 1 ) 2 + ( 6 − 5 ) 2 + ( 9 − 9 ) 2 + ( 11 − 11 ) 2 {(2-1)^2}+{(6-5)^2}+{(9-9)^2}+{(11-11)^2} (21)2+(65)2+(99)2+(1111)2
RSS的值越小,表明该函数与原数据拟合的越好。

1.2.3 如何求解最佳拟合曲线

这里我们对RSS进行一般化表示,在方程 y ^ = k ∗ x ^ + b \hat{y}=k*\hat{x}+b y^=kx^+b 中:
RSS= ( y 1 ^ − y 1 ) 2 + ( y 2 ^ − y 2 ) 2 + ( y 3 ^ − y 3 ) 2 + . . . . + ( y n ^ − y n ) 2 {(\hat{y_1}-y_1)^2}+{(\hat{y_2}-y_2)^2}+{(\hat{y_3}-y_3)^2}+....+{(\hat{y_n}-y_n)^2} (y1^y1)2+(y2^y2)2+(y3^y3)2+....+(yn^yn)2 = ∑ i = 1 n ( y i ^ − y i ) 2 \displaystyle \sum^{n}_{i=1 }{(\hat{y_i}-y_i)^2} i=1n(yi^yi)2

由于 y i ^ = k ∗ x i ^ + b \hat{y_i}=k*\hat{x_i}+b yi^=kxi^+b ,所以

RSS= ( k ∗ x 1 ^ + b − y 1 ) 2 + ( k ∗ x 2 ^ + b − y 2 ) 2 + . . . . + ( k ∗ x n ^ + b − y n ) 2 {(k*\hat{x_1}+b-y_1)^2}+{(k*\hat{x_2}+b-y_2)^2}+....+{(k*\hat{x_n}+b-y_n)^2} (kx1^+by1)2+(kx2^+by2)2+....+(kxn^+byn)2 = ∑ i = 1 n ( k ∗ x i ^ + b − y i ) 2 \displaystyle \sum^{n}_{i=1 }{(k*\hat{x_i}+b-y_i)^2} i=1n(kxi^+byi)2

现在要求RSS的最小值,我们只要算得RSS方程中导数为0的点即可
f ( k , b ) = ∑ i = 1 n ( k ∗ x i ^ + b − y i ) 2 f(k,b)=\displaystyle \sum^{n}_{i=1 }{(k*\hat{x_i}+b-y_i)^2} f(k,b)=i=1n(kxi^+byi)2
只要求出导数最为0的点就可求出 k,b
第一步
首先对k求偏导 ∂ f ( k , b ) ∂ k = 2 ∑ i = 1 n ( k ∗ x i ^ + b − y i ) x i ^ = 2 k ∑ i = 1 n x i ^ 2 + 2 b ∑ i = 1 n x i ^ − 2 ∑ i = 1 n y i x i ^ \frac{\partial f(k,b)}{\partial k}=2\displaystyle \sum^{n}_{i=1 }{(k*\hat{x_i}+b-y_i)}\hat{x_i}=2k\sum^{n}_{i=1 }\hat{x_i}^2+2b\sum^{n}_{i=1 }\hat{x_i}-2\sum^{n}_{i=1 }y_i\hat{x_i} kf(k,b)=2i=1n(kxi^+byi)xi^=2ki=1nxi^2+2bi=1nxi^2i=1nyixi^
令偏导为0
可得 2 k ∑ i = 1 n x i ^ 2 + 2 b ∑ i = 1 n x i ^ = 2 ∑ i = 1 n y i x i ^ 2k\sum^{n}_{i=1 }\hat{x_i}^2+2b\sum^{n}_{i=1 }\hat{x_i}=2\sum^{n}_{i=1 }y_i\hat{x_i} 2ki=1nxi^2+2bi=1nxi^=2i=1nyixi^
第二步
对b求偏导 ∂ f ( k , b ) ∂ b = 2 ∑ i = 1 n ( k ∗ x i ^ + b − y i ) = 2 ∑ i = 1 n k ∗ x i ^ + 2 n b − 2 ∑ i = 1 n y i \frac{\partial f(k,b)}{\partial b}=2\displaystyle \sum^{n}_{i=1 }{(k*\hat{x_i}+b-y_i)}=2\displaystyle \sum^{n}_{i=1 }k*\hat{x_i}+2nb-2\displaystyle \sum^{n}_{i=1 }y_i bf(k,b)=2i=1n(kxi^+byi)=2i=1nkxi^+2nb2i=1nyi
令偏导为0
2 ∑ i = 1 n k ∗ x i ^ + 2 n b = 2 ∑ i = 1 n y i 2\displaystyle \sum^{n}_{i=1 }k*\hat{x_i}+2nb=2\displaystyle \sum^{n}_{i=1 }y_i 2i=1nkxi^+2nb=2i=1nyi
同除2n
⇒ k x ˉ + b = y ˉ \Rightarrow k\bar{x}+b=\bar{y} kxˉ+b=yˉ
第三步
b = y ˉ − k x ˉ b=\bar{y}-k\bar{x} b=yˉkxˉ 带入第一步我们所求的式子中
可得
k ∑ i = 1 n x i ^ 2 + ( y ˉ − k x ˉ ) ∗ ∑ i = 1 n x i ^ = ∑ i = 1 n y i x i ^ k\sum^{n}_{i=1 }\hat{x_i}^2+(\bar{y}-k\bar{x})*\sum^{n}_{i=1 }\hat{x_i}=\sum^{n}_{i=1 }y_i\hat{x_i} ki=1nxi^2+(yˉkxˉ)i=1nxi^=i=1nyixi^
⇒ k ∑ i = 1 n x i ^ 2 + y ˉ ∗ ∑ i = 1 n x i ^ − k x ˉ ∗ ∑ i = 1 n x i ^ = ∑ i = 1 n y i x i ^ \Rightarrow k\sum^{n}_{i=1 }\hat{x_i}^2+\bar{y}*\sum^{n}_{i=1 }\hat{x_i}-k\bar{x}*\sum^{n}_{i=1 }\hat{x_i}=\sum^{n}_{i=1 }y_i\hat{x_i} ki=1nxi^2+yˉi=1nxi^kxˉi=1nxi^=i=1nyixi^
⇒ k ( ∑ i = 1 n x i ^ 2 − x ˉ ∗ ∑ i = 1 n x i ^ ) = ∑ i = 1 n y i x i ^ − y ˉ ∗ ∑ i = 1 n x i ^ \Rightarrow k(\sum^{n}_{i=1 }\hat{x_i}^2-\bar{x}*\sum^{n}_{i=1 }\hat{x_i})=\sum^{n}_{i=1 }y_i\hat{x_i}-\bar{y}*\sum^{n}_{i=1 }\hat{x_i} k(i=1nxi^2xˉi=1nxi^)=i=1nyixi^yˉi=1nxi^

⇒ k = ( ∑ i = 1 n y i x i ^ − y ˉ ∗ ∑ i = 1 n x i ^ ) ( ∑ i = 1 n x i ^ 2 − x ˉ ∗ ∑ i = 1 n x i ^ ) \Rightarrow k=\frac {(\sum^{n}_{i=1 }y_i\hat{x_i}-\bar{y}*\sum^{n}_{i=1 }\hat{x_i})} {(\sum^{n}_{i=1 }\hat{x_i}^2-\bar{x}*\sum^{n}_{i=1 }\hat{x_i})} k=(i=1nxi^2xˉi=1nxi^)(i=1nyixi^yˉi=1nxi^)

到此我们已经把k求出来了,将k带回 b = y ˉ − k x ˉ b=\bar{y}-k\bar{x} b=yˉkxˉ 可以求出b

1.2.4 使用正规方程拟合

虽然上面已经求出k和b,但是这只是一元函数。但是,如过方程有三个变量,四个变量,那该如何下手?
例如一个三元方程: f ( x 1 , x 2 , x 3 ) = k 1 ∗ x 1 + k 2 ∗ x 2 + k 3 ∗ x 3 + b f(x_1,x_2,x_3)=k_1*x_1+k_2*x_2+k_3*x_3+b f(x1,x2,x3)=k1x1+k2x2+k3x3+b
再用上述方法来求解会非常复杂
于是我们将上述方程转换成矩阵形式

f ( k , b ) = ( k ∗ x 1 ^ + b − y 1 ) 2 + ( k ∗ x 2 ^ + b − y 2 ) 2 + . . . + ( k ∗ x n ^ + b − y n ) 2 f(k,b)={(k*\hat{x_1}+b-y_1)^2}+{(k*\hat{x_2}+b-y_2)^2}+...+{(k*\hat{x_n}+b-y_n)^2} f(k,b)=(kx1^+by1)2+(kx2^+by2)2+...+(kxn^+byn)2
= = =
[ ( k ∗ x 1 ^ + b − y 1 ) , ( k ∗ x 2 ^ + b − y 2 ) , ⋯   , ( k ∗ x n ^ + b − y n ) ] ∗ [ ( k ∗ x 1 ^ + b − y 1 ) ( k ∗ x 2 ^ + b − y 2 ) ⋮ ( k ∗ x n ^ + b − y n ) ] \left[ \begin{matrix} {(k*\hat{x_1}+b-y_1)},{(k*\hat{x_2}+b-y_2)}, \cdots,{(k*\hat{x_n}+b-y_n)}\\ \end{matrix} \right]* \left[ \begin{matrix} {(k*\hat{x_1}+b-y_1)}\\ {(k*\hat{x_2}+b-y_2)}\\ \vdots \\ {(k*\hat{x_n}+b-y_n)}\\ \end{matrix} \right] [(kx1^+by1),(kx2^+by2),,(kxn^+byn)](kx1^+by1)(kx2^+by2)(kxn^+byn)
θ = [ k b ] \theta=\left[ \begin{matrix} {k}\\ b\\ \end{matrix} \right] θ=[kb]
X = [ x 1 ^ , 1 x 2 ^ , 1 ⋮ x n ^ , 1 ] X=\left[ \begin{matrix} \hat{x_1},1\\ \hat{x_2}, 1\\ \vdots \\ \hat{x_n}, 1\\ \end{matrix} \right] X=x1^,1x2^,1xn^,1
Y = [ y 1 y 2 ⋮ y n ] Y=\left[ \begin{matrix} {y_1}\\ {y_2}\\ \vdots \\ {y_n}\\ \end{matrix} \right] Y=y1y2yn
原方程= ( ( ( X θ − Y ) T ( X θ − Y ) X\theta - Y)^T(X\theta - Y) XθY)T(XθY)
接下来,只要对 θ \theta θ求导,我们就可以得到正规方程
那么,如何对一个矩阵求导?矩阵求导到底是什么?

1.2.4.1 矩阵的求导

在介绍矩阵求导前,先了解一下标量函数与向量函数
标量函数 f ( x ) = x 2 f(x)= x^2 f(x)=x2 即输出为一个值
向量函数 f ( x ) = [ x x 2 ] f(x)=\left[ \begin{matrix} x\\ x^2\\ \end{matrix} \right] f(x)=[xx2] 输出为一个矩阵
矩阵求导的本质
d A d B \frac {dA} {dB} dBdA矩阵A中的每个元素对矩阵B中的每一个元素求导

标量函数对向量求导
d f ( x ) d X \frac {df(x)} {dX} dXdf(x)
其中 f ( x ) = f ( x 1 , x 2 , . . . x n ) f(x)=f(x_1,x_2,...x_n) f(x)=f(x1,x2,...xn)
X = [ x 1 x 2 ⋮ x n ] X=\left[ \begin{matrix} x_1\\ x_2\\ \vdots \\ x_n\\ \end{matrix} \right] X=x1x2xn
标量函数对矩阵的结果为
d f ( x ) d X = [ d f ( x ) d x 1 d f ( x ) d x 2 ⋮ d f ( x ) d x n ] \frac {df(x)} {dX}=\left[ \begin{matrix} \frac {df(x)} {dx_1}\\ \frac {df(x)} {dx_2}\\ \vdots \\ \frac {df(x)} {dx_n}\\ \end{matrix} \right] dXdf(x)=dx1df(x)dx2df(x)dxndf(x)
向量函数对标量求导
f ( x ) = [ f 1 ( x ) f 2 ( x ) ⋮ f n ( x ) ] f(x)=\left[ \begin{matrix} f_1(x)\\ f_2(x)\\ \vdots\\ f_n(x)\\ \end{matrix} \right] f(x)=f1(x)f2(x)fn(x)
向量函数对标量求导的结果为
d f ( x ) d x = [ d f 1 ( x ) d x , d f 2 ( x ) d x , ⋯   , d f n ( x ) d x ] \frac {df(x)} {dx}=\left[ \begin{matrix} \frac {df_1(x)} {dx},\frac {df_2(x)} {dx},\cdots,\frac {df_n(x)} {dx}\\ \end{matrix} \right] dxdf(x)=[dxdf1(x),dxdf2(x),,dxdfn(x)]
向量函数对向量求导
f ( x ) = [ f 1 ( x ) f 2 ( x ) ⋮ f n ( x ) ] f(x)=\left[ \begin{matrix} f_1(x)\\ f_2(x)\\ \vdots\\ f_n(x)\\ \end{matrix} \right] f(x)=f1(x)f2(x)fn(x)
更具标量对向量以及向量对标量,我们可得向量函数对向量求导的结果为
X = [ x 1 x 2 ⋮ x n ] X=\left[ \begin{matrix} x_1\\ x_2\\ \vdots \\ x_n\\ \end{matrix} \right] X=x1x2xn
d f ( x ) d X = [ d f 1 ( x ) d x 1 , d f 2 ( x ) d x 1 , ⋯   , d f n ( x ) d x 1 d f 2 ( x ) d x 2 , d f 2 ( x ) d x 2 , ⋯   , d f n ( x ) d x 2 ⋮ d f n ( x ) d x n , d f 2 ( x ) d x n , ⋯   , d f n ( x ) d x n ] \frac {df(x)} {dX}=\left[ \begin{matrix} \frac {df_1(x)} {dx_1},\frac {df_2(x)} {dx_1},\cdots,\frac {df_n(x)} {dx_1}\\ \frac {df_2(x)} {dx_2},\frac {df_2(x)} {dx_2},\cdots,\frac {df_n(x)} {dx_2}\\ \vdots\\ \frac {df_n(x)} {dx_n},\frac {df_2(x)} {dx_n},\cdots,\frac {df_n(x)} {dx_n}\\ \end{matrix} \right] dXdf(x)=dx1df1(x),dx1df2(x),,dx1dfn(x)dx2df2(x),dx2df2(x),,dx2dfn(x)dxndfn(x),dxndf2(x),,dxndfn(x)

1.2.4.2 常见的矩阵求导公式推导

f ( x ) = A T X = ∑ i = 1 n a i x i f(x)=A^TX=\displaystyle \sum^{n}_{i=1 }a_ix_i f(x)=ATX=i=1naixi
d f ( x ) d X \frac {df(x)} {dX} dXdf(x) 对X求导
其中 A = [ a 1 , a 2 , . . . , a n ] A=[a_1,a_2,...,a_n] A=[a1,a2,...,an]
很明显,这里 f(x)为标量,X为向量
所以,结果为
d f ( x ) d X = [ d f ( x ) d x 1 d f ( x ) d x 2 ⋮ d f ( x ) d x n ] = [ d ( a 1 x 1 ) d x 1 d ( a 2 x 2 ) d x 2 ⋮ d a n x n d x n ] = [ a 1 a 2 ⋮ a n ] = A \frac {df(x)} {dX}=\left[ \begin{matrix} \frac {df(x)} {dx_1}\\ \frac {df(x)} {dx_2}\\ \vdots \\ \frac {df(x)} {dx_n}\\ \end{matrix} \right]= \left[ \begin{matrix} \frac {d(a_1x_1)} {dx_1}\\ \frac {d(a_2x_2)} {dx_2}\\ \vdots \\ \frac {da_nx_n} {dx_n}\\ \end{matrix} \right]= \left[ \begin{matrix} a_1\\ a_2\\ \vdots \\ a_n\\ \end{matrix} \right]= A dXdf(x)=dx1df(x)dx2df(x)dxndf(x)=dx1d(a1x1)dx2d(a2x2)dxndanxn=a1a2an=A
由于 f ( x ) = X T A = ∑ i = 1 n a i x i f(x)=X^TA=\displaystyle \sum^{n}_{i=1 }a_ix_i f(x)=XTA=i=1naixi
所以 f ( x ) = X T A , 和 f ( x ) = A T X 对 矩 阵 X 的 导 为 A f(x)=X^TA,和f(x)=A^TX对矩阵X的导为A f(x)=XTA,f(x)=ATXXA

1.2.4.3 正规方程的推导

由于原方程= ( ( ( X θ − Y ) T ( X θ − Y ) = ( θ T X T − Y T ) ( X θ − Y ) = θ T X T X θ − θ T X T Y − Y T X θ + Y T Y X\theta - Y)^T(X\theta - Y)=(\theta^TX^T-Y^T)(X\theta-Y)=\theta^T X^TX\theta-\theta^T X^TY-Y^TX\theta+Y^TY XθY)T(XθY)=(θTXTYT)(XθY)=θTXTXθθTXTYYTXθ+YTY
θ \theta θ求导数的结果为
2 X T X θ − 2 X T Y 2X^TX\theta-2X^TY 2XTXθ2XTY
令原始为 0
可以求得 θ = ( X T X ) − 1 X T Y \theta=(X^TX)^{-1}X^TY θ=(XTX)1XTY (正规方程)
现在,即使是多元函数,我们也可以方便求解了

1.2.4.4 在python中用正规方程实现线性回归

知道了原理,接下来,使用代码来实现一下回归。

import numpy as np
from sklearn.model_selection import train_test_split
from numpy.linalg import inv

date = np.loadtxt("./date/aqi.csv", delimiter=",", skiprows=1, dtype=np.float32) 
 # delimiter:   以逗号分开                dtype:加载时的数据类型
 # skiprows:删除第一条数据(标题)
index = np.ones((date.shape[0], 1)) # 生成一列全部为1的数据  (正规方程需要多一列的数据)
date = np.hstack((date, index))     # 插入一列
x = date[:, 1:]                     # 截取行(第0行到最后一行),列(第1行到最后一列)
y = date[:, 0]                      # 截取行(第0行到最后一行),列(第0列)
# print(x)

# 将数据分隔为训练集和验证集
train_x, test_x, train_y, test_y = train_test_split(x, y, train_size = 0.7)
 # 百分之80的数据为训练集,20为验证集
theta = np.dot(np.dot(inv(np.dot(train_x.T, train_x)), train_x.T), train_y)   # 正规方程
# np.dot()矩阵相乘    inv() 求逆    .T 转置 
predict = np.dot(test_x, theta)
print(test_x[:, 0])
print(predict)

import matplotlib.pyplot as plt		# 对预测结果与实际结果进行显示,比较
plt.plot(range(len(test_y)), test_y, c="red", alpha=0.5)
plt.plot(range(len(test_y)), predict, c="blue", alpha=0.5)
plt.show()

其中aqi.csv的数据为

x,y
1,1.1
2,2.3
3,3.1
4,4.5
5,5.4
6,6.7
7,7.8
8,9
9,9.7
10,11

1.2.5 使用梯度下降拟合

1.2.5.1 什么是梯度下降

举个例子,在方程 y = x 2 y=x^2 y=x2中,我们如何求该函数的最小值?
由于该方程比较简单。我们可以直接得出,当x为0 时,y最小为0
但是,在方程 y = − x 1 2 + 6 x 2 2 + 3 x 3 2 − 5 x 4 2 y=-x_1^2+6x_2^2+3x_3^2-5x_4^2 y=x12+6x22+3x325x42中,我们如何求他的最小值呢?

这时候,梯度下降的优势就体现出来了。
还是从 y = x 2 y=x^2 y=x2开始,要求得y的最小值,我们可以给x随机取一个值,判断在改点的导数大小,如果导数大于0,说明y在增大,我们后退一点;如果导数小于0,说明y在减小,就对x增大一些。

具体的方程为: x x x的更新值=上一次 x 的 值 − k ∗ d y d x x的值-k*\frac {dy} {dx} xkdxdy,然后对该方程进行迭代
其中k为我们随机取的一个小数。
实现过程:
在这里插入图片描述
第一步 首先我们随机取x,令x=-10,随机取k,令k=0.1,
很明显 d y d x = 2 x \frac {dy} {dx}=2x dxdy=2x,带入更新方程: x x x的更新值=上一次 x 的 值 − k ∗ d y d x x的值-k*\frac {dy} {dx} xkdxdy
X = − 10 − 0.1 ∗ 2 ∗ ( − 10 ) = − 8 X=-10-0.1*2*(-10)=-8 X=100.12(10)=8
第二步 对方程进行迭代,刚刚得到的x为-8,所以新的x值为
X = − 8 − 0.1 ∗ 2 ∗ ( − 8 ) = − 6.4 X=-8-0.1*2*(-8)=-6.4 X=80.12(8)=6.4
迭代5次后,得到的图像为上图所示
方程代码如下:

import numpy as np
import matplotlib.pyplot as plt
x = -10
A = [-10]
B = [100]
for i in range(5):  # 迭代5次
    y = 2*x         # 导数为2x
    x = x-0.1*y     # 更新方程
    A.append(round(x, 2))
    B.append(round(x*x, 2))

x = np.arange(-10, 10, 0.01)
y = x*x

fig = plt.figure()
ax = fig.add_subplot(111)
for xy in zip(A, B):
    ax.annotate('(%s, %s)' % xy, xy=xy, textcoords='data')  # 绘制(x,y)
plt.plot(A, B, "ro")  # 绘制点
plt.plot(x, y)
plt.title("")
plt.show()

下图是迭代10次后的结果:
在这里插入图片描述
这里,可以发现,随着迭代次数的增加,方程会越来越接近最小值。

好了,现在回到原来的问题,如何求方程 y = − x 1 2 + 6 x 2 2 + 3 x 3 2 − 5 x 4 2 y=-x_1^2+6x_2^2+3x_3^2-5x_4^2 y=x12+6x22+3x325x42的最小值。这个问题似乎还是有点难!
知道了一元函数,我们还是从二元函数入手。
现在,求 z = x 2 + y 2 z=x^2+y^2 z=x2+y2的最小值
第一步 随机取,x和y的值 ,这里 我们 取 (x=3,y=4) ,取k为0.1,
d z d x = 2 x \frac {dz} {dx}=2x dxdz=2x, d z d y = 2 y \frac {dz} {dy}=2y dydz=2y ,
(x,y)=(3,4)-0.1(6,8)=(2.4,3.2)
第二步 对x,y进行迭代,刚刚求得的(x,y)=(2.4,3.2),
新一轮的结果为(x,y)=(2.4,3.2)-0.1(4.8,6.4)=(1.92,2.56)
迭代5次的效果图为下图所示:
在这里插入图片描述
我们发现红点渐渐向最低点移动了
迭代源码:

from matplotlib import pyplot as plot  # 用来绘制图形

import numpy as np  # 用来处理数据

from mpl_toolkits.mplot3d import Axes3D  # 用来给出三维坐标系。

figure = plot.figure()

# 画出三维坐标系:
axes = Axes3D(figure)
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)

x = 3
y = 4  # 初始 x 与 y 的坐标
A = [3]
B = [4]
C = [25]   # A B C 存放 x,y,z的坐标变化
for i in range(5):  # 循环5次
    x = x-0.1*2*x
    y = y-0.1*2*y
    A.append(round(x, 2))
    B.append(round(y, 2))
    C.append(round(x*x+y*y, 2))

# 限定图形的样式是网格线的样式:
X, Y = np.meshgrid(X, Y)
Z = (X) ** 2 + (Y) ** 2

# 绘制曲面,采用彩虹色着色:
axes.scatter(A, B, C, c='r', marker='o')
axes.plot_surface(X, Y, Z, cmap='rainbow')

# 图形可视化:
plot.show()

下图为迭代100次的效果图:
在这里插入图片描述
在这里,k有个专业的名称,称之为学习率,一般用 a a a代替

1.2.5.2 梯度下降拟合线性回归流程

原方程为 f ( k , b ) = ∑ i = 1 n ( k ∗ x i ^ + b − y i ) 2 f(k,b)=\displaystyle \sum^{n}_{i=1 }{(k*\hat{x_i}+b-y_i)^2} f(k,b)=i=1n(kxi^+byi)2
要求f(k,b)的最小值,
第一步 和之前的做法类似,首先任意取k和b的值,取a为0.1,求得 ∂ f ( k , b ) ∂ k , ∂ f ( k , b ) ∂ k \frac{\partial f(k,b)}{\partial k}, \frac{\partial f(k,b)}{\partial k} kf(k,b),kf(k,b)后,带入 ( x i ^ , y i ) (\hat{x_i},y_i) (xi^,yi),设带入后的结果为 A,B

根据之前的梯度下降算法,得(k,b)=(k,b)-0.1(A,B)
第二步 对(k,b)做反复迭代。

1.2.5.3 梯度下降拟合实例

还是之前的x,y分布

x357813
y26911?

现在,用梯度下降来拟合
第一步 任意取k和b,令 k=1,b=6,这里a要取的稍微小些,取a=0.001,
首先对k求偏导 ∂ f ( k , b ) ∂ k = 2 ∑ i = 1 n ( k ∗ x i ^ + b − y i ) x i ^ = 2 k ∑ i = 1 n x i ^ 2 + 2 b ∑ i = 1 n x i ^ − 2 ∑ i = 1 n y i x i ^ \frac{\partial f(k,b)}{\partial k}=2\displaystyle \sum^{n}_{i=1 }{(k*\hat{x_i}+b-y_i)}\hat{x_i}=2k\sum^{n}_{i=1 }\hat{x_i}^2+2b\sum^{n}_{i=1 }\hat{x_i}-2\sum^{n}_{i=1 }y_i\hat{x_i} kf(k,b)=2i=1n(kxi^+byi)xi^=2ki=1nxi^2+2bi=1nxi^2i=1nyixi^
然后对b求偏导 ∂ f ( k , b ) ∂ b = 2 ∑ i = 1 n ( k ∗ x i ^ + b − y i ) = 2 ∑ i = 1 n k ∗ x i ^ + 2 n b − 2 ∑ i = 1 n y i \frac{\partial f(k,b)}{\partial b}=2\displaystyle \sum^{n}_{i=1 }{(k*\hat{x_i}+b-y_i)}=2\displaystyle \sum^{n}_{i=1 }k*\hat{x_i}+2nb-2\displaystyle \sum^{n}_{i=1 }y_i bf(k,b)=2i=1n(kxi^+byi)=2i=1nkxi^+2nb2i=1nyi
k和更新后的值为(k,b)= ( 1 , 6 ) − 0.001 ∗ ( ( 2 ∗ 1 ∗ ( 3 2 + 5 2 + 7 2 + 8 2 ) + 2 ∗ 6 ∗ ( 3 + 5 + 7 + 8 ) − 2 ∗ ( 2 ∗ 3 + 5 ∗ 6 + 7 ∗ 9 + 8 ∗ 11 ) , ( 2 ∗ k ∗ ( 3 + 5 + 7 + 8 ) + 2 ∗ 4 ∗ 6 − 2 ∗ ( 2 + 6 + 9 + 11 ) (1,6)-0.001*((2*1*(3^2+5^2+7^2+8^2)+2*6*(3+5+7+8)-2*(2*3+5*6+7*9+8*11),(2*k*(3+5+7+8)+2*4*6-2*(2+6+9+11) (1,6)0.001(2132+52+72+82+263+5+7+8223+56+79+811,(2k(3+5+7+8)+2462(2+6+9+11)=(0.804,5.971)
第二步 对k和b的值进行反复的迭代
迭代到50次的k为0.39,b为5.57,图像如下图所示
在这里插入图片描述
迭代50次的python源码

import numpy as np
import matplotlib.pyplot as plt
k = 1
b = 6
x = [3, 5, 7, 8]
y = [2, 6, 9, 11]
A = []
B = []
xsum = 0  # x1*x1+x2*x2+...
xxsum = 0  # x1+x2+x3+x4..
ysum = 0
yysum = 0
xysum = 0  # x1*y1+x2*y2+...
f=0
for i in x:
    xsum += i*i
for i in x:
    xxsum += i
for i in y:
    ysum += i*i
for i in y:
    yysum += i
for i in range(len(x)):
    xysum += x[i]*y[i]

for i in range(50):  # 循环50次
    k = k-0.001*(2*k*xsum+2*b*xxsum-2*xysum)
    b = b-0.001*(2*k*xxsum+2*4*b-2*yysum)
    A.append(round(k, 2))
    B.append(round(b, 2))
f = 0
for i in range(len(x)):
    f += (k * x[i] + b - y[i]) ** 2
print("loss={},k={},b={}".format(f, k, b))
fig = plt.figure()
ax = fig.add_subplot(111)
for xy in zip(x, y):
    ax.annotate('(%s, %s)' % xy, xy=xy, textcoords='data')  # 绘制(x,y)

x1 = np.arange(0, 10, 0.01)
y1 = k * x1 + b
plt.plot(x1, y1)
plt.plot(x, y, "ro")  # 绘制点
plt.title("")
plt.show()

当迭代到1000次时,k,b如下图所示:
在这里插入图片描述
此时k=1.11,b=0.98
当迭代到10000次时,可以看出,已经和直线非常拟合了,
此时的k=1.76,b= -3.13
在这里插入图片描述

1.3 用sklearn实现线性回归

1.3.1 sklearn中有自带实现线性回归的库
from sklearn.model_selection import train_test_split
from sklearn import linear_model #线性模型
import numpy as np
date = np.loadtxt("./date/aqi.csv", delimiter=",", skiprows=1, dtype=np.float32)  # delimiter:以,分开 dtype:加载时的数据类型
x = date[:, 1:]
y = date[:, 0]
train_x, test_x, train_y, test_y = train_test_split(x, y, train_size=0.7)
model = linear_model.LinearRegression()     # 线性回归模型对象
model.fit(train_x, train_y)
print(model.coef_) # 系数 (权重)
print(model.intercept_) # 截距 (偏置)

y_predict = model.predict(test_x)

import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ["SimHei"] # 支持中文
plt.title("预测")
plt.xlabel("x 轴")
plt.ylabel("y 轴")
plt.scatter(test_x, test_y, c="r")     # 画点
plt.plot(test_x, y_predict, c="blue")  # 画直线
plt.show()
1.3.2 机器学习中模型的保存 与 调用

如何把训练好的模型保存下来?

from sklearn.model_selection import train_test_split
from sklearn import linear_model #线性模型
import numpy as np
import pickle
date = np.loadtxt("./date/aqi.csv", delimiter=",", skiprows=1, dtype=np.float32)  # delimiter:以,分开 dtype:加载时的数据类型
x = date[:, 1:]
y = date[:, 0]
train_x, test_x, train_y, test_y = train_test_split(x, y, train_size=0.7)
model = linear_model.LinearRegression()     # 线性回归模型对象
model.fit(train_x, train_y)

with open("model.pickle", "wb") as f:  # 模型的保存
    pickle.dump(model, f)

调用自己训练好的模型

import pickle

with open("model.pickle", "rb") as f:
    model = pickle.load(f)
test = [[23]]
y_predict = model.predict(test)
print(y_predict)

2、逻辑回归

2.1 什么是逻辑回归?

假设有一批数据,让你求x=13时,y的值为多少。其中y的值只为0或者1

x357813
y0011?

我们首先用刚刚的线性回归的方法,进行拟合直线
在这里插入图片描述
然后把x=13带入方程,这里求得的k为0.23,b为-0.86,求得y为2.13。
现在,如何判断y的值呢?
首先,我们刚刚的拟合方法是有些问题的,因为y不是连续函数。
在这里,我们显然只要找一条直线,只要将两类数据划分开来就行了。我们随机划分一条直线,
在这里插入图片描述
上图为,k=0.15,b=-0.4 时 y ^ = k x + b \hat{y}=kx+b y^=kx+b的图像。接下来如何算x=13时,y的值呢?
我们可以这样,首先分别计算,x为3,5,7,8时 , y ^ \hat{y} y^的取值
x=3时, y ^ = 0.15 ∗ 3 − 0.4 = 0.05 \hat{y}=0.15*3-0.4=0.05 y^=0.1530.4=0.05
x=5时, y ^ = 0.15 ∗ 5 − 0.4 = 0.35 \hat{y}=0.15*5-0.4=0.35 y^=0.1550.4=0.35
x=7时, y ^ = 0.15 ∗ 7 − 0.4 = 0.65 \hat{y}=0.15*7-0.4=0.65 y^=0.1570.4=0.65
x=8时, y ^ = 0.15 ∗ 8 − 0.4 = 0.8 \hat{y}=0.15*8-0.4=0.8 y^=0.1580.4=0.8
然后,我们现在取一个在x=5和x=7时, y ^ \hat{y} y^的值作为分界线(0.35,0.65)
我们随机取值为 0.5,即 y ^ \hat{y} y^大于0.5,y为1; y ^ \hat{y} y^小于0.5,y为0
接下来算x=13时, y ^ \hat{y} y^=0.15*13-0.4=1.55
因为 y ^ \hat{y} y^>0.5所以y的值为 1
但是,我们画出的图像却是这样的
在这里插入图片描述
我们原本是想用这条直线来划分两类,但是由于数据的增加,我们不得不重新选择k与b的值了。
那么有没有什么办法把这条直线映射到另一个方便观察的线条呢?

数学家把他映射到了 y = 1 1 + e − z y=\frac{1}{1+e^{-z}} y=1+ez1
在这里插入图片描述
上图,我们可以看出,该线条很好的映射出了 y ^ \hat{y} y^与y的映射关系。该函数称为sigmoid函数,也叫logistic函数。
逻辑回归实际上解决的是分类问题,即如何把离散的点映射到线段。那么为什么不叫逻辑"分类"。据说因为它是从线性回归推导过来的。

2.2 逻辑回归的损失函数

2.2.1 为什么不能用线性回归时的残差平方和做为损失函数?

在线性回归中我们的损失函数为,RSS= ∑ i = 1 n ( y ^ − y i ) 2 \displaystyle \sum^{n}_{i=1 }{(\hat{y}-y_i)^2} i=1n(y^yi)2 其中 y ^ = k ∗ x i ^ + b \hat{y}=k*\hat{x_i}+b y^=kxi^+b
在逻辑回归中,我们的 y ^ = 1 1 + e − y \hat{y}=\frac{1}{1+e^{-y}} y^=1+ey1其中 y = k ∗ x i ^ + b {y}=k*\hat{x_i}+b y=kxi^+b,如果我们也用RSS。 R S S = ( 1 − 0.78 ) 2 + ( 1 − 0.66 ) 2 + ( 1 − 0.63 ) 2 + 0.5 7 2 + 0.5 1 2 RSS = (1-0.78)^2+(1-0.66)^2+(1-0.63)^2+0.57^2+0.51^2 RSS=(10.78)2+(10.66)2+(10.63)2+0.572+0.512
看起来用这个损失函数,似乎也没有什么问题。但是使用该函数作为损失函数,如果使用梯度下降法的话,会产生多个局部最优解。为什么还会有多个局部优?
设损失函数为f(k,b)= ∑ i = 1 n ( 1 1 + e − ( k ∗ x i ^ + b ) − y i ) 2 \displaystyle \sum^{n}_{i=1 }{(\frac{1}{1+e^{-(k*\hat{x_i}+b)}}-y_i)^2} i=1n(1+e(kxi^+b)1yi)2 ,要求出 ∂ f ( k , b ) ∂ k \frac{\partial f(k,b)}{\partial k} kf(k,b)
我们先化简方程 y ^ = 1 1 + e − y \hat{y}=\frac{1}{1+e^{-y}} y^=1+ey1的导数, ∂ y ^ ∂ y = e − y ( 1 + e − y ) 2 = 1 + e − y − 1 ( 1 + e − y ) 2 = y ^ − y ^ 2 \frac{\partial \hat{y}}{\partial y}=\frac{e^{-y}}{(1+e^{-y})^2}=\frac{1+e^{-y}-1}{(1+e^{-y})^2}=\hat{y}-\hat{y}^2 yy^=(1+ey)2ey=(1+ey)21+ey1=y^y^2,求出 y ^ \hat{y} y^导后, 这里只是其中一个项的导数 ∂ f ( k , b ) ∂ k = 2 ( y ^ − y i ) ∗ ( y ^ − y ^ 2 ) ∗ x i ^ \frac{\partial f(k,b)}{\partial k}=2{({\hat{y}}-y_i)}*(\hat{y}-\hat{y}^2)*\hat{x_i} kf(k,b)=2(y^yi)(y^y^2)xi^
想要判断其凹凸性,我们需要对其做二阶导数= ∂ ( 2 ( y ^ − y i ) ( y ^ − y ^ 2 ) ∗ x i ^ ) ∂ k = ∂ ( 2 ( y ^ 2 − y ^ 3 − y ^ y i + y ^ 2 y i ) ∗ x i ^ ) ∂ k = 2 x i ^ ( 2 y ^ − 3 y ^ 2 − y i + 2 y ^ y i ) ∗ ( y ^ − y ^ 2 ) ∗ x i ^ \frac{\partial (2{({\hat{y}}-y_i)}(\hat{y}-\hat{y}^2)*\hat{x_i})}{\partial k}=\frac{\partial(2{({\hat{y}}^2-{\hat{y}}^3}-\hat{y}y_i+\hat{y}^2y_i)*\hat{x_i})}{\partial k}=2\hat{x_i}(2\hat{y}-3{\hat{y}}^2-y_i+2\hat{y}y_i)*(\hat{y}-\hat{y}^2)*\hat{x_i} k(2(y^yi)(y^y^2)xi^)=k(2(y^2y^3y^yi+y^2yi)xi^)=2xi^(2y^3y^2yi+2y^yi)(y^y^2)xi^

2.2.2 函数的二阶导数

函数的二阶导数有什么特性呢?
例如方程 y = x 2 y=x^2 y=x2中,函数的一阶导为2x,所以在左半轴,导数小于0,y值逐渐减小;在右半轴,导数大于0,y值逐渐变大。函数的二阶导为2,所以无论x取何值,二阶导恒大于0,
在这里插入图片描述
我们可以看到,二阶导大于0时,为凸函数,
在这里插入图片描述
接下来,我们对刚刚的导数 2 x i ^ ( 2 y ^ − 3 y ^ 2 − y i + 2 y ^ y i ) ∗ ( y ^ − y ^ 2 ) ∗ x i ^ 2\hat{x_i}(2\hat{y}-3{\hat{y}}^2-y_i+2\hat{y}y_i)*(\hat{y}-\hat{y}^2)*\hat{x_i} 2xi^(2y^3y^2yi+2y^yi)(y^y^2)xi^进行分析,
假设 y i = 0 , y ^ {y}_i=0,\hat{y} yi=0,y^在(0,1)内时,方程= 2 x i ^ 2 ( 2 y ^ − 3 y ^ 2 ) ∗ ( y ^ − y ^ 2 ) 2\hat{x_i}^2(2\hat{y}-3{\hat{y}}^2)*(\hat{y}-\hat{y}^2) 2xi^2(2y^3y^2)(y^y^2)
由于 y ^ \hat{y} y^在(0,1)时, 2 x i ^ 2 2\hat{x_i}^2 2xi^2恒大于0, ( y ^ − y ^ 2 ) (\hat{y}-\hat{y}^2) (y^y^2)恒大于0, 2 y ^ − 3 y ^ 2 2\hat{y}-3{\hat{y}}^2 2y^3y^2有正有负,所以凹凸性都存在。所以使用残差平方和不能作为逻辑回归的损失函数。
为了求逻辑回归的损失函数,我们需要知道什么是最大似然估计

2.3 最大似然估计

什么是最大似然估计?

举一个别人博客的一个例子。

假如有一个罐子,里面有黑白两种颜色的球,数目多少不知,两种颜色的比例也不知。我们想知道罐中白球和黑球的比例,但我们不能把罐中的球全部拿出来数。现在我们可以每次任意从已经摇匀的罐中拿一个球出来,记录球的颜色,然后把拿出来的球 再放回罐中。这个过程可以重复,我们可以用记录的球的颜色来估计罐中黑白球的比例。假如在前面的4次重复记录中,有1次是白球,请问罐中白球所占的比例最有可能是多少?
在这里插入图片描述
很多人马上就有答案了: 1 4 \frac{1}{4} 41
为什么大家都会想到 1 4 \frac{1}{4} 41
假设罐中白球的比例是p,那么黑球的比例就是1-p。
极大似然函数的思想就是:使之前出现的场景概率最大。
例如刚刚的场景:取到3次黑球,一次白球,写成函数即:
y = ( 1 − p ) ∗ ( 1 − p ) ∗ ( 1 − p ) ∗ p y=(1-p)*(1-p)*(1-p)*p y=(1p)(1p)(1p)p, 我们画出它的图像
在这里插入图片描述
从图像可以看出,p为0.25时,y的最大值为0.10546875。
这不是我们刚刚估计的结果值嘛,不过这是刚刚用计算机跑出来的结果!
现在,再用方程的思想来解y的最大值,由于ln()函数具有很好的单调性,而且可以把连乘拆分。
所以要求 y = ( 1 − p ) ∗ ( 1 − p ) ∗ ( 1 − p ) ∗ p y=(1-p)*(1-p)*(1-p)*p y=(1p)(1p)(1p)p的最大值,就等价与求 l n ( y ) = l n ( ( 1 − p ) ∗ ( 1 − p ) ∗ ( 1 − p ) ∗ p ) ln(y)=ln((1-p)*(1-p)*(1-p)*p) ln(y)=ln((1p)(1p)(1p)p)的最大值。
l n ( y ) ln(y) ln(y)的最大值,只需要对p求导,并且让其导数为0即可。
原始= l n ( 1 − p ) + l n ( 1 − p ) + l n ( 1 − p ) + l n ( p ) ln(1-p)+ln(1-p)+ln(1-p)+ln(p) ln(1p)+ln(1p)+ln(1p)+ln(p),求导后= − 3 1 − p + 1 p -\frac{3}{1-p}+\frac{1}{p} 1p3+p1
令其为0,解得p为0.25,这与之前用计算机跑出的结果一致。

2.4 逻辑回归的损失函数

了解了极大似然估计,理解逻辑回归的损失函数就很简单了。
首先,logistic函数表示的是一个概率值, y ^ = 1 1 + e − y \hat{y}=\frac{1}{1+e^{-y}} y^=1+ey1,如果真实值为1,那么 y ^ \hat{y} y^越大,表明效果越好;如果真实值为0,那么 y ^ \hat{y} y^越小,表明效果越好。
我们随机找一个函数: f ( y ^ , y i ) f(\hat{y},y_i) f(y^,yi),当 y i y_i yi为1时,损失函数为 1 − y ^ 1-\hat{y} 1y^,当 y i y_i yi为0时,损失函数为 y ^ \hat{y} y^
写出最大似然函数 = ∏ i = 1 n ( 1 − y ^ ) 1 − y i ∗ y ^ y i =\prod_{i=1}^n(1-\hat{y})^{1-y_i}*{\hat{y}}^{y_i} =i=1n(1y^)1yiy^yi,当 y i y_i yi为1时, y ^ \hat{y} y^有效,且 y ^ \hat{y} y^越大,似然函数越大
根据最大似然函数的值,我们可以知道似然函数的最大值,就是最接近结果的真实值,对似然函数取log的话, ∑ i = 1 n [ ( 1 − y i ) l o g ( ( 1 − y ^ ) ) + y i l o g ( y ^ ) ] \displaystyle \sum^{n}_{i=1 }[({1-y_i})log((1-\hat{y}))+{y_i}log({\hat{y}})] i=1n[(1yi)log((1y^))+yilog(y^)],加负号的话就成了损失函数。因为损失值的话是越小越好,所以logistic的损失函数为loss= − ∑ i = 1 n [ ( 1 − y i ) l o g ( ( 1 − y ^ ) ) + y i l o g ( y ^ ) ] -\displaystyle \sum^{n}_{i=1 }[({1-y_i})log((1-\hat{y}))+{y_i}log({\hat{y}})] i=1n[(1yi)log((1y^))+yilog(y^)]

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值