完整教程:神经网络(①MNIST 手写数字识别)

️ 创建虚拟环境

python -m venv ai

这会在当前目录下生成一个名为 ai/ 的文件夹,里面包含独立的 Python 解释器和库环境。

️ 激活虚拟环境

.\ai\Scripts\Activate

️ 安装依赖

pip install tensorflow matplotlib numpy

MNIST 数据集会自动从网络下载一次,并缓存在本地是这个代码

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()

默认下载位置

Windows: C:\Users\<你的用户名>\.keras\datasets\

当你在代码里加上:

import os
os.environ["KERAS_HOME"] = "."

然后运行

from tensorflow.keras.datasets import mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()

Keras 会检查当前目录下是否存在 datasets/ 文件夹:

如果没有,它会自动新建 datasets/ 文件夹;

然后把 mnist.npz 下载到 ./datasets/mnist.npz;

以后再运行时,就直接从这个文件读取,不会重复下载。

MNIST 手写数字识别

import os
# 设置 Keras 数据集缓存目录为当前目录
os.environ["KERAS_HOME"] = "."
import tensorflow as tf
from tensorflow.keras import layers, models
import matplotlib.pyplot as plt
import numpy as np
# 1. 加载数据集(会下载到 ./datasets/mnist.npz)
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
# 2. 数据预处理:归一化到 0-1
x_train = x_train.astype("float32") / 255.0
x_test  = x_test.astype("float32") / 255.0
# 3. 构建模型(全连接网络)
model = models.Sequential([
layers.Flatten(input_shape=(28, 28)),   # 把28x28展开成784维
layers.Dense(128, activation="relu"),   # 隐藏层
layers.Dense(10, activation="softmax")  # 输出层,10个类别
])
# 4. 编译模型
model.compile(optimizer="adam",
loss="sparse_categorical_crossentropy",
metrics=["accuracy"])
# 5. 训练模型
history = model.fit(x_train, y_train,
epochs=5, batch_size=128,
validation_split=0.2)
# 6. 评估模型
test_loss, test_acc = model.evaluate(x_test, y_test)
print("测试集准确率:", test_acc)
# 7. 预测示例
sample = x_test[0].reshape(1, 28, 28)
prediction = model.predict(sample)
print("预测结果:", np.argmax(prediction), "真实标签:", y_test[0])
# 8. 可视化预测结果
plt.imshow(x_test[0], cmap="gray")
plt.title(f"预测: {np.argmax(prediction)} / 真实: {y_test[0]}")
plt.show()

训练集 (train)

(x_train, y_train)
用来“教”模型,让模型在这些数据上学习规律。
x_train:输入数据(手写数字图片)
y_train:对应的标签(真实数字 0–9)
比如:一张 28×28 的图片 → 标签是 7。

测试集 (test)

(x_test, y_test)
用来“考”模型,检验它学得好不好。
这些数据模型在训练过程中没见过,所以能反映模型的泛化能力。
x_test:测试图片
y_test:真实标签

train 是“教科书”,test 是“考试卷”。模型要在教科书上学习,在考试卷上验证。

像素值归一化 ≠ “非黑即白”。

正确理解

原始像素值:灰度图里每个像素是 0–255 的整数。

0 = 黑
255 = 白
中间值(比如 128)= 灰色

归一化:把 0–255 的范围缩放到 0–1 的小数范围。

0 → 0.0
128 → 0.5
255 → 1.0


️ 1. 28×28 → Flatten → 784 维

28×28:一张 MNIST 手写数字图片就是一个 28 行 × 28 列的“像素矩阵”。

可以想象成一张小小的方格纸,每个格子里有一个像素值(0–255)。

Flatten:把二维的 28×28 矩阵“拉直”成一行。

28×28 = 784,所以就变成了一个长度为 784 的向量。

类比:把一张 28 行的表格一行一行抄下来,拼成一长串数字。

输入层:神经网络的第一层就是接收这 784 个数字作为输入。

2. 隐藏层(Hidden Layer)

位置:输入层和输出层之间的“中间计算层”。

