Pembelajaran Mesin dengan Node.js Menggunakan Perpustakaan Tensorflow.js

Halo semuanya, kolega!

Mungkin para penggemar perpustakaan Tensorflow, yang sudah memperhatikan buku ini di pre-order kami, juga melihat dengan dekat pada kemungkinan mesin dan pembelajaran mendalam di browser, terutama karena Francois Schollet sendiri tidak mengabaikan topik. Kami mengundang mereka yang tertarik pada kucing, yang menceritakan bagaimana gambar dikenali menggunakan perpustakaan Tensorflow.js.

TensorFlow.js adalah versi baru dari perpustakaan open source populer yang memperkaya JavaScript dengan kemampuan belajar yang mendalam. Pengembang sekarang dapat mendefinisikan, melatih, dan menjalankan model menggunakan API pustaka tingkat tinggi .

Berkat model pra-terlatih, pengembang sekarang dapat dengan mudah menyelesaikan tugas-tugas kompleks seperti pengenalan pola , generasi musik atau menentukan posisi manusia hanya dalam beberapa baris JavaScript.

Tensorflow.js dimulai sebagai perpustakaan front-end untuk bekerja di browser, tetapi tahun ini dukungan eksperimental untuk Node.js ditambahkan ke dalamnya. Dengan demikian, TensorFlow.js juga dapat digunakan dalam aplikasi JavaScript backend, yang sepenuhnya menyelamatkan kita dari keharusan beralih ke Python.

Membaca tentang perpustakaan ini, saya memutuskan untuk mencobanya pada tugas sederhana ...
Gunakan TensorFlow.js untuk pengenalan visual gambar pada gambar saat menggunakan JavaScript dari Node.js
Sayangnya, dokumentasi dan contoh kode terutama menggambarkan penggunaan perpustakaan ini di browser. Utilitas proyek yang dirancang untuk menyederhanakan pemuatan dan penggunaan model pra-terlatih pada saat penulisan tidak mendukung Node.js. Saya harus menghabiskan banyak waktu untuk membaca sumber naskah untuk perpustakaan ini dengan baik.

Namun, setelah beberapa hari bersumpah, saya masih melakukannya! Hore!

Sebelum beralih ke analisis rinci kode, mari kita bicara tentang implementasi lain dari perpustakaan TensorFlow.

Tensorflow

TensorFlow adalah perpustakaan perangkat lunak gratis untuk aplikasi pembelajaran mesin. TensorFlow dapat digunakan untuk membuat jaringan saraf dan mengimplementasikan algoritma pembelajaran mendalam lainnya.

Ini adalah perpustakaan yang dirilis oleh Google pada November 2015, awalnya ditulis dengan Python . Untuk pelatihan dan evaluasi model yang dibuat, ia menggunakan perhitungan pada CPU atau GPU. Awalnya, perpustakaan ini dibuat untuk bekerja pada server berkinerja tinggi menggunakan GPU intensif sumber daya.

Pembaruan terbaru telah memungkinkan untuk mengoptimalkan perpustakaan ini dan menggunakannya di lingkungan dengan sumber daya yang lebih terbatas - misalnya, pada perangkat seluler dan browser web.

TensorFlow Lite

Tensorflow Lite , versi lite perpustakaan ini untuk perangkat seluler dan sistem tertanam, dirilis pada Mei 2017. Bersama dengan itu, satu set model mendalam pra-dilatih disediakan untuk tugas-tugas yang berkaitan dengan pengenalan pola; koleksi ini disebut MobileNet . Model MobileNet telah dirancang khusus untuk operasi yang efisien di lingkungan dengan sumber daya yang terbatas, seperti perangkat seluler.

TensorFlow.js

Mengikuti Tensorflow Lite, TensorFlow.js diumumkan pada Maret 2018. Versi perpustakaan ini dirancang untuk berjalan di browser dan didasarkan pada proyek sebelumnya yang disebut deeplearn.js . WebGL menyediakan akses GPU ke perpustakaan. Pengembang menggunakan JavaScript API untuk melatih, memuat, dan menjalankan model.

Kemudian TensorFlow.js diperluas untuk bekerja dengan Node.js, tfjs-node library add tfjs-node digunakan untuk ini.

Impor model yang ada ke TensorFlow.js

Model TensorFlow dan Keras yang sudah jadi dapat dieksekusi menggunakan perpustakaan TensorFlow.js. Sebelum menjalankan model, Anda harus mengonversi ke format baru menggunakan alat ini . Model pra-dilatih dan ditransformasikan untuk mengklasifikasikan gambar, menentukan pose, dan mendeteksi tetangga terdekat k tersedia di Github .

