ConvNets yang Keras dan modern, di TPU

1. Ringkasan

Di lab ini, Anda akan mempelajari cara membangun, melatih, dan menyesuaikan dari awal jaringan neural konvolusional Anda sendiri dengan Keras dan Tensorflow 2. Hal ini kini dapat dilakukan dalam hitungan menit menggunakan kecanggihan TPU. Anda juga akan mempelajari beberapa pendekatan dari transfer learning yang sangat sederhana hingga arsitektur konvolusi modern seperti Squeezenet. Lab ini mencakup penjelasan teoretis mengenai jaringan neural dan merupakan titik awal yang baik bagi developer yang mempelajari deep learning.

Membaca makalah deep learning bisa jadi sulit dan membingungkan. Mari kita lihat secara langsung arsitektur jaringan neural konvolusional modern.

ca8cc21f6838eccc.png

Yang akan Anda pelajari

  • Menggunakan Keras dan Tensor Processing Unit (TPU) untuk membangun model kustom Anda lebih cepat.
  • Untuk menggunakan tf.data.Dataset API dan format TFRecord untuk memuat data pelatihan secara efisien.
  • Untuk melakukan kecurangan 😈, gunakan transfer learning, bukan membuat model Anda sendiri.
  • Untuk menggunakan gaya model fungsional dan berurutan Keras.
  • Untuk membuat pengklasifikasi Keras Anda sendiri dengan lapisan softmax dan kerugian entropi silang.
  • Untuk menyesuaikan model Anda dengan pilihan lapisan konvolusi yang baik.
  • Untuk mengeksplorasi ide arsitektur konvnet modern seperti modul, penggabungan rata-rata global, dll.
  • Untuk membuat convnet modern sederhana menggunakan arsitektur Squeezenet.

Masukan

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

2. Memulai cepat Google Colaboratory

Lab ini menggunakan Kolaborasi Google dan tidak memerlukan penyiapan dari Anda. Anda dapat menjalankannya dari Chromebook. Buka file di bawah, lalu jalankan sel untuk memahami notebook Colab.

c3df49e90e5a654f.png Welcome to Colab.ipynb

Memilih backend TPU

8832c6208c99687d.pngS

Di menu Colab, pilih Runtime > Ubah jenis runtime, lalu pilih TPU. Di codelab ini, Anda akan menggunakan TPU (Tensor Processing Unit) canggih yang didukung untuk pelatihan akselerasi hardware. Koneksi ke runtime akan terjadi secara otomatis pada eksekusi pertama, atau Anda dapat menggunakan tombol "Hubungkan" di pojok 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. Fitur ini adalah fitur notebook khusus Colab. Anda dapat mengkliknya dua kali untuk melihat kode di dalamnya, tetapi biasanya ini tidak terlalu menarik. Biasanya mendukung atau fungsi visualisasi. Anda masih perlu menjalankan sel ini agar fungsi di dalamnya dapat ditentukan.

Autentikasi

cdd4b41413100543.png

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

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

Ringkasan singkat

f88cf6facfc70166.png

Kode untuk melatih model pada 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=...)

Kita akan menggunakan TPU saat ini untuk membangun dan mengoptimalkan pengklasifikasi bunga dengan kecepatan interaktif (menit per sesi pelatihan).

688858c21e3beff2.pngS

Mengapa TPU?

GPU modern diatur berdasarkan "core" yang dapat diprogram, yaitu arsitektur yang sangat fleksibel yang memungkinkannya 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 perkalian matriks besar, seperti jaringan saraf.

8eb3e718b8e2ed08.pngS

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

Hardware

MXU dan VPU

Core TPU v2 terbuat 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.pngS

Floating point presisi campuran dan bfloat16

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

19c5fc432840c714.png

Pelatihan jaringan neural biasanya tahan terhadap derau yang diperkenalkan oleh presisi floating point yang dikurangi. Ada kalanya derau bahkan membantu pengoptimal melakukan konvergensi. Presisi floating point 16-bit secara tradisional telah digunakan untuk mempercepat komputasi tetapi format float16 dan float32 memiliki rentang yang sangat berbeda. Mengurangi presisi dari float32 ke float16 biasanya menghasilkan aliran berlebih dan kurang. Ada solusi, tetapi pekerjaan tambahan biasanya diperlukan agar float16 berfungsi.

Itulah mengapa Google memperkenalkan format bfloat16 di TPU. bfloat16 adalah float32 yang terpotong dengan bit dan rentang eksponen yang sama persis dengan float32. Hal ini, ditambah dengan fakta bahwa TPU menghitung perkalian matriks dalam presisi campuran dengan input bfloat16, tetapi output float32, berarti bahwa, biasanya, tidak ada perubahan kode yang diperlukan untuk mendapatkan manfaat dari peningkatan performa presisi yang dikurangi.

Array sistolik

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

Elemen dasar perkalian matriks adalah perkalian titik antara garis dari satu matriks dan kolom dari matriks lain (lihat ilustrasi di bagian atas bagian ini). Untuk perkalian matriks Y=X*W, 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 perkalian titik ini ke dalam "core" GPU, lalu menjalankannya di sebanyak mungkin "core" yang tersedia secara paralel untuk mencoba dan menghitung setiap nilai matriks yang dihasilkan sekaligus. Jika matriks yang dihasilkan berukuran 128x128, diperlukan 128x128=16K "core" yang biasanya tidak tersedia. GPU terbesar memiliki sekitar 4.000 core. Di sisi lain, TPU menggunakan hardware minimum untuk unit komputasi di MXU: hanya multi-akumulator bfloat16 x bfloat16 => float32, tidak ada lainnya. Ini sangat kecil sehingga TPU dapat mengimplementasikan 16K di antaranya dalam MXU 128x128 dan memproses perkalian matriks ini dalam satu langkah.

f1b283fc45966717.gif

