使用Python实现一个简单的神经网络
人工神经网络(Artificial Neural Networks, ANNs)是深度学习的核心技术之一,它模拟人脑神经元的工作方式,通过大量数据进行训练,从而完成图像识别、自然语言处理、语音识别等任务。在本文中,我们将使用 Python 从头开始实现一个简单的神经网络,并用它来解决一个基本的分类问题。
我们将使用 numpy
库来进行数值计算,并构建一个具有输入层、隐藏层和输出层的前馈神经网络(Feedforward Neural Network)。最后,我们将使用该网络对一个合成的二分类数据集进行训练和预测。
环境准备
首先,请确保你已经安装了以下库:
pip install numpy matplotlib scikit-learn
神经网络结构概述
我们将构建一个三层神经网络:
输入层:接收特征向量隐藏层:使用 Sigmoid 激活函数输出层:使用 Sigmoid 激活函数,用于二分类任务损失函数我们使用均方误差(MSE),优化算法使用梯度下降法。
数据准备
为了演示目的,我们将使用 scikit-learn
的 make_blobs
函数生成一个二维的二分类数据集。
import numpy as npimport matplotlib.pyplot as pltfrom sklearn.datasets import make_blobs# 生成数据X, y = make_blobs(n_samples=300, centers=2, cluster_std=1.5, random_state=42)y = y.reshape((-1, 1)) # 转换为列向量# 可视化数据plt.scatter(X[:, 0], X[:, 1], c=y, cmap='coolwarm')plt.title('Generated Binary Classification Dataset')plt.show()
这段代码会生成两个类别的点,并将其可视化。
构建神经网络模型
定义激活函数及其导数
我们使用 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)
初始化参数
接下来定义我们的神经网络类 SimpleNeuralNetwork
,并初始化权重和偏置:
class SimpleNeuralNetwork: def __init__(self, input_dim, hidden_dim, output_dim): # 初始化权重和偏置 self.W1 = np.random.randn(input_dim, hidden_dim) self.b1 = np.zeros((1, hidden_dim)) self.W2 = np.random.randn(hidden_dim, output_dim) self.b2 = np.zeros((1, output_dim)) def forward(self, X): # 前向传播 self.z1 = X @ self.W1 + self.b1 self.a1 = sigmoid(self.z1) self.z2 = self.a1 @ self.W2 + self.b2 self.a2 = sigmoid(self.z2) return self.a2 def compute_loss(self, y_true, y_pred): # 均方误差损失 return np.mean((y_true - y_pred)**2) def backward(self, X, y_true, learning_rate=0.01): # 反向传播 m = X.shape[0] # 输出层误差 delta2 = (y_pred - y_true) * sigmoid_derivative(y_pred) dW2 = self.a1.T @ delta2 / m db2 = np.sum(delta2, axis=0, keepdims=True) / m # 隐藏层误差 delta1 = delta2 @ self.W2.T * sigmoid_derivative(self.a1) dW1 = X.T @ delta1 / m db1 = np.sum(delta1, axis=0, keepdims=True) / m # 更新参数 self.W2 -= learning_rate * dW2 self.b2 -= learning_rate * db2 self.W1 -= learning_rate * dW1 self.b1 -= learning_rate * db1
训练模型
现在我们可以实例化模型并进行训练:
# 初始化模型nn = SimpleNeuralNetwork(input_dim=2, hidden_dim=4, output_dim=1)# 训练参数epochs = 10000learning_rate = 0.1# 训练过程losses = []for epoch in range(epochs): y_pred = nn.forward(X) loss = nn.compute_loss(y, y_pred) losses.append(loss) nn.backward(X, y, learning_rate) if epoch % 1000 == 0: print(f"Epoch {epoch}, Loss: {loss:.6f}")# 绘制损失曲线plt.plot(losses)plt.title("Training Loss")plt.xlabel("Epoch")plt.ylabel("Loss")plt.show()
随着训练的进行,损失值应该逐渐减小,表示模型正在学习如何更好地拟合数据。
模型评估与预测
我们可以将输出大于等于 0.5 的样本预测为类别 1,小于 0.5 的预测为类别 0:
# 预测y_pred_class = (y_pred >= 0.5).astype(int)# 计算准确率accuracy = np.mean(y_pred_class == y)print(f"Accuracy: {accuracy * 100:.2f}%")
完整代码汇总
以下是完整的代码,你可以直接复制运行:
import numpy as npimport matplotlib.pyplot as pltfrom sklearn.datasets import make_blobs# 生成数据X, y = make_blobs(n_samples=300, centers=2, cluster_std=1.5, random_state=42)y = y.reshape((-1, 1)) # 转换为列向量# 可视化数据plt.scatter(X[:, 0], X[:, 1], c=y, cmap='coolwarm')plt.title('Generated Binary Classification Dataset')plt.show()# 激活函数def sigmoid(x): return 1 / (1 + np.exp(-x))def sigmoid_derivative(x): return x * (1 - x)# 神经网络类class SimpleNeuralNetwork: def __init__(self, input_dim, hidden_dim, output_dim): # 初始化权重和偏置 self.W1 = np.random.randn(input_dim, hidden_dim) self.b1 = np.zeros((1, hidden_dim)) self.W2 = np.random.randn(hidden_dim, output_dim) self.b2 = np.zeros((1, output_dim)) def forward(self, X): # 前向传播 self.z1 = X @ self.W1 + self.b1 self.a1 = sigmoid(self.z1) self.z2 = self.a1 @ self.W2 + self.b2 self.a2 = sigmoid(self.z2) return self.a2 def compute_loss(self, y_true, y_pred): # 均方误差损失 return np.mean((y_true - y_pred)**2) def backward(self, X, y_true, learning_rate=0.01): # 反向传播 m = X.shape[0] # 输出层误差 delta2 = (self.a2 - y_true) * sigmoid_derivative(self.a2) dW2 = self.a1.T @ delta2 / m db2 = np.sum(delta2, axis=0, keepdims=True) / m # 隐藏层误差 delta1 = delta2 @ self.W2.T * sigmoid_derivative(self.a1) dW1 = X.T @ delta1 / m db1 = np.sum(delta1, axis=0, keepdims=True) / m # 更新参数 self.W2 -= learning_rate * dW2 self.b2 -= learning_rate * db2 self.W1 -= learning_rate * dW1 self.b1 -= learning_rate * db1# 初始化模型nn = SimpleNeuralNetwork(input_dim=2, hidden_dim=4, output_dim=1)# 训练参数epochs = 10000learning_rate = 0.1# 训练过程losses = []for epoch in range(epochs): y_pred = nn.forward(X) loss = nn.compute_loss(y, y_pred) losses.append(loss) nn.backward(X, y, learning_rate) if epoch % 1000 == 0: print(f"Epoch {epoch}, Loss: {loss:.6f}")# 绘制损失曲线plt.plot(losses)plt.title("Training Loss")plt.xlabel("Epoch")plt.ylabel("Loss")plt.show()# 预测y_pred = nn.forward(X)y_pred_class = (y_pred >= 0.5).astype(int)# 计算准确率accuracy = np.mean(y_pred_class == y)print(f"Accuracy: {accuracy * 100:.2f}%")
总结
在本文中,我们使用 Python 和 NumPy 实现了一个简单的三层前馈神经网络,并成功地对其进行了训练和测试。虽然这个模型相对简单,但它展示了神经网络的基本原理,包括:
前向传播损失计算反向传播参数更新如果你有兴趣进一步扩展这个项目,可以尝试:
添加更多的隐藏层使用不同的激活函数(如 ReLU)改用交叉熵损失函数加入正则化防止过拟合将模型封装成可复用的模块希望这篇文章能帮助你更好地理解神经网络的内部工作原理,并激发你深入探索深度学习的兴趣!