机器学习、深度学习、数据分析、大数据、服务端技术栈等等,这几部分都是很全的。可以先看部分(价值超大!!)
免费分享给大家,点击这里!
很多的初学者最初接触、以及最熟悉的损失函数一定是平方损失函数(MSE)。
对于在逻辑回归中遇到的对数损失函数立马会让很多同学陷入蒙圈的状态~
这几天,就有一位可爱的同学问到:逻辑回归中,对数损失函数是什么?如何深层次理解其中的原理?
当然,不是这么的直接,绕弯好久才说清楚。
那下面,咱们一起深层次的学习一下关于对数损失函数的内容。
老规矩:大家伙如果觉得近期文章还不错!欢迎大家点个赞、转个发~
首先,我们要了解逻辑回归是用来解决分类问题的一种机器学习方法。
在逻辑回归中,我们试图建立一个模型来预测一个样本属于某个类别的概率。
在逻辑回归中,我们通常使用对数损失函数(logarithmic loss function),也称为交叉熵损失函数(cross-entropy loss function)。
对于二分类问题,其定义如下:
这个同学们已经很熟悉了,其中:
是损失函数;
是样本数量;
是逻辑回归的假设函数;
是第
个样本的实际类别;
是第
个样本的特征向量;
是模型参数。
通常,对数损失函数的含义可以从两个方面来理解:
在逻辑回归中,我们假设样本的类别服从伯努利分布,即每个样本属于正类的概率为
,属于负类的概率为
。这个假设使得逻辑回归的输出被解释为一个概率值。
我们希望找到一个参数
,使得给定样本的情况下,出现这个样本的概率最大。这就是最大似然估计(MLE)的思想。具体地,我们希望最大化似然函数:
其中,
是样本
的类别分布。对于逻辑回归,这个分布可以用逻辑回归的假设函数
来表示。当样本的实际类别为1时,
;当实际类别为0时,
。
为了方便计算,通常转换成对数似然函数:
我们的目标是最大化对数似然函数
,即找到最优的参数
,使得给定样本的情况下,出现这个样本的概率最大。
为了将最大化对数似然函数转换为最小化问题(因为大多数优化算法是针对最小化问题设计的),我们可以将对数似然函数取负号,得到对数损失函数
。最终目标是最小化对数损失函数:
这就是对数损失函数在最大似然估计角度的解释。通过最小化对数损失函数,我们能够找到使得给定样本的情况下,出现这个样本的概率最大的参数
,从而得到最优的逻辑回归模型。
在逻辑回归中,我们希望用一个线性决策边界将两类样本分开。这个决策边界可以用一个线性函数来表示,即
,其中
是样本的特征向量,
是模型的参数。
对于二分类问题,样本的标签
只能取0或1。我们可以将
视为样本
属于正类的概率,即
,则
就是样本
属于负类的概率,即
。
对数损失函数的表达式为:
其中,第一项
表示当样本的实际类别为1时,我们希望
越接近于1,对数损失越小;第二项
表示当样本的实际类别为0时,我们希望
越接近于0,对数损失越小。
换言之,对数损失函数在几何上的解释是:我们希望模型的预测值
与实际类别
越接近,损失越小;当模型的预测值与实际类别相符合时,对数损失函数的值趋近于0。而当预测值与实际类别偏离较大时,对数损失函数的值会变得非常大。
换句话说,对数损失函数是一种衡量模型预测准确性的指标。它可以直观地告诉我们模型在分类任务中的表现如何。通过最小化对数损失函数,我们可以找到最优的参数
,从而得到一个能够较好地分类样本的逻辑回归模型。
让我们用最简单的代码来实现上面所有的理论基础~
import numpy as np
import matplotlib.pyplot as plt
# 生成一些模拟数据
np.random.seed(0)
X = 2 * np.random.rand(100, 1)
y = (X > 1).astype(int)
# 定义逻辑回归的假设函数
def sigmoid(z):
return 1 / (1 + np.exp(-z))
# 计算对数损失函数
def compute_loss(X, y, theta):
m = len(y)
h = sigmoid(X.dot(theta))
loss = -1/m * np.sum(y * np.log(h) + (1 - y) * np.log(1 - h))
return loss
# 使用梯度下降来训练模型
def gradient_descent(X, y, theta, learning_rate, iterations):
m = len(y)
loss_history = []
for i in range(iterations):
h = sigmoid(X.dot(theta))
gradient = 1/m * X.T.dot(h - y)
theta -= learning_rate * gradient
loss = compute_loss(X, y, theta)
loss_history.append(loss)
return theta, loss_history
# 在特征向量中添加偏置项
X_b = np.c_[np.ones((100, 1)), X]
# 初始化参数
theta = np.random.randn(2, 1)
# 设置学习率和迭代次数
learning_rate = 0.01
iterations = 1000
# 训练模型
theta_final, loss_history = gradient_descent(X_b, y, theta, learning_rate, iterations)
# 绘制损失函数随迭代次数的变化
plt.plot(loss_history)
plt.xlabel('Iterations')
plt.ylabel('Loss')
plt.title('Loss Function')
plt.show()
咱们整体详细的来解释一下这个代码,这些天,老有很多同学问到代码的细节。
首先,我们导入了所需的库,包括NumPy用于数学运算和数组操作,以及Matplotlib用于绘图。
# 生成一些模拟数据
np.random.seed(0)
X = 2 * np.random.rand(100, 1)
y = (X > 1).astype(int)
然后,我们生成了一些模拟数据,包括特征向量 X 和对应的标签 y。这里使用了随机数生成函数 np.random.rand()
生成 100 个在 [0, 2] 范围内的随机数作为特征向量,然后根据大于 1 的条件判断将标签设为 1 或 0。
# 定义逻辑回归的假设函数
def sigmoid(z):
return 1 / (1 + np.exp(-z))
定义了逻辑回归的假设函数 sigmoid,用于将线性模型的输出转换为 [0, 1] 之间的概率值。
# 计算对数损失函数
def compute_loss(X, y, theta):
m = len(y)
h = sigmoid(X.dot(theta))
loss = -1/m * np.sum(y * np.log(h) + (1 - y) * np.log(1 - h))
return loss
定义了计算对数损失函数的函数 compute_loss()
。首先,通过逻辑回归的假设函数计算模型的预测值,然后利用对数损失函数的表达式来计算整体的损失。
# 使用梯度下降来训练模型
def gradient_descent(X, y, theta, learning_rate, iterations):
m = len(y)
loss_history = []
for i in range(iterations):
h = sigmoid(X.dot(theta))
gradient = 1/m * X.T.dot(h - y)
theta -= learning_rate * gradient
loss = compute_loss(X, y, theta)
loss_history.append(loss)
return theta, loss_history
定义了使用梯度下降法来训练逻辑回归模型的函数 gradient_descent()
。在每次迭代中,计算当前模型参数下的损失函数值,并更新参数以使损失函数减小。
# 在特征向量中添加偏置项
X_b = np.c_[np.ones((100, 1)), X]
# 初始化参数
theta = np.random.randn(2, 1)
# 设置学习率和迭代次数
learning_rate = 0.01
iterations = 1000
# 训练模型
theta_final, loss_history = gradient_descent(X_b, y, theta, learning_rate, iterations)
对特征向量 X 添加了一列偏置项,即在特征向量前面加了一列全为1的向量,这样可以使模型拟合更灵活。然后初始化模型参数 (\theta),设置学习率和迭代次数,并调用梯度下降函数来训练模型,得到最终的模型参数和损失值的历史记录。
# 绘制损失函数随迭代次数的变化
plt.plot(loss_history)
plt.xlabel('Iterations')
plt.ylabel('Loss')
plt.title('Loss Function')
plt.show()
最后,咱们利用 Matplotlib 库绘制了损失函数随着迭代次数的变化曲线图,用于可视化损失函数的收敛情况,以及训练过程中损失的变化。
在逻辑回归中,对数损失函数是用来衡量模型预测值与实际类别之间差异的重要指标。
通过最大化似然函数或者几何角度的解释,我们可以理解为什么选择对数损失函数作为逻辑回归的损失函数。同时,通过Python代码和图形的展示,我们可以直观地看到损失函数随着训练次数的变化而变化,从而更好地理解损失函数的作用和逻辑回归模型的训练过程。