index.html完整代码
<!DOCTYPE html><html><head> <title>TensorFlow.js Tutorial</title> <!-- Import TensorFlow.js --> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js"></script> <!-- Import tfjs-vis --> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-vis@1.0.2/dist/tfjs-vis.umd.min.js"></script> <!-- Import the main script file --> <script src="script.js"></script></head><body></body></html>
script.js完整代码
/** * Get the car data reduced to just the variables we are interested * and cleaned of missing data. */async function getData() { const carsDataResponse = await fetch('https://storage.googleapis.com/tfjs-tutorials/carsData.json'); const carsData = await carsDataResponse.json(); const cleaned = carsData.map(car => ({ mpg: car.Miles_per_Gallon, horsepower: car.Horsepower, })) .filter(car => (car.mpg != null && car.horsepower != null)); return cleaned;}async function run() { // Load and plot the original input data that we are going to train on. const data = await getData(); const values = data.map(d => ({ x: d.horsepower, y: d.mpg, })); tfvis.render.scatterplot({ name: 'Horsepower v MPG' }, { values }, { xLabel: 'Horsepower', yLabel: 'MPG', height: 300 }); // More code will be added below const model = createModel(); tfvis.show.modelSummary({ name: 'Model Summary' }, model); // Convert the data to a form we can use for training. const tensorData = convertToTensor(data); const { inputs, labels } = tensorData; // Train the model await trainModel(model, inputs, labels); console.log('Done Training'); // Make some predictions using the model and compare them to the // original data testModel(model, data, tensorData);}document.addEventListener('DOMContentLoaded', run);function createModel() { // Create a sequential model const model = tf.sequential(); // Add a single input layer // dense 是一种层,可将输入与矩阵(称为“权重”)相乘,并向结果添加一个数字(称为“偏差”) // inputShape 是 [1],因为我们将 1 数字用作输入(某辆指定汽车的马力) // units 用于设置权重矩阵在层中的大小。将其设置为 1 即表示数据的每个输入特征的权重为 1 model.add(tf.layers.dense({ inputShape: [1], units: 1, useBias: true })); model.add(tf.layers.dense({ units: 10, activation: 'sigmoid' })); model.add(tf.layers.dense({ units: 20, activation: 'sigmoid' })); // model.add(tf.layers.dense({ units: 50, activation: 'sigmoid' })); // Add an output layer model.add(tf.layers.dense({ units: 1, useBias: true })); return model;}/** * Convert the input data to tensors that we can use for machine * learning. We will also do the important best practices of _shuffling_ * the data and _normalizing_ the data * MPG on the y-axis. * 数据重排和归一化 */function convertToTensor(data) { // 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 => d.horsepower) const labels = data.map(d => 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, } });}// 创建模型实例并将数据表示为张量之后,我们就可以开始训练过程了。async function trainModel(model, inputs, labels) { // 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'] }) });}// 预测function testModel(model, inputData, normalizationData) { 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 => ({ 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 });}