Ilustrasi: array sistolik MXU. Elemen komputasi adalah pengganda akumulator. Nilai satu matriks dimuat ke dalam array (titik merah). Nilai matriks lain mengalir melalui array (titik abu-abu). Garis vertikal menyebarkan nilai ke atas. Garis horizontal menyebarkan jumlah parsial. Ini menjadi latihan bagi pengguna untuk memverifikasi bahwa saat data mengalir melalui array, Anda akan mendapatkan hasil perkalian matriks yang keluar dari sisi kanan.

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

Cloud TPU

Saat meminta satu "Cloud TPU v2" di Google Cloud Platform, Anda akan mendapatkan virtual machine (VM) yang memiliki board TPU yang terhubung ke PCI. Papan TPU memiliki empat chip TPU dual-core. Setiap inti TPU memiliki VPU (Vector Processing Unit) dan MXU (MatriX dikalikan Unit) 128x128. "Cloud TPU" ini 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 terpasang pada jaringan. "Cloud TPU" sendiri terbuat dari VM dengan board TPU yang terpasang pada PCI dan dilengkapi 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 TPU v3 core.

2ec1e0d341e7fc34.jpeg

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

Selama pelatihan, gradien dipertukarkan antar-core TPU menggunakan algoritma all-reduce ( penjelasan yang baik tentang all-reduce di sini). Model yang sedang dilatih dapat memanfaatkan hardware dengan melakukan pelatihan pada ukuran batch yang besar.

d97b9cc5d40fdb1d.gif

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

Software

Pelatihan ukuran batch besar

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

Dalam codelab 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 mendapatkan tips performa tambahan, lihat Panduan Performa TPU. Untuk ukuran tumpukan yang sangat besar, perlakuan khusus pada beberapa model mungkin diperlukan. Lihat LARSOptimizer untuk mengetahui detail selengkapnya.

Di balik layar: XLA

Program Tensorflow menentukan grafik komputasi. TPU tidak langsung menjalankan kode Python, tetapi menjalankan grafik komputasi yang ditentukan oleh program Tensorflow Anda. Di balik layar, compiler bernama XLA (Accelerated Linear Algebra compiler) mengubah grafik Tensorflow dari node komputasi 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, grafik komputasi yang ditentukan oleh program Tensorflow Anda akan diterjemahkan terlebih dahulu ke representasi XLA (compiler Algebra Linear yang dipercepat), kemudian dikompilasi oleh XLA menjadi 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 adalah 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. Cloud Endpoints berfungsi tanpa parameter di sebagian besar sistem Google Cloud (tugas AI Platform, Colaboratory, Kubeflow, Deep Learning VM yang dibuat melalui utilitas 'ctpu up'). Sistem ini dapat mengetahui lokasi TPU mereka berkat variabel lingkungan TPU_NAME. Jika Anda membuat TPU secara manual, tetapkan variabel lingkungan TPU_NAME di VM tempat Anda menggunakannya, atau panggil TPUClusterResolver dengan parameter eksplisit: TPUClusterResolver(tp_uname, zone, project)
  • TPUStrategy adalah bagian yang mengimplementasikan distribusi dan algoritma sinkronisasi gradien "all-reduce".
  • Strategi diterapkan melalui cakupan. Model harus ditentukan dalam cakupan strategi().
  • Fungsi tpu_model.fit mengharapkan objek tf.data.Dataset untuk input pelatihan TPU.

Tugas transfer TPU umum

  • Meskipun ada banyak cara untuk memuat data dalam model TensorFlow, penggunaan tf.data.Dataset API diperlukan untuk TPU.
  • TPU sangat cepat dan menyerap data sering menjadi bottleneck saat menjalankannya. Ada alat yang dapat Anda gunakan untuk mendeteksi bottleneck data dan tips performa lainnya di Panduan Performa TPU.
  • angka int8 atau int16 dianggap 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 maju dan 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. Memuat Data

c0ecb860e4cad0a9.jpeg cc4781a7739c49ae.jpeg 81236b00f8bbf39e.jpeg 961e2228974076bb.jpeg 7517dc163bdffcd5.jpeg 96392df4767f566d.png

Kita akan bekerja dengan {i>dataset<i} gambar bunga. Tujuannya adalah belajar mengkategorikannya ke dalam 5 jenis bunga. Pemuatan data dilakukan menggunakan tf.data.Dataset API. Pertama, mari kita kenali API.

Langsung

Buka notebook berikut, jalankan sel (Shift-ENTER), lalu ikuti petunjuk di mana pun Anda melihat label "DIPERLUKAN KERJA".

c3df49e90e5a654f.png Fun with tf.data.Dataset (playground).ipynb

Informasi tambahan

Tentang set data "flowers"

Set data diatur dalam 5 folder. Setiap folder berisi satu jenis bunga. Folder tersebut diberi nama bunga matahari, daisy, dandelion, tulip, dan mawar. Data di-host dalam bucket publik di Google Cloud Storage. Cuplikan:

gs://flowers-public/sunflowers/5139971615_434ff8ed8b_n.jpg
gs://flowers-public/daisy/8094774544_35465c1c64.jpg
gs://flowers-public/sunflowers/9309473873_9d62b9082e.jpg
gs://flowers-public/dandelion/19551343954_83bb52f310_m.jpg
gs://flowers-public/dandelion/14199664556_188b37e51e.jpg
gs://flowers-public/tulips/4290566894_c7f061583d_m.jpg
gs://flowers-public/roses/3065719996_c16ecd5551.jpg
gs://flowers-public/dandelion/8168031302_6e36f39d87.jpg
gs://flowers-public/sunflowers/9564240106_0577e919da_n.jpg
gs://flowers-public/daisy/14167543177_cd36b54ac6_n.jpg

Mengapa tf.data.Dataset?

Keras dan Tensorflow menerima Set Data di semua fungsi pelatihan dan evaluasinya. Setelah Anda memuat data di Set Data, API tersebut menawarkan semua fungsi umum yang berguna untuk data pelatihan jaringan neural:

dataset = ... # load something (see below)
dataset = dataset.shuffle(1000) # shuffle the dataset with a buffer of 1000
dataset = dataset.cache() # cache the dataset in RAM or on disk
dataset = dataset.repeat() # repeat the dataset indefinitely
dataset = dataset.batch(128) # batch data elements together in batches of 128
AUTOTUNE = tf.data.AUTOTUNE
dataset = dataset.prefetch(AUTOTUNE) # prefetch next batch(es) while training

Anda dapat menemukan tips performa dan praktik terbaik Set data di artikel ini. Dokumentasi referensi tersedia di sini.

Dasar-dasar tf.data.Dataset

Data biasanya terdiri dari beberapa file, di sini gambar. Anda dapat membuat set data nama file dengan memanggil:

filenames_dataset = tf.data.Dataset.list_files('gs://flowers-public/*/*.jpg')
# The parameter is a "glob" pattern that supports the * and ? wildcards.

Kemudian, Anda "memetakan" fungsi ke setiap nama file yang biasanya akan memuat dan mendekode file menjadi data sebenarnya dalam memori:

def decode_jpeg(filename):
  bits = tf.io.read_file(filename)
  image = tf.io.decode_jpeg(bits)
  return image

image_dataset = filenames_dataset.map(decode_jpeg)
# this is now a dataset of decoded images (uint8 RGB format)

Untuk melakukan iterasi pada Set data:

for data in my_dataset:
  print(data)

Set data tuple

Dalam pembelajaran dengan pengawasan, set data pelatihan biasanya terdiri dari pasangan data pelatihan dan jawaban yang benar. Untuk memungkinkan hal ini, fungsi decoding dapat menampilkan tuple. Anda kemudian akan memiliki {i>dataset <i}yang terdiri dari tupel dan tuple akan dikembalikan saat Anda melakukan iterasi. Nilai yang ditampilkan adalah tensor Tensorflow yang siap digunakan oleh model Anda. Anda dapat memanggil .numpy() untuk melihat nilai mentah:

def decode_jpeg_and_label(filename):
  bits = tf.read_file(filename)
  image = tf.io.decode_jpeg(bits)
  label = ... # extract flower name from folder name
  return image, label

image_dataset = filenames_dataset.map(decode_jpeg_and_label)
# this is now a dataset of (image, label) pairs 

for image, label in dataset:
  print(image.numpy().shape, label.numpy())

Kesimpulan:memuat gambar satu per satu sangatlah lambat.

Saat melakukan iterasi pada set data ini, Anda akan melihat bahwa Anda dapat memuat sekitar 1-2 gambar per detik. Terlalu lambat! Akselerator hardware yang akan kita gunakan untuk pelatihan dapat bertahan berkali-kali lipat kecepatan ini. Buka bagian berikutnya untuk melihat cara kami mencapainya.

Solusi

Berikut notebook solusinya. Anda dapat menggunakannya jika mengalami kesulitan.

c3df49e90e5a654f.png Fun with tf.data.Dataset (solution).ipynb

Yang telah kita bahas

  • 🤔 tf.data.Dataset.list_files
  • 🤔 tf.data.Dataset.map
  • 🤔 Set data tuple
  • 😀 melakukan iterasi melalui Set Data

Luangkan waktu sejenak untuk mengingat checklist ini.

5. Memuat data dengan cepat

Akselerator hardware Tensor Processing Unit (TPU) yang akan kita gunakan di lab ini sangat cepat. Tantangannya sering kali adalah memberinya data dengan cukup cepat agar tetap sibuk. Google Cloud Storage (GCS) mampu mempertahankan throughput yang sangat tinggi, tetapi seperti semua sistem penyimpanan cloud, memulai koneksi akan menimbulkan biaya jaringan bolak-balik. Oleh karena itu, menyimpan data kita sebagai ribuan file individual tidaklah ideal. Kita akan mengelompokkannya dalam jumlah file yang lebih kecil dan menggunakan kecanggihan tf.data.Dataset untuk membaca dari beberapa file secara paralel.

Pembacaan

Kode yang memuat file gambar, mengubah ukurannya ke ukuran umum, lalu menyimpannya di 16 file TFRecord ada di notebook berikut. Harap baca dengan cepat. Anda tidak perlu menjalankannya karena data berformat TFRecord yang benar akan disediakan untuk sisa codelab.

c3df49e90e5a654f.png Flower pictures to TFRecords.ipynb

Tata letak data yang ideal untuk throughput GCS yang optimal

Format file TFRecord

Format file pilihan Tensorflow untuk menyimpan data adalah format TFRecord berbasis protobuf. Format serialisasi lainnya juga akan berfungsi, tetapi Anda dapat memuat set data dari file TFRecord secara langsung dengan menulis:

filenames = tf.io.gfile.glob(FILENAME_PATTERN)
dataset = tf.data.TFRecordDataset(filenames)
dataset = dataset.map(...) # do the TFRecord decoding here - see below

Untuk performa yang optimal, sebaiknya gunakan kode yang lebih kompleks berikut untuk membaca dari beberapa file TFRecord sekaligus. Kode ini akan membaca dari file N secara paralel dan mengabaikan urutan data demi kecepatan pembacaan.

AUTOTUNE = tf.data.AUTOTUNE
ignore_order = tf.data.Options()
ignore_order.experimental_deterministic = False

filenames = tf.io.gfile.glob(FILENAME_PATTERN)
dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=AUTOTUNE)
dataset = dataset.with_options(ignore_order)
dataset = dataset.map(...) # do the TFRecord decoding here - see below

Tips praktis TFRecord

Tiga jenis data dapat disimpan dalam TFRecords: string byte (daftar byte), integer 64 bit, dan float 32 bit. Elemen data selalu disimpan sebagai daftar, satu elemen data akan menjadi daftar berukuran 1. Anda dapat menggunakan fungsi bantuan berikut untuk menyimpan data ke dalam TFRecords.

menulis string byte

# warning, the input is a list of byte strings, which are themselves lists of bytes
def _bytestring_feature(list_of_bytestrings):
  return tf.train.Feature(bytes_list=tf.train.BytesList(value=list_of_bytestrings))

menulis bilangan bulat

def _int_feature(list_of_ints): # int64
  return tf.train.Feature(int64_list=tf.train.Int64List(value=list_of_ints))

