5. 准备数据以用于训练

为了享有 TensorFlow.js 的性能优势,从而让训练机器学习模型切实可行,我们需要将数据转换为张量。我们还会对数据执行许多转换(这是最佳做法),即重排归一化

将以下代码添加到您的
script.js 文件中

  1. /**
  2. * Convert the input data to tensors that we can use for machine
  3. * learning. We will also do the important best practices of _shuffling_
  4. * the data and _normalizing_ the data
  5. * MPG on the y-axis.
  6. */
  7. function convertToTensor(data) {
  8. // Wrapping these calculations in a tidy will dispose any
  9. // intermediate tensors.
  10. return tf.tidy(() => {
  11. // Step 1. Shuffle the data
  12. tf.util.shuffle(data);
  13. // Step 2. Convert data to Tensor
  14. const inputs = data.map(d => d.horsepower)
  15. const labels = data.map(d => d.mpg);
  16. const inputTensor = tf.tensor2d(inputs, [inputs.length, 1]);
  17. const labelTensor = tf.tensor2d(labels, [labels.length, 1]);
  18. //Step 3. Normalize the data to the range 0 - 1 using min-max scaling
  19. const inputMax = inputTensor.max();
  20. const inputMin = inputTensor.min();
  21. const labelMax = labelTensor.max();
  22. const labelMin = labelTensor.min();
  23. const normalizedInputs = inputTensor.sub(inputMin).div(inputMax.sub(inputMin));
  24. const normalizedLabels = labelTensor.sub(labelMin).div(labelMax.sub(labelMin));
  25. return {
  26. inputs: normalizedInputs,
  27. labels: normalizedLabels,
  28. // Return the min/max bounds so we can use them later.
  29. inputMax,
  30. inputMin,
  31. labelMax,
  32. labelMin,
  33. }
  34. });
  35. }


我们来详细了解一下发生哪些情况。

重排数据

  1. // Step 1. Shuffle the data
  2. tf.util.shuffle(data);

我们会随机排列提供给训练算法的样本的顺序。数据重排很重要,因为在训练期间,数据集通常会被拆分成较小的子集(称为批次),以用于训练模型。借助重排,每个批次可从分布的所有数据中获取各种数据。通过这样做,我们可以帮助模型:

  • 不学习纯粹依赖于数据输入顺序的东西
  • 对子组中的结构不敏感(例如,如果模型在训练的前半部分仅看到高马力汽车,可能会学习一种不适用于数据集其余部分的关系)。

    最佳做法 1:您应始终重排数据,然后再将其传递给 TensorFlow.js 中的训练算法

转换为张量

  1. // Step 2. Convert data to Tensor
  2. const inputs = data.map(d => d.horsepower)
  3. const labels = data.map(d => d.mpg);
  4. const inputTensor = tf.tensor2d(inputs, [inputs.length, 1]);
  5. const labelTensor = tf.tensor2d(labels, [labels.length, 1]);

我们会创建两个数组,一个用于输入样本(马力条目),另一个用于真实输出值(在机器学习中称为标签)。

然后,将每个数组数据转换为 2d 张量。张量的形状将为 [num_examples, num_features_per_example]。我们使用的是 inputs.length 样本,每个样本都具有 1 输入特征(马力)。

对数据进行归一化

  1. //Step 3. Normalize the data to the range 0 - 1 using min-max scaling
  2. const inputMax = inputTensor.max();
  3. const inputMin = inputTensor.min();
  4. const labelMax = labelTensor.max();
  5. const labelMin = labelTensor.min();
  6. const normalizedInputs = inputTensor.sub(inputMin).div(inputMax.sub(inputMin));
  7. const normalizedLabels = labelTensor.sub(labelMin).div(labelMax.sub(labelMin));

接下来,我们将实施另一种最佳做法来进行机器学习训练。我们会对数据进行归一化。我们使用最小-最大缩放比例)将数据归一化为数值范围 0-1。归一化至关重要,因为您将使用 tensorflow.js 构建的许多机器学习模型的内部构件旨在处理不太大的数字。对数据进行归一化以包含 0 to 1 或 -1 to 1 的通用范围。如果您养成将数据归一化到某合理范围内的习惯,那么在训练模型时就更有可能取得成功。

最佳做法 2:在训练之前,您应始终考虑对数据进行归一化。某些数据集无需进行归一化即可学习,但是对数据进行归一化通常会消除一类妨碍有效学习的问题。

您可以在将数据转换为张量之前对其进行归一化。我们之所以这样做,是因为我们可以利用 TensorFlow.js 中的矢量化来执行最小最大缩放操作,而无需编写任何明确的 for 循环。

返回数据和归一化边界

  1. return {
  2. inputs: normalizedInputs,
  3. labels: normalizedLabels,
  4. // Return the min/max bounds so we can use them later.
  5. inputMax,
  6. inputMin,
  7. labelMax,
  8. labelMin,
  9. }


我们希望保留训练期间用于归一化的值,以便我们可以将输出取消归一化,以使其恢复到原始比例,并且使我们能以相同方式对今后的输入数据进行归一化。