作用:提取特征。

比如:某些神经元可能学会识别“竖线”,某些学会识别“弯曲”,某些学会识别“交叉”。

128 个神经元:就像有 128 个小专家,每个专家都在关注不同的特征。

激活函数 ReLU:让这些神经元能学到非线性特征(比如弯曲,而不仅仅是直线)。

类比:

输入层 = 原始像素(原材料)

隐藏层 = 工厂里的工人(加工原材料,提取有用特征)

3. 输出层(Output Layer)

10 个神经元:对应数字 0–9。

Softmax:把输出转成概率分布。

比如模型输出:

[0.01, 0.02, 0.95, 0.01, 0.01, 0, 0, 0, 0, 0]

→ 意思是“95% 的概率是数字 2”。

最终预测:取概率最大的那个数字。

Softmax

作用:把一堆数字,变成“概率分布”。

举个例子: 模型最后输出了 10 个数(对应数字 0–9):

[2.0, 1.0, 0.1, 3.0, 0.5, ...]

Softmax 会把它们转成概率:

[0.1, 0.05, 0.02, 0.7, 0.03, ...]

每个数都在 0–1 之间

所有数加起来 = 1

最大的那个概率就是模型的预测结果

类比: 就像一场选举,10 个候选人(数字 0–9)都拿到一些票数,Softmax 会把票数换算成“得票率”,最后得票率最高的就是预测结果。

ReLU

公式:f(x) = max(0, x)

如果输入是正数 → 原样输出

如果输入是负数 → 直接变成 0

所以 ReLU 的作用就是:只保留有用的正信号,把负的干扰信号清零

隐藏层

一个神经元的计算:

h = 激活函数( 权重 × 输入 + 偏置 )

1. 输入(784 个像素)

想象你要判断一张手写数字图片是不是“数字 7”。

输入就是这张图片的 784 个像素值(28×28)。

每个像素就是一个小信号:黑、灰、白。

2. 权重(重要性系数)

神经元不会把所有像素都当成一样重要。

比如:

“数字 7 的斜线”区域 → 权重大(更重要)。

“空白背景”区域 → 权重小(不重要)。

所以每个输入像素都会乘上一个“权重”。

类比: 你在考试判卷时,“大题”分值高(权重大),小题分值低(权重小)。

3. 加权求和 + 偏置

把所有像素 × 权重 的结果加起来,得到一个总分。

然后再加一个 偏置 b,相当于“调节门槛”。

类比:

就像你要判断一个人是不是“高个子”:

输入 = 身高(比如 180cm)

权重 = 1(身高很重要)

偏置 = -170(门槛)

结果 = 180×1 - 170 = 10 → 大于 0,说明“是高个子”。

4. 激活函数 (ReLU)

现在我们有了一个数值(可能是正的,也可能是负的)。

ReLU 的规则:

如果结果 ≤ 0 → 输出 0(神经元不激活,沉默)。

如果结果 > 0 → 输出这个数(神经元激活,点亮)。

类比:

就像一个“灯泡开关”:

电流不足(≤0) → 灯泡不亮。

电流够大(>0) → 灯泡亮起来。


权重和偏置不是你手动一个个去设置的,而是模型在训练过程中自动学出来的参数

训练前

权重 (Weights):一开始会被随机初始化成一些很小的数(不是全 0,也不是你自己设定的固定值)。

偏置 (Biases):通常初始化为 0 或一个小数。

这样做的目的是:让每个神经元一开始“看法不同”,避免大家都学到一样的东西。

训练中

当你把训练数据(比如 MNIST 的手写数字)输入网络:

前向传播:网络根据当前的权重和偏置算出预测结果。

计算误差:预测结果和真实标签对比,得到“损失值”。

反向传播:根据误差,计算每个权重和偏置应该往哪个方向调整。

梯度下降(优化器 Adam/SGD 等):一步步更新权重和偏置,让预测越来越准。

所以,权重和偏置是 自动更新的,不是你手动调的。

posted @ 2025-10-22 20:11  yjbjingcha  阅读(1)  评论(0)    收藏  举报