首页 > 解决方案 > “从 2D 数据进行预测”代码实验室在每次刷新时给出随机结果

问题描述

我一直在关注这个代码实验室,但是我在测试经过训练的模型时得到的结果看起来很错误,代码实验室显示了这个图表

在此处输入图像描述

但是当我运行下面的代码时,直接取自代码实验室,我的图表看起来像这样..

在此处输入图像描述

如果我再次刷新,我会得到 在此处输入图像描述

再一次 在此处输入图像描述

为什么每次页面刷新的结果差异如此之大?

我曾尝试延迟测试,但没有更好的结果

      setTimeout(function(){ 
        console.log('Testing');
        testModel(model, data, tensorData);
       }, 6000);

我不明白为什么它们看起来如此不同,我的代码如下......

import React, { useEffect } from "react";
import * as tf from "@tensorflow/tfjs";
import * as tfvis from "@tensorflow/tfjs-vis";

function App() {
  useEffect(() => {
    const testModel = (model: any, inputData: any, normalizationData: any) => {
      const {inputMax, inputMin, labelMin, labelMax} = normalizationData;  

      // Generate predictions for a uniform range of numbers between 0 and 1;
      // We un-normalize the data by doing the inverse of the min-max scaling 
      // that we did earlier.
      const [xs, preds] = tf.tidy(() => {

        const xs = tf.linspace(0, 1, 100);      
        const preds = model.predict(xs.reshape([100, 1]));      

        const unNormXs = xs
          .mul(inputMax.sub(inputMin))
          .add(inputMin);

        const unNormPreds = preds
          .mul(labelMax.sub(labelMin))
          .add(labelMin);

        // Un-normalize the data
        return [unNormXs.dataSync(), unNormPreds.dataSync()];
      });


      const predictedPoints = Array.from(xs).map((val, i) => {
        return {x: val, y: preds[i]}
      });

      const originalPoints = inputData.map((d:any) => ({
        x: d.horsepower, y: d.mpg,
      }));


      tfvis.render.scatterplot(
        {name: 'Model Predictions vs Original Data'}, 
        {values: [originalPoints, predictedPoints], series: ['original', 'predicted']}, 
        {
          xLabel: 'Horsepower',
          yLabel: 'MPG',
          height: 300
        }
      );
    }

    function convertToTensor(data:any) {
      // Wrapping these calculations in a tidy will dispose any 
      // intermediate tensors.

      return tf.tidy(() => {
        // Step 1. Shuffle the data    
        tf.util.shuffle(data);

        // Step 2. Convert data to Tensor
        const inputs = data.map((d:any) => d.horsepower)
        const labels = data.map((d:any) => 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 scaling
        const 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,
        }
      });  
    }
    const trainModel = async(model:any, inputs:any, labels:any) => {
      // Prepare the model for training.  
      model.compile({
        optimizer: tf.train.adam(),
        loss: tf.losses.meanSquaredError,
        metrics: ['mse'],
      });

      const batchSize = 32;
      const epochs = 50;

      return await model.fit(inputs, labels, {
        batchSize,
        epochs,
        shuffle: true,
        callbacks: tfvis.show.fitCallbacks(
          { name: 'Training Performance' },
          ['loss', 'mse'], 
          { height: 200, callbacks: ['onEpochEnd'] }
        )
      });
    }

    const createModel = () => {
      // Create a sequential model
      const model = tf.sequential(); 
      // Add a single input layer
      model.add(tf.layers.dense({inputShape: [1], units: 1, useBias: true}));
      // Add an output layer
      model.add(tf.layers.dense({units: 1, useBias: true}));
      return model;
    }

    const getData = async () => {
      const carsDataReq = await fetch("https://storage.googleapis.com/tfjs-tutorials/carsData.json");
      const carsData = await carsDataReq.json();
      const cleaned = carsData.map((car: any) => ({
          mpg: car.Miles_per_Gallon,
          horsepower: car.Horsepower
        }))
        .filter((car:any) => car.mpg != null && car.horsepower != null);
      return cleaned;
    }



    const run = async () => {
      const data = await getData();
      const values = data.map((d:any) => ({
        x: d.horsepower,
        y: d.mpg,
      }));

      tfvis.render.scatterplot(
        {name: 'Horsepower v MPG'},
        {values}, 
        {
          xLabel: 'Horsepower',
          yLabel: 'MPG',
          height: 300
        }
      );
      const model = createModel();  
      tfvis.show.modelSummary({name: 'Model Summary'}, model);

      const tensorData = convertToTensor(data);
      const {inputs, labels} = tensorData;

      // Train the model  
      await trainModel(model, inputs, labels);
      console.log('Done Training');
      testModel(model, data, tensorData);
    }
    run();
  });

  return <div className="App"></div>;
}

export default App;

标签: reactjstensorflowtensorflow.js

解决方案


每次刷新的预测值都不同,因为每次刷新都有新的训练。模型权重用随机值初始化。在训练期间,权重可以收敛到最佳值或发散。这取决于许多参数。实际上,即使是最好的模型也不会总是在固定数量的训练时期收敛。

为了始终具有相同的值,可以使用固定数据设置权重的初始值。但同样如何找到能够产生最佳预测的数据呢?找到这些权重并不总是那么容易。初始化层权重的一种简单方法是使用层权重kernelInitializer

model.add(tf.layers.dense({inputShape: [1], units: 1, useBias: true, kernelInitializer : 'zeros'}));

这个新层的权重将初始化为 0。也可以使用ones。其他初始化器是可能的。使用固定权重,预测不会改变。但实际上,由于上​​述原因,权重很少被初始化,除非人们确定哪些可能的值会导致良好的准确性。另一方面,跟踪模型的准确性并在模型具有令人满意的准确性时创建一个检查点。


推荐阅读