使用 Python 实现一个简单的神经网络
在当今的人工智能和机器学习领域,神经网络是一种非常重要的工具。它模仿人脑的工作方式,通过多个“神经元”层对数据进行处理和学习。本文将介绍如何使用 Python 编写一个简单的全连接前馈神经网络,并用它来解决一个基本的分类问题。
我们将使用 NumPy 来处理矩阵运算,并实现一个两层(输入层 + 隐藏层 + 输出层)的神经网络。最后我们会用这个网络去训练一个小规模的数据集,比如逻辑异或(XOR)问题。
1. 神经网络的基本结构
一个典型的全连接前馈神经网络由输入层、隐藏层和输出层组成。每一层都包含若干个神经元,每个神经元与下一层的所有神经元相连。神经元之间的连接都有权重,这些权重是通过训练过程不断调整的。
我们将在本例中实现一个具有以下结构的神经网络:
输入层:2个节点隐藏层:3个节点(使用 Sigmoid 激活函数)输出层:1个节点(Sigmoid 激活函数)2. 所需库
我们需要导入 numpy
来进行数值计算:
import numpy as np
3. 定义激活函数及其导数
常用的激活函数之一是 Sigmoid 函数,定义如下:
$$\sigma(x) = \frac{1}{1 + e^{-x}}$$
它的导数形式为:
$$\sigma'(x) = \sigma(x)(1 - \sigma(x))$$
我们将其封装成函数:
def sigmoid(x): return 1 / (1 + np.exp(-x))def sigmoid_derivative(x): return x * (1 - x)
4. 初始化网络参数
接下来我们初始化权重和偏置。通常我们会随机初始化权重以打破对称性。
# 输入数据(XOR 问题)X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])# 标签y = np.array([[0], [1], [1], [0]])# 设置种子以保证结果可重复np.random.seed(42)# 初始化权重input_neurons = 2hidden_neurons = 3output_neurons = 1# 权重矩阵weights_input_hidden = np.random.uniform(size=(input_neurons, hidden_neurons))weights_hidden_output = np.random.uniform(size=(hidden_neurons, output_neurons))# 偏置向量bias_hidden = np.random.uniform(size=(1, hidden_neurons))bias_output = np.random.uniform(size=(1, output_neurons))print("初始权重(输入 -> 隐藏):\n", weights_input_hidden)print("初始权重(隐藏 -> 输出):\n", weights_hidden_output)
5. 前向传播
前向传播是指从输入到输出的一次完整计算过程。
def forward_propagation(X): # 输入层到隐藏层 hidden_layer_input = np.dot(X, weights_input_hidden) + bias_hidden hidden_layer_output = sigmoid(hidden_layer_input) # 隐藏层到输出层 output_layer_input = np.dot(hidden_layer_output, weights_hidden_output) + bias_output output = sigmoid(output_layer_input) return hidden_layer_output, output
6. 反向传播与梯度下降
反向传播是根据预测误差调整网络权重的过程。我们使用均方误差作为损失函数:
$$E = \frac{1}{2} \sum (y{true} - y{pred})^2$$
我们通过链式法则计算梯度并更新权重。
def backpropagation(X, y, hidden_layer_output, output): global weights_input_hidden, weights_hidden_output, bias_hidden, bias_output learning_rate = 0.1 # 输出层误差 output_error = y - output output_delta = output_error * sigmoid_derivative(output) # 隐藏层误差 hidden_error = output_delta.dot(weights_hidden_output.T) hidden_delta = hidden_error * sigmoid_derivative(hidden_layer_output) # 更新权重和偏置 weights_hidden_output += hidden_layer_output.T.dot(output_delta) * learning_rate weights_input_hidden += X.T.dot(hidden_delta) * learning_rate bias_output += np.sum(output_delta, axis=0, keepdims=True) * learning_rate bias_hidden += np.sum(hidden_delta, axis=0, keepdims=True) * learning_rate
7. 训练神经网络
我们将整个流程整合起来,进行多次迭代训练:
epochs = 10000for epoch in range(epochs): hidden_layer_output, output = forward_propagation(X) backpropagation(X, y, hidden_layer_output, output) if epoch % 1000 == 0: loss = np.mean(np.square(y - output)) print(f"Epoch {epoch}, Loss: {loss:.6f}")
8. 测试模型
训练完成后,我们可以用训练好的模型进行预测:
_, predictions = forward_propagation(X)print("\n预测结果:")print(predictions)
预期输出应接近 [0, 1, 1, 0]
。
9. 完整代码汇总
以下是完整的 Python 神经网络实现代码:
import numpy as np# 激活函数def sigmoid(x): return 1 / (1 + np.exp(-x))def sigmoid_derivative(x): return x * (1 - x)# 数据集X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])y = np.array([[0], [1], [1], [0]])np.random.seed(42)# 初始化参数input_neurons = 2hidden_neurons = 3output_neurons = 1weights_input_hidden = np.random.uniform(size=(input_neurons, hidden_neurons))weights_hidden_output = np.random.uniform(size=(hidden_neurons, output_neurons))bias_hidden = np.random.uniform(size=(1, hidden_neurons))bias_output = np.random.uniform(size=(1, output_neurons))# 前向传播def forward_propagation(X): hidden_layer_input = np.dot(X, weights_input_hidden) + bias_hidden hidden_layer_output = sigmoid(hidden_layer_input) output_layer_input = np.dot(hidden_layer_output, weights_hidden_output) + bias_output output = sigmoid(output_layer_input) return hidden_layer_output, output# 反向传播def backpropagation(X, y, hidden_layer_output, output): global weights_input_hidden, weights_hidden_output, bias_hidden, bias_output learning_rate = 0.1 output_error = y - output output_delta = output_error * sigmoid_derivative(output) hidden_error = output_delta.dot(weights_hidden_output.T) hidden_delta = hidden_error * sigmoid_derivative(hidden_layer_output) weights_hidden_output += hidden_layer_output.T.dot(output_delta) * learning_rate weights_input_hidden += X.T.dot(hidden_delta) * learning_rate bias_output += np.sum(output_delta, axis=0, keepdims=True) * learning_rate bias_hidden += np.sum(hidden_delta, axis=0, keepdims=True) * learning_rate# 训练epochs = 10000for epoch in range(epochs): hidden_layer_output, output = forward_propagation(X) backpropagation(X, y, hidden_layer_output, output) if epoch % 1000 == 0: loss = np.mean(np.square(y - output)) print(f"Epoch {epoch}, Loss: {loss:.6f}")# 预测_, predictions = forward_propagation(X)print("\n预测结果:")print(predictions.round())
10. 总结与扩展
本文通过纯 Python 和 NumPy 实现了一个基础的前馈神经网络,并成功解决了 XOR 分类问题。虽然该网络结构简单,但它展示了神经网络的核心原理:前向传播 + 损失计算 + 反向传播 + 参数更新。
未来可以尝试:
使用更复杂的网络结构(如卷积神经网络、循环神经网络)引入更多优化算法(如 Adam、RMSProp)使用 PyTorch 或 TensorFlow 进行深度学习开发应用于图像识别、自然语言处理等领域如果你对 AI 和机器学习感兴趣,建议继续深入研究相关理论和实践项目,不断提升自己的技术水平。