API lapisan TensorFlow.js untuk pengguna Keras

Layers API TensorFlow.js dimodelkan setelah Keras dan kami berupaya membuat Layers API serupa dengan Keras sebagaimana wajarnya mengingat perbedaan antara JavaScript dan Python. Hal ini memudahkan pengguna yang berpengalaman mengembangkan model Keras dengan Python untuk bermigrasi ke Lapisan TensorFlow.js di JavaScript. Misalnya, kode Keras berikut diterjemahkan ke dalam JavaScript:

# Python:
import keras
import numpy as np

# Build and compile model.
model = keras.Sequential()
model.add(keras.layers.Dense(units=1, input_shape=[1]))
model.compile(optimizer='sgd', loss='mean_squared_error')

# Generate some synthetic data for training.
xs = np.array([[1], [2], [3], [4]])
ys = np.array([[1], [3], [5], [7]])

# Train model with fit().
model.fit(xs, ys, epochs=1000)

# Run inference with predict().
print(model.predict(np.array([[5]])))
// JavaScript:
import * as tf from '@tensorflow/tfjs';

// Build and compile model.
const model = tf.sequential();
model.add(tf.layers.dense({units: 1, inputShape: [1]}));
model.compile({optimizer: 'sgd', loss: 'meanSquaredError'});

// Generate some synthetic data for training.
const xs = tf.tensor2d([[1], [2], [3], [4]], [4, 1]);
const ys = tf.tensor2d([[1], [3], [5], [7]], [4, 1]);

// Train model with fit().
await model.fit(xs, ys, {epochs: 1000});

// Run inference with predict().
model.predict(tf.tensor2d([[5]], [1, 1])).print();

Namun, ada beberapa perbedaan yang ingin kami sampaikan dan jelaskan dalam dokumen ini. Setelah Anda memahami perbedaan-perbedaan ini dan alasan di baliknya, migrasi Python-ke-JavaScript Anda (atau migrasi ke arah sebaliknya) akan menjadi pengalaman yang relatif lancar.

Konstruktor mengambil Objek JavaScript sebagai konfigurasi

Bandingkan baris Python dan JavaScript berikut dari contoh di atas: keduanya membuat lapisan Padat .

# Python:
keras.layers.Dense(units=1, inputShape=[1])
// JavaScript:
tf.layers.dense({units: 1, inputShape: [1]});

Fungsi JavaScript tidak memiliki argumen kata kunci yang setara dalam fungsi Python. Kami ingin menghindari penerapan opsi konstruktor sebagai argumen posisi dalam JavaScript, yang akan sangat rumit untuk diingat dan digunakan untuk konstruktor dengan banyak argumen kata kunci (misalnya, LSTM ). Inilah sebabnya kami menggunakan objek konfigurasi JavaScript. Objek tersebut memberikan tingkat invariansi dan fleksibilitas posisi yang sama dengan argumen kata kunci Python.

Beberapa metode kelas Model, misalnya Model.compile() , juga menggunakan objek konfigurasi JavaScript sebagai masukan. Namun, perlu diingat bahwa Model.fit() , Model.evaluate() dan Model.predict() sedikit berbeda. Karena metode ini mengambil data wajib x (fitur) dan y (label atau target) sebagai masukan; x dan y adalah argumen posisi yang terpisah dari objek konfigurasi berikutnya yang berperan sebagai argumen kata kunci. Misalnya:

// JavaScript:
await model.fit(xs, ys, {epochs: 1000});

Model.fit() tidak sinkron

Model.fit() adalah metode utama yang digunakan pengguna untuk melakukan pelatihan model di TensorFlow.js. Metode ini seringkali memakan waktu lama, berlangsung selama beberapa detik atau menit. Oleh karena itu, kami memanfaatkan fitur async pada bahasa JavaScript, sehingga fungsi ini dapat digunakan dengan cara yang tidak memblokir thread UI utama saat dijalankan di browser. Ini mirip dengan fungsi lain yang berpotensi berjalan lama di JavaScript, seperti async mengambil . Perhatikan bahwa async adalah konstruksi yang tidak ada di Python. Sementara metode fit() di Keras mengembalikan objek History, mitra dari metode fit() di JavaScript mengembalikan Promise of History, yang dapat menunggu (seperti pada contoh di atas) atau digunakan dengan metodethen().

