样本 x 有 m 个属性
多元线性回归
- 线性回归模型函数
- 模型参数
- 属性(特征值)列表
其中:
是线性回归的截距的权重,恒定为1 - 代价函数
其中:
表示是关于参数的函数
表示一共有个样本数据
为第个样本对应的真实值
为第个样本通过预测函数 计算得到的预测值
是为了推导方便而添加的常量
梯度下降法
- 求当前的梯度需要求得在的偏导数
其中:
表示第个样本的第个特征值 - 由于我们的目的是让代价函数取得极小值,于是需要让参数往负梯度的方向更新,从而让代价函数取值变小
- 参数每次更新需要一个正数步长(可以为0.001、0.0001)来确定每次参数更新的速度
- 参数的负增量:
梯度下降法过程:
1.初始化权重
2.使用代价函数计算代价
3.计算梯度,使用更新权重
4.若代价值小于某一阈值(或训练某个次数)则停止训练
5.得到权重
以下是使用Python实现线性回归的类
import numpy as np
class LinearRegressionLM(object):
# 初始化(
# eta -> 初始化学习率
# n_iter -> 训练次数
def __init__(self, eta=0.001, n_iter=20):
self.eta = eta
self.n_iter = n_iter
# 训练
# X -> 训练的所有样本(n+1)xm
# y -> 训练样本的真实值(n+1)x1
def fit(self, X, y):
# 初始化权重w_
self.w_ = np.zeros(1 + X.shape[1])
# 初始化代价
self.cost_ = []
for i in range(self.n_iter):
# 得到预测值
output = self.net_input(X)
# 得到残差值
errors = (y - output)
# 更新第 0 个权重(这个比较特殊)
self.w_[0] += self.eta * errors.sum()
# 更新第 1...m个权重
self.w_[1:] += self.eta * X.T.dot(errors)
# 计算代价值
cost = (errors**2).sum() / 2.0
# 存储代价值
self.cost_.append(cost)
return self
# 使用现有的权重w_得到预测值
def net_input(self, X):
return np.dot(X, self.w_[1:]) + self.w_[0]
# 预测
def predict(self, X):
return self.net_input(X)
注解:
# 更新第 0 个权重(这个比较特殊)
self.w_[0] += self.eta * errors.sum()
推导过程:
关于这行代码
# 更新第 1...m个权重
self.w_[1:] += self.eta * X.T.dot(errors)
为什么是X的转置点乘残差值?以下是推导过程
由参数的负增量:
注意:代码中不包括,另外计算
实际上就是代码中
= self.eta * X.T.dot(errors)
******** 以下是代码实践 ********
1.初始化随机线性回归数据(每个样本只取一个属性)
from sklearn.datasets import make_regression
import matplotlib.pyplot as plt
X, y, eof = make_regression(n_samples=1000, n_features=1, noise=40, coef=True, random_state=14)
plt.scatter(X, y, c='r', s=3)
2.初始化线性回归的类,开始训练
linearRegressionLM = LinearRegressionLM()
linearRegressionLM.fit(X, y)
print('训练参数 = ' , linearRegressionLM.w_)
训练参数 = [ 0.70041376 76.66596196]
3.绘制回归线
x_line = np.linspace(-3, 3, 20)
print(x_line.shape)
print(type(x_line))
x_line_ones = np.ones((x_line.shape[0], 1))
# 添加每个样本的 x_0 = 1
x_line_all = np.column_stack((x_line_ones, x_line))
y_line = np.dot(x_line_all, linearRegressionLM.w_)
plt.scatter(X, y, c='r', s=3)
plt.plot(x_line, y_line, color='blue')