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.
1 | tf.util.shuffle( data ); |
|
TensorFlow Tensors
To use TensorFlow, input data needs to be converted to tensor data:
2 | const inputs = values.map( obj => obj.x ); |
4 | const labels = values.map( obj => obj.y ); |
7 | const inputTensor = tf.tensor2d( inputs, [ inputs.length, 1 ] ); |
8 | 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:
1 | const inputMin = inputTensor.min( ); |
2 | const inputMax = inputTensor.max( ); |
3 | const labelMin = labelTensor.min( ); |
4 | const labelMax = labelTensor.max( ); |
5 | const nmInputs = inputTensor.sub( inputMin ).div( inputMax.sub( inputMin ) ); |
6 | const nmLabels = labelTensor.sub( labelMin ).div( labelMax.sub( labelMin ) ); |
|
|
http://undcemcs01.und.edu/~wen.chen.hu/course/525/13/car.html
|
|
005 | <title>Car TensorFlow.js</title> |
010 | <input name= "hp" id= "hp" size= "7" value= "85" /> |
011 | <input type= "button" onClick= "runTF( )" value= "Train and test" /> |
012 | <input type= "reset" /> |
013 | The predicted MPG is <span id= "answer" >0.00</span> miles per gallon. |
014 | <div id= "plot1" ></div> |
015 | <div id= "plot2" ></div> |
020 | function extractData( obj ) { |
021 | return { x:obj.Horsepower, y:obj.Miles_per_Gallon }; |
023 | function removeErrors( obj ) { |
024 | return ( ( obj.x != null ) && ( obj.y != null ) ); |
028 | function tfPlot( values, surface ) { |
029 | tfvis.render.scatterplot( surface, |
030 | { values:values, series:[ 'Original' , 'Predicted' ] }, |
031 | { xLabel: 'Horsepower' , yLabel: 'MPG' } ); |
035 | async function runTF( ) { |
036 | const jsonData = await fetch( "carsData.json" ); |
037 | let values = await jsonData.json( ); |
038 | values = values.map( extractData ).filter( removeErrors ); |
041 | const surface1 = document.getElementById( "plot1" ); |
042 | const surface2 = document.getElementById( "plot2" ); |
043 | tfPlot( values, surface1 ); |
046 | const inputs = values.map( obj => obj.x ); |
047 | const labels = values.map( obj => obj.y ); |
048 | const inputTensor = tf.tensor2d( inputs, [inputs.length, 1] ); |
049 | const labelTensor = tf.tensor2d( labels, [labels.length, 1] ); |
050 | const inputMin = inputTensor.min( ); |
051 | const inputMax = inputTensor.max( ); |
052 | const labelMin = labelTensor.min( ); |
053 | const labelMax = labelTensor.max( ); |
054 | const nmInputs = inputTensor.sub(inputMin).div( inputMax.sub(inputMin) ); |
055 | const nmLabels = labelTensor.sub(labelMin).div( labelMax.sub(labelMin) ); |
058 | const model = tf.sequential( ); |
059 | model.add( tf.layers.dense( { inputShape:[1], units:1, useBias: true } ) ); |
060 | model.add( tf.layers.dense( { units: 1, useBias: true } ) ); |
061 | model.compile( { loss: 'meanSquaredError' , optimizer: 'sgd' } ); |
064 | await trainModel( model, nmInputs, nmLabels, surface2 ); |
067 | let unX = tf.linspace( 0, 1, 100 ); |
068 | let unY = model.predict( unX.reshape( [100, 1] ) ); |
069 | const unNormunX = unX |
070 | .mul( inputMax.sub( inputMin ) ) |
072 | const unNormunY = unY |
073 | .mul( labelMax.sub( labelMin ) ) |
075 | unX = unNormunX.dataSync( ); |
076 | unY = unNormunY.dataSync( ); |
079 | const predicted = Array.from(unX).map( (val, i) => { |
080 | return { x: val, y: unY[i] } |
082 | tfPlot( [values, predicted], surface1 ); |
085 | var hp = parseInt( document.getElementById( "hp" ).value ); |
086 | unX.sort( ( a, b ) => a[0] - b[0] ); |
088 | for ( let i = 1; i < unX.length-1; i++ ) { |
090 | if ( ( x1 <= hp ) && ( hp < x2 ) ) { |
091 | document.getElementById( "answer" ).innerHTML = Math.round( unY[i-1] ); |
099 | async function trainModel( model, inputs, labels, surface ) { |
100 | const batchSize = 25; |
102 | const callbacks = tfvis.show.fitCallbacks( |
103 | surface, [ 'loss' ], { callbacks:[ 'onEpochEnd' ] } ); |
104 | return await model.fit( inputs, labels, |
105 | { batchSize, epochs, shuffle: true , callbacks:callbacks } ); |
|