Logistic迴歸與最大熵模型 優化算法

Logistic迴歸與最大熵模型-理論推導中提到了4個優化算法:分別是:

  1. 梯度降低算法
  2. 擬牛頓法(牛頓法)
  3. 通用迭代尺度法(GIS: Generalized Iterative Scaling)。
  4. 改進的迭代尺度法(IIS: Improved Iterative Scaling)。

logistics和最大熵模型的表達式和目標函數爲:

logistics模型
  • 表達式
\begin{align}
h_w(x_i) =\frac{e^{w·x_i}} {1+e^{w·x_i}}\tag{1.1}
\end{align}
  • 目標函數
\begin{align}
J(w) = \underset{w}{max}\ log L(w) =&\sum_{i=1}^{N} [y_i(w·x) - log(1+exp(w·x))]\tag{1.2}
\end{align}
最大熵模型
  • 表達式
\begin{align}
p_w(y|x) =& \frac{exp (\sum_{i=1}^{n} w_i f_i(x,y))} {Z_w(x)} \tag{1.3}
\end{align}
  • 目標函數
\begin{align}
\underset{w}{max}\ \Psi(w)=& \sum_{i=1}^{n}w_i ·\sum_{x,y} \widetilde{P}(x,y)f_i(x,y) - logZ_w(x) ·( \sum_{x}\widetilde{P}(x)) \tag{1.4}
\end{align}

其中git

Z_w(x) = \sum_{y} exp (\sum_{i=1}^{n} w_i f_i(x,y))\tag{1.5}

大前提

對於數據集T=\{(x_1,y_1),...,(x_N,y_N)\}y_i表明第i條數據的類標籤,x_i表明第i條數據的特徵,x_i^{(j)}表明第i條數據的j個特徵。github

假定目標函數f爲凸函數,且兩階連續可微,函數的最小值爲x^*算法


1.梯度降低算法

1.1 梯度

梯度在數學上的定義是:梯度的方向是變化速度最快的方向。 這樣的意義在於,沿着梯度的方向,更加容易找到函數的最大值;若相反,梯度減小也最快,更容易找到最小值。bash

1.2 應用

在logistics 模型中,計算目標函數對每一個特徵的權重的偏導數。dom

\begin{align}
\frac{\partial{J(w)}}{\partial{w^{(j)}}} =& \sum_{i=1}^{N} [y_i·x_i^{(j)} - h_w(x_i)·x_i^{(j)}]
\end{align}

則權重的更新爲:ide

\begin{align}
J(w) =J(w)+\alpha \frac{\partial{J(w)}}{\partial w^{(j)}}
\end{align}

算法流程-《梯度降低法、牛頓法和擬牛頓法》

1.3 不足

每一步走的距離在極值點附近很是重要,若是走的步子過大,容易在極值點附近震盪而沒法收斂。函數

解決辦法:將\alpha設定爲隨着迭代次數而不斷減少的變量,可是也不能徹底減爲零。學習

1.4 各類梯度降低

1.4.1 批量梯度降低法(Batch Gradient Descent) 批量梯度降低法,是梯度降低法最經常使用的形式,具體作法也就是在更新參數時使用全部的樣原本進行更新。 1.4.2 隨機梯度降低法(Stochastic Gradient Descent) 隨機梯度降低法,其實和批量梯度降低法原理相似,區別在與求梯度時沒有用全部的樣本的數據,而是僅僅選取一個樣原本求梯度。 隨機梯度降低法,和批量梯度降低法是兩個極端,一個採用全部數據來梯度降低,一個用一個樣原本梯度降低。天然各自的優缺點都很是突出。對於訓練速度來講,隨機梯度降低法因爲每次僅僅採用一個樣原本迭代,訓練速度很快,而批量梯度降低法在樣本量很大的時候,訓練速度不能讓人滿意。對於準確度來講,隨機梯度降低法用於僅僅用一個樣本決定梯度方向,致使解頗有可能不是最優。對於收斂速度來講,因爲隨機梯度降低法一次迭代一個樣本,致使迭代方向變化很大,不能很快的收斂到局部最優解。 1.4.3 小批量梯度降低法(Mini-batch Gradient Descent) 小批量梯度降低法是批量梯度降低法和隨機梯度降低法的折衷,也就是對於m個樣本,咱們採用x個樣原本迭代,1<x<m,通常x=16,32,64...,固然根據樣本的數據,能夠調整這個值。優化

1.5 代碼實現

