国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

機(jī)器學(xué)習(xí)之梯度下降法與線性回歸

cod7ce / 2026人閱讀

摘要:表示學(xué)習(xí)率,是梯度下降法的一個(gè)超參數(shù),其取值影響最優(yōu)解的速度。因此在使用梯度下降法之前,最好進(jìn)行數(shù)據(jù)歸一化。同時(shí)在隨機(jī)梯度下降法中學(xué)習(xí)率的取值是逐漸遞減的,為了防止固定取值的學(xué)習(xí)率使得梯度下降到達(dá)最優(yōu)解附近時(shí)繼續(xù)跳出這個(gè)范圍。

梯度下降法不是一個(gè)機(jī)器學(xué)習(xí)算法,而是一種基于搜索的最優(yōu)化方法,用于最小化一個(gè)效用函數(shù)。

簡(jiǎn)單理解梯度下降法

假設(shè)存在一個(gè)只有一個(gè)參數(shù) $ heta$ 的損失函數(shù) $J$,想找到最小極值處的 $ heta$,如圖所示:

借助于損失函數(shù) $J$ 在 $ heta$ 處的切線,可以直觀的反映出損失函數(shù) $J$ 在 $ heta$ 處的導(dǎo)數(shù)大小;導(dǎo)數(shù)的大小代表著 $ heta$ 變化時(shí) $J$ 相應(yīng)的變化。

同時(shí)導(dǎo)數(shù)也可以代表 $J$ 增大的方向,如果將導(dǎo)數(shù)與 $-eta$ 相乘,即 $-etafrac{dJ}{d heta}$ 代表了 $J$ 減小的方向。

$eta$ 表示學(xué)習(xí)率,是梯度下降法的一個(gè)超參數(shù),其取值影響最優(yōu)解的速度。太小會(huì)減慢收斂學(xué)習(xí)速度,太大可能導(dǎo)致不收斂。

如果 $J$ 中存在多處導(dǎo)數(shù)為零的情況,即存在一個(gè)全局最優(yōu)解和多個(gè)局部最優(yōu)解,此時(shí)可以多次使用梯度下降法,每次隨機(jī)化一個(gè)初始點(diǎn)。

對(duì)于有多個(gè) $ heta$ 的 $J$ 類似,即找出全局最優(yōu)解處的這些 $ heta$ 的值。

模擬梯度下降法

首先,模擬一個(gè)損失曲線 $J$:

import numpy as np

plot_x = np.linspace(-1, 6, 141)
plot_y = (plot_x - 2.5) ** 2 - 1

作圖表示如下:

定義函數(shù) dJ() 用于求 $J$ 在 $ heta$ 處的導(dǎo)數(shù):

def dJ(theta):
    return 2 * (theta - 2.5)

函數(shù) J() 用于求 $J$ 在 $ heta$ 處的大?。?/p>

def J(theta):
    return (theta - 2.5) ** 2 - 1

接著使用梯度下降法,首先給 $ heta$ 賦一個(gè)初值 0 及學(xué)習(xí)率 $eta$ 為 0.1,接著在循環(huán)里進(jìn)行多次梯度下降。每次循環(huán)都要求得 $J$ 在 $ heta$ 處的導(dǎo)數(shù)值 $gradient$,并且 $ heta$ 向?qū)?shù)的負(fù)方向移動(dòng),即:$ heta= heta-eta*gradient$。

由于計(jì)算機(jī)計(jì)算浮點(diǎn)數(shù)存在誤差,對(duì)于求得的 $ heta$ 可能不能剛好等于 0,因此設(shè)定一個(gè)精度值(epsilon = 1e-8),如果新的 $ heta$ 對(duì)應(yīng)的損失函數(shù)的值與上一次 $ heta$ 對(duì)應(yīng)的損失函數(shù)的值的差值滿足精度要求,就表示找到了要找的 $ heta$。程序如下:

