记得先看之前的梯度下降文章!
链式求导的核心来了,就高中数学知识:
代码实现:
import numpy as np
import matplotlib.pyplot as plt
# Sigmoid 激活函数及其导数
def sigmoid(z):
return 1 / (1 + np.exp(-z))
def sigmoid_derivative(z):
return sigmoid(z) * (1 - sigmoid(z))
# 前向传播
def forward(x, w, b):
z = w * x + b
return sigmoid(z), z
# 反向传播
def backward(y_pred, y_true, z, x):
dz = (y_pred - y_true) * sigmoid_derivative(z)
dw = dz * x
db = dz
return dw, db
# 初始化参数
w = 2
b = 1
# 生成数据:在真实函数上加入噪声
np.random.seed(42)
x = np.linspace(0, 5, 100)
y_true = 1 / (1 + np.exp(-(2 * x + 1))) # 这是我们的真实函数
y_true = y_true + np.random.normal(0, 0.02, len(x)) # 加入噪声
alpha = 0.1
epochs = 1000
losses = []
# 训练过程
for epoch in range(epochs):
total_loss = 0
for i in range(len(x)):
y_pred, z = forward(x[i], w, b)
error = y_true[i] - y_pred
total_loss += error ** 2
dw, db = backward(y_pred, y_true[i], z, x[i])
# 更新参数
w = w - alpha * dw
b = b - alpha * db
# 保存每个 epoch 的损失值
losses.append(total_loss / len(x))
if epoch % 100 == 0:
print(f"Epoch {epoch}/{epochs} - Loss: {total_loss / len(x)}")
# 绘制预测值与实际值对比
y_preds = [forward(i, w, b)[0] for i in x]
plt.plot(x, y_true, 'ro', label="True values")
plt.plot(x, y_preds, 'bo', label="Predicted values")
plt.title("Predicted vs True values")
plt.xlabel("x")
plt.ylabel("y")
plt.legend()
plt.tight_layout()
plt.show()
看看输出: