5. 准备数据以用于训练
为了享有 TensorFlow.js 的性能优势,从而让训练机器学习模型切实可行,我们需要将数据转换为张量。我们还会对数据执行许多转换(这是最佳做法),即重排和归一化。
将以下代码添加到您的
script.js 文件中
/*** Convert the input data to tensors that we can use for machine* learning. We will also do the important best practices of _shuffling_* the data and _normalizing_ the data* MPG on the y-axis.*/function convertToTensor(data) {// Wrapping these calculations in a tidy will dispose any// intermediate tensors.return tf.tidy(() => {// Step 1. Shuffle the datatf.util.shuffle(data);// Step 2. Convert data to Tensorconst inputs = data.map(d => d.horsepower)const labels = data.map(d => d.mpg);const inputTensor = tf.tensor2d(inputs, [inputs.length, 1]);const labelTensor = tf.tensor2d(labels, [labels.length, 1]);//Step 3. Normalize the data to the range 0 - 1 using min-max scalingconst inputMax = inputTensor.max();const inputMin = inputTensor.min();const labelMax = labelTensor.max();const labelMin = labelTensor.min();const normalizedInputs = inputTensor.sub(inputMin).div(inputMax.sub(inputMin));const normalizedLabels = labelTensor.sub(labelMin).div(labelMax.sub(labelMin));return {inputs: normalizedInputs,labels: normalizedLabels,// Return the min/max bounds so we can use them later.inputMax,inputMin,labelMax,labelMin,}});}
我们来详细了解一下发生哪些情况。
重排数据
// Step 1. Shuffle the datatf.util.shuffle(data);
我们会随机排列提供给训练算法的样本的顺序。数据重排很重要,因为在训练期间,数据集通常会被拆分成较小的子集(称为批次),以用于训练模型。借助重排,每个批次可从分布的所有数据中获取各种数据。通过这样做,我们可以帮助模型:
- 不学习纯粹依赖于数据输入顺序的东西
- 对子组中的结构不敏感(例如,如果模型在训练的前半部分仅看到高马力汽车,可能会学习一种不适用于数据集其余部分的关系)。
最佳做法 1:您应始终重排数据,然后再将其传递给 TensorFlow.js 中的训练算法
转换为张量
// Step 2. Convert data to Tensorconst inputs = data.map(d => d.horsepower)const labels = data.map(d => d.mpg);const inputTensor = tf.tensor2d(inputs, [inputs.length, 1]);const labelTensor = tf.tensor2d(labels, [labels.length, 1]);
我们会创建两个数组,一个用于输入样本(马力条目),另一个用于真实输出值(在机器学习中称为标签)。
然后,将每个数组数据转换为 2d 张量。张量的形状将为 [num_examples, num_features_per_example]。我们使用的是 inputs.length 样本,每个样本都具有 1 输入特征(马力)。
对数据进行归一化
//Step 3. Normalize the data to the range 0 - 1 using min-max scalingconst inputMax = inputTensor.max();const inputMin = inputTensor.min();const labelMax = labelTensor.max();const labelMin = labelTensor.min();const normalizedInputs = inputTensor.sub(inputMin).div(inputMax.sub(inputMin));const normalizedLabels = labelTensor.sub(labelMin).div(labelMax.sub(labelMin));
接下来,我们将实施另一种最佳做法来进行机器学习训练。我们会对数据进行归一化。我们使用最小-最大缩放比例)将数据归一化为数值范围 0-1。归一化至关重要,因为您将使用 tensorflow.js 构建的许多机器学习模型的内部构件旨在处理不太大的数字。对数据进行归一化以包含 0 to 1 或 -1 to 1 的通用范围。如果您养成将数据归一化到某合理范围内的习惯,那么在训练模型时就更有可能取得成功。
最佳做法 2:在训练之前,您应始终考虑对数据进行归一化。某些数据集无需进行归一化即可学习,但是对数据进行归一化通常会消除一类妨碍有效学习的问题。
您可以在将数据转换为张量之前对其进行归一化。我们之所以这样做,是因为我们可以利用 TensorFlow.js 中的矢量化来执行最小最大缩放操作,而无需编写任何明确的 for 循环。
返回数据和归一化边界
return {inputs: normalizedInputs,labels: normalizedLabels,// Return the min/max bounds so we can use them later.inputMax,inputMin,labelMax,labelMin,}
我们希望保留训练期间用于归一化的值,以便我们可以将输出取消归一化,以使其恢复到原始比例,并且使我们能以相同方式对今后的输入数据进行归一化。