theta = 0.0
eta = 0.1
epsilon = 1e-8

while True:
    gradient = dJ(theta)
    last_theta = theta
    
    theta = theta - eta * gradient
    if (abs(J(theta) - J(last_theta)) < epsilon):
        break

運(yùn)行程序求得的 $ heta$ 為:2.499891109642585。

對(duì)于 $ heta$ 的取值變化,可以用圖片表示,如下(紅色的點(diǎn)):

對(duì)于學(xué)習(xí)率 $eta$,這里取值 0.1 是沒有問題的,但如果取值 1.1 程序運(yùn)行就會(huì)報(bào)錯(cuò):

OverflowError                             Traceback (most recent call last)
 in 
      8 
      9     theta = theta - eta * gradient
---> 10     if (abs(J(theta) - J(last_theta)) < epsilon):
     11         break
     12 

 in J(theta)
      1 def J(theta):
----> 2     return (theta - 2.5) ** 2 - 1

OverflowError: (34, "Result too large")

這是因?yàn)閷W(xué)習(xí)率過大會(huì)導(dǎo)致 J(theta) 越來越大。為了使程序不會(huì)報(bào)錯(cuò),修改 J() 方法:

def J(theta):
    try:
        return (theta - 2.5) ** 2 - 1
    except:
        return float("inf")

注意,當(dāng)無窮減無窮時(shí),結(jié)果時(shí) nan 而不是 0,此時(shí) if (abs(J(theta) - J(last_theta)) < epsilon) 將永遠(yuǎn)無法觸發(fā)而使得程序進(jìn)入死循環(huán)。為了解決這個(gè)問題,增加一個(gè)新的超參數(shù) n_iters,表示能夠執(zhí)行循環(huán)的最大次數(shù)。

比如使 n_iters=10,$ heta$ 取值變化如圖:

最后,把梯度下降法封裝到方法中:

def gradient_descent(initial_theta, eta, n_iters=1e4, epsilon=1e-8):
    theta = initial_theta
    i_ters = 0

    while i_ters < n_iters:
        gradient = dJ(theta)
        last_theta = theta

        theta = theta - eta * gradient
        if (abs(J(theta) - J(last_theta)) < epsilon):
            break
        
        i_ters += 1
    
    return theta
多元線性回歸中的梯度下降法 原理

多元線性回歸的損失函數(shù)為:

$$ J=sum_{i=1}^{m}(y^{(i)} - hat{y}^{(i)})^2 $$

其中:$hat{y}^{(i)} = heta_{0} + heta_{1}X_{1}^{(i)} + heta_{2}X_{2}^{(i)} + ... + heta_{n}X_{n}^{(i)}$ 。

對(duì) $J$ 求導(dǎo)為:

$$ abla J=(frac{partial J}{partial heta_0},frac{partial J}{partial heta_1},...,frac{partial J}{partial heta_n}) $$

其中:$frac{partial J}{partial heta_i}$ 為偏導(dǎo)數(shù),與導(dǎo)數(shù)的求法一樣。

對(duì) $ abla J$ 進(jìn)一步計(jì)算:

$$ abla J( heta) = egin{pmatrix} frac{partial J}{partial heta_0} frac{partial J}{partial heta_1} frac{partial J}{partial heta_2} cdots frac{partial J}{partial heta_n} end{pmatrix} = egin{pmatrix} sum_{i=1}^{m}2(y^{(i)} - X_b^{(i)} heta)·(-1) sum_{i=1}^{m}2(y^{(i)} - X_b^{(i)} heta)·(-X_1^{(i)}) sum_{i=1}^{m}2(y^{(i)} - X_b^{(i)} heta)·(-X_2^{(i)}) cdots sum_{i=1}^{m}2(y^{(i)} - X_b^{(i)} heta)·(-X_n^{(i)}) end{pmatrix} = 2·egin{pmatrix} sum_{i=1}^{m}(X_b^{(i)} heta - y^{(i)}) sum_{i=1}^{m}(X_b^{(i)} heta - y^{(i)})·X_1^{(i)} sum_{i=1}^{m}(X_b^{(i)} heta - y^{(i)})·X_2^{(i)} cdots sum_{i=1}^{m}(X_b^{(i)} heta - y^{(i)})·X_n^{(i)} end{pmatrix} $$

