当前位置: 首页 > news >正文

深度学习激活函数与损失函数全解析:从Sigmoid到交叉熵的数学原理与实践应用

目录

  • 前言
  • 一、sigmoid 及导数求导
  • 二、tanh 
  • 三、ReLU 
  • 四、Leaky Relu
  • 五、 Prelu
  • 六、Softmax
  • 七、ELU
  • 八、极大似然估计与交叉熵损失函数
  • 8.1 极大似然估计与交叉熵损失函数算法理论
  • 8.1.1 伯努利分布
  • 8.1.2 二项分布
  • 8.1.3 极大似然估计
  • 总结

前言

书接上文

PaddlePaddle线性回归详解:从模型定义到加载,掌握深度学习基础-CSDN博客文章浏览阅读995次,点赞24次,收藏18次。本文深入讲解了使用PaddlePaddle框架实现线性回归的完整流程,涵盖了模型定义(包括序列方式和类方式)、数据加载、模型保存(基础API和高级API)、模型加载(基础API和高级API)以及模型网络结构查看等关键步骤,旨在帮助读者全面掌握PaddlePaddle框架下线性回归的实现方法,并理解其背后的原理。同时,文章还涉及曲线拟合的理论与实践,以及多种激活函数的特性与应用,为读者构建扎实的深度学习基础。 https://blog.csdn.net/qq_58364361/article/details/147408186?fromshare=blogdetail&sharetype=blogdetail&sharerId=147408186&sharerefer=PC&sharesource=qq_58364361&sharefrom=from_link


一、sigmoid 及导数求导

import numpy as np  # 导入 numpy 库,用于数值计算
import matplotlib.pyplot as plt  # 导入 matplotlib.pyplot 模块,用于绘图def sigmoid(x):"""Sigmoid 激活函数:param x: 输入值:return: Sigmoid 函数的输出"""return 1 / (1 + np.exp(-x))  # Sigmoid 函数的公式def sigmoid_derivative(x):"""Sigmoid 激活函数的导数:param x: 输入值:return: Sigmoid 函数导数的输出"""return sigmoid(x) * (1 - sigmoid(x))  # Sigmoid 导数的公式x = np.linspace(-5, 5, 100)  # 创建一个从 -5 到 5 的等间隔的 100 个点的数组
y = sigmoid(x)  # 计算 sigmoid 函数的值
y1 = sigmoid_derivative(x)  # 计算 sigmoid 导数的值plt.figure()  # 创建一个新的图形
plt.plot(x, y, label='sigmoid')  # 绘制 sigmoid 函数的图像
plt.plot(x, y1, label='sigmoid_derivative')  # 绘制 sigmoid 导数的图像
plt.legend()  # 显示图例
plt.show()  # 显示图形


二、tanh 

下面学一下双曲正切的激活函数tanh

tanh激活函数的数学公式为

该函数解决了Sigmoid函数不以零为中心的问题,它的取值范围是(-1,1),无限接近1和-1,但永不等于1或者-1,它是关于0中心对称,以零为中心。

tanh导数公式为:

tanh特点总结:

输出范围:tanh 函数的输出范围被限制在 -1 到 1 之间,因此它可以使神经网络的输出更接近于零中心,有助于减少梯度消失问题。

零中心性:tanh 函数的输出以零为中心,即在输入为 0 时函数值为 0,这有助于减少梯度消失问题,并使得神经网络更容易学习。

相对于Sigmoid函数,优势显而易见

输出以零为中心:tanh函数的输出范围是-1到1之间,其均值为零,因此它是零中心的激活函数。相比于Sigmoid函数,tanh函数能够更好地处理数据的中心化和对称性,有助于提高网络的学习效率。

饱和区域更大:在输入绝对值较大时,tanh函数的斜率较大,这使得它在非线性变换上比Sigmoid函数更加陡峭,有助于提供更强的非线性特性,从而提高了网络的表达能力。

良好的输出范围:tanh函数的输出范围在-1到1之间,相比于Sigmoid函数的0到1之间,输出范围更广,有助于减少数据在网络中传播时的数值不稳定性。

但是缺点也同样明显:

容易出现梯度消失问题:虽然相比于Sigmoid函数,tanh函数在非饱和区域的斜率较大,但在输入绝对值较大时,其导数仍然会接近于零,可能导致梯度消失问题。

  • 计算难度同样大
