博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
机器学习之线性回归(纯python实现)][转]
阅读量:6908 次
发布时间:2019-06-27

本文共 3975 字,大约阅读时间需要 13 分钟。

本文转载自:

机器学习之线性回归(纯python实现)

线性回归是机器学习中最基本的一个算法,大部分算法都是由基本的算法演变而来。本文着重用很简单的语言说一下线性回归。

线性回归

包括一元线性回归和多元线性回归,一元指的是只有一个x和一个y。通过一元对于线性回归有个基本的理解。

一元线性回归就是在数据中找到一条直线,以最小的误差来(Loss)来拟和数据。

image.png

 

上面提到的误差可以这样表示,假设那条直线如下图:

image.png

 

理想情况是所有点都落在直线上。退一步,希望所有点离直线的距离最近。简单起见,将距离求平方,误差可以表示为:

image.png

 

上面的i表示第i个数据。一般情况下对Loss求平均,来当作最终的损失。

最小化误差

找到最能拟合数据的直线,也就是最小化误差。

最小二乘法

上述公式只有m, b未知,因此可以看最一个m, b的二次方程,求Loss的问题就转变成了求极值问题。 这里不做详细说明。

另每个变量的偏导数为0, 求方程组的解。

image.png
image.png求出m,b即可得到所要的直线。

 

梯度下降法

没有梯度下降就没有现在的深度学习。 最小二乘法可以一步到位,直接求出m,b。在大部分公式中是无法简单的直接计算的。而梯度下降通过一步一步的迭代,慢慢的去靠近那条最优的直线,因此需要不断的优化。 Loss的函数图像可以类比成一个碗。

image.png要求的最小值就在碗底,随意给出一点往下走,即沿着下降最快的方向(梯度)往下走,定义每一步移动的步长,移动的次数来逼近最优值。 下面用算法来实现:

 

初始化:

def init_data():    data = np.loadtxt('data.csv', delimiter=',')    return datadef linear_regression():    learning_rate = 0.01 #步长    initial_b = 0    initial_m = 0    num_iter = 1000 #迭代次数 data = init_data() [b, m] = optimizer(data, initial_b, initial_m, learning_rate, num_iter) plot_data(data,b,m) print(b, m) return b, m 复制代码

优化器去做梯度下降:

def optimizer(data, initial_b, initial_m, learning_rate, num_iter):    b = initial_b    m = initial_m    for i in range(num_iter):        b, m = compute_gradient(b, m, data, learning_rate)        # after = computer_error(b, m, data)        if i % 100 == 0:            print(i, computer_error(b, m, data)) # 损失函数,即误差 return [b, m] 复制代码

每次迭代计算梯度做参数更新:

def compute_gradient(b_cur, m_cur, data, learning_rate):    b_gradient = 0    m_gradient = 0    N = float(len(data))    #    # 偏导数, 梯度    for i in range(0, len(data)): x = data[i, 0] y = data[i, 1] b_gradient += -(2 / N) * (y - ((m_cur * x) + b_cur)) m_gradient += -(2 / N) * x * (y - ((m_cur * x) + b_cur)) #偏导数 new_b = b_cur - (learning_rate * b_gradient) new_m = m_cur - (learning_rate * m_gradient) return [new_b, new_m] 复制代码

Loss值的计算:

def computer_error(b, m, data):    totalError = 0    x = data[:, 0]    y = data[:, 1]    totalError = (y - m * x - b) ** 2    totalError = np.sum(totalError, axis=0)    return totalError / len(data)复制代码

执行函数计算结果:

if __name__ == '__main__':    linear_regression()复制代码

运算结果如下:

0 3.26543633854100 1.41872132865200 1.36529867423300 1.34376973304400 1.33509372632500 1.33159735872600 1.330188348700 1.32962052693800 1.32939169917900 1.329299483251.23930380135 1.86724196887复制代码

可以看到,随着迭代次数的增加,Loss函数越来越逼近最小值,而m,b也越来越逼近最优解。

注意:

在上面的方法中,还是通过计算Loss的偏导数来最小化误差。上述方法在梯度已知的情况下,即肯定按照下降最快的方法到达碗底。那么在公式非常难以计算的情况下怎么去求最优解。此时求偏导数可以使用导数的定义,看另一个函数。

def optimizer_two(data, initial_b, initial_m, learning_rate, num_iter):    b = initial_b    m = initial_m    while True:        before = computer_error(b, m, data)        b, m = compute_gradient(b, m, data, learning_rate)        after = computer_error(b, m, data)        if abs(after - before) < 0.0000001:  #不断减小精度            break    return [b, m] def compute_gradient_two(b_cur, m_cur, data, learning_rate): b_gradient = 0 m_gradient = 0 N = float(len(data)) delta = 0.0000001 for i in range(len(data)): x = data[i, 0] y = data[i, 1] # 利用导数的定义来计算梯度 b_gradient = (error(x, y, b_cur + delta, m_cur) - error(x, y, b_cur - delta, m_cur)) / (2*delta) m_gradient = (error(x, y, b_cur, m_cur + delta) - error(x, y, b_cur, m_cur - delta)) / (2*delta) b_gradient = b_gradient / N m_gradient = m_gradient / N # new_b = b_cur - (learning_rate * b_gradient) new_m = m_cur - (learning_rate * m_gradient) return [new_b, new_m] def error(x, y, b, m): return (y - (m * x) - b) ** 2 复制代码

上述两种中,迭代次数足够多都可以逼近最优解。 分别求得的最优解为: 1: 1.23930380135 1.86724196887 2: 1.24291450769 1.86676417482

简单比较

sklearn中有相应的方法求线性回归,其直接使用最小二乘法求最优解。简单实现以做个比较。

def scikit_learn():    data = init_data()    y = data[:, 1]    x = data[:, 0]    x = (x.reshape(-1, 1))    linreg = LinearRegression()    linreg.fit(x, y)    print(linreg.coef_)    print(linreg.intercept_)if __name__ == '__main__':    # linear_regression() scikit_learn() 复制代码

 

此时求的解为: 1.24977978176 1.86585571。 可以说明上述计算结果比较满意,通过后期调整参数,可以达到比较好的效果。

源码和数据参考:

感谢并参考博文:

作者:swensun
链接:https://juejin.im/post/5a924df16fb9a0634514d6e1
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
你可能感兴趣的文章
分别让div浮层靠左靠右和居中
查看>>
如何解决 JMeter 通过 JDBC 访问 Oracle 和 MySQL 的问题 (留言中有 Test Plan 实例下载)...
查看>>
19.7 主动模式和被动模式;19.8 添加监控主机;19.9 添加自定义模板19.10处理图形中的...
查看>>
SCOM2012功能测试(14)—创建.NET应用程序性能监控
查看>>
我的友情链接
查看>>
IEnumerable和IEnumerable<T>接口
查看>>
重定向redirect与跳转forward区别
查看>>
CentOS7之Rsync+Inotify架构实现实时同步文件和文件夹
查看>>
linux日志管理
查看>>
A.约数个数的和
查看>>
BZOJ1041:[HAOI2008]圆上的整点(数论)
查看>>
c# small tips
查看>>
双色球
查看>>
git 添加tab补全
查看>>
web.xml配置
查看>>
个人作业——软件工程实践总结作业(天亮了)
查看>>
修改dedecms中某个页面ueditor的宽度
查看>>
String为什么要设置成Final类型
查看>>
生成XML文件,并保存到本地文件
查看>>
[C++]const、typedef联合使用注意
查看>>