【邏輯迴歸LR】算法原理 公式推導 python編程實現

學習筆記,TensorFlow實現源碼地址:

https://github.com/lsq960124/DeepLearning/blob/master/TensorFlow%20notes/TensorFlow%20basis03.ipynb

1.在二分類問題中,對於每個觀察樣本:

                             \large p(x_{i},y_{i})=p(y_{i}=1|x_{i})^{y_{i}}(1-p(y_{i}=1|x_{i}))^{1-y_{i}}

這個公式很好理解,拆分開來可以這樣表示:

                             \large p(x_{i},y_{i})=\left\{\begin{matrix} p(y_{i}=1|x_{i})& y_{i}=1\\ (1-p(y_{i}=1|x_{i})) &y_{i}=0\end{matrix}\right.

2.對於n個出現的樣本,樣本間相互獨立,則n個出現的概率爲每一個出現的概率的乘積。

                             \large L(w)=\prod p(y_{i}=1|x_{i})^{y_{i}}(1-p(y_{i}=1|x_{i}))^{1-y_{i}}

3.爲了滿足凸函數求最優解的思想,我們對L(w)取對數,並化簡:

                              \large L(w)=\prod p(y_{i}=1|x_{i})^{y_{i}}(1-p(y_{i}=1|x_{i}))^{1-y_{i}}

                             \large j(w)=\sum_{i=1}^{n}[ y_{i}log(p(y_{i}=1|x_{i}))+(1-y_{i})log(1-p(y_{i}=1|x_{i}))]

                            \large j(w)=\sum_{i=1}^{n}[ y_{i}log(\frac{p(y_{i}=1|x_{i})}{1-p(y_{i}=1|x_{i})})+log(1-p(y_{i}=1|x_{i}))]

4.由sigmod函數可以推到出如下結果:

                             \large p(y_{i}=1|x_{i})=\frac{1}{1+e^{-z}}               

                             \large 1-p(y_{i}=1|x_{i})=\frac{1}{1+e^{z}}

     從而推到出:

                            \large log(\frac{p(y_{i}=1|x_{i})}{1-p(y_{i}=1|x_{i})})=log(\frac{1+e^{z}}{1+e^{-z}})=z=w^{T}x+b

                           \large log(1-p(y_{i}=1|x_{i}))=log(\frac{1}{1+e^{z}})=-log(1+e^{z})

 5.將4中結果代入3中 :

                          \large j(w)=\sum_{i=1}^{n}[ y_{i}(w^{T}x+b)-log(1+e^{w^{T}x+b})]

 6.J(w)是一個凸函數,我們對這個凸函數求導,利用梯度下降算法來得到最優解,即導數爲0的那點。

如上圖,即找到最低點。

                                 \bg_white \large \frac{\partial j(w)}{\partial w}=\sum_{i=1}^{n}[ y_{i}x_{i}-\frac{e^{w^{T}x+b}}{1+e^{w^{T}x+b}}x_{i}]=\sum_{i=1}^{n}[y_{i}-g(w^{T}x+b)]x_{i}

                                    \large \dpi{120} \large w_{j}:=w_{j}+ a\frac{\partial j(w)}{\partial w}


import numpy as np

def sigmod(z):
    return 1/(1+np.exp(-z)
              
def gradAscent(data,label):
    dataMatrix=np.mat(data)
    classLabels=mat(label).transpose()
    m,n = shape(dataMatrix)
    a=0.001        #梯度幅度
    maxCycles=500  #迭代次數
    weights = ones((n,1))
    for i in range(maxCycles):
        h=sigmod(dataMatrix*weights)
        error = label-h
        weight=weight+a*error* dataMatrix.transpose()
    return array(weights)

tensorflow版本:

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

train_X = np.linspace(-1,1,100)

train_Y = 2*train_X + np.random.randn(*train_X.shape)*0.3

#顯示模擬數據點
plt.plot(train_X,train_Y,'ro',label='Original data')

#佔位符

X = tf.placeholder('float')
Y = tf.placeholder('float')

w = tf.Variable(tf.random_normal([1]),name='weight')
b = tf.Variable(tf.zeros([1]),name='bias')

z = tf.multiply(X,w)+b

cost = tf.reduce_mean(tf.square(Y - z))

learning_rate = 0.001

optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)

#初始化所有變量
init = tf.global_variables_initializer()

#定義參數
training_epochs = 500
display_step = 2

with tf.Session() as sess:
    sess.run(init)
    plotdata={'batchsize':[],'loss':[]}

    for epoch in range(training_epochs):
        for (x,y) in zip(train_X,train_Y):
            sess.run(optimizer,feed_dict={X:x,Y:y})

        if epoch % display_step == 0:
            loss = sess.run(cost,feed_dict={X:train_X,Y:train_Y})
            print('Epoch:',epoch,'cost=',loss,'w=',sess.run(w),'b=',sess.run(b))

            if not (loss == 'NA'):
                plotdata['batchsize'].append(epoch)
                plotdata['loss'].append(loss)

    print('finished!')
    print('cost=',sess.run(cost,feed_dict={X:train_X,Y:train_Y}),'w=',sess.run(w),'b=',sess.run(b))

由於處理的數據有不同的量綱和量綱單位,導致不同維度的數據之間尺度差異很大,如下圖(左)所示,目標函數的等高線是橢圓形的。這樣在通過最小化目標函數尋找最優解的過程中,梯度下降法所走的路線是鋸齒狀的,需要經過的迭代次數過多,嚴重影響了算法的效率。 
這裏寫圖片描述
爲了解決這個問題,可以對數據進行歸一化,例如採用min-max標準化將輸入數據範圍統一到[0,1]之間,處理後的結果如上圖(右)所示,經過很少次數的迭代就可以達到目標函數的最低點,極大提高算法的執行效率。

2. 牛頓法

數據歸一化是從數據預處理的角度解決梯度下降法迭代次數過多這個問題的,若從目標函數優化的角度去思考,可以用牛頓法替代梯度下降法,從而提高參數最優值的求解速度。 
有n個變量的函數J(θ)J(θ)的一階導數爲: 

二階導數(也稱爲Hessian矩陣)爲: 

目標函數J(θ)J(θ)的包含二階導數的泰勒展開式爲: 

將J(θ+Δθ)J(θ+Δθ)看做ΔθΔθ的函數的話,其最小值在其偏導數等於0處取得: 

θ+Δθθ+Δθ是對目標函數取得最小值時參數的一個較好的估計,在牛頓法中會在ΔθΔθ的基礎上乘以一個步長αα(取值小於1,比如0.001)。 使用牛頓法迭代過程爲:

    for i in xrange(0, num_passes):
        Jprime = X_expand.T.dot(sigmoid(X_expand.dot(theta))-y.reshape(X.shape[0],1))
        for j in xrange(0, num_examples):
            H_theta = sigmoid(X_expand[j,:].dot(theta))
            A[j,j] = H_theta*(1-H_theta) + 0.0001
        Jprime2 = X_expand.T.dot(A).dot(X_expand)
        delta_theta = np.linalg.solve(Jprime2,Jprime)
        delta_theta += reg_lambda*theta
        theta += -al*delta_theta
    return theta 

 

 

打賞一下作者:

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