import numpy as np  # 导入 numpy 库,用于数值计算
import matplotlib.pyplot as plt  # 导入 matplotlib.pyplot 模块,用于绘图def tanh(x):"""tanh 激活函数:param x: 输入值:return: tanh 函数的输出"""return np.tanh(x)  # 返回 tanh 函数的计算结果def tanh_derivative(x):"""tanh 激活函数的导数:param x: 输入值:return: tanh 函数导数的输出"""return 1 - np.tanh(x) ** 2  # 返回 tanh 导数的计算结果x = np.linspace(-5, 5, 100)  # 创建一个从 -5 到 5 的等间隔的 100 个点的数组
y = tanh(x)  # 计算 tanh 函数的值
y1 = tanh_derivative(x)  # 计算 tanh 导数的值plt.figure()  # 创建一个新的图形
plt.plot(x, y, label='tanh')  # 绘制 tanh 函数的图像
plt.plot(x, y1, label='tanh_derivative')  # 绘制 tanh 导数的图像
plt.legend()  # 显示图例
plt.show()  # 显示图形


三、ReLU 

 ReLU激活函数的数学公式为:

ReLU函数其实是分段线性函数,把所有的负值都变为0,而正值不变。

ReLU函数的导数公式为:

ReLU特点:

稀疏性:ReLU 函数的导数在输入为负数时为零,这意味着在反向传播过程中,只有激活的神经元会传递梯度,从而促进了稀疏激活的现象,有助于减少过拟合。

计算高效:ReLU 函数的计算非常简单,并且在实践中被证明是非常高效的。

解决梯度消失问题: ReLU函数在输入大于零时输出其本身值,这使得在反向传播时梯度保持为常数1,避免了梯度消失问题。ReLU函数在深度网络中更容易训练。

ReLU函数的优势

  • 解决梯度消失问题: ReLU函数在输入大于零时输出输入值,这使得在反向传播时梯度保持为常数1,避免了梯度消失问题。相比于Sigmoid和tanh函数,ReLU函数在深度网络中更容易训练,使得网络能够更有效地学习复杂的特征。
  • 计算速度快: ReLU函数的计算非常简单,只需进行一次阈值判断和取最大值操作。这使得在大规模深度神经网络中,ReLU函数的计算速度远快于Sigmoid和tanh函数,加快了模型训练的速度。
  • 稀疏激活性: 在输入小于零的情况下,ReLU函数的输出是零,这表现为稀疏激活性。这意味着在激活后,一部分神经元将被激活,而其他神经元则保持不活跃。这有助于减少神经网络中的冗余计算和参数数量,提高了网络的泛化能力。

它的劣势:

  • 死亡ReLU问题(Dying ReLU): 在训练过程中,某些神经元可能会遇到“死亡ReLU”问题,即永远不会被激活。如果某个神经元在训练过程中的权重更新导致在其上的输入始终为负值,那么它的输出将永远为零。这意味着该神经元不会再学习或参与后续训练,导致该神经元“死亡”,从而减少了网络的表达能力。

死亡relu问题理解

ReLU函数导数只可以取两个值,当输入小于0时,导数为0;当输入大于0时,导数为1,在反向传播过程中,

(w新=w旧-学习率*梯度),如果学习率比较大,一个很大的梯度更新后,经过Relu激活函数,可能会导致ReLU神经元更新后的权重是负数,进而导致下一轮正向传播过程中ReLU神经元的输入是负数,输出是0,由于ReLU神经元的输出为0,在后续迭代的反向过程中,该处的梯度一直为0,相关参数不再变化,从而导致ReLU神经元的输入始终是负数,输出始终为0。即为“死亡ReLU问题”。

(relu产生的情况,第一种情况就是输入大部分是负值,第二种情况 w更新后成为负数,第3种情况就是b为比较大的负数)

  • 输出不是以零为中心: ReLU函数的输出范围是从零开始,因此输出不是以零为中心的。这可能会导致训练过程中的参数更新存在偏差,降低了网络的优化能力。
  • 不适合所有问题: 尽管ReLU函数在大多数情况下表现良好,但并不是适合所有问题。对于一些问题,特别是在处理一些包含负值的数据时,ReLU函数可能不够理想,可能会产生不良的结果。

