单特征线性回归

线性回归模型是回归模型的一种,通常用于预测数据。

一、模型

XGboost回归模型算法过程 回归模型b的含义_线性回归

二、成本函数的使用

线性回归的目标是找到合适的w、b,使成本函数的值最小,让假设函数直线与训练集拟合最好。成本函数是衡量预测值与真实值之间的差异,也即误差,误差越小,预测的结果自然更接近真实值。

以下将展示成本函数与参数的可视化图形。

1.简化的假设函数,f=wx:

XGboost回归模型算法过程 回归模型b的含义_数据_02

2.完整的假设函数,f=wx+b:

XGboost回归模型算法过程 回归模型b的含义_线性回归_03

在同一条等高线上,可能有多种不同的参数w、b使成本函数值相等,这样并不利于预测。在这样碗状图形的最底部或最低点,成本函数的值是最小的,也是唯一的。

XGboost回归模型算法过程 回归模型b的含义_XGboost回归模型算法过程_04

三、梯度下降

如何寻找最合适的参数w、b?虽然我们已经理解最低处是使成本函数最小的点,但是直接利用可视化图形去读取,这在复杂的模型中显然是不可取的。此时,就要利用到梯度下降算法,它是机器学习中最重要的算法之一。实际上,梯度下降算法不仅仅适用于回归模型,它适用于几乎所有多参数模型。

1、思想

从起始点开始梯度下降,每走一步都选择梯度下降最快的点,直至到达局部最低点。

XGboost回归模型算法过程 回归模型b的含义_XGboost回归模型算法过程_05

2、梯度下降算法的实现

每下降一次就更新一次参数w、b。到达局部最低点以后,w、b的值将不再变化。

XGboost回归模型算法过程 回归模型b的含义_梯度下降_06

3、梯度下降的理解

梯度下降的任务是找到最小化成本函数的参数w、b。

以简化模型为例,只有一个参数w时:

XGboost回归模型算法过程 回归模型b的含义_XGboost回归模型算法过程_07

4、学习率的选择

当学习率过小时,下降的步子过小,导致到达最低点需要很多步,需要的时间也更多;

当学习率过大时,下降的步子较大,可能越过最低点,导致越来越远,甚至永远也到达不了最低点。

为什么我们可以采用固定的学习率?因为越靠近最低点,斜率将会越来越小,等于迈的步子越来越小了,最终也会慢慢靠近最低点。

四、线性回归的梯度下降

1、微积分的推导

XGboost回归模型算法过程 回归模型b的含义_XGboost回归模型算法过程_08

2、梯度下降

XGboost回归模型算法过程 回归模型b的含义_XGboost回归模型算法过程_09

3、差异

在梯度下降中,成本函数可能存在多个局部最小值,但是对于线性回归而言,成本函数只有一个全剧最小点。

所以在线性回归模型中,只要学习率选择得当,成本函数总是会收敛于全局最小值。

XGboost回归模型算法过程 回归模型b的含义_线性回归_10

4、批量梯度下降

批量梯度下降指的是在梯度下降的每一步,我们都会考虑所有的训练样本,而不是训练数据的一个子集。事实上,还有其他的梯度下降算法在下降时仅仅考虑训练数据的一个子集,在这里我们采用批量梯度下降的方法处理线性回归模型。

五、实现

部分数据集和完整代码

6.1101,17.592
5.5277,9.1302
8.5186,13.662
7.0032,11.854
5.8598,6.8233
8.3829,11.886
7.4764,4.3483
8.5781,12
6.4862,6.5987
5.0546,3.8166
5.7107,3.2522
14.164,15.505
5.734,3.1551
.......
"""
    在本练习的这一部分,您将使用单变量实现线性回归,以预测食品卡车的利润。
    假设你是一家餐饮连锁店的首席执行官,正在考虑在不同的城市开设新的分店。这家连锁店已经在各个城市拥有卡车,你可以从这些城市获得利润和人口数据。您希望使用这些数据来帮助您选择下一步要扩展到哪个城市。文件ex1data1.txt包含线性回归问题的数据集。第一列是一个城市的人口,第二列是该城市食品卡车的利润。利润为负值表示亏损。
"""

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 导入数据
path = r'data/ex1data1.txt'
data = pd.read_csv(path, header=None, names=['Population', 'Profit'])

