1. 目的
给定一组数据(x,y),如何让机器学习该数据从而预测其他情况。例如:我们现在有一组(房子面积,房子价格)的数据,即数据集,如何推测其他房子面积的价格呢,这是一个回归问题。这时我们就需要通过已知数据,得到一个f(x),从而预测其他值。
注:数据比较多,故不能全部列举
我们将要用来描述这个回归问题的标记如下:
- 𝑛 代表训练集中实例的数量
- 𝑦 代表特征/输入变量
- 𝑧 代表目标变量/输出变量
- (𝑦,𝑧) 代表训练集中的实例
- (𝑦 (𝑗) ,𝑧 (𝑗) ) 代表第𝑗 个观察实例
- ℎ 代表学习算法的解决方案或函数也称为假设(hypothesis)
2. 数学推导
2.1 假设函数
一种可能的表达方式为:,因为只含有一个特征(输入变量),因此这样的问题叫作单变量线性回归问题。这个函数就叫假设函数。
重点:
, 是我们最终要求的,它的值决定了我们预测的精确性。
所谓线性回归就是再找最佳的,(计算机会一遍一遍得去试这两个值,直到损失值最小的)
2.2 损失函数
我们选择的参数决定了我们得到的直线相对于我们的训练集的准确程度,模型所预测的值与训练集中实际值之间的差距(下图中蓝线所指)就是 建模误差。
我们的目标便是选择出可以使得建模误差的平方和能够最小的模型参数。 即使得损失函数 (代价函数)最小(预测值与实际值更接近),
损失值为0,是最理想状态。
2.3 梯度下降
梯度下降是一个用来求函数最小值的算法,我们将使用梯度下降算法来求出损失函数的最小值。
思想:开始我们先随机选择一个参数价函数,然后我们寻找下一个能让代价函数值下降最多的参数组合。我们持续这么做直到到到一个局部最小值(local minimum),因为我们并没有尝试完所有的参数组合,所以不能确定我们得到的局部最小值是否便是全局最小值(global minimum),选择不同的初始参数组合,可能会找到不同的局部最小值
注:其中是学习率(learning rate),它决定了我们沿着能让代价函数下降程度最大的方向向下迈出的步子有多大,在批量梯度下降中,我们每一次都同时让所有的参数减去学习速率乘以代价函数的导数。
通常为:0.01,0.03, 0.1, 0.3 ,1 (损失函数容易收敛)
3. 代码实现
# -*- coding: utf-8 -*-
"""
作用:使用梯度下降法,实现一个特征值的线性回归
"""
import pandas as pd
import matplotlib.pyplot as plt # 画图包
import numpy as np
#读取数据并赋予列名
data = pd.read_csv('ex1data1.txt', names=['population', 'profit'])
# 求损失函数
def computerCost(x,y,theta):
# .power(矩阵,2):矩阵所有元素平方;.T:求转置
inner = np.power(((x*theta.T)-y),2)
# .sum:矩阵所有元素求和
return np.sum(inner)/(2*len(x))
# 批量梯度下降函数
def gradientDescent(x,y,theta,alpha,iters):
"""
批量梯度下降函数,求最优参数
:param x:
:param y:
:param theta: 参数矩阵
:param alpha: 学习率
:param iters: 迭代次数
:return: 参数估计值,损失值
"""
temp = np.matrix(np.zeros(theta.shape)) # 构建1*2零值矩阵
parameters = int(theta.ravel().shape[1]) # ravel()计算需要求解参数的个数(这里为2)
cost = np.zeros(iters) # 创建iters个0数组,用来存放每一次迭代的损失值
for i in range(iters):
error = (x * theta.T) - y
for j in range(parameters):
term = np.multiply(error,x[:,j]) #计算两矩阵相乘
temp[0,j] = theta[0,j] -((alpha/len(x))*np.sum(term))
theta = temp
cost[i] = computerCost(x,y,theta)
return theta,cost
# 绘制训练数据
#data.plot(kind='scatter',x='population',y='profit',figsize=(12,8))
# 插入一列,列名:ones 列值:全为1
data.insert(0,'ones',1)
# shape[0]表示数组行数 shape[1]表示列数
cols = data.shape[1]
# iloc 选取行或列
x = data.iloc[:,0:cols-1] # 选取所有行,0-1列 ,左闭右开
y = data.iloc[:,cols-1:cols] # 选取所有行, 2列
# 转换为numpy矩阵
x = np.matrix(x.values)
y = np.matrix(y.values)
theta = np.matrix(np.array([0,0])) # 定义参数,要求的系数
alpha = 0.01 # 学习率
iters = 1000 # 学习次数(迭代次数)
g,cost = gradientDescent(x,y,theta,alpha,iters)
# 绘制预测图像
x = np.linspace(data.population.min(),data.population.max(),100) #从最小值到最大值之间抽取100个值
y = g[0,0] + (g[0,1]*x) # 求对应y值
fig,ax = plt.subplots(figsize=(12,8))
ax.plot(x,y,'r',label='prediction')
ax.scatter(data.population,data.profit,label='Traning Data')
ax.legend(loc=4)
ax.set_ylabel('Profit')
ax.set_xlabel('Population')
ax.set_title('predicted profit by population')
plt.show()
# 画损失值
fig,ax = plt.subplots(figsize = (12,8))
ax.plot(np.arange(iters),cost,'r')
ax.set_ylabel('Cost')
ax.set_xlabel('Iterations')
ax.set_title('Error')
plt.show()
4. 回归效果
设置学习率alpha = 0.01 ,学习次数iters = 1000 (迭代次数),其效果如下:
4.1 拟合效果
4.2 损失函数
5.小结
5.1 优点
适合所以回归问题
5.2 缺点
损失函数的精度受学习率和学习次数(迭代次数)的影响,只能无限逼近于最优解。
参考资料:
https://www.bilibili.com/video/BV124411A75S?from=search&seid=1259570581914598099