针对ReLU函数的劣势,研究人员也提出了一些改进的激活函数,如Leaky ReLU、Parametric ReLU和Exponential Linear Units(ELU)等,这些函数在一定程度上缓解了ReLU函数的问题,并在特定情况下表现更好。因此,在实际使用中,根据具体问题和实验结果选择合适的激活函数是很重要的。

import numpy as np  # 导入 numpy 库,用于数值计算
import matplotlib.pyplot as plt  # 导入 matplotlib.pyplot 模块,用于绘图def relu(x):"""ReLU 激活函数:param x: 输入值:return: ReLU 函数的输出"""return np.maximum(0, x)  # 返回 ReLU 函数的计算结果,即 max(0, x)def relu_derivative(x):"""ReLU 激活函数的导数:param x: 输入值:return: ReLU 函数导数的输出"""return np.where(x > 0, 1, 0)  # 返回 ReLU 导数的计算结果,当 x > 0 时为 1,否则为 0x = np.linspace(-5, 5, 100)  # 创建一个从 -5 到 5 的等间隔的 100 个点的数组
y = relu(x)  # 计算 ReLU 函数的值
y1 = relu_derivative(x)  # 计算 ReLU 导数的值plt.figure()  # 创建一个新的图形
plt.plot(x, y, label='relu')  # 绘制 ReLU 函数的图像
plt.plot(x, y1, label='relu_derivative')  # 绘制 ReLU 导数的图像
plt.legend()  # 显示图例
plt.show()  # 显示图形

四、Leaky Relu

公式:

f(x)=max(αx, x),其中 α 是一个小常数(例如0.01)

导数:

f’(x)=1,当x>0时。

f’(x)=α,当x<=0时。

Leaky ReLU 通过在负数区域引入小的正斜率 α 来避免ReLU的“死亡”问题,允许负数区域的梯度不为零。

import numpy as np  # 导入 numpy 库,用于数值计算
import matplotlib.pyplot as plt  # 导入 matplotlib.pyplot 模块,用于绘图def leaky_relu(x, a=0.01):"""Leaky ReLU 激活函数:param x: 输入值:param a: 斜率,默认为 0.01:return: Leaky ReLU 函数的输出"""return np.maximum(a * x, x)  # 返回 Leaky ReLU 函数的计算结果,即 max(a*x, x)def leaky_relu_derivative(x, a=0.01):"""Leaky ReLU 激活函数的导数:param x: 输入值:param a: 斜率,默认为 0.01:return: Leaky ReLU 函数导数的输出"""return np.where(x > 0, 1, a)  # 返回 Leaky ReLU 导数的计算结果,当 x > 0 时为 1,否则为 ax = np.linspace(-5, 5, 100)  # 创建一个从 -5 到 5 的等间隔的 100 个点的数组
y = leaky_relu(x)  # 计算 leaky_relu 函数的值
y1 = leaky_relu_derivative(x)  # 计算 leaky_relu 导数的值plt.figure()  # 创建一个新的图形
plt.plot(x, y, label='relu')  # 绘制 leaky_relu 函数的图像
plt.plot(x, y1, label='relu_derivative')  # 绘制 leaky_relu 导数的图像
plt.legend()  # 显示图例
plt.show()  # 显示图形

五、 Prelu

Prelu 和 Leaky Relu想比,Prelu的α是可学习的。

公式:

f(x)=max(αx, x),其中 α 是一个可学习的参数。

导数:

f’(x)=1,当x>0时。

f’(x)=α,当x<=0时。

PReLU是Leaky ReLu的一个变种,其中a是通过学习得到的,这使得模型可以适应性地改变其行为。