Tidak ada NumPy untuk TensorFlow.js

Pengguna Python Keras sering menggunakan NumPy untuk melakukan operasi numerik dan array dasar, seperti menghasilkan tensor 2D pada contoh di atas.

# Python:
xs = np.array([[1], [2], [3], [4]])

Di TensorFlow.js, operasi numerik dasar semacam ini dilakukan dengan paket itu sendiri. Misalnya:

// JavaScript:
const xs = tf.tensor2d([[1], [2], [3], [4]], [4, 1]);

Namespace tf.* juga menyediakan sejumlah fungsi lain untuk operasi array dan aljabar linier seperti perkalian matriks. Lihat dokumentasi TensorFlow.js Core untuk informasi selengkapnya.

Gunakan metode pabrik, bukan konstruktor

Baris dalam Python ini (dari contoh di atas) adalah panggilan konstruktor:

# Python:
model = keras.Sequential()

Jika diterjemahkan secara ketat ke dalam JavaScript, panggilan konstruktor yang setara akan terlihat seperti berikut:

// JavaScript:
const model = new tf.Sequential();  // !!! DON'T DO THIS !!!

Namun, kami memutuskan untuk tidak menggunakan konstruktor “baru” karena 1) kata kunci “baru” akan membuat kode lebih membengkak dan 2) konstruktor “baru” dianggap sebagai “bagian buruk” dari JavaScript: potensi jebakan, seperti diperdebatkan dalam JavaScript: Bagian yang Baik . Untuk membuat model dan lapisan di TensorFlow.js, panggil metode pabrik yang memiliki nama LowerCamelCase, misalnya:

// JavaScript:
const model = tf.sequential();

const layer = tf.layers.batchNormalization({axis: 1});

Nilai string opsi adalah lowerCamelCase, bukan Snake_case

Dalam JavaScript, penggunaan huruf unta lebih umum untuk nama simbol (misalnya, lihat Panduan Gaya JavaScript Google ), dibandingkan dengan Python, yang huruf besar ularnya umum (misalnya, dalam Keras). Oleh karena itu, kami memutuskan untuk menggunakan lowerCamelCase untuk nilai string untuk opsi berikut:

  • Format Data, misalnya, channelsFirst , bukan channels_first
  • Penginisialisasi, misalnya glorotNormal , bukan glorot_normal
  • Kerugian dan metrik, misalnya meanSquaredError dari pada mean_squared_error , categoricalCrossentropy dari pada categorical_crossentropy .

Misalnya saja seperti pada contoh di atas:

// JavaScript:
model.compile({optimizer: 'sgd', loss: 'meanSquaredError'});

Berkenaan dengan serialisasi model dan deserialisasi, yakinlah. Mekanisme internal TensorFlow.js memastikan bahwa kasus ular di objek JSON ditangani dengan benar, misalnya, saat memuat model terlatih dari Python Keras.

Jalankan objek Layer dengan apply(), bukan dengan memanggilnya sebagai fungsi

Di Keras, objek Layer memiliki metode __call__ yang ditentukan. Oleh karena itu pengguna dapat menjalankan logika lapisan dengan memanggil objek sebagai fungsi, misalnya,

# Python:
my_input = keras.Input(shape=[2, 4])
flatten = keras.layers.Flatten()

print(flatten(my_input).shape)

Sintaks gula Python ini diimplementasikan sebagai metode apply() di TensorFlow.js:

// JavaScript:
const myInput = tf.input({shape: [2, 4]});
const flatten = tf.layers.flatten();

console.log(flatten.apply(myInput).shape);

Layer.apply() mendukung evaluasi penting (bersemangat) pada tensor beton

