深度学习入门Python实践教程:从零搭建你的第一个神经网络

导读部分 返回列表

👋 哈喽,各位小伙伴!我是你们的学长小杰~ 最近好多朋友私信我说:「学长,我听说深度学习特别牛,但一看各种公式和论文就头大,有没有什么简单一点的上手方法?」 💡 其实我特别理解你,因为我当年也是文科转...

正文内容

👋 哈喽,各位小伙伴!我是你们的学长小杰~

最近好多朋友私信我说:「学长,我听说深度学习特别牛,但一看各种公式和论文就头大,有没有什么简单一点的上手方法?」

💡 其实我特别理解你,因为我当年也是文科转AI的,最开始看到反向传播、梯度下降这些名词的时候,也是一脸懵。不过别担心!今天咱们一起来操作一下,用Python从零搭建一个能识别手写数字的简单神经网络。相信我,等你跑起来的那一刻,你会觉得「原来深度学习也没那么难嘛!」

深度学习入门Python实践教程封面图

📍 第一步:环境准备——装好Python和必要的库

咱们先检查一下有没有Python环境。打开你的终端(CMD或Terminal),输入:

python --version

✅ 如果能看到版本号(比如Python 3.8+),那就没问题啦。如果没有,先去 python.org 下载安装,记得安装时勾选「Add Python to PATH」。

然后安装我们需要的几个库,建议用豆瓣源加速:

pip install numpy matplotlib scikit-learn -i https://pypi.douban.com/simple

🎉 搞定!这些库分别是处理数据、画图和机器学习的工具包。放心,我帮你试过了,这样安装没问题。

📍 第二步:加载数据——先认识一下MNIST手写数字集

咱们用的数据集叫MNIST,里面是0~9的手写数字图片,每张是28×28像素的灰度图。这个数据集太经典了,就像深度学习界的「Hello World」。

下面我们用scikit-learn来加载它:

from sklearn.datasets import fetch_openml
import numpy as np

# 加载MNIST数据集(第一次会自动下载,大约12MB)
mnist = fetch_openml('mnist_784', version=1, as_frame=False)
X, y = mnist.data.astype(np.float32) / 255.0, mnist.target.astype(np.int64)

print(f"数据形状: {X.shape}")   # (70000, 784) —— 7万张图片,每张784个像素
print(f"标签形状: {y.shape}")   # (70000,)

💡 注意:我们把像素值除以255,归一化到0~1之间,这样神经网络训练起来更稳定。

然后我们划分训练集和测试集:

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=10000, random_state=42)
print(f"训练集: {X_train.shape}, 测试集: {X_test.shape}")

📍 第三步:构建神经网络——动手写一个最简单的网络

我们要建的是一个「单隐层神经网络」,结构长这样:输入层(784个神经元) → 隐藏层(100个神经元) → 输出层(10个神经元)。

咱们一步一步来写类定义:

class SimpleNN:
    def __init__(self, input_size=784, hidden_size=100, output_size=10, lr=0.01):
        # 随机初始化权重和偏置
        self.W1 = np.random.randn(input_size, hidden_size) * 0.01
        self.b1 = np.zeros((1, hidden_size))
        self.W2 = np.random.randn(hidden_size, output_size) * 0.01
        self.b2 = np.zeros((1, output_size))
        self.lr = lr

    def relu(self, x):
        return np.maximum(0, x)

    def softmax(self, x):
        exp_x = np.exp(x - np.max(x, axis=1, keepdims=True))
        return exp_x / np.sum(exp_x, axis=1, keepdims=True)

    def forward(self, X):
        self.z1 = np.dot(X, self.W1) + self.b1
        self.a1 = self.relu(self.z1)
        self.z2 = np.dot(self.a1, self.W2) + self.b2
        self.a2 = self.softmax(self.z2)
        return self.a2

    def cross_entropy_loss(self, y_pred, y_true):
        m = y_true.shape[0]
        log_likelihood = -np.log(y_pred[range(m), y_true] + 1e-8)
        return np.sum(log_likelihood) / m

    def backward(self, X, y_true_one_hot, y_pred):
        m = X.shape[0]
        # 输出层梯度
        dz2 = y_pred - y_true_one_hot
        dW2 = np.dot(self.a1.T, dz2) / m
        db2 = np.sum(dz2, axis=0, keepdims=True) / m
        # 隐藏层梯度
        da1 = np.dot(dz2, self.W2.T)
        dz1 = da1 * (self.z1 > 0)  # ReLU导数
        dW1 = np.dot(X.T, dz1) / m
        db1 = np.sum(dz1, axis=0, keepdims=True) / m
        # 更新参数
        self.W2 -= self.lr * dW2
        self.b2 -= self.lr * db2
        self.W1 -= self.lr * dW1
        self.b1 -= self.lr * db1

    def train(self, X, y, epochs=50, batch_size=64):
        m = X.shape[0]
        y_one_hot = np.eye(10)[y]  # 转为one-hot编码
        for epoch in range(epochs):
            # 打乱数据
            indices = np.random.permutation(m)
            X_shuffled = X[indices]
            y_one_hot_shuffled = y_one_hot[indices]
            for i in range(0, m, batch_size):
                X_batch = X_shuffled[i:i+batch_size]
                y_batch = y_one_hot_shuffled[i:i+batch_size]
                y_pred = self.forward(X_batch)
                self.backward(X_batch, y_batch, y_pred)
            # 每个epoch计算损失
            y_pred_all = self.forward(X)
            loss = self.cross_entropy_loss(y_pred_all, y)
            if epoch % 10 == 0:
                print(f"Epoch {epoch}, Loss: {loss:.4f}")

    def predict(self, X):
        y_pred = self.forward(X)
        return np.argmax(y_pred, axis=1)

    def accuracy(self, X, y):
        preds = self.predict(X)
        return np.mean(preds == y)

