TensorFlow.js - Membuat Prediksi dari Data 2D

Dalam codelab ini, Anda akan melatih model untuk membuat prediksi dari data numerik yang menjelaskan sekumpulan mobil.

Latihan ini akan menunjukkan langkah-langkah umum untuk melatih berbagai jenis model, tetapi akan menggunakan set data kecil dan model sederhana (dangkal). Tujuan utamanya adalah membantu Anda memahami istilah, konsep, dan sintaksis dasar seputar model pelatihan dengan TensorFlow.js dan menyediakan batu loncatan untuk eksplorasi dan pembelajaran lebih lanjut.

Karena kita melatih model untuk memprediksi bilangan berkelanjutan, tugas ini terkadang disebut sebagai tugas regresi. Kita akan melatih model dengan menampilkan banyak contoh input disertai dengan output yang benar. Ini disebut sebagai pembelajaran yang diawasi.

Hal yang akan Anda buat

Anda akan membuat halaman web yang menggunakan TensorFlow.js untuk melatih model di browser. Dengan mempertimbangkan “Tenaga kuda” pada sebuah mobil, model ini akan memprediksi “Mil per Galon” (MPG) untuk mobil tersebut.

Untuk melakukannya, Anda akan:

  • Memuat data dan menyiapkannya untuk pelatihan.
  • Menentukan arsitektur model.
  • Melatih model dan memantau performanya saat model tersebut berlatih.
  • Mengevaluasi model yang dilatih dengan membuat beberapa prediksi.

Hal yang akan Anda pelajari

  • Praktik terbaik untuk persiapan data untuk machine learning, termasuk pengacakan dan normalisasi.
  • Sintaksis TensorFlow.js untuk membuat model menggunakan tf.layers API.
  • Cara memantau pelatihan dalam browser menggunakan library tfjs-vis.

Hal yang akan Anda perlukan

Membuat halaman HTML dan menyertakan JavaScript

96914ff65fc3b74c.png Salin kode berikut ke file html yang dipanggil

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>

Membuat file JavaScript untuk kode

  1. Dalam folder yang sama dengan file HTML di atas, buat file yang disebut script.js dan masukkan kode berikut ke dalamnya.
console.log('Hello TensorFlow');

Melakukan pengujian

Setelah Anda mendapatkan file HTML dan JavaScript, uji file tersebut. Buka file index.html di browser dan buka konsol devtools.

Jika semuanya berfungsi, akan ada dua variabel global yang dibuat dan tersedia di konsol devtools:

  • tf adalah referensi ke library TensorFlow.js
  • tfvis adalah referensi ke library tfjs-vis

Buka alat developer browser, di sana Anda akan melihat pesan yang bertuliskan Hello TensorFlow dalam output konsol. Jika demikian, Anda siap melanjutkan ke langkah berikutnya.

Sebagai langkah pertama, mari kita muat, format, dan visualisasikan data yang ingin digunakan untuk melatih model.

Kami akan memuat set data "mobil" dari file JSON yang telah kami hosting untuk Anda. Set data ini berisi berbagai fitur tentang setiap mobil yang diberikan. Untuk tutorial ini, kami hanya ingin mengekstrak data tentang Tenaga kuda dan Mil Per Galon.

96914ff65fc3b74c.png Tambahkan kode berikut ke file

script.js Anda

