前文我们已经实现了对每批数据的训练,下面继续实现一轮完整的训练。
完整的训练循环
一轮训练就是对训练数据的每个批量都重复上述训练步骤,而完整的训练循环就是重复多轮训练。
def fit(model, images, labels, epochs, batch_size=128):
for epoch_counter in range(epochs):
print(f"Epoch {epoch_counter}")
batch_generator = BatchGenerator(images, labels)
for batch_counter in range(batch_generator.num_batches):
images_batch, labels_batch = batch_generator.next()
loss = one_training_step(model, images_batch, labels_batch)
if batch_counter % 100 == 0:
print(f"loss at batch {batch_counter}: {loss:.2f}")
我们来试运行一下。
from tensorflow.keras.datasets import mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype("float32") / 255
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype("float32") / 255
fit(model, train_images, train_labels, epochs=10, batch_size=128)
评估模型
我们可以评估模型,方法是对模型在测试图像上的预测值取argmax,并将其与预期标签进行比较。
predictions = model(test_images)
predictions = predictions.numpy() ←----对TensorFlow张量调用.numpy(),可将其转换为NumPy张量
predicted_labels = np.argmax(predictions, axis=1)
matches = predicted_labels == test_labels
print(f"accuracy: {matches.mean():.2f}")
用几行Keras代码就能完成的工作,手动实现起来还是挺费劲的。但手动实现一遍之后可以清楚地了解在调用fit()时神经网络内部都发生了什么。拥有这种对代码底层原理的思维模型,可以更好地使用Keras API的高级功能。
总结
张量构成了现代机器学习系统的基石。它具有不同的dtype(数据类型)、rank(阶)、shape(形状)等。
可以通过张量运算(比如加法、张量积或逐元素乘法)对数值张量进行操作。这些运算可看作几何变换。一般来说,深度学习的所有内容都有几何解释。
深度学习模型由简单的张量运算链接而成,它以权重为参数,权重就是张量。模型权重保存的是模型所学到的“知识”。
学习是指找到一组模型参数值,使模型在一组给定的训练数据样本及其对应目标值上的损失函数最小化。
学习的过程:随机选取包含数据样本及其目标值的批量,计算批量损失相对于模型参数的梯度。随后将模型参数沿着梯度的反方向移动一小步(移动距离由学习率决定)。这个过程叫作小批量随机梯度下降。
整个学习过程之所以能够实现,是因为神经网络中所有张量运算都是可微的。因此,可以利用求导链式法则来得到梯度函数。这个函数将当前参数和当前数据批量映射为一个梯度值。这一步叫作反向传播。在将数据输入模型之前,你需要先对损失和优化器进行定义。
损失是在训练过程中需要最小化的量。它衡量的是当前任务是否已成功解决。优化器是利用损失梯度对参数进行更新的具体方式,比如RMSprop优化器、带动量的随机梯度下降(SGD)等。
接下来总结一下我们的实现代码。
NaiveDense层实现了下述功能:
1.初始化权重,w,b
2.实现前向传播
3.提供查询和修改权重的接口
模型NaiveSequence实现了下述功能:
1.保存模型的各个层
2.调用模型的所有层进行前向传播
批量生成器:
1.封装原始数据
2.根据批量的大小对原始数据进行迭代,不会循环!只遍历一次
一轮训练:
1.定义梯度带
2.对批量数据进行前向传播
3.计算损失
4.计算平均损失
5.利用梯度带计算平均损失相对于模型权重的梯度
6.利用梯度更新权重
完整的训练循环:
1.利用批量生成器对原始数据进行切割迭代
2.利用原始数据对模型进行训练。
3.所有原始数据对模型更新一次叫做一个epoch
4.进行epochs的模型更新
5.计算模型指标
说个无关的话题,python语法的元组打包/拆包功能真好用!如果大家python0基础,但是熟悉其它编程语言,可以直接查看python与c系列语言的差异文章快速入门。
本文以及前文的代码可以直接在python环境下赋值张贴然后运行。(前提是计算机安装了TensorFlow库以及计算机可以联网)