Jaringan Saraf Konvolusi (CNN)

Lihat di TensorFlow.org Jalankan di Google Colab Lihat sumber di GitHub Unduh buku catatan

Tutorial ini mendemonstrasikan pelatihan Convolutional Neural Network (CNN) sederhana untuk mengklasifikasikan citra CIFAR . Karena tutorial ini menggunakan Keras Sequential API , membuat dan melatih model Anda hanya membutuhkan beberapa baris kode.

Impor TensorFlow

import tensorflow as tf

from tensorflow.keras import datasets, layers, models
import matplotlib.pyplot as plt

Unduh dan siapkan kumpulan data CIFAR10

Dataset CIFAR10 berisi 60.000 gambar berwarna di 10 kelas, dengan 6.000 gambar di setiap kelas. Dataset dibagi menjadi 50.000 gambar pelatihan dan 10.000 gambar pengujian. Kelas-kelas itu saling eksklusif dan tidak ada tumpang tindih di antara mereka.

(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()

# Normalize pixel values to be between 0 and 1
train_images, test_images = train_images / 255.0, test_images / 255.0
Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
170500096/170498071 [==============================] - 11s 0us/step
170508288/170498071 [==============================] - 11s 0us/step

Verifikasi datanya

Untuk memverifikasi bahwa dataset terlihat benar, mari plot 25 gambar pertama dari set pelatihan dan tampilkan nama kelas di bawah setiap gambar:

class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
               'dog', 'frog', 'horse', 'ship', 'truck']

plt.figure(figsize=(10,10))
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(train_images[i])
    # The CIFAR labels happen to be arrays, 
    # which is why you need the extra index
    plt.xlabel(class_names[train_labels[i][0]])
plt.show()

png

Buat basis konvolusi

6 baris kode di bawah ini mendefinisikan basis konvolusi menggunakan pola umum: tumpukan lapisan Conv2D dan MaxPooling2D .

Sebagai input, CNN mengambil tensor bentuk (image_height, image_width, color_channels), mengabaikan ukuran batch. Jika Anda baru mengenal dimensi ini, color_channels mengacu pada (R,G,B). Dalam contoh ini, Anda akan mengonfigurasi CNN untuk memproses input bentuk (32, 32, 3), yang merupakan format gambar CIFAR. Anda dapat melakukan ini dengan meneruskan argumen input_shape ke lapisan pertama Anda.

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))

Mari kita tampilkan arsitektur model Anda sejauh ini:

model.summary()
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d (Conv2D)             (None, 30, 30, 32)        896       
                                                                 
 max_pooling2d (MaxPooling2D  (None, 15, 15, 32)       0         
 )                                                               
                                                                 
 conv2d_1 (Conv2D)           (None, 13, 13, 64)        18496     
                                                                 
 max_pooling2d_1 (MaxPooling  (None, 6, 6, 64)         0         
 2D)                                                             
                                                                 
 conv2d_2 (Conv2D)           (None, 4, 4, 64)          36928     
                                                                 
=================================================================
Total params: 56,320
Trainable params: 56,320
Non-trainable params: 0
_________________________________________________________________

Di atas, Anda dapat melihat bahwa output dari setiap lapisan Conv2D dan MaxPooling2D adalah bentuk tensor 3D (tinggi, lebar, saluran). Dimensi lebar dan tinggi cenderung menyusut saat Anda masuk lebih dalam ke jaringan. Jumlah saluran keluaran untuk setiap lapisan Conv2D dikendalikan oleh argumen pertama (misalnya, 32 atau 64). Biasanya, karena lebar dan tinggi menyusut, Anda dapat (secara komputasi) menambahkan lebih banyak saluran keluaran di setiap lapisan Conv2D.

Tambahkan lapisan padat di atas

Untuk melengkapi model, Anda akan memasukkan tensor keluaran terakhir dari basis konvolusi (berbentuk (4, 4, 64)) ke dalam satu atau lebih lapisan Dense untuk melakukan klasifikasi. Lapisan padat mengambil vektor sebagai input (yaitu 1D), sedangkan output saat ini adalah tensor 3D. Pertama, Anda akan meratakan (atau membuka gulungan) output 3D menjadi 1D, lalu menambahkan satu atau lebih lapisan Padat di atasnya. CIFAR memiliki 10 kelas keluaran, jadi Anda menggunakan lapisan padat akhir dengan 10 keluaran.

