4. TensorFlow模型训练基础(一):环境搭建与手写数字识别
好,咱们正式开始动手了。这一章的目标很明确——把TensorFlow环境搭起来,然后用一个最简单的全连接网络,把MNIST手写数字识别跑通。说白了,就是先让模型“动起来”,后面再谈怎么优化、怎么移植到STM32上。
我个人习惯把环境搭建放在第一步。很多初学者一上来就写代码,结果跑不通,最后发现是Python版本不对或者CUDA没装好。嗯,咱们先把地基打牢。
4.1 TensorFlow环境搭建
TensorFlow支持CPU和GPU两种模式。如果你只是做模型验证和轻量训练,CPU版完全够用。但如果你要训练稍大一点的网络,我建议还是用GPU版,速度快很多。
4.1.1 安装步骤(Windows/Linux通用)
- 安装Python:推荐3.8~3.10版本。我遇到过3.11装TF报错的情况,所以别追新。
- 创建虚拟环境(强烈建议):
python -m venv tf_env tf_env\Scripts\activate # Windows source tf_env/bin/activate # Linux - 安装TensorFlow:
pip install tensorflow==2.10.0 - 验证安装:
python -c "import tensorflow as tf; print(tf.__version__)"
pip install tensorflow 装到最新版,结果跟CUDA版本不匹配,训练时直接报错。后来我养成了习惯——先查TF官方文档的“Build from source”页面,确认CUDA和cuDNN的对应版本再装。
4.1.2 环境验证清单
| 组件 | 推荐版本 | 验证命令 |
|---|---|---|
| Python | 3.8 ~ 3.10 | python --version |
| TensorFlow | 2.10.0 | tf.__version__ |
| Keras | 2.10.0(随TF自带) | tf.keras.__version__ |
| NumPy | 1.24.3 | np.__version__ |
4.2 Keras Sequential API入门
Keras的Sequential API,说白了就是“搭积木”。你一层一层往上加,模型就搭好了。我个人觉得这是最适合入门的方式——代码直观,逻辑清晰。
你想想看,一个神经网络无非就是:输入层 → 隐藏层 → 输出层。Sequential API让你用.add()方法一层层堆叠,跟写清单一样简单。
4.2.1 核心概念
- 层(Layer):
Dense(全连接层)、Conv2D(卷积层)、Flatten(展平层)等。 - 激活函数:
relu、softmax、sigmoid。 - 损失函数:分类用
categorical_crossentropy或sparse_categorical_crossentropy。 - 优化器:
adam、sgd。
categorical_crossentropy;如果标签是整数(如2),用sparse_categorical_crossentropy。选错了会报错,我刚开始就犯过这个错。
4.3 全连接网络实现手写数字识别(MNIST)
MNIST数据集是深度学习的“Hello World”。28×28像素的手写数字图片,0到9共10个类别。咱们用全连接网络来识别它。
4.3.1 数据加载与预处理
import tensorflow as tf
from tensorflow.keras.datasets import mnist
# 加载数据
(x_train, y_train), (x_test, y_test) = mnist.load_data()
# 归一化:把0-255的像素值缩放到0-1之间
x_train = x_train.astype('float32') / 255.0
x_test = x_test.astype('float32') / 255.0
# 展平:把28x28的二维图像变成一维向量(784个像素)
x_train = x_train.reshape(-1, 784)
x_test = x_test.reshape(-1, 784)
# 标签转one-hot编码
y_train = tf.keras.utils.to_categorical(y_train, 10)
y_test = tf.keras.utils.to_categorical(y_test, 10)
4.3.2 构建模型
model = tf.keras.Sequential([
tf.keras.layers.Dense(128, activation='relu', input_shape=(784,)),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
# 编译模型
model.compile(
optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy']
)
# 查看模型结构
model.summary()
这个网络结构很简单:输入784个像素 → 128个神经元(ReLU) → 64个神经元(ReLU) → 10个输出(Softmax)。你想想看,这其实就是在做“特征提取+分类”。
4.3.3 模型训练
history = model.fit(
x_train, y_train,
batch_size=32,
epochs=10,
validation_split=0.2,
verbose=1
)
训练时你会看到loss逐渐下降,accuracy逐渐上升。一般来说,10个epoch后测试集准确率能到97%以上。嗯,这个网络虽然简单,但效果还不错。
4.4 模型保存与加载(.h5格式)
训练好的模型要保存下来,后面才能转成STM32能用的格式。我个人习惯保存成.h5格式,兼容性好,Keras原生支持。
4.4.1 保存模型
# 保存整个模型(结构+权重+优化器状态)
model.save('mnist_fc_model.h5')
# 或者只保存权重(更轻量)
model.save_weights('mnist_fc_weights.h5')
4.4.2 加载模型
from tensorflow.keras.models import load_model
# 加载完整模型
loaded_model = load_model('mnist_fc_model.h5')
# 验证加载是否正确
loss, accuracy = loaded_model.evaluate(x_test, y_test)
print(f'Test accuracy: {accuracy:.4f}')
4.5 本章知识体系
下面这张图把本章的核心流程串起来了。从环境搭建到模型保存,每一步都是后面移植的基础。
4.6 完整代码示例
下面是一份可以直接运行的完整代码。你复制到Python文件里,跑一遍,就能看到训练过程和保存的模型文件。
import tensorflow as tf
from tensorflow.keras.datasets import mnist
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.utils import to_categorical
# 1. 加载数据
(x_train, y_train), (x_test, y_test) = mnist.load_data()
# 2. 预处理
x_train = x_train.reshape(-1, 784).astype('float32') / 255.0
x_test = x_test.reshape(-1, 784).astype('float32') / 255.0
y_train = to_categorical(y_train, 10)
y_test = to_categorical(y_test, 10)
# 3. 构建模型
model = Sequential([
Dense(128, activation='relu', input_shape=(784,)),
Dense(64, activation='relu'),
Dense(10, activation='softmax')
])
# 4. 编译
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
# 5. 训练
model.fit(x_train, y_train,
batch_size=32,
epochs=10,
validation_split=0.2,
verbose=1)
# 6. 评估
loss, acc = model.evaluate(x_test, y_test, verbose=0)
print(f'Test accuracy: {acc:.4f}')
# 7. 保存
model.save('mnist_fc_model.h5')
print('Model saved as mnist_fc_model.h5')
嗯,这一章的内容就到这里。环境搭好了,模型跑通了,文件也保存了。后面的事情,就是怎么把这个模型塞进STM32里——那才是咱们这门课的核心。不过别急,先把基础打牢,后面自然水到渠成。