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
- Chrome versi terbaru atau browser modern lainnya.
- Editor teks, yang dijalankan secara lokal di komputer Anda atau di web melalui sesuatu seperti Codepen atau Glitch.
- Pengetahuan tentang HTML, CSS, JavaScript, dan Chrome DevTools (atau devtool browser pilihan Anda).
- Pemahaman konseptual tingkat tinggi tentang Jaringan Neural. Jika Anda memerlukan informasi pengantar atau penyegaran terkait materi yang akan dipelajari, pertimbangkan untuk menonton video dari 3blue1brown atau video Deep Learning in JavaScript dari Ashi Krishnan ini.
Membuat halaman HTML dan menyertakan JavaScript
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
- 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.jstfvis
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.
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.
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.
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.
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
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.
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.
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 menggunakanmeanSquaredError
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
.
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.
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.
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.
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.
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
atautf.model
, lalu tambahkan lapisan menggunakantf.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.