使用Python实现一个简单的神经网络

今天 5阅读

在机器学习和人工智能领域,神经网络是一种非常强大的工具。它模仿人脑的结构和功能,通过多层非线性变换来学习数据中的复杂模式。本文将介绍如何使用 Python 实现一个简单的全连接前馈神经网络(Feedforward Neural Network),并通过一个简单的分类任务来演示其训练过程。

我们将使用 NumPy 库进行数值计算,并手动实现反向传播算法。整个实现不依赖于任何深度学习框架(如 TensorFlow 或 PyTorch),以帮助读者更深入理解神经网络的工作原理。


1. 神经网络的基本概念

一个基本的神经网络由输入层、隐藏层和输出层组成。每一层都包含多个神经元,每个神经元与下一层的所有神经元相连,因此也称为全连接层

神经网络的核心操作包括:

前向传播(Forward Propagation):输入数据经过各层神经元计算,最终得到预测结果。损失函数(Loss Function):衡量预测值与真实值之间的误差。反向传播(Backward Propagation):根据损失函数对参数求导,更新权重矩阵。优化器(Optimizer):使用梯度下降等方法来更新参数。

2. 数据准备

为了简化问题,我们使用一个合成的二分类数据集。我们可以使用 sklearn.datasets.make_blobs 来生成一些二维数据点。

import numpy as npimport matplotlib.pyplot as pltfrom sklearn.datasets import make_blobsfrom sklearn.model_selection import train_test_split# 生成数据X, y = make_blobs(n_samples=300, centers=2, cluster_std=1.5, random_state=42)y = y.reshape((y.shape[0], 1))  # 将标签转换为列向量# 划分训练集和测试集X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)print("训练集特征维度:", X_train.shape)print("训练集标签维度:", y_train.shape)

3. 激活函数与损失函数

常用的激活函数有 Sigmoid 和 ReLU。在这里我们使用 Sigmoid 函数作为隐藏层的激活函数,以及输出层用于二分类的概率输出。

Sigmoid 函数及其导数:

$$\sigma(x) = \frac{1}{1 + e^{-x}}, \quad \sigma'(x) = \sigma(x)(1 - \sigma(x))$$

二分类交叉熵损失函数:

$$L = -\frac{1}{N} \sum_{i=1}^{N} \left[ y_i \log(\hat{y}_i) + (1 - y_i) \log(1 - \hat{y}_i) \right]$$

下面是对应的 Python 实现:

def sigmoid(x):    return 1 / (1 + np.exp(-x))def sigmoid_derivative(x):    s = sigmoid(x)    return s * (1 - s)def binary_cross_entropy(y_true, y_pred):    epsilon = 1e-15  # 防止 log(0)    loss = -np.mean(y_true * np.log(y_pred + epsilon) + (1 - y_true) * np.log(1 - y_pred + epsilon))    return loss

4. 网络结构定义

我们构建一个具有以下结构的神经网络:

输入层:2个神经元(对应二维特征)隐藏层:4个神经元输出层:1个神经元(二分类)

初始化权重矩阵和偏置项:

input_size = 2hidden_size = 4output_size = 1# 初始化权重和偏置W1 = np.random.randn(input_size, hidden_size)b1 = np.zeros((1, hidden_size))W2 = np.random.randn(hidden_size, output_size)b2 = np.zeros((1, output_size))

5. 前向传播

定义前向传播函数:

def forward(X, W1, b1, W2, b2):    Z1 = np.dot(X, W1) + b1    A1 = sigmoid(Z1)    Z2 = np.dot(A1, W2) + b2    A2 = sigmoid(Z2)    return Z1, A1, Z2, A2

6. 反向传播与参数更新

根据链式法则计算梯度并更新参数:

def backward(X, y, Z1, A1, Z2, A2, W1, W2, learning_rate=0.01):    m = X.shape[0]    dZ2 = A2 - y    dW2 = np.dot(A1.T, dZ2) / m    db2 = np.sum(dZ2, axis=0, keepdims=True) / m    dA1 = np.dot(dZ2, W2.T)    dZ1 = dA1 * sigmoid_derivative(Z1)    dW1 = np.dot(X.T, dZ1) / m    db1 = np.sum(dZ1, axis=0, keepdims=True) / m    # 更新参数    W1 -= learning_rate * dW1    b1 -= learning_rate * db1    W2 -= learning_rate * dW2    b2 -= learning_rate * db2    return W1, b1, W2, b2

7. 训练模型

接下来,我们训练神经网络:

# 超参数epochs = 1000learning_rate = 0.1# 存储损失值losses = []for epoch in range(epochs):    Z1, A1, Z2, A2 = forward(X_train, W1, b1, W2, b2)    loss = binary_cross_entropy(y_train, A2)    losses.append(loss)    if epoch % 100 == 0:        print(f"Epoch {epoch}, Loss: {loss:.4f}")    W1, b1, W2, b2 = backward(X_train, y_train, Z1, A1, Z2, A2, W1, b2, learning_rate)

8. 模型评估

最后,我们在测试集上评估模型表现:

# 在测试集上进行预测_, _, _, predictions = forward(X_test, W1, b1, W2, b2)predictions = (predictions > 0.5).astype(int)# 计算准确率accuracy = np.mean(predictions == y_test)print(f"测试集准确率: {accuracy * 100:.2f}%")# 绘制损失曲线plt.plot(losses)plt.xlabel('Epoch')plt.ylabel('Loss')plt.title('Training Loss Curve')plt.show()

9. 总结

在本文中,我们使用纯 Python 和 NumPy 实现了一个简单的两层前馈神经网络。我们详细介绍了神经网络的基本组成部分,包括前向传播、损失函数、反向传播和参数更新。此外,我们还实现了数据准备、模型训练和评估流程。

虽然这个神经网络比较简单,但它的结构可以扩展到更多层和更复杂的任务中。对于更高级的应用,建议使用成熟的深度学习框架(如 PyTorch 或 TensorFlow),它们提供了自动微分、GPU加速等强大功能。


附录:完整代码汇总

import numpy as npimport matplotlib.pyplot as pltfrom sklearn.datasets import make_blobsfrom sklearn.model_selection import train_test_split# 生成数据X, y = make_blobs(n_samples=300, centers=2, cluster_std=1.5, random_state=42)y = y.reshape((y.shape[0], 1))X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 激活函数与损失函数def sigmoid(x):    return 1 / (1 + np.exp(-x))def sigmoid_derivative(x):    s = sigmoid(x)    return s * (1 - s)def binary_cross_entropy(y_true, y_pred):    epsilon = 1e-15    loss = -np.mean(y_true * np.log(y_pred + epsilon) + (1 - y_true) * np.log(1 - y_pred + epsilon))    return loss# 初始化参数input_size = 2hidden_size = 4output_size = 1W1 = np.random.randn(input_size, hidden_size)b1 = np.zeros((1, hidden_size))W2 = np.random.randn(hidden_size, output_size)b2 = np.zeros((1, output_size))# 前向传播def forward(X, W1, b1, W2, b2):    Z1 = np.dot(X, W1) + b1    A1 = sigmoid(Z1)    Z2 = np.dot(A1, W2) + b2    A2 = sigmoid(Z2)    return Z1, A1, Z2, A2# 反向传播def backward(X, y, Z1, A1, Z2, A2, W1, W2, learning_rate=0.01):    m = X.shape[0]    dZ2 = A2 - y    dW2 = np.dot(A1.T, dZ2) / m    db2 = np.sum(dZ2, axis=0, keepdims=True) / m    dA1 = np.dot(dZ2, W2.T)    dZ1 = dA1 * sigmoid_derivative(Z1)    dW1 = np.dot(X.T, dZ1) / m    db1 = np.sum(dZ1, axis=0, keepdims=True) / m    W1 -= learning_rate * dW1    b1 -= learning_rate * db1    W2 -= learning_rate * dW2    b2 -= learning_rate * db2    return W1, b1, W2, b2# 训练模型epochs = 1000learning_rate = 0.1losses = []for epoch in range(epochs):    Z1, A1, Z2, A2 = forward(X_train, W1, b1, W2, b2)    loss = binary_cross_entropy(y_train, A2)    losses.append(loss)    if epoch % 100 == 0:        print(f"Epoch {epoch}, Loss: {loss:.4f}")    W1, b1, W2, b2 = backward(X_train, y_train, Z1, A1, Z2, A2, W1, W2, learning_rate)# 测试模型_, _, _, predictions = forward(X_test, W1, b1, W2, b2)predictions = (predictions > 0.5).astype(int)accuracy = np.mean(predictions == y_test)print(f"测试集准确率: {accuracy * 100:.2f}%")# 绘制损失曲线plt.plot(losses)plt.xlabel('Epoch')plt.ylabel('Loss')plt.title('Training Loss Curve')plt.show()

如果你有任何关于神经网络或代码的问题,欢迎继续提问!

免责声明:本文来自网站作者,不代表CIUIC的观点和立场,本站所发布的一切资源仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。客服邮箱:ciuic@ciuic.com

目录[+]

您是本站第23228名访客 今日有23篇新文章

微信号复制成功

打开微信,点击右上角"+"号,添加朋友,粘贴微信号,搜索即可!