Menggunakan TensorFlow.js dengan Node.js

Instal TensorFlow Libraries

TensorFlow.js dapat diinstal dari registri NPM .


 npm install @tensorflow/tfjs @tensorflow/tfjs-node // ... npm install @tensorflow/tfjs @tensorflow/tfjs-node-gpu 

Kedua ekstensi untuk Node.js menggunakan dependensi asli, yang akan dikompilasi sesuai permintaan.

Unduh TensorFlow Libraries

API JavaScript untuk Tensorflow disediakan dari pustaka inti. Tidak ada ekstensi API yang disediakan dalam modul ekstensi yang mendukung Node.js.

  const tf = require('@tensorflow/tfjs') //   ( CPU) require('@tensorflow/tfjs-node') //    ( GPU) require('@tensorflow/tfjs-node-gpu') 

Unduh Model TensorFlow

TensorFlow.js menyediakan perpustakaan NPM ( tfjs-models ) yang menyederhanakan pemuatan tfjs-models yang telah dilatih dan ditransformasikan untuk mengklasifikasikan gambar , menentukan pose, dan mendeteksi k-tetangga terdekat .

Model klasifikasi gambar MobileNet adalah jaringan saraf yang dalam yang dilatih untuk membedakan antara 1000 kelas gambar yang berbeda .

Dalam file README untuk proyek, kode berikut digunakan sebagai contoh , digunakan untuk memuat model.

 import * as mobilenet from '@tensorflow-models/mobilenet'; //   const model = await mobilenet.load(); 

Salah satu masalah pertama yang saya temui adalah kode ini tidak berfungsi dengan Node.js.

 Error: browserHTTPRequest is not supported outside the web browser. 

Setelah memeriksa kode sumber , kita melihat bahwa perpustakaan mobilenet adalah pembungkus untuk kelas tf.Model . Ketika dipanggil, metode load() secara otomatis mengunduh file model yang diperlukan yang terletak di alamat HTTP eksternal dan membuat model TensorFlow.

Ekstensi Node.js pada saat penulisan ini belum mendukung permintaan HTTP untuk pengambilan model dinamis. Yang tersisa hanyalah memuat model secara manual ke dalam sistem file.

Namun, setelah membaca kode sumber perpustakaan, saya menemukan solusi ...

Mengunduh model dari sistem file

Jika kelas MobileNet dibuat secara manual, Anda tidak dapat memanggil metode load modul, tetapi menulis ulang path variabel yang dibuat secara otomatis yang berisi alamat HTTP model, mengganti alamat ini dengan jalur lokal di sistem file. Setelah itu, ketika metode load dipanggil dalam instance kelas, kelas sistem file loader akan menyala; dalam hal ini, kami menolak untuk menggunakan pengunduh HTTP berbasis browser.

 const path = "mobilenet/model.json" const mn = new mobilenet.MobileNet(1, 1); mn.path = `file://${path}` await mn.load() 

Keren, semuanya berfungsi!

Tapi dari mana file model berasal?

Model MobileNet

Model untuk TensorFlow.js terdiri dari dua jenis file: file konfigurasi model yang disimpan dalam format JSON dan bobot model yang disimpan dalam format biner. Bobot model sering terpecah menjadi banyak bagian untuk mengoptimalkan caching browser.

Setelah mempertimbangkan kode unduhan otomatis untuk model MobileNet, kami melihat bahwa model, konfigurasi, dan fragmen bobotnya diekstraksi dari wadah publik di alamat berikut.

 https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v${version}_${alpha}_${size}/ 

Parameter templat di URL menjelaskan versi model yang tercantum di sini . Akurasi klasifikasi yang dihasilkan juga ditampilkan pada halaman yang sama.

Kode sumber menunjukkan bahwa hanya model MobileNet v1 yang dapat diunduh menggunakan tensorflow-models/mobilenet .

Kode ekstraksi HTTP mengunduh file model.json dari lokasi penyimpanan, dan kemudian secara rekursif memilih semua fragmen model dengan bobot yang direferensikan. Ini adalah file dalam format groupX-shard1of1 .

Mengunduh model secara manual

Jika Anda ingin menyimpan semua file model dalam sistem file, Anda dapat melakukan ini: ekstrak file konfigurasi model, parsing sintaks semua file tertimbang yang dirujuk dalam file konfigurasi, dan kemudian unduh setiap file tertimbang secara manual.
Saya akan menggunakan modul MobileNet V1 dengan nilai alpha 1,0 dan gambar 224 piksel . Jadi saya mendapatkan URL berikut untuk file konfigurasi model.

 https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_1.0_224/model.json 