# 在训练集中索引为0处添加一列,以便我们可以使用向量化的解决方案来计算代价和梯度,值为1,命名为“ones”
data.insert(0, 'ones', 1)

# 取数据集列数:3
cols = data.shape[1]  # df.shape返回的是一个元组(97,3),97表示行数,3表示列数

X = data.iloc[:, 0:cols - 1]  # 提取数据集除最后一列外的所有数据
y = data.iloc[:, cols - 1:cols]  # 提取数据集最后一列的数据

# 转换成numpy的矩阵格式
X = np.matrix(X.values)  # 97x2的矩阵 
y = np.matrix(y.values)  # 97x1的矩阵

# theta存放参数w、b,初始化为0
theta = np.matrix(np.array([0, 0]))  # 一个1x2矩阵(0 0)

alpha = 0.0001  # 学习速率α
iters = 1000  # 下降的步数。

def computeCost(X, y, theta):
    """代价函数"""
    linear = np.power(((X * theta.T) - y), 2)  # np.power(x,y),计算x的y次方
    cost = np.sum(linear) / (2 * len(X))
    return cost

def gradientDescent(X, y, theta, alpha, iters):   
    """梯度下降法"""
    # 存放参数w、b的中间量
    temp = np.matrix(np.zeros(theta.shape))  # np.zeros生成一个给定形状和类型的用0填充的数组
    
    # 参数的个数
    parameters = int(theta.ravel().shape[1])  # ravel:扁平化函数,矩阵变成1行N列
    # # 生成一个包含iters个0的数组,用于存放每一次下降后的成本
    cost = np.zeros(iters)  
    
    # 迭代iters次
    for i in range(iters):
        error = (X * theta.T) - y  # 表示成本f(w,b) - y
        # 更新参数w、b。(j为0时表示更新b,j为1时表示更新w,theta为存放参数w、b的矩阵[b w])
        for j in range(parameters):
            term = np.multiply(error, X[:, j])  # (f(w,b) - y )* x(j)
            temp[0, j] = theta[0, j] - (alpha / len(X)) * np.sum(term)  
        theta = temp
        #计算成本
        cost[i] = computeCost(X, y, theta)
    # 返回更新iters次后的theta,以及每次下降后的代价值
    return theta, cost  

print("theta初始值为0的成本值为:",computeCost(X,y,theta))

# 开始梯度下降
g, cost = gradientDescent(X, y, theta, alpha, iters)
print("更新{}次后的成本值为:".format(iters), computeCost(X, y, g))

# 构造假设函数
x = np.linspace(data.Population.min(), data.Population.max(), 100)  # 从最小值到最大值之间均匀的取100个值
h = g[0, 0] + (g[0, 1] * x)  # 假设函数

# 绘制训练集散点图和拟合直线
fig, ax = plt.subplots(figsize=(12, 8))
ax.plot(x, h, 'r', label='Prediction')  #绘制假设函数拟合的直线
ax.scatter(data.Population, data.Profit, label='Traning Data')  # 训练集散点图
ax.legend(loc=2)
ax.set_xlabel('Population')
ax.set_ylabel('Profit')
ax.set_title('Predicted Profit VS. Population Size')
plt.show()

# 绘制学习曲线
fig, ax = plt.subplots(figsize=(12, 8))
ax.plot(np.arange(iters), cost, 'r')  # 观察成本函数下降情况
ax.set_xlabel('Iterations')
ax.set_ylabel('Cost')
ax.set_title('Error vs. Training Epoch')
plt.show()