/**
 * 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;
}

Tindakan ini juga akan menghapus entri yang tidak memiliki mil per galon atau tenaga kuda yang ditentukan. Mari kita petakan data ini dalam diagram sebar untuk melihat tampilannya.

96914ff65fc3b74c.png Tambahkan kode berikut ke bagian bawah file

script.js Anda.

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
}

document.addEventListener('DOMContentLoaded', run);

Saat Anda memuat ulang halaman. Anda akan melihat panel di sisi kiri halaman dengan diagram sebar yang berisi data. Tampilannya akan terlihat seperti berikut.

cf44e823106c758e.png

Panel ini dikenal sebagai visor dan disediakan oleh tfjs-vis. Panel ini menyediakan tempat yang nyaman untuk menampilkan visualisasi.

Umumnya saat menangani data, sebaiknya cari cara untuk melihat data Anda dan membersihkannya jika perlu. Dalam hal ini, kita harus menghapus entri tertentu dari carsData yang tidak memiliki semua kolom wajib diisi. Memvisualisasikan data dapat memberikan gambaran tentang apakah ada struktur pada data yang dapat dipelajari model.

Kita dapat melihat dari pemetaan data di atas bahwa ada korelasi negatif antara tenaga kuda dan MPG, yaitu saat tenaga kuda naik, mobil umumnya mendapatkan lebih sedikit mil per galon.

Membuat konsep tugas

Data input kita sekarang akan terlihat seperti ini.

...
{
  "mpg":15,
  "horsepower":165,
},
{
  "mpg":18,
  "horsepower":150,
},
{
  "mpg":16,
  "horsepower":150,
},
...

Tujuan kita adalah melatih model yang akan mengambil satu angka, Tenaga kuda, dan mempelajari cara memprediksi satu angka, Mil per Galon. Ingatlah pemetaan one-to-one tersebut, karena akan penting untuk bagian berikutnya.

Kita akan memasukkan contoh ini, tenaga kuda dan MPG, ke jaringan neural yang akan mempelajari formula (atau fungsi) untuk memprediksi MPG dengan tenaga kuda tertentu dari contoh ini. Berdasarkan contoh ini, pembelajaran yang kita dapatkan jawabannya disebut Pembelajaran yang Diawasi.

Di bagian ini, kita akan menuliskan kode untuk menjelaskan arsitektur model. Arsitektur model juga bisa dianggap sebagai "fungsi yang akan dijalankan model saat dieksekusi", atau "algoritme yang akan digunakan model untuk menghitung jawabannya".

Model ML adalah algoritme yang mengambil input dan menghasilkan output. Ketika menggunakan jaringan neural, algoritme adalah sekumpulan lapisan neuron dengan 'bobot' (angka) yang mengatur output-nya. Proses pelatihan mempelajari nilai yang cocok untuk bobot tersebut.

96914ff65fc3b74c.png Tambahkan fungsi berikut ke

file script.js Anda untuk menentukan arsitektur model.

function 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;
}

Ini adalah salah satu model yang paling sederhana yang dapat kita tentukan di tensorflow.js, mari sedikit kita uraikan setiap barisnya.

Membuat instance model

const model = tf.sequential();

Tindakan ini akan membuat instance objek tf.Model. Model ini sequential karena input-nya mengalir langsung ke output-nya. Jenis model lainnya dapat memiliki cabang, atau bahkan beberapa input dan output, tetapi dalam banyak kasus, model Anda akan berurutan. Model berurutan juga memiliki API yang lebih mudah digunakan.

Menambahkan lapisan

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

Tindakan ini menambahkan lapisan input ke jaringan, yang secara otomatis terhubung ke lapisan dense dengan satu unit tersembunyi. Lapisan dense adalah jenis lapisan yang mengalikan input-nya dengan matriks (disebut bobot), lalu menambahkan angka (disebut bias) ke hasilnya. Karena ini adalah lapisan pertama jaringan, kita perlu menentukan inputShape. inputShape adalah [1] karena kita memiliki angka 1 sebagai input (tenaga kuda mobil tertentu).

units menetapkan seberapa besar matriks bobot dalam lapisan. Dengan menyetelnya ke 1 di sini, artinya akan ada 1 bobot untuk setiap fitur input data.

model.add(tf.layers.dense({units: 1}));

Kode di atas menghasilkan lapisan output. Kita menetapkan units ke 1 karena ingin menghasilkan output angka 1.

Membuat instance

96914ff65fc3b74c.png Tambahkan kode berikut ke fungsi

run yang telah kita tentukan sebelumnya.

// Create the model
const model = createModel();
tfvis.show.modelSummary({name: 'Model Summary'}, model);

Tindakan ini akan membuat instance model dan menampilkan ringkasan lapisan di halaman web.

Untuk mendapatkan manfaat performa TensorFlow.js yang membuat model machine learning pelatihan menjadi praktis, kita perlu melakukan konversi data menjadi tensor. Kita juga akan melakukan sejumlah transformasi pada data yang merupakan praktik terbaik, yaitu pengacakan dan normalisasi.

96914ff65fc3b74c.png Tambahkan kode berikut ke file

script.js Anda

/**
 * 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,
    }
  });
}

Mari uraikan apa yang terjadi di sini.

Mengacak data

// Step 1. Shuffle the data
tf.util.shuffle(data);

Di sini, kita mengacak urutan contoh yang akan kita masukkan ke algoritme pelatihan. Pengacakan itu penting karena biasanya selama pelatihan, set data dibagi menjadi subset yang lebih kecil, yang disebut batch, tempat model dilatih. Pengacakan membantu setiap batch memiliki berbagai data dari seluruh distribusi data. Dengan melakukannya, kita membantu model:

  • Tidak mempelajari hal-hal yang murni bergantung pada urutan data dimasukkan
  • Tidak peka terhadap struktur di subgrup (misalnya jika hanya melihat mobil bertenaga kuda tinggi untuk paruh pertama dalam pelatihannya, model ini dapat mempelajari hubungan yang tidak berlaku di seluruh set data).

Melakukan konversi ke tensor

// 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]);

Di sini, kita membuat dua array. Satu untuk contoh input (entri tenaga kuda), dan satu lagi untuk nilai output yang benar (yang dikenal sebagai label dalam machine learning).

Kemudian kita mengonversi setiap data array ke tensor 2d. Tensor akan memiliki bentuk [num_examples, num_features_per_example]. Di sini, kita memiliki contoh inputs.length dan setiap contoh memiliki 1 fitur input (tenaga kuda).

Menormalisasi data

//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));

Selanjutnya, kita akan melakukan praktik terbaik lainnya untuk pelatihan machine learning. Kita menormalisasi data. Di sini, kita menormalisasi data menjadi rentang numerik 0-1 menggunakan penskalaan min-maks. Normalisasi penting untuk dilakukan karena bagian internal dari banyak model machine learning yang akan Anda build dengan tensorflow.js dirancang agar dapat berfungsi dengan angka yang tidak terlalu besar. Rentang umum untuk menormalisasi data agar menyertakan 0 to 1 atau -1 to 1. Anda akan lebih berhasil dalam melatih model jika sudah terbiasa menormalisasi data ke beberapa rentang yang wajar.

Mengembalikan data dan batas normalisasi

return {
  inputs: normalizedInputs,
  labels: normalizedLabels,
  // Return the min/max bounds so we can use them later.
  inputMax,
  inputMin,
  labelMax,
  labelMin,
}

Kita ingin mempertahankan nilai yang digunakan untuk normalisasi selama pelatihan, sehingga kita dapat membatalkan normalisasi output agar mengembalikannya ke skala awal dan agar kita dapat menormalisasi data input mendatang dengan cara yang sama.

Dengan instance model yang dibuat dan data yang direpresentasikan sebagai tensor, kita memiliki semua hal yang diperlukan untuk memulai proses pelatihan.

96914ff65fc3b74c.png Salin fungsi berikut ke file

script.js Anda.

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'] }
    )
  });
}

Mari bahas secara mendetail.

Bersiap untuk pelatihan

// Prepare the model for training.
model.compile({
  optimizer: tf.train.adam(),
  loss: tf.losses.meanSquaredError,
  metrics: ['mse'],
});

Kita harus 'mengompilasi' model sebelum melatihnya. Untuk melakukannya, kita harus menentukan sejumlah hal yang sangat penting:

  • optimizer: Ini adalah algoritme yang akan mengatur pembaruan pada model saat melihat contoh. Tersedia banyak pengoptimal di TensorFlow.js. Di sini, kita telah memilih pengoptimal adam karena cukup efektif dalam praktiknya dan tidak memerlukan konfigurasi.
  • loss: ini adalah fungsi yang akan memberi tahu model seberapa baik performanya dalam mempelajari setiap batch (subset data) yang ditampilkan. Di sini, kita menggunakan meanSquaredError untuk membandingkan prediksi yang dibuat oleh model dengan nilai yang benar.
const batchSize = 32;
const epochs = 50;

Selanjutnya, kita memilih ukuran batch dan sejumlah iterasi pelatihan:

  • batchSize mengacu pada ukuran subset data yang akan dilihat model pada setiap iterasi pelatihan. Ukuran batch umum cenderung berada dalam rentang 32-512. Tidak ada ukuran batch yang benar-benar ideal untuk semua masalah dan hal ini di luar cakupan tutorial ini untuk menjelaskan motivasi matematis untuk berbagai ukuran batch.
  • epochs mengacu pada berapa kali model akan melihat seluruh set data yang Anda berikan. Di sini, kita akan mengambil 50 iterasi melalui set data.

Memulai loop pelatihan

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

model.fit adalah fungsi yang kita panggil untuk memulai loop pelatihan. Ini adalah fungsi asinkron, sehingga kita mengembalikan promise yang diberikannya agar pemanggil dapat menentukan kapan pelatihan selesai.

Untuk memantau progres pelatihan, kita meneruskan beberapa callback ke model.fit. Kita menggunakan tfvis.show.fitCallbacks untuk membuat fungsi yang memetakan diagram untuk metrik 'kerugian' dan 'grk' yang telah ditentukan sebelumnya.

Merangkum pemahaman

Sekarang kita harus memanggil fungsi yang telah kita tentukan dari fungsi run.

96914ff65fc3b74c.png Tambahkan kode berikut ke bagian bawah fungsi

run Anda

// 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');

Saat Anda memuat ulang halaman, setelah beberapa detik Anda akan melihat grafik berikut yang diperbarui.

c6d3214d6e8c3752.png

Ini dibuat oleh callback yang telah kita buat sebelumnya. Grafik ini menampilkan kerugian dan grk, yang dirata-ratakan di seluruh set data, di akhir setiap iterasi pelatihan.

Saat melatih model, kita ingin melihat kerugian menurun. Dalam hal ini, karena metrik kita adalah ukuran error, kita juga ingin melihatnya menurun.

Setelah model dilatih, kita ingin membuat beberapa prediksi. Mari kita evaluasi model dengan melihat apa yang diprediksi untuk rentang yang sama dengan jumlah tenaga kuda dari rendah hingga tinggi.

96914ff65fc3b74c.png Tambahkan fungsi berikut ke file script.js Anda

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
    }
  );
}

Beberapa hal yang perlu diperhatikan dalam fungsi di atas.

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

Kita membuat 100 'contoh' baru untuk dimasukkan ke model. Model.predict adalah cara kita memasukkan contoh tersebut ke dalam model. Perhatikan bahwa contoh tersebut harus memiliki bentuk yang mirip ([num_examples, num_features_per_example]) seperti saat kita melakukan pelatihan.

// Un-normalize the data
const unNormXs = xs
  .mul(inputMax.sub(inputMin))
  .add(inputMin);

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

Untuk mengembalikan data ke rentang asli (bukan 0-1), kita menggunakan nilai yang dihitung saat melakukan normalisasi, tetapi hanya membalikkan operasi.

return [unNormXs.dataSync(), unNormPreds.dataSync()];

.dataSync() adalah metode yang dapat kita gunakan untuk mendapatkan typedarray nilai yang disimpan dalam tensor. Dengan cara ini, kita dapat memproses nilai tersebut dalam JavaScript reguler. Ini adalah versi sinkron dari metode .data() yang umumnya lebih disukai.

Terakhir, kita menggunakan tfjs-vis untuk memetakan data asli dan prediksi dari model.

96914ff65fc3b74c.png Tambahkan kode berikut ke fungsi

run Anda

// Make some predictions using the model and compare them to the
// original data
testModel(model, data, tensorData);

Muat ulang halaman dan Anda akan melihat sesuatu seperti berikut setelah model menyelesaikan pelatihan.

fe610ff34708d4a.png

Selamat! Anda baru saja melatih model machine learning yang sederhana. Saat ini model tersebut hanya melakukan apa yang dikenal sebagai regresi linear, yang mencoba menyesuaikan garis dengan tren yang ada dalam data input.

Langkah-langkah dalam melatih model machine learning meliputi:

Meringkas tugas:

  • Apakah ini masalah regresi atau klasifikasi?
  • Apakah ini dapat dilakukan dengan pembelajaran yang diawasi atau tidak diawasi?
  • Bagaimana bentuk data input? Data output akan terlihat seperti apa?

Menyiapkan data:

  • Bersihkan data dan periksa pola secara manual jika memungkinkan
  • Acak data Anda sebelum digunakan untuk pelatihan
  • Normalisasikan data ke dalam rentang yang wajar untuk jaringan neural. Biasanya 0-1 atau -1-1 adalah rentang yang baik untuk data numerik.
  • Konversi data Anda menjadi tensor

Mem-build dan menjalankan model:

  • Tentukan model menggunakan tf.sequential atau tf.model, lalu tambahkan lapisan menggunakan tf.layers.*
  • Pilih pengoptimal (adam biasanya adalah pengoptimal yang baik), dan parameter seperti ukuran batch dan jumlah iterasi pelatihan.
  • Pilih fungsi kerugian yang sesuai untuk masalah Anda, dan metrik akurasi untuk membantu mengevaluasi progres Anda. meanSquaredError adalah fungsi kerugian umum untuk masalah regresi.
  • Pantau pelatihan untuk melihat apakah kerugian menurun

Mengevaluasi model Anda

  • Pilih metrik evaluasi untuk model yang dapat Anda pantau saat pelatihan. Setelah model dilatih, coba buat beberapa prediksi pengujian untuk mendapatkan kualitas prediksi.
  • Lakukan eksperimen dengan mengubah jumlah iterasi pelatihan. Berapa banyak iterasi pelatihan yang Anda butuhkan sebelum grafik menjadi rata.
  • Lakukan eksperimen dengan meningkatkan jumlah unit di lapisan tersembunyi.
  • Lakukan eksperimen dengan menambahkan lebih banyak lapisan tersembunyi di antara lapisan tersembunyi pertama yang ditambahkan dan lapisan output akhir. Kode untuk lapisan tambahan ini akan terlihat seperti ini.
model.add(tf.layers.dense({units: 50, activation: 'sigmoid'}));

Hal baru yang paling penting tentang lapisan tersembunyi ini adalah lapisan tersebut memiliki fungsi aktivasi non-linear, dalam hal ini aktivasi sigmoid. Untuk mempelajari lebih lanjut fungsi aktivasi, baca artikel ini.

Lihat apakah Anda bisa mendapatkan model untuk menghasilkan output seperti dalam gambar di bawah.

a21c5e6537cf81d.png