Kursus

Deep learning adalah subbidang machine learning, yaitu sekumpulan algoritma yang terinspirasi oleh struktur dan fungsi otak.
TensorFlow adalah kerangka kerja machine learning kedua yang dibuat Google dan digunakan untuk merancang, membangun, dan melatih model deep learning. Anda dapat menggunakan pustaka TensorFlow untuk melakukan komputasi numerik, yang mungkin tampak biasa saja, tetapi komputasi ini dilakukan dengan grafik aliran data. Dalam grafik ini, node mewakili operasi matematis, sementara edge mewakili data, yang biasanya berupa array data multidimensi atau tensor, yang dikomunikasikan di antara edge tersebut.
Mengerti, kan? Nama “TensorFlow” diambil dari operasi yang dilakukan jaringan saraf pada array data multidimensi atau tensor! Secara harfiah adalah aliran tensor. Untuk saat ini, ini saja yang perlu Anda ketahui tentang tensor, tetapi Anda akan membahasnya lebih dalam di bagian selanjutnya!
Tutorial TensorFlow untuk pemula hari ini akan memperkenalkan Anda pada deep learning secara interaktif:
Unduh notebook tutorial ini di sini.
Anda juga mungkin tertarik pada kursus Deep Learning in Python, tutorial Keras dari DataCamp atau tutorial keras dengan R.
Mengenal Tensor
Untuk memahami tensor dengan baik, sebaiknya Anda memiliki pengetahuan kerja aljabar linear dan kalkulus vektor. Anda telah membaca di pengantar bahwa tensor diimplementasikan di TensorFlow sebagai array data multidimensi, tetapi perlu sedikit pengantar lagi agar benar-benar memahami tensor dan penggunaannya dalam machine learning.
Vektor Bidang
Sebelum membahas vektor bidang, ada baiknya meninjau singkat konsep “vektor”; Vektor adalah jenis khusus matriks, yaitu susunan persegi panjang dari angka-angka. Karena vektor adalah kumpulan angka yang berurut, vektor sering dipandang sebagai matriks kolom: hanya memiliki satu kolom dan sejumlah baris. Dengan kata lain, Anda juga dapat menganggap vektor sebagai besaran skalar yang diberi arah.
Ingat: contoh skalar adalah “5 meter” atau “60 m/dtk”, sedangkan vektor misalnya “5 meter ke utara” atau “60 m/dtk ke timur”. Perbedaannya jelas pada arah pada vektor. Walaupun demikian, contoh-contoh yang Anda lihat sejauh ini mungkin terasa jauh dari vektor yang mungkin Anda temui saat mengerjakan masalah machine learning. Ini wajar; Panjang vektor matematis adalah angka murni: absolut. Sementara itu, arah bersifat relatif: diukur relatif terhadap suatu arah referensi dan memiliki satuan radian atau derajat. Biasanya Anda mengasumsikan arah positif dan berputar berlawanan arah jarum jam dari arah referensi.

