逻辑回归损失函数_逻辑回归为何不用平方差损失函数

本文探讨逻辑回归的损失函数选择,解释为何不用平方差损失,重点在于交叉熵损失函数避免了梯度消失问题,更利于模型优化。通过实验对比,交叉熵损失在训练效果上优于平方差损失。
摘要由CSDN通过智能技术生成

当面试一些刚进入机器学习领域的学生时,我都会问这两个问题:   (1) 逻辑回归的损失函数是?   (2) 逻辑回归为何不用平方差损失函数?
对于第一个问题,大多数人都知道是交叉熵损失函数;对于第二个问题,却有不少人回答不出来或者回答不是那么准确。有的回答说:因为逻辑回归的预测值在[0,1]范围内,用交叉熵损失函数能方便转成概率问题进行计算,这种回答显然没有回答出我想要的理想答案。

其实当初我也被这个问题困惑过:为何线性回归用的是平方差损失函数,到了逻辑回归就改成交叉熵损失函数。这次就说说我对于这个问题的理解。

为何损失函数

损失函数是用来评价模型优劣的一个函数,也称为目标函数、代价函数。那模型的优劣如何来评价呢,一个最直观的做法就是看预测值db1af235-1f3f-eb11-8da9-e4434bdf6706.svg与真实值df1af235-1f3f-eb11-8da9-e4434bdf6706.svg的差距,若差距为0,则说明预测正确;若差值越大,则说明模型表现的越糟糕。这也就引出了平方差损失函数的形式,如下。e01af235-1f3f-eb11-8da9-e4434bdf6706.svg
其中e31af235-1f3f-eb11-8da9-e4434bdf6706.svg数据集的样本数量。

为何交叉熵损失函数

交叉熵是衡量两个概率分布的差异,也称对数损失函数。交叉熵越大,两个分布之间差异越大,说明预测的结果越糟糕;反之,交叉熵越小,两个分布很接近,说明预测的结果越完美。
在逻辑回归上,交叉熵损失函数表现形式如下:e51af235-1f3f-eb11-8da9-e4434bdf6706.svg

为何逻辑回归选择交叉损失函数

其实这个主要问题在于逻辑回归是在线性回归的基础上加了非线性激活函数sigmoid,在反向传播用梯度下降的方式求解的时候,若采用平方差损失函数,导致参数的导数带了sigmoid激活函数,而sigmoid在值很大或很小的两端会出现梯度消失的情况;而若采用交叉熵损失函数,参数的导数跟sigmoid激活函数无关,这样在参数更新的时候更容易求到最优解。下面展示下公式的推导过程。

假设e81af235-1f3f-eb11-8da9-e4434bdf6706.svg,其中ea1af235-1f3f-eb11-8da9-e4434bdf6706.svged1af235-1f3f-eb11-8da9-e4434bdf6706.svg为sigmoid激活函数,在考虑单条样本下:若采用平方差损失函数,在使用梯度下降方法进行ef1af235-1f3f-eb11-8da9-e4434bdf6706.svgf21af235-1f3f-eb11-8da9-e4434bdf6706.svg更新时,需要损失函数对它们进行求导:f51af235-1f3f-eb11-8da9-e4434bdf6706.svgf91af235-1f3f-eb11-8da9-e4434bdf6706.svg

然后在ff1af235-1f3f-eb11-8da9-e4434bdf6706.svg的学习率下更新ef1af235-1f3f-eb11-8da9-e4434bdf6706.svgf21af235-1f3f-eb11-8da9-e4434bdf6706.svg时:0b1bf235-1f3f-eb11-8da9-e4434bdf6706.svg0e1bf235-1f3f-eb11-8da9-e4434bdf6706.svg

因为sigmoid函数的特性(如下图),当111bf235-1f3f-eb11-8da9-e4434bdf6706.svg过大或过小的时候,函数呈平坦趋势,导致131bf235-1f3f-eb11-8da9-e4434bdf6706.svg很小,甚至为0,也就出现梯度消失的情况,也造成ef1af235-1f3f-eb11-8da9-e4434bdf6706.svgf21af235-1f3f-eb11-8da9-e4434bdf6706.svg更新非常慢,使得平方损失函数难以求的最优解的概率加大。

1bc2f42271905c583cd7d8b09262ab65.png

若采用交叉熵损失函数,情况就有好很多。对应参数的导数如下(若对详细推导过程感兴趣,建议在纸上自己推导下):1b1bf235-1f3f-eb11-8da9-e4434bdf6706.svg1d1bf235-1f3f-eb11-8da9-e4434bdf6706.svg

ff1af235-1f3f-eb11-8da9-e4434bdf6706.svg的学习率下更新ef1af235-1f3f-eb11-8da9-e4434bdf6706.svgf21af235-1f3f-eb11-8da9-e4434bdf6706.svg时:241bf235-1f3f-eb11-8da9-e4434bdf6706.svg261bf235-1f3f-eb11-8da9-e4434bdf6706.svg
可以看出来,参数更新中没有131bf235-1f3f-eb11-8da9-e4434bdf6706.svg,只受2a1bf235-1f3f-eb11-8da9-e4434bdf6706.svg, 而这相当于预测误差,当误差大的时候,权重更新快;当误差小的时候,权重更新慢。这一特性更适合损失函数能更快求到最优解。

以上也就能足够说明逻辑回归选择交叉熵而不选择平方差作为损失函数的原因了。

在实际情况下两个损失函数有多大差别

为了验证两个损失函数的差异,我选择MNIST数据集进行实验:只识别数字3,这样将数据集的label转变为[0,1],1代表是数字3,0为其他数字。模型最后一层选择sigmod作为激活函数进行回归预测,然后选择这两个不同的损失函数,看看训练情况如何。下面为对应的代码。

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import numpy as np

# load dataset
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train = x_train.reshape(60000, 784).astype('float32') /255
x_test = x_test.reshape(10000, 784).astype('float32') /255

y_train=np.array([0 if d==2 else 1 for d in y_train])
y_test=np.array([0 if d==2 else 1 for d in y_test])
#build model
inputs = keras.Input(shape=(784,), name='mnist_input')
h1 = layers.Dense(64, activation='relu')(inputs)
outputs = layers.Dense(1, activation='sigmoid')(h1)
model = tf.keras.Model(inputs, outputs)
#以平方差损失函数来编译模型进行训练
model.compile(optimizer=keras.optimizers.RMSprop(),
loss=tf.keras.losses.MeanSquaredError(),
metrics=['accuracy'])
#以交叉熵函数来编译模型进行训练
model.compile(optimizer=keras.optimizers.RMSprop(),
loss=keras.losses.BinaryCrossentropy(),
metrics=['accuracy'])
#training 
history = model.fit(x_train, y_train, batch_size=64, epochs=5,
validation_data=(x_test, y_test))

训练的结果对应如下:

2678fd3f0a7e0511b8a7fa04de93f5a6.png

平方差损失函数训练结果

c315856a247d8b6fafbc7fe74fd29d05.png

交叉熵损失函数训练结果

从结果可以看出,不论在训练集上,还是验证集上,交叉熵损失函数都是明显优于平方差损失函数。此外,也能看到在平方差损失函数下,验证集上的准确率没发生变化,说明模型的参数没更新过,跟上述公式推导结论也是吻合的。所以,在训练模型时候,选择一个合适的损失函数也是至关重要的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值