1. 程式人生 > >【機器學習筆記04】隨機梯度下降

【機器學習筆記04】隨機梯度下降

梯度下降

梯度下降是一個尋找函式機值的方式,屬於最優化裡的基礎演算法,在低維度的情況下非常容易理解。 例如存在函式y=x2y=x^2存在導數dy=2x,若當前點在x=1點,設dx的步長為0.1。此時我們通過負梯度計算下一個x點xt+1=xt20.1=0.8x^{t+1}=x^t - 2 * 0.1=0.8,我們可以知道x=0.8比x=1更接近函式y=x2y=x^2的最小值。 在多維情況下理解為考慮更多下降的方向。

(隨機)梯度下降演算法

存線上性迴歸問題如下 f(x)=i=0mθixi=θTxf(x)=\sum_{i=0}^m\theta_ix_i=\theta^Tx

1 存在代價函式如下(歐式距離): J(θ)=1/2i=1m(fθ(xi)yi)2J(\theta)=1/2\sum_{i=1}^m(f_{\theta}(x_i)-y_i)^2 2 對代價函式求$\theta$的偏導數: J(θ)θ=(fθ(xi)yi)xj\dfrac{\partial J(\theta)}{\partial \theta}=(f_\theta(x_i)-y_i)x_j 3 根據代價函式求得的偏導數,更新引數θ\theta
θjt+1=θjtλJ(θ)θ\theta_j^{t+1}=\theta_j^t-\lambda\dfrac{\partial J(\theta)}{\partial \theta},其中λ\lambda是一個常量 4 迭代上述過程

備註:這裡要注意的是若屬於隨機梯度下降演算法,則其代價函式為: J(θ)=1/2(fθ(xi)yi)2J(\theta)=1/2(f_{\theta}(x_i)-y_i)^2,也就是說每個訓練樣本都會使得引數隨著負梯度方向下降,而不是像傳統的梯度下降一樣需要累加所有的樣本。

隨機梯度下降程式實現(純python)
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

def init_train_data():
    """
    初始化二元線性函式y = 2x + 3x的訓練資料
    """
    global x1arr
    global x2arr
    global yarr
    global LEN

    LEN = 500
    x1arr = np.random.rand(1,LEN)
    x2arr = np.random.rand(1,LEN)
    yarr = np.zeros(LEN)
    for i in range(0,LEN):
        yarr.data[i] = 2 * x1arr.data[0,i] + 3*x2arr.data[0,i] + np.random.rand()

def draw_train_data():
    """
    繪製訓練資料
    """
    fig = plt.figure()
    ax = Axes3D(fig)
    ax.set_xlabel('x1')
    ax.set_ylabel('x2')
    ax.set_zlabel('y')

    global x1arr
    global x2arr
    global yarr
    global weight

    #分佈雜湊點,點為紅色的三角形
    ax.scatter(x1arr[0], x2arr[0], yarr, c = 'r', marker = '^')

    x1 = np.arange(0, 1, 0.05)
    x2 = np.arange(0, 1, 0.05)
    x1, x2 = np.meshgrid(x1, x2)
    y = weight[0]*x1 + weight[1]*x2
    ax.plot_surface(x1, x2, y, rstride=1, cstride=1, cmap=plt.cm.coolwarm)  # 用取樣點(x,y,z)去構建曲面

    plt.show()

def do_linear_regression_with_sgd(iternum):
    """
    利用隨機梯度下降法進行訓練
    """
    #此時y = a1*x1 + a2*x2
    global x1arr
    global x2arr
    global yarr
    global weight

    weight = np.array([1.0,1.0])

    step = 0.01

    for t in range(1, iternum):

        # 取一個訓練樣本
        i = t % (LEN - 1)

        #對代價函式求相當於a1的偏導數,為(f(x)-y)*x1
        da1 = (weight[0]*x1arr[0,i] + weight[1]*x2arr[0,i] - yarr[i])*x1arr[0,i]
        da2 = (weight[0] * x1arr[0,i] + weight[1] * x2arr[0,i] - yarr[i]) * x2arr[0,i]

        #更新weight,注意這裡是減,為負梯度方向
        #最終weight更新值為[ 2.70433803  3.21959271]
        weight[0] -= step * da1
        weight[1] -= step * da2

    return

"""
說明:

隨機梯度下降程式碼實現,對應的筆記《03.隨機梯度下降》

作者:fredric

日期:2018-8-5

"""
if __name__ == '__main__':
    init_train_data()
    do_linear_regression_with_sgd(1000)
    draw_train_data()

在這裡插入圖片描述