#==============梯度上升優化算法=======================#
    def _batchGradientAscent(self, nums, lr):
        ''' 梯度上升優化算法 ------ :param nums: <np.ndarray>迭代次數 :param lr: <np.ndarray>學習率 :return: '''
        for k in range(nums):
            print('%d th iterations' % k)
            output = self.predict(self.input_vecs)
            delta = lr * (self.labels - output.T)
            delta_weight = np.dot(self.input_vecs.T, delta)
            self.weight += delta_weight.T

    # ==============隨機梯度上升優化算法=======================#
    def _StochasticGradientAscent0(self, lr):
        ''' 隨機梯度上升優化算法 ------ :param lr: <np.ndarray>學習率 :return: '''
        for inum in range(self.n_nums):
            output = self.predict(self.input_vecs[inum])
            delta = lr * (self.labels[inum] - output.T)
            delta_weight = self.input_vecs[inum] * delta
            self.weight += delta_weight.T

    # ==============隨機梯度上升優化算法=======================#
    def _StochasticGradientAscent1(self, nums):
        ''' 隨機梯度上升優化算法 ------ :param nums: <np.ndarray>迭代次數 :return: '''
        for iteration in range(nums):
            for inum in range(self.n_nums):
                data_index = [_ for _ in range(self.n_nums)]
                lr = 4 / (iteration + inum + 1) + 0.01
                rand_index = int(random.uniform(0, self.n_nums))
                output = self.predict(self.input_vecs[rand_index])
                delta = lr * (self.labels[rand_index] - output.T)
                delta_weight = self.input_vecs[rand_index] * delta
                self.weight += delta_weight.T
                del(data_index[rand_index])

    # ==============小批量梯度上升優化算法=======================#
    def _MiniBatchGradientAscent(self, nums, lr, batch_size=16):
        ''' 小批量梯度上升優化算法 ------ :param nums: <np.ndarray>迭代次數 :param lr: <np.ndarray>學習率 :param batch_size: <np.ndarray>批學習大小 :return: '''
        for iteration in range(nums):
            for ibatch in range(1, self.n_nums // batch_size):
                start_index = (ibatch-1) * batch_size
                end_index = ibatch * batch_size

                mini_train_data = self.input_vecs[start_index: end_index, ]
                mini_label = self.labels[start_index: end_index, ]

                output = self.predict(mini_train_data)
                delta = lr * (mini_label - output.T)
                delta_weight = np.dot(mini_train_data.T, delta)
                self.weight += delta_weight.T

    def train(self, nums, optimization='gradAscent', lr=0.001):
        ''' 訓練logistics模型 :param nums: 迭代次數 :param input_vecs: 訓練樣本的特徵值 :return: '''
        if optimization == 'gradAscent':
            self._batchGradientAscent(nums, lr)
        elif optimization == 'SGA0':
            self._StochasticGradientAscent0(lr)
        elif optimization == 'SGA1':
            self._StochasticGradientAscent1(nums)
        elif optimization == 'MGA':
            self._MiniBatchGradientAscent(nums, lr, batch_size=16)
複製代碼

2. 牛頓法

2.1 基本思想(先考慮單值的狀況)

利用牛頓法判斷函數的解。設在x_k爲當前極小值的估計點,由泰勒公式可知ui

\begin{align}
\psi(x) = f(x_k)+f'(x_k)(x-x_k)+\frac{1}{2}f''(x_k)(x-x_k)^2\tag{2.2}
\end{align}

\psi(x)=0,若x_k不知足條件,則迭代式可爲

\begin{align}
x_{k+1}=x_k-\frac{f'(x_k)}{f''(x_k)}
\end{align}

此時可認定爲f(x_{k+1})f(x_k)更接近與0,當f(x^*)=0的時候收斂。

2.1 基本思想(矩陣的狀況)

\begin{align}
\psi(x) = f(x_k)+\bigtriangledown f(x_k)(x-x_k)+\frac{1}{2}\bigtriangledown^2f(x_k)(x-x_k)^2\tag{2.2}
\end{align}

若要\psi(x)有極值點,則須要\bigtriangledown \psi(x)=0,故有

\bigtriangledown f(x_k) + \bigtriangledown^2 f(x_k)(x-x_k) = 0 \tag{2.3}

當矩陣H_k非奇異矩陣時,有

x_{k+1}=x_k + (\bigtriangledown^2 f(x_k))^{-1}·\bigtriangledown f(x_k) = 0 \tag{2.3}

image.png


3. 擬牛頓法

牛頓法與擬牛頓法學習筆記(二)擬牛頓條件

牛頓法與擬牛頓法學習筆記(三)DFP 算法


4. 迭代尺度法(最大熵模型)完整代碼

參考文獻

相關文章
相關標籤/搜索