一个线性回归实例的公式推导、代码实现、问题解析以及模型评价
1. 公式推导:
线性模型:
y = a x + b y = ax+b y=ax+b
损失函数:
l ( a , b ) = 1 2 m ∑ i = 1 m ( a x i + b − y l a b e l ) 2 l(a,b) = \frac{1}{2m}\sum_{i = 1}^{m} (ax_i + b - y_{label})^2 l(a,b)=2m1∑i=1m(axi+b−ylabel)2
梯度函数及其简单推导:
∂ l ∂ a \frac{\partial l }{\partial a} ∂a∂l
= 1 2 m ∑ i = 1 m [ 2 ( a x i + b − y l a b e l ) x i ] = \frac{1}{2m}\sum_{i = 1}^{m}[2(ax_i+b-y_{label})x_i] =2m1∑i=1m[2(axi+b−ylabel)xi]
= 1 m ∑ i = 1 m [ ( a x i + b − y l a b e l ) x i ] =\frac{1}{m}\sum_{i = 1}^{m}[(ax_i+b-y_{label})x_i] =m1∑i=1m[(axi+b−ylabel)xi]
∂ l ∂ b \frac{\partial l }{\partial b} ∂b∂l
= 1 2 m ∑ i = 1 m 2 ( a x i + b − y l a b e l ) = \frac{1}{2m}\sum_{i = 1}^{m}2(ax_i+b-y_{label}) =2m1∑i=1m2(axi+b−ylabel)
= 1 m ∑ i = 1 m ( a x i + b − y l a b e l ) =\frac{1}{m}\sum_{i = 1}^{m}(ax_i+b-y_{label}) =m1∑i=1m(axi+b−ylabel)
梯度下降迭代公式:
a : = a − α ∂ l ∂ a a := a - \alpha \frac{\partial l }{\partial a} a:=a−α∂a∂l
b : = b − α ∂ l ∂ b b := b - \alpha\frac{\partial l }{\partial b} b:=b−α∂b∂l
2. 代码实现:
import numpy as np
import matplotlib.pyplot as plt
class MyModel(object):
'''
对南京仙林大学城二手房价格的预测
'''
def __init__(self):
self._train_data_x = np.array([26,30,48,50,52,60,68,84,\
89,93,99,100,110,126,136])
self._train_data_y = np.array([126,116,195,205,188,220,240,\
325,262,350,275,258,410,455,430])
def func_linear_model(self,x,a,b):
'''
面积 - 价格的线性模型
y = a * x + b
'''
return a * x + b
def func_lost(self,x,a,b,y):
y_pred = self.func_linear_model(x,a,b)
return sum(pow(y_pred - y,2)) / 2 / len(x)
def _gradient_descent(self,x,a,b,y):
grad_b = sum(a * x + b - y) / len(y)
grad_a = sum((a * x + b - y).T * x) / len(y)
return grad_a,grad_b
def train(self,alpha=0.0002,times=100000):
a = 3
b = 40
x = self._train_data_x
y = self._train_data_y
lostList = []
for i in range(times):
delta_a,delta_b = self._gradient_descent(x,a,b,y)
a -= alpha * delta_a
b -= alpha * delta_b
lostList.append(self.func_lost(x,a,b,y))
return a,b,lostList
3. 问题解析:
- 建立房子的面积与总价之间的线性模型:由于忽略了房间数,所以此线性模型是单变量的,只要输入房子的面积x,我们就能对其总价y进行预测;又因为要求是建立线性模型,所以我们可以简单的假设此模型为 y = a x + b y = ax+b y=ax+b,需要确定的是参数a和b。我们采用梯度下降的做法求解这两个参数。
- 梯度下降的本质是通过某种迭代求解a和b,使得使用这两个参数进行预测的时候,预测结果尽可能的与真实值 Y l a b e l Y_{label} Ylabel相同,所以我们需要一个量考量预测值 a x + b ax+b ax+b与真实值 y l a b e l y_{label} ylabel之间的关系,这个量与参数有关,我们称其为损失函数: l ( a , b ) = 1 2 m ∑ i = 1 m ( a x i + b − y l a b e l ) 2 l(a,b) = \frac{1}{2m}\sum_{i = 1}^{m} (ax_i + b - y_{label})^2 l(a,b)=2m1∑i=1m(axi+b−ylabel)2,其中,m是现有数据的总量,我们将一组现有数据的每个单个数据 x i x_i xi放入模型预测,将预测值与数据的真实值作差并平方,再对所有的单个数据误差求和、除以 2 m 2m 2m。其中的 2 2 2只是为了后续处理的方便,并无真实含义。
- 得到损失函数以后,由于损失函数与两个参数a与b有关,是一个二元函数,所以我们对其求偏导;在累加中,对整体的偏导可以转化为对部分的偏导结果进行累加,所以这两个偏导数的求解并不困难。
- 求解出偏导函数(或者所谓梯度函数)以后,我们需要对梯度下降进行理解。我们的目的是使得在已有数据集上使得损失函数的值最小,这样我们的模型使用的参数a和b能进行最好的预测,这就是梯度下降的作用——使得损失函数的值最小,而我们有了损失函数的两个偏导函数。
我们不妨先假设损失函数不是二元函数,而是一个简单的一元函数,或者进一步的,是一个简单的一元二次函数,我们的偏导数就相当于损失函数的导函数。我们首先任意选择一个起始点a,此时的导函数(即梯度函数)值就是a处损失函数的导数。我们沿着负方向将a的值减小一个值,这个值是a与导数的乘积的某个倍数,此倍数称为步长;之后继续此过程,很容易发现,经过多次迭代,我们会找到这个一元二次损失函数的“谷底”——损失函数的最小值,这就是梯度下降算法的含义。
4. 模型评价:
- 使用梯度下降算法建立的模型远不如使用最小二乘法拟合得到的模型。
- 此模型的建立需要严格的步长、初始的参数值。
- 模型的问题可能出在数据——数据的问题可能是量较少,也可能是数据的线性关系不明显、不适合线性模型的梯度下降拟合。
从损失函数与迭代次数的关系可以明显看到,模型的工作结果很差。
本文地址:https://blog.csdn.net/weixin_43628432/article/details/109900130