【逻辑回归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 

 

 

打赏一下作者:

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