使用Python实现一个简单的神经网络
人工神经网络(Artificial Neural Networks, ANNs)是深度学习的核心技术之一,广泛应用于图像识别、自然语言处理、时间序列预测等领域。本文将带领读者从零开始使用 Python 实现一个简单的全连接前馈神经网络(Feedforward Neural Network),并通过它来解决一个二分类问题。
我们将使用 numpy
库进行数值计算,并手动实现反向传播算法。整个过程不仅有助于理解神经网络的工作原理,也为后续学习更复杂的模型打下基础。
神经网络的基本概念
1.1 神经元与激活函数
神经网络的基本单元是“神经元”。每个神经元接收输入信号,经过加权求和后通过一个激活函数产生输出。常见的激活函数包括:
Sigmoid 函数:$$ \sigma(x) = \frac{1}{1 + e^{-x}} $$ReLU 函数:$$ \text{ReLU}(x) = \max(0, x) $$我们将在本例中使用 Sigmoid 函数作为激活函数。
1.2 前馈传播
前馈传播是指输入数据依次通过每一层网络,最终得到输出的过程。假设我们有一个输入层、一个隐藏层和一个输出层:
输入层:$ X $权重矩阵:$ W_1 $:输入层到隐藏层的权重$ W_2 $:隐藏层到输出层的权重激活函数:Sigmoid则前馈传播可以表示为:
$$Z_1 = X \cdot W_1 \A_1 = \sigma(Z_1) \Z_2 = A_1 \cdot W_2 \\hat{Y} = \sigma(Z_2)$$
其中 $ \hat{Y} $ 是网络的预测输出。
1.3 损失函数
为了衡量预测值与真实值之间的差距,我们使用交叉熵损失函数(Cross-Entropy Loss):
$$L = -\frac{1}{N} \sum_{i=1}^{N} [y_i \log(\hat{y}_i) + (1 - y_i) \log(1 - \hat{y}_i)]$$
其中 $ N $ 是样本数量。
1.4 反向传播
反向传播利用链式法则计算损失函数对各层权重的梯度,并更新权重以最小化损失。具体步骤如下:
计算输出层误差;计算隐藏层误差;更新权重 $ W_2 $ 和 $ W_1 $。代码实现
我们使用 Python 编写一个完整的神经网络类,包含初始化、前向传播、反向传播和训练方法。
import numpy as npclass SimpleNeuralNetwork: def __init__(self, input_size, hidden_size, output_size): # 初始化权重矩阵 self.W1 = np.random.randn(input_size, hidden_size) self.W2 = np.random.randn(hidden_size, output_size) def sigmoid(self, x): return 1 / (1 + np.exp(-x)) def sigmoid_derivative(self, x): return x * (1 - x) def forward(self, X): # 前向传播 self.Z1 = np.dot(X, self.W1) self.A1 = self.sigmoid(self.Z1) self.Z2 = np.dot(self.A1, self.W2) self.A2 = self.sigmoid(self.Z2) return self.A2 def backward(self, X, y, learning_rate=0.1): # 反向传播 m = X.shape[0] # 输出层误差 dZ2 = self.A2 - y dW2 = np.dot(self.A1.T, dZ2) / m # 隐藏层误差 dA1 = np.dot(dZ2, self.W2.T) dZ1 = dA1 * self.sigmoid_derivative(self.A1) dW1 = np.dot(X.T, dZ1) / m # 更新权重 self.W1 -= learning_rate * dW1 self.W2 -= learning_rate * dW2 def train(self, X, y, epochs=1000, learning_rate=0.1): for epoch in range(epochs): # 前向传播 output = self.forward(X) # 反向传播 self.backward(X, y, learning_rate) if epoch % 100 == 0: loss = self.cross_entropy_loss(output, y) print(f"Epoch {epoch}, Loss: {loss:.6f}") def cross_entropy_loss(self, y_pred, y_true): m = y_true.shape[0] return -(1/m) * np.sum(y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred)) def predict(self, X): return np.round(self.forward(X))
测试模型
我们使用一个简单的二分类数据集来测试我们的神经网络。例如 XOR 数据集:
X1 | X2 | Y |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
# 构建XOR数据集X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])y = np.array([[0], [1], [1], [0]])# 创建神经网络实例nn = SimpleNeuralNetwork(input_size=2, hidden_size=4, output_size=1)# 训练网络nn.train(X, y, epochs=10000, learning_rate=0.5)# 测试预测predictions = nn.predict(X)print("Predictions:")print(predictions)
运行结果应接近以下输出:
Epoch 0, Loss: 0.897574Epoch 100, Loss: 0.616712...Epoch 9900, Loss: 0.000102Predictions:[[0.] [1.] [1.] [0.]]
说明我们的神经网络成功地学会了 XOR 分类任务。
总结与扩展
本文介绍了如何使用 Python 和 NumPy 手动实现一个简单的前馈神经网络。虽然该网络结构简单,但完整实现了前向传播、反向传播和训练流程,对于理解神经网络的基本原理非常有帮助。
后续改进方向:
增加正则化项:如 L2 正则化防止过拟合;支持更多层和节点数:构建更深的网络;添加偏置项(Bias);使用不同的优化器:如 Adam、SGD with Momentum;封装成模块化的库:便于复用和扩展。如果你希望继续深入学习神经网络,推荐进一步研究 PyTorch 或 TensorFlow 等深度学习框架,它们在底层实现了高效的自动微分机制和 GPU 加速,适合大规模应用开发。
参考资料
Goodfellow I., Bengio Y., Courville A. Deep Learning. MIT Press, 2016.CS231n Convolutional Neural Networks for Visual Recognition, Stanford University.NumPy 官方文档:https://numpy.org/doc/字数统计:约 1400 字