# 归一化任务

把大数量级特征转化到较小的数量级下,通常是[0, 1]或[-1, 1]

# 为何要归一化

  • 绝大多数 tensorflow.js 的模型都不是给特别大的数设计的
  • 将不同数量级的特征转换到同一数量级,防止某个特征影响过大

# 初始数据

import * as tf from "@tensorflow/tfjs";
import * as tfvis from "@tensorflow/tfjs-vis";

window.onload = () => {
  const heigths = [150, 160, 170];
  const weights = [40, 50, 60];

  tfvis.render.scatterplot(
    { name: "身高体重训练数据" },
    { values: heigths.map((x, i) => ({ x, y: weights[i] })) },
    { xAxisDomain: [140, 180], yAxisDomain: [30, 70] }
  );
};
1
2
3
4
5
6
7
8
9
10
11
12
13

# 归一化操作

import * as tf from "@tensorflow/tfjs";
import * as tfvis from "@tensorflow/tfjs-vis";

window.onload = () => {
  const heigths = [150, 160, 170];
  const weights = [40, 50, 60];

  tfvis.render.scatterplot(
    { name: "身高体重训练数据" },
    { values: heigths.map((x, i) => ({ x, y: weights[i] })) },
    { xAxisDomain: [140, 180], yAxisDomain: [30, 70] }
  );
  // ----------------------------------------------------------------
  // 归一化操作

  // 输入值归一化
  // 数组的数据先减去最小值 150,然后再除以间距 20 ,这样数据就被处理成了归一化的 [0,1]之间的数了
  const inputs = tf
    .tensor(heigths)
    .sub(150)
    .div(20);
  inputs.print(); // Tensor [0, 0.5, 1]
  const labels = tf
    .tensor(weights)
    .sub(40)
    .div(20);
  labels.print(); // Tensor [0, 0.5, 1]

  // ----------------------------------------------------------------
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 训练,预测,反归一化

import * as tf from "@tensorflow/tfjs";
import * as tfvis from "@tensorflow/tfjs-vis";
import { mod, input } from "@tensorflow/tfjs";

window.onload = async () => {
  const heigths = [150, 160, 170];
  const weights = [40, 50, 60];

  tfvis.render.scatterplot(
    { name: "身高体重训练数据" },
    { values: heigths.map((x, i) => ({ x, y: weights[i] })) },
    { xAxisDomain: [140, 180], yAxisDomain: [30, 70] }
  );

  // 归一化操作

  // 输入值归一化
  // 数组的数据先减去最小值 150,然后再除以间距 20 ,这样数据就被处理成了归一化的 [0,1]之间的数了
  const inputs = tf
    .tensor(heigths)
    .sub(150)
    .div(20);
  const labels = tf
    .tensor(weights)
    .sub(40)
    .div(20);

  // 训练,预测,反归一化

  const model = tf.sequential();
  model.add(tf.layers.dense({ units: 1, inputShape: [1] }));
  model.compile({
    loss: tf.losses.meanSquaredError,
    optimizer: tf.train.sgd(0.1)
  });

  await model.fit(inputs, labels, {
    batchSize: 3,
    epochs: 100,
    callbacks: tfvis.show.fitCallbacks({ name: "训练过程" }, ["loss"])
  });

  // 预测数据需要归一化
  const output = model.predict(
    tf
      .tensor([180])
      .sub(150)
      .div(20)
  );
  alert(
    `如果身高为 180cm, 那么预测体重为 ${
      output
        .mul(20)
        .add(40)
        .dataSync()[0]
    }`
  );
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

tensorflow