从Zero到Hero:跟随Andrej Karpathy的神经网络教程构建你的第一个AI模型

1次阅读
没有评论

共计 2870 个字符,预计需要花费 8 分钟才能阅读完成。

image.webp

神经网络基础概念简介

神经网络是深度学习的基础,理解其核心概念对于构建 AI 模型至关重要。让我们从最基本的三个概念开始:前向传播、反向传播和激活函数。

从 Zero 到 Hero:跟随 Andrej Karpathy 的神经网络教程构建你的第一个 AI 模型

  1. 前向传播 :这是神经网络进行预测的过程。输入数据从输入层经过隐藏层,最终到达输出层。每一层都会对数据进行线性变换(权重乘以输入加上偏置)和非线性变换(通过激活函数)。

  2. 反向传播 :这是神经网络学习的核心机制。通过计算损失函数对权重的梯度,然后使用梯度下降法来更新权重,逐步减少预测误差。

  3. 激活函数 :引入非线性,使神经网络能够学习复杂模式。常见的激活函数包括 ReLU、Sigmoid 和 Tanh。

使用 Python 和 NumPy 实现神经网络

下面是一个简单的神经网络实现,使用 Python 和 NumPy 库。这个实现包含一个输入层、一个隐藏层和一个输出层。

import numpy as np

class NeuralNetwork:
    def __init__(self, input_size, hidden_size, output_size):
        self.weights1 = np.random.randn(input_size, hidden_size)
        self.weights2 = np.random.randn(hidden_size, output_size)
        self.bias1 = np.zeros((1, hidden_size))
        self.bias2 = np.zeros((1, 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.hidden = self.sigmoid(np.dot(X, self.weights1) + self.bias1)
        self.output = self.sigmoid(np.dot(self.hidden, self.weights2) + self.bias2)
        return self.output

    def backward(self, X, y, learning_rate):
        # 计算输出层的误差
        output_error = y - self.output
        output_delta = output_error * self.sigmoid_derivative(self.output)

        # 计算隐藏层的误差
        hidden_error = np.dot(output_delta, self.weights2.T)
        hidden_delta = hidden_error * self.sigmoid_derivative(self.hidden)

        # 更新权重和偏置
        self.weights2 += learning_rate * np.dot(self.hidden.T, output_delta)
        self.weights1 += learning_rate * np.dot(X.T, hidden_delta)
        self.bias2 += learning_rate * np.sum(output_delta, axis=0, keepdims=True)
        self.bias1 += learning_rate * np.sum(hidden_delta, axis=0, keepdims=True)

    def train(self, X, y, epochs, learning_rate):
        for epoch in range(epochs):
            output = self.forward(X)
            self.backward(X, y, learning_rate)
            if epoch % 1000 == 0:
                loss = np.mean(np.square(y - output))
                print(f'Epoch {epoch}, Loss: {loss}')

训练过程中的常见问题及解决方案

  1. 梯度消失 :当使用 Sigmoid 或 Tanh 激活函数时,梯度可能会变得非常小,导致权重更新缓慢。解决方案包括使用 ReLU 激活函数或批量归一化。

  2. 过拟合 :模型在训练数据上表现良好,但在测试数据上表现差。解决方案包括使用正则化(如 L1/L2 正则化)、Dropout 或增加训练数据。

  3. 学习率选择不当 :学习率过高可能导致模型不收敛,学习率过低可能导致训练过慢。解决方案包括使用学习率调度器或自适应优化算法(如 Adam)。

性能优化技巧

  1. 批量归一化 :通过对每一层的输入进行归一化,可以加速训练并减少对初始化的依赖。

  2. 学习率调整 :使用学习率衰减或自适应优化算法(如 Adam)可以动态调整学习率,提高训练效率。

  3. 权重初始化 :合适的权重初始化(如 Xavier 初始化)可以避免梯度消失或爆炸。

MNIST 手写数字识别案例

下面是一个完整的 MNIST 手写数字识别案例,使用上述神经网络实现。

from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelBinarizer

# 加载 MNIST 数据集
mnist = fetch_openml('mnist_784')
X = mnist.data / 255.0  # 归一化
Y = LabelBinarizer().fit_transform(mnist.target)

# 划分训练集和测试集
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2)

# 创建神经网络
input_size = X_train.shape[1]
hidden_size = 128
output_size = Y_train.shape[1]
nn = NeuralNetwork(input_size, hidden_size, output_size)

# 训练神经网络
nn.train(X_train.values, Y_train, epochs=10000, learning_rate=0.1)

# 测试神经网络
predictions = nn.forward(X_test.values)
predicted_classes = np.argmax(predictions, axis=1)
true_classes = np.argmax(Y_test, axis=1)
accuracy = np.mean(predicted_classes == true_classes)
print(f'Test Accuracy: {accuracy * 100:.2f}%')

延伸思考题

  1. 如何改进当前的神经网络架构以提高 MNIST 数据集的识别准确率?
  2. 除了 MNIST 数据集,还有哪些经典的图像分类数据集可以用来测试神经网络的性能?
  3. 在实际应用中,如何选择适合的激活函数和优化算法?

通过本文的学习,你应该已经掌握了神经网络的基础实现原理,并能够独立构建和训练自己的 AI 模型。希望你能在实践中不断探索和优化,进一步提升模型的性能和应用范围。

正文完
 0
评论(没有评论)