TensorFlow Model


Shuffling Data
Always shuffle data before training.

When a model is trained, the data is divided into small sets (batches). Each batch is then fed to the model. Shuffling is important to prevent the model getting the same data over again. If using the same data twice, the model will not be able to generalize the data and give the right output. Shuffling gives a better variety of data in each batch.

tf.util.shuffle( data );

TensorFlow Tensors
To use TensorFlow, input data needs to be converted to tensor data:

// Mapping x values to Tensor inputs
const inputs = values.map( obj => obj.x );
// Mapping y values to Tensor labels
const labels = values.map( obj => obj.y );

// Converting inputs and labels to 2d tensors
const inputTensor = tf.tensor2d( inputs, [ inputs.length, 1 ] );
const labelTensor = tf.tensor2d( labels, [ labels.length, 1 ] );

Data Normalization
Data should be normalized before being used in a neural network. A range of 0 - 1 using min-max are often best for numerical data:

const inputMin = inputTensor.min( );
const inputMax = inputTensor.max( );
const labelMin = labelTensor.min( );
const labelMax = labelTensor.max( );
const nmInputs = inputTensor.sub( inputMin ).div( inputMax.sub( inputMin ) );
const nmLabels = labelTensor.sub( labelMin ).div( labelMax.sub( labelMin ) );

http://undcemcs01.und.edu/~wen.chen.hu/course/525/13/car.html
<html>
 <head>
  <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
  <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-vis"></script>
  <title>Car TensorFlow.js</title>
 </head>
 <body>
  <form>
   Horsepower:
   <input name="hp" id="hp" size="7" value="85" />
   <input type="button" onClick="runTF( )" value="Train and test" />
   <input type="reset" />
   The predicted MPG is <span id="answer">0.00</span> miles per gallon.
   <div id="plot1"></div>
   <div id="plot2"></div>
  </form>

  <script>
   // Extracting the required data 
   function extractData( obj ) {
    return { x:obj.Horsepower, y:obj.Miles_per_Gallon };
   }
   function removeErrors( obj ) {
    return ( ( obj.x != null ) && ( obj.y != null ) );
   }

   // Plotting the extracted data
   function tfPlot( values, surface ) {
    tfvis.render.scatterplot( surface,
     { values:values, series:[ 'Original', 'Predicted' ] },
     { xLabel:'Horsepower', yLabel:'MPG' } );
   }

   // Main function
   async function runTF( ) {
    const jsonData = await fetch( "carsData.json" );
    let values = await jsonData.json( );
    values = values.map( extractData ).filter( removeErrors );

    // Plotting the Data
    const surface1 = document.getElementById( "plot1" );
    const surface2 = document.getElementById( "plot2" );
    tfPlot( values, surface1 );

    // Converting the input to Tensors
    const inputs = values.map( obj => obj.x );
    const labels = values.map( obj => obj.y );
    const inputTensor = tf.tensor2d( inputs, [inputs.length, 1] );
    const labelTensor = tf.tensor2d( labels, [labels.length, 1] );
    const inputMin = inputTensor.min( );  
    const inputMax = inputTensor.max( );
    const labelMin = labelTensor.min( );
    const labelMax = labelTensor.max( );
    const nmInputs = inputTensor.sub(inputMin).div( inputMax.sub(inputMin) );
    const nmLabels = labelTensor.sub(labelMin).div( labelMax.sub(labelMin) );

    // Creating a Tensorflow model
    const model = tf.sequential( ); 
    model.add( tf.layers.dense( { inputShape:[1], units:1, useBias:true } ) );
    model.add( tf.layers.dense( { units: 1, useBias: true } ) );
    model.compile( { loss:'meanSquaredError', optimizer:'sgd' } );

    // Starting training
    await trainModel( model, nmInputs, nmLabels, surface2 );

    // Un-normalizing the data
    let unX = tf.linspace( 0, 1, 100 );      
    let unY = model.predict( unX.reshape( [100, 1] ) );      
    const unNormunX = unX
     .mul( inputMax.sub( inputMin ) )
     .add( inputMin );
    const unNormunY = unY
     .mul( labelMax.sub( labelMin ) )
     .add( labelMin );
    unX = unNormunX.dataSync( );
    unY = unNormunY.dataSync( );

    // Testing the model
    const predicted = Array.from(unX).map( (val, i) => {
     return { x: val, y: unY[i] }
    } );
    tfPlot( [values, predicted], surface1 );

    // Finding the MPG of the input horsepower  
    var hp = parseInt( document.getElementById( "hp" ).value );
    unX.sort( ( a, b ) => a[0] - b[0] );
    let x1 = unX[0];
    for ( let i = 1; i < unX.length-1; i++ ) {
     let x2 = unX[i];
     if ( ( x1 <= hp ) && ( hp < x2 ) ) {
      document.getElementById("answer").innerHTML = Math.round( unY[i-1] );
      break;
     }
     x1 = x2;
    }
   }     // End of the main function runTF( )

   // Asyncronous function to train the model
   async function trainModel( model, inputs, labels, surface ) {
    const batchSize = 25;
    const epochs = 50;
    const callbacks = tfvis.show.fitCallbacks(
     surface, ['loss'], { callbacks:['onEpochEnd'] } );
    return await model.fit( inputs, labels,
     { batchSize, epochs, shuffle:true, callbacks:callbacks } );
   }     // End of trainModel
  </script>
 </body>
</html>