【机器学习】逻辑回归(Logistic Regression)

1、前言

逻辑回归(Logistic Regression)是机器学习中的基础算法,但是逻辑回归并非像他的名字一样是回归算法,而是一种使用了回归操作通过sigmoid函数最后映射到0到1之间的小数(我们将其理解为概率)的分类算法。因为回归工作占据了大量的工作所以叫做逻辑回归也是无可厚非的。
当然每当提到逻辑回归的时候就经常会联系到线性回归,这个我之后会详解他们之间的异同,因为逻辑回归就是在线性回归的基础上加入了非线性的激活函数的影响,就变成了逻辑回归。

2、算法思想

在逻辑回归中假设数据为伯努利二分分布,通过极大似然估计的方法定义出损失函数,然后通过梯度下降的方法不断逼近最优分类曲线达到分类的目的。

首先定义一个抛硬币的场景,我们有一枚硬币,抛出正面的概率为 p 抛出背面的概率就是 1-p
首先我们假设我们数据是伯努利分布的,我们可以假设回归函数为 h θ ( x ) = p 那么负样本的概率就是 1 h θ ( x ) 假设回归函数满足以下形式:

h θ ( x ) = s i g m o i d ( θ T x )
s i g m o i d ( x ) = 1 1 + e x 1 1 + e x p ( x )

逻辑回归的损失函数是它的极大似然函数

L θ ( x ) = i = 1 m ( h θ ( x i ) ) y i ( 1 h θ ( x i ) ) 1 y i

极大似然函数无法直接求解,所以使用梯度下降来不断逼急最优解。常见的梯度下降有随机梯度下降SGD,批量梯度下降batch GD,minibatch GD小批量梯度下降

  • 批梯度下降会获得全局最优解,缺点是在更新每个参数的时候需要遍历所有的数据,计算量会很大,并且会有很多的冗余计算,导致的结果是当数据量大的时候,每个参数的更新都会很慢。
  • 随机梯度下降是以高方差频繁更新,优点是使得SGD会跳到新的和潜在更好的局部最优解,缺点是使得收敛到局部最优解的过程更加的复杂。
  • 小批量梯度下降结合了SGD和Batch-SGD的优点,每次更新的时候使用n个样本。减少了参数更新的次数,可以达到更加稳定收敛结果,一般在深度学习当中我们采用这种方法。

另外还存在动态改变学习率的Adam与动量等优化算法,他们可通过动态改变学习率来适应当前梯度选择合适的步长进行学习。我们正常开始学习的时候参数和最优解隔的比较远,需要保持一个较大的学习率尽快逼近最优解。但是学习到后面的时候,参数和最优解已经隔的比较近了,如果学习率设置不合理还保持最初的学习率,就会用力过猛越过最优点,在最优点附近来回振荡。

分类思路:逻辑回归通过最大化类标记的条件似然度来学习一个线性分类器。为了定义这个条件概率,使用sigmoid 函数将线性分类器的响应值 w,x 映射到一个概率上。sigmoid的值域为(0,1),满足概率的要求;而且是一个单调上升函数,可将较大的w,x映射到较大的概率p(y=1|x,w)。sigmoid的这些良好性质恰好能满足LR的需求。

3、公式推导

接下来我们对以上公式进行具体推导

h θ ( x ) = s i g m o i d ( θ T x )
s i g m o i d ( x ) = 1 1 + e x 1 1 + e x p ( x )

根据sigmoid函数的的特点我们可以得出
d d x s i g m o i d ( x ) = s i g m o i d ( x ) ( 1 s i g m o i d ( x ) )
所以 h θ ( x ) = h θ ( x ) ( 1 h θ ( x ) )
基于上文假设 y ( i ) 呈为伯努利分布, P ( y ( i ) = 1 | x ( i ) ) 表示投掷第 i 次为正面概率

P ( y ( i ) = 1 | x ( i ) ; θ ) = h θ ( x ( i ) )
P ( y ( i ) = 0 | x ( i ) ; θ ) = 1 h θ ( x ( i ) )

则以上可等价于

P ( y ( i ) | x ( i ) ; θ ) = h θ ( x ( i ) ) y i ( 1 h θ ( x i ) ) 1 y i

根据极大似然估计可以得到似然函数为

L ( y | x ; θ ) = i = 1 m P ( y ( i ) | x ( i ) ; θ )
L ( y | x ; θ ) = i = 1 m h θ ( x ( i ) ) y i ( 1 h θ ( x i ) ) 1 y ( i )

为了展开连乘 我们可以取对数进行化简

l n L ( y | x ; θ ) = i = 1 m ( y ( i ) l n ( h θ ( x ( i ) ) ) + ( 1 y ( i ) ) l n ( 1 h θ ( x ( i ) ) ) )

因为我们最终要定义损失函数所以要将原式求极大改为最小化问题所以要加个“- 1 m ”所以我们可以定义损失函数为

J ( θ ) = 1 m i = 1 m ( y ( i ) l n ( h θ ( x ( i ) ) ) + ( 1 y ( i ) ) l n ( 1 h θ ( x ( i ) ) ) )

所以我们要使似然估计最大,就是把损失函数最小然后我们使用损失函数的极小值代替最小值
所以梯度可通过对 θ j 求偏导数

J ( θ ) = θ j J ( θ ) = 1 m i = 1 m ( y ( i ) h θ ( x ( i ) ) ( 1 y ( i ) ) 1 h θ ( x ( i ) ) ) h θ ( x ( i ) ) ( 1 h θ ( x ( i ) ) ) x j i

J ( θ ) = 1 m i = 1 m ( h θ ( x ( i ) ) y ( i ) ) x j i

然后即可使用梯度下降法进行迭代求解

θ j ( t + 1 ) θ j ( t ) α θ j J ( θ )

4、算法实现

实现代码tensorflow入门的手写体识别样例,使用logistic回归进行手写体分类,利用softmax产生各个分类的概率达到识别的目的

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets("input_data/", one_hot=True)
# 超参数
learning_rate = 0.01
epochs = 1000
display_step = 20
batch_size = 100

# 定义占位符
X = tf.placeholder(tf.float32, [None, 784])
Y = tf.placeholder(tf.float32, [None, 10])

# 定义变量
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))

# 定义模型
Wx_plus_b = tf.matmul(X, W) + b
pred = tf.nn.softmax(Wx_plus_b)
# 定义损失函数与梯度下降公式
loss = tf.reduce_mean(-tf.reduce_sum(Y*tf.log(pred), reduction_indices=1))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(loss)
init = tf.global_variables_initializer()

# 启动tf系统流程
with tf.Session() as sess:
    sess.run(init)
    for epoch in range(epochs):
        avg_loss = 0.
        total_batch = int(mnist.train.num_examples / batch_size)
        for i in range(total_batch):
            batch_x, batch_y = mnist.train.next_batch(batch_size)
            _, c = sess.run([optimizer, loss], feed_dict={X:batch_x, Y:batch_y})
            avg_loss += c/total_batch

        # 输出当前的损失函数
        # if (epoch+1) % display_step == 0:
        #     print("Epoch:", '%04d' % (epoch+1), "cost=", "{:.9f}".format(avg_loss))
        print("Epoch:", '%04d' % (epoch+1), "cost=", "{:.9f}".format(avg_loss))
    print("Optimizer Finished")

    # 验证模型的准确率
    correct_pred = tf.equal(tf.argmax(pred, 1), tf.argmax(Y,1))
    accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
    print("Accuracy:",accuracy.eval({X:mnist.test.images, Y:mnist.test.labels}))

猜你喜欢

转载自blog.csdn.net/qq_30615903/article/details/80826892