Menghasilkan paket browser dengan ukuran yang dioptimalkan dengan TensorFlow.js

Ringkasan

TensorFlow.js 3.0 menghadirkan dukungan untuk membuat paket browser berorientasi produksi dengan ukuran optimal . Dengan kata lain, kami ingin memudahkan Anda mengirimkan lebih sedikit JavaScript ke browser.

Fitur ini ditujukan untuk pengguna dengan kasus penggunaan produksi yang khususnya akan mendapat manfaat dari pengurangan byte dari payload mereka (dan dengan demikian bersedia melakukan upaya untuk mencapai hal ini). Untuk menggunakan fitur ini Anda harus familiar dengan Modul ES , alat bundling JavaScript seperti webpack atau rollup , dan konsep seperti penghapusan pohon-gemetar/kode mati .

Tutorial ini menunjukkan cara membuat modul tensorflow.js khusus yang dapat digunakan dengan bundler untuk menghasilkan build ukuran yang dioptimalkan untuk program menggunakan tensorflow.js.

Terminologi

Dalam konteks dokumen ini ada beberapa istilah kunci yang akan kami gunakan:

Modul ES - Sistem modul JavaScript standar . Diperkenalkan pada ES6/ES2015. Dapat diidentifikasi dengan menggunakan pernyataan impor dan ekspor .

Bundling - Mengambil sekumpulan aset JavaScript dan mengelompokkan/menggabungkannya menjadi satu atau lebih aset JavaScript yang dapat digunakan di browser. Ini adalah langkah yang biasanya menghasilkan aset akhir yang disajikan ke browser. Aplikasi umumnya akan melakukan bundling sendiri langsung dari sumber perpustakaan yang ditranspilasi . Bundel yang umum mencakup rollup dan webpack . Hasil akhir dari bundling dikenal sebagai bundel (atau terkadang sebagai potongan jika dipecah menjadi beberapa bagian)

Penghapusan Kode yang Mengguncang Pohon / Mati - Penghapusan kode yang tidak digunakan oleh aplikasi tertulis akhir. Hal ini dilakukan selama bundling, biasanya pada langkah minifikasi.

Operasi (Ops) - Operasi matematika pada satu atau lebih tensor yang menghasilkan satu atau lebih tensor sebagai keluaran. Operasi adalah kode 'tingkat tinggi' dan dapat menggunakan operasi lain untuk menentukan logikanya.

Kernel - Implementasi spesifik dari suatu operasi yang terkait dengan kemampuan perangkat keras tertentu. Kernel bersifat 'tingkat rendah' ​​dan spesifik untuk backend. Beberapa operasi memiliki pemetaan satu-ke-satu dari operasi ke kernel sementara operasi lainnya menggunakan banyak kernel.

Cakupan dan Kasus Penggunaan

Hanya inferensi model grafik

Kasus penggunaan utama yang kami dengar dari pengguna terkait hal ini, dan mendukungnya dalam rilis ini adalah melakukan inferensi dengan model grafik TensorFlow.js . Jika Anda menggunakan model lapisan TensorFlow.js , Anda dapat mengonversinya ke format model grafik menggunakan tfjs-converter . Format model grafik lebih efisien untuk kasus penggunaan inferensi.

Manipulasi Tensor tingkat rendah dengan tfjs-core

Kasus penggunaan lain yang kami dukung adalah program yang secara langsung menggunakan paket @tensorflow/tjfs-core untuk manipulasi tensor tingkat rendah.

Pendekatan kami terhadap pembuatan khusus

Prinsip inti kami saat merancang fungsi ini meliputi hal berikut:

  • Manfaatkan sistem modul JavaScript (ESM) secara maksimal dan izinkan pengguna TensorFlow.js melakukan hal yang sama.
  • Jadikan TensorFlow.js sebisa mungkin dapat digoncangkan oleh bundler yang ada (misalnya webpack, rollup, dll). Hal ini memungkinkan pengguna untuk memanfaatkan semua kemampuan bundler tersebut termasuk fitur seperti pemisahan kode.
  • Sebisa mungkin pertahankan kemudahan penggunaan bagi pengguna yang tidak terlalu sensitif terhadap ukuran bundel . Ini berarti bahwa build produksi akan memerlukan lebih banyak upaya karena banyak default di perpustakaan kami mendukung kemudahan penggunaan dibandingkan build yang ukurannya dioptimalkan.

Tujuan utama alur kerja kami adalah menghasilkan modul JavaScript khusus untuk TensorFlow.js yang hanya berisi fungsionalitas yang diperlukan untuk program yang kami coba optimalkan. Kami mengandalkan bundler yang ada untuk melakukan optimasi sebenarnya.

Meskipun kami terutama mengandalkan sistem modul JavaScript, kami juga menyediakan alat CLI khusus untuk menangani bagian-bagian yang tidak mudah ditentukan melalui sistem modul dalam kode yang dilihat pengguna. Dua contohnya adalah:

  • Spesifikasi model disimpan dalam file model.json
  • Opsi untuk sistem pengiriman kernel khusus backend yang kami gunakan.

Hal ini membuat pembuatan tfjs kustom menjadi sedikit lebih rumit daripada sekadar mengarahkan bundler ke paket @tensorflow/tfjs biasa.