import numpy as np  # 导入NumPy库,用于数值计算
import matplotlib.pyplot as plt  # 导入Matplotlib库,用于绘图def p_relu(x, alpha=0.25):"""参数化ReLU激活函数:param x: 输入值:param alpha: 斜率小于0时的系数,默认为0.25:return: PReLU激活值"""return np.maximum(alpha * x, x)  # 返回alpha*x和x中的较大值def p_relu_derivative(x, alpha=0.25):"""参数化ReLU激活函数的导数:param x: 输入值:param alpha: 斜率小于0时的系数,默认为0.25:return: PReLU导数值"""return np.where(x > 0, 1, alpha)  # 当x>0时返回1,否则返回alphax = np.linspace(-5, 5, 100)  # 创建一个从-5到5的等间隔数组,包含100个点
y_p_relu = p_relu(x)  # 计算x的PReLU激活值
y_p_relu_derivative = p_relu_derivative(x)  # 计算x的PReLU导数值
plt.figure(figsize=(8, 6))  # 创建一个图形,设置大小为8x6英寸
plt.plot(x, y_p_relu)  # 绘制x和PReLU激活值的关系图
plt.plot(x, y_p_relu_derivative)  # 绘制x和PReLU导数值的关系图
plt.show()  # 显示图形

 


六、Softmax

softmax激活函数,但是很多地方,不会把softmax称为激活函数,但是呢没有一个合理的叫法,它就叫softmax函数,但是呢,它的性质上无论和我们的sigmoid或者tanh 或者relu等其实是类似的,我们可以把它称为激活函数。

softmax激活函数为什么不把它称为激活函数,是因为和它的位置是有关系的。为什么呢?

softmax这个函数和我们的sigmoid函数也好。relu函数也好,不一样的点在哪里?如果sigmoid函数位于算法的最后一层,做二分类的活。softmax函数它一般只用于最后一次的激活,也就是输出之前的一次激活,前面不用softmax。 softmax一般不用于回归算法中,一般是用于分类中,我们前面计算的都是在算拟合和回归,softmax它做的是分类。

eg:猫和狗,当我们的输出不是一个值而是一个向量的时候,比如要分成三类(猫,狗 ,老虎)三类,根据输出的向量数值,按照下面的公式进行计算。

然后再结合后面的交叉熵就可以计算损失值。

Softmax函数,可以将神经网络计算出来的数值通过公式变成概率,经过softmax后得到的结果相加和为1。

另一个优势就是不论向量输出的结果是正值还是负值都能转化为正值。

这个在后续的深度学习中用的非常多。

当n=100时,即有100类时,其图像如下图所示:

softmax 特点总结:

概率分布:Softmax函数将输入转换为概率分布,因此在多分类问题中常用于将模型的原始输出转换为概率值。

连续可导:Softmax函数是连续可导的,这使得它可以与梯度下降等优化算法一起使用进行训练。

指数增长:Softmax函数中的指数运算可能会导致数值稳定性问题,特别是当输入较大时。为了解决这个问题,可以通过减去输入向量中的最大值来进行数值稳定的计算。

梯度计算简单:Softmax函数的导数计算相对简单,可以通过对Softmax函数的定义进行微分得到。

涉及到softmax求导,看一下它怎么求导?

import numpy as np  # 导入NumPy库,用于数值计算
import matplotlib.pyplot as plt  # 导入Matplotlib库,用于绘图def softmax(x):n_val = np.exp(x)  # 计算输入x的指数d_val = np.sum(np.exp(x))  # 计算所有指数的和return n_val / d_val  # 返回Softmax值def softmax_derivative(x):s = softmax(x)  # 计算Softmax值return np.diagflat(s) - np.outer(s, s)  # 计算Softmax导数x = np.linspace(-5, 5, 50)  # 创建一个从-5到5的等间隔数组,包含50个点
y_softmax = softmax(x)  # 计算x的Softmax值
y_softmax_derivative = softmax_derivative(x)  # 计算x的Softmax导数
plt.figure(figsize=(8, 6))  # 创建一个图形,设置大小为8x6英寸
plt.plot(x, y_softmax)  # 绘制x和Softmax值的关系图
plt.plot(x, y_softmax_derivative)  # 绘制x和Softmax导数的关系图
plt.show()  # 显示图形


七、ELU

前面的激活函数学完后,现在学习最后一个激活函数,它叫ELU的激活函数。

ELU(Expoentital Linear Unit)激活函数是深度学习中用于增强网络学习能力的又一种激活函数,ELU通过在负值输入时提供负值输出,旨在结合Relu的优点和解决其潜在的一些问题,如ReLU的不活跃神经元问题。

数序定义

ELU函数的数学表达式定义为:

中,x是函数的输入,α是一个预定义的超参数,用于控制x为负值时输出的饱和度。

图像如下:

2.函数特性

非线性:ELU是非线性的,可以帮助神经网络学习复杂的数据表示。

连续可导:ELU在整个定义域内连续可导,这有助于提高梯度下降优化算法的稳定性

解决梯度消失问题:对于负值输入,ELU提供了负值输出,这有助于减轻梯度消失问题,尤其是在深度网络中。

输出均值接近0:ELU函数能够产生负值输出,这意味着其激活输出的均值更接近0,有助于数据的中心化,减少训练过程中的偏置偏移。

3.导数

ELU函数的导数如下:

图像如下:

意味着在正数区域,梯度为1,而在负数区域,梯度取决于α和x的指数值,这有助于保持负输入值的梯度更新。

ELU优势:

ELU通过在负数区域引入指数衰减,能够减少ReLU的“死亡”问题,同时保持负值的输出,有助于保持平均激活接近零,这有助于加快学习。

ELU劣势:

计算成本:由于ELU在负值时涉及指数运算,其计算成本高于Relu及其直接变体,尤其是在前向传播时。

import numpy as np  # 导入NumPy库,用于数值计算
import matplotlib.pyplot as plt  # 导入Matplotlib库,用于绘图def elu(x, alpha=0.25):"""ELU激活函数:param x: 输入值:param alpha: x小于0时的系数,默认为0.25:return: ELU激活值"""return np.where(x > 0, x, alpha * (np.exp(x) - 1))  # 当x>0时返回x,否则返回alpha * (np.exp(x) - 1)def elu_derivative(x, alpha=0.25):"""ELU激活函数的导数:param x: 输入值:param alpha: x小于0时的系数,默认为0.25:return: ELU导数值"""return np.where(x > 0, 1, alpha * (np.exp(x)))  # 当x>0时返回1,否则返回alpha * np.exp(x)x = np.linspace(-5, 5, 100)  # 创建一个从-5到5的等间隔数组,包含100个点
y_elu = elu(x)  # 计算x的ELU激活值
y_elu_derivative = elu_derivative(x)  # 计算x的ELU导数值plt.figure(figsize=(8, 6))  # 创建一个图形,设置大小为8x6英寸
plt.plot(x, y_elu)  # 绘制x和ELU激活值的关系图
plt.plot(x, y_elu_derivative)  # 绘制x和ELU导数值的关系图
plt.show()  # 显示图形


八、极大似然估计与交叉熵损失函数

从以下3个方面对极大似然估计与交叉熵损失函数进行介绍
1.极大似然估计与交叉熵损失函数算法理论讲解
2.编程实例与步骤


8.1 极大似然估计与交叉熵损失函数算法理论

交叉熵损失函数是独立于的MSE(均方差损失函数)

交叉熵损失函数是另一种损失函数。MSE损失函数和交叉熵损失函数它们的应用场合是不一样的。

均方差损失函数主要应用在回归、拟合领域。(eg:有一些点用直线拟合它,或者用曲线去拟合)。

交叉熵损失函数主要应用在分类领域

交叉熵损失函数主要应用在分类领域

eg:对有猫和狗的图片进行分类,输入猫和狗的照片,然后特征提取,得到两类结果,可以先用softmax,得到两类的概率值将求解出来的概率,交给交叉熵计算损失?就可以进行模型优化了。

那分类问题指的是什么问题呢?

分类问题是机器学习中最常见的问题之一。分类问题的目标是根据给定的特征将数据分为不同的类别

分类问题怎么去优化的呢?

主要是使用最小化交叉熵损失去优化

MSE解决分类问题的弊端?

在回归预测问题中,使用MSE作为损失函数,L2距离(欧式距离)能够很漂亮的体现出预测值与实际值的差距(距离)。

在分类问题中,网络输出的是属于某个类的概率。最后一层使用(softmax激活函数或者sigmoid激活函数)进行处理,二分类可以使用Sigmoid也可以使用Softmax,多分类使用Softmax,如果使用MSE,当与Sigmoid或Softmax搭配使用时,loss的偏导数的变化趋势和预测值及真实值之间的数值的变化趋势不一致。

当真实值y=1时,若预测值等于1,

等于0

当真实值y=1时,如预测值等于0,

等于0