Saat ini, di Keras, metode panggilan hanya dapat beroperasi pada objek tf.Tensor (Python) TensorFlow (dengan asumsi backend TensorFlow), yang bersifat simbolis dan tidak memiliki nilai numerik sebenarnya. Inilah yang ditunjukkan pada contoh di bagian sebelumnya. Namun, di TensorFlow.js, metode lapisan apply() dapat beroperasi dalam mode simbolis dan imperatif. Jika apply() dipanggil dengan SymbolicTensor (analogi mirip dengan tf.Tensor), nilai yang dikembalikan akan menjadi SymbolicTensor. Ini biasanya terjadi selama pembuatan model. Namun jika apply() dipanggil dengan nilai Tensor konkret yang sebenarnya, Tensor konkret akan dikembalikan. Misalnya:

// JavaScript:
const flatten = tf.layers.flatten();

flatten.apply(tf.ones([2, 3, 4])).print();

Fitur ini mengingatkan pada Eager Execution (Python) TensorFlow. Hal ini memberikan interaktivitas dan kemampuan debug yang lebih besar selama pengembangan model, selain membuka pintu untuk menyusun jaringan saraf dinamis.

Pengoptimal sedang dilatih. , bukan pengoptimal.

Di Keras, konstruktor untuk objek Optimizer berada di bawah namespace keras.optimizers.* . Di Lapisan TensorFlow.js, metode pabrik untuk Pengoptimal berada di bawah namespace tf.train.* . Misalnya:

# Python:
my_sgd = keras.optimizers.sgd(lr=0.2)
// JavaScript:
const mySGD = tf.train.sgd({lr: 0.2});

loadLayersModel() memuat dari URL, bukan file HDF5

Di Keras, model biasanya disimpan sebagai file HDF5 (.h5), yang nantinya dapat dimuat menggunakan metode keras.models.load_model() . Metode ini mengambil jalur ke file .h5. Rekanan load_model() di TensorFlow.js adalah tf.loadLayersModel() . Karena HDF5 bukan format file yang ramah browser, tf.loadLayersModel() menggunakan format khusus TensorFlow.js. tf.loadLayersModel() mengambil file model.json sebagai argumen masukannya. Model.json dapat dikonversi dari file Keras HDF5 menggunakan paket pip tensorflowjs.

// JavaScript:
const model = await tf.loadLayersModel('https://foo.bar/model.json');

Perhatikan juga bahwa tf.loadLayersModel() mengembalikan Promise tf.Model .

Secara umum, penyimpanan dan pemuatan tf.Model di TensorFlow.js dilakukan masing-masing menggunakan metode tf.Model.save dan tf.loadLayersModel . Kami merancang API ini agar serupa dengan API simpan dan muat_model Keras. Namun lingkungan browser sangat berbeda dari lingkungan backend yang menjalankan kerangka pembelajaran mendalam seperti Keras, khususnya dalam rangkaian rute untuk menyimpan dan mentransmisikan data. Oleh karena itu, ada beberapa perbedaan menarik antara API simpan/muat di TensorFlow.js dan di Keras. Lihat tutorial kami tentang Menyimpan dan Memuat tf.Model untuk lebih jelasnya.

Gunakan fitDataset() untuk melatih model menggunakan objek tf.data.Dataset

Di tf.keras Python TensorFlow, model dapat dilatih menggunakan objek Dataset . Metode fit() model menerima objek tersebut secara langsung. Model TensorFlow.js juga dapat dilatih dengan objek Dataset yang setara dengan JavaScript (lihat dokumentasi tf.data API di TensorFlow.js ). Namun berbeda dengan Python, pelatihan berbasis Dataset dilakukan melalui metode khusus yaitu fitDataset . Metode fit() hanya untuk pelatihan model berbasis tensor.

Manajemen memori objek Lapisan dan Model

TensorFlow.js berjalan di WebGL di browser, dengan bobot objek Lapisan dan Model didukung oleh tekstur WebGL. Namun, WebGL tidak memiliki dukungan pengumpulan sampah bawaan. Objek Lapisan dan Model secara internal mengelola memori tensor untuk pengguna selama panggilan inferensi dan pelatihannya. Namun mereka juga mengizinkan pengguna untuk membuangnya untuk mengosongkan memori WebGL yang ditempati. Hal ini berguna jika banyak contoh model dibuat dan dirilis dalam satu pemuatan halaman. Untuk membuang objek Lapisan atau Model, gunakan metode dispose() .