機器學習“傻瓜式”理解(6)梯度下降法(第一部分)

基礎理解

看到梯度下降算法,首先我們應該去了解幾個問題,這是什麼?幹什麼用的?爲什麼會產生這個概念或者事物?實現的具體思路是什麼?爲什麼這麼實現,其背後的原理是什麼?
首先我們應該明確的一點是,所謂的梯度下降算法並不是一個機器學習算法,而是一個基於搜索的最優化算法。我們在上一節所講到的線性迴歸算法的目標是最優化一個損失函數,這也是梯度下降算法的思路。而梯度上升算法是最大化一個效用函數。
其次我們需要明確,爲什麼會產生這種算法呢?從上一節我們可以看出來,我們可以通過正規方程解的方式求解出theta的值,但是很多數情況下theta的值是沒法求出其具體的公式的,因此梯度下降算法應允而生。
實現的具體思路及邏輯:
要實現梯度下降,要就是實現最小化一個損失函數,需要用到導數,參數爲theta,對theta進行求解導數,需要不斷的遞減theta然後進行求解,此時便用到了學習速率。
在這裏插入圖片描述
而且學習速率取值的大小也十分的重要。
如圖所示:
在這裏插入圖片描述

梯度下降算法在線性迴歸中的使用:

公式推導:
在這裏插入圖片描述

代碼封裝:

    def fit_gd(self,X_train,y_train,eta=0.01,n_iters=1e4):
        '''check'''
        assert X_train.shape[0] == y_train.shape[0],\
                "the size must be valid"

        '''No.1 get J'''
        def J(X_b,theta,y):
            try:
                return np.sum(y - X_b.dot(theta)) / len(y)
            except:
                return float('inf')

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

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

            while cur_iters < n_iters:
                gradient = DJ(X_b,y,theta)
                last_theta = theta
                theta = theta - gradient*n_iters
                if(abs(J(X_b,y,theta) - J(X_b,y,last_theta)) < epsilon):
                    break

                cur_iters += 1

        X_b = np.hstack([np.ones((len(X_train),1)),X_train])
        initial_theta = np.zeros(X_b.shape[1])
        self._theta  = gradient_decent(X_b,y_train,initial_theta,eta,n_iters)
        self.coef_ = self._theta[1:]
        self.interception_ = self._theta[0]
        return self

隨機梯度下降法

隨機梯度下降法和批量梯度下降法在計算theta時是兩種不同的方式,兩者互有千秋,將兩者正式融合的是小批量梯度下降法(代碼會在GitHub中開源,博客不會詳細介紹)。
現在介紹兩者區別:
批量梯度下降法(Batch Gradient Descent):是梯度下降的最原始的一種方式,使用特點和思路是使用全部的樣本進行更新theta,這樣的做法效率很低,訓練過程慢。
隨機梯度下降法:和BGD不同,隨機梯度下降法在更新theta時使用的是隨機的一個樣本進行更新,例如如果存在10萬條數據,我們使用幾萬條數據便將theta更新到最優解了,大大提升了訓練模型的效率,但是準確率較低。(通常情況下,我們願意使用犧牲模型一定的精度來換取訓練模型所用的時間)。
另外,實現隨機梯度下降時所用的學習速率需要注意:
我們每次都是採取的隨機的一個樣本,如果採用固定的學習速率的話,如果我們接近找到的最佳的theta,就會慢慢的跳出最優位置,解決方案是需要讓學習速率根據運行的次數越來越小。
模擬退火的思想,我們將學習速率定義爲下面的函數:
在這裏插入圖片描述
經驗上比較適合的值:a = 5、b = 50;
封裝隨機梯度下降算法

    def fit_sgd(self,X_train,y_train,eta=0.01,n_iters=5,t0=5,t1=50):
        '''check'''
        assert X_train.shape[0] == y_train.shape[0],\
                "the size must be valid"
        assert n_iters>=1,\
                "the valud must be >= 1"

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

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

            for cur_iters in range(n_iters):
                indexes = np.random.permutation(m)
                X_b_new = X_b[indexes]
                y_train_new = y_train[indexes]
                for i in range(m):
                    gradient = dJ_sgd(theta,X_b_new[i],y_train_new[i])
                    theta = theta - eta * gradient

            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, eta, n_iters)
        self.coef_ = self._theta[1:]
        self.interception_ = self._theta[0]
        return self

後一小節將介紹小批量梯度下降算法和對梯度下降算法的更多思考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章