Mạng thần kinh hợp hiến (CNN)

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHub Tải xuống sổ ghi chép

Hướng dẫn này trình bày việc đào tạo Mạng nơron hợp hiến (CNN) đơn giản để phân loại hình ảnh CIFAR . Vì hướng dẫn này sử dụng Keras Sequential API , nên việc tạo và đào tạo mô hình của bạn sẽ chỉ mất một vài dòng mã.

Nhập TensorFlow

import tensorflow as tf

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

Tải xuống và chuẩn bị tập dữ liệu CIFAR10

Bộ dữ liệu CIFAR10 chứa 60.000 hình ảnh màu trong 10 lớp, với 6.000 hình ảnh trong mỗi lớp. Bộ dữ liệu được chia thành 50.000 hình ảnh đào tạo và 10.000 hình ảnh thử nghiệm. Các lớp loại trừ lẫn nhau và không có sự chồng chéo giữa chúng.

(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

Xác minh dữ liệu

Để xác minh rằng tập dữ liệu có đúng không, hãy vẽ biểu đồ 25 hình ảnh đầu tiên từ tập hợp đào tạo và hiển thị tên lớp bên dưới mỗi hình ảnh:

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

Tạo cơ sở phức hợp

6 dòng mã bên dưới xác định cơ sở tích chập bằng cách sử dụng một mẫu chung: chồng các lớp Conv2DMaxPooling2D .

Khi đầu vào, một CNN có hàng chục hình dạng (chiều cao hình ảnh, chiều rộng hình ảnh, kênh màu), bỏ qua kích thước lô. Nếu bạn chưa quen với các thứ nguyên này, color_channels đề cập đến (R, G, B). Trong ví dụ này, bạn sẽ định cấu hình CNN của mình để xử lý đầu vào của hình dạng (32, 32, 3), là định dạng của hình ảnh CIFAR. Bạn có thể thực hiện việc này bằng cách chuyển đối số input_shape vào lớp đầu tiên của mình.

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'))

Hãy hiển thị kiến ​​trúc của mô hình của bạn cho đến nay:

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
_________________________________________________________________

Ở trên, bạn có thể thấy rằng đầu ra của mọi lớp Conv2D và MaxPooling2D là một hình dạng 3D (chiều cao, chiều rộng, kênh). Kích thước chiều rộng và chiều cao có xu hướng thu hẹp khi bạn đi sâu hơn vào mạng. Số lượng kênh đầu ra cho mỗi lớp Conv2D được điều khiển bởi đối số đầu tiên (ví dụ: 32 hoặc 64). Thông thường, khi chiều rộng và chiều cao thu hẹp lại, bạn có thể đủ khả năng (về mặt tính toán) để thêm nhiều kênh đầu ra hơn trong mỗi lớp Conv2D.

Thêm các lớp dày đặc lên trên

Để hoàn thành mô hình, bạn sẽ cấp tensor đầu ra cuối cùng từ cơ sở tích chập (có hình dạng (4, 4, 64)) thành một hoặc nhiều lớp dày đặc để thực hiện phân loại. Các lớp dày đặc lấy vectơ làm đầu vào (là 1D), trong khi đầu ra hiện tại là tensor 3D. Đầu tiên, bạn sẽ làm phẳng (hoặc mở cuộn) đầu ra 3D thành 1D, sau đó thêm một hoặc nhiều lớp dày đặc lên trên. CIFAR có 10 lớp đầu ra, vì vậy bạn sử dụng lớp Dày cuối cùng với 10 đầu ra.

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

Đây là kiến ​​trúc hoàn chỉnh của mô hình của bạn:

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
_________________________________________________________________

Tóm tắt mạng cho thấy rằng (4, 4, 64) đầu ra đã được làm phẳng thành các vectơ có hình dạng (1024) trước khi đi qua hai lớp dày đặc.

Biên dịch và đào tạo mô hình

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

Đánh giá mô hình

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 đơn giản của bạn đã đạt được độ chính xác trong bài kiểm tra hơn 70%. Không tệ cho một vài dòng mã! Đối với một phong cách CNN khác, hãy xem phần khởi động nhanh TensorFlow 2 để biết ví dụ về các chuyên gia sử dụng API phân lớp Keras và tf.GradientTape .