Setelah file ini diunduh secara lokal, Anda dapat menggunakan alat jq untuk mem-parsing nama semua file yang tertimbang.

 $ cat model.json | jq -r ".weightsManifest[].paths[0]" group1-shard1of1 group2-shard1of1 group3-shard1of1 ... 

Menggunakan alat sed , Anda dapat mengawali nama setiap elemen HTTP dengan URL untuk menghasilkan URL untuk setiap file berat.

 $ cat model.json | jq -r ".weightsManifest[].paths[0]" | sed 's/^/https:\/\/storage.googleapis.com\/tfjs-models\/tfjs\/mobilenet_v1_1.0_224\//' https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_1.0_224/group1-shard1of1 https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_1.0_224/group2-shard1of1 https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_1.0_224/group3-shard1of1 ... 

Perintah parallel dan curl kemudian memungkinkan Anda untuk mengunduh semua file ini ke direktori lokal saya.

 cat model.json | jq -r ".weightsManifest[].paths[0]" | sed 's/^/https:\/\/storage.googleapis.com\/tfjs-models\/tfjs\/mobilenet_v1_1.0_224\//' | parallel curl -O 

Klasifikasi gambar

Kode sampel ini disediakan dengan TensorFlow.js menunjukkan cara mengembalikan hasil klasifikasi gambar.

 const img = document.getElementById('img'); //   const predictions = await model.classify(img); 

Ini tidak berfungsi di Node.js karena kurangnya dukungan DOM.

Metode classify menerima berbagai elemen DOM ( canvas , video , image ) dan secara otomatis mengekstrak dan mengubah byte "gambar" dari elemen-elemen ini ke kelas tf.Tensor3D , yang digunakan sebagai input model. Atau, tf.Tensor3D dapat ditransmisikan secara langsung.

Saya memutuskan untuk tidak mencoba menggunakan paket eksternal untuk mensimulasikan elemen DOM secara manual, tetapi menemukan bahwa tf.Tensor3D lebih mudah untuk dirakit secara manual .

Kami menghasilkan Tensor3D dari gambar

Membaca kode sumber metode yang digunakan untuk mengkonversi elemen DOM ke kelas Tensor3D, kami menemukan bahwa parameter input berikut digunakan untuk menghasilkan kelas Tensor3D.

 const values = new Int32Array(image.height * image.width * numChannels); //     ,    const outShape = [image.height, image.width, numChannels]; const input = tf.tensor3d(values, outShape, 'int32'); 

pixels adalah array tipe dua dimensi (Int32Array) berisi daftar nilai saluran berurutan untuk setiap piksel. numChannels adalah jumlah nilai saluran per piksel.

Membuat Nilai Input untuk JPEG

Perpustakaan jpeg-js adalah encoder / decoder JPEG untuk Node.js yang ditulis dalam JavaScript murni. Dengan menggunakan perpustakaan ini, Anda dapat mengekstraksi nilai RGB untuk setiap piksel.

 const pixels = jpeg.decode(buffer, true); 

Hasilnya, kami mendapatkan Uint8Array dengan empat nilai saluran ( RGBA ) untuk setiap piksel ( width * height ). Model MobileNet hanya menggunakan tiga saluran warna ( RGB ) untuk klasifikasi, saluran alfa diabaikan. Kode ini mengubah array empat saluran menjadi versi tiga saluran yang sebenarnya.

  const numChannels = 3; const numPixels = image.width * image.height; const values = new Int32Array(numPixels * numChannels); for (let i = 0; i < numPixels; i++) { for (let channel = 0; channel < numChannels; ++channel) { values[i * numChannels + channel] = pixels[i * 4 + channel]; } } 

Persyaratan Input untuk Model MobileNet

Model MobileNet yang digunakan di sini mengklasifikasikan gambar dengan tinggi dan lebar 224 piksel. Input tensor harus mengandung nilai floating point dalam kisaran -1 hingga 1 untuk masing-masing dari tiga nilai saluran setiap piksel.

Nilai input untuk gambar dengan dimensi yang berbeda harus dikonversi ke ukuran yang benar sebelum klasifikasi. Selain itu, nilai-nilai piksel yang diperoleh dari dekoder JPEG berada dalam kisaran 0 - 255, bukan -1 - 1. Nilai-nilai ini juga perlu dikonversi sebelum klasifikasi.

TensorFlow.js memiliki metode pustaka untuk menyederhanakan proses ini, tetapi, lebih baik lagi, ada tfjs-models/mobilenet yang secara otomatis menyelesaikan masalah ini !

