先说点废话
在之前的项目中使用了深度学习算法,但是没有取得比较好的效果。这个也不只是算法的原因,跟他们的数据也有一定的关系。然后就开始考虑要不要使用一些其他比较简单的机器学习算法来尝试一下。打算把一些常用的机器学习算法写一个系列来跟大家分享交流,今天主要讨论的就是线性回归算法。ps:最近刚刚从组长那里知道csdn可以直接写数学公式,哈哈哈,再也不用去word里敲公式再截图了。废话不多说,上干货!
线性回归算法模型
线性回归算法模型很简单,每条数据有n个特征,每个特征对应着一个自己的权重值,与权重的乘积再加上一个偏置值,这个就是线性回归模型,公式如下:
y=w1∗x1+w2∗x2+...+wn∗xn+b
y
=
w
1
∗
x
1
+
w
2
∗
x
2
+
.
.
.
+
w
n
∗
x
n
+
b
为了方便后续写成矩阵的形式,我们这边可以稍作修改,令 w0=b,x0=1 w 0 = b , x 0 = 1 ,就可以写成下边的形式:
y=w0∗x0+w1∗x1+w2∗x2+...+wn∗xn
y
=
w
0
∗
x
0
+
w
1
∗
x
1
+
w
2
∗
x
2
+
.
.
.
+
w
n
∗
x
n
假设现在有m个样本,写成矩阵的形式就是:
X=⎡⎣⎢⎢⎢⎢11...1x11x12...x1mx21x22...x2m............xn1xn2...xnm⎤⎦⎥⎥⎥⎥Y=⎡⎣⎢⎢⎢y1y2...ym⎤⎦⎥⎥⎥
X
=
[
1
x
1
1
x
1
2
.
.
.
x
1
n
1
x
2
1
x
2
2
.
.
.
x
2
n
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
x
m
1
x
m
2
.
.
.
x
m
n
]
Y
=
[
y
1
y
2
.
.
.
y
m
]
权重 w w 也可以写成矩阵的形式:
那么可以写成一种简单明了的方式:
Y=XWT
Y
=
X
W
T
ps: n n 代表特征数目,代表样本数目
损失函数
损失函数是可以一定程度上衡量模型的好坏的一个算法,我们这里介绍一个在回归问题中比较常用的损失:均方误差(MSE)
cost=1m∑i=1m(yi^−yi)2
c
o
s
t
=
1
m
∑
i
=
1
m
(
y
i
^
−
y
i
)
2
其中 yi^ y i ^ 是样本的预测值, yi y i 是样本的实际值,可以看出当 cost c o s t 值越小的时候,预测值越接近实际值。
优化器
算法在学习的过程中是要逐渐的去减少 cost c o s t 的值的,那么如何减少损失函数的值呢,我们这里简单介绍一种优化器:梯度下降算法
假设我们的样本只有一个特征,且偏置项为0,那么我们的损失函数就可以写为:
cost(w)=1m∑i=1m(w∗x−yi)2
c
o
s
t
(
w
)
=
1
m
∑
i
=
1
m
(
w
∗
x
−
y
i
)
2
可以看出这是一个关于 w w 的二次函数,图像如下:
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/8f27ac1b1564dd936cff4e0dabf99c89.png)
(没了解过画图工具,从别人那里截的图,就是我们的 cost(w) c o s t ( w ) , θ θ 就对应我们的 w w )
如果拓展到三维空间就是一个往下凹的曲面。梯度下降算法就是通过每次训练,更新的值,使得每次更新之后,损失值变的更小。那么他是怎么更新的呢?我们需要自己定义一个初始的 w w 值,函数对 w w 求导,每次更新的时候都是在原来的基础上减去, α α 就是学习率,控制更新参数的快慢,可以看出 α α 值比较大的话,训练很快,但是很容易就跳过了最优解,但是 α α 太小又训练的很慢,这个就需要自己去适当的调整了。
在全部特征的情况下, cost(w) c o s t ( w ) 对各参数求导之后的公式为:
dd(wi)cost(w)=2m∑i=1m(yi^−yi)xi
d
d
(
w
i
)
c
o
s
t
(
w
)
=
2
m
∑
i
=
1
m
(
y
i
^
−
y
i
)
x
i
一共有n+1个参数,各参数同步更新。
一个小例子
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
#模拟数据
x = np.linspace(0, 10, 50)
noise = np.random.uniform(-2,2,size=50)
y = 5 * x + 6 + noise
#创建模型
liner = LinearRegression()
#拟合模型
liner.fit(np.reshape(x,(-1,1)),np.reshape(y,(-1,1)))
print(liner)
#预测
y_pred = liner.predict(np.reshape(x,(-1,1)))
plt.figure(figsize=(5,5))
plt.scatter(x,y)
plt.plot(x,y_pred, color="r")
plt.show()
print(liner.coef_)
print(liner.intercept_)
对数据的拟合情况如下:
打印出来的coef_ = [[4.97289515]]
intercept_ = [5.96788364]
我们设置的权重为5,偏置为6,可以看出相差不是很大。
手动撸算法源代码
个人感觉还是手动撸一波算法的源代码,能够对这个算法有更深刻的认识,我自己大致写了个这个算法的模板,运行之后效果还不错。设置的数据还是斜率为5,截距为6,训练之后的结果如下:
可以看出已经非常接近了。附上代码
import numpy as np
from sklearn.linear_model import LinearRegression
#模拟数据
x = np.linspace(0, 10, 50)
noise = np.random.uniform(-1,1,size=50)
y = 5 * x + 6 + noise
#计算损失函数
def compute_cost(x, y, theta):
y_pred = np.dot(x, theta.T)
inner = np.power((y_pred-y), 2)
cost = np.sum(inner, axis=0) / (2 * x.shape[0])
return cost
#梯度下降
def grandient_descent(x, y, theta, alpha, iters):
#参数长度
len_params = theta.shape[1]
#参数更新次数
for it in range(iters):
error_val = np.dot(x, theta.T) - y
error_val = np.reshape(error_val, (50,))
update_val_temp = np.zeros(shape=x.shape)
#参数个数
for p in range(len_params):
update_val_temp[:,p] = error_val * x[:,p]
update_val = np.mean(update_val_temp, axis=0)
#更新参数
theta = theta - alpha * update_val
print('第%d次训练===截距:%f,斜率%f' % (it, theta[0,0], theta[0,1]))
cost = compute_cost(x, y, theta)
return cost, theta
#初始化参数
#x插入一列值为1
x = np.reshape(x, (-1,1))
x = np.insert(x, 0, 1, axis=1)
#y值重新reshape一下
y = np.reshape(y, (-1,1))
theta = np.zeros(shape=(1, x.shape[1]))
#初始化参数
alpha = 0.01
iters = 2000
cost, theta_v = grandient_descent(x, y, theta, alpha, iters)
print(cost, theta_v)