单特征线性回归
线性回归模型是回归模型的一种,通常用于预测数据。
一、模型
二、成本函数的使用
线性回归的目标是找到合适的w、b,使成本函数的值最小,让假设函数直线与训练集拟合最好。成本函数是衡量预测值与真实值之间的差异,也即误差,误差越小,预测的结果自然更接近真实值。
以下将展示成本函数与参数的可视化图形。
1.简化的假设函数,f=wx:
2.完整的假设函数,f=wx+b:
在同一条等高线上,可能有多种不同的参数w、b使成本函数值相等,这样并不利于预测。在这样碗状图形的最底部或最低点,成本函数的值是最小的,也是唯一的。
三、梯度下降
如何寻找最合适的参数w、b?虽然我们已经理解最低处是使成本函数最小的点,但是直接利用可视化图形去读取,这在复杂的模型中显然是不可取的。此时,就要利用到梯度下降算法,它是机器学习中最重要的算法之一。实际上,梯度下降算法不仅仅适用于回归模型,它适用于几乎所有多参数模型。
1、思想
从起始点开始梯度下降,每走一步都选择梯度下降最快的点,直至到达局部最低点。
2、梯度下降算法的实现
每下降一次就更新一次参数w、b。到达局部最低点以后,w、b的值将不再变化。
3、梯度下降的理解
梯度下降的任务是找到最小化成本函数的参数w、b。
以简化模型为例,只有一个参数w时:
4、学习率的选择
当学习率过小时,下降的步子过小,导致到达最低点需要很多步,需要的时间也更多;
当学习率过大时,下降的步子较大,可能越过最低点,导致越来越远,甚至永远也到达不了最低点。
为什么我们可以采用固定的学习率?因为越靠近最低点,斜率将会越来越小,等于迈的步子越来越小了,最终也会慢慢靠近最低点。
四、线性回归的梯度下降
1、微积分的推导
2、梯度下降
3、差异
在梯度下降中,成本函数可能存在多个局部最小值,但是对于线性回归而言,成本函数只有一个全剧最小点。
所以在线性回归模型中,只要学习率选择得当,成本函数总是会收敛于全局最小值。
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()