API lapisan TensorFlow.js untuk pengguna Keras

Layers API dari TensorFlow.js adalah model setelah Keras dan kami berusaha untuk membuat Layers API sebagai mirip dengan Keras sebagai wajar mengingat perbedaan antara JavaScript dan Python. Hal ini memudahkan pengguna yang berpengalaman mengembangkan model Keras dengan Python untuk bermigrasi ke Lapisan TensorFlow.js dalam 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 '@tensorlowjs/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 sebutkan dan jelaskan dalam dokumen ini. Setelah Anda memahami 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 berikut Python dan JavaScript baris dari contoh di atas: mereka berdua membuat padat lapisan.

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

Fungsi JavaScript tidak memiliki ekuivalen dengan argumen kata kunci dalam fungsi Python. Kami ingin menghindari menerapkan pilihan konstruktor sebagai argumen posisional dalam JavaScript, yang akan terutama rumit untuk mengingat dan digunakan untuk konstruktor dengan sejumlah besar argumen kata kunci (misalnya, LSTM ). Inilah mengapa kami menggunakan objek konfigurasi JavaScript. Objek tersebut memberikan tingkat invarians posisi dan fleksibilitas yang sama seperti argumen kata kunci Python.

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

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

Model.fit() tidak sinkron

Model.fit() adalah metode utama dengan mana pengguna melakukan pelatihan model dalam TensorFlow.js. Metode ini seringkali dapat berjalan lama, berlangsung selama beberapa detik atau menit. Oleh karena itu, kami memanfaatkan async fitur bahasa JavaScript, sehingga fungsi ini dapat digunakan dengan cara yang tidak memblokir UI thread utama ketika berjalan di browser. Hal ini mirip dengan fungsi berpotensi lama berjalan lain dalam JavaScript, seperti async mengambil . Perhatikan bahwa async adalah membangun yang tidak ada di Python. Sementara fit() metode dalam Keras mengembalikan sebuah objek Sejarah, mitra dari fit() metode dalam JavaScript mengembalikan Janji Sejarah, yang dapat Tunggulah, ed (seperti dalam contoh di atas) atau digunakan dengan metode kemudian ().

Tidak Ada NumPy untuk TensorFlow.js

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

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

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

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

The tf.* Namespace juga menyediakan sejumlah fungsi lainnya untuk operasi array dan aljabar linier seperti perkalian matriks. Lihat dokumentasi TensorFlow.js Inti untuk informasi lebih lanjut.

Gunakan metode pabrik, bukan konstruktor

Baris ini dalam Python (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 dikatakan dalam JavaScript: Parts 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, itu lebih umum untuk kasus penggunaan unta untuk nama simbol (misalnya, lihat Google JavaScript Style Guide ), dibandingkan dengan Python, di mana kasus ular adalah umum (misalnya, di Keras). Karena itu, kami memutuskan untuk menggunakan lowerCamelCase untuk nilai string untuk opsi termasuk yang berikut:

  • DataFormat, misalnya, channelsFirst bukan channels_first
  • Initializer, misalnya, glorotNormal bukan glorot_normal
  • Rugi dan metrik, misalnya, meanSquaredError bukan mean_squared_error , categoricalCrossentropy bukan categorical_crossentropy .

Misalnya seperti pada contoh di atas:

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

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

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

Dalam Keras, benda Lapisan memiliki __call__ metode didefinisikan. Oleh karena itu pengguna dapat memanggil 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)

Gula sintaksis 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 imperatif (bersemangat) pada tensor beton

Saat ini, di Keras, metode panggilan hanya dapat beroperasi pada (Python) TensorFlow ini tf.Tensor objek (dengan asumsi TensorFlow backend), yang simbolis dan tidak memegang nilai-nilai numerik yang 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 dekat tf.Tensor), nilai kembali akan SymbolicTensor a. Ini biasanya terjadi selama pembuatan model. Tetapi jika apply() dipanggil dengan beton nilai Tensor yang sebenarnya, itu akan mengembalikan beton Tensor. Sebagai contoh:

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

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

Fitur ini mengingatkan (Python) TensorFlow ini Eksekusi Bersemangat . Ini memberikan interaktivitas dan kemampuan debugg yang lebih besar selama pengembangan model, selain membuka pintu untuk menyusun jaringan saraf dinamis.

Pengoptimal sedang dalam proses. , bukan pengoptimal.

Dalam Keras, konstruktor untuk objek Optimizer berada di bawah keras.optimizers.* Namespace. Dalam TensorFlow.js Layers, metode pabrik untuk pengoptimalan berada di bawah tf.train.* Namespace. Sebagai contoh:

# 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

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

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

Juga mencatat bahwa tf.loadLayersModel() mengembalikan Promise dari tf.Model .

Secara umum, tabungan dan pemuatan tf.Model dalam TensorFlow.js dilakukan dengan menggunakan tf.Model.save dan tf.loadLayersModel metode, masing-masing. Kami merancang API ini mirip dengan save dan load_model API dari Keras. Tetapi lingkungan browser sangat berbeda dari lingkungan backend tempat framework deep learning pokok seperti Keras dijalankan, terutama dalam susunan rute untuk bertahan dan mentransmisikan data. Oleh karena itu, ada beberapa perbedaan menarik antara save/load API di TensorFlow.js dan di Keras. Lihat tutorial kami pada Tabungan dan Loading tf.Model untuk lebih jelasnya.

Gunakan fitDataset() untuk model kereta menggunakan tf.data.Dataset benda

Dalam tf.keras Python TensorFlow ini, model dapat dilatih menggunakan Dataset objek. Model fit() metode menerima benda seperti langsung. Model A TensorFlow.js dapat dilatih dengan setara JavaScript dari Dataset objek juga (lihat dokumentasi dari tf.data API di TensorFlow.js ). Namun, pelatihan tidak seperti di Python, Dataset berbasis dilakukan melalui metode khusus, yaitu fitDataset . The fit () metode ini hanya untuk pelatihan model berbasis tensor.

Manajemen memori objek Layer dan Model

TensorFlow.js berjalan di WebGL di browser, dengan bobot objek Layer dan Model didukung oleh tekstur WebGL. Namun, WebGL tidak memiliki dukungan pengumpulan sampah bawaan. Objek Layer dan Model secara internal mengelola memori tensor untuk pengguna selama panggilan inferensi dan pelatihan mereka. Tetapi mereka juga memungkinkan pengguna untuk membuangnya untuk membebaskan memori WebGL yang mereka tempati. Ini berguna dalam kasus di mana banyak contoh model dibuat dan dirilis dalam satu pemuatan halaman. Untuk membuang Layer atau objek Model, gunakan dispose() metode.