其中:$X_b = egin{pmatrix} 1 & X_1^{(1)} & X_2^{(1)} & cdots & X_n^{(1)} 1 & X_1^{(2)} & X_2^{(2)} & cdots & X_n^{(2)} cdots & & & & cdots 1 & X_1^{(m)} & X_2^{(m)} & cdots & X_n^{(m)} end{pmatrix}$

這個(gè)結(jié)果是與樣本數(shù)量 m 相關(guān)的,為了使結(jié)果與 m 無關(guān),對(duì)這個(gè)梯度除以 m,即:

$$ abla J( heta) = frac{2}{m}·egin{pmatrix} sum_{i=1}^{m}(X_b^{(i)} heta - y^{(i)}) sum_{i=1}^{m}(X_b^{(i)} heta - y^{(i)})·X_1^{(i)} sum_{i=1}^{m}(X_b^{(i)} heta - y^{(i)})·X_2^{(i)} cdots sum_{i=1}^{m}(X_b^{(i)} heta - y^{(i)})·X_n^{(i)} end{pmatrix} $$

此時(shí),目標(biāo)函數(shù)就成了使 $frac{1}{m}sum_{i=1}^{m}(y^{(i)} - hat{y}^{(i)})^2$ 盡可能小,即均方誤差盡可能小:

$$ J( heta) = MSE(y, hat{y}) $$

使用梯度下降法訓(xùn)練模型

首先模擬訓(xùn)練數(shù)據(jù)集:

import numpy as np

x = np.random.random(size=100)
y = x * 3.0 + 4.0 + np.random.normal(size=100)

X = x.reshape(-1, 1)

定義函數(shù) J() 計(jì)算損失函數(shù)的值:

def J(theta, X_b, y):
    try:
        return np.sum((y - X_b.dot(theta)) ** 2) / len(X_b)
    except:
        return float("inf")

函數(shù) dJ() 對(duì) $ heta$ 求導(dǎo)數(shù):

def dJ(theta, X_b, y):
    res = np.empty(len(theta))
    res[0] = np.sum(X_b.dot(theta) - y)
    for i in range(1, len(theta)):
        res[i] = (X_b.dot(theta) - y).dot(X_b[:, i])
    return res * 2 / len(X_b)

注意:對(duì) $J$ 求導(dǎo)更好的方式是進(jìn)行向量化處理,即 $ abla J( heta) = frac{2}{m}·X_b^T·(X_b heta-y)$,dJ() 改寫為:

def dJ(theta, X_b, y):
    return X_b.T.dot(X_b.dot(theta) - y) * 2 / len(X_b)

梯度下降的過程為:

def gradient_descent(X_b, y, initial_theta, eta, n_iters=1e4, epsilon=1e-8):
    theta = initial_theta
    i_ters = 0

    while i_ters < n_iters:
        gradient = dJ(theta, X_b, y)
        last_theta = theta

        theta = theta - eta * gradient
        if (abs(J(theta, X_b, y) - J(last_theta, X_b, y)) < epsilon):
            break
        
        i_ters += 1
        
    return theta

執(zhí)行程序找出最優(yōu)的 $ heta$ 如下:

X_b = np.hstack([np.ones((len(X), 1)), X])
initial_theta = np.zeros(X_b.shape[1])
eta = 0.01

theta = gradient_descent(X_b, y, initial_theta, eta)

$ heta$ 結(jié)果為:

array([4.0269033, 3.0043078])

將梯度下降法封裝到線性回歸算法的模型訓(xùn)練方法 fit_gd() 中:

class LinearRegression:
    # other codes here
    
    def fit_gd(self, X_train, y_train, eta=0.01, n_iters=1e4):
        def J(theta, X_b, y):
            try:
                return np.sum((y - X_b.dot(theta)) ** 2) / len(X_b)
            except:
                return float("inf")

        def dJ(theta, X_b, y):
            return X_b.T.dot(X_b.dot(theta) - y) * 2 /len(X_b)

        def gradient_descent(X_b, y, initial_theta, eta, n_iters=n_iters, epsilon=1e-8):
            theta = initial_theta
            i_ters = 0

            while i_ters < n_iters:
                gradient = dJ(theta, X_b, y)
                last_theta = theta

                theta = theta - eta * gradient
                
                if (abs(J(theta, X_b, y) - J(last_theta, X_b, y)) < epsilon):
                    break
                
                i_ters += 1
                
            return theta

        X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
        initial_theta = np.zeros(X_b.shape[1])

        self._theta = gradient_descent(X_b, y_train, initial_theta, eta)
        self.interception_ = self._theta[0]
        self.coef_ = self._theta[1:]

        return self
注意:

在真實(shí)的數(shù)據(jù)集 (X, y) 中,X 整體不在一個(gè)規(guī)模上會(huì)影響梯度的結(jié)果,而梯度的結(jié)果再乘以 $eta$ 得到步長就太大或太小,從而導(dǎo)致訓(xùn)練出的模型可能很差。因此在使用梯度下降法之前,最好進(jìn)行數(shù)據(jù)歸一化。

隨機(jī)梯度下降法

$ abla J( heta) = frac{2}{m}·egin{pmatrix} sum_{i=1}^{m}(X_b^{(i)} heta - y^{(i)}) sum_{i=1}^{m}(X_b^{(i)} heta - y^{(i)})·X_1^{(i)} sum_{i=1}^{m}(X_b^{(i)} heta - y^{(i)})·X_2^{(i)} cdots sum_{i=1}^{m}(X_b^{(i)} heta - y^{(i)})·X_n^{(i)} end{pmatrix}$ 中每一項(xiàng)都要對(duì)所有樣本進(jìn)行計(jì)算,因此這種梯度下降法稱為批量梯度下降法(Batch Gradient Descent)。如果 m 非常大,使用批量梯度下降法計(jì)算梯度的計(jì)算量就會(huì)非常大。

改進(jìn)的方法是對(duì)每一項(xiàng)計(jì)算時(shí)不再計(jì)算所有的樣本而是選取其中一個(gè)樣本進(jìn)行計(jì)算,即:

$$ 2·egin{pmatrix} (X_b^{(i)} heta - y^{(i)})·X_0^{(i)} (X_b^{(i)} heta - y^{(i)})·X_1^{(i)} (X_b^{(i)} heta - y^{(i)})·X_2^{(i)} cdots (X_b^{(i)} heta - y^{(i)})·X_n^{(i)} end{pmatrix} = 2·(X_b^{(i)})^T·(X_b^{(i)} heta-y^{(i)}) $$

這樣的方式就是隨機(jī)梯度下降法(Stochastic Gradient Descent),此時(shí)搜索路徑如圖所示:

隨機(jī)梯度下降法不能保證梯度下降的方向就是損失函數(shù)減小最快的方向(有時(shí)會(huì)是增大的方向),但整體上是會(huì)到達(dá)最小值附近的(滿足一定的精度)。

同時(shí)在隨機(jī)梯度下降法中學(xué)習(xí)率 $eta$ 的取值是逐漸遞減的,為了防止固定取值的學(xué)習(xí)率使得梯度下降到達(dá)最優(yōu)解附近時(shí)繼續(xù)跳出這個(gè)范圍。一個(gè)合理的取值方式為:

$$ eta = frac{t0}{i\_iter + t1} $$

其中:$t0、t1$ 為超參數(shù)。