Cara membuat bundel khusus yang ukurannya dioptimalkan

Langkah 1: Tentukan kernel mana yang digunakan program Anda

Langkah ini memungkinkan kami menentukan semua kernel yang digunakan oleh model apa pun yang Anda jalankan atau kode sebelum/pasca-pemrosesan berdasarkan backend yang Anda pilih.

Gunakan tf.profile untuk menjalankan bagian aplikasi Anda yang menggunakan tensorflow.js dan dapatkan kernelnya. Ini akan terlihat seperti ini

const profileInfo = await tf.profile(() => {
  // You must profile all uses of tf symbols.
  runAllMyTfjsCode();
});

const kernelNames = profileInfo.kernelNames
console.log(kernelNames);

Salin daftar kernel tersebut ke clipboard Anda untuk langkah berikutnya.

Anda perlu membuat profil kode menggunakan backend yang sama yang ingin Anda gunakan dalam paket khusus Anda.

Anda perlu mengulangi langkah ini jika model Anda berubah atau kode pra/pasca pemrosesan berubah.

Langkah 2. Tulis file konfigurasi untuk modul tfjs khusus

Berikut adalah contoh file konfigurasi.

Ini terlihat seperti ini:

{
  "kernels": ["Reshape", "_FusedMatMul", "Identity"],
  "backends": [
      "cpu"
  ],
  "models": [
      "./model/model.json"
  ],
  "outputPath": "./custom_tfjs",
  "forwardModeOnly": true
}
  • kernels: Daftar kernel yang akan disertakan dalam bundel. Salin ini dari output Langkah 1.
  • backends: Daftar backend yang ingin Anda sertakan. Opsi yang valid mencakup "cpu", "webgl", dan "wasm".
  • models: Daftar file model.json untuk model yang Anda muat di aplikasi Anda. Bisa kosong jika program Anda tidak menggunakan tfjs_converter untuk memuat model grafik.
  • outputPath: Jalur ke folder untuk meletakkan modul yang dihasilkan.
  • forwardModeOnly: Setel ke false jika Anda ingin menyertakan gradien untuk kernel yang terdaftar sebelumnya.

Langkah 3. Hasilkan modul tfjs khusus

Jalankan alat build khusus dengan file konfigurasi sebagai argumen. Anda harus menginstal paket @tensorflow/tfjs agar dapat mengakses alat ini.

npx tfjs-custom-module  --config custom_tfjs_config.json

Ini akan membuat folder di outputPath dengan beberapa file baru.

Langkah 4. Konfigurasikan bundler Anda ke alias tfjs ke modul kustom baru.

Dalam bundler seperti webpack dan rollup, kami dapat membuat alias referensi yang ada ke modul tfjs untuk menunjuk ke modul tfjs khusus yang baru kami buat. Ada tiga modul yang perlu alias untuk penghematan maksimal dalam ukuran bundel.

Berikut cuplikan tampilannya di webpack ( contoh lengkap di sini ):

...

config.resolve = {
  alias: {
    '@tensorflow/tfjs$':
        path.resolve(__dirname, './custom_tfjs/custom_tfjs.js'),
    '@tensorflow/tfjs-core$': path.resolve(
        __dirname, './custom_tfjs/custom_tfjs_core.js'),
    '@tensorflow/tfjs-core/dist/ops/ops_for_converter': path.resolve(
        __dirname, './custom_tfjs/custom_ops_for_converter.js'),
  }
}

...

Dan berikut cuplikan kode yang setara untuk rollup ( contoh lengkap di sini ):

import alias from '@rollup/plugin-alias';

...

alias({
  entries: [
    {
      find: /@tensorflow\/tfjs$/,
      replacement: path.resolve(__dirname, './custom_tfjs/custom_tfjs.js'),
    },
    {
      find: /@tensorflow\/tfjs-core$/,
      replacement: path.resolve(__dirname, './custom_tfjs/custom_tfjs_core.js'),
    },
    {
      find: '@tensorflow/tfjs-core/dist/ops/ops_for_converter',
      replacement: path.resolve(__dirname, './custom_tfjs/custom_ops_for_converter.js'),
    },
  ],
}));

...

Jika bundler Anda tidak mendukung aliasing modul, Anda perlu mengubah pernyataan import untuk mengimpor tensorflow.js dari custom_tfjs.js yang dihasilkan yang dibuat pada Langkah 3. Definisi operasi tidak akan dihilangkan, tetapi kernel akan tetap berupa pohon -terguncang. Umumnya kernel yang mengguncang pohon memberikan penghematan terbesar dalam ukuran bundel akhir.

Jika Anda hanya menggunakan paket @tensoflow/tfjs-core, maka Anda hanya perlu membuat alias pada satu paket tersebut.

Langkah 5. Buat bundel Anda

Jalankan bundler Anda (misalnya webpack atau rollup ) untuk menghasilkan bundel Anda. Ukuran bundel harus lebih kecil dibandingkan jika Anda menjalankan bundler tanpa aliasing modul. Anda juga dapat menggunakan visualisator seperti ini untuk melihat apa yang berhasil masuk ke dalam paket akhir Anda.

Langkah 6. Uji aplikasi Anda

Pastikan untuk menguji apakah aplikasi Anda berfungsi seperti yang diharapkan!