🔥 这段代码你可能觉得有点长,但别紧张!核心其实就是3个公式:

  • 前向传播:输入×权重+偏置 → 激活 → 输出概率
  • 反向传播:计算每个权重对误差的贡献,然后沿着梯度下降
  • 参数更新:权重 = 权重 – 学习率×梯度

我刚开始学的时候也是抄了一遍又一遍才理解的,你先跟着跑起来再说~

📍 第四步:训练模型——让神经网络学会认数字

现在咱们实例化网络并训练:

model = SimpleNN(input_size=784, hidden_size=100, output_size=10, lr=0.1)
model.train(X_train, y_train, epochs=30, batch_size=128)
# 看下训练集准确率
train_acc = model.accuracy(X_train, y_train)
print(f"训练集准确率: {train_acc*100:.2f}%")

💪 如果一切顺利,你应该能看到损失从2.3左右逐渐下降到0.3附近,准确率能到95%以上!注意:第一次跑可能会有点慢(大概几十秒),喝杯咖啡等它跑完~

📍 第五步:测试——看看它到底学会了没

test_acc = model.accuracy(X_test, y_test)
print(f"测试集准确率: {test_acc*100:.2f}%")
# 随机显示几个预测结果
import matplotlib.pyplot as plt
sample_idx = np.random.choice(len(X_test), 10)
fig, axes = plt.subplots(2, 5, figsize=(10,4))
for i, idx in enumerate(sample_idx):
    ax = axes[i//5][i%5]
    ax.imshow(X_test[idx].reshape(28,28), cmap='gray')
    pred = model.predict(X_test[idx:idx+1])[0]
    ax.set_title(f"Pred: {pred}")
    ax.axis('off')
plt.tight_layout()
plt.show()

🎉 怎么样,是不是很神奇!你亲自写的神经网络已经能识别手写数字啦~

如果想继续进阶,可以试试:

  • 增加隐藏层深度(变成深层网络)
  • 使用更高级的优化器(如Adam)
  • 用Keras或PyTorch框架,几行代码就能实现一样的网络

对了,如果你还想了解如何用这个网络做一个完整的Web应用,推荐看看站内这篇 豆包MarsCode教程,以及 DeepSeek实战指南,里面有很多实战经验分享。

💪 好了,今天的动手时间就到这儿啦!快去试试看,如果遇到报错,记得先检查是不是库没装全,或者代码复制时有没有缺了空格。有任何问题欢迎留言交流~ 加油!

本文出自 AI一族,原文链接:https://www.aiyizu.cn/?p=3706

转发请注明出处,禁止未经允许用于任何商业用途。

文章评分

这篇文章对您有帮助吗?

🤖 随时召唤ZUZU陪你一起探索AI世界
ZUZU 伴学
登录享无限次提问 · 答案仅供参考
ZUZU答:
亲爱的小伙伴您好,我是ZUZU,有什么可以帮您的?😃

分享到

微信
朋友圈
QQ
QQ空间
微博
抖音
小红书
复制
二维码

实用功能

夜间模式
小字
大字
收藏
目录
笔记
朗读
相关
搜索
我的笔记
文章内搜索
相关文章推荐
正在加载相关文章...

反馈建议

您需要登录后才能填写意见反馈信息

分享二维码

使用手机扫描二维码

操作成功