深度解析 tanh tanh 激活函数
1. 引言
在现代深度学习中,激活函数(Activation Function)是神经网络的核心组件之一。它的主要作用是引入非线性,从而使神经网络能够学习和表示复杂的非线性关系。如果没有激活函数,神经网络的输出将只是输入的线性组合,无法有效地解决复杂问题,例如图像识别、语音处理和自然语言理解。
在众多激活函数中,双曲正切函数(Hyperbolic Tangent Function,简称 (\tanh))是一个经典的选择,特别是在早期的深度学习模型中。它被广泛应用于隐藏层,尤其是在循环神经网络(RNN)中扮演重要角色。
1.1 激活函数的作用
神经网络的每一层通过激活函数来调整输出,从而能够:
- 引入非线性,使网络能够拟合复杂的模式。
- 限制输出范围,帮助网络更稳定地训练。
- 改善梯度传播,促进权重的高效更新。
1.2 为什么关注 tanh \tanh tanh?
( tanh ) (\tanh) (tanh) 函数之所以重要,是因为它在某些场景中具有独特的优势:
- 输出范围在 ( [ − 1 , 1 ] ) ([-1, 1]) ([−1,1]),比 Sigmoid 的 ( [ 0 , 1 ] ) ([0, 1]) ([0,1]) 更适合对称分布的数据。
- 输出是零中心的(Zero-centered),这对于梯度更新更加友好。
- 在时间序列建模、情感分析和回归任务中, ( tanh ) (\tanh) (tanh) 函数表现出色。
1.3 ( tanh ) (\tanh) (tanh) 的应用场景
虽然近年来 ReLU 等激活函数在许多深度学习任务中成为主流, ( tanh ) (\tanh) (tanh) 函数依然在以下场景中被广泛使用:
- 循环神经网络(RNN):用于隐藏层的状态更新,处理时间序列数据。
- LSTM 和 GRU:在这些改进的循环神经网络中, ( tanh ) (\tanh) (tanh) 被用于候选隐藏状态。
- 自然语言处理(NLP):在情感分析和翻译等任务中, ( tanh ) (\tanh) (tanh) 常用于处理对称数据。
2. t a n h tanh tanh 的数学定义与性质
2.1 数学公式与定义
( tanh ) (\tanh) (tanh) 是双曲正切函数(Hyperbolic Tangent Function)的简称,其数学公式定义为:
tanh ( x ) = sinh ( x ) cosh ( x ) = e x − e − x e x + e − x \tanh(x) = \frac{\sinh(x)}{\cosh(x)} = \frac{e^x - e^{-x}}{e^x + e^{-x}} tanh(x)=cosh(x)sinh(x)=ex+e−xex−e−x
其中:
- sinh ( x ) \sinh(x) sinh(x)是双曲正弦函数,定义为: s i n h ( x ) = e x − e − x 2 sinh(x) = \frac{e^x - e^{-x}}{2} sinh(x)=2ex−e−x。
- c o s h ( x ) cosh(x) cosh(x) 是双曲余弦函数,定义为: c o s h ( x ) = e x + e − x 2 cosh(x) = \frac{e^x + e^{-x}}{2} cosh(x)=2ex+e−x。
t a n h ( x ) tanh(x) tanh(x) 是一个标准的非线性函数,它可以将输入映射到一个有限范围内,广泛应用于神经网络的隐藏层。
2.2 输出范围与图像特性
-
输出范围:
− 1 ≤ tanh ( x ) ≤ 1 -1 \leq \tanh(x) \leq 1 −1≤tanh(x)≤1- 当 x → + ∞ x \to +\infty x→+∞, tanh ( x ) → 1 \tanh(x) \to 1 tanh(x)→1。
- 当 x → − ∞ x \to -\infty x→−∞, tanh ( x ) → − 1 \tanh(x) \to -1 tanh(x)→−1。
-
函数图像特性:
- tanh ( x ) \tanh(x) tanh(x) 是一个平滑的“S”形曲线,呈对称分布。
- 当 x = 0 x = 0 x=0, tanh ( 0 ) = 0 \tanh(0) = 0 tanh(0)=0。
- tanh ( x ) \tanh(x) tanh(x) 的变化主要集中在 [ − 2 , 2 ] [-2, 2] [−2,2] 范围内,越接近边界,变化越小。
图像特性:
- 中心对称:关于原点对称,满足奇函数的性质。
- 单调递增:随着 x x x 增大, tanh ( x ) \tanh(x) tanh(x) 也增大。
2.3 与 Sigmoid 的关系(对称性)
tanh ( x ) \tanh(x) tanh(x) 与 Sigmoid 激活函数有密切关系,可以通过公式转换为对方:
tanh ( x ) = 2 ⋅ Sigmoid ( 2 x ) − 1 \tanh(x) = 2 \cdot \text{Sigmoid}(2x) - 1 tanh(x)=2⋅Sigmoid(2x)−1
Sigmoid 的公式为:
Sigmoid ( x ) = 1 1 + e − x \text{Sigmoid}(x) = \frac{1}{1 + e^{-x}} Sigmoid(x)=1+e−x1
主要区别:
- 输出范围:
- Sigmoid 的输出范围是 [ 0 , 1 ] [0, 1] [0,1],适合处理概率问题。
- tanh ( x ) \tanh(x) tanh(x) 的输出范围是 [ − 1 , 1 ] [-1, 1] [−1,1],更适合对称分布。
- 零中心化:
- Sigmoid 的输出非零中心化,会影响梯度更新效率。
- t a n h ( x ) tanh(x) tanh(x) 是零中心化的,对梯度更新更加友好。
- 速度:
- tanh ( x ) \tanh(x) tanh(x) 在神经网络中通常比 Sigmoid 收敛更快。
2.4 ( tanh ) (\tanh) (tanh) 的导数与梯度计算
( tanh ( x ) ) (\tanh(x)) (tanh(x)) 的导数公式为:
d d x tanh ( x ) = 1 − tanh 2 ( x ) \frac{d}{dx} \tanh(x) = 1 - \tanh^2(x) dxdtanh(x)=1−tanh2(x)
推导过程:
- 根据定义:
tanh ( x ) = e x − e − x e x + e − x \tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}} tanh(x)=ex+e−xex−e−x - 对其求导:
d d x tanh ( x ) = ( e x + e − x ) ⋅ ( e x − e − x ) ′ − ( e x − e − x ) ⋅ ( e x + e − x ) ′ ( e x + e − x ) 2 \frac{d}{dx} \tanh(x) = \frac{(e^x + e^{-x}) \cdot (e^x - e^{-x})' - (e^x - e^{-x}) \cdot (e^x + e^{-x})'}{(e^x + e^{-x})^2} dxdtanh(x)=(ex+e−x)2(ex+e−x)⋅(ex−e−x)′−(ex−e−x)⋅(ex+e−x)′ - 简化后得:
d d x tanh ( x ) = 4 ( e x + e − x ) 2 = 1 − tanh 2 ( x ) \frac{d}{dx} \tanh(x) = \frac{4}{(e^x + e^{-x})^2} = 1 - \tanh^2(x) dxdtanh(x)=(ex+e−x)24=1−tanh2(x)
梯度特性:
- 当 tanh ( x ) \tanh(x) tanh(x) 接近 ± 1 \pm 1 ±1 时, t a n h ′ ( x ) tanh'(x) tanh′(x) 会趋近于 0,可能引发梯度消失问题。
- 当 x x x 在 [ − 1 , 1 ] [-1, 1] [−1,1] 内时,梯度值较大,有助于高效训练。
3. 为什么选择 t a n h tanh tanh
t a n h tanh tanh 函数作为一种经典的激活函数,凭借其独特的特性在深度学习中占有一席之地。它通过平滑的非线性变换和零中心化输出,为神经网络提供了强大的建模能力,尤其是在处理对称数据和时间序列问题时。
3.1 零中心化输出的优势
t a n h tanh tanh 的输出范围为 [ − 1 , 1 ] [-1, 1] [−1,1],并且是零中心化的。这一特性为神经网络的训练带来了多方面的优势:
-
权重更新更高效:
- 零中心化意味着正负输出值的对称性,这让权重的正负变化更加平衡,避免了像 Sigmoid 那样总是向一个方向偏移。
- 梯度更新时不容易产生偏移,从而加快收敛速度。
-
适合对称分布的数据:
- 如果输入数据经过标准化(均值为 0), t a n h tanh tanh 的输出能更好地保持对称性,从而与数据的分布更加匹配。
-
减小梯度爆炸风险:
- 零中心化输出有助于稳定梯度传播,避免因输出值过于偏向正值或负值而导致的梯度爆炸问题。
3.2 非线性特性如何提升神经网络表现
激活函数的非线性是神经网络能够拟合复杂关系的关键, t a n h tanh tanh 的非线性特性在以下方面提升了网络的表现:
-
引入非线性能力:
- 如果没有激活函数,神经网络的每一层只能执行线性运算(矩阵乘法和加法),即便网络很深,最终的输出仍是线性变换,无法解决复杂的非线性问题。
- t a n h tanh tanh 将输入数据通过非线性映射变换为 [ − 1 , 1 ] [-1, 1] [−1,1],使网络能够学习复杂的特征模式。
-
对中间特征的放大与压缩:
- 在 [ − 2 , 2 ] [-2, 2] [−2,2] 的输入范围内, t a n h tanh tanh 对输入值的变化较为敏感,能放大特征差异,从而更好地捕捉细节信息。
- 对于极值输入(非常大或非常小的值), t a n h tanh tanh 将输出压缩到接近 ( − 1 ) (-1) (−1) 或 ( 1 ) (1) (1),起到了正则化的作用,避免过拟合。
-
平滑的梯度变化:
- t a n h tanh tanh 是一个平滑的函数,其导数在大多数区间内都较为稳定。这让网络能够更平稳地调整权重,尤其是在处理非平滑输入时。
3.3 t a n h tanh tanh 的适用场景
t a n h tanh tanh 的特性使其在以下场景中表现尤为突出:
-
循环神经网络(RNN):
- 在时间序列任务中,RNN 使用隐藏状态来捕捉时间上的依赖关系, t a n h tanh tanh 常用于隐藏状态的激活函数。
- LSTM 和 GRU 等变体中, t a n h tanh tanh 用于候选状态的更新,帮助模型捕捉非线性时间依赖。
-
对称分布的回归问题:
- 如果输出目标在 [ − 1 , 1 ] [-1, 1] [−1,1] 范围内, t a n h tanh tanh 是一个很好的激活函数选择。例如,用于归一化后的数据预测。
-
情感分析任务:
- 在 NLP 任务中,情感分布通常具有对称性(如正向情感与负向情感), t a n h tanh tanh 的零中心化输出能很好地反映这一特点。
-
中小规模神经网络:
- 在浅层网络或隐藏层较少的模型中, t a n h tanh tanh提供了足够的非线性能力和梯度稳定性。
-
特定场景下的对比分析:
- 例如,在对比两个输入的相似性时, t a n h tanh tanh 函数的对称性有助于捕捉输入特征的相对关系。
4. t a n h tanh tanh 在深度学习中的应用
双曲正切函数 t a n h tanh tanh因其零中心化的输出和非线性特性,在深度学习中得到了广泛应用。虽然近几年 ReLU 函数占据主导地位,但 t a n h tanh tanh 仍然在一些特定场景和模型中表现突出,尤其是在时间序列建模、循环神经网络(RNN)以及对称性任务中。
4.1 经典应用:循环神经网络(RNN)
在循环神经网络(RNN)中,(\tanh) 是隐藏层的默认激活函数。
RNN 通过隐藏状态捕捉序列数据中的时间依赖性, t a n h tanh tanh 在状态更新中起到关键作用。
隐藏状态更新公式:
h t = tanh ( W ⋅ x t + U ⋅ h t − 1 + b ) h_t = \tanh(W \cdot x_t + U \cdot h_{t-1} + b) ht=tanh(W⋅xt+U⋅ht−1+b)
- t a n h tanh tanh 的作用是对加权求和的结果进行非线性变换,平滑输出,并将其限制在 [ − 1 , 1 ] [-1, 1] [−1,1] 的范围内。
- 零中心化输出使得梯度更新更加平稳,从而在序列数据(如时间序列、语音信号)处理中表现良好。
4.2 在 LSTM 和 GRU 中的作用
LSTM(长短时记忆网络)和 GRU(门控循环单元)是 RNN 的改进版本,它们解决了标准 RNN 的梯度消失问题, t a n h tanh tanh 在这些模型中依然扮演重要角色。
-
LSTM 中的 (\tanh) 应用:
- t a n h tanh tanh 用于计算候选隐藏状态 h ~ t \tilde{h}_t h~t:
h ~ t = tanh ( W h ⋅ x t + U h ⋅ h t − 1 + b h ) \tilde{h}_t = \tanh(W_h \cdot x_t + U_h \cdot h_{t-1} + b_h) h~t=tanh(Wh⋅xt+Uh⋅ht−1+bh) - t a n h tanh tanh 的平滑输出帮助 LSTM 在记忆与遗忘之间进行动态平衡。
- t a n h tanh tanh 用于计算候选隐藏状态 h ~ t \tilde{h}_t h~t:
-
GRU 中的 (\tanh) 应用:
- GRU 的更新公式中,(\tanh) 被用来生成新隐藏状态:
h t = ( 1 − z t ) ⋅ h t − 1 + z t ⋅ tanh ( W ⋅ x t + U ⋅ ( r t ⋅ h t − 1 ) + b ) h_t = (1 - z_t) \cdot h_{t-1} + z_t \cdot \tanh(W \cdot x_t + U \cdot (r_t \cdot h_{t-1}) + b) ht=(1−zt)⋅ht−1+zt⋅tanh(W⋅xt+U⋅(rt⋅ht−1)+b) - t a n h tanh tanh 的非线性能力增强了模型的表达力,使其能够捕捉复杂的时间序列模式。
- GRU 的更新公式中,(\tanh) 被用来生成新隐藏状态:
4.3 自然语言处理(NLP)中的应用
在 NLP 任务中, t a n h tanh tanh 经常用于捕捉语义和情感信息:
-
情感分析:
- 由于情感数据通常具有对称性(正面情感与负面情感), t a n h tanh tanh 的零中心化输出可以很好地表达这种特性。
- 示例:在分类模型中, t a n h tanh tanh 用于隐藏层处理输入特征,例如句子嵌入。
-
句子匹配与相似度计算:
- 例如,在问答系统或文本匹配任务中, t a n h tanh tanh 可用于构造两个句子向量的相似度度量。
-
语言生成任务:
- 在生成任务中, t a n h tanh tanh 能帮助模型平滑输出,避免产生过于离散或不连贯的文本。
4.4 回归与对称性任务
对于某些对称分布的回归任务, t a n h tanh tanh 是隐藏层的良好选择。例如:
-
时间序列预测:
- (\tanh) 的平滑输出特性适合预测连续时间序列值,尤其是归一化后的目标值。
-
信号处理:
- 在音频信号处理或物理系统建模中, t a n h tanh tanh 常用于对对称性数据进行非线性建模。
4.5 其他场景中的应用
-
生成对抗网络(GAN):
- 在生成器或判别器中, t a n h tanh tanh 有时用于平滑输出,限制输出范围。
-
深层自动编码器(Deep Autoencoders):
- t a n h tanh tanh 可以作为隐藏层的激活函数,用于捕捉输入数据的非线性特征。
-
迁移学习与小规模模型:
- 在浅层网络或小规模模型中, t a n h tanh tanh 提供了足够的非线性能力,同时相较于 ReLU 减少了参数爆炸的风险。
5. t a n h tanh tanh 的优缺点
双曲正切函数 t a n h tanh tanh作为一种经典的激活函数,在深度学习的早期阶段得到了广泛应用。它具有独特的零中心化特性和非线性映射能力,但也存在一些局限性。以下将对 t a n h tanh tanh 的优缺点进行详细分析。
5.1 优点
-
零中心化输出
t a n h tanh tanh 的输出范围为 [ − 1 , 1 ] [-1, 1] [−1,1],且零中心化(输出可以为正或负)。- 优势:
- 零中心化可以避免激活值总是偏向某个方向,有利于权重的平衡更新。
- 相较于 Sigmoid(输出范围为 [ 0 , 1 ] [0, 1] [0,1]), t a n h tanh tanh 更适合数据对称分布的场景。
- 优势:
-
非线性特性
- t a n h tanh tanh 引入非线性,使神经网络能够学习和拟合复杂的非线性关系。
- 它在中间区域(接近 [ − 2 , 2 ] [-2, 2] [−2,2])对输入变化敏感,可以更好地捕捉特征差异。
-
输出范围适中
- t a n h tanh tanh 将输入限制在 [ − 1 , 1 ] [-1, 1] [−1,1] 范围内,这在某些需要归一化输出的任务中非常有用,例如 RNN 和回归任务。
-
适合对称性任务
- 在处理对称数据(如情感分析、图像对称特征)时, t a n h tanh tanh 的对称性输出能够更好地表达特征。
-
梯度平滑
- t a n h tanh tanh 是一个平滑函数,其导数为 ( 1 − tanh 2 ( x ) ) (1 - \tanh^2(x)) (1−tanh2(x)),在输入范围内梯度变化较为平稳,适合于小型网络或浅层网络。
5.2 缺点
-
梯度消失问题
- 现象:
- 当输入值 x x x 较大或较小时, t a n h ( x ) tanh(x) tanh(x) 的输出接近 ( − 1 ) (-1) (−1) 或 ( 1 ) (1) (1),这时其导数趋近于 0。
- 梯度传播过程中,权重的更新会变得极其缓慢,尤其是在深层网络中,这一问题更加明显。
- 影响:
- 导致深层网络无法有效训练。
- 梯度消失问题是 t a n h tanh tanh 在深度学习中逐渐被 ReLU 替代的主要原因。
- 现象:
-
计算复杂度较高
- t a n h ( x ) tanh(x) tanh(x) 的计算涉及指数运算 e x e^x ex和 e − x e^{-x} e−x,相比 ReLU(简单的 m a x ( 0 , x ) max(0, x) max(0,x) 运算),计算成本更高,尤其在大型模型中可能成为瓶颈。
-
对极端值的敏感性较低
- 在输入值较大的情况下, t a n h ( x ) tanh(x) tanh(x) 的输出趋于饱和,梯度几乎为 0,这意味着网络对这些极端值的输入几乎失去了学习能力。
-
不适合深层网络
- 在深层神经网络中,由于梯度消失问题, t a n h tanh tanh 会导致模型收敛速度变慢,甚至可能无法训练。因此,在现代深层网络(如 CNN)中很少使用 t a n h tanh tanh。
5.3 总结对比
优点 | 缺点 |
---|---|
输出范围 [ − 1 , 1 ] [-1, 1] [−1,1],零中心化 | 梯度消失问题严重,尤其是深层网络 |
非线性映射能力强 | 计算复杂度高 |
输出平滑且范围适中 | 对极端值输入不敏感,导致学习能力下降 |
适合对称性任务 | 不适合深层网络的训练,效率较低 |
适用场景
尽管存在梯度消失问题, t a n h tanh tanh 在以下场景中仍然是一个不错的选择:
- 浅层网络:
- 网络深度较小、隐藏层较少的情况下, t a n h tanh tanh 的优点能得到充分发挥。
- 对称性任务:
- 在数据分布或任务目标具有对称性时(如情感分析), t a n h tanh tanh 的零中心化输出非常有帮助。
- 时间序列建模:
- t a n h tanh tanh 在 RNN、LSTM 和 GRU 中用于捕捉时间序列中的非线性关系。
- 归一化输出的需求:
- 当任务需要对隐藏层输出进行归一化(范围在 [ − 1 , 1 ] [-1, 1] [−1,1])时, t a n h tanh tanh 是自然的选择。
6. 实践:如何在深度学习框架中使用 t a n h tanh tanh
在深度学习框架中,如 TensorFlow 和 PyTorch, t a n h tanh tanh 是一个内置的激活函数,使用起来非常简单。以下内容将介绍如何在实际应用中使用 t a n h tanh tanh,包括代码示例和常见场景。
6.1 TensorFlow 中使用 t a n h tanh tanh
TensorFlow 提供了 t a n h tanh tanh 激活函数,可以直接在模型定义中调用。
1) 基本用法
import tensorflow as tf# 示例:定义一个简单的全连接层使用 tanh 激活函数
model = tf.keras.Sequential([tf.keras.layers.Dense(64, activation='tanh', input_shape=(100,)),tf.keras.layers.Dense(10, activation='softmax') # 输出层
])# 编译模型
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])# 模拟数据
import numpy as np
X = np.random.random((1000, 100)) # 输入数据
y = np.random.randint(0, 10, size=(1000,)) # 类别标签# 转换标签为 one-hot 编码
y_one_hot = tf.keras.utils.to_categorical(y, num_classes=10)# 训练模型
model.fit(X, y_one_hot, epochs=10, batch_size=32)
2) 自定义使用 t a n h tanh tanh
你也可以通过 TensorFlow 提供的数学函数直接使用 (\tanh):
# 自定义激活函数
def custom_tanh(x):return tf.math.tanh(x)# 使用自定义 tanh 激活函数
model = tf.keras.Sequential([tf.keras.layers.Dense(64, activation=custom_tanh, input_shape=(100,)),tf.keras.layers.Dense(10, activation='softmax')
])
6.2 PyTorch 中使用 t a n h tanh tanh
在 PyTorch 中, t a n h tanh tanh 是 torch.nn
模块的内置激活函数,使用起来也非常方便。
1) 基本用法
import torch
import torch.nn as nn
import torch.optim as optim# 定义一个简单的网络
class SimpleModel(nn.Module):def __init__(self):super(SimpleModel, self).__init__()self.fc1 = nn.Linear(100, 64) # 全连接层self.tanh = nn.Tanh() # tanh 激活函数self.fc2 = nn.Linear(64, 10) # 输出层def forward(self, x):x = self.tanh(self.fc1(x))x = self.fc2(x)return x# 创建模型
model = SimpleModel()# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)# 模拟数据
X = torch.rand(1000, 100) # 输入数据
y = torch.randint(0, 10, (1000,)) # 类别标签# 训练模型
for epoch in range(10):optimizer.zero_grad()outputs = model(X)loss = criterion(outputs, y)loss.backward()optimizer.step()print(f'Epoch [{epoch+1}/10], Loss: {loss.item():.4f}')
2) 自定义使用 t a n h tanh tanh
在 PyTorch 中,也可以直接使用 torch.tanh
函数来自定义逻辑:
# 自定义激活函数
def custom_tanh(x):return torch.tanh(x)# 在网络中使用自定义 tanh
class CustomModel(nn.Module):def __init__(self):super(CustomModel, self).__init__()self.fc1 = nn.Linear(100, 64)self.fc2 = nn.Linear(64, 10)def forward(self, x):x = custom_tanh(self.fc1(x))x = self.fc2(x)return x
6.3 t a n h tanh tanh 在 RNN/LSTM 中的使用
在处理时间序列或自然语言处理任务时, t a n h tanh tanh 是 RNN 和 LSTM 中的重要组成部分。
1) TensorFlow 示例
# 使用 LSTM,内部自动使用 tanh 激活函数
model = tf.keras.Sequential([tf.keras.layers.LSTM(64, activation='tanh', input_shape=(10, 50)),tf.keras.layers.Dense(10, activation='softmax')
])
2) PyTorch 示例
# PyTorch 中的 LSTM 自动使用 tanh
rnn = nn.LSTM(input_size=50, hidden_size=64, num_layers=1, batch_first=True)# 模拟输入数据
X = torch.rand(32, 10, 50) # Batch size = 32, Sequence length = 10, Input size = 50
output, (hn, cn) = rnn(X)
print(output.shape) # 输出维度
6.4 t a n h tanh tanh 在自定义任务中的应用
如果需要手动实现 t a n h tanh tanh 激活函数,可以通过以下方式:
TensorFlow 自定义实现 t a n h tanh tanh
# 实现 tanh 函数
def custom_tanh(x):return (tf.exp(x) - tf.exp(-x)) / (tf.exp(x) + tf.exp(-x))# 使用自定义实现
x = tf.constant([[1.0, -1.0], [0.5, -0.5]])
y = custom_tanh(x)
print(y.numpy())
PyTorch 自定义实现 t a n h tanh tanh
# 实现 tanh 函数
def custom_tanh(x):return (torch.exp(x) - torch.exp(-x)) / (torch.exp(x) + torch.exp(-x))# 使用自定义实现
x = torch.tensor([[1.0, -1.0], [0.5, -0.5]])
y = custom_tanh(x)
print(y)
6.5 实践建议
- 框架内置函数:对于大多数深度学习任务,直接使用 TensorFlow 或 PyTorch 提供的内置 t a n h tanh tanh 激活函数即可,无需手动实现。
- 适用场景:
- RNN、LSTM、GRU 等模型中, t a n h tanh tanh 是默认激活函数。
- 对称性数据或零中心化数据场景,可以考虑使用 t a n h tanh tanh。
- 替代方案:如果训练较深的网络且存在梯度消失问题,可以尝试使用 ReLU 或其变体作为激活函数。
通过这些示例,您可以在实际深度学习任务中轻松地将 t a n h tanh tanh 应用到模型中!
7. 对比分析: t a n h tanh tanh 与其他激活函数
激活函数是深度学习的核心组件,不同的激活函数有各自的优缺点和适用场景。以下从数学特性、优缺点和应用场景等方面对 t a n h tanh tanh 与其他常见激活函数(Sigmoid、ReLU、Leaky ReLU、Swish)进行对比分析。
7.1 t a n h tanh tanh 与 Sigmoid 的对比
特性 | t a n h tanh tanh | Sigmoid |
---|---|---|
数学公式 | t a n h ( x ) = e x − e − x e x + e − x tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}} tanh(x)=ex+e−xex−e−x | σ ( x ) = 1 1 + e − x \sigma(x) = \frac{1}{1 + e^{-x}} σ(x)=1+e−x1 |
输出范围 | [ − 1 , 1 ] [-1, 1] [−1,1] | [ 0 , 1 ] [0, 1] [0,1] |
零中心化 | 是 | 否 |
梯度消失问题 | 存在 | 更严重 |
计算复杂度 | 高 | 高 |
适用场景 | 对称性数据、隐藏层激活 | 输出概率值(二分类任务) |
总结
- t a n h tanh tanh 在隐藏层中表现优于 Sigmoid,主要因为它是零中心化的,权重更新更加平衡。
- Sigmoid 更适合用在输出层,特别是二分类任务中,可以直接输出概率值。
7.2 t a n h tanh tanh 与 ReLU 的对比
特性 | t a n h tanh tanh | ReLU |
---|---|---|
数学公式 | t a n h ( x ) = e x − e − x e x + e − x tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}} tanh(x)=ex+e−xex−e−x | f ( x ) = max ( 0 , x ) f(x) = \max(0, x) f(x)=max(0,x) |
输出范围 | [ − 1 , 1 ] [-1, 1] [−1,1] | [ 0 , ∞ ) [0, \infty) [0,∞) |
零中心化 | 是 | 否 |
梯度消失问题 | 存在 | 不存在 |
计算复杂度 | 高 | 低 |
额外问题 | 无 | 可能有“神经元死亡”问题 |
适用场景 | 浅层网络、对称数据 | 深层网络(如 CNN、Transformer) |
总结
- ReLU 的优势:梯度传播稳定,计算简单,是深度神经网络的主流激活函数。
- t a n h tanh tanh 的优势:适合对称性任务,输出零中心化。对于较浅的网络或者对称分布数据,(\tanh) 的表现更好。
7.3 t a n h tanh tanh 与 Leaky ReLU 的对比
特性 | t a n h tanh tanh | Leaky ReLU |
---|---|---|
数学公式 | a n h ( x ) = e x − e − x e x + e − x anh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}} anh(x)=ex+e−xex−e−x | ( f ( x ) = max ( 0 , x ) + α ⋅ min ( 0 , x ) (f(x) = \max(0, x) + \alpha \cdot \min(0, x) (f(x)=max(0,x)+α⋅min(0,x) |
输出范围 | [ − 1 , 1 ] [-1, 1] [−1,1] | ( − ∞ , ∞ ) (-\infty, \infty) (−∞,∞) |
零中心化 | 是 | 否 |
梯度消失问题 | 存在 | 不存在 |
神经元死亡问题 | 无 | 无(通过负斜率 (\alpha) 解决) |
计算复杂度 | 高 | 低 |
适用场景 | 对称性任务 | 深层网络,尤其是梯度稀疏或负值较多的场景 |
总结
- Leaky ReLU 解决了标准 ReLU 的“神经元死亡”问题,更适合深层网络。
- t a n h tanh tanh 适合对称性数据,但在深层网络中性能可能不如 Leaky ReLU。
7.4 t a n h tanh tanh 与 Swish 的对比
特性 | t a n h tanh tanh | Swish |
---|---|---|
数学公式 | t a n h ( x ) = e x − e − x e x + e − x tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}} tanh(x)=ex+e−xex−e−x | f ( x ) = x ⋅ σ ( x ) f(x) = x \cdot \sigma(x) f(x)=x⋅σ(x) |
输出范围 | [ − 1 , 1 ] [-1, 1] [−1,1] | ( − ∞ , ∞ ) (-\infty, \infty) (−∞,∞) |
零中心化 | 是 | 否 |
梯度消失问题 | 存在 | 极少 |
计算复杂度 | 高 | 较高(包含 Sigmoid 运算) |
适用场景 | 对称性任务 | 深层网络,尤其是需要更强非线性能力的场景 |
总结
- Swish 是近年来提出的新型激活函数,在深层网络中表现更佳,尤其是在 Transformer 等复杂模型中。
- 相较于 Swish, t a n h tanh tanh 的应用更经典,但在现代深层网络中逐渐被替代。
7.5 总结对比表
激活函数 | 输出范围 | 零中心化 | 梯度消失问题 | 计算复杂度 | 适用场景 |
---|---|---|---|---|---|
t a n h tanh tanh | [ − 1 , 1 ] [-1, 1] [−1,1] | 是 | 存在 | 高 | 对称性任务、浅层网络 |
Sigmoid | [ 0 , 1 ] [0, 1] [0,1] | 否 | 更严重 | 高 | 二分类问题的输出层 |
ReLU | [ 0 , ∞ ) [0, \infty) [0,∞) | 否 | 无 | 低 | 深层网络(如 CNN) |
Leaky ReLU | ( − ∞ , ∞ ) (-\infty, \infty) (−∞,∞) | 否 | 无 | 低 | 深层网络,负值较多的场景 |
Swish | ( − ∞ , ∞ ) (-\infty, \infty) (−∞,∞) | 否 | 极少 | 较高 | 深层网络(如 Transformer) |
7.6 选择建议
-
使用 t a n h tanh tanh 的场景:
- 数据分布对称,输出需要在 [ − 1 , 1 ] [-1, 1] [−1,1] 范围内。
- 小型或浅层神经网络,例如 RNN 的隐藏层。
- 需要零中心化输出的场景。
-
替代方案:
- 如果存在梯度消失问题或计算资源有限,推荐使用 ReLU 或其变体(如 Leaky ReLU)。
- 在深层网络中,Swish 或 GELU(Gaussian Error Linear Unit)可能更适合。
通过对比分析可以看出, t a n h tanh tanh 仍然适合特定场景,但在现代深层网络中逐渐被 ReLU 和 Swish 替代。选择合适的激活函数,需要根据任务特点和模型复杂度综合考虑。
8. 实际场景: t a n h tanh tanh 在应用中的案例
尽管近年来 ReLU 和其变体成为主流激活函数, t a n h tanh tanh 函数仍在某些实际应用中扮演重要角色。以下列举几个典型场景,说明 t a n h tanh tanh 的独特优势和应用方式。
8.1 时间序列预测
场景描述:
时间序列数据(如天气、股票价格、传感器数据)通常具有非线性关系和长时间依赖性。由于 t a n h tanh tanh 的平滑性和零中心化输出特性,它在 RNN 和 LSTM 中是处理时间序列的核心激活函数。
应用案例:
预测未来几天的天气温度变化。
实现示例(使用 LSTM):
import tensorflow as tf
import numpy as np# 模拟时间序列数据
X = np.random.random((100, 10, 1)) # 100 条样本,每条样本有 10 个时间步,每步一个特征
y = np.random.random((100, 1)) # 对应的目标值# 定义模型
model = tf.keras.Sequential([tf.keras.layers.LSTM(64, activation='tanh', input_shape=(10, 1)),tf.keras.layers.Dense(1) # 输出预测值
])# 编译模型
model.compile(optimizer='adam', loss='mse')# 训练模型
model.fit(X, y, epochs=10, batch_size=16)
t a n h tanh tanh 的作用:
- 平滑激活输出,限制范围在 [ − 1 , 1 ] [-1, 1] [−1,1],避免数值不稳定。
- 零中心化输出有助于捕捉时间序列中的正负变化趋势。
8.2 自然语言处理(NLP)
场景描述:
在 NLP 任务(如情感分析、翻译、文本生成)中,(\tanh) 是许多经典模型(如 RNN、GRU、LSTM)的核心组件,用于捕捉上下文关系和语义特征。
应用案例:
进行情感分析,预测用户评论是正面还是负面。
实现示例(使用 RNN):
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding, SimpleRNN, Dense# 模拟数据
vocab_size = 5000 # 词汇表大小
max_len = 100 # 最大序列长度
X = np.random.randint(1, vocab_size, size=(2000, max_len)) # 输入序列
y = np.random.randint(0, 2, size=(2000,)) # 二分类标签# 定义模型
model = Sequential([Embedding(input_dim=vocab_size, output_dim=64, input_length=max_len),SimpleRNN(128, activation='tanh'),Dense(1, activation='sigmoid') # 输出正负情感概率
])# 编译模型
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])# 训练模型
model.fit(X, y, epochs=5, batch_size=32)
t a n h tanh tanh 的作用:
- 捕捉文本序列中的上下文依赖关系。
- 平滑处理语义特征,特别适合情感分析等对称性任务。
8.3 图像对比度增强
场景描述:
在图像处理任务中, t a n h tanh tanh 常用于归一化和对比度调整。其输出范围( [ − 1 , 1 ] [-1, 1] [−1,1])有助于限制像素值,增强图像细节。
应用案例:
增强医学图像的对比度,以便医生更清晰地观察病灶。
实现示例(归一化图像像素值):
import numpy as np# 模拟灰度图像
image = np.random.random((256, 256)) * 255 # 灰度范围 [0, 255]# 使用 tanh 归一化
def normalize_image(image):normalized = np.tanh(image / 255.0 - 0.5) # 归一化到 [-1, 1]return normalizednormalized_image = normalize_image(image)
t a n h tanh tanh 的作用:
- 将像素值映射到 [ − 1 , 1 ] [-1, 1] [−1,1],便于进一步处理。
- 平滑调整对比度,避免过度增强。
8.4 对称性任务
场景描述:
在需要处理对称分布数据的任务中(如物理模拟、情感分类), t a n h tanh tanh 的零中心化输出特性可以很好地反映数据的对称性。
应用案例:
模拟物理系统中正负力的相互作用。
实现示例:
import torch
import torch.nn as nn# 模拟输入
x = torch.tensor([[1.0, -1.0], [0.5, -0.5]])# 使用 tanh 激活函数
tanh = nn.Tanh()
output = tanh(x)
print(output)
t a n h tanh tanh 的作用:
- 捕捉正负值之间的对称关系。
- 输出范围适中,避免数值爆炸。
8.5 自动编码器(Autoencoder)
场景描述:
在自动编码器中, t a n h tanh tanh 常用于隐藏层激活函数,帮助捕捉输入数据的非线性结构。
应用案例:
对高维图像数据进行降维压缩。
实现示例(简单自动编码器):
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dense# 输入数据
input_dim = 784 # 假设输入是 28x28 的图像
input_layer = Input(shape=(input_dim,))# 编码器
encoded = Dense(128, activation='tanh')(input_layer)
encoded = Dense(64, activation='tanh')(encoded)# 解码器
decoded = Dense(128, activation='tanh')(encoded)
output_layer = Dense(input_dim, activation='sigmoid')(decoded)# 定义模型
autoencoder = Model(input_layer, output_layer)# 编译模型
autoencoder.compile(optimizer='adam', loss='mse')# 模拟数据
X = np.random.random((1000, 784)) # 输入图像数据
autoencoder.fit(X, X, epochs=10, batch_size=32)
t a n h tanh tanh 的作用:
- 限制隐藏层的输出范围,避免解码器产生不合理的值。
- 平滑降维过程,提高模型对输入数据的重构能力。
9. 结论
双曲正切函数 t a n h tanh tanh作为一种经典的激活函数,在深度学习的早期阶段发挥了重要作用。尽管随着深度网络的发展, t a n h tanh tanh 在某些场景中逐渐被 ReLU 和其他变体所取代,但它的独特特性使得它在特定任务中依然表现出色。
核心特性回顾
- 零中心化输出: t a n h tanh tanh 的输出范围为 [ − 1 , 1 ] [-1, 1] [−1,1],并且是零中心化的。这使得权重更新更加平衡,适合对称性数据和时间序列任务。
- 非线性映射能力: t a n h tanh tanh 能够引入非线性特性,使神经网络能够学习复杂的数据模式和关系。
- 平滑的梯度变化:在中间输入范围内 [ − 2 , 2 ] [-2, 2] [−2,2], t a n h tanh tanh 的梯度较大且稳定,有助于提高训练效率。
适用场景
- 时间序列建模:如天气预测、股票价格分析等场景, t a n h tanh tanh 在 RNN 和 LSTM 中表现优异。
- 自然语言处理:适用于情感分析、翻译等需要捕捉上下文关系的任务。
- 对称性任务:例如物理模拟、情感分类等,对称分布的数据特别适合使用 t a n h tanh tanh。
- 图像处理:用于像素归一化、对比度增强等图像预处理任务。
- 浅层网络:在隐藏层较少的网络中, t a n h tanh tanh 的非线性能力能够充分发挥。
优缺点总结
-
优点:
- 零中心化输出,适合对称数据。
- 输出范围限制,避免过大值影响训练稳定性。
- 平滑性强,适合连续性数据的特征学习。
-
缺点:
- 梯度消失问题:对于深层网络,极值输入导致梯度趋于 0,从而影响模型的训练效率。
- 计算复杂度较高:相比 ReLU, t a n h tanh tanh 涉及指数计算,速度略慢。
- 不适合非常深的网络,现代深度学习任务中逐渐被其他激活函数取代。
与其他激活函数的对比
t a n h tanh tanh 在浅层网络和特定任务中具有明显的优势,但在深层网络中,由于梯度消失问题,ReLU、Leaky ReLU 和 Swish 等激活函数表现更好。选择激活函数时,应根据任务特点、数据分布和模型深度综合考虑。
10. 附录
以下是本文相关内容的数学推导、代码示例和其他补充资料,为读者提供进一步学习和实践的基础。
10.1 数学推导
1) t a n h ( x ) tanh(x) tanh(x) 的公式推导
t a n h ( x ) tanh(x) tanh(x) 是双曲正切函数,其定义为:
tanh ( x ) = sinh ( x ) cosh ( x ) = e x − e − x e x + e − x \tanh(x) = \frac{\sinh(x)}{\cosh(x)} = \frac{e^x - e^{-x}}{e^x + e^{-x}} tanh(x)=cosh(x)sinh(x)=ex+e−xex−e−x
其中:
- s i n h ( x ) sinh(x) sinh(x)(双曲正弦函数): s i n h ( x ) = e x − e − x 2 sinh(x) = \frac{e^x - e^{-x}}{2} sinh(x)=2ex−e−x
- c o s h ( x ) cosh(x) cosh(x)(双曲余弦函数): c o s h ( x ) = e x + e − x 2 cosh(x) = \frac{e^x + e^{-x}}{2} cosh(x)=2ex+e−x
通过化简可得:
tanh ( x ) = e x − e − x 2 e x + e − x 2 = e x − e − x e x + e − x \tanh(x) = \frac{\frac{e^x - e^{-x}}{2}}{\frac{e^x + e^{-x}}{2}} = \frac{e^x - e^{-x}}{e^x + e^{-x}} tanh(x)=2ex+e−x2ex−e−x=ex+e−xex−e−x
2) t a n h ( x ) tanh(x) tanh(x) 的导数推导
t a n h ( x ) tanh(x) tanh(x) 的导数为:
d d x tanh ( x ) = 1 − tanh 2 ( x ) \frac{d}{dx} \tanh(x) = 1 - \tanh^2(x) dxdtanh(x)=1−tanh2(x)
推导过程:
- 根据定义:
tanh ( x ) = e x − e − x e x + e − x \tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}} tanh(x)=ex+e−xex−e−x - 对其求导:
d d x tanh ( x ) = ( e x + e − x ) ⋅ ( e x − e − x ) ′ − ( e x − e − x ) ⋅ ( e x + e − x ) ′ ( e x + e − x ) 2 \frac{d}{dx} \tanh(x) = \frac{(e^x + e^{-x}) \cdot (e^x - e^{-x})' - (e^x - e^{-x}) \cdot (e^x + e^{-x})'}{(e^x + e^{-x})^2} dxdtanh(x)=(ex+e−x)2(ex+e−x)⋅(ex−e−x)′−(ex−e−x)⋅(ex+e−x)′ - 化简后得:
d d x tanh ( x ) = 4 ( e x + e − x ) 2 = 1 − tanh 2 ( x ) \frac{d}{dx} \tanh(x) = \frac{4}{(e^x + e^{-x})^2} = 1 - \tanh^2(x) dxdtanh(x)=(ex+e−x)24=1−tanh2(x)
10.2 实现代码示例
1) 自定义 t a n h tanh tanh 激活函数
在深度学习框架中, t a n h tanh tanh 通常由框架提供,但也可以手动实现。
- TensorFlow 实现:
import tensorflow as tfdef custom_tanh(x):return (tf.exp(x) - tf.exp(-x)) / (tf.exp(x) + tf.exp(-x))x = tf.constant([1.0, -1.0, 0.5, -0.5])
y = custom_tanh(x)
print("Custom tanh output:", y.numpy())
- PyTorch 实现:
import torchdef custom_tanh(x):return (torch.exp(x) - torch.exp(-x)) / (torch.exp(x) + torch.exp(-x))x = torch.tensor([1.0, -1.0, 0.5, -0.5])
y = custom_tanh(x)
print("Custom tanh output:", y)
2) 自动编码器中的 (\tanh)
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dense# 定义输入层
input_dim = 784 # 假设输入是 28x28 的图像
input_layer = Input(shape=(input_dim,))# 编码器部分
encoded = Dense(128, activation='tanh')(input_layer)
encoded = Dense(64, activation='tanh')(encoded)# 解码器部分
decoded = Dense(128, activation='tanh')(encoded)
output_layer = Dense(input_dim, activation='sigmoid')(decoded)# 自动编码器模型
autoencoder = Model(input_layer, output_layer)# 编译并训练
autoencoder.compile(optimizer='adam', loss='mse')
10.3 t a n h tanh tanh 的常见问题与解决方法
-
梯度消失问题:
- 现象:输入值较大时, t a n h ( x ) tanh(x) tanh(x) 的导数接近 0,导致梯度传播时更新缓慢。
- 解决方案:
- 使用 ReLU 或其变体(Leaky ReLU、Swish)替代。
- 对输入数据进行标准化,限制输入范围。
-
计算复杂度:
- 现象: t a n h tanh tanh 的计算涉及指数运算,相比 ReLU 等激活函数速度较慢。
- 解决方案:对于大型网络,优先选择计算简单的激活函数(如 ReLU)。
10.4 t a n h tanh tanh 在现代深度学习中的角色
尽管 t a n h tanh tanh 在现代深层网络中逐渐被其他激活函数替代,但它在以下场景中仍有不可替代的作用:
- 时间序列建模:如 LSTM、GRU 等。
- 对称性任务:如情感分析、物理模拟。
- 图像归一化:处理像素值范围的归一化问题。
10.5 常用激活函数对比总结表
激活函数 | 数学公式 | 输出范围 | 零中心化 | 优点 | 缺点 | 典型应用 |
---|---|---|---|---|---|---|
t a n h tanh tanh | e x − e − x e x + e − x \frac{e^x - e^{-x}}{e^x + e^{-x}} ex+e−xex−e−x | [ − 1 , 1 ] [-1, 1] [−1,1] | 是 | 零中心化,适合对称数据 | 梯度消失,计算复杂 | RNN、对称任务 |
Sigmoid | 1 1 + e − x \frac{1}{1 + e^{-x}} 1+e−x1 | [ 0 , 1 ] [0, 1] [0,1] | 否 | 简单直观,用于输出概率 | 梯度消失,非零中心 | 二分类输出 |
ReLU | m a x ( 0 , x ) max(0, x) max(0,x) | [ 0 , ∞ ) [0, \infty) [0,∞) | 否 | 计算简单,解决梯度消失问题 | 可能导致神经元死亡 | 深层网络(CNN、Transformer) |
Leaky ReLU | x x x(正值)或 α x \alpha x αx(负值) | ( − ∞ , ∞ ) (-\infty, \infty) (−∞,∞) | 否 | 解决神经元死亡问题 | 零中心化问题仍存在 | 深层网络 |
Swish | x ⋅ σ ( x ) x \cdot \sigma(x) x⋅σ(x) | ( − ∞ , ∞ ) (-\infty, \infty) (−∞,∞) | 否 | 强大的非线性能力,梯度稳定 | 计算复杂 | 深层网络(如 Transformer) |
参考文献与资源
- 深度学习激活函数教程:https://www.deeplearningbook.org/
- TensorFlow 官方文档:https://www.tensorflow.org/
- PyTorch 官方文档:https://pytorch.org/
- 激活函数对比与发展:https://arxiv.org/abs/1710.05941
相关文章:
深度解析 tanh tanh 激活函数
1. 引言 在现代深度学习中,激活函数(Activation Function)是神经网络的核心组件之一。它的主要作用是引入非线性,从而使神经网络能够学习和表示复杂的非线性关系。如果没有激活函数,神经网络的输出将只是输入的线性组…...

