梯度下降法和Sklearn实现线性回归

1.线性回归模型

线性回归 (linear regression)是—种线性模型, 它假设输入变量 x和单个输出变量 y 之间存在线性关系。具体来说,利用线性回归模型,可以从—组输入变量 x 的线性组合中, 计算输出变量 y. 即y=ax+b

给定有d个属性(特征)描述的示例X=(x1;x2;...,xd),其中xi是x在第i个属性(特征)上的取值,线性模型(linear model)试图学得一个通过属性(特征)的线性组合来进行预测的函数,即:

{\color{Red} }f(x)=w1x2+w2x2+...+wdxd+b{\color{Red} }

一般用向量形式写成:

f(x)=$w^T$+b

其中w=(w1;w2;..;wd)

假设特征和结果都满足线性,即不大于一次方。 w和b学习之后,模型就得以确定。

许多功能更为强大的非线性模型可在线性模型的基础上通过引入层次结构或高维映射而得。

2.多元线性回归

如果有两个或两个以上的自变量,这样的线性回归分析就称为多元线性回归

实际问题中,一个现象往往受多个因素影响的,所以多元线性回归比一元线性回归的实际应用更广。

3.梯度下降法求解线性回归

  • 梯度下降法一般用于多元线性回归求解
  • 梯度下降(gradient descent)是一种常用的一阶优化方法,是求解无约束优化问题最简单、最经典的方法之一
  • 梯度方向:函数变化增长最快的方向(变量沿此方向变化时函数增长最快)
  • 负梯度方向:函数变化减少最快的方向(变量沿此方向变化时函数减少最快)
  • 损失函数是系数的山上,那么如果系数沿着损失函数的负梯度方向变化,此时损失函数减少最快,能够以最快速度下降到极小值。
  • 沿着负梯度方向迭代,迭代后的\Theta使损失函数J(\Theta )更小:

                \Theta =\Theta - \alpha*(\partial J(\Theta )/\partial \Theta )

  • 梯度下降不一定能够找到全局的最优解,有可能是一个局部最优解
  • 如果损失函数是凸函数,梯度下降法得到的解就一定是全局最优解

下面是公式的推导过程:

  • \alpha在梯度下降算法中被称为学习率或者步长
  • 这意味着我们可以通过\alpha来控制每一步走的距离,以保证不要走太快,错过了最低点;同时也要保证收敛速度不要太慢
  • 所以\alpha的选择在梯度下降法中往往是最重要的,不能太大也不能太小

4.梯度下降法和最小二乘法对比

  • 相同点

本质和目标不同:两种算法都是经典的学习算法,在给定已知数据的前提下利用求导算出一个模型(函数),使得损失函数最小,然后对给定的新数据进行估算预测

  • 不同点

- 损失函数:梯度下降可以选取其他损失函数,而最小二乘一定是平方损失函数

- 实现方法:最小二乘法是直接求导找出全局最小;而梯度下降是一种迭代法

- 效果:最小二乘找到的一定是全局最小,但计算繁琐,且复杂情况下未必有解;梯度下降迭代计算简单,但找到的一般是局部最小,只有在目标函数是凸函数时才是全局最小;

 到最小点附近时收d敛速度会变慢,且对初始点的选择极为敏感。

5.线性回归梯度下降代码实现

首先新建一个data.csv文件,里面填充两列数据。由于csdn不好上传data.csv文件,在这里需要大家自己新建测试数据。我是用python语言,在jupyter中实现的。

(1)引入依赖和导入数据

#引入依赖
import numpy as np
import matplotlib.pyplot as plt

#导入数据
points = np.genfromtxt('data.csv', delimiter=',')
points[0,0]

# 提取points中的两列数据,分别作为x,y
x = points[:, 0]
y = points[:, 1]

# 用plt画出散点图
plt.scatter(x, y)
plt.show()

(2)定义损失函数

# 损失函数是系数的函数,另外还要传入数据的x,y
def compute_cost(w, b, points):
    total_cost = 0
    M = len(points)
    
    # 逐点计算平方损失误差,然后求平均数
    for i in range(M):
        x = points[i, 0]
        y = points[i, 1]
        total_cost += ( y - w * x - b ) ** 2
    
    return total_cost/M

(3)定义模型参数 

alpha = 0.0001
initial_w = 0
initial_b = 0
num_iter = 10

(4)定义核心梯度下降算法函数 

def grad_desc(points, initial_w, initial_b, alpha, num_iter):
    w = initial_w
    b = initial_b
    # 定义一个list保存所有的损失函数值,用来显示下降的过程
    cost_list = []
    
    for i in range(num_iter):
        cost_list.append( compute_cost(w, b, points) )
        w, b = step_grad_desc( w, b, alpha, points )
    
    return [w, b, cost_list]

def step_grad_desc( current_w, current_b, alpha, points ):
    sum_grad_w = 0
    sum_grad_b = 0
    M = len(points)
    
    # 对每个点,代入公式求和
    for i in range(M):
        x = points[i, 0]
        y = points[i, 1]
        sum_grad_w += ( current_w * x + current_b - y ) * x
        sum_grad_b += current_w * x + current_b - y
    
    # 用公式求当前梯度
    grad_w = 2/M * sum_grad_w
    grad_b = 2/M * sum_grad_b
    
    # 梯度下降,更新当前的w和b
    updated_w = current_w - alpha * grad_w
    updated_b = current_b - alpha * grad_b
    
    return updated_w, updated_b

(5)测试:运行梯度下降算法计算最优的w和b 

w, b, cost_list = grad_desc( points, initial_w, initial_b, alpha, num_iter )

print("w is: ", w)
print("b is: ", b)

cost = compute_cost(w, b, points)

print("cost is: ", cost)

plt.plot(cost_list)
plt.show()

输出显示:

(6)画出拟合曲线 

plt.scatter(x, y)
# 针对每一个x,计算出预测的y值
pred_y = w * x + b

plt.plot(x, pred_y, c='r')
plt.show()

6.调用sklearn库代码实现

 前(1)(2)步骤同上述代码

from sklearn.linear_model import LinearRegression
lr = LinearRegression()

x_new = x.reshape(-1, 1)#行数不限,显示成一列
y_new = y.reshape(-1, 1)
lr.fit(x_new, y_new)
# 从训练好的模型中提取系数和截距
w = lr.coef_[0][0]
b = lr.intercept_[0]

print("w is: ", w)
print("b is: ", b)

cost = compute_cost(w, b, points)

print("cost is: ", cost)
plt.scatter(x, y)
# 针对每一个x,计算出预测的y值
pred_y = w * x + b

plt.plot(x, pred_y, c='r')
plt.show()

猜你喜欢

转载自blog.csdn.net/lovebaby1689/article/details/110940682