Secara visual, tentu saja, Anda merepresentasikan vektor sebagai panah, seperti pada gambar di atas. Ini berarti Anda juga dapat menganggap vektor sebagai panah yang memiliki arah dan panjang. Arah ditunjukkan oleh ujung panah, sedangkan panjang ditunjukkan oleh panjang panah.
Lalu bagaimana dengan vektor bidang?
Vektor bidang adalah susunan tensor yang paling lurus. Mereka mirip dengan vektor biasa seperti yang Anda lihat di atas, dengan satu perbedaan bahwa mereka berada dalam ruang vektor. Untuk memahami ini lebih baik, mari mulai dengan contoh: Anda memiliki vektor berukuran 2 X 1. Ini berarti vektor tersebut termasuk ke dalam himpunan bilangan real yang dipasangkan dua-dua. Atau, dengan kata lain, bagian dari ruang dua dimensi. Dalam kasus seperti itu, Anda dapat merepresentasikan vektor pada bidang koordinat (x,y) dengan panah atau sinar.
Dengan bekerja dari bidang koordinat ini dalam posisi standar di mana vektor memiliki titik ujung di titik asal (0,0), Anda dapat menurunkan koordinat x dengan melihat baris pertama vektor, sedangkan koordinat y ada di baris kedua. Tentu saja, posisi standar ini tidak selalu harus dipertahankan: vektor dapat bergerak sejajar dengan dirinya di bidang tanpa mengalami perubahan.
Catatan bahwa serupa, untuk vektor berukuran 3 X 1, Anda berbicara tentang ruang tiga dimensi. Anda dapat merepresentasikan vektor sebagai bangun tiga dimensi dengan panah yang menunjuk ke posisi dalam ruang vektor: digambar pada sumbu x, y, dan z standar.
Menyenangkan memiliki vektor dan merepresentasikannya pada bidang koordinat, tetapi pada dasarnya, Anda memiliki vektor agar dapat melakukan operasi terhadapnya dan salah satu hal yang membantu adalah mengekspresikan vektor sebagai basis atau vektor satuan.
Vektor satuan adalah vektor dengan magnitudo satu. Anda sering mengenalinya dengan huruf kecil bertanda topi. Vektor satuan akan berguna jika Anda ingin mengekspresikan vektor 2-D atau 3-D sebagai jumlah dari dua atau tiga komponen ortogonal, seperti sumbu x dan y, atau sumbu z.
Dan ketika Anda berbicara tentang mengekspresikan satu vektor, misalnya sebagai jumlah komponen, itu berarti Anda berbicara tentang vektor komponen, yaitu dua atau lebih vektor yang jumlahnya adalah vektor tersebut.
Tip: tonton video ini, yang menjelaskan apa itu tensor dengan bantuan benda-benda rumah tangga sederhana!
Tensor
Selain vektor bidang, kovektor dan operator linear adalah dua kasus lain yang ketiganya memiliki kesamaan: semuanya adalah kasus khusus tensor. Anda masih ingat bagaimana vektor dikarakterisasi di bagian sebelumnya sebagai besaran skalar yang diberi arah. Tensor, maka, adalah representasi matematis dari entitas fisik yang dapat dikarakterisasi oleh magnitudo dan multi arah.
Dan, seperti Anda merepresentasikan skalar dengan satu angka dan vektor dengan deret tiga angka dalam ruang 3 dimensi, misalnya, tensor dapat direpresentasikan oleh array berisi 3R angka dalam ruang 3 dimensi.
Huruf “R” pada notasi ini mewakili rank tensor: ini berarti bahwa dalam ruang 3 dimensi, tensor dengan rank dua dapat direpresentasikan oleh 3 pangkat 2 atau 9 angka. Dalam ruang N dimensi, skalar tetap memerlukan satu angka, vektor memerlukan N angka, dan tensor memerlukan N^R angka. Inilah mengapa Anda sering mendengar bahwa skalar adalah tensor berderajat 0: karena tidak memiliki arah, cukup direpresentasikan dengan satu angka.
Dengan ini, cukup mudah mengenali skalar, vektor, dan tensor serta membedakannya: skalar direpresentasikan oleh satu angka, vektor oleh sekumpulan angka berurut, dan tensor oleh array angka.
Yang membuat tensor unik adalah kombinasi antara komponen dan vektor basis: vektor basis berubah cara tertentu antar kerangka acuan dan komponennya berubah sedemikian rupa sehingga kombinasi antara komponen dan vektor basis tetap sama.
Menginstal TensorFlow
Sekarang Anda mengetahui lebih banyak tentang TensorFlow, saatnya memulai dan memasang pustakanya. Perlu diketahui bahwa TensorFlow menyediakan API untuk Python, C++, Haskell, Java, Go, Rust, dan ada juga paket pihak ketiga untuk R bernama tensorflow.
Tip: jika Anda ingin mengetahui lebih banyak tentang paket deep learning di R, pertimbangkan untuk melihat keras: Tutorial Deep Learning di R dari DataCamp.
Dalam tutorial ini, Anda akan mengunduh versi TensorFlow yang memungkinkan Anda menulis kode untuk proyek deep learning Anda dalam Python. Pada laman instalasi TensorFlow, Anda akan melihat beberapa cara paling umum dan instruksi terbaru untuk memasang TensorFlow menggunakan virtualenv, pip, Docker dan terakhir, ada juga beberapa cara lain untuk memasang TensorFlow di komputer pribadi Anda.
Catatan Anda juga dapat menginstal TensorFlow dengan Conda jika Anda bekerja di Windows. Namun, karena instalasi TensorFlow didukung oleh komunitas, sebaiknya periksa instruksi instalasi resmi.
Sekarang setelah Anda melalui proses instalasi, saatnya memeriksa ulang bahwa TensorFlow telah terpasang dengan benar dengan mengimpornya ke ruang kerja Anda dengan alias tf:
import tensorflow as tf
Catatan bahwa alias yang Anda gunakan pada baris kode di atas semacam konvensi - Digunakan agar Anda tetap konsisten dengan pengembang lain yang menggunakan TensorFlow dalam proyek data science di satu sisi, dan dengan proyek TensorFlow open-source di sisi lain.
Mulai dengan TensorFlow: Dasar-dasar
Anda umumnya akan menulis program TensorFlow yang dijalankan sebagai satu kesatuan; Sekilas ini agak bertentangan saat Anda bekerja dengan Python. Namun, jika Anda mau, Anda juga dapat menggunakan Interactive Session milik TensorFlow untuk bekerja lebih interaktif dengan pustaka ini. Ini sangat berguna jika Anda terbiasa bekerja dengan IPython.
Untuk tutorial ini, Anda akan fokus pada opsi kedua: ini akan membantu Anda mulai cepat dengan deep learning di TensorFlow. Namun sebelum melangkah lebih jauh, mari coba beberapa hal kecil sebelum mulai dengan pekerjaan berat.
Pertama, impor pustaka tensorflow dengan alias tf, seperti yang Anda lihat pada bagian sebelumnya. Lalu inisialisasi dua variabel yang sebenarnya merupakan konstanta. Berikan array berisi empat angka ke fungsi constant().
Catatan bahwa Anda juga berpotensi dapat memberikan sebuah bilangan bulat, tetapi lebih sering Anda akan bekerja dengan array. Seperti Anda lihat di pengantar, tensor adalah tentang array! Jadi pastikan Anda memberikan sebuah array :) Selanjutnya, Anda dapat menggunakan multiply() untuk mengalikan kedua variabel Anda. Simpan hasilnya ke variabel result. Terakhir, cetak result dengan bantuan fungsi print().
Catatan bahwa Anda telah mendefinisikan konstanta pada potongan kode DataCamp Light di atas. Namun, ada dua jenis nilai lain yang dapat Anda gunakan, yaitu placeholder, yaitu nilai yang belum ditetapkan dan akan diinisialisasi oleh sesi saat dijalankan. Seperti namanya, ini hanyalah placeholder untuk tensor yang akan selalu diisi saat sesi dijalankan; Ada juga Variable, yaitu nilai yang dapat berubah. Konstanta, seperti yang mungkin sudah Anda pahami, adalah nilai yang tidak berubah.
Hasil baris kode tersebut adalah tensor abstrak dalam grafik komputasi. Namun, bertentangan dengan dugaan Anda, result sebenarnya belum dihitung. Itu hanya mendefinisikan model, tetapi belum ada proses yang berjalan untuk menghitung hasilnya. Anda dapat melihatnya pada keluaran cetak: tidak ada hasil yang benar-benar Anda inginkan (yakni, 30). Ini berarti TensorFlow menggunakan evaluasi malas!
Namun, jika Anda ingin melihat hasilnya, Anda harus menjalankan kode ini dalam sesi interaktif. Anda dapat melakukannya dengan beberapa cara, seperti yang ditunjukkan pada potongan kode DataCamp Light di bawah ini:
Catatan bahwa Anda juga dapat menggunakan baris kode berikut untuk memulai Session interaktif, menjalankan result dan menutup Session secara otomatis setelah mencetak output:
Pada potongan kode di atas Anda baru saja mendefinisikan Session bawaan, tetapi perlu diketahui juga bahwa Anda dapat meneruskan opsi. Misalnya, Anda dapat menentukan argumen config lalu menggunakan protocol buffer ConfigProto untuk menambahkan opsi konfigurasi untuk sesi Anda.
Contohnya, jika Anda menambahkan
config=tf.ConfigProto(log_device_placement=True)
ke Session, Anda memastikan bahwa perangkat GPU atau CPU yang ditugaskan ke suatu operasi dicatat. Anda kemudian akan mendapatkan informasi perangkat mana yang digunakan dalam sesi untuk setiap operasi. Anda juga dapat menggunakan konfigurasi sesi berikut, misalnya, saat Anda menggunakan soft constraint untuk penempatan perangkat:
config=tf.ConfigProto(allow_soft_placement=True)
Sekarang TensorFlow sudah terpasang dan diimpor ke ruang kerja Anda dan Anda telah melalui dasar-dasar bekerja dengan paket ini, saatnya menyingkirkan ini sejenak dan beralih ke data Anda. Seperti biasa, Anda akan terlebih dahulu meluangkan waktu untuk mengeksplorasi dan memahami data Anda sebelum mulai memodelkan jaringan saraf.
Rambu Lalu Lintas Belgia: Latar Belakang
Walaupun topik lalu lintas umumnya sudah dikenal, tidak ada salahnya meninjau singkat observasi yang termasuk dalam dataset ini untuk memastikan Anda memahami semuanya sebelum mulai. Intinya, pada bagian ini, Anda akan mempercepat penguasaan pengetahuan domain yang Anda perlukan untuk melanjutkan tutorial ini.
Tentu saja, karena saya orang Belgia, saya juga akan membagikan beberapa anekdot :)
- Rambu lalu lintas Belgia biasanya dalam bahasa Belanda dan Prancis. Ini baik untuk diketahui, tetapi untuk dataset yang akan Anda gunakan, ini tidak terlalu penting!
- Ada enam kategori rambu lalu lintas di Belgia: rambu peringatan, rambu prioritas, rambu larangan, rambu perintah, rambu terkait parkir dan berhenti di jalan, dan terakhir rambu penunjuk.
- Pada 1 Januari 2017, lebih dari 30.000 rambu lalu lintas dihapus dari jalan-jalan Belgia. Semuanya adalah rambu larangan terkait kecepatan.
- Berbicara tentang penghapusan, keberlimpahan rambu lalu lintas telah menjadi diskusi yang terus berlanjut di Belgia (dan secara lebih luas, seluruh Uni Eropa).
Memuat dan Mengeksplorasi Data
Sekarang setelah Anda mengumpulkan lebih banyak informasi latar belakang, saatnya mengunduh dataset di sini. Anda harus mendapatkan dua file zip yang tercantum di sebelah "BelgiumTS for Classification (cropped images)", yaitu "BelgiumTSC_Training" dan "BelgiumTSC_Testing".
Tip: jika Anda telah mengunduh file atau akan melakukannya setelah menyelesaikan tutorial ini, lihat struktur folder data yang Anda unduh! Anda akan melihat bahwa folder data pengujian dan pelatihan berisi 61 subfolder, yaitu 62 jenis rambu lalu lintas yang akan Anda gunakan untuk klasifikasi pada tutorial ini. Selain itu, Anda akan menemukan bahwa file berakhiran .ppm atau Portable Pixmap Format. Anda telah mengunduh gambar rambu lalu lintas!
Mari mulai mengimpor data ke ruang kerja Anda. Mari mulai dengan baris kode yang muncul di bawah User-Defined Function (UDF) load_data():
- Pertama, tetapkan
ROOT_PATHAnda. Ini adalah path tempat Anda membuat direktori dengan data pelatihan dan pengujian Anda. - Kemudian, Anda dapat menambahkan path spesifik ke
ROOT_PATHAnda dengan bantuan fungsijoin(). Simpan dua path spesifik ini ditrain_data_directorydantest_data_directory. - Setelah itu, Anda dapat memanggil fungsi
load_data()dan meneruskantrain_data_directoryke dalamnya. - Sekarang, fungsi
load_data()sendiri dimulai dengan mengumpulkan semua subdirektori yang ada ditrain_data_directory; Ini dilakukan dengan list comprehension, yang merupakan cara yang cukup alami untuk membangun list - pada dasarnya mengatakan bahwa, jika Anda menemukan sesuatu ditrain_data_directory, Anda akan memeriksa ulang apakah itu direktori, dan jika ya, Anda akan menambahkannya ke list Anda. Ingat bahwa setiap subdirektori merepresentasikan sebuah label. - Berikutnya, Anda harus melakukan loop melalui subdirektori. Pertama, inisialisasi dua list,
labelsdanimages. Selanjutnya, kumpulkan path subdirektori dan nama file gambar yang disimpan di subdirektori tersebut. Kemudian, Anda dapat mengumpulkan data ke dalam dua list tersebut dengan fungsiappend().
def load_data(data_directory):
directories = [d for d in os.listdir(data_directory)
if os.path.isdir(os.path.join(data_directory, d))]
labels = []
images = []
for d in directories:
label_directory = os.path.join(data_directory, d)
file_names = [os.path.join(label_directory, f)
for f in os.listdir(label_directory)
if f.endswith(".ppm")]
for f in file_names:
images.append(skimage.data.imread(f))
labels.append(int(d))
return images, labels
ROOT_PATH = "/your/root/path"
train_data_directory = os.path.join(ROOT_PATH, "TrafficSigns/Training")
test_data_directory = os.path.join(ROOT_PATH, "TrafficSigns/Testing")
images, labels = load_data(train_data_directory)
Catatan bahwa pada potongan kode di atas, data pelatihan dan pengujian berada di folder bernama "Training" dan "Testing", yang keduanya merupakan subdirektori dari direktori lain "TrafficSigns". Di mesin lokal, ini bisa terlihat seperti "/Users/Name/Downloads/TrafficSigns", dengan dua subfolder bernama "Training" dan "Testing".
Tip: tinjau kembali cara menulis fungsi di Python dengan Python Functions Tutorial dari DataCamp.
Statistik Rambu Lalu Lintas
Setelah data dimuat, saatnya inspeksi data! Anda dapat memulai dengan analisis yang cukup sederhana dengan bantuan atribut ndim dan size dari array images:
Perhatikan bahwa variabel images dan labels adalah list, jadi Anda mungkin perlu menggunakan np.array() untuk mengonversi variabel menjadi array di ruang kerja Anda. Hal ini sudah dilakukan untuk Anda di sini!
Catatan bahwa images[0] yang Anda cetak sebenarnya adalah satu gambar tunggal yang direpresentasikan oleh array di dalam array! Ini mungkin terasa berlawanan dengan intuisi pada awalnya, tetapi ini sesuatu yang akan Anda biasakan saat Anda semakin jauh bekerja dengan gambar dalam aplikasi machine learning atau deep learning.
Selanjutnya, Anda juga dapat sedikit melihat labels, tetapi seharusnya tidak ada terlalu banyak kejutan pada titik ini:
Angka-angka ini sudah memberi Anda wawasan tentang seberapa sukses impor Anda dan ukuran pasti data Anda. Sekilas, semuanya dieksekusi seperti yang Anda harapkan, dan Anda melihat bahwa ukuran array cukup besar jika Anda mempertimbangkan bahwa Anda berurusan dengan array di dalam array.
Tip coba tambahkan atribut berikut ke array Anda untuk mendapatkan informasi lebih lanjut tentang tata letak memori, panjang satu elemen array dalam byte, dan total byte yang dikonsumsi oleh elemen array dengan atribut flags, itemsize, dan nbytes. Anda dapat mengujinya di konsol IPython pada potongan DataCamp Light di atas!
Berikutnya, Anda juga dapat melihat distribusi rambu lalu lintas:
Kerja bagus! Sekarang mari lihat lebih dekat histogram yang Anda buat!

Sekilas, Anda melihat ada label yang jauh lebih banyak hadir dalam dataset daripada yang lain: label 22, 32, 38, dan 61 sangat menonjol. Pada titik ini, bagus untuk mengingat hal ini, tetapi Anda pasti akan membahasnya lebih lanjut di bagian berikutnya!
Memvisualisasikan Rambu Lalu Lintas
Analisis atau pemeriksaan kecil sebelumnya sudah memberi Anda gambaran tentang data yang Anda gunakan, tetapi ketika data Anda sebagian besar berupa gambar, langkah yang sebaiknya Anda lakukan untuk mengeksplorasi data adalah dengan memvisualisasikannya.
Mari lihat beberapa rambu lalu lintas acak:
- Pertama, pastikan Anda mengimpor modul
pyplotdari paketmatplotlibdengan alias umumplt. - Kemudian, Anda akan membuat list dengan 4 angka acak. Ini akan digunakan untuk memilih rambu lalu lintas dari array
imagesyang baru saja Anda tinjau di bagian sebelumnya. Dalam kasus ini, Anda menggunakan300,2250,3650, dan4000. - Berikutnya, Anda akan menyatakan bahwa untuk setiap elemen dalam panjang list tersebut, jadi dari 0 hingga 4, Anda akan membuat subplot tanpa sumbu (agar tidak menarik perhatian dan fokus Anda hanya pada gambar!). Dalam subplot ini, Anda akan menampilkan gambar tertentu dari array
imagessesuai dengan angka pada indeksi. Pada loop pertama, Anda memberikan300keimages[], pada putaran kedua2250, dan seterusnya. Terakhir, Anda menyesuaikan subplot agar ada cukup jarak di antaranya. - Hal terakhir yang tersisa adalah menampilkan plot Anda dengan fungsi
show()!
Ini dia:
# Import the `pyplot` module of `matplotlib`
import matplotlib.pyplot as plt
# Determine the (random) indexes of the images that you want to see
traffic_signs = [300, 2250, 3650, 4000]
# Fill out the subplots with the random images that you defined
for i in range(len(traffic_signs)):
plt.subplot(1, 4, i+1)
plt.axis('off')
plt.imshow(images[traffic_signs[i]])
plt.subplots_adjust(wspace=0.5)
plt.show()
Seperti yang Anda duga dari 62 label yang termasuk dalam dataset ini, rambu-rambunya berbeda satu sama lain.
Apa lagi yang Anda perhatikan? Lihat lagi dengan saksama gambar di bawah ini:

Keempat gambar ini tidak berukuran sama!
Anda tentu bisa mencoba-coba angka dalam list traffic_signs dan menindaklanjuti pengamatan ini lebih jauh, tetapi apa pun itu, ini adalah pengamatan penting yang perlu Anda pertimbangkan saat mulai memanipulasi data agar dapat diberikan ke jaringan saraf.
Mari konfirmasi hipotesis perbedaan ukuran dengan mencetak shape, nilai minimum dan maksimum dari gambar spesifik yang Anda masukkan ke dalam subplot.
Kode di bawah ini sangat mirip dengan yang Anda gunakan untuk membuat plot di atas, tetapi berbeda karena di sini Anda mengalihkan ukuran dan gambar alih-alih hanya memplot gambar berdampingan:
# Import `matplotlib`
import matplotlib.pyplot as plt
# Determine the (random) indexes of the images
traffic_signs = [300, 2250, 3650, 4000]
# Fill out the subplots with the random images and add shape, min and max values
for i in range(len(traffic_signs)):
plt.subplot(1, 4, i+1)
plt.axis('off')
plt.imshow(images[traffic_signs[i]])
plt.subplots_adjust(wspace=0.5)
plt.show()
print("shape: {0}, min: {1}, max: {2}".format(images[traffic_signs[i]].shape,
images[traffic_signs[i]].min(),
images[traffic_signs[i]].max()))
Catatan bagaimana Anda menggunakan metode format() pada string "shape: {0}, min: {1}, max: {2}" untuk mengisi argumen {0}, {1}, dan {2} yang Anda tentukan.

Sekarang setelah Anda melihat gambar-gambar terpisah, Anda mungkin juga ingin meninjau kembali histogram yang Anda cetak pada langkah awal eksplorasi data; Anda dapat dengan mudah melakukannya dengan memplot ringkasan dari semua 62 kelas dan satu gambar yang termasuk ke setiap kelas:
# Import the `pyplot` module as `plt`
import matplotlib.pyplot as plt
# Get the unique labels
unique_labels = set(labels)
# Initialize the figure
plt.figure(figsize=(15, 15))
# Set a counter
i = 1
# For each unique label,
for label in unique_labels:
# You pick the first image for each label
image = images[labels.index(label)]
# Define 64 subplots
plt.subplot(8, 8, i)
# Don't include axes
plt.axis('off')
# Add a title to each subplot
plt.title("Label {0} ({1})".format(label, labels.count(label)))
# Add 1 to the counter
i += 1
# And you plot this first image
plt.imshow(image)
# Show the plot
plt.show()
Catatan bahwa meskipun Anda mendefinisikan 64 subplot, tidak semuanya akan menampilkan gambar (karena hanya ada 62 label!). Perhatikan juga bahwa lagi-lagi Anda tidak menyertakan sumbu apa pun agar perhatian pembaca tidak melenceng dari topik utama: rambu lalu lintas!

Seperti yang Anda duga dari histogram di atas, ada jauh lebih banyak rambu lalu lintas dengan label 22, 32, 38, dan 61. Hipotesis ini kini terkonfirmasi dalam plot ini: Anda melihat ada 375 instance dengan label 22, 316 instance dengan label 32, 285 instance dengan label 38, dan terakhir 282 instance dengan label 61.
Salah satu pertanyaan menarik yang dapat Anda ajukan sekarang adalah apakah ada keterkaitan di antara semua instance ini - mungkin semuanya adalah rambu penunjuk?
Mari lihat lebih dekat: Anda melihat bahwa label 22 dan 32 adalah rambu larangan, tetapi label 38 dan 61 masing-masing adalah rambu penunjuk dan rambu prioritas. Ini berarti tidak ada keterkaitan langsung di antara keempatnya, kecuali fakta bahwa setengah dari rambu yang memiliki kehadiran substansial dalam dataset adalah jenis larangan.

Ekstraksi Fitur
Sekarang setelah Anda mengeksplorasi data secara menyeluruh, saatnya mulai bekerja! Mari rekap singkat apa yang Anda temukan agar tidak lupa langkah apa pun dalam manipulasi:
- Ukuran gambar tidak seragam;
- Ada 62 label atau nilai target (karena label Anda dimulai dari 0 dan berakhir di 61);
- Distribusi nilai rambu lalu lintas cukup tidak merata; Tidak ada keterkaitan nyata di antara rambu yang sangat banyak dalam dataset.
Sekarang setelah Anda memiliki gambaran jelas tentang apa yang perlu diperbaiki, Anda dapat mulai memanipulasi data sedemikian rupa agar siap diberikan ke jaringan saraf atau model apa pun yang ingin Anda gunakan. Mari mulai dengan mengekstraksi beberapa fitur – Anda akan mengubah skala gambar, dan mengonversi gambar dalam array images ke grayscale. Anda melakukan konversi warna ini terutama karena warna kurang penting dalam pertanyaan klasifikasi seperti yang Anda coba jawab sekarang. Namun untuk deteksi, warna berperan besar! Jadi dalam kasus tersebut, konversi ini tidak diperlukan!
Mengubah Skala Gambar
Untuk mengatasi perbedaan ukuran gambar, Anda akan mengubah skala gambar; Anda dapat dengan mudah melakukannya dengan bantuan pustaka skimage atau Scikit-Image, yang merupakan kumpulan algoritma untuk pemrosesan gambar.
Dalam kasus ini, modul transform akan berguna karena menyediakan fungsi resize(); Anda akan melihat bahwa Anda menggunakan list comprehension (lagi!) untuk mengubah ukuran setiap gambar menjadi 28 kali 28 piksel. Sekali lagi, Anda melihat cara Anda sebenarnya membentuk list: untuk setiap gambar yang Anda temukan di array images, Anda akan melakukan operasi transformasi yang Anda pinjam dari pustaka skimage. Terakhir, Anda menyimpan hasilnya di variabel images28:
# Import the `transform` module from `skimage`
from skimage import transform
# Rescale the images in the `images` array
images28 = [transform.resize(image, (28, 28)) for image in images]
Ini cukup mudah, bukan?
Catatan bahwa gambar sekarang berdimensi empat: jika Anda mengonversi images28 menjadi array dan menambahkan atribut shape, Anda akan melihat bahwa keluaran menunjukkan dimensi images28 adalah (4575, 28, 28, 3). Gambar berukuran 784 dimensi (karena gambar Anda berukuran 28 kali 28 piksel).
Anda dapat memeriksa hasil operasi pengubahan skala dengan menggunakan kembali kode yang Anda gunakan di atas untuk memplot 4 gambar acak menggunakan variabel traffic_signs. Jangan lupa mengganti semua referensi images menjadi images28.
Lihat hasilnya di sini:

Catatan bahwa karena Anda mengubah skala, nilai min dan max Anda juga berubah; Nilai-nilainya tampaknya berada dalam rentang yang sama sekarang, yang sangat bagus karena Anda tidak harus menormalisasi data!
Konversi Gambar ke Grayscale
Seperti disebutkan pada pengantar bagian ini, warna pada gambar kurang penting saat Anda mencoba menjawab pertanyaan klasifikasi. Itulah mengapa Anda juga akan mengonversi gambar ke grayscale.
Catatan, namun demikian, Anda juga dapat menguji sendiri apa yang terjadi pada hasil akhir model Anda jika Anda tidak melakukan langkah khusus ini.
Sama seperti pada pengubahan skala, Anda kembali dapat mengandalkan pustaka Scikit-Image; Dalam kasus ini, modul color dengan fungsi rgb2gray() yang perlu Anda gunakan untuk mencapai tujuan.
Ini akan mudah dan cepat!
Namun, jangan lupa mengonversi variabel images28 kembali ke array, karena fungsi rgb2gray() memang mengharapkan argumen berupa array.
# Import `rgb2gray` from `skimage.color`
from skimage.color import rgb2gray
# Convert `images28` to an array
images28 = np.array(images28)
# Convert `images28` to grayscale
images28 = rgb2gray(images28)
Periksa ulang hasil konversi grayscale Anda dengan memplot beberapa gambar; Di sini, Anda bisa kembali menggunakan dan sedikit menyesuaikan sebagian kode untuk menampilkan gambar yang sudah disesuaikan:
import matplotlib.pyplot as plt
traffic_signs = [300, 2250, 3650, 4000]
for i in range(len(traffic_signs)):
plt.subplot(1, 4, i+1)
plt.axis('off')
plt.imshow(images28[traffic_signs[i]], cmap="gray")
plt.subplots_adjust(wspace=0.5)
# Show the plot
plt.show()
Catatan bahwa Anda memang harus menentukan color map atau cmap dan menyetelnya ke "gray" untuk memplot gambar dalam grayscale. Itu karena imshow() secara default menggunakan peta warna mirip heatmap. Baca lebih lanjut di sini.

Tip: karena Anda sudah cukup sering menggunakan fungsi ini dalam tutorial, Anda bisa mempertimbangkan untuk menjadikannya sebuah fungsi :)
Dua langkah ini sangat mendasar; Operasi lain yang bisa Anda coba pada data termasuk augmentasi data (rotasi, blur, pergeseran, mengubah kecerahan, dll.). Jika Anda mau, Anda juga bisa menyiapkan seluruh pipeline operasi manipulasi data yang akan memproses gambar Anda.
Deep Learning dengan TensorFlow
Sekarang setelah Anda mengeksplorasi dan memanipulasi data, saatnya membangun arsitektur jaringan saraf Anda dengan bantuan paket TensorFlow!
Pemodelan Jaringan Saraf
Sama seperti yang mungkin sudah Anda lakukan dengan Keras, saatnya membangun jaringan saraf Anda, selapis demi selapis.
Jika belum, impor tensorflow ke ruang kerja Anda dengan alias konvensional tf. Lalu, Anda dapat menginisialisasi Graph dengan bantuan Graph(). Anda menggunakan fungsi ini untuk mendefinisikan komputasi. Catatan bahwa dengan Graph, Anda tidak menghitung apa pun, karena tidak menyimpan nilai. Graph hanya mendefinisikan operasi yang ingin Anda jalankan nanti.
Dalam kasus ini, Anda menyiapkan konteks bawaan dengan as_default(), yang mengembalikan context manager yang menjadikan Graph tertentu ini sebagai graph bawaan. Anda menggunakan metode ini jika ingin membuat beberapa graph dalam proses yang sama: dengan fungsi ini, Anda memiliki graph bawaan global tempat semua operasi akan ditambahkan jika Anda tidak secara eksplisit membuat graph baru.
Berikutnya, Anda siap menambahkan operasi ke graph. Seperti yang mungkin Anda ingat saat bekerja dengan Keras, Anda membangun model, lalu saat mengompilasinya, Anda mendefinisikan fungsi loss, optimizer, dan metrik. Sekarang semua ini terjadi dalam satu langkah saat Anda bekerja dengan TensorFlow:
- Pertama, Anda mendefinisikan placeholder untuk input dan label karena Anda belum memasukkan data “nyata”. Ingat bahwa placeholder adalah nilai yang belum ditetapkan dan akan diinisialisasi oleh sesi saat Anda menjalankannya. Jadi saat Anda akhirnya menjalankan sesi, placeholder ini akan mendapatkan nilai dari dataset yang Anda teruskan ke fungsi
run()! - Kemudian, Anda membangun jaringan. Anda mulai dengan meratakan input dengan bantuan fungsi
flatten(), yang akan memberi Anda array berukuran[None, 784]alih-alih[None, 28, 28], yaitu shape gambar grayscale Anda. - Setelah Anda meratakan input, Anda membuat fully connected layer yang menghasilkan logits berukuran
[None, 62]. Logits adalah fungsi yang beroperasi pada keluaran tak diskalakan dari layer sebelumnya dan menggunakan skala relatif untuk memahami unit yang bersifat linear. - Dengan multilayer perceptron yang telah dibuat, Anda dapat mendefinisikan fungsi loss. Pilihan fungsi loss bergantung pada tugas yang Anda hadapi: dalam kasus ini, Anda menggunakan
sparse_softmax_cross_entropy_with_logits()
- Fungsi ini menghitung sparse softmax cross entropy antara logits dan label. Dengan kata lain, ini mengukur kesalahan probabilitas dalam tugas klasifikasi diskret di mana kelas-kelasnya saling eksklusif. Artinya setiap entri berada tepat di satu kelas. Di sini, sebuah rambu hanya bisa memiliki satu label. Ingat bahwa, sementara regresi digunakan untuk memprediksi nilai kontinu, klasifikasi digunakan untuk memprediksi nilai diskret atau kelas dari titik data. Anda membungkus fungsi ini dengan
reduce_mean(), yang menghitung rata-rata elemen di berbagai dimensi tensor. - Anda juga ingin mendefinisikan optimizer pelatihan; Beberapa algoritma optimasi paling populer adalah Stochastic Gradient Descent (SGD), ADAM, dan RMSprop. Bergantung pada algoritma yang Anda pilih, Anda perlu menyetel parameter tertentu, seperti learning rate atau momentum. Dalam kasus ini, Anda memilih optimizer ADAM, dengan learning rate
0.001. - Terakhir, Anda menginisialisasi operasi untuk dieksekusi sebelum beralih ke pelatihan.
# Import `tensorflow`
import tensorflow as tf
# Initialize placeholders
x = tf.placeholder(dtype = tf.float32, shape = [None, 28, 28])
y = tf.placeholder(dtype = tf.int32, shape = [None])
# Flatten the input data
images_flat = tf.contrib.layers.flatten(x)
# Fully connected layer
logits = tf.contrib.layers.fully_connected(images_flat, 62, tf.nn.relu)
# Define a loss function
loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(labels = y,
logits = logits))
# Define an optimizer
train_op = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)
# Convert logits to label indexes
correct_pred = tf.argmax(logits, 1)
# Define an accuracy metric
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
Anda sekarang telah berhasil membuat jaringan saraf pertama Anda dengan TensorFlow!
Jika Anda mau, Anda juga dapat mencetak nilai (sebagian besar) variabel untuk mendapatkan rekap cepat atau pemeriksaan dari apa yang baru saja Anda tulis:
print("images_flat: ", images_flat)
print("logits: ", logits)
print("loss: ", loss)
print("predicted_labels: ", correct_pred)
Tip: jika Anda melihat kesalahan seperti “module 'pandas' has no attribute 'computation'”, pertimbangkan untuk meningkatkan paket dask dengan menjalankan pip install --upgrade dask di baris perintah Anda. Lihat posting StackOverflow ini untuk informasi lebih lanjut.
Menjalankan Jaringan Saraf
Sekarang setelah Anda membangun model selapis demi selapis, saatnya benar-benar menjalankannya! Untuk melakukannya, Anda pertama-tama perlu menginisialisasi sesi dengan Session() yang dapat Anda beri graph yang Anda definisikan pada bagian sebelumnya. Selanjutnya, Anda dapat menjalankan sesi dengan run(), yang Anda beri operasi terinisialisasi dalam bentuk variabel init yang juga Anda definisikan pada bagian sebelumnya.
Selanjutnya, Anda dapat menggunakan sesi terinisialisasi ini untuk memulai epoch atau loop pelatihan. Dalam kasus ini, Anda memilih 201 karena Anda ingin mencatat loss_value terakhir; Dalam loop, Anda menjalankan sesi dengan optimizer pelatihan dan metrik loss (atau akurasi) yang Anda definisikan di bagian sebelumnya. Anda juga memberikan argumen feed_dict, yang Anda gunakan untuk memberi data ke model. Setelah setiap 10 epoch, Anda akan mendapatkan log yang memberi wawasan lebih lanjut tentang loss atau biaya model.
Seperti yang Anda lihat pada bagian dasar TensorFlow, tidak perlu menutup sesi secara manual; ini dilakukan untuk Anda. Namun, jika Anda ingin mencoba pengaturan berbeda, Anda mungkin perlu melakukannya dengan sess.close() jika Anda mendefinisikan sesi sebagai sess, seperti pada potongan kode di bawah ini:
tf.set_random_seed(1234)
sess = tf.Session()
sess.run(tf.global_variables_initializer())
for i in range(201):
print('EPOCH', i)
_, accuracy_val = sess.run([train_op, accuracy], feed_dict={x: images28, y: labels})
if i % 10 == 0:
print("Loss: ", loss)
print('DONE WITH EPOCH')
Ingat bahwa Anda juga dapat menjalankan potongan kode berikut, tetapi yang ini akan langsung menutup sesi setelahnya, seperti yang Anda lihat pada pengantar tutorial ini:
tf.set_random_seed(1234)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for i in range(201):
_, loss_value = sess.run([train_op, loss], feed_dict={x: images28, y: labels})
if i % 10 == 0:
print("Loss: ", loss)
Catatan bahwa Anda menggunakan global_variables_initializer() karena fungsi initialize_all_variables() sudah deprecated.
Anda sekarang telah berhasil melatih model Anda! Tidak terlalu sulit, bukan?
Mengevaluasi Jaringan Saraf Anda
Anda belum sepenuhnya selesai; Anda masih perlu mengevaluasi jaringan saraf Anda. Dalam kasus ini, Anda sudah bisa mencoba melihat sekilas seberapa baik model Anda bekerja dengan memilih 10 gambar acak dan membandingkan label prediksi dengan label sebenarnya.
Anda bisa mencetaknya terlebih dahulu, tetapi mengapa tidak menggunakan matplotlib untuk memplot rambu lalu lintas itu sendiri dan membuat perbandingan visual?
# Import `matplotlib`
import matplotlib.pyplot as plt
import random
# Pick 10 random images
sample_indexes = random.sample(range(len(images28)), 10)
sample_images = [images28[i] for i in sample_indexes]
sample_labels = [labels[i] for i in sample_indexes]
# Run the "correct_pred" operation
predicted = sess.run([correct_pred], feed_dict={x: sample_images})[0]
# Print the real and predicted labels
print(sample_labels)
print(predicted)
# Display the predictions and the ground truth visually.
fig = plt.figure(figsize=(10, 10))
for i in range(len(sample_images)):
truth = sample_labels[i]
prediction = predicted[i]
plt.subplot(5, 2,1+i)
plt.axis('off')
color='green' if truth == prediction else 'red'
plt.text(40, 10, "Truth: {0}\nPrediction: {1}".format(truth, prediction),
fontsize=12, color=color)
plt.imshow(sample_images[i], cmap="gray")
plt.show()

Namun, hanya melihat gambar acak tidak banyak memberi Anda wawasan tentang seberapa baik model Anda sebenarnya bekerja. Itulah mengapa Anda akan memuat data uji.
Catatan bahwa Anda menggunakan fungsi load_data(), yang Anda definisikan di awal tutorial ini.
# Import `skimage`
from skimage import transform
# Load the test data
test_images, test_labels = load_data(test_data_directory)
# Transform the images to 28 by 28 pixels
test_images28 = [transform.resize(image, (28, 28)) for image in test_images]
# Convert to grayscale
from skimage.color import rgb2gray
test_images28 = rgb2gray(np.array(test_images28))
# Run predictions against the full test set.
predicted = sess.run([correct_pred], feed_dict={x: test_images28})[0]
# Calculate correct matches
match_count = sum([int(y == y_) for y, y_ in zip(test_labels, predicted)])
# Calculate the accuracy
accuracy = match_count / len(test_labels)
# Print the accuracy
print("Accuracy: {:.3f}".format(accuracy))
Ingat untuk menutup sesi dengan sess.close() jika Anda tidak menggunakan with tf.Session() as sess: untuk memulai sesi TensorFlow Anda.
Ke Mana Selanjutnya?
Jika Anda ingin terus bekerja dengan dataset ini dan model yang telah Anda susun dalam tutorial ini, coba hal-hal berikut:
- Terapkan regularized LDA pada data sebelum Anda memberikannya ke model. Ini adalah saran yang berasal dari salah satu makalah asli, yang ditulis oleh para peneliti yang mengumpulkan dan menganalisis dataset ini.
- Anda juga bisa, seperti disebutkan dalam tutorial, melihat beberapa operasi augmentasi data lain yang dapat Anda lakukan pada gambar rambu lalu lintas. Selain itu, Anda juga bisa mencoba menyetel jaringan ini lebih lanjut; Yang Anda buat sekarang cukup sederhana.
- Early stopping: Lacak error pelatihan dan pengujian saat Anda melatih jaringan saraf. Hentikan pelatihan ketika kedua error turun lalu tiba-tiba naik kembali - ini pertanda jaringan saraf mulai overfit pada data pelatihan.
- Cobalah berbagai optimizer.
Pastikan untuk melihat buku Machine Learning With TensorFlow karya Nishant Shukla.
Tip lihat juga TensorFlow Playground dan TensorBoard.
Jika Anda ingin terus bekerja dengan gambar, pastikan untuk melihat tutorial scikit-learn dari DataCamp, yang membahas dataset MNIST dengan bantuan PCA, K-Means, dan Support Vector Machines (SVM). Atau lihat tutorial lain seperti yang ini yang menggunakan dataset rambu lalu lintas Belgia.
