### 简化的BP神经网络实现
为了便于 Python 新手理解,以下代码仅依赖于基本的数学运算和逻辑操作,不使用任何第三方库(如 NumPy)。代码结构清晰简单,适合初学者学习。
---
#### 1. **前向传播**
前向传播的核心是从输入层经过隐藏层到达输出层的过程。每一层的计算包括加权求和以及激活函数的应用[^1]。
#### 2. **反向传播**
反向传播的目标是通过误差信号调整权重和偏置,从而优化模型性能。它基于链式法则逐步计算梯度,并更新参数以减小损失函数值[^2]。
---
### 简化版 BP 神经网络代码
```python
import random
# Sigmoid 激活函数及其导数
def sigmoid(x):
return 1 / (1 + pow(2.71828, -x))
def sigmoid_derivative(x):
s = sigmoid(x)
return s * (1 - s)
# 初始化权重和偏置
def initialize_parameters(input_size, hidden_size, output_size):
weights_input_hidden = [[random.uniform(-1, 1) for _ in range(hidden_size)] for _ in range(input_size)]
bias_hidden = [random.uniform(-1, 1) for _ in range(hidden_size)]
weights_hidden_output = [[random.uniform(-1, 1) for _ in range(output_size)] for _ in range(hidden_size)]
bias_output = [random.uniform(-1, 1) for _ in range(output_size)]
return (
weights_input_hidden,
bias_hidden,
weights_hidden_output,
bias_output,
)
# 前向传播
def forward_propagate(inputs, weights_input_hidden, bias_hidden, weights_hidden_output, bias_output):
# 隐藏层计算
hidden_raw = [
sum(w * inp for w, inp in zip(weights_input_hidden[i], inputs)) + bias_hidden[i]
for i in range(len(bias_hidden))
]
hidden_activated = list(map(sigmoid, hidden_raw))
# 输出层计算
output_raw = [
sum(w * h for w, h in zip(weights_hidden_output[i], hidden_activated)) + bias_output[i]
for i in range(len(bias_output))
]
output_activated = list(map(sigmoid, output_raw))
return hidden_raw, hidden_activated, output_raw, output_activated
# 计算损失
def calculate_loss(expected_outputs, actual_outputs):
return sum((e - a) ** 2 for e, a in zip(expected_outputs, actual_outputs)) / 2
# 反向传播
def backpropagate(
inputs,
expected_outputs,
actual_outputs,
output_raw,
hidden_activated,
hidden_raw,
weights_hidden_output,
learning_rate,
):
# 输出层误差
error_output = [(expected_outputs[i] - actual_outputs[i]) * sigmoid_derivative(output_raw[i]) for i in range(len(actual_outputs))]
# 隐藏层误差
error_hidden = [
sum(error_output[j] * weights_hidden_output[k][j] for j in range(len(error_output))) *
sigmoid_derivative(hidden_raw[k])
for k in range(len(hidden_raw))
]
# 更新输出层权重和偏置
delta_weights_hidden_output = [
[learning_rate * error_output[j] * hidden_activated[k] for k in range(len(hidden_activated))]
for j in range(len(error_output))
]
delta_bias_output = [learning_rate * err for err in error_output]
# 更新隐藏层权重和偏置
delta_weights_input_hidden = [
[learning_rate * error_hidden[j] * inputs[k] for k in range(len(inputs))]
for j in range(len(error_hidden))
]
delta_bias_hidden = [learning_rate * err for err in error_hidden]
return (
delta_weights_input_hidden,
delta_bias_hidden,
delta_weights_hidden_output,
delta_bias_output,
)
# 更新参数
def update_parameters(
weights_input_hidden,
bias_hidden,
weights_hidden_output,
bias_output,
dwih,
dbh,
dwho,
dbo,
):
new_weights_input_hidden = [
[weights_input_hidden[i][j] + dwih[i][j] for j in range(len(dwih[0]))]
for i in range(len(dwih))
]
new_bias_hidden = [bias_hidden[i] + dbh[i] for i in range(len(dbh))]
new_weights_hidden_output = [
[weights_hidden_output[i][j] + dwho[i][j] for j in range(len(dwho[0]))]
for i in range(len(dwho))
]
new_bias_output = [bias_output[i] + dbo[i] for i in range(len(dbo))]
return new_weights_input_hidden, new_bias_hidden, new_weights_hidden_output, new_bias_output
# 主训练循环
def train_network(inputs_list, targets_list, epochs, learning_rate, input_size, hidden_size, output_size):
weights_input_hidden, bias_hidden, weights_hidden_output, bias_output = initialize_parameters(input_size, hidden_size, output_size)
for epoch in range(epochs):
total_loss = 0
for idx, inputs in enumerate(inputs_list):
target = targets_list[idx]
# 前向传播
hidden_raw, hidden_activated, output_raw, output_activated = forward_propagate(
inputs, weights_input_hidden, bias_hidden, weights_hidden_output, bias_output
)
# 计算损失
loss = calculate_loss(target, output_activated)
total_loss += loss
# 反向传播
deltas = backpropagate(
inputs,
target,
output_activated,
output_raw,
hidden_activated,
hidden_raw,
weights_hidden_output,
learning_rate,
)
delta_weights_input_hidden, delta_bias_hidden, delta_weights_hidden_output, delta_bias_output = deltas
# 参数更新
weights_input_hidden, bias_hidden, weights_hidden_output, bias_output = update_parameters(
weights_input_hidden,
bias_hidden,
weights_hidden_output,
bias_output,
delta_weights_input_hidden,
delta_bias_hidden,
delta_weights_hidden_output,
delta_bias_output,
)
average_loss = total_loss / len(inputs_list)
if epoch % 100 == 0:
print(f"Epoch {epoch}, Average Loss: {average_loss}")
return weights_input_hidden, bias_hidden, weights_hidden_output, bias_output
# 测试数据
inputs_list = [[0, 0], [0, 1], [1, 0], [1, 1]]
targets_list = [[0], [1], [1], [0]] # XOR problem
# 超参数设置
input_size = 2
hidden_size = 4
output_size = 1
epochs = 1000
learning_rate = 0.5
trained_params = train_network(inputs_list, targets_list, epochs, learning_rate, input_size, hidden_size, output_size)
```
---
###