1. Ringkasan
Tutorial ini telah diperbarui untuk TensorFlow 2.2.
Dalam codelab ini, Anda akan mempelajari cara membangun dan melatih jaringan neural yang mengenali digit tulisan tangan. Dalam prosesnya, saat meningkatkan neural network untuk mencapai akurasi 99%, Anda juga akan menemukan alat perdagangan yang digunakan para profesional deep learning untuk melatih model mereka secara efisien.
Codelab ini menggunakan set data MNIST, yaitu kumpulan 60.000 digit berlabel yang membuat generasi PhD tetap sibuk selama hampir dua dekade. Anda akan menyelesaikan masalah dengan kurang dari 100 baris kode Python / TensorFlow.
Yang akan Anda pelajari
- Apa itu jaringan neural dan cara melatihnya
- Cara membangun jaringan neural 1 lapis dasar menggunakan tf.keras
- Cara menambahkan lebih banyak lapisan
- Cara menyiapkan jadwal kecepatan pembelajaran
- Cara membangun jaringan neural konvolusional
- Cara menggunakan teknik regularisasi: dropout, normalisasi batch
- Apa itu overfitting
Yang Anda butuhkan
Cukup dengan browser. Workshop ini dapat dijalankan sepenuhnya dengan Google Colaboratory.
Masukan
Beri tahu kami jika Anda melihat ada yang tidak beres di lab ini atau menurut Anda harus diperbaiki. Kami menangani masukan melalui masalah GitHub [link masukan].
2. Memulai cepat Google Colaboratory
Lab ini menggunakan Google Colaboratory dan tidak memerlukan penyiapan dari Anda. Anda dapat menjalankannya dari Chromebook. Buka file di bawah, lalu jalankan sel untuk memahami notebook Colab.
Petunjuk tambahan di bawah:
Memilih backend GPU
Di menu Colab, pilih Runtime > Ubah jenis runtime, lalu pilih GPU. Koneksi ke runtime akan terjadi secara otomatis pada eksekusi pertama, atau Anda dapat menggunakan tombol "Hubungkan" di pojok kanan atas.
Eksekusi notebook
Jalankan sel satu per satu dengan mengklik sel dan menggunakan Shift-ENTER. Anda juga dapat menjalankan seluruh notebook dengan Runtime > Jalankan semua
Daftar isi
Semua notebook memiliki daftar isi. Anda dapat membukanya menggunakan panah hitam di sebelah kiri.
Sel tersembunyi
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 harus menjalankan sel-sel ini agar fungsi di dalamnya dapat ditentukan.
3. Melatih jaringan neural
Pertama-tama, kita akan melihat pelatihan jaringan neural. Buka notebook di bawah dan jalankan melalui semua sel. Jangan memperhatikan kodenya karena kami akan mulai menjelaskannya nanti.
Saat Anda menjalankan {i>notebook<i}, fokuslah pada visualisasi. Lihat penjelasan di bawah.
Data pelatihan
Kita memiliki sebuah {i>dataset <i}yang terdiri dari angka-angka tulisan tangan yang telah diberi label sehingga kita tahu apa yang diwakili oleh setiap gambar, yaitu angka antara 0 dan 9. Di notebook tersebut, Anda akan melihat kutipan:
Jaringan neural yang akan kita bangun mengklasifikasikan digit tulisan tangan dalam 10 kelasnya (0, .., 9). Klasifikasi ini didasarkan pada parameter internal yang harus memiliki nilai yang benar agar klasifikasi berfungsi dengan baik. "Nilai yang benar" ini dipelajari melalui proses pelatihan yang membutuhkan "set data berlabel" dengan gambar dan jawaban benar yang terkait.
Bagaimana cara kita mengetahui apakah jaringan neural yang terlatih memiliki performa yang baik atau tidak? Menggunakan set data pelatihan untuk menguji jaringan adalah tindakan curang. Ia telah melihat set data tersebut beberapa kali selama pelatihan dan pastinya sangat berperforma baik. Kita memerlukan {i>dataset<i} lain yang berlabel, yang tidak pernah terlihat selama pelatihan, untuk mengevaluasi "dunia nyata" performa jaringan. Set data ini disebut "set data validasi"
Pelatihan
Seiring dengan berlangsungnya pelatihan, satu batch data pelatihan pada satu waktu, parameter model internal akan diperbarui dan model menjadi semakin baik dalam mengenali digit yang ditulis tangan. Anda dapat melihatnya di grafik pelatihan:
Di sebelah kanan, "akurasi" adalah persentase dari digit yang dapat dikenali dengan benar. Nilainya akan terus meningkat seiring dengan progres pelatihan, dan ini bagus.
Di sebelah kiri, kita bisa melihat "kerugian". Untuk menjalankan pelatihan, kita akan mendefinisikan "kerugian" , yang mewakili seberapa buruk sistem mengenali digit, dan mencoba untuk meminimalkannya. Yang Anda lihat di sini adalah bahwa kerugian akan menurun pada data pelatihan dan validasi saat pelatihan berlangsung: itu bagus. Artinya, jaringan neural sedang belajar.
Sumbu X merepresentasikan jumlah "epoch" atau iterasi di seluruh {i>dataset<i}.
Prediksi
Ketika model dilatih, kita dapat menggunakannya untuk mengenali digit tulisan tangan. Visualisasi berikutnya menunjukkan seberapa baik performanya pada beberapa digit yang dirender dari font lokal (baris pertama) dan kemudian pada 10.000 digit dari {i>dataset<i} validasi. Class yang diprediksi akan muncul di bawah setiap digit, dan berwarna merah jika salah.
Seperti yang dapat Anda lihat, model awal ini kurang tepat tetapi masih mengenali beberapa digit dengan benar. Akurasi validasi akhirnya adalah sekitar 90% yang tidak terlalu buruk untuk model sederhana yang kita mulai, tetapi itu masih berarti bahwa model itu melewatkan 1000 digit validasi dari 10.000. Itu jauh lebih banyak yang bisa ditampilkan, itulah sebabnya sepertinya semua jawaban salah (merah).
Tensor
Data disimpan dalam matriks. Suatu gambar hitam putih berukuran 28x28 piksel sesuai dengan matriks dua dimensi berukuran 28x28. Tetapi untuk gambar berwarna, kita membutuhkan lebih banyak dimensi. Ada 3 nilai warna per piksel (Merah, Hijau, Biru), sehingga diperlukan tabel tiga dimensi dengan dimensi [28, 28, 3]. Dan untuk menyimpan kumpulan 128 gambar berwarna, diperlukan tabel empat dimensi dengan dimensi [128, 28, 28, 3].
Tabel multi-dimensi ini disebut "tensor" dan daftar dimensinya adalah "bentuk".
4. [INFO]: Dasar-dasar jaringan neural
Ringkasan singkat
Jika semua istilah yang dicetak tebal di paragraf berikutnya sudah diketahui, 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 padat dapat ditulis dalam Keras sebagai:
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=[28, 28, 1]),
tf.keras.layers.Dense(200, activation="relu"),
tf.keras.layers.Dense(60, activation="relu"),
tf.keras.layers.Dense(10, activation='softmax') # classifying into 10 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, ... )
Satu lapisan padat
Digit tulisan tangan dalam set data MNIST adalah gambar hitam putih berukuran 28x28 piksel. Pendekatan paling sederhana untuk mengklasifikasikannya adalah dengan menggunakan 28x28=784 piksel sebagai input untuk jaringan neural 1-lapisan.
Setiap "neuron" dalam jaringan neural melakukan jumlah tertimbang dari semua inputnya, menambahkan konstanta yang disebut "bias" lalu memberikan hasilnya melalui beberapa "fungsi aktivasi" non-linear. "weights" dan "biases" adalah parameter yang akan ditentukan melalui pelatihan. Sebelumnya, mereka diinisialisasi dengan nilai acak.
Gambar di atas mewakili jaringan neural 1 lapis dengan 10 neuron output karena kita ingin mengklasifikasikan digit ke dalam 10 kelas (0 hingga 9).
Dengan perkalian matriks
Berikut ini adalah bagaimana lapisan jaringan neural, yang memproses kumpulan gambar, dapat direpresentasikan dengan perkalian matriks:
Dengan menggunakan kolom pertama bobot dalam matriks bobot W, kita menghitung jumlah terbobot dari semua piksel dari gambar pertama. Jumlah ini sesuai dengan neuron pertama. Dengan menggunakan kolom bobot kedua, kita lakukan hal yang sama untuk neuron kedua dan seterusnya sampai neuron ke-10. Kemudian, kita dapat mengulangi operasi untuk 99 gambar lainnya. Jika kita memanggil X, matriks yang berisi 100 gambar, semua jumlah terbobot untuk 10 neuron kita, yang dihitung pada 100 gambar adalah X.W, sebuah perkalian matriks.
Setiap neuron sekarang harus menambahkan biasnya (konstanta). Karena kita memiliki 10 neuron, kita memiliki 10 konstanta bias. Kita akan menyebut vektor 10 nilai ini dengan b. Nilai tersebut harus ditambahkan ke setiap baris matriks yang telah dihitung sebelumnya. Menggunakan keajaiban "penyiaran" kita akan menulisnya dengan tanda tambah sederhana.
Kita akhirnya menerapkan fungsi aktivasi, misalnya "softmax" (dijelaskan di bawah) dan dapatkan formula yang menjelaskan jaringan neural 1 lapis, yang diterapkan ke 100 gambar:
Di Keras
Dengan library jaringan neural tingkat tinggi seperti Keras, kita tidak perlu menerapkan formula ini. Namun, penting untuk dipahami bahwa lapisan jaringan neural hanyalah kumpulan perkalian dan penambahan. Di Keras, lapisan padat akan ditulis sebagai:
tf.keras.layers.Dense(10, activation='softmax')
Pelajari lebih dalam
Sangat mudah untuk merangkai lapisan jaringan neural. Lapisan pertama menghitung jumlah piksel tertimbang. Lapisan berikutnya menghitung jumlah output dari lapisan sebelumnya.
Satu-satunya perbedaan, terlepas dari jumlah neuron, adalah pilihan fungsi aktivasi.
Fungsi aktivasi: relu, softmax, dan sigmoid
Anda biasanya akan menggunakan "relu" fungsi aktivasi untuk semua lapisan kecuali yang terakhir. Lapisan terakhir, dalam pengklasifikasi, akan menggunakan "softmax" aktivasi.
Sekali lagi, "neuron" menghitung jumlah tertimbang dari semua {i>input<i}-nya, menambahkan nilai yang disebut "bias" dan memberi tahu hasilnya melalui fungsi aktivasi.
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.
Fungsi aktivasi tradisional dalam jaringan neural adalah "sigmoid" tetapi "relu" terbukti memiliki properti konvergensi yang lebih baik hampir di semua tempat dan sekarang lebih disukai.
Aktivasi softmax untuk klasifikasi
Lapisan terakhir dari jaringan neural kita memiliki 10 neuron karena kita ingin mengklasifikasikan digit tulisan tangan ke dalam 10 kelas (0,..9). Ini harus menghasilkan 10 angka antara 0 dan 1 yang mewakili probabilitas digit ini menjadi 0, 1, 2 dan seterusnya. Untuk ini, di lapisan terakhir, kita akan menggunakan fungsi aktivasi yang disebut "softmax".
Penerapan softmax pada vektor dilakukan dengan mengambil eksponensial setiap elemen dan kemudian menormalisasi vektor, biasanya dengan membaginya dengan "L1" norma (yaitu jumlah nilai absolut) sehingga nilai yang dinormalisasi berjumlah 1 dan dapat ditafsirkan sebagai probabilitas.
Output lapisan terakhir, sebelum aktivasi terkadang disebut "logits". Jika vektor ini adalah L = [L0, L1, L2, L3, L4, L5, L6, L7, L8, L9], maka:
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, apa yang disebut "jarak entropi silang" adalah yang paling efektif. Kita akan menyebutnya {i>error<i} atau "{i>loss<i}" {i>function<i}:
Penurunan gradien
"Pelatihan" jaringan neural sebenarnya berarti menggunakan gambar dan label pelatihan untuk menyesuaikan bobot dan bias guna meminimalkan fungsi kerugian entropi silang. Begini cara kerjanya.
Entropi silang adalah fungsi bobot, bias, piksel dari gambar pelatihan dan kelasnya 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 dari gradien adalah bahwa gradien tersebut menunjuk "ke atas". Karena kita ingin menuju tempat yang nilai entropi silangnya rendah, kita melakukan ke arah yang berlawanan. Kita memperbarui bobot dan bias dengan menggunakan sebagian kecil dari gradien. Kemudian kita melakukan hal yang sama berulang kali menggunakan batch gambar dan label pelatihan berikutnya, dalam satu loop pelatihan. Mudah-mudahan, ini konvergensi ke tempat di mana entropi silang minimal meskipun tidak ada jaminan bahwa minimum ini unik.
Pengelompokan mini dan momentum
Anda dapat menghitung gradien hanya pada satu gambar contoh dan segera memperbarui bobot dan bias, tetapi melakukan hal ini pada sekumpulan, misalnya, 128 gambar memberikan gradien yang lebih mewakili batasan yang diberlakukan oleh gambar contoh yang berbeda dan karenanya cenderung menyatu menuju solusi lebih cepat. Ukuran tumpukan mini adalah parameter yang dapat disesuaikan.
Teknik ini, kadang-kadang disebut "penurunan gradien stokastik" memiliki manfaat lain yang lebih pragmatis: bekerja dengan batch juga berarti bekerja dengan matriks yang lebih besar dan ini biasanya lebih mudah dioptimalkan pada GPU dan TPU.
Konvergensi masih bisa sedikit kacau dan bahkan bisa berhenti jika vektor gradien semua nol. Apakah itu berarti kita telah menemukan minimum? Tidak selalu. Komponen gradien dapat bernilai nol pada nilai minimum atau maksimum. Dengan vektor gradien dengan jutaan elemen, jika semuanya bernilai nol, maka probabilitas bahwa setiap nol sesuai dengan nilai minimum dan tidak satu pun dari mereka hingga titik maksimum cukup kecil. Dalam ruang dari berbagai dimensi, saddle point cukup umum dan kita tidak ingin berhenti di sini.
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. "Batch" dimensi biasanya adalah dimensi pertama dari tensor data. Misalnya, tensor 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.
features: input dari jaringan neural 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 "kelas" atau jawaban yang benar dalam masalah klasifikasi yang diawasi
kecepatan pembelajaran: 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 dulunya merupakan fungsi aktivasi yang paling populer. "Output neuron sebelum fungsi logistik" disingkat menjadi "logits".
kerugian: fungsi error yang membandingkan output jaringan neural dengan jawaban yang benar
neuron: menghitung jumlah input tertimbang, menambahkan bias, dan memberikan hasilnya melalui fungsi aktivasi.
enkode one-hot: kelas 3 dari 5 dienkode sebagai vektor 5 elemen, semua angka nol kecuali yang ketiga yaitu 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 bertindak pada vektor, meningkatkan perbedaan antara komponen terbesar dan yang lainnya, serta menormalkan vektor untuk memiliki jumlah 1 sehingga dapat ditafsirkan sebagai vektor probabilitas. Digunakan sebagai langkah terakhir dalam pengklasifikasi.
tensor: "tensor" seperti matriks tetapi dengan jumlah dimensi yang arbitrer. Tensor 1-dimensi adalah vektor. Tensor 2 dimensi adalah sebuah matriks. Dan kemudian Anda dapat memiliki tensor dengan 3, 4, 5 atau lebih dimensi.
5. Mari kita mulai kodenya
Kembali ke {i>notebook<i} studi dan kali ini, mari kita baca kodenya.
Mari kita lihat semua sel di {i>notebook<i} ini.
"Parameter" sel
Ukuran batch, jumlah epoch pelatihan, dan lokasi file data ditentukan di sini. File data dihosting di bucket Google Cloud Storage (GCS), itulah sebabnya alamatnya diawali dengan gs://
Sel "Impor"
Semua library Python yang diperlukan diimpor ke sini, termasuk TensorFlow dan matplotlib untuk visualisasi.
Sel "utilisasi visualisasi [RUN ME]****"
Sel ini berisi kode visualisasi yang tidak menarik. Secara default, tampilan ini diciutkan, tetapi Anda dapat membukanya dan melihat kode saat ada waktu dengan mengklik dua kali pada kode tersebut.
Sel "tf.data.Dataset: mengurai file serta menyiapkan set data pelatihan dan validasi"
Sel ini menggunakan tf.data.Dataset API untuk memuat set data MNIST dari file data. Tidak perlu menghabiskan terlalu banyak waktu di sel ini. Jika Anda tertarik dengan tf.data.Dataset API, berikut adalah tutorial yang menjelaskannya: pipeline data berkecepatan TPU. Untuk saat ini, dasar-dasarnya adalah:
Gambar dan label (jawaban yang benar) dari set data MNIST disimpan dalam kumpulan data dengan panjang tetap dalam 4 file. File tersebut dapat dimuat dengan fungsi perekaman tetap khusus:
imagedataset = tf.data.FixedLengthRecordDataset(image_filename, 28*28, header_bytes=16)
Sekarang kita memiliki set data byte gambar. Kolom tersebut perlu didekodekan menjadi gambar. Kita menentukan fungsi untuk melakukannya. Gambar tidak dikompresi sehingga fungsi tidak perlu mendekode apa pun (decode_raw
pada dasarnya tidak melakukan apa pun). Gambar kemudian dikonversi ke nilai floating point antara 0 dan 1. Kita dapat membentuk ulang di sini sebagai gambar 2D tetapi sebenarnya kita menyimpannya sebagai susunan piksel datar berukuran 28*28 karena itulah yang diharapkan oleh lapisan padat awal kita.
def read_image(tf_bytestring):
image = tf.io.decode_raw(tf_bytestring, tf.uint8)
image = tf.cast(image, tf.float32)/256.0
image = tf.reshape(image, [28*28])
return image
Kami menerapkan fungsi ini ke set data menggunakan .map
dan mendapatkan set data gambar:
imagedataset = imagedataset.map(read_image, num_parallel_calls=16)
Kita melakukan jenis pembacaan dan decoding yang sama untuk label dan kita melakukan .zip
gambar serta label secara bersamaan:
dataset = tf.data.Dataset.zip((imagedataset, labelsdataset))
Sekarang kita memiliki set data yang terdiri dari pasangan (image, label). Inilah yang diharapkan oleh model kita. Kita belum siap menggunakannya dalam fungsi pelatihan:
dataset = dataset.cache()
dataset = dataset.shuffle(5000, reshuffle_each_iteration=True)
dataset = dataset.repeat()
dataset = dataset.batch(batch_size)
dataset = dataset.prefetch(tf.data.experimental.AUTOTUNE)
tf.data.Dataset API memiliki semua fungsi utilitas yang diperlukan untuk menyiapkan set data:
.cache
men-cache set data di RAM. Ini adalah {i>dataset<i} kecil sehingga akan bisa berfungsi. .shuffle
mengacaknya dengan buffer 5.000 elemen. Data pelatihan harus diacak dengan baik. .repeat
melakukan loop set data. Kita akan melatihnya beberapa kali (beberapa epoch). .batch
mengumpulkan beberapa gambar dan label menjadi satu batch mini. Terakhir, .prefetch
dapat menggunakan CPU untuk menyiapkan batch berikutnya saat batch saat ini sedang dilatih di GPU.
Set data validasi disiapkan dengan cara serupa. Sekarang kita siap untuk menentukan model dan menggunakan set data ini untuk melatihnya.
Sel "Model Keras"
Semua model akan menjadi urutan lapisan lurus sehingga kita dapat menggunakan gaya tf.keras.Sequential
untuk membuatnya. Awalnya, ini adalah lapisan padat tunggal. Ia memiliki 10 neuron karena kita mengklasifikasikan digit tulisan tangan ke dalam 10 kelas. Menggunakan "softmax" aktivasi karena merupakan lapisan
terakhir dalam pengklasifikasi.
Model Keras juga perlu mengetahui bentuk inputnya. tf.keras.layers.Input
dapat digunakan untuk menentukannya. Di sini, vektor input adalah vektor datar dari nilai piksel dengan panjang 28*28.
model = tf.keras.Sequential(
[
tf.keras.layers.Input(shape=(28*28,)),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='sgd',
loss='categorical_crossentropy',
metrics=['accuracy'])
# print model layers
model.summary()
# utility callback that displays training curves
plot_training = PlotTraining(sample_rate=10, zoom=1)
Mengonfigurasi model dilakukan di Keras menggunakan fungsi model.compile
. Di sini kita menggunakan pengoptimal dasar 'sgd'
(Penurunan Gradien Stokastik). Model klasifikasi memerlukan fungsi kerugian entropi silang, yang disebut 'categorical_crossentropy'
di Keras. Terakhir, kita meminta model untuk menghitung metrik 'accuracy'
, yang merupakan persentase gambar yang diklasifikasikan dengan benar.
Keras menawarkan utilitas model.summary()
yang sangat bagus yang mencetak detail model yang telah Anda buat. Instruktur Anda telah menambahkan utilitas PlotTraining
(ditentukan dalam sel "utilitas visualisasi") yang akan menampilkan berbagai kurva pelatihan selama pelatihan.
Sel "Latih dan validasi model"
Di sinilah pelatihan dilakukan, dengan memanggil model.fit
dan meneruskan set data pelatihan dan validasi. Secara default, Keras menjalankan putaran validasi di akhir setiap epoch.
model.fit(training_dataset, steps_per_epoch=steps_per_epoch, epochs=EPOCHS,
validation_data=validation_dataset, validation_steps=1,
callbacks=[plot_training])
Di Keras, Anda dapat menambahkan perilaku kustom selama pelatihan menggunakan callback. Begitulah cara menerapkan plot pelatihan yang diperbarui secara dinamis untuk workshop ini.
Sel "Visualisasikan prediksi"
Setelah model dilatih, kita bisa mendapatkan prediksi darinya dengan memanggil model.predict()
:
probabilities = model.predict(font_digits, steps=1)
predicted_labels = np.argmax(probabilities, axis=1)
Di sini kami telah menyiapkan satu set digit yang dicetak yang dirender dari font lokal, sebagai tes. Ingat bahwa jaringan neural menampilkan vektor dengan 10 probabilitas dari "softmax" akhirnya. Untuk mendapatkan labelnya, kita harus mencari tahu probabilitas mana yang tertinggi. np.argmax
dari library numpy akan melakukannya.
Untuk memahami alasan parameter axis=1
diperlukan, perlu diingat bahwa kami telah memproses sekumpulan 128 gambar sehingga model akan menampilkan 128 vektor probabilitas. Bentuk tensor output adalah [128, 10]. Kita menghitung argmax dari 10 probabilitas yang ditampilkan untuk setiap gambar, sehingga axis=1
(sumbu pertama adalah 0).
Model sederhana ini sudah mengenali 90% digit. Tidak buruk, tetapi sekarang Anda akan meningkatkannya secara signifikan.
6. Menambahkan lapisan
Untuk meningkatkan akurasi pengenalan, kami akan menambahkan lebih banyak lapisan ke jaringan neural.
Kita pertahankan softmax sebagai fungsi aktivasi di lapisan terakhir karena paling sesuai dengan klasifikasinya. Namun, pada lapisan perantara, kita akan menggunakan fungsi aktivasi yang paling klasik: fungsi sigmoid:
Misalnya, model Anda bisa terlihat seperti ini (jangan lupa koma, tf.keras.Sequential
mengambil daftar lapisan yang dipisahkan koma):
model = tf.keras.Sequential(
[
tf.keras.layers.Input(shape=(28*28,)),
tf.keras.layers.Dense(200, activation='sigmoid'),
tf.keras.layers.Dense(60, activation='sigmoid'),
tf.keras.layers.Dense(10, activation='softmax')
])
Lihat "ringkasan" model. Parameter tersebut sekarang memiliki setidaknya 10 kali lebih banyak parameter. Seharusnya 10x lebih baik! Tapi karena alasan tertentu, bukanlah ...
Kerugian tampaknya juga ditembak menembus atap. Terjadi error.
7. Perawatan khusus untuk jaringan dalam
Anda baru saja mengalami jaringan neural, karena orang-orang terbiasa merancangnya di tahun 80-an dan 90-an. Tidak heran mereka menyerah dari ide tersebut, sehingga mengantarkan apa yang disebut "musim dingin AI". Bahkan, saat Anda menambahkan lapisan, jaringan neural akan semakin sulit untuk dikonvergensi.
Ternyata jaringan saraf dalam dengan banyak lapisan (20, 50, bahkan 100 hari ini) dapat bekerja dengan sangat baik, menyediakan beberapa trik kotor matematis untuk membuatnya bertemu. Penemuan trik sederhana ini menjadi salah satu alasan renaisans deep learning pada tahun 2010-an.
Aktivasi RELU
Fungsi aktivasi sigmoid sebenarnya cukup bermasalah di jaringan dalam. Ia squash semua nilai antara 0 dan 1 dan ketika Anda melakukannya berulang kali, output neuron dan gradiennya dapat menghilang sepenuhnya. Hal tersebut disebutkan karena alasan sejarah, tetapi jaringan modern menggunakan RELU (Unit Linear Terarah) yang terlihat seperti ini:
Di sisi lain, relu memiliki turunan 1, setidaknya di sisi kanannya. Dengan aktivasi RELU, meskipun gradien yang berasal dari beberapa neuron bisa bernilai nol, akan selalu ada yang lain yang memberikan gradien bukan nol yang jelas dan pelatihan dapat dilanjutkan dengan kecepatan yang baik.
Pengoptimalan yang lebih baik
Dalam ruang berdimensi sangat tinggi seperti di sini — kita memiliki bobot dan bias dengan urutan 10 ribu — "titik pelana" sering terjadi. Ini adalah titik yang bukan minimuma lokal, tetapi gradiennya tetap nol dan pengoptimal penurunan gradien tetap ada di sana. TensorFlow memiliki berbagai pengoptimal yang tersedia, termasuk sebagian yang berfungsi dengan sejumlah inersia dan akan berjalan dengan aman melewati titik saddle.
Inisialisasi acak
Seni menginisialisasi bias-bias bobot sebelum pelatihan adalah bidang penelitian itu sendiri, dengan banyak makalah yang diterbitkan tentang topik tersebut. Anda dapat melihat semua penginisialisasi yang tersedia di Keras di sini. Untungnya, Keras melakukan hal yang benar secara default dan menggunakan penginisialisasi 'glorot_uniform'
yang merupakan yang terbaik dalam hampir semua kasus.
Anda tidak perlu melakukan apa pun, karena Keras sudah melakukan hal yang benar.
NaN ???
Rumus entropi silang melibatkan logaritma dan log(0) bukan Angka (NaN, kerusakan numerik jika Anda mau). Dapatkah masukan ke entropi silang menjadi 0? Input berasal dari softmax yang pada dasarnya merupakan eksponensial dan eksponensial tidak pernah nol. Jadi kita aman!
Iya gitu? Di dunia matematika yang indah, kita akan aman, tetapi di dunia komputer, exp(-150), yang direpresentasikan dalam format float32, sama nolnya dan terjadi error entropi silang.
Untungnya, tidak ada yang bisa Anda lakukan di sini, karena Keras menangani ini dan menghitung softmax diikuti oleh entropi silang dengan cara yang sangat hati-hati untuk memastikan stabilitas numerik dan menghindari NaN yang ditakuti.
Berhasil?
Sekarang akurasi Anda seharusnya mencapai 97%. Sasaran dalam workshop ini adalah meningkatkan skor di atas 99% secara signifikan. Jadi, mari kita lanjutkan.
Jika Anda mengalami kesulitan, berikut solusinya untuk saat ini:
8. Penurunan kecepatan pembelajaran
Mungkin kita bisa coba berlatih lebih cepat? Kecepatan pembelajaran default di pengoptimal Adam adalah 0,001. Mari kita coba meningkatkannya.
Melaju lebih cepat tampaknya tidak akan banyak membantu dan apa arti keributan ini?
Kurva pelatihan sangat rumit dan memperhatikan kedua kurva validasi: kurvanya melompat ke atas dan ke bawah. Ini artinya kami bekerja terlalu cepat. Kita bisa kembali ke kecepatan sebelumnya, tapi ada cara yang lebih baik.
Solusi yang tepat adalah memulai dengan cepat dan menurunkan kecepatan pembelajaran secara eksponensial. Di Keras, Anda dapat melakukannya dengan callback tf.keras.callbacks.LearningRateScheduler
.
Kode yang berguna untuk menyalin dan menempel:
# lr decay function
def lr_decay(epoch):
return 0.01 * math.pow(0.6, epoch)
# lr schedule callback
lr_decay_callback = tf.keras.callbacks.LearningRateScheduler(lr_decay, verbose=True)
# important to see what you are doing
plot_learning_rate(lr_decay, EPOCHS)
Jangan lupa menggunakan lr_decay_callback
yang telah Anda buat. Tambahkan ke daftar callback di model.fit
:
model.fit(..., callbacks=[plot_training, lr_decay_callback])
Dampak dari perubahan kecil ini spektakuler. Anda melihat bahwa sebagian besar noise sudah hilang dan akurasi pengujiannya kini di atas 98% secara berkelanjutan.
9. Dropout, overfitting
Modelnya kini tampak konvergensi dengan baik. Mari kita coba untuk lebih dalam lagi.
Apakah itu membantu?
Tidak juga, akurasinya masih di angka 98% dan melihat kerugian validasi. Meningkat! Algoritma pembelajaran hanya berfungsi pada data pelatihan dan mengoptimalkan kerugian pelatihan sebagaimana mestinya. Ia tidak pernah melihat data validasi, sehingga tidak mengherankan jika setelah beberapa saat pekerjaannya tidak lagi memiliki efek pada kerugian validasi yang berhenti menurun dan bahkan terkadang memantul kembali.
Hal ini tidak langsung memengaruhi kemampuan pengenalan dunia nyata model Anda, tetapi akan mencegah Anda menjalankan banyak iterasi dan umumnya merupakan tanda bahwa pelatihan tidak lagi memiliki efek positif.
Pemutusan ini biasanya disebut "overfitting" dan saat Anda melihatnya, Anda bisa mencoba menerapkan teknik regularisasi yang disebut "dropout". Teknik ini menembakkan neuron acak pada setiap iterasi pelatihan.
Apa itu berhasil?
Derau muncul kembali (secara tidak terduga, mengingat cara kerja putus sekolah). Kerugian validasi tampaknya tidak meningkat lagi, tetapi secara keseluruhan lebih tinggi daripada tanpa putus sekolah. Dan akurasi validasinya sedikit menurun. Ini adalah hasil yang cukup mengecewakan.
Sepertinya {i>dropout<i} bukanlah solusi yang tepat, atau mungkin "overfitting" merupakan konsep yang lebih kompleks dan beberapa penyebabnya tidak dapat diterima untuk “{i>dropout<i}” diperbaiki?
Apa yang dimaksud dengan "overfitting"? Overfitting terjadi saat jaringan neural belajar "dengan buruk", dengan cara yang sesuai untuk contoh pelatihan, tetapi tidak begitu baik pada data di dunia nyata. Ada teknik regularisasi seperti dropout yang bisa memaksanya untuk belajar dengan cara yang lebih baik, tetapi overfitting juga memiliki akar yang lebih dalam.
{i>Overfitting<i} dasar terjadi ketika jaringan neural memiliki terlalu banyak tingkat kebebasan untuk masalah yang dihadapi. Bayangkan kita memiliki begitu banyak neuron sehingga jaringan dapat menyimpan semua gambar pelatihan kita di dalamnya dan kemudian mengenalinya dengan pencocokan pola. Model ini akan gagal pada data di dunia nyata sepenuhnya. Jaringan neural harus sedikit dibatasi sehingga terpaksa menggeneralisasi apa yang dipelajarinya selama pelatihan.
Jika data pelatihan Anda sangat sedikit, bahkan jaringan kecil pun dapat mempelajarinya secara hati dan Anda akan melihat "overfitting". Secara umum, Anda selalu membutuhkan banyak data untuk melatih jaringan neural.
Akhirnya, jika Anda telah melakukan semuanya dari buku tersebut, bereksperimen dengan berbagai ukuran jaringan untuk memastikan tingkat kebebasannya terbatas, menerapkan putus-putus, dan dilatih dengan banyak data, Anda mungkin masih terjebak pada tingkat kinerja yang tampaknya tidak ada yang dapat ditingkatkan. Artinya, jaringan neural Anda, dalam bentuknya saat ini, tidak mampu mengekstrak lebih banyak informasi dari data, seperti dalam kasus kita di sini.
Ingat bagaimana kita menggunakan gambar, yang disatukan menjadi satu vektor? Itu ide yang sangat buruk. Digit tulisan tangan terbuat dari berbagai bentuk dan kami membuang informasi bentuk saat meratakan piksel. Namun, ada jenis jaringan neural yang dapat memanfaatkan informasi bentuk: jaringan konvolusional. Mari kita coba.
Jika Anda mengalami kesulitan, berikut solusinya untuk saat ini:
10. [INFO] jaringan konvolusional
Ringkasan singkat
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, baca terus.
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([
tf.keras.layers.Reshape(input_shape=(28*28,), target_shape=(28, 28, 1)),
tf.keras.layers.Conv2D(kernel_size=3, filters=12, activation='relu'),
tf.keras.layers.Conv2D(kernel_size=6, filters=24, strides=2, activation='relu'),
tf.keras.layers.Conv2D(kernel_size=6, filters=32, strides=2, activation='relu'),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(10, activation='softmax')
])
Dalam lapisan jaringan konvolusional, satu "neuron" melakukan penjumlahan piksel di atasnya yang diberi bobot, hanya di seluruh wilayah 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 melalui gambar secara dua arah ("konvolusi"). Output memiliki nilai sebanyak piksel dalam gambar (tetapi beberapa padding diperlukan di bagian tepinya). Ini adalah operasi pemfilteran. Dalam ilustrasi di atas, ia menggunakan filter dengan bobot 4x4x3=48.
Namun, 48 bobot tidak akan cukup. Untuk menambahkan lebih banyak derajat kebebasan, kita mengulangi operasi yang sama dengan set berat baru. Tindakan ini akan menghasilkan serangkaian output filter baru. Sebut saja "channel" output secara analogi dengan saluran R,G,B pada gambar input.
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.
Ilustrasi: jaringan neural konvolusional mengubah "kubus" data ke dalam "kubus" lain. yang besar.
Konvolusi berjalan, penggabungan maksimum
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)
Ilustrasi: menggeser jendela komputasi sebesar 3 piksel menghasilkan nilai output yang lebih sedikit. Konvolusi melangkah atau penggabungan maksimum (maksimum pada jendela 2x2 yang bergeser dengan langkah 2) adalah cara mengecilkan kubus data dalam dimensi horizontal.
Lapisan terakhir
Setelah lapisan konvolusional terakhir, data akan dalam bentuk "kubus". Ada dua cara untuk memasoknya melalui lapisan padat akhir.
Yang pertama adalah meratakan kubus data menjadi vektor dan kemudian memasukkannya ke lapisan softmax. Terkadang, Anda bahkan dapat menambahkan lapisan padat sebelum lapisan softmax. Ini cenderung mahal dari segi jumlah bobot. Lapisan padat di akhir jaringan konvolusional dapat berisi lebih dari setengah bobot seluruh jaringan neural.
Alih-alih menggunakan lapisan padat yang mahal, kita juga dapat membagi "kubus" data yang masuk ke dalam sebanyak mungkin bagian dari class yang kita miliki, menghitung nilai rata-ratanya, dan memasukkan nilai tersebut melalui fungsi aktivasi softmax. Cara pembuatan head klasifikasi ini memerlukan bobot 0. Di Keras, ada lapisan untuk ini: tf.keras.layers.GlobalAveragePooling2D()
.
Langsung ke bagian berikutnya guna membuat jaringan konvolusional untuk masalah yang dihadapi.
11. Jaringan konvolusional
Mari kita membangun jaringan konvolusional untuk pengenalan digit yang ditulis tangan. Kita akan menggunakan tiga lapisan konvolusional di bagian atas, lapisan pembacaan softmax tradisional di bagian bawah, dan menghubungkannya dengan satu lapisan yang terhubung sepenuhnya:
Perhatikan bahwa lapisan konvolusional kedua dan ketiga memiliki langkah dua yang menjelaskan mengapa mereka menurunkan jumlah nilai output dari 28x28 menjadi 14x14 dan kemudian 7x7.
Mari kita tulis kode Keras.
Perhatian khusus diperlukan sebelum lapisan konvolusional pertama. Sebenarnya, mereka mengharapkan 'kubus' 3D data tetapi set data kita sejauh ini telah diatur untuk lapisan padat dan semua piksel gambar diratakan menjadi vektor. Kita perlu membentuk ulang mereka menjadi gambar 28x28x1 (1 saluran untuk gambar hitam putih):
tf.keras.layers.Reshape(input_shape=(28*28,), target_shape=(28, 28, 1))
Anda dapat menggunakan baris ini, alih-alih lapisan tf.keras.layers.Input
yang Anda miliki hingga saat ini.
Di Keras, sintaksis untuk lapisan konvolusional yang diaktifkan 'relu' adalah:
tf.keras.layers.Conv2D(kernel_size=3, filters=12, padding='same', activation='relu')
Untuk konvolusi tegang, Anda akan menulis:
tf.keras.layers.Conv2D(kernel_size=6, filters=24, padding='same', activation='relu', strides=2)
Untuk meratakan sebuah kubus data menjadi vektor agar dapat digunakan oleh lapisan padat:
tf.keras.layers.Flatten()
Dan untuk lapisan padat, sintaksisnya tidak berubah:
tf.keras.layers.Dense(200, activation='relu')
Apakah model Anda menembus batas akurasi 99%? Sedikit lagi... tetapi perhatikan kurva kerugian validasi. Apakah Anda pernah mendengarnya?
Lihat juga prediksinya. Untuk pertama kalinya, Anda akan melihat bahwa sebagian besar dari 10.000 digit pengujian kini dikenali dengan benar. Hanya sekitar 4 1⁄2 baris kesalahan deteksi yang tersisa (sekitar 110 digit dari 10.000)
Jika Anda mengalami kesulitan, berikut solusinya untuk saat ini:
12. Dropout lagi
Pelatihan sebelumnya menunjukkan tanda-tanda overfitting yang jelas (dan akurasinya masih di bawah 99%). Haruskah kita mencoba batal lagi?
Bagaimana rasanya kali ini?
Sepertinya mereka telah melakukan eliminasi saat ini. Kerugian validasi tidak lagi meningkat dan akurasi akhir seharusnya jauh di atas 99%. Selamat!
Saat pertama kali mencoba menerapkan dropout, kami pikir kami memiliki masalah overfitting, padahal masalahnya terletak pada arsitektur jaringan neural. Kami tidak dapat melangkah lebih jauh tanpa lapisan konvolusional dan tidak ada yang dapat dilakukan pelamar tentang hal itu.
Kali ini, sepertinya overfitting adalah penyebab masalah dan {i>dropout<i} benar-benar membantu. Ingat, ada banyak hal yang dapat menyebabkan terputusnya koneksi antara kurva kerugian pelatihan dan validasi, dengan kerugian validasi yang semakin besar. Overfitting (terlalu banyak tingkat kebebasan, digunakan dengan buruk oleh jaringan) hanyalah salah satunya. Jika set data terlalu kecil atau arsitektur jaringan neural tidak memadai, Anda mungkin melihat perilaku serupa pada kurva kerugian, tetapi proses dropout tidak akan membantu.
13. Normalisasi batch
Akhirnya, mari kita coba menambahkan normalisasi {i>batch<i}.
Itulah teorinya, dalam praktiknya, ingatlah beberapa aturan:
Mari kita lihat buku yang sesuai untuk saat ini dan tambahkan lapisan norma batch pada setiap lapisan {i>neural network<i}, tetapi yang terakhir. Jangan tambahkan ke "softmax" terakhir feedforward. Di sana tidak akan berguna.
# Modify each layer: remove the activation from the layer itself.
# Set use_bias=False since batch norm will play the role of biases.
tf.keras.layers.Conv2D(..., use_bias=False),
# Batch norm goes between the layer and its activation.
# The scale factor can be turned off for Relu activation.
tf.keras.layers.BatchNormalization(scale=False, center=True),
# Finish with the activation.
tf.keras.layers.Activation('relu'),
Bagaimana akurasinya sekarang?
Dengan sedikit penyesuaian (BATCH_SIZE=64, parameter peluruhan kecepatan pembelajaran 0,666, tingkat putus-putus pada lapisan padat 0,3) dan sedikit keberuntungan, Anda bisa mencapai 99,5%. Penyesuaian kecepatan pembelajaran dan putus sekolah dilakukan berdasarkan "praktik terbaik" untuk menggunakan norma batch:
- Normalnya batch membantu jaringan neural untuk dikonvergensi dan biasanya memungkinkan Anda berlatih lebih cepat.
- Norma batch adalah regularizer. Biasanya Anda bisa mengurangi jumlah {i>dropout<i} yang digunakan, atau bahkan tidak menggunakan {i>dropout<i} sama sekali.
Notebook solusi ini menjalankan pelatihan sebesar 99,5%:
14. Berlatih di cloud dengan hardware yang canggih: AI Platform
Anda akan menemukan versi kode siap pakai di cloud di folder mlengine pada GitHub, beserta petunjuk untuk menjalankannya di Google Cloud AI Platform. Sebelum dapat menjalankan bagian ini, Anda harus membuat akun Google Cloud dan mengaktifkan penagihan. Resource yang diperlukan untuk menyelesaikan lab harus kurang dari beberapa dolar (dengan asumsi 1 jam waktu pelatihan pada satu GPU). Untuk menyiapkan akun:
- Buat project Google Cloud Platform ( http://cloud.google.com/console).
- Aktifkan penagihan.
- Instal alat command line GCP ( GCP SDK di sini).
- Buat bucket Google Cloud Storage (berada di region
us-central1
). Ini akan digunakan untuk melakukan tahapan kode pelatihan dan menyimpan model yang telah Anda latih. - Aktifkan API yang diperlukan dan minta kuota yang diperlukan (jalankan perintah pelatihan sekali dan Anda akan mendapatkan pesan error yang memberi tahu Anda apa yang harus diaktifkan).
15. Selamat!
Anda telah membuat jaringan neural pertama dan melatihnya hingga akurasi 99%. Teknik yang dipelajari selama proses ini tidak spesifik untuk set data MNIST. Sebenarnya, teknik tersebut banyak digunakan saat bekerja dengan jaringan neural. Sebagai kado perpisahan, ini dia "catatan tebing" untuk lab, dalam versi kartun. Anda dapat menggunakannya untuk mengingat apa yang telah Anda pelajari:
Langkah berikutnya
- Setelah jaringan terhubung sepenuhnya dan konvolusional, Anda harus mempelajari jaringan saraf berulang.
- Untuk menjalankan pelatihan atau inferensi Anda di cloud pada infrastruktur terdistribusi, Google Cloud menyediakan AI Platform.
- Terakhir, kami senang menerima masukan. Beri tahu kami jika Anda melihat ada yang tidak beres di lab ini atau menurut Anda harus diperbaiki. Kami menangani masukan melalui masalah GitHub [link masukan].
Penulis: Martin GörnerTwitter: @martin_gorner |
Hak cipta semua gambar kartun di lab ini: alexpokusay / 123RF stock photos