iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 9
0
自我挑戰組

Tensorflow.js初學筆記系列 第 9

Day8 初探TensorFlow.js,不用設定環境的機器學習

  • 分享至 

  • xImage
  •  

進入TensorFlow.js的世界

Making predictions from 2d data

Day8 初探TensorFlow.js,不用設定環境的機器學習

論效能瀏覽器內的TensorFlow.js比不上原生TensorFlow(Python版本)
速度比較

但要使用的時候完全不用設定環境,只要有瀏覽器(必須支持WebGL,但哪加沒有?),就可以進行開發跟試驗了。
1.在HTML中載入TensorFlow.js的程式碼

    <!-- TensorFlow.js Core -->
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.2.7/dist/tf.min.js"></script>
    <!-- TensorFlow.js Visualiztion -->
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-vis@1.1.0/dist/tfjs-vis.umd.min.js"></script>

.首先先載入Google預設好的測試檔案

let tutorial_data_path='https://storage.googleapis.com/tfjs-tutorials/carsData.json';
async function getData() {
    //拿到資料
    const carsDataReq = await fetch(tutorial_data_path);
    //轉成JSON
    const carsData = await carsDataReq.json();
    //將Miles_per_Gallon跟.Horsepower取出
    //篩掉空資料
    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 visualiztion() {
  const values = (await getData()).map(d => ({
    x: d.horsepower,
    y: d.mpg,
  }));
  tfvis.render.scatterplot(
    {name: 'Horsepower v MPG'},
    {values}, 
    {
      xLabel: 'Horsepower',
      yLabel: 'MPG',
      height: 300
    }
  );
}
document.addEventListener('DOMContentLoaded', visualiztion);

基本上會看到這張圖擬和圖

可以看出馬力與單位加侖走的距離呈現負相關
這樣的資料還不錯,看得出來有一定的模式,如果沒有任何隱藏的關聯,也就是說資料間事隨機的話,機器是學習不到什麼東西的
那他這裡的目標是透過機器學習,建立一個可以用馬力來預測單位加侖走的距離的模型
接下來就是建立模型了

function createModel() {
    // Create a sequential model
    const model = tf.sequential();

    // Add a single hidden layer
    model.add(tf.layers.dense({ inputShape: [1], units: 20, useBias: true }));
    model.add(tf.layers.dense({units: 50, activation: 'sigmoid'}));
    model.add(tf.layers.dense({units: 10, activation: 'sigmoid'}));
    // Add an output layer
    model.add(tf.layers.dense({ units: 1, useBias: true }));

    // 加入最佳化的求解器、用MSE做為損失計算方式
    model.compile({
        optimizer: tf.train.adam(),
        loss: tf.losses.meanSquaredError,
        metrics: ['mse'],
    });
    return model;
}

首先是創造TensorFlow裡面的Model
API中,顯示TensorFlow.js 1.2.7版本有兩種創建模型的方式,一種是上面用的tf.sequential(),另外一種是tf.model(),兩者的差別是tf.sequential()提供的神經元網路層與層是線性堆疊的,而tf.model()定義的神經元網路層與層之間的關係較為隨意。

然後就要把資料轉成Tensor

function convertToTensor(data) {
    // 使用tf.tidy讓除了回傳值以外,中間過程中的所佔用的空間釋放掉
    return tf.tidy(() => {
        // 打亂資料,在訓練最好都要做打亂資料的動作 
        tf.util.shuffle(data);
        // 將資料轉成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]);
        //取最大值與最小值
        const inputMax = inputTensor.max();
        const inputMin = inputTensor.min();
        const labelMax = labelTensor.max();
        const labelMin = labelTensor.min();
        //正規化 將 (tensor內的資料-最小值)/(最大值-最小值)) 出來的結果在0-1之間
        const normalizedInputs = inputTensor.sub(inputMin).div(inputMax.sub(inputMin));
        const normalizedLabels = labelTensor.sub(labelMin).div(labelMax.sub(labelMin));
        return {
            inputs: normalizedInputs,
            labels: normalizedLabels,
            inputMax,
            inputMin,
            labelMax,
            labelMin,
        }
    });
}

接下來就是訓練的程式碼

async function trainModel(model, inputs, labels) {
    //每次訓練的樣本數
    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'] }
        )
    });
}

把上面得程式拼在一起

async function runTensorFlow(){
    const model = createModel();
    const data = await getData();
    const tensorData = convertToTensor(data);
    await trainModel(model, tensorData.inputs, tensorData.labels);
    console.log('Done Training');
}
document.addEventListener('DOMContentLoaded', runTensorFlow);

這時候會看到類似這樣的圖
圖片來自TensorFlow.js Tutorial

嘗試預測資料

function getPrediction(model, normalizationData) {
    const { inputMax, inputMin, labelMin, labelMax } = normalizationData;
    return tf.tidy(() => {
        //tf.linspace(start_value,end_value,number_of_value);
        const input_x = tf.linspace(0, 1, 100);
        //將產生的資料轉成[num_examples, num_features_per_example]
        const preds = model.predict(input_x.reshape([100, 1]));
        //轉回原本的數= 數字*(最大值-最小值)+最小值
        const toOrignalX = input_x
            .mul(inputMax.sub(inputMin))
            .add(inputMin);
        const toOrignalY = preds
            .mul(labelMax.sub(labelMin))
            .add(labelMin);
        //tensor.dataSync() return data from tensor to array
        return [toOrignalX.dataSync(), toOrignalY.dataSync()];
    });
}

將預測資料視覺化

function visualiztionPrediction(originalData,predictedData){
    const originalPoints = originalData.map(d => ({
        x: d.horsepower, y: d.mpg,
    }));
    const [px,py]=predictedData;
    const predictedPoints = Array.from(px).map((val, i) => {
        return {x: val, y: py[i]}
    });
    tfvis.render.scatterplot(
    {name: 'Model Predictions vs Original Data'}, 
    {values: [originalPoints, predictedPoints], series: ['original', 'predicted']}, 
    {
      xLabel: 'Horsepower',
      yLabel: 'MPG',
      height: 300
    }
  );
}

加到執行過程

async function runTensorFlow(){
    const model = createModel();
    const data = await getData();
    const tensorData = convertToTensor(data);
    await trainModel(model, tensorData.inputs, tensorData.labels);
    console.log('Done Training');
    const predictedData= getPrediction(model,tensorData);
    visualiztionPrediction(data,predictedData)
}

這時候會看到最後的結果,完成了簡單的回歸


上一篇
Day7 Tensorflow.js機器學習Part7
下一篇
Day9 TensorFlow.js: MNIST手寫數字辨識
系列文
Tensorflow.js初學筆記27
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言