ConvNets, SqueezeNet, Xception modern, dengan Keras dan TPU

1. Ringkasan

Dalam lab ini, Anda akan mempelajari arsitektur konvolusional modern dan menggunakan pengetahuan Anda untuk menerapkan convnet sederhana namun efektif yang disebut "squeezenet".

Lab ini mencakup penjelasan teoretis yang diperlukan tentang jaringan neural konvolusional dan merupakan titik awal yang baik bagi developer yang mempelajari deep learning.

Lab ini adalah Bagian 4 dari seri "Keras di TPU". Anda dapat melakukannya dalam urutan berikut atau secara terpisah.

ca8cc21f6838eccc.png

Yang akan Anda pelajari

  • Untuk menguasai gaya fungsional Keras
  • Untuk membuat model menggunakan arsitektur squeezenet
  • Untuk menggunakan TPU agar dapat melatih dengan cepat dan melakukan iterasi pada arsitektur Anda
  • Untuk menerapkan pengayaan data dengan tf.data.dataset
  • Untuk melakukan fine-tuning model besar terlatih (Xception) di TPU

Masukan

Jika Anda melihat sesuatu yang tidak beres dalam codelab ini, harap beri tahu kami. Masukan dapat diberikan melalui masalah GitHub [link masukan].

2. Mulai cepat Google Colaboratory

Lab ini menggunakan Google Collaboratory dan tidak memerlukan penyiapan di pihak Anda. Colaboratory adalah platform notebook online untuk tujuan pendidikan. Colab menawarkan pelatihan CPU, GPU, dan TPU gratis.

688858c21e3beff2.png

Anda dapat membuka notebook contoh ini dan menjalankan beberapa sel untuk memahami Colaboratory.

c3df49e90e5a654f.png Welcome to Colab.ipynb

Pilih backend TPU

8832c6208c99687d.png

Di menu Colab, pilih Runtime > Ubah jenis runtime, lalu pilih TPU. Dalam codelab ini, Anda akan menggunakan TPU (Tensor Processing Unit) yang andal yang didukung untuk pelatihan yang dipercepat hardware. Koneksi ke runtime akan terjadi secara otomatis pada eksekusi pertama, atau Anda dapat menggunakan tombol "Hubungkan" di sudut kanan atas.

Eksekusi notebook

76d05caa8b4db6da.png

Jalankan sel satu per satu dengan mengklik sel dan menggunakan Shift-ENTER. Anda juga dapat menjalankan seluruh notebook dengan Runtime > Run all

Daftar isi

429f106990037ec4.png

Semua notebook memiliki daftar isi. Anda dapat membukanya menggunakan panah hitam di sebelah kiri.

Sel tersembunyi

edc3dba45d26f12a.png

Beberapa sel hanya akan menampilkan judulnya. Ini adalah fitur notebook khusus Colab. Anda dapat mengklik dua kali untuk melihat kode di dalamnya, tetapi biasanya tidak terlalu menarik. Biasanya mendukung fungsi atau visualisasi. Anda tetap perlu menjalankan sel ini agar fungsi di dalamnya dapat ditentukan.

Autentikasi

cdd4b41413100543.png

Colab dapat mengakses bucket Google Cloud Storage pribadi Anda asalkan Anda melakukan autentikasi dengan akun yang sah. Cuplikan kode di atas akan memicu proses autentikasi.

3. [INFO] Apa itu Tensor Processing Unit (TPU)?

Singkatnya

f88cf6facfc70166.png

Kode untuk melatih model di TPU di Keras (dan kembali ke GPU atau CPU jika TPU tidak tersedia):

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

Hari ini kita akan menggunakan TPU untuk membuat dan mengoptimalkan pengklasifikasi bunga dengan kecepatan interaktif (menit per proses pelatihan).

688858c21e3beff2.png

Mengapa TPU?

GPU modern disusun di sekitar "core" yang dapat diprogram, sebuah arsitektur yang sangat fleksibel yang memungkinkan GPU menangani berbagai tugas seperti rendering 3D, deep learning, simulasi fisik, dll. Di sisi lain, TPU memasangkan prosesor vektor klasik dengan unit perkalian matriks khusus dan unggul dalam tugas apa pun yang didominasi oleh perkalian matriks besar, seperti jaringan neural.

8eb3e718b8e2ed08.png

Ilustrasi: lapisan jaringan neural padat sebagai perkalian matriks, dengan batch delapan gambar yang diproses melalui jaringan neural sekaligus. Lakukan perkalian satu baris x kolom untuk memverifikasi bahwa operasi ini memang melakukan jumlah berbobot dari semua nilai piksel gambar. Lapisan konvolusional juga dapat direpresentasikan sebagai perkalian matriks meskipun sedikit lebih rumit ( penjelasan di sini, di bagian 1).

Hardware

MXU dan VPU

Core TPU v2 terdiri dari Matrix Multiply Unit (MXU) yang menjalankan perkalian matriks dan Vector Processing Unit (VPU) untuk semua tugas lainnya seperti aktivasi, softmax, dll. VPU menangani komputasi float32 dan int32. Di sisi lain, MXU beroperasi dalam format floating point 16-32 bit presisi campuran.

7d68944718f76b18.png

Floating point presisi campuran dan bfloat16

MXU menghitung perkalian matriks menggunakan input bfloat16 dan output float32. Akumulasi perantara dilakukan dengan presisi float32.

19c5fc432840c714.png

Pelatihan jaringan neural biasanya tahan terhadap derau yang diperkenalkan oleh presisi floating point yang berkurang. Ada kasus ketika derau bahkan membantu pengoptimalan konvergen. Presisi floating point 16-bit secara tradisional digunakan untuk mempercepat komputasi, tetapi format float16 dan float32 memiliki rentang yang sangat berbeda. Mengurangi presisi dari float32 ke float16 biasanya menyebabkan overflow dan underflow. Solusi memang ada, tetapi biasanya diperlukan pekerjaan tambahan agar float16 dapat berfungsi.

Itulah sebabnya Google memperkenalkan format bfloat16 di TPU. bfloat16 adalah float32 yang dipangkas dengan bit eksponen dan rentang yang sama persis dengan float32. Selain itu, TPU menghitung perkalian matriks dalam presisi campuran dengan input bfloat16, tetapi output float32. Artinya, biasanya tidak ada perubahan kode yang diperlukan untuk mendapatkan manfaat dari peningkatan performa presisi yang lebih rendah.

Array sistolik

MXU mengimplementasikan perkalian matriks di hardware menggunakan arsitektur "array sistolik" yang disebut di mana elemen data mengalir melalui array unit komputasi hardware. (Dalam bidang medis, "sistolik" mengacu pada kontraksi jantung dan aliran darah, di sini mengacu pada aliran data.)

Elemen dasar perkalian matriks adalah produk titik antara baris dari satu matriks dan kolom dari matriks lainnya (lihat ilustrasi di bagian atas bagian ini). Untuk perkalian matriks Y=X*W, salah satu elemen hasilnya adalah:

Y[2,0] = X[2,0]*W[0,0] + X[2,1]*W[1,0] + X[2,2]*W[2,0] + ... + X[2,n]*W[n,0]

Di GPU, seseorang akan memprogram produk titik ini ke dalam "core" GPU, lalu mengeksekusinya di sebanyak mungkin "core" secara paralel untuk mencoba menghitung setiap nilai matriks yang dihasilkan sekaligus. Jika matriks yang dihasilkan berukuran 128x128, maka diperlukan 128x128=16 ribu "core" yang tersedia, yang biasanya tidak mungkin. GPU terbesar memiliki sekitar 4.000 core. Sebaliknya, TPU menggunakan hardware minimum untuk unit komputasi di MXU: hanya bfloat16 x bfloat16 => float32 multiply-accumulator, tidak ada yang lain. Unit ini sangat kecil sehingga TPU dapat menerapkan 16 ribu unit di MXU 128x128 dan memproses perkalian matriks ini sekaligus.

f1b283fc45966717.gif

Ilustrasi: array sistolik MXU. Elemen komputasi adalah multiply-accumulator. Nilai satu matriks dimuat ke dalam array (titik merah). Nilai matriks lainnya mengalir melalui array (titik abu-abu). Garis vertikal menyebarkan nilai ke atas. Garis horizontal menyebarkan jumlah parsial. Pengguna harus memverifikasi bahwa saat data mengalir melalui array, Anda akan mendapatkan hasil perkalian matriks yang keluar dari sisi kanan.

Selain itu, saat perkalian titik dihitung dalam MXU, jumlah sementara hanya mengalir di antara unit komputasi yang berdekatan. Nilai ini tidak perlu disimpan dan diambil ke/dari memori atau bahkan file register. Hasil akhirnya adalah arsitektur array sistolik TPU memiliki keunggulan kepadatan dan daya yang signifikan, serta keunggulan kecepatan yang tidak dapat diabaikan dibandingkan GPU, saat menghitung perkalian matriks.

Cloud TPU

Saat Anda meminta satu " Cloud TPU v2" di Google Cloud Platform, Anda akan mendapatkan mesin virtual (VM) yang memiliki board TPU yang terhubung ke PCI. Board TPU memiliki empat chip TPU dual-core. Setiap inti TPU memiliki VPU (Vector Processing Unit) dan MXU (MatriX multiply Unit) 128x128. "Cloud TPU" ini kemudian biasanya terhubung melalui jaringan ke VM yang memintanya. Jadi, gambaran lengkapnya akan terlihat seperti ini:

dfce5522ed644ece.png

Ilustrasi: VM Anda dengan akselerator "Cloud TPU" yang terhubung ke jaringan. "Cloud TPU" itu sendiri terdiri dari VM dengan board TPU yang terhubung ke PCI dengan empat chip TPU dual-core di dalamnya.

Pod TPU

Di pusat data Google, TPU terhubung ke interkoneksi komputasi berperforma tinggi (HPC) yang dapat membuatnya muncul sebagai satu akselerator yang sangat besar. Google menyebutnya pod dan dapat mencakup hingga 512 core TPU v2 atau 2048 core TPU v3.

2ec1e0d341e7fc34.jpeg

Ilustrasi: pod TPU v3. Board dan rak TPU yang terhubung melalui interkoneksi HPC.

Selama pelatihan, gradien dipertukarkan antar-core TPU menggunakan algoritma pengurangan penuh ( penjelasan yang baik tentang pengurangan penuh di sini). Model yang dilatih dapat memanfaatkan hardware dengan melatih ukuran batch yang besar.

d97b9cc5d40fdb1d.gif

Ilustrasi: sinkronisasi gradien selama pelatihan menggunakan algoritma all-reduce di jaringan HPC mesh toroida 2D TPU Google.

Software

Pelatihan ukuran batch besar

Ukuran batch yang ideal untuk TPU adalah 128 item data per core TPU, tetapi hardware sudah dapat menunjukkan pemanfaatan yang baik dari 8 item data per core TPU. Ingat bahwa satu Cloud TPU memiliki 8 core.

Dalam lab kode ini, kita akan menggunakan Keras API. Di Keras, batch yang Anda tentukan adalah ukuran batch global untuk seluruh TPU. Batch Anda akan otomatis dibagi menjadi 8 dan dijalankan di 8 core TPU.

da534407825f01e3.png

Untuk tips performa tambahan, lihat Panduan Performa TPU. Untuk ukuran batch yang sangat besar, penanganan khusus mungkin diperlukan di beberapa model. Lihat LARSOptimizer untuk mengetahui detail selengkapnya.

Di balik layar: XLA

Program Tensorflow menentukan grafik komputasi. TPU tidak menjalankan kode Python secara langsung, tetapi menjalankan grafik komputasi yang ditentukan oleh program Tensorflow Anda. Di balik layar, compiler yang disebut XLA (compiler aljabar linier yang dipercepat) mengubah grafik node komputasi Tensorflow menjadi kode mesin TPU. Compiler ini juga melakukan banyak pengoptimalan lanjutan pada kode dan tata letak memori Anda. Kompilasi terjadi secara otomatis saat tugas dikirim ke TPU. Anda tidak harus menyertakan XLA dalam rantai build secara eksplisit.

edce61112cd57972.png

Ilustrasi: untuk dijalankan di TPU, graf komputasi yang ditentukan oleh program Tensorflow Anda pertama-tama diterjemahkan ke dalam representasi XLA (compiler aljabar linier yang dipercepat), lalu dikompilasi oleh XLA ke dalam kode mesin TPU.

Menggunakan TPU di Keras

TPU didukung melalui Keras API mulai Tensorflow 2.1. Dukungan Keras berfungsi di TPU dan pod TPU. Berikut contoh yang berfungsi di TPU, GPU, dan CPU:

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

Dalam cuplikan kode ini:

  • TPUClusterResolver().connect() menemukan TPU di jaringan. Fungsi ini dapat digunakan tanpa parameter di sebagian besar sistem Google Cloud (job AI Platform, Colaboratory, Kubeflow, VM Deep Learning yang dibuat melalui utilitas 'ctpu up'). Sistem ini mengetahui lokasi TPU berkat variabel lingkungan TPU_NAME. Jika Anda membuat TPU secara manual, tetapkan variabel lingkungan TPU_NAME di VM yang Anda gunakan, atau panggil TPUClusterResolver dengan parameter eksplisit: TPUClusterResolver(tp_uname, zone, project)
  • TPUStrategy adalah bagian yang menerapkan algoritma sinkronisasi gradien "all-reduce" dan distribusi.
  • Strategi diterapkan melalui cakupan. Model harus ditentukan dalam strategy scope().
  • Fungsi tpu_model.fit mengharapkan objek tf.data.Dataset sebagai input untuk pelatihan TPU.

Tugas umum porting TPU

  • Meskipun ada banyak cara untuk memuat data dalam model Tensorflow, untuk TPU, penggunaan API tf.data.Dataset diperlukan.
  • TPU sangat cepat dan penyerapan data sering kali menjadi hambatan saat berjalan di TPU. Ada alat yang dapat Anda gunakan untuk mendeteksi hambatan data dan tips performa lainnya di Panduan Performa TPU.
  • Angka int8 atau int16 diperlakukan sebagai int32. TPU tidak memiliki hardware bilangan bulat yang beroperasi pada kurang dari 32 bit.
  • Beberapa operasi Tensorflow tidak didukung. Daftarnya ada di sini. Kabar baiknya adalah batasan ini hanya berlaku untuk kode pelatihan, yaitu penerusan dan penerusan mundur melalui model Anda. Anda tetap dapat menggunakan semua operasi Tensorflow di pipeline input data karena akan dieksekusi di CPU.
  • tf.py_func tidak didukung di TPU.

4. [INFO] Pengklasifikasi jaringan neural 101

Singkatnya

Jika semua istilah yang dicetak tebal di paragraf berikutnya sudah Anda ketahui, Anda dapat melanjutkan ke latihan berikutnya. Jika Anda baru memulai deep learning, selamat datang, dan silakan baca terus.

Untuk model yang dibuat sebagai urutan lapisan, Keras menawarkan Sequential API. Misalnya, pengklasifikasi gambar yang menggunakan tiga lapisan padat dapat ditulis di Keras sebagai:

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=[192, 192, 3]),
    tf.keras.layers.Dense(500, activation="relu"),
    tf.keras.layers.Dense(50, activation="relu"),
    tf.keras.layers.Dense(5, activation='softmax') # classifying into 5 classes
])

# this configures the training of the model. Keras calls it "compiling" the model.
model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy']) # % of correct answers

# train the model
model.fit(dataset, ... )

688858c21e3beff2.png

Jaringan neural padat

Ini adalah jaringan neural paling sederhana untuk mengklasifikasikan gambar. Jaringan ini terdiri dari "neuron" yang disusun dalam lapisan. Lapisan pertama memproses data input dan memasukkan outputnya ke lapisan lain. Lapisan ini disebut "padat" karena setiap neuron terhubung ke semua neuron di lapisan sebelumnya.

c21bae6dade487bc.png

Anda dapat memasukkan gambar ke dalam jaringan seperti itu dengan meratakan nilai RGB semua pikselnya menjadi vektor panjang dan menggunakannya sebagai input. Teknik ini bukan yang terbaik untuk pengenalan gambar, tetapi kami akan meningkatkannya nanti.

Neuron, aktivasi, RELU

"Neuron" menghitung jumlah bobot semua inputnya, menambahkan nilai yang disebut "bias", dan meneruskan hasilnya melalui "fungsi aktivasi". Bobot dan bias tidak diketahui pada awalnya. Bobot ini akan diinisialisasi secara acak dan "dipelajari" dengan melatih jaringan neural pada banyak data yang diketahui.

644f4213a4ee70e5.png

Fungsi aktivasi yang paling populer disebut RELU untuk Rectified Linear Unit. Ini adalah fungsi yang sangat sederhana seperti yang dapat Anda lihat pada grafik di atas.

Aktivasi softmax

Jaringan di atas diakhiri dengan lapisan 5 neuron karena kita mengklasifikasikan bunga ke dalam 5 kategori (mawar, tulip, dandelion, daisy, bunga matahari). Neuron di lapisan perantara diaktifkan menggunakan fungsi aktivasi RELU klasik. Namun, di lapisan terakhir, kita ingin menghitung angka antara 0 dan 1 yang merepresentasikan probabilitas bunga ini sebagai mawar, tulip, dan sebagainya. Untuk itu, kita akan menggunakan fungsi aktivasi yang disebut "softmax".

Penerapan softmax pada vektor dilakukan dengan mengambil eksponensial setiap elemen, lalu menormalisasi vektor, biasanya menggunakan norma L1 (jumlah nilai absolut) sehingga nilai-nilai tersebut berjumlah 1 dan dapat ditafsirkan sebagai probabilitas.

ef0d98c0952c262d.png d51252f75894479e.gif

Kerugian entropi silang

Setelah jaringan neural kita menghasilkan prediksi dari gambar input, kita perlu mengukur seberapa baik prediksi tersebut, yaitu jarak antara yang disampaikan jaringan dan jawaban yang benar, yang sering disebut "label". Ingatlah bahwa kita memiliki label yang benar untuk semua gambar dalam set data.

Jarak apa pun akan berfungsi, tetapi untuk masalah klasifikasi, yang disebut "jarak entropi silang" adalah yang paling efektif. Kita akan menyebutnya sebagai fungsi error atau "loss":

7bdf8753d20617fb.png

Penurunan gradien

"Melatih" jaringan neural sebenarnya berarti menggunakan gambar dan label pelatihan untuk menyesuaikan bobot dan bias sehingga dapat meminimalkan fungsi loss cross-entropy. Berikut cara kerjanya.

Cross-entropy adalah fungsi bobot, bias, piksel gambar pelatihan, dan kelasnya yang diketahui.

Jika kita menghitung turunan parsial cross-entropy relatif terhadap semua bobot dan semua bias, kita akan mendapatkan "gradien", yang dihitung untuk gambar, label, dan nilai bobot dan bias saat ini. Ingatlah bahwa kita dapat memiliki jutaan bobot dan bias, sehingga menghitung gradien akan membutuhkan banyak pekerjaan. Untungnya, Tensorflow melakukannya untuk kita. Properti matematika gradien adalah bahwa gradien mengarah "ke atas". Karena kita ingin menuju tempat dengan entropi silang yang rendah, kita bergerak ke arah yang berlawanan. Kita memperbarui bobot dan bias dengan sebagian kecil gradien. Kemudian, kita melakukan hal yang sama berulang kali menggunakan batch berikutnya dari gambar dan label pelatihan, dalam loop pelatihan. Semoga, proses ini akan mencapai titik di mana entropi silang minimal, meskipun tidak ada jaminan bahwa minimum ini unik.

gradient descent2.png

Mini-batching dan momentum

Anda dapat menghitung gradien hanya pada satu contoh gambar dan langsung memperbarui bobot dan bias, tetapi melakukannya pada batch, misalnya, 128 gambar akan memberikan gradien yang lebih baik dalam merepresentasikan batasan yang diberlakukan oleh contoh gambar yang berbeda dan oleh karena itu cenderung lebih cepat mencapai solusi. Ukuran tumpukan mini adalah parameter yang dapat disesuaikan.

Teknik ini, yang terkadang disebut "stochastic gradient descent", memiliki manfaat lain yang lebih pragmatis: bekerja dengan batch juga berarti bekerja dengan matriks yang lebih besar dan biasanya lebih mudah dioptimalkan di GPU dan TPU.

Konvergensi masih bisa sedikit kacau dan bahkan dapat berhenti jika vektor gradien semuanya nol. Apakah itu berarti kita telah menemukan nilai minimum? Tidak selalu. Komponen gradien dapat bernilai nol pada minimum atau maksimum. Dengan vektor gradien yang memiliki jutaan elemen, jika semuanya adalah nol, probabilitas bahwa setiap nol sesuai dengan titik minimum dan tidak ada yang sesuai dengan titik maksimum cukup kecil. Dalam ruang dengan banyak dimensi, titik pelana cukup umum dan kita tidak ingin berhenti di titik tersebut.

52e824fe4716c4a0.png

Ilustrasi: titik pelana. Gradiennya adalah 0, tetapi bukan minimum di semua arah. (Atribusi gambar Wikimedia: By Nicoguaro - Own work, CC BY 3.0)

Solusinya adalah menambahkan beberapa momentum ke algoritma pengoptimalan sehingga dapat melewati titik pelana tanpa berhenti.

Glosarium

batch atau tumpukan mini: pelatihan selalu dilakukan pada batch data dan label pelatihan. Dengan demikian, algoritma dapat melakukan konvergensi. Dimensi "batch" biasanya merupakan dimensi pertama tensor data. Misalnya, tensor dengan bentuk [100, 192, 192, 3] berisi 100 gambar berukuran 192x192 piksel dengan tiga nilai per piksel (RGB).

Kerugian entropi silang: fungsi kerugian khusus yang sering digunakan dalam pengklasifikasi.

lapisan padat: lapisan neuron di mana setiap neuron terhubung ke semua neuron di lapisan sebelumnya.

fitur: input jaringan saraf terkadang disebut "fitur". Seni mencari tahu bagian mana dari set data (atau kombinasi bagian) yang akan dimasukkan ke jaringan neural untuk mendapatkan prediksi yang baik disebut "rekayasa fitur".

label: nama lain untuk "kelas" atau jawaban yang benar dalam masalah klasifikasi terawasi

kecepatan pembelajaran: fraksi gradien yang digunakan untuk memperbarui bobot dan bias pada setiap iterasi loop pelatihan.

logits: output lapisan neuron sebelum fungsi aktivasi diterapkan disebut "logits". Istilah ini berasal dari "fungsi logistik" alias "fungsi sigmoid" yang dulunya merupakan fungsi aktivasi paling populer. "Neuron outputs before logistic function" disingkat menjadi "logits".

loss: fungsi error yang membandingkan output jaringan neural dengan jawaban yang benar

neuron: menghitung jumlah input yang diberi bobot, menambahkan bias, dan meneruskan hasilnya melalui fungsi aktivasi.

enkode one-hot: kelas 3 dari 5 dienkode sebagai vektor 5 elemen, semua nol kecuali yang ke-3 yaitu 1.

relu: unit linear yang diperbaiki. Fungsi aktivasi yang populer untuk neuron.

sigmoid: fungsi aktivasi lain yang dulu populer dan masih berguna dalam kasus khusus.

softmax: fungsi aktivasi khusus yang bekerja pada vektor, meningkatkan perbedaan antara komponen terbesar dan semua komponen lainnya, serta menormalisasi vektor agar memiliki jumlah 1 sehingga dapat ditafsirkan sebagai vektor probabilitas. Digunakan sebagai langkah terakhir dalam pengklasifikasi.

tensor: "Tensor" seperti matriks, tetapi dengan jumlah dimensi yang berubah-ubah. Tensor 1 dimensi adalah vektor. Tensor 2 dimensi adalah matriks. Kemudian, Anda dapat memiliki tensor dengan 3, 4, 5, atau lebih dimensi.

5. [INFO] Jaringan neural konvolusional

Singkatnya

Jika semua istilah yang dicetak tebal di paragraf berikutnya sudah Anda ketahui, Anda dapat melanjutkan ke latihan berikutnya. Jika Anda baru memulai jaringan neural konvolusional, silakan baca terus.

convolutional.gif

Ilustrasi: memfilter gambar dengan dua filter berurutan yang masing-masing terdiri dari 48 bobot yang dapat dipelajari (4x4x3=48).

Berikut tampilan jaringan neural konvolusional sederhana di Keras:

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=12, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=6, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

688858c21e3beff2.png

Dasar-dasar jaringan neural konvolusional

Dalam lapisan jaringan konvolusional, satu "neuron" melakukan jumlah berbobot piksel tepat di atasnya, hanya di seluruh area kecil gambar. Lapisan ini menambahkan bias dan memasukkan jumlah melalui fungsi aktivasi, seperti halnya neuron di lapisan padat biasa. Operasi ini kemudian diulangi di seluruh gambar menggunakan bobot yang sama. Ingatlah bahwa di lapisan padat, setiap neuron memiliki bobotnya sendiri. Di sini, satu "patch" bobot meluncur di seluruh gambar ke kedua arah (sebuah "konvolusi"). Output memiliki nilai sebanyak jumlah piksel dalam gambar (meskipun beberapa padding diperlukan di tepi). Operasi ini adalah operasi pemfilteran, menggunakan filter dengan 4x4x3=48 bobot.

Namun, 48 bobot tidak akan cukup. Untuk menambahkan lebih banyak derajat kebebasan, kita mengulangi operasi yang sama dengan kumpulan bobot baru. Tindakan ini akan menghasilkan serangkaian output filter baru. Mari kita sebut sebagai "saluran" output berdasarkan analogi dengan saluran R,G,B dalam gambar input.

Screen Shot 2016-07-29 at 16.02.37.png

Dua (atau lebih) set bobot dapat dijumlahkan sebagai satu tensor dengan menambahkan dimensi baru. Hal ini memberi kita bentuk umum tensor bobot untuk lapisan konvolusional. Karena jumlah saluran input dan output adalah parameter, kita dapat mulai menumpuk dan merangkai lapisan konvolusional.

d1b557707bcd1cb9.png

Ilustrasi: jaringan neural konvolusional mengubah "kubus" data menjadi "kubus" data lainnya.

Konvolusi berirama, penggabungan maks

Dengan melakukan konvolusi dengan langkah 2 atau 3, kita juga dapat mengecilkan kubus data yang dihasilkan dalam dimensi horizontalnya. Ada dua cara umum untuk melakukannya:

  • Konvolusi berirama: filter geser seperti di atas, tetapi dengan irama >1
  • Penggabungan maks: jendela geser yang menerapkan operasi MAX (biasanya pada patch 2x2, diulang setiap 2 piksel)

2b2d4263bb8470b.gif

Ilustrasi: menggeser jendela komputasi sebesar 3 piksel akan menghasilkan lebih sedikit nilai output. Konvolusi berirama atau penggabungan maks (maks pada jendela 2x2 yang bergeser dengan irama 2) adalah cara untuk mengecilkan kubus data dalam dimensi horizontal.

Convolutional classifier (Pengklasifikasi konvolusional)

Terakhir, kita melampirkan head klasifikasi dengan meratakan kubus data terakhir dan memasukkannya melalui lapisan padat yang diaktifkan softmax. Pengklasifikasi konvolusional standar dapat terlihat seperti ini:

4a61aaffb6cba3d1.png

Ilustrasi: pengklasifikasi gambar menggunakan lapisan konvolusional dan softmax. Menggunakan filter 3x3 dan 1x1. Lapisan maxpool mengambil nilai maksimum dari grup titik data 2x2. Kepala klasifikasi diimplementasikan dengan lapisan padat dengan aktivasi softmax.

Di Keras

Stack konvolusional yang diilustrasikan di atas dapat ditulis di Keras seperti ini:

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)    
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=16, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=8, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

6. [INFO BARU] Arsitektur konvolusional modern

Singkatnya

7968830b57b708c0.png

Ilustrasi: "modul" konvolusional. Apa yang terbaik saat ini? Lapisan max-pool yang diikuti dengan lapisan konvolusional 1x1 atau kombinasi lapisan yang berbeda? Coba semuanya, gabungkan hasilnya, dan biarkan jaringan memutuskan. Di sebelah kanan: arsitektur konvolusional " inception" yang menggunakan modul tersebut.

Di Keras, untuk membuat model dengan alur data yang dapat bercabang masuk dan keluar, Anda harus menggunakan gaya model "fungsional". Berikut ini contohnya:

l = tf.keras.layers # syntax shortcut

y = l.Conv2D(filters=32, kernel_size=3, padding='same',
             activation='relu', input_shape=[192, 192, 3])(x) # x=input image

# module start: branch out
y1 = l.Conv2D(filters=32, kernel_size=1, padding='same', activation='relu')(y)
y3 = l.Conv2D(filters=32, kernel_size=3, padding='same', activation='relu')(y)
y = l.concatenate([y1, y3]) # output now has 64 channels
# module end: concatenation

# many more layers ...

# Create the model by specifying the input and output tensors.
# Keras layers track their connections automatically so that's all that's needed.
z = l.Dense(5, activation='softmax')(y)
model = tf.keras.Model(x, z)

688858c21e3beff2.png

Trik murahan lainnya

Filter 3x3 kecil

40a7b15fb7dbe75c.png

Dalam ilustrasi ini, Anda akan melihat hasil dari dua filter 3x3 berturut-turut. Coba telusuri kembali titik data mana yang berkontribusi pada hasil: kedua filter 3x3 berturut-turut ini menghitung beberapa kombinasi wilayah 5x5. Kombinasinya tidak persis sama dengan yang akan dihitung oleh filter 5x5, tetapi patut dicoba karena dua filter 3x3 berturut-turut lebih murah daripada satu filter 5x5.

Konvolusi 1x1?

fd7cac16f8ecb423.png

Dalam istilah matematika, konvolusi "1x1" adalah perkalian dengan konstanta, bukan konsep yang terlalu berguna. Namun, dalam jaringan saraf tiruan konvolusional, ingatlah bahwa filter diterapkan ke kubus data, bukan hanya gambar 2D. Oleh karena itu, filter "1x1" menghitung jumlah berbobot dari kolom data 1x1 (lihat ilustrasi) dan saat Anda menggesernya di seluruh data, Anda akan mendapatkan kombinasi linear dari saluran input. Hal ini sebenarnya berguna. Jika Anda menganggap saluran sebagai hasil dari operasi pemfilteran individual, misalnya filter untuk "telinga runcing", filter lain untuk "kumis", dan filter ketiga untuk "mata sipit", maka lapisan konvolusional "1x1" akan menghitung beberapa kemungkinan kombinasi linear dari fitur ini, yang mungkin berguna saat mencari "kucing". Selain itu, lapisan 1x1 menggunakan lebih sedikit bobot.

7. Squeezenet

Cara sederhana untuk menggabungkan ide-ide ini telah ditunjukkan dalam makalah"Squeezenet". Penulis menyarankan desain modul konvolusional yang sangat sederhana, hanya menggunakan lapisan konvolusional 1x1 dan 3x3.

1730ac375379269b.png

Ilustrasi: arsitektur squeezenet berdasarkan "modul api". Model ini bergantian menggunakan lapisan 1x1 yang "memadatkan" data yang masuk dalam dimensi vertikal, diikuti dengan dua lapisan konvolusional 1x1 dan 3x3 paralel yang "memperluas" kedalaman data lagi.

Interaktif

Lanjutkan di notebook sebelumnya dan bangun jaringan neural konvolusional yang terinspirasi dari squeezenet. Anda harus mengubah kode model ke "gaya fungsional" Keras.

c3df49e90e5a654f.png Keras_Flowers_TPU (playground).ipynb

Info tambahan

Akan berguna untuk latihan ini jika Anda menentukan fungsi bantuan untuk modul squeezenet:

def fire(x, squeeze, expand):
  y = l.Conv2D(filters=squeeze, kernel_size=1, padding='same', activation='relu')(x)
  y1 = l.Conv2D(filters=expand//2, kernel_size=1, padding='same', activation='relu')(y)
  y3 = l.Conv2D(filters=expand//2, kernel_size=3, padding='same', activation='relu')(y)
  return tf.keras.layers.concatenate([y1, y3])

# this is to make it behave similarly to other Keras layers
def fire_module(squeeze, expand):
  return lambda x: fire(x, squeeze, expand)

# usage:
x = l.Input(shape=[192, 192, 3])
y = fire_module(squeeze=24, expand=48)(x) # typically, squeeze is less than expand
y = fire_module(squeeze=32, expand=64)(y)
...
model = tf.keras.Model(x, y)

Tujuan kali ini adalah mencapai akurasi 80%.

Hal-hal yang dapat dicoba

Mulai dengan satu lapisan konvolusional, lalu ikuti dengan "fire_modules", bergantian dengan lapisan MaxPooling2D(pool_size=2). Anda dapat bereksperimen dengan 2 hingga 4 lapisan max pooling dalam jaringan dan juga dengan 1, 2, atau 3 modul fire berurutan di antara lapisan max pooling.

Dalam modul api, parameter "squeeze" biasanya harus lebih kecil daripada parameter "expand". Parameter ini sebenarnya adalah jumlah filter. Nilai ini biasanya berkisar antara 8 hingga 196. Anda dapat bereksperimen dengan arsitektur yang jumlah filternya meningkat secara bertahap melalui jaringan, atau arsitektur sederhana yang semua modul apinya memiliki jumlah filter yang sama.

Berikut ini contohnya:

x = tf.keras.layers.Input(shape=[*IMAGE_SIZE, 3]) # input is 192x192 pixels RGB

y = tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu')(x)
y = fire_module(24, 48)(y)
y = tf.keras.layers.MaxPooling2D(pool_size=2)(y)
y = fire_module(24, 48)(y)
y = tf.keras.layers.MaxPooling2D(pool_size=2)(y)
y = fire_module(24, 48)(y)
y = tf.keras.layers.GlobalAveragePooling2D()(y)
y = tf.keras.layers.Dense(5, activation='softmax')(y)

model = tf.keras.Model(x, y)

Pada titik ini, Anda mungkin menyadari bahwa eksperimen Anda tidak berjalan dengan baik dan tujuan akurasi 80% tampaknya sulit dicapai. Saatnya melakukan beberapa trik murah lainnya.

Normalisasi Batch

Batch norm akan membantu mengatasi masalah konvergensi yang Anda alami. Akan ada penjelasan mendetail tentang teknik ini di workshop berikutnya. Untuk saat ini, gunakan sebagai bantuan "ajaib" black box dengan menambahkan baris ini setelah setiap lapisan konvolusional di jaringan Anda, termasuk lapisan di dalam fungsi fire_module:

y = tf.keras.layers.BatchNormalization(momentum=0.9)(y)
# please adapt the input and output "y"s to whatever is appropriate in your context

Parameter momentum harus dikurangi dari nilai defaultnya 0,99 menjadi 0,9 karena set data kita kecil. Lupakan detail ini untuk saat ini.

Augmentasi data

Anda akan mendapatkan beberapa poin persentase lagi dengan menambah data menggunakan transformasi sederhana seperti pembalikan kiri-kanan perubahan saturasi:

4ed2958e09b487ca.png

ad795b70334e0d6b.png

Hal ini sangat mudah dilakukan di TensorFlow dengan tf.data.Dataset API. Tentukan fungsi transformasi baru untuk data Anda:

def data_augment(image, label):
    image = tf.image.random_flip_left_right(image)
    image = tf.image.random_saturation(image, lower=0, upper=2)
    return image, label

Kemudian, gunakan dalam transformasi data akhir Anda (sel "training and validation datasets", fungsi "get_batched_dataset"):

dataset = dataset.repeat() # existing line
# insert this
if augment_data:
  dataset = dataset.map(data_augment, num_parallel_calls=AUTO)
dataset = dataset.shuffle(2048) # existing line

Jangan lupa untuk membuat augmentasi data menjadi opsional dan menambahkan kode yang diperlukan untuk memastikan hanya set data pelatihan yang di-augmentasi. Tidak ada gunanya memperbesar set data validasi.

Akurasi 80% dalam 35 epoch kini dapat dicapai.

Solusi

Berikut adalah notebook solusi. Anda dapat menggunakannya jika mengalami masalah.

c3df49e90e5a654f.png Keras_Flowers_TPU_squeezenet.ipynb

Yang telah kita bahas

  • 🤔 Model "gaya fungsional" Keras
  • 🤓 Arsitektur Squeezenet
  • 🤓 Augmentasi data dengan tf.data.dataset

Luangkan waktu sejenak untuk meninjau checklist ini dalam pikiran Anda.

8. Xception yang di-fine-tune

Konvolusi yang dapat dipisahkan

Cara lain untuk menerapkan lapisan konvolusi baru-baru ini menjadi populer: konvolusi yang dapat dipisahkan menurut kedalaman. Saya tahu, namanya cukup rumit, tetapi konsepnya cukup sederhana. Lapisan ini diimplementasikan di TensorFlow dan Keras sebagai tf.keras.layers.SeparableConv2D.

Konvolusi yang dapat dipisahkan juga menjalankan filter pada gambar, tetapi menggunakan serangkaian bobot yang berbeda untuk setiap saluran gambar input. Setelah itu, dilakukan "konvolusi 1x1", serangkaian perkalian titik yang menghasilkan jumlah berbobot dari saluran yang difilter. Dengan bobot baru setiap kali, sebanyak mungkin kombinasi berbobot dari saluran dihitung sesuai kebutuhan.

615720b803bf8dda.gif

Ilustrasi: konvolusi yang dapat dipisahkan. Fase 1: konvolusi dengan filter terpisah untuk setiap saluran. Fase 2: penggabungan saluran secara linear. Diulang dengan kumpulan bobot baru hingga jumlah saluran output yang diinginkan tercapai. Fase 1 juga dapat diulang, dengan bobot baru setiap kali, tetapi dalam praktiknya jarang dilakukan.

Konvolusi yang dapat dipisahkan digunakan dalam arsitektur jaringan konvolusional terbaru: MobileNetV2, Xception, EfficientNet. Ngomong-ngomong, MobileNetV2 adalah model yang Anda gunakan untuk pemelajaran transfer sebelumnya.

Operasi ini lebih murah daripada konvolusi reguler dan terbukti sama efektifnya dalam praktiknya. Berikut adalah jumlah bobot untuk contoh yang diilustrasikan di atas:

Lapisan konvolusional: 4 x 4 x 3 x 5 = 240

Lapisan konvolusional yang dapat dipisahkan: 4 x 4 x 3 + 3 x 5 = 48 + 15 = 63

Pembaca dapat menghitung jumlah perkalian yang diperlukan untuk menerapkan setiap gaya lapisan konvolusional dengan cara yang serupa. Konvolusi yang dapat dipisahkan lebih kecil dan jauh lebih efektif secara komputasi.

Interaktif

Mulai ulang dari notebook playground "transfer learning", tetapi kali ini pilih Xception sebagai model terlatih. Xception hanya menggunakan konvolusi yang dapat dipisahkan. Biarkan semua bobot dapat dilatih. Kami akan menyempurnakan bobot yang telah dilatih sebelumnya pada data kami, bukan menggunakan lapisan yang telah dilatih sebelumnya.

c3df49e90e5a654f.png Keras Flowers transfer learning (playground).ipynb

Tujuan: akurasi > 95% (Ya, sungguh, ini mungkin!)

Karena ini adalah latihan terakhir, Anda akan memerlukan lebih banyak kode dan pekerjaan data science.

Info tambahan tentang penyesuaian

Xception tersedia dalam model terlatih standar di tf.keras.application.* Jangan lupa untuk membuat semua bobot dapat dilatih kali ini.

pretrained_model = tf.keras.applications.Xception(input_shape=[*IMAGE_SIZE, 3],
                                                  include_top=False)
pretrained_model.trainable = True

Untuk mendapatkan hasil yang baik saat menyesuaikan model, Anda harus memperhatikan kecepatan pembelajaran dan menggunakan jadwal kecepatan pembelajaran dengan periode penyesuaian. Seperti ini:

9b1af213b2b36d47.png

Memulai dengan kecepatan pembelajaran standar akan mengganggu bobot model yang telah dilatih sebelumnya. Memulai secara progresif akan mempertahankan data tersebut hingga model telah terhubung ke data Anda dan dapat memodifikasinya dengan cara yang wajar. Setelah ramp, Anda dapat melanjutkan dengan laju pembelajaran yang konstan atau menurun secara eksponensial.

Di Keras, laju pembelajaran ditentukan melalui callback yang memungkinkan Anda menghitung laju pembelajaran yang sesuai untuk setiap epoch. Keras akan meneruskan laju pembelajaran yang benar ke pengoptimal untuk setiap epoch.

def lr_fn(epoch):
  lr = ...
  return lr

lr_callback = tf.keras.callbacks.LearningRateScheduler(lr_fn, verbose=True)

model.fit(..., callbacks=[lr_callback])

Solusi

Berikut adalah notebook solusi. Anda dapat menggunakannya jika mengalami masalah.

c3df49e90e5a654f.png 07_Keras_Flowers_TPU_xception_fine_tuned_best.ipynb

Yang telah kita bahas

  • 🤔 Konvolusi yang dapat dipisahkan menurut kedalaman
  • 🤓 Jadwal kecepatan pembelajaran
  • 😈 Melakukan fine-tuning model terlatih.

Luangkan waktu sejenak untuk meninjau checklist ini dalam pikiran Anda.

9. Selamat!

Anda telah membangun jaringan neural konvolusional modern pertama dan melatihnya hingga akurasi 90% +, melakukan iterasi pada pelatihan berikutnya hanya dalam beberapa menit berkat TPU. Ini mengakhiri 4 "codelab Keras di TPU":

TPU dalam praktik

TPU dan GPU tersedia di Cloud AI Platform:

Terakhir, kami menyambut masukan dengan tangan terbuka. Beri tahu kami jika Anda melihat sesuatu yang tidak beres di lab ini atau jika menurut Anda lab ini harus ditingkatkan. Masukan dapat diberikan melalui masalah GitHub [link masukan].

HR.png

Martin Görner ID small.jpg
Penulis: Martin Görner
Twitter: @martin_gorner

tensorflow logo.jpg
www.tensorflow.org