也就是说,预测为错误时,依然没有梯度让网络可以学习。可以得出MSE对于分类问题无法有效地度量类别之间的差异,导致对于分类任务的优化不够敏感。


8.1.1 伯努利分布

伯努利分布是一种离散型概率分布,它描述的是一次伯努利试验中成功和失败的概率分布。在伯努利分布中,只有两种可能的结果,通过用0和1来表示,其中0表示失败,1表示成功。

伯努利分布的数学公式表达如下:

如果表示抛硬币,则正面向上的概率 p为当x=1时,p(1)=p^1*(1-p)^(1-1)=p,

反面向上的概率1-p为当x=0时,p(0)=p^0*(1-p)=1-p


8.1.2 二项分布

二项分布是描述了n次独立的伯努利试验中成功的次数的概率分布。在二项分布中,每次试验都是独立的,且成功和失败的概率保持不变。二项分布的概率质量函数公式如下:

其中n表示试验次数,k表示成功的次数,p表示单次实验成功的概率。

8.1.3 极大似然估计

极大似然估计,通俗理解来说,就是利用已知的样本结果信息,反推最具有可能(最大概率)导致这些样本结果出现的模型参数值

假设现在进行伯努利试验10次,结果用随机变量xi表示,则x1,x2,...x10,满足独立同分布。其值为(1,0,1,0,0,0,1,0,0,0),每个样本出现的概率的乘积为:

对于上面的例子结果为:

极大似然估计的目标是不是要求最大的L(p)值中对应的p值?

举个例子(p=0.1 L(p)=0.0004782969

p=0.2 L(p)=0.0016777216

p=0.5 L(p)=0.0009765625 )


总结

        本文结合理论与实践,详细解析Sigmoid、tanh、ReLU系列激活函数的数学特性与梯度行为,指出ReLU的死亡问题及改进方案如Leaky ReLU、PReLU和ELU的设计逻辑。通过可视化对比各函数曲线与导数,阐明零中心性、稀疏性对神经网络训练的影响。在损失函数部分,从极大似然估计出发,论证交叉熵在分类任务中的必要性,对比MSE的缺陷,强调概率输出与损失函数适配的重要性。代码实现覆盖函数绘制、导数计算及实际应用场景,提供完整的理论与实操参考。

http://www.xdnf.cn/news/98227.html

相关文章:

  • MYSQL之表的操作
  • 店匠科技摘得 36 氪“2025 AI Partner 创新大奖”
  • 深入解析:RocketMQ、RabbitMQ和Kafka的区别与使用场景
  • 高并发系统设计的六字真言
  • 7.7 Axios+Redux+JWT全链路实战:打通前后端API通信最佳实践
  • 努比亚Z70S Ultra 摄影师版将于4月28日发布,首发【光影大师990】传感器
  • 事关数据安全,ARM被爆不可修复漏洞
  • TCP编程
  • 智能电网第3期 | 配电房巡检机器人通信升级方案
  • Qt实现语言切换的完整方案
  • springboot+vue 支付宝支付(沙箱方式,测试环境使用)
  • 聊聊Spring AI Alibaba的ObsidianDocumentReader
  • 【人工智能】DeepSeek 的开源生态:释放 AI 潜能的社区协同与技术突破
  • Unity-无限滚动列表实现Timer时间管理实现
  • ubuntu24设置拼音输入法,解决chrome不能输入中文
  • 经验分享-上传ios的ipa文件
  • Windows 同步技术-计时器队列和内存屏障
  • 32单片机——GPIO的工作模式
  • 工具指南:免费将 PDF 转换为 Word 的 10 个工具
  • [蓝桥杯 2025 省 Python B] 最多次数
  • 数据一致性问题剖析与实践(三)——分布式事务的一致性问题
  • MIT IDSS深度解析:跨学科融合与系统科学实践
  • 【正则表达式】核心知识点全景解析
  • 【解决】layui layer的提示框,弹出框一闪而过的问题
  • 12、高阶组件:魔法增幅器——React 19 HOC模式
  • 深入详解Java中的@PostConstruct注解:实现简洁而高效初始化操作
  • java记忆手册(2)
  • python 更换 pip 镜像源
  • 书香换绿意,爱心已成荫|平安养老险陕西分公司“以书换植”公益活动
  • 区块链技术在物联网中的应用:构建可信的智能世界