# 多分类(iris 鸢尾花分类问题)

# 代码展示

import * as tf from '@tensorflow/tfjs';
import * as tfvis from '@tensorflow/tfjs-vis';
import { getIrisData, IRIS_CLASSES } from './data';
import { accuracy } from '@tensorflow/tfjs-vis/dist/util/math';

window.onload = async () => {
  /*获取训练集和验证集数据*/
  const [xTrain, yTrain, xTest, yText] = getIrisData(0.15); // 15%的数据作为验证集
  console.log('xTrain', xTrain);
  console.log('yTrain', yTrain);
  console.log('xTest', xTest);
  console.log('yText', yText);
  console.log('IRIS_CLASSES', IRIS_CLASSES);

  /*初始化模型*/
  const model = tf.sequential();

  /*添加层*/
  model.add(
    tf.layers.dense({
      units: 10, // 神经元个数(超参数自己估计调整值)
      inputShape: [xTrain.shape[1]], // 长度为4的一维数组
      activation: 'sigmoid', // 只要能带来非线性的变化都行
    })
  );

  model.add(
    tf.layers.dense({
      units: 3, // 输出类别的个数(花有3类)
      activation: 'softmax', // 输出一个各值和为1的的数组data.js
    })
  );

  /*设置损失函数和优化器*/
  model.compile({
    loss: 'categoricalCrossentropy',
    optimizer: tf.train.adam(0.1),
    metrics: ['accuracy'], // 制定度量单位(制作损失曲线)
  });

  /*训练*/
  await model.fit(xTrain, yTrain, {
    epochs: 100,
    validationData: [xTest, yText], // 验证集(格式和训练集一样)
    callbacks: tfvis.show.fitCallbacks(
      { name: '训练效果' },
      ['loss', 'val_loss', 'acc', 'val_acc'], // 训练集损失/验证集损失/训练集准确度/验证集准确度
      { callbacks: ['onEpochEnd'] } // 只显示onEpochEnd
    ),
  });

  window.predict = (form) => {
    const input = tf.tensor([
      [form.a.value * 1, form.b.value * 1, form.c.value * 1, form.d.value * 1],
    ]);
    const pred = model.predict(input);
    alert(`预测结果:${IRIS_CLASSES[pred.argMax(1).dataSync(0)]}`); // argMax输出某个维度的最大值
  };
};

# 重点笔记

  • 验证集是用来验证模型是否训练好了的,验证集和训练集的数据结构是一摸一样的,都包含了输入特征和标签。在实际工作中,验证集往往是从训练集分一部分出来的。训练集是用于训练神经网络的,神经网络的权重会因为训练集的数据而变化。而验证集仅仅作验证作用。

  • 如何加载验证集,训练集和验证集的损失和准确度

  • 可视化化准确度,准确度的设置。准确度是指预测的结果和真实的结果的对比

  • 通过训练集里面可以通过 data.shape[1]获取特征长度也就是 inputShape 所需要的值

  • 本示例的第一层激活函数可以使用任意一种带来非线性变化的激活函数,最后一层使用 softmax 即可

  • 输出类别有三类(三种花)所以最后一层的神经元个数为 3,才能输出三个概率。并且使用 softmax 使得概率和为 1

  • 设置准确度的度量单位在 model.compile 中的 metrics 中设置

/*设置损失函数和优化器*/
model.compile({
  loss: 'categoricalCrossentropy',
  optimizer: tf.train.adam(0.1),
  metrics: ['accuracy'], // 制定度量单位(制作损失曲线)
});
  • 丢入验证集在 model.fit 中的第三个参数中的 validationData 总设置如下

  • callbacks 中视图 tfvis.show.fitCallbacks 第二个参数是数组--度量,其中 ['loss', 'val_loss', 'acc', 'val_acc'], // 训练损失/验证损失/训练准确度/验证准确度

  • tfvis.show.fitCallbacks 第三个参数{ callbacks: ['onEpochEnd'] }标识显示的种类,如图只显示 onEpochEnd 就少了 onBatchEnd

await model.fit(xTrain, yTrain, {
  epochs: 100,
  validationData: [xTest, yText], // 验证集(格式和训练集一样)
  callbacks: tfvis.show.fitCallbacks(
    { name: '训练效果' },
    ['loss', 'val_loss', 'acc', 'val_acc'], // 训练集损失/验证集损失/训练集准确度/验证集准确度
    { callbacks: ['onEpochEnd'] } // 只显示onEpochEnd
  ),
});
  • 输入的数据要和训练的数据保持一致,所以是一个二维数组

  • argMax 可以输出某个纬度的最大值的坐标,配合 IRIS_CLASSES 可以获取到预测的最大可能结果。 argMax 是一个 tensor,.dataSync(0)转换成前端值

const pred = model.predict(input);
alert(`预测结果:${IRIS_CLASSES[pred.argMax(1).dataSync(0)]}`); // argMax获取第x+1维数据的最大值,比如想获取第二维就传1第一维就传0