Pengembang dapat meneruskan input Tensor3D dari tipe int32 , serta berbagai dimensi ke metode classify , yang menerjemahkan nilai input ke dalam format yang benar sebelum klasifikasi. Artinya, kita tidak ada hubungannya di sini. Hebat!

Mendapat Prediksi

Model MobileNet Tensorflow belajar mengenali objek dari 1000 kelas paling penting dari kumpulan data ImageNet . Pada output model memberikan nilai probabilistik yang mengkarakterisasi apa saja peluang menemukan objek-objek ini dalam gambar rahasia.

Daftar lengkap kelas terlatih untuk model yang digunakan ada di file ini .

tfjs-models/mobilenet menawarkan metode classify di kelas MobileNet , yang mengembalikan top-X dari kelas yang paling mungkin, berdasarkan pada apa yang ditunjukkan pada gambar.

 const predictions = await mn_model.classify(input, 10); 

predictions adalah array kelas X dan probabilitas dalam format berikut.

  { className: 'panda', probability: 0.9993536472320557 } 

Contoh

Jadi, kami telah menemukan cara menggunakan perpustakaan TensorFlow.js dan model MobileNet di Node.js, dan sekarang mempertimbangkan bagaimana skrip ini mengklasifikasikan gambar yang ditentukan sebagai argumen baris perintah.

Kode sumber

Simpan file skrip ini dan deskriptor paket dalam file lokal.

 { "name": "tf-js", "version": "1.0.0", "main": "script.js", "license": "MIT", "dependencies": { "@tensorflow-models/mobilenet": "^0.2.2", "@tensorflow/tfjs": "^0.12.3", "@tensorflow/tfjs-node": "^0.1.9", "jpeg-js": "^0.3.4" } } 

 const tf = require('@tensorflow/tfjs') const mobilenet = require('@tensorflow-models/mobilenet'); require('@tensorflow/tfjs-node') const fs = require('fs'); const jpeg = require('jpeg-js'); const NUMBER_OF_CHANNELS = 3 const readImage = path => { const buf = fs.readFileSync(path) const pixels = jpeg.decode(buf, true) return pixels } const imageByteArray = (image, numChannels) => { const pixels = image.data const numPixels = image.width * image.height; const values = new Int32Array(numPixels * numChannels); for (let i = 0; i < numPixels; i++) { for (let channel = 0; channel < numChannels; ++channel) { values[i * numChannels + channel] = pixels[i * 4 + channel]; } } return values } const imageToInput = (image, numChannels) => { const values = imageByteArray(image, numChannels) const outShape = [image.height, image.width, numChannels]; const input = tf.tensor3d(values, outShape, 'int32'); return input } const loadModel = async path => { const mn = new mobilenet.MobileNet(1, 1); mn.path = `file://${path}` await mn.load() return mn } const classify = async (model, path) => { const image = readImage(path) const input = imageToInput(image, NUMBER_OF_CHANNELS) const mn_model = await loadModel(model) const predictions = await mn_model.classify(input) console.log('classification results:', predictions) } if (process.argv.length !== 4) throw new Error('incorrect arguments: node script.js <MODEL> <IMAGE_FILE>') classify(process.argv[2], process.argv[3]) 

Pengujian

Unduh file model ke direktori mobilenet dengan mengikuti instruksi di atas.
Tetapkan dependensi proyek menggunakan NPM

npm install

Unduh contoh file JPEG untuk klasifikasi

wget http://bit.ly/2JYSal9 -O panda.jpg



Jalankan skrip, argumen yang akan menjadi model file dan gambar input.

node script.js mobilenet/model.json panda.jpg

Jika semuanya bekerja dengan benar, maka output berikut ini akan muncul di konsol.

  classification results: [ { className: 'giant panda, panda, panda bear, coon bear', probability: 0.9993536472320557 } ] 

Gambar diklasifikasikan dengan benar sebagai mengandung panda dengan probabilitas 99,93%!

Kesimpulan

Pustaka TensorFlow.js membuka peluang pembelajaran yang mendalam bagi pengembang JavaScript. Menggunakan model pra-terlatih dengan perpustakaan TensorFlow.js memungkinkan Anda untuk dengan mudah membangun aplikasi JavaScript fitur baru untuk memecahkan masalah pembelajaran mesin yang kompleks, dengan upaya minimal dan kode ringkas.

Pustaka TensorFlow.js dibuat murni untuk bekerja di browser, tetapi sekarang berinteraksi dengan Node.js, meskipun tidak semua alat dan utilitas mendukung runtime baru ini. Setelah bermain-main dengan perpustakaan selama beberapa hari, saya belajar menggunakannya dengan model MobileNet untuk pengenalan visual gambar dari file lokal.

Source: https://habr.com/ru/post/id432984/


All Articles