嵌入式入门Day38
C Day1 第一个C程序C中的输入输出输出操作coutcin练习 命名空间使用方法自定义命名空间冲突问题 C对字符串的扩充C风格字符串的使用定义以及初始化C风格字符串与C风格字符串的转换C风格的字符串的关系运算常用的成员变量输入方法 布尔类型C对堆区空间使用的扩充作业 第一个C程序…...
探索Rancher服务发现机制:容器世界的“导航仪”
《探索Rancher服务发现机制:容器世界的“导航仪”》 在当今容器化技术蓬勃发展的时代,容器的大规模部署和微服务架构的广泛应用使得服务之间的相互发现与通信变得至关重要。Rancher作为一款功能强大的容器管理平台,其服务发现机制宛如一座无…...
【ROS2】Qt事件循环和ROS2订阅机制一起使用有什么注意事项?
1、简述 Qt的事件循环和ROS订阅回调函数都可能在阻塞函数中运行, 例如:Qt的QApplication::exec() 和 ROS的rclcpp::spin() 两个阻塞函数不能在同一个线程中使用,如果使用不当,会造成Qt不处理事件或者ROS2不处理订阅的回调函数。 2、多线程 一般 QApplication::exec() 运…...

donet (MVC)webAPI 的接受json 的操作
直接用对象来进行接收,这个方法还不错的。 public class BangdingWeiguiJiluController : ApiController{/// <summary>/// Json数据录入错误信息/// </summary>/// <param name"WeiguiInfos"></param>/// <returns></r…...
Qt 界面外观
一、前言 1、 一个完善的应用程序,不仅应该有实用的功能,还要有一个漂亮的外观,这样才能使应用程序更加友好,更加吸引用户。 2、 作为一个跨平台的UI开发框架,Qt提供了强大而灵活的界面外观设计机制。 3、 本篇会讲解&…...

aws(学习笔记第二十二课) 复杂的lambda应用程序(python zip打包)
aws(学习笔记第二十二课) 开发复杂的lambda应用程序(python的zip包) 学习内容: 练习使用CloudShell开发复杂lambda应用程序(python) 1. 练习使用CloudShell CloudShell使用背景 复杂的python的lambda程序会有许多依赖的包,如果不提前准备好这些python的…...
HTML课堂之搜索工具箱/讲师duluo
目录: 源码在最后 小提示: 1.养成打卡习惯没日多加练习即可提什能力 2.源码在最后,请先看完代码讲解,在尝试自己写,这样容易掌握 3.请勿复制粘贴,因为你没掌握,即使复制粘贴也学不会 课堂重点笔…...

当歌 - RSS 订阅分发平台开发
以下将详细介绍当歌平台的技术架构、功能实现以及相关代码逻辑。 一、项目概述 当歌是一个极简的 RSS 订阅分发平台,旨在为用户提供便捷的 RSS 管理和订阅服务,帮助用户轻松获取和分享最新资讯。 二、技术架构 后端语言:PHP 数据库&#…...

学习threejs,导入wrl格式的模型
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.VRMLLoader wrl模型加…...

使用GitLab+Jenkins搭建CICD执行环境
使用GitLabJenkins搭建CI\CD执行环境 前言什么是DevOps?什么是CI/CD?使用GitLabJenkins搭建CI\CD执行环境GitLab安装1. 安装和配置所需的依赖2. 下载并安装极狐GitLab3. 登录极狐GitLab 实例4.常用gitlab指令5.修改密码 Jenkins安装1.Jenkins 的主要特点…...
使用vue-pdf预览pdf和解决pdf电子签章显示问题
使用vue-pdf预览pdf和解决pdf电子签章显示问题 第一步:npm install vue-pdf 第二步页面使用vue-pdf <template><div class"pdf1"><Pdf v-for"i in numPages" :key"i" :src"src" :page"i" />…...

【Rust自学】11.3. 自定义错误信息
喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 11.3.1. 添加错误信息 在 11.2. 断言(Assert) 中我们学习了assert!、assert_eq!和assert_ne!这三个宏,而这篇文章讲的就是它…...
05、Docker学习,常用安装:Mysql、Redis、Nginx、Nacos
Docker学习,常用安装:Mysql、Redis、Nginx、Nacos 一、Docker安装Mysql 1、docker search mysql ##查找mysql版本都有哪些 2、docker pull mysql:5.6 ##下载5.6版本的mysql镜像 3、docker run -p 13306:3306 --name mysql ##运行…...

RabbitMQ高级篇之MQ可靠性 数据持久化
文章目录 消息丢失的原因分析内存存储的缺陷如何确保 RabbitMQ 的消息可靠性?数据持久化的三个方面持久化对性能的影响持久化实验验证性能对比Spring AMQP 默认持久化总结 消息丢失的原因分析 RabbitMQ 默认使用内存存储消息,但这种方式带来了两个主要问…...
leetcode 2274. 不含特殊楼层的最大连续楼层数 中等
Alice 管理着一家公司,并租用大楼的部分楼层作为办公空间。Alice 决定将一些楼层作为 特殊楼层 ,仅用于放松。 给你两个整数 bottom 和 top ,表示 Alice 租用了从 bottom 到 top(含 bottom 和 top 在内)的所有楼层。另…...

Tauri教程-基础篇-第二节 Tauri的核心概念上篇
“如果结果不如你所愿,就在尘埃落定前奋力一搏。”——《夏目友人帐》 “有些事不是看到了希望才去坚持,而是因为坚持才会看到希望。”——《十宗罪》 “维持现状意味着空耗你的努力和生命。”——纪伯伦 Tauri 技术教程 * 第四章 Tauri的基础教程 第二节…...
大风车excel:怎么把题库导入excel?题库导入excel
高效管理试题库:如何批量导入试题到 Excel? 在教育培训、学校管理以及在线学习平台中,试题库的管理是核心工作之一。如何快速、准确地将试题导入到 Excel 表格中,成为许多教育工作者和开发者的迫切需求。本文将围绕“题库导入 Ex…...

Java 兼容读取WPS和Office图片,结合EasyExcel读取单元格信息
在Java开发中,处理Excel文件中的图片(包括浮动图片和嵌入图片)是一个常见的需求。本文将介绍如何使用EasyExcel和Apache POI库来读取Excel文件中的图片,并将其与数据进行关联。 1. 引言 在许多应用场景中,Excel文件不…...

电脑硬盘系统迁移及问题处理
一、系统迁移准备 1、确认你的电脑主板是否支持安装两块硬盘,如电脑主板有多个M2硬盘接口,我们将新硬盘安装到主板上,原来的老硬盘安装在第二个接口上,主板只有一个M2接口的话可以使用移动硬盘盒。 2、新硬盘安装好后,我们进入原来的系统,在 此电脑–右键–管理–磁盘管…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...

LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...