线性回归(一):一元线性回归(附python实现)


线性回归原理

一元线性回归

一元线性回归其实就是从一堆训练集中去算出一条直线,使数据集到直线之间的距离差最小。

举个栗子:

唯一特征X,共有m = 500个数据数量,Y是实际结果,要从中找到一条直线,使数据集到直线之间的距离差最小,如下图所示:

那要如何去完成这个操作呢?

线性回归所提供的思路是,先假设一条直线:

h(x) = \theta _{0} + \theta _{1} * x

可以将特征X中每一个值x^{i}都带入其中,得到对应的h\left ( x ^{i}\right ),定义可以将损失定义为y{i}h\left ( x ^{i}\right ) 之间的差值平方的和:

loss =\Sigma \left ( h\left ( x^{i} \right ) \right - y^{i})^{2}

而为了之后计算将其修改为

J\left ( \theta \right ) = \frac{1}{2m}\sum_{i = 0}^{m}(h(x^{i})-y^i)^2

接下来问题就简单了,只需要求出最小的J(\theta ) 就可以了。


梯度下降

可以看出,现在的问题已经变成了一个求极值的问题,这里面有很多种方法,有最小二乘,标准方程方法,以及梯度下降等等,在这里只简要分析一下梯度下降法。

\theta _{1}\theta _{2}分别从(-50,50)中取值,算出其的损失值,可以做出如下图:

其中x、y轴就是\theta _{1}\theta _{2},z轴是J\left ( \theta \right ) = \frac{1}{2m}\sum_{i = 0}^{m}(h(x^{i})-y^i)^2的值,现在目标就变成了从图中找到最低点,而最低点的xy轴坐标就是我们要的\theta

而梯度下降,顾名思义,就是要往下走,而这个往下走,方向并不随意,而是要沿着梯度最大的位置往下走,而最大,不久是它的偏导数吗,接下来要做的就是对J(\theta )求偏导:

\frac{\partial J(\theta ))}{\partial \theta _{0}}=\frac{1}{m}\sum_{i=1}^{m}(h_{\theta }(x^{i})-y^{i})

\frac{\partial J(\theta ))}{\partial \theta _{1}}=\frac{1}{m}\sum_{i=1}^{m}(h_{\theta }(x^{i})-y^{i})*x^i

之后更新得到新的\theta _0\theta _{1}

\theta _{0}:=\theta _{0}-\alpha \frac{1}{m}\sum_{i=1}^{m}(h_{\theta }(x^{i})-y^{i})

\theta _{1}:=\theta _{1} - \alpha \frac{1}{m}\sum_{i=1}^{m}(h_{\theta }(x^{i})-y^{i})*x^i

在这个公式里突然多了一个\alpha,它表示的是学习率,用来限定步长的大小,也很容易理解,毕竟得到的偏导是类似斜率的东西,只是一个方向,总得加个数值,才能表示向这个方向移动的距离。

对于\alpha的取值,一般都取的比较小,但也不要太小,太小就意味着迭代步数要增加,运算时间边长。

另外,迭代的步数要自己设置。

python实现

因为并没有数据集,就自己做了一个,代码只是简单的实现了一下。

# -*- coding: utf-8 -*-
"""
Created on Wed Jun 20 17:09:13 2018

@author: 96jie
"""

#导入cv模块
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

#数据
a = np.random.standard_normal((1, 500))
x = np.arange(0,50,0.1)
y = np.arange(20,120,0.2)
y = y - a*10
y = y[0]


#梯度下降
def Optimization(x,y,theta,learning_rate):
    for i in range(iter):
        theta = Updata(x,y,theta,learning_rate)
    return theta

def Updata(x,y,theta,learning_rate):
    m = len(x)
    sum = 0.0
    sum1 = 0.0
    alpha = learning_rate
    h = 0
    for i in range(m):
        h = theta[0] + theta[1] * x[i]
        sum += (h - y[i])
        sum1 += (h - y[i]) * x[i]
    theta[0] -= alpha * sum / m 
    theta[1] -= alpha * sum1 / m 
    return theta

#数据初始化
learning_rate = 0.001
theta = [0,0]
iter = 1000
theta = Optimization(x,y,theta,learning_rate)

plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
'''
plt.figure(figsize=(35,35))
plt.scatter(x,y,marker='o')
plt.xticks(fontsize=40)
plt.yticks(fontsize=40)
plt.xlabel('特征X',fontsize=40)
plt.ylabel('Y',fontsize=40)
plt.title('样本',fontsize=40)
plt.savefig("样本.jpg")
'''
#可视化
b = np.arange(0,50)
c = theta[0] + b * theta[1]

plt.figure(figsize=(35,35))
plt.scatter(x,y,marker='o')
plt.plot(b,c)
plt.xticks(fontsize=40)
plt.yticks(fontsize=40)
plt.xlabel('特征X',fontsize=40)
plt.ylabel('Y',fontsize=40)
plt.title('结果',fontsize=40)
plt.savefig("结果.jpg")

猜你喜欢

转载自blog.csdn.net/i96jie/article/details/81206473