机器学习 - 线性回归梯度下降推导

样本 x 有 m 个属性
多元线性回归

  • 线性回归模型函数
    \begin{align} y & = w_0x_0 + w_1x_1 + \dots + w_mx_m \\ & = \sum_{i = 0}^mw_ix_i \\ & = \mathbf{w}^T\mathbf{x} \end{align}
  • 模型参数
    \mathbf{w}^T = \begin{bmatrix} w_0 & \dots & w_m \end{bmatrix}_{1 \times(m+1)}
  • 属性(特征值)列表
    \mathbf{x} = \begin{bmatrix} x_0 \\ \vdots \\ x_m \end{bmatrix}_{(m+1) \times 1}
    其中:
    x_0 = 1是线性回归的截距的权重,恒定为1
  • 代价函数
    \mathbf{J}(\mathbf{w}) = \frac{1}{2}\sum_{i = 1}^{n}(y^{(i)} - \hat{y}^{(i)})^2
    其中:
    \mathbf{J}(\mathbf{w})表示\mathbf{J}是关于参数\mathbf{w}的函数
    n 表示一共有n个样本数据
    y^{(i)} 为第i个样本对应的真实值
    \hat{y}^{(i)} 为第i个样本通过预测函数 \hat{y} = \mathbf{w}^T\mathbf{x}计算得到的预测值
    \frac{1}{2}是为了推导方便而添加的常量

梯度下降法

  • 求当前\mathbf{w}的梯度需要求得\mathbf{w}w_j(j\in[0, m])的偏导数
    \begin{align} \frac{\partial{\mathbf{J(\mathbf{w})}}}{\partial{w_j}} & = \frac{1}{2}\sum_{i = 1}^{n}\frac{\partial}{\partial{w_j}}[(y^{(i)} - \hat{y}^{(i)})^2] \\ & = \sum_{i = 1}^{n}(y^{(i)} - \hat{y}^{(i)})\frac{\partial}{\partial{w_j}}(y^{(i)} - \hat{y}^{(i)}) \\ & = \sum_{i = 1}^{n}(y^{(i)} - \hat{y}^{(i)})(-x_j^{(i)}) \\ & = -\sum_{i = 0}^{n}x_j^{(i)}(y^{(i)} - \hat{y}^{(i)}) \end{align}
    其中:
    x_j^{(i)} 表示第i个样本的第j个特征值
  • 由于我们的目的是让代价函数\mathbf{J}(\mathbf{w})取得极小值,于是需要让参数\mathbf{w}往负梯度的方向更新,从而让代价函数\mathbf{J}(\mathbf{w})取值变小
  • 参数每次更新需要一个正数步长\eta(可以为0.001、0.0001)来确定每次参数更新的速度
  • 参数的负增量:\begin{align} \Delta\mathbf{w}_j & = -\eta\frac{\partial\mathbf{J}(\mathbf{w})}{\partial{w_j}} \\ & = \eta\sum_{i = 0}^{n}x_j^{(i)}(y^{(i)} - \hat{y}^{(i)}) \\ \end{align}

梯度下降法过程:
1.初始化权重\mathbf{w}
2.使用代价函数计算代价
3.计算梯度,使用\mathbf{w} +=\Delta\mathbf{w}更新权重\mathbf{w}
4.若代价值小于某一阈值(或训练某个次数)则停止训练
5.得到权重\mathbf{w}

以下是使用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()

推导过程:
\begin{align} \Delta\mathbf{w}_0 & = \eta\sum_{i = 0}^nx_0^{(i)}(y^{(i)} - \hat{y}^{(i)}) \\ & = \eta\sum_{i = 0}^n(y^{(i)} - \hat{y}^{(i)}) \\ \end{align}

关于这行代码

# 更新第 1...m个权重
self.w_[1:] += self.eta * X.T.dot(errors)

为什么是X的转置点乘残差值?以下是推导过程

由参数的负增量:\begin{align} \Delta\mathbf{w}_j & = -\eta\frac{\partial\mathbf{J}(\mathbf{w})}{\partial{w_j}} \\ & = \eta\sum_{i = 0}^{n}x_j^{(i)}(y^{(i)} - \hat{y}^{(i)}) \\ \end{align}

注意:代码中\Delta\mathbf{w}不包括\Delta\mathbf{w}_0\Delta\mathbf{w}_0另外计算
\Delta\mathbf{w} = \begin{bmatrix} \Delta\mathbf{w}_1 \\ \vdots \\ \Delta\mathbf{w}_m \\ \end{bmatrix} = \eta \begin{bmatrix} \sum_{i = 0}^{n}x_1^{(i)}(y^{(i)} - \hat{y}^{(i)}) \\ \vdots \\ \sum_{i = 0}^{n}x_m^{(i)}(y^{(i)} - \hat{y}^{(i)}) \\ \end{bmatrix}
= \eta \begin{bmatrix} \sum_{i = 0}^{n}x_1^{(i)}(y^{(i)} - \hat{y}^{(i)}) \\ \vdots \\ \sum_{i = 0}^{n}x_m^{(i)}(y^{(i)} - \hat{y}^{(i)}) \\ \end{bmatrix}
=\eta \begin{bmatrix} x_1^{(0)}(y^{(0)} - \hat{y}^{(0)}) + \dots + x_1^{(n)}(y^{(n)} - \hat{y}^{(n)})\\ \vdots \\ x_m^{(0)}(y^{(0)} - \hat{y}^{(0)}) + \dots + x_m^{(n)}(y^{(n)} - \hat{y}^{(n)})\\ \end{bmatrix}_{m\times1}
= \eta \begin{bmatrix} x_1^{(0)} \dots x_1^{(n)} \\ \vdots \\ x_m^{(0)} \dots x_m^{(n)} \\ \end{bmatrix}_{m\times(n+1)} \begin{bmatrix} (y^{(0)} - \hat{y}^{(0)}) \\ \vdots \\ (y^{(n)} - \hat{y}^{(n)}) \\ \end{bmatrix}_{(n+1)\times1}
= \eta \begin{bmatrix} x_1^{(0)} \dots x_m^{(0)} \\ \vdots \\ x_1^{(n)} \dots x_m^{(n)} \\ \end{bmatrix}_{(n+1)\times{m}}^T \begin{bmatrix} (y^{(0)} - \hat{y}^{(0)}) \\ \vdots \\ (y^{(n)} - \hat{y}^{(n)}) \\ \end{bmatrix}_{(n+1)\times1}
实际上就是代码中

= 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)
随机数据.png

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')
回归线.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容