引自免费微信小程序:皆我百晓生
要构建一个具有sigmoid激活函数的神经网络,使其输出与输入的tanh函数相匹配,可以采用反向传播和梯度下降的方法进行训练。首先,我们需要定义网络结构、损失函数和优化器。
假设我们有一个简单的全连接神经网络(Multilayer Perceptron, MLP),它由两个隐藏层组成,其中第一个隐藏层有m个节点,第二个隐藏层只有一个节点,输出层的激活函数是sigmoid。整个网络可以表示为NN_2(1,m,1;sigmoid,id),其中id表示恒等映射(即线性变换)作为最后一个隐藏层的激活函数。
网络结构:
Input -> Linear -> Sigmoid -> Linear -> Identity (Identity is tanh)
给定输入x,网络的输出f(x)可以通过以下步骤计算:
- 输入通过第一层线性变换,得到
y = W1*x + b1
。 y
经过sigmoid激活,得到z = sigmoid(y)
。z
通过第二层线性变换,得到g = W2*z + b2
。- 输出
f(x) = g
,因为最后一层的激活函数是恒等映射。
我们的目标是找到权重矩阵W1, W2和偏置向量b1, b2,使网络的输出尽可能接近tanh(x)。为此,我们可以使用均方误差(MSE)作为损失函数,并使用梯度下降法进行优化。
损失函数L:
def loss(x, y_true):
y_pred = forward_pass(x) # 前向传播过程
return np.mean((y_pred - y_true) ** 2)
前向传播函数forward_pass:
def forward_pass(x):
y = np.dot(W1, x) + b1
z = sigmoid(y)
g = np.dot(W2, z) + b2
return g
sigmoid函数sigmoid:
def sigmoid(x):
return 1 / (1 + np.exp(-x))
为了找到最佳参数,我们可以使用随机初始化的权重和偏置,然后迭代地更新它们,直到损失函数收敛到足够小的值。这里使用Python和numpy库来进行计算。
初始化权重和偏置:
import numpy as np
# 随机初始化权重和偏置
np.random.seed(0)
W1 = np.random.randn(m, 1)
b1 = np.zeros((m, 1))
W2 = np.random.randn(1, m)
b2 = 0
定义优化器,这里使用Adam优化器:
from tensorflow.keras.optimizers import Adam
optimizer = Adam()
接下来,我们可以编写一个训练循环来更新权重和偏置:
epochs = 10000
x_data = np.linspace(-5, 5, num=1000).reshape(-1, 1) # 生成训练数据
y_true = np.tanh(x_data)
for epoch in range(epochs):
with tf.GradientTape() as tape:
y_pred = forward_pass(x_data)
loss_value = loss(x_data, y_true)
gradients = tape.gradient(loss_value, [W1, W2, b1, b2])
optimizer.apply_gradients(zip(gradients, [W1, W2, b1, b2]))
if (epoch+1) % 1000 == 0:
print(f'Epoch {epoch+1}/{epochs}, Loss: {loss_value:.4f}')
这个训练过程会不断调整权重和偏置,使得神经网络的输出更接近于输入的tanh函数。请注意,由于sigmoid函数在某些区间内可能很难精确拟合tanh函数,所以完全拟合可能会有些困难,但我们可以尝试逼近。
最终,当训练完成后,我们得到了权重矩阵W1, W2和偏置向量b1, b2,这些参数将使得神经网络的输出尽可能接近于输入的tanh函数。