menulis float

def _float_feature(list_of_floats): # float32
  return tf.train.Feature(float_list=tf.train.FloatList(value=list_of_floats))

menulis TFRecord, menggunakan helper di atas

# input data in my_img_bytes, my_class, my_height, my_width, my_floats
with tf.python_io.TFRecordWriter(filename) as out_file:
  feature = {
    "image": _bytestring_feature([my_img_bytes]), # one image in the list
    "class": _int_feature([my_class]),            # one class in the list
    "size": _int_feature([my_height, my_width]),  # fixed length (2) list of ints
    "float_data": _float_feature(my_floats)       # variable length  list of floats
  }
  tf_record = tf.train.Example(features=tf.train.Features(feature=feature))
  out_file.write(tf_record.SerializeToString())

Untuk membaca data dari TFRecords, Anda harus mendeklarasikan tata letak kumpulan data yang telah disimpan terlebih dahulu. Dalam deklarasi, Anda dapat mengakses kolom bernama sebagai daftar panjang tetap atau daftar panjang variabel:

membaca dari TFRecords

def read_tfrecord(data):
  features = {
    # tf.string = byte string (not text string)
    "image": tf.io.FixedLenFeature([], tf.string), # shape [] means scalar, here, a single byte string
    "class": tf.io.FixedLenFeature([], tf.int64),  # shape [] means scalar, i.e. a single item
    "size": tf.io.FixedLenFeature([2], tf.int64),  # two integers
    "float_data": tf.io.VarLenFeature(tf.float32)  # a variable number of floats
  }

  # decode the TFRecord
  tf_record = tf.io.parse_single_example(data, features)

  # FixedLenFeature fields are now ready to use
  sz = tf_record['size']

  # Typical code for decoding compressed images
  image = tf.io.decode_jpeg(tf_record['image'], channels=3)

  # VarLenFeature fields require additional sparse.to_dense decoding
  float_data = tf.sparse.to_dense(tf_record['float_data'])

  return image, sz, float_data

# decoding a tf.data.TFRecordDataset
dataset = dataset.map(read_tfrecord)
# now a dataset of triplets (image, sz, float_data)

Cuplikan kode yang berguna:

membaca elemen data tunggal

tf.io.FixedLenFeature([], tf.string)   # for one byte string
tf.io.FixedLenFeature([], tf.int64)    # for one int
tf.io.FixedLenFeature([], tf.float32)  # for one float

membaca daftar elemen berukuran tetap

tf.io.FixedLenFeature([N], tf.string)   # list of N byte strings
tf.io.FixedLenFeature([N], tf.int64)    # list of N ints
tf.io.FixedLenFeature([N], tf.float32)  # list of N floats

membaca jumlah item data yang bervariasi

tf.io.VarLenFeature(tf.string)   # list of byte strings
tf.io.VarLenFeature(tf.int64)    # list of ints
tf.io.VarLenFeature(tf.float32)  # list of floats

VarLenFeature menampilkan vektor jarang dan langkah tambahan diperlukan setelah mendekode TFRecord:

dense_data = tf.sparse.to_dense(tf_record['my_var_len_feature'])

Anda juga dapat memiliki kolom opsional di TFRecords. Jika Anda menentukan nilai default saat membaca kolom, nilai default akan ditampilkan, bukan error jika kolom tidak ada.

tf.io.FixedLenFeature([], tf.int64, default_value=0) # this field is optional

Yang telah kita bahas

  • 🤔 sharding file data untuk akses cepat dari GCS
  • Mengautentikasi cara menulis TFRecords. (Anda lupa sintaksnya? Tidak apa-apa, bookmark halaman ini sebagai catatan singkat)
  • 🤔 memuat Set Data dari TFRecords menggunakan TFRecordDataset

Luangkan waktu sejenak untuk mengingat checklist ini.

6. [INFO] Dasar-dasar pengklasifikasi jaringan saraf

Singkatnya

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

Untuk model yang dibangun sebagai urutan lapisan Keras menawarkan Sequential API. Misalnya, pengklasifikasi gambar yang menggunakan tiga lapisan rapat 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 rapat

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

c21bae6dade487bc.png

Anda bisa memasukkan gambar ke dalam jaringan seperti itu dengan meratakan nilai RGB dari semua pikselnya menjadi vektor yang panjang dan menggunakannya sebagai input. Ini bukanlah teknik terbaik untuk pengenalan citra, tetapi kami akan meningkatkannya nanti.

Neuron, aktivasi, RELU

"Neuron" menghitung jumlah berbobot dari semua inputnya, menambahkan nilai yang disebut "bias", dan memasukkan hasilnya melalui "fungsi aktivasi". Bobot dan bias pada awalnya tidak diketahui. Model tersebut 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 Unit Linear Terarah. 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 kami mengklasifikasikan bunga menjadi 5 kategori (mawar, tulip, dandelion, daisy, bunga matahari). Neuron di lapisan perantara diaktifkan menggunakan fungsi aktivasi RELU klasik. Pada lapisan terakhir, kita ingin menghitung angka antara 0 dan 1 yang mewakili probabilitas bunga ini adalah mawar, tulip, dan seterusnya. Untuk itu, kita akan menggunakan fungsi aktivasi yang disebut "softmax".

Penerapan softmax pada vektor dilakukan dengan mengambil eksponensial dari setiap elemen dan kemudian menormalisasi vektor tersebut, biasanya menggunakan norma L1 (jumlah nilai absolut) sehingga nilainya bertambah hingga 1 dan dapat diinterpretasikan sebagai probabilitas.

ef0d98c0952c262d.png d51252f75894479e.gif

Kerugian entropi silang

Sekarang setelah jaringan neural kita menghasilkan prediksi dari gambar input, kita perlu mengukur seberapa bagus prediksinya, yaitu jarak antara apa yang ditunjukkan jaringan kepada kita dan jawaban yang benar, yang sering disebut "label". Ingatlah bahwa kita memiliki label yang benar untuk semua gambar dalam {i>dataset<i}.