定義函數(shù) dJ_sgd() 對(duì)應(yīng)批量梯度下降法中對(duì)損失函數(shù)求導(dǎo)的過程,此時(shí)傳入函數(shù)的就不再是所有樣本 $(X_b, y)$ 了,而是其中一個(gè)樣本 $(X_b^{(i)}, y^{(i)})$:

def dJ_sgd(theta, X_b_i, y_i):
    return X_b_i.T.dot(X_b_i.dot(theta) - y_i) * 2.

函數(shù) sgd() 中定義了一個(gè) learning_rate() 方法用來計(jì)算學(xué)習(xí)率,傳入?yún)?shù)為當(dāng)前迭代次數(shù)。

因?yàn)橐S機(jī)的選取樣本中的一個(gè),但又要將所有樣本看一遍,所以我們將這個(gè)樣本集打亂形成一個(gè)新的樣本集 $(X_{b,new}^{(i)}, y_{new}^{(i)})$,同時(shí)指定參數(shù) n_iters 表示將這個(gè)樣本集看幾遍:

def sgd(X_b, y, initial_theta, n_iters, t0, t1):

    def learning_rate(t):
        return t0 / (t + t1)

    theta = initial_theta
    m = len(X_b)

    for cur_iter in range(n_iters):
        indexes = np.random.permutation(m)
        X_b_new = X_b[indexes]
        y_new = y[indexes]

        for i in range(m):
            grandient = dJ_sgd(theta, X_b_new[i], y_new[i])
            theta = theta - learning_rate(cur_iter * m + i) * grandient

            return theta

將隨機(jī)梯度下降法封裝到線性回歸算法的模型訓(xùn)練方法 fit_sgd() 中:

class LinearRegression:
    # other codes here
    
    def fit_sgd(self, X_train, y_train, n_iters=5, t0=5, t1=50):
        def dJ_sgd(theta, X_b_i, y_i):
            return X_b_i.T.dot(X_b_i.dot(theta) - y_i) * 2.

        def sgd(X_b, y, initial_theta, n_iters, t0, t1):
            
            def learning_rate(t):
                return t0 / (t + t1)
            
            theta = initial_theta
            m = len(X_b)

            for cur_iter in range(n_iters):
                indexes = np.random.permutation(m)
                X_b_new = X_b[indexes]
                y_new = y[indexes]

                for i in range(m):
                    grandient = dJ_sgd(theta, X_b_new[i], y_new[i])
                    theta = theta - learning_rate(cur_iter * m + i) * grandient
                
            return theta

        X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
        initial_theta = np.zeros(X_b.shape[1])

        self._theta = sgd(X_b, y_train, initial_theta, n_iters, t0, t1)
        self.interception_ = self._theta[0]
        self.coef_ = self._theta[1:]

        return self

在 Scikit Learn 的 linear_model 模塊中提供了一個(gè)使用隨機(jī)梯度下降法的回歸算法 SGDRegressor:

from sklearn.linear_model import SGDRegressor
源碼地址

Github | ML-Algorithms-Action

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/45024.html

相關(guān)文章

  • 機(jī)器學(xué)習(xí)之邏輯回歸

    摘要:邏輯回歸將樣本特征和樣本發(fā)生的概率聯(lián)系起來,用于解決分類問題。因此可對(duì)二分類的分類方式為損失函數(shù)如果實(shí)際的分類為,越小時(shí),損失越大如果實(shí)際的分類為,越大時(shí),損失越大。對(duì)于有樣本的數(shù)據(jù)集,損失函數(shù)為其中。 邏輯回歸將樣本特征和樣本發(fā)生的概率聯(lián)系起來,用于解決分類問題。 Sigmoid 函數(shù) 在最簡(jiǎn)單的二分類中,邏輯回歸里樣本發(fā)生的概率的值域?yàn)?[0, 1],對(duì)于線性回歸 $hat{y} ...

    tain335 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

cod7ce

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<