用 Python 从零开始创建神经网络(二十):模型评估

embedded/2025/1/17 0:46:36/

模型评估

  • 引言

引言

在第11章《测试或样本外数据》中,我们讨论了验证数据和测试数据之间的区别。对于目前的模型,我们在训练过程中进行了验证,但目前没有一个好的方法来对测试数据运行测试或进行预测。首先,我们将在Model类中添加一个新的evaluate方法:

python">    # Evaluates the model using passed in datasetdef evaluate(self, X_val, y_val, *, batch_size=None):

此方法接收样本( X v a l X_{val} Xval)、目标输出( y v a l y_{val} yval)以及一个可选的批次大小参数。首先,根据数据的长度和批次大小参数计算步骤数量。这与train方法中的计算方式相同:

python">        # Default value if batch size is not being setvalidation_steps = 1# Calculate number of stepsif batch_size is not None:validation_steps = len(X_val) // batch_size# Dividing rounds down. If there are some remaining# data, but not a full batch, this won't include it# Add `1` to include this not full batchif validation_steps * batch_size < len(X_val):validation_steps += 1

然后,我们将从Model类的train方法中移动一段代码。我们将这段代码以及用于计算步骤数量和重置累积损失与准确率的代码部分移动到evaluate方法中,使其变成:

python">    # Evaluates the model using passed in datasetdef evaluate(self, X_val, y_val, *, batch_size=None):# Default value if batch size is not being setvalidation_steps = 1# Calculate number of stepsif batch_size is not None:validation_steps = len(X_val) // batch_size# Dividing rounds down. If there are some remaining# data, but not a full batch, this won't include it# Add `1` to include this not full batchif validation_steps * batch_size < len(X_val):validation_steps += 1# Reset accumulated values in loss# and accuracy objectsself.loss.new_pass()self.accuracy.new_pass()# Iterate over stepsfor step in range(validation_steps):# If batch size is not set -# train using one step and full datasetif batch_size is None:batch_X = X_valbatch_y = y_val# Otherwise slice a batchelse:batch_X = X_val[step*batch_size:(step+1)*batch_size]batch_y = y_val[step*batch_size:(step+1)*batch_size]# Perform the forward passoutput = self.forward(batch_X, training=False)# Calculate the lossself.loss.calculate(output, batch_y)# Get predictions and calculate an accuracypredictions = self.output_layer_activation.predictions(output)self.accuracy.calculate(predictions, batch_y)# Get and print validation loss and accuracyvalidation_loss = self.loss.calculate_accumulated()validation_accuracy = self.accuracy.calculate_accumulated()# Print a summaryprint(f'validation, ' +f'acc: {validation_accuracy:.3f}, ' +f'loss: {validation_loss:.3f}')

现在,在Model类的train方法中原本放置那段代码的位置,我们可以调用新的evaluate方法:

python"># Model class
class Model:...# def train(self, X, y, *, epochs=1, print_every=1, validation_data=None):def train(self, X, y, *, epochs=1, batch_size=None, print_every=1, validation_data=None):......# If there is the validation dataif validation_data is not None:# Evaluate the model:self.evaluate(*validation_data, batch_size=batch_size)

如果你对*validation_data部分感到困惑,这里的星号(称为“解包表达式”)会将validation_data列表解包为单个值。以下是一个简单的示例,说明其工作原理:

python">a = (1, 2)def test(n1, n2):print(n1, n2)test(*a)
python">>>>
1 2

现在我们有了这个独立的evaluate方法,可以随时评估模型——无论是在训练期间还是按需评估,只需传入验证数据或测试数据即可。首先,我们像往常一样创建并训练一个模型:

python"># Create dataset
X, y, X_test, y_test = create_data_mnist('fashion_mnist_images')# Shuffle the training dataset
keys = np.array(range(X.shape[0]))
np.random.shuffle(keys)
X = X[keys]
y = y[keys]# Scale and reshape samples
X = (X.reshape(X.shape[0], -1).astype(np.float32) - 127.5) / 127.5
X_test = (X_test.reshape(X_test.shape[0], -1).astype(np.float32) - 127.5) / 127.5# Instantiate the model
model = Model()# Add layers
model.add(Layer_Dense(X.shape[1], 128))
model.add(Activation_ReLU())
model.add(Layer_Dense(128, 128))
model.add(Activation_ReLU())
model.add(Layer_Dense(128, 10))
model.add(Activation_Softmax())# Set loss, optimizer and accuracy objects
model.set(loss=Loss_CategoricalCrossentropy(),optimizer=Optimizer_Adam(decay=1e-3),accuracy=Accuracy_Categorical())# Finalize the model
model.finalize()# Train the model
model.train(X, y, validation_data=(X_test, y_test), epochs=10, batch_size=128, print_every=100)

然后我们可以添加代码来进行评估。目前,除了我们用于验证的数据之外,没有其他特定的测试数据,但现在我们可以使用这些数据来测试这个方法:

python">model.evaluate(X_test, y_test)

运行之后,我们得到:

python">>>>
...
epoch: 10
step: 0, acc: 0.906, loss: 0.198 (data_loss: 0.198, reg_loss: 0.000), lr: 0.0001915341888527102
step: 100, acc: 0.930, loss: 0.193 (data_loss: 0.193, reg_loss: 0.000), lr: 0.00018793459875963167
step: 200, acc: 0.922, loss: 0.175 (data_loss: 0.175, reg_loss: 0.000), lr: 0.00018446781036709093
step: 300, acc: 0.922, loss: 0.245 (data_loss: 0.245, reg_loss: 0.000), lr: 0.00018112660749864155
step: 400, acc: 0.898, loss: 0.303 (data_loss: 0.303, reg_loss: 0.000), lr: 0.00017790428749332856
step: 468, acc: 0.938, loss: 0.144 (data_loss: 0.144, reg_loss: 0.000), lr: 0.00017577781683951485
training, acc: 0.915, loss: 0.237 (data_loss: 0.237, reg_loss: 0.000), lr: 0.00017577781683951485
validation, acc: 0.881, loss: 0.334
validation, acc: 0.881, loss: 0.334

验证准确率和损失在末尾重复显示两次,并显示相同的值,因为我们在训练期间进行了验证,并在相同数据上立即进行了评估。通常,你会训练一个模型,调整其超参数,然后重新训练,依此类推,使用传递给训练方法的训练和验证数据。接着,当你找到表现最佳的模型和超参数时,你会将该模型应用于测试数据,并在将来用于生产环境中的预测。

接下来,我们还可以对训练数据进行评估:

python">model.evaluate(X, y)

运行之后打印结果:

python">>>>
validation, acc: 0.915, loss: 0.231

这里的“验证”是指我们对模型进行了评估,但这是使用训练数据完成的。我们将其与刚刚在这些数据上进行的训练结果进行比较:

python">training, acc: 0.915, loss: 0.237 (data_loss: 0.237, reg_loss: 0.000), lr: 0.00017577781683951485

你可能会注意到,尽管使用的是相同的数据集,但准确率和损失值之间仍存在一些差异。这种差异源于以下事实:模型打印的是训练轮次期间累积的准确率和损失,而此时模型仍在学习;因此,平均准确率和损失与训练结束后在训练数据上进行的评估结果有所不同。在训练过程结束时对训练数据运行评估将返回最终的准确率和损失。

在下一章中,我们将添加保存和加载模型的功能;同时,我们还将构建一种方法来获取和设置模型的参数。



本章的章节代码、更多资源和勘误表:https://nnfs.io/ch20


http://www.ppmy.cn/embedded/154515.html

相关文章

Nacos 配置与服务注册问题排查指南

Nacos 配置与服务注册问题排查指南 1. Nacos 配置文件优先级 在 Spring Boot 应用中&#xff0c;配置文件的优先级从高到低依次为&#xff1a; bootstrap.propertiesbootstrap.ymlapplication.propertiesapplication.yml 2. Nacos 配置中心配置示例 以下是一个典型的 Naco…

List 接口的实现类

在 Java 中&#xff0c;List 是一个非常常用的接口&#xff0c;提供了有序、可重复的元素集合。List 接口有多个实现类&#xff0c;每个实现类都有其特定的特性和适用场景。以下是 Java 中主要实现了 List 接口的类及其详细介绍。 1. 常见的 List 实现类 1.1 ArrayList 简介&…

Flink CDC 在阿里云实时计算Flink版的云上实践

摘要&#xff1a;本文整理自阿里云高级开发工程师&#xff0c;Apache Flink Committer 阮航老师在 Flink Forward Asia 2024 生产实践&#xff08;三&#xff09;专场中的分享&#xff0c;主要分为以下四个方面&#xff1a; Flink CDC & 实时计算 Flink CDC YAML 核心功能…

如何从 iPhone 16/15/14 恢复已删除的文件?

在日常使用 iPhone 的过程中&#xff0c;我们经常可能会因为误操作或者设备故障而丢失重要文件。这些文件可能包括照片、联系人、消息等&#xff0c;所有这些对我们的个人或工作生活都至关重要。如果您发现自己处于这种情况&#xff0c;请不要惊慌&#xff01;本文将指导您如何…

深度学习每周学习总结R4(LSTM-实现糖尿病探索与预测)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客R6中的内容&#xff0c;为了便于自己整理总结起名为R4&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 目录 0. 总结1. LSTM介绍LSTM的基本组成部分如何理解与应用LSTM 2. 数据预处理3. 数…

C#知识|泛型Generic概念与方法

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 关于泛型在前面学习记录过 《泛型集合List相关方法》、《Dictionary泛型集合的使用总结》&#xff1b; 其中泛型集合 List<T>、Dictionary<k,v>所在的命名空间为&#xff1a;System.Collection.Generic…

初步认识 Neo4j 图数据库

Neo4j 是一种高性能的图数据库管理系统&#xff0c;基于图论设计&#xff0c;能够高效地存储和查询复杂的关系数据。以下是关于 Neo4j 的详细介绍&#xff1a; 核心特性 数据模型&#xff1a; Neo4j 使用图数据模型&#xff0c;将数据以节点&#xff08;Node&#xff09;、关系…

mysql,PostgreSQL,Oracle数据库sql的细微差异(2) [whith as; group by; 日期引用]

sql示例(MySQL) WITHtemp1 AS (SELECT name AS resultsFROM Users uJOIN MovieRating m ON u.user_id m.user_idGROUP BY m.user_idORDER BY COUNT(*) DESC,left(name,1)LIMIT 1),temp2 AS (SELECT title AS resultsFROM Movies mJOIN MovieRating r ON m.movie_id r.movie_…