model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10))

Inilah arsitektur lengkap model Anda:

model.summary()
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d (Conv2D)             (None, 30, 30, 32)        896       
                                                                 
 max_pooling2d (MaxPooling2D  (None, 15, 15, 32)       0         
 )                                                               
                                                                 
 conv2d_1 (Conv2D)           (None, 13, 13, 64)        18496     
                                                                 
 max_pooling2d_1 (MaxPooling  (None, 6, 6, 64)         0         
 2D)                                                             
                                                                 
 conv2d_2 (Conv2D)           (None, 4, 4, 64)          36928     
                                                                 
 flatten (Flatten)           (None, 1024)              0         
                                                                 
 dense (Dense)               (None, 64)                65600     
                                                                 
 dense_1 (Dense)             (None, 10)                650       
                                                                 
=================================================================
Total params: 122,570
Trainable params: 122,570
Non-trainable params: 0
_________________________________________________________________

Ringkasan jaringan menunjukkan bahwa (4, 4, 64) keluaran diratakan menjadi vektor bentuk (1024) sebelum melewati dua lapisan Padat.

Kompilasi dan latih modelnya

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

history = model.fit(train_images, train_labels, epochs=10, 
                    validation_data=(test_images, test_labels))
Epoch 1/10
1563/1563 [==============================] - 8s 4ms/step - loss: 1.4971 - accuracy: 0.4553 - val_loss: 1.2659 - val_accuracy: 0.5492
Epoch 2/10
1563/1563 [==============================] - 6s 4ms/step - loss: 1.1424 - accuracy: 0.5966 - val_loss: 1.1025 - val_accuracy: 0.6098
Epoch 3/10
1563/1563 [==============================] - 6s 4ms/step - loss: 0.9885 - accuracy: 0.6539 - val_loss: 0.9557 - val_accuracy: 0.6629
Epoch 4/10
1563/1563 [==============================] - 6s 4ms/step - loss: 0.8932 - accuracy: 0.6878 - val_loss: 0.8924 - val_accuracy: 0.6935
Epoch 5/10
1563/1563 [==============================] - 6s 4ms/step - loss: 0.8222 - accuracy: 0.7130 - val_loss: 0.8679 - val_accuracy: 0.7025
Epoch 6/10
1563/1563 [==============================] - 6s 4ms/step - loss: 0.7663 - accuracy: 0.7323 - val_loss: 0.9336 - val_accuracy: 0.6819
Epoch 7/10
1563/1563 [==============================] - 6s 4ms/step - loss: 0.7224 - accuracy: 0.7466 - val_loss: 0.8546 - val_accuracy: 0.7086
Epoch 8/10
1563/1563 [==============================] - 6s 4ms/step - loss: 0.6726 - accuracy: 0.7611 - val_loss: 0.8777 - val_accuracy: 0.7068
Epoch 9/10
1563/1563 [==============================] - 6s 4ms/step - loss: 0.6372 - accuracy: 0.7760 - val_loss: 0.8410 - val_accuracy: 0.7179
Epoch 10/10
1563/1563 [==============================] - 6s 4ms/step - loss: 0.6024 - accuracy: 0.7875 - val_loss: 0.8475 - val_accuracy: 0.7192

Evaluasi modelnya

plt.plot(history.history['accuracy'], label='accuracy')
plt.plot(history.history['val_accuracy'], label = 'val_accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.ylim([0.5, 1])
plt.legend(loc='lower right')

test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=2)
313/313 - 1s - loss: 0.8475 - accuracy: 0.7192 - 634ms/epoch - 2ms/step

png

print(test_acc)
0.7192000150680542

CNN sederhana Anda telah mencapai akurasi pengujian lebih dari 70%. Tidak buruk untuk beberapa baris kode! Untuk gaya CNN lainnya, lihat contoh panduan memulai TensorFlow 2 untuk pakar yang menggunakan API subkelas Keras dan tf.GradientTape .