Semua jarak dapat digunakan, tetapi untuk masalah klasifikasi, yang disebut "jarak entropi silang" adalah yang paling efektif. Kita akan menyebutnya error atau fungsi "kerugian":

7bdf8753d20617fb.pngS

Penurunan gradien

"Melatih" jaringan neural sebenarnya berarti menggunakan gambar dan label pelatihan untuk menyesuaikan bobot dan bias sehingga dapat meminimalkan fungsi kerugian entropi silang. Berikut cara kerjanya.

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

Jika kita menghitung turunan parsial dari entropi silang secara relatif terhadap semua bobot dan semua bias, kita memperoleh "gradien", yang dihitung untuk gambar, label, dan nilai sekarang dari bobot dan bias. Ingatlah bahwa kita dapat memiliki jutaan bobot dan bias sehingga menghitung gradien terdengar seperti pekerjaan yang berat. Untungnya, Tensorflow melakukannya untuk kita. Properti matematika gradien adalah bahwa gradien mengarah "ke atas". Karena kita ingin menuju tempat entropi silang rendah, kita akan menuju ke arah yang berlawanan. Kita memperbarui bobot dan bias dengan sebagian gradien. Kemudian, kita melakukan hal yang sama berulang kali menggunakan batch gambar dan label pelatihan berikutnya, dalam loop pelatihan. Semoga, hal ini akan konvergen ke tempat cross-entropy minimal meskipun tidak ada yang menjamin bahwa minimum ini unik.

descent2.png

Pengelompokan mini dan momentum

Anda dapat menghitung gradien hanya pada satu contoh gambar dan segera memperbarui bobot dan bias, tetapi melakukannya pada batch, misalnya, 128 gambar akan memberikan gradien yang lebih baik mewakili batasan yang diberlakukan oleh berbagai contoh gambar sehingga cenderung akan berkonvergensi ke solusi lebih cepat. 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.

Namun, 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 berupa nol pada minimum atau maksimum. Dengan vektor gradien yang memiliki jutaan elemen, jika semuanya nol, probabilitas bahwa setiap nol sesuai dengan nilai 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 sana.

52e824fe4716c4a0.png

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

Solusinya adalah menambahkan beberapa momentum pada algoritme pengoptimalan sehingga algoritme tersebut dapat berlayar melewati titik pelana tanpa berhenti.

Glosarium

batch atau mini-batch: pelatihan selalu dilakukan pada batch data dan label pelatihan. Tindakan ini akan membantu algoritma konvergensi. Dimensi "batch" biasanya merupakan dimensi pertama dari 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 yang setiap neuronnya terhubung ke semua neuron di lapisan sebelumnya.

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

label: nama lain untuk "class" atau jawaban yang benar dalam masalah klasifikasi berpengawasan

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

logits: output dari lapisan neuron sebelum fungsi aktivasi diterapkan disebut "logits". Istilah ini berasal dari "fungsi logistik" alias "fungsi sigmoid" yang sebelumnya merupakan fungsi aktivasi yang paling populer. "Output neuron sebelum fungsi logistik" disingkat menjadi "logits".

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

neuron: menghitung jumlah input tertimbang, menambahkan bias, dan memberikan hasilnya melalui fungsi aktivasi.

Encoding one-hot: class 3 dari 5 dienkode sebagai vektor 5 elemen, semua nol kecuali elemen ke-3 yang bernilai 1.

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

sigmoid: fungsi aktivasi lain yang sebelumnya populer dan masih berguna dalam kasus tertentu.

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

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

7. Pemelajaran Transfer

Untuk masalah klasifikasi gambar, lapisan padat mungkin tidak cukup. Kita harus mempelajari lapisan konvolusi dan berbagai cara untuk mengaturnya.

Tapi kita juga bisa mengambil jalan pintas! Ada jaringan neural konvolusional terlatih yang bisa didownload. Anda dapat memotong lapisan terakhirnya, kepala klasifikasi softmax, dan menggantinya dengan milik Anda. Semua bobot dan bias yang dilatih tetap seperti itu, Anda hanya melatih ulang lapisan softmax yang Anda tambahkan. Teknik ini disebut pemelajaran transfer dan luar biasa, teknik ini bekerja selama {i>dataset<i} tempat jaringan neural yang dilatih sebelumnya "cukup dekat" dengan milik Anda.

Praktis

Buka notebook berikut, jalankan sel (Shift-ENTER), dan ikuti petunjuk di mana pun Anda melihat label &quot;KERJA DIPERLUKAN&quot;.

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

Informasi tambahan

Dengan pemelajaran transfer, Anda mendapatkan manfaat dari arsitektur jaringan neural konvolusi lanjutan yang dikembangkan oleh peneliti teratas dan dari pra-pelatihan pada set data gambar yang sangat besar. Dalam kasus ini, kita akan melakukan transfer learning dari jaringan yang dilatih di ImageNet, database gambar yang berisi banyak tanaman dan pemandangan luar ruangan, yang cukup mirip dengan bunga.

b8fc1efd2001f072.png

Ilustrasi: menggunakan jaringan saraf konvolusi yang kompleks, yang telah dilatih, sebagai kotak hitam, hanya melatih ulang head klasifikasi. Inilah pemelajaran transfer. Kita akan melihat cara kerja pengaturan lapisan konvolusi yang rumit ini nanti. Untuk saat ini, masalahnya ada di tangan orang lain.

Transfer pembelajaran di Keras

Di Keras, Anda dapat membuat instance model terlatih dari koleksi tf.keras.applications.*. MobileNet V2 misalnya adalah arsitektur konvolusional yang sangat baik dengan ukuran yang tetap wajar. Dengan memilih include_top=False, Anda mendapatkan model terlatih tanpa lapisan softmax akhirnya sehingga Anda dapat menambahkan model Anda sendiri:

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

model = tf.keras.Sequential([
    pretrained_model,
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(5, activation='softmax')
])

