شبکه عصبی کانولوشنال (CNN)

مشاهده در TensorFlow.org در Google Colab اجرا شود مشاهده منبع در GitHub دانلود دفترچه یادداشت

این آموزش آموزش یک شبکه عصبی کانولوشنال ساده (CNN) را برای طبقه بندی تصاویر CIFAR نشان می دهد . از آنجایی که این آموزش از Keras Sequential API استفاده می کند، ایجاد و آموزش مدل شما تنها به چند خط کد نیاز دارد.

وارد کردن TensorFlow

import tensorflow as tf

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

مجموعه داده CIFAR10 را دانلود و آماده کنید

مجموعه داده CIFAR10 شامل 60000 تصویر رنگی در 10 کلاس با 6000 تصویر در هر کلاس است. مجموعه داده به 50000 تصویر آموزشی و 10000 تصویر آزمایشی تقسیم شده است. کلاس ها متقابل هستند و هیچ تداخلی بین آنها وجود ندارد.

(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

داده ها را تأیید کنید

برای تأیید درست به نظر رسیدن مجموعه داده، بیایید 25 تصویر اول از مجموعه آموزشی را رسم کنیم و نام کلاس را در زیر هر تصویر نمایش دهیم:

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

پایه کانولوشن را ایجاد کنید

6 خط کد زیر پایه کانولوشنال را با استفاده از یک الگوی مشترک تعریف می کند: پشته ای از لایه های Conv2D و MaxPooling2D .

به عنوان ورودی، یک CNN تانسورهای شکل (ارتفاع_تصویر، پهنای_تصویر، رنگ_کانال ها) را می گیرد و اندازه دسته را نادیده می گیرد. اگر در این ابعاد تازه کار هستید، color_channels به (R,G,B) اشاره دارد. در این مثال، شما CNN خود را برای پردازش ورودی های شکل (32، 32، 3)، که فرمت تصاویر CIFAR است، پیکربندی می کنید. شما می توانید این کار را با ارسال آرگومان input_shape به لایه اول خود انجام دهید.

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

بیایید معماری مدل شما را تا کنون نمایش دهیم:

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
_________________________________________________________________

در بالا، می بینید که خروجی هر لایه Conv2D و MaxPooling2D یک تانسور سه بعدی شکل (ارتفاع، عرض، کانال ها) است. ابعاد عرض و ارتفاع با رفتن به عمق شبکه کاهش می یابد. تعداد کانال های خروجی برای هر لایه Conv2D توسط اولین آرگومان کنترل می شود (مثلاً 32 یا 64). به طور معمول، با کوچک شدن عرض و ارتفاع، می توانید (از لحاظ محاسباتی) کانال های خروجی بیشتری را در هر لایه Conv2D اضافه کنید.

لایه های متراکم را در بالا اضافه کنید

برای تکمیل مدل، آخرین تانسور خروجی را از پایه کانولوشن (شکل (4، 4، 64)) به یک یا چند لایه متراکم برای انجام طبقه‌بندی تغذیه می‌کنید. لایه های متراکم بردارها را به عنوان ورودی می گیرند (که 1 بعدی هستند)، در حالی که خروجی جریان یک تانسور سه بعدی است. ابتدا خروجی 3 بعدی را صاف می کنید (یا باز می کنید) و سپس یک یا چند لایه متراکم را در بالا اضافه می کنید. CIFAR دارای 10 کلاس خروجی است، بنابراین شما از یک لایه متراکم نهایی با 10 خروجی استفاده می کنید.

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

در اینجا معماری کامل مدل شما آمده است:

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
_________________________________________________________________

خلاصه شبکه نشان می دهد که (4، 4، 64) خروجی ها قبل از عبور از دو لایه متراکم به بردارهای شکل (1024) مسطح شدند.

کامپایل و آموزش مدل

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

مدل را ارزیابی کنید

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 ساده شما به دقت تست بیش از 70 درصد دست یافته است. برای چند خط کد بد نیست! برای یک سبک دیگر CNN، نمونه راه اندازی سریع TensorFlow 2 را برای متخصصان بررسی کنید که از API فرعی Keras و tf.GradientTape استفاده می کند.