Perhatikan juga setelan pretrained_model.trainable = False. Fungsi ini membekukan bobot dan bias model terlatih sehingga Anda hanya melatih lapisan softmax. Hal ini biasanya melibatkan bobot yang relatif sedikit dan dapat dilakukan dengan cepat serta tanpa memerlukan set data yang sangat besar. Namun, jika Anda memiliki banyak data, transfer learning dapat berfungsi lebih baik dengan pretrained_model.trainable = True. Bobot yang telah dilatih sebelumnya kemudian memberikan nilai awal yang sangat baik dan masih dapat disesuaikan oleh pelatihan agar lebih sesuai dengan masalah Anda.

Terakhir, perhatikan lapisan Flatten() yang disisipkan sebelum lapisan softmax padat Anda. Lapisan padat bekerja pada vektor data datar, tetapi kita tidak tahu apakah itu yang ditampilkan oleh model terlatih. Itulah sebabnya kita perlu meratakan. Di bab berikutnya, saat mempelajari arsitektur convolutional, kita akan menjelaskan format data yang ditampilkan oleh lapisan convolutional.

Akurasi Anda akan mendekati 75% dengan pendekatan ini.

Solusi

Berikut notebook solusinya. Anda dapat menggunakannya jika mengalami kesulitan.

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

Yang telah kita bahas

  • 🤔 Cara menulis pengklasifikasi di Keras
  • 🤓 dikonfigurasikan dengan lapisan terakhir softmax, dan kerugian entropi silang
  • 📈 Pemelajaran transfer
  • 🤔 Melatih model pertama Anda
  • 🧐 Memantau kerugian dan akurasinya selama pelatihan

Luangkan waktu sejenak untuk membaca {i>checklist<i} ini di kepala Anda.

8. [INFO] Jaringan neural konvolusi

Ringkasan

Jika semua istilah yang dicetak tebal di paragraf berikutnya sudah diketahui, Anda dapat melanjutkan ke latihan berikutnya. Jika Anda baru mulai mempelajari jaringan neural konvolusional, harap baca terus.

convolutional.gif

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

Berikut adalah 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

Jaringan neural konvolusi 101

Dalam lapisan jaringan konvolusional, satu "neuron" melakukan penjumlahan piksel tertimbang tepat di atasnya, hanya melintasi sebagian kecil gambar. Fungsi ini menambahkan bias dan memasukkan jumlah tersebut melalui fungsi aktivasi, sama seperti yang dilakukan neuron dalam lapisan padat biasa. Operasi ini kemudian diulang di seluruh gambar menggunakan bobot yang sama. Ingatlah bahwa di lapisan padat, setiap neuron memiliki bobotnya sendiri. Di sini, satu "patch" bobot bergeser di seluruh gambar dalam kedua arah ("konvolusi"). Output memiliki nilai sebanyak piksel dalam gambar (tetapi beberapa padding diperlukan di bagian tepinya). Ini adalah operasi penyaringan, dengan menggunakan filter dengan bobot 4 x 4 x 3=48.

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. Sebut saja ini sebagai "saluran" {i>output<i} dengan analogi dengan saluran R,G,B di gambar input.

Screenshot 29-07-2016 at 16.02.37.png

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

d1b557707bcd1cb9.png

Ilustrasi: jaringan saraf konvolusi mengubah "kubus" data menjadi "kubus" data lainnya.

Konvolusi dengan stride, max pooling

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

  • Langkah konvolusi: filter geser seperti di atas tetapi dengan langkah >1
  • Pengumpulan maksimum: 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 melangkah atau penggabungan maksimum (maksimum pada jendela 2x2 yang bergeser dengan langkah 2) adalah cara mengecilkan kubus data dalam dimensi horizontal.

Pengklasifikasi lokal

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

4a61aaffb6cba3d1.png

Ilustrasi: pengklasifikasi gambar menggunakan lapisan konvolusi dan softmax. Filter ini menggunakan filter 3x3 dan 1x1. Lapisan maxpool mengambil jumlah maksimal grup titik data 2x2. Head klasifikasi diimplementasikan dengan lapisan padat dengan aktivasi softmax.

Di Keras

Stack convolutional 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'])

9. Convnet kustom Anda

Praktis

Mari kita buat dan latih jaringan neural konvolusional dari awal. Penggunaan TPU akan memungkinkan kita melakukan iterasi dengan sangat cepat. Buka notebook berikut, jalankan sel (Shift-ENTER), dan ikuti petunjuk di mana pun Anda melihat label "KERJA DIPERLUKAN".

c3df49e90e5a654f.png Keras_Flowers_TPU (playground).ipynb

Sasarannya adalah mengalahkan akurasi model pemelajaran transfer sebesar 75%. Model tersebut memiliki keunggulan, karena telah dilatih sebelumnya pada set data yang berisi jutaan gambar, sedangkan kita hanya memiliki 3.670 gambar di sini. Bisakah Anda setidaknya mencocokkannya?

Informasi tambahan

Berapa banyak lapisan, seberapa besar?

Memilih ukuran lapisan lebih merupakan seni daripada sains. Anda harus menemukan keseimbangan yang tepat antara memiliki terlalu sedikit dan terlalu banyak parameter (bobot dan bias). Dengan bobot yang terlalu sedikit, jaringan neural tidak dapat merepresentasikan kompleksitas bentuk bunga. Dengan terlalu banyak, pemodelan bisa menjadi rentan terhadap "overfitting", yaitu mengkhususkan diri dalam gambar pelatihan dan tidak dapat melakukan generalisasi. Dengan banyak parameter, model juga akan lambat dilatih. Di Keras, fungsi model.summary() menampilkan struktur dan jumlah parameter model Anda:

Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 192, 192, 16)      448       
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 192, 192, 30)      4350      
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 96, 96, 30)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 96, 96, 60)        16260     
_________________________________________________________________
 ... 
_________________________________________________________________
global_average_pooling2d (Gl (None, 130)               0         
_________________________________________________________________
dense (Dense)                (None, 90)                11790     
_________________________________________________________________
dense_1 (Dense)              (None, 5)                 455       
=================================================================
Total params: 300,033
Trainable params: 300,033
Non-trainable params: 0
_________________________________________________________________

Beberapa tips:

  • Memiliki beberapa lapisan adalah hal yang membuat jaringan neural "dalam" efektif. Untuk masalah pengenalan bunga sederhana ini, 5 hingga 10 lapisan adalah hal yang masuk akal.
  • Gunakan filter kecil. Biasanya, filter 3x3 bagus di mana saja.
  • Filter 1x1 juga dapat digunakan dan murah. Mereka tidak benar-benar "memfilter" apa pun kecuali menghitung kombinasi linier dari saluran. Ganti dengan filter yang sebenarnya. (Selengkapnya tentang "konvolusi 1x1" di bagian berikutnya.)
  • Untuk masalah klasifikasi seperti ini, lakukan pengurangan sampel secara rutin dengan lapisan penggabungan maksimum (atau konvolusi dengan langkah >1). Anda tidak peduli di mana bunganya berada, hanya saja bunga itu adalah mawar atau dandelion sehingga kehilangan informasi x dan y tidak penting dan memfilter area yang lebih kecil menjadi lebih murah.
  • Jumlah filter biasanya menjadi serupa dengan jumlah class di akhir jaringan (mengapa? lihat trik "global average pooling" di bawah). Jika Anda mengklasifikasikan ke dalam ratusan class, tingkatkan jumlah filter secara bertahap di lapisan berturut-turut. Untuk set data bunga dengan 5 kelas, pemfilteran hanya dengan 5 filter tidak akan cukup. Anda dapat menggunakan jumlah filter yang sama di sebagian besar lapisan, misalnya 32, lalu menguranginya menjelang akhir.
  • Lapisan padat akhir mahal. Lapisan ini dapat memiliki lebih banyak bobot daripada gabungan semua lapisan konvolusional. Misalnya, meskipun dengan output yang sangat wajar dari kubus data terakhir yang terdiri dari 24x24x10 titik data, lapisan padat 100 neuron akan memerlukan 24x24x10x100=576.000 bobot !!! Cobalah untuk mempertimbangkan, atau coba penggabungan rata-rata global (lihat di bawah).

Pemrosesan rata-rata global

Alih-alih menggunakan lapisan padat yang mahal di akhir jaringan neural konvolusional, Anda dapat membagi data yang masuk "kubus" menjadi sebanyak mungkin bagian yang Anda miliki class, menghitung nilai rata-ratanya, dan memasukkan nilai tersebut melalui fungsi aktivasi softmax. Cara pembuatan head klasifikasi ini memerlukan bobot 0. Di Keras, sintaksisnya adalah tf.keras.layers.GlobalAveragePooling2D().

93240029f59df7c2.png

Solusi

Berikut notebook solusinya. Anda dapat menggunakannya jika mengalami kesulitan.

c3df49e90e5a654f.png Keras_Flowers_TPU (solution).ipynb

Yang telah kita bahas

  • 🤔 Bermain dengan lapisan konvolusi
  • 🤓 Bereksperimen dengan pengumpulan maksimal, langkah, penggabungan rata-rata global, ...
  • 😀 melakukan iterasi pada model dunia nyata dengan cepat, di TPU

Luangkan waktu sejenak untuk mengingat checklist ini.

10. [INFO] Arsitektur konvolusi modern

Ringkasan singkat

7968830b57b708c0.png

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

Di Keras, untuk membuat model tempat aliran data 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.pngS

Trik murah lainnya

Filter 3x3 kecil

40a7b15fb7dbe75c.pngS

Dalam ilustrasi ini, Anda melihat hasil dari dua filter 3x3 berturut-turut. Coba lacak kembali titik data mana yang berkontribusi pada hasilnya: dua filter 3x3 berturut-turut ini menghitung beberapa kombinasi dari region 5x5. Kombinasi ini tidak sama persis dengan yang akan dihitung filter 5x5, tetapi layak 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 sangat berguna. Namun, dalam jaringan saraf konvolusi, ingatlah bahwa filter diterapkan ke kubus data, bukan hanya gambar 2D. Oleh karena itu, filter "1x1" menghitung jumlah tertimbang kolom data 1x1 (lihat ilustrasi) dan saat Anda menggesernya di seluruh data, Anda akan mendapatkan kombinasi linier dari saluran input. Hal ini sebenarnya berguna. Jika Anda menganggap saluran sebagai hasil dari operasi pemfilteran individual, misalnya filter untuk "telinga runcing", yang lain untuk "kumis", dan yang ketiga untuk "mata bercak", maka lapisan konvolusional "1x1" akan menghitung beberapa kemungkinan kombinasi linier dari fitur-fitur ini, yang mungkin berguna saat mencari "kucing". Selain itu, lapisan 1x1 menggunakan bobot yang lebih sedikit.

11. Squeezenet

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

1730ac375379269b.png

Ilustrasi: arsitektur squeezenet berdasarkan "modul kebakaran". Mereka mengganti lapisan 1x1 yang "memeras" data yang masuk dalam dimensi vertikal diikuti oleh dua lapisan konvolusional 1x1 dan 3x3 paralel yang "memperluas" kedalaman data lagi.

Praktis

Lanjutkan di notebook sebelumnya dan buat jaringan saraf konvolusi yang terinspirasi dari squeezenet. Anda harus mengubah kode model ke "gaya fungsional" Keras.

c3df49e90e5a654f.png Keras_Flowers_TPU (playground).ipynb

Info tambahan

Akan sangat berguna untuk latihan ini untuk menentukan fungsi bantuan di 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)

Target kali ini adalah mencapai akurasi 80%.

Yang perlu 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 di jaringan dan juga dengan 1, 2, atau 3 modul fire berturut-turut di antara lapisan max pooling.

Dalam modul kebakaran, parameter "squeeze" biasanya harus lebih kecil dari parameter "expand". Parameter ini sebenarnya adalah jumlah filter. Biasanya, jumlah ini berkisar antara 8 hingga 196. Anda dapat bereksperimen dengan arsitektur yang jumlah filternya meningkat secara bertahap melalui jaringan, atau arsitektur sederhana yang semua modul kebakarannya 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 tahap ini, Anda mungkin melihat bahwa eksperimen Anda tidak berjalan dengan baik dan tujuan akurasi 80% tampaknya tidak mungkin tercapai. Saatnya mencoba beberapa trik murah lainnya.

Normalisasi Batch

Norma batch akan membantu mengatasi masalah konvergensi yang Anda alami. Akan ada penjelasan mendetail tentang teknik ini di workshop berikutnya. Untuk saat ini, gunakan baris ini sebagai helper "ajaib" kotak hitam dengan menambahkan baris ini setelah setiap lapisan konvolusional dalam 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 diturunkan dari nilai default 0,99 menjadi 0,9 karena dataset kita kecil. Untuk saat ini, abaikan detail ini.

Pengayaan data

Anda akan mendapatkan beberapa poin persentase lainnya dengan menambahkan data dengan transformasi mudah seperti perubahan saturasi yang dibalik kiri-kanan:

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 &quot;set data pelatihan dan validasi&quot;, fungsi &quot;get_batched_dataset&quot;):

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 ditingkatkan. Tidak masuk akal untuk menambah set data validasi.

Akurasi 80% dalam 35 epoch kini akan dapat dicapai.

Solusi

Berikut notebook solusinya. Anda dapat menggunakannya jika mengalami kesulitan.

c3df49e90e5a654f.png Keras_Flowers_TPU_squeezenet.ipynb

Yang telah kita bahas

  • 🤔 Model &quot;gaya fungsional&quot; Keras
  • 🤓 Arsitektur Squeezenet
  • 🤓 Augmentasi data dengan tf.data.datset

Luangkan waktu sejenak untuk membaca {i>checklist<i} ini di kepala Anda.

12. Xception yang disesuaikan

Konvolusi yang dapat dipisahkan

Cara lain untuk menerapkan lapisan konvolusi telah menjadi populer baru-baru ini: konvolusi yang dapat dipisahkan kedalamannya. Saya tahu, istilahnya panjang, tetapi konsepnya cukup sederhana. Class ini diimplementasikan di Tensorflow dan Keras sebagai tf.keras.layers.SeparableConv2D.

Convolution yang dapat dipisahkan juga menjalankan filter pada gambar, tetapi menggunakan set bobot yang berbeda untuk setiap saluran gambar input. Langkah ini diikuti dengan &quot;konvolusi 1x1&quot;, serangkaian perkalian titik yang menghasilkan jumlah berbobot dari saluran yang difilter. Dengan bobot baru setiap saat, sebanyak mungkin rekombinasi berbobot saluran dihitung sesuai kebutuhan.

615720b803bf8dda.gif

Ilustrasi: konvolusi yang dapat dipisahkan. Fase 1: konvolusi dengan filter terpisah untuk setiap saluran. Fase 2: rekombinasi linear saluran. Diulangi dengan satu set 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 terpisah digunakan dalam arsitektur jaringan konvolusional terbaru: MobileNetV2, Xception, EfficientNet. Ngomong-ngomong, MobileNetV2 adalah alat yang Anda gunakan untuk pemelajaran transfer sebelumnya.

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

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

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

Hal ini dibiarkan sebagai latihan bagi pembaca untuk menghitung jumlah perkalian yang diperlukan untuk menerapkan setiap gaya skala lapisan konvolusi dengan cara yang serupa. Konvolusi yang dapat dipisahkan lebih kecil dan jauh lebih efektif secara komputasi.

Praktis

Mulai ulang dari notebook playground "pembelajaran transfer", tetapi kali ini pilih Xception sebagai model terlatih. Xception hanya menggunakan konvolusi yang dapat dipisahkan. Biarkan semua bobot dapat dilatih. Kita akan menyesuaikan bobot terlatih pada data kita, bukan menggunakan lapisan terlatih seperti itu.

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

Sasaran: akurasi > 95% (Tidak, serius, itu mungkin!)

Latihan ini adalah latihan terakhir, sehingga memerlukan lebih banyak kode dan pekerjaan data science.

Info tambahan tentang penyesuaian

Xception tersedia dalam model standar terlatih di tf.keras.application.* Jangan lupa untuk membiarkan 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 peningkatan. Seperti ini:

9b1af213b2b36d47.png

Memulai dengan kecepatan pembelajaran standar akan mengganggu bobot model yang telah dilatih sebelumnya. Mulai secara bertahap mempertahankannya hingga model telah terkunci pada data Anda sehingga dapat mengubahnya dengan cara yang masuk akal. Setelah ramp, Anda dapat melanjutkan dengan kecepatan pemelajaran yang konstan atau menurun secara eksponensial.

Di Keras, kecepatan pemelajaran ditentukan melalui callback yang memungkinkan Anda menghitung kecepatan pemelajaran yang sesuai untuk setiap epoch. Keras akan meneruskan kecepatan belajar 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 notebook solusinya. Anda dapat menggunakannya jika mengalami kesulitan.

c3df49e90e5a654f.png 07_Keras_Flowers_TPU_xception_fine_tuned_best.ipynb

Yang telah kita bahas

  • 🤔 Konvolusi yang dapat dipisahkan kedalaman
  • 🤓 Jadwal kecepatan pembelajaran
  • 📈 Meningkatkan kualitas model terlatih.

Luangkan waktu sejenak untuk membaca {i>checklist<i} ini di kepala Anda.

13. Selamat!

Anda telah membangun jaringan neural konvolusional modern pertama Anda dan melatihnya hingga akurasi 90% +, sehingga melakukan iterasi pada pelatihan berturut-turut hanya dalam hitungan menit berkat TPU.

TPU dalam praktik

TPU dan GPU tersedia di Vertex AI Google Cloud:

Terakhir, kami senang menerima masukan. Beri tahu kami jika Anda melihat ada yang tidak beres di lab ini atau jika menurut Anda ada yang perlu ditingkatkan. Masukan dapat diberikan melalui masalah GitHub [link masukan].

HR.png

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