DEV Community

Suth
Suth

Posted on

การจำแนกภาพ CIFAR-10 ใน TensorFlow

ในบทความนี้เราจะพูดถึงวิธีการจำแนกภาพโดยใช้ TensorFlow ในการจำแนก โดยเราจะทำการจำแนกภาพตามหมวดหมู่ของคลาสที่เกี่ยวข้องกับ CIFAR-10 Dataset โดยจะมีภาพที่แตกต่างกัน 10 กลุ่ม มีรวมกันทั้งหมด 60,000 ภาพ โดยใน 10 กลุ่มแบ่งออกเป็น Airplane, Automobile, Bird, Cat, Deer, Dog, Frog, Horse, Ship, Truck และทุกภาพมีขนาด 32×32 รวมทั้งมีทั้งหมด 50,000 ภาพสำหรับใช้ในการฝึกและอีก 10,000 ภาพที่ใช้สำหรับการทดสอบ
โดยเราจะใช้ tensorflow's keras API เพื่อสร้างโมเดล และแนะนำว่าให้ใช้ GPU หรือ Google colab notebooks ช่วยในการทำงาน

ขั้นตอนทำ

เริ่มจากการนำไลบรารีและโมดูลที่จำเข้าไปใน Google Colab

import tensorflow as tf 
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.layers import Input, Conv2D, Dense, Flatten, Dropout
from tensorflow.keras.layers import GlobalMaxPooling2D, MaxPooling2D
from tensorflow.keras.layers import BatchNormalization
from tensorflow.keras.models import Model
Enter fullscreen mode Exit fullscreen mode

หลังจากเรานำไลบรารีและโมดูลที่จำเข้าไปใน Google Colab แล้วเราจะมาทำการโหลดข้อมูล CIFAR-10 ที่มีอยู่ใน tensorflow keras API โดยใช้ tensorflow.keras.datasets.cifar10 แล้วจะแบ่งเป็นชุดฝึกและชุดทดสอบโดยใช้ฟังก์ชัน load_data()

cifar10 = tf.keras.datasets.cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
print(x_train.shape, y_train.shape, x_test.shape, y_test.shape)
Enter fullscreen mode Exit fullscreen mode

ได้ออกมาเป็นแบบนี้
Image description
โดยเราจะเห็นได้ว่ามีภาพที่ใช้ฝึก 50,000 และภาพทดสอบ 10,000 ภาพตามที่ระบุไว้ในตอนแรก โดยทุกภาพจะมีขนาด 32x32 และมีช่องสี 3 นั่นคือเป็นภาพสี นอกจากนี้ยังเห็นได้ว่ามีการกำหนดป้ายชื่อเพียงหนึ่งป้ายชื่อต่อภาพเท่านั้น

ในตอนนี้เรามีข้อมูลที่ใช้ในการจำแนกภาพแล้ว แต่ยังต้องทำการประมวลผลข้อมูลก่อนโดยเราจะทำการลดค่าพิกเซลจากช่วง 1-256 ให้อยู่ในค่าระหว่าง 0 และ 1 เพื่อให้การฝึกมีประสิทธิภาพ และเราจะทำการยุบ (flatten) ค่าป้ายของภาพโดยใช้ฟังก์ชัน flatten() ให้เป็นแถวด้วย

x_train, x_test = x_train / 255.0, x_test / 255.0

y_train, y_test = y_train.flatten(), y_test.flatten()
Enter fullscreen mode Exit fullscreen mode

ตอนนี้เราจะมาดูผลลัพธ์กันว่าภาพเป็นอย่างไรบ้างโดยใช้ฟังก์ชัน subplot() จาก matplotlib และวนลูปผ่านภาพ 25 ภาพแรกจากชุดข้อมูลการฝึกของเรา

fig, ax = plt.subplots(5, 5)
k = 0

for i in range(5):
    for j in range(5):
        ax[i][j].imshow(x_train[k], aspect='auto')
        k += 1

plt.show()
Enter fullscreen mode Exit fullscreen mode

ต่อจากนี้เราจะเริ่มทำการสร้างโมเดลกัน โดยเราจะใช้Convolution Neural Network หรือ CNN , convolution ที่เป็น Conv2d , pooling , normalization methods ในส่วนท้ายก็จะส่งผ่านไปยัง dense และ dense ซึ่งเป็นการเอาต์พุต เราใช้ activation function ชื่อ "relu" ในการเอาต์พุตและใช้ฟังก์ชัน "softmax"

นอกจากนี้เรายังควรระบุโครงสร้างของโมเดลที่เราจะสร้าง เช่น จำนวนชั้นของ convolution, ขนาดของ kernel, จำนวนชั้นที่ใช้ในการปรับปรุงความลึกของชั้น, และจำนวนหน่วยในชั้นที่เชื่อมต่อแบบ fully connected ตามลำดับ ดังนั้นเราสามารถเริ่มต้นการสร้างโมเดลด้วยโค้ดต่อไปนี้

K = len(set(y_train))

print("number of classes:", K)

i = Input(shape=x_train[0].shape)
x = Conv2D(32, (3, 3), activation='relu', padding='same')(i)
x = BatchNormalization()(x)
x = Conv2D(32, (3, 3), activation='relu', padding='same')(x)
x = BatchNormalization()(x)
x = MaxPooling2D((2, 2))(x)

x = Conv2D(64, (3, 3), activation='relu', padding='same')(x)
x = BatchNormalization()(x)
x = Conv2D(64, (3, 3), activation='relu', padding='same')(x)
x = BatchNormalization()(x)
x = MaxPooling2D((2, 2))(x)

x = Conv2D(128, (3, 3), activation='relu', padding='same')(x)
x = BatchNormalization()(x)
x = Conv2D(128, (3, 3), activation='relu', padding='same')(x)
x = BatchNormalization()(x)
x = MaxPooling2D((2, 2))(x)

x = Flatten()(x)
x = Dropout(0.2)(x)

x = Dense(1024, activation='relu')(x)
x = Dropout(0.2)(x)

x = Dense(K, activation='softmax')(x)

model = Model(i, x)

model.summary()
Enter fullscreen mode Exit fullscreen mode

ผลลัพธ์
Image description
จากนั้นเราจะทำการคอมไพล์มัน โดยใช้ฟังก์ชัน model.compile() เพื่อคอมไพล์

model.compile(optimizer='adam',
            loss='sparse_categorical_crossentropy',
            metrics=['accuracy'])
Enter fullscreen mode Exit fullscreen mode

เมื่อคอมไพล์เสร็จก็จะมาถึงการฝึกโมเดลของเรา โดยเราจะใช้ model.fit() ทั้งหมดเข้าไปในโมเดล โดยเราจะฝึกโมเดลจนกระทั่ง 10 epochs แต่จริงแล้วเราจะฝึกโมเดลกี่ epochs ก็ได้ตามที่ต้องการ

r = model.fit(
x_train, y_train, validation_data=(x_test, y_test), epochs=10)
Enter fullscreen mode Exit fullscreen mode

เมื่อโมเดลเริ่มฝึกการฝึกจะมีลักษณะนี้
Image description
หลังจากเราฝึกโมเดลของเราจนเสร็จแล้ว มันก็สามารถทำได้เลยแต่หากอยากได้ความแม่นยำมากขึ้นเราสามารถเพิ่มการเพิ่มข้อมูลในข้อมูลของเราแล้วฝึกโมเดลอีกครั้ง โดยการเรียกใช้ model.fit() อีกครั้งบนข้อมูลที่เพิ่มขึ้น การเพิ่มข้อมูลที่เพิ่มขึ้นจะทำให้การฝึกทำงานต่อไปจากที่จบลง โดยเราจะให้ข้อมูลของเราใน batch size ของ 32 และเราจะย้ายช่วงของความกว้างและความสูงไป 0.1 และพลิกภาพตามแนวนอน จากนั้นเรียก model.fit อีกครั้ง

batch_size = 32
data_generator = tf.keras.preprocessing.image.ImageDataGenerator(
width_shift_range=0.1, height_shift_range=0.1, horizontal_flip=True)

train_generator = data_generator.flow(x_train, y_train, batch_size)
steps_per_epoch = x_train.shape[0] // batch_size

r = model.fit(train_generator, validation_data=(x_test, y_test),
            steps_per_epoch=steps_per_epoch, epochs=10)
Enter fullscreen mode Exit fullscreen mode

Image description
เราจะมาดูความแม่นยำกันด้วยโค้ดนี้

plt.plot(r.history['accuracy'], label='acc', color='red')
plt.plot(r.history['val_accuracy'], label='val_acc', color='green')
plt.legend()
Enter fullscreen mode Exit fullscreen mode

Image description
ต่อมาเราจะมาทำการจำแนกภาพโดยใช้ฟังก์ชัน model.predict() ก่อนที่จะส่งภาพไปยังโมเดลของเรา เราจำเป็นต้องลดค่าพิกเซลให้อยู่ในช่วงระหว่าง 0 และ 1 และเปลี่ยนรูปร่างให้เป็น (1,32,32,3) เพราะโมเดลของเราต้องการข้อมูลนำเข้าในรูปแบบนี้เท่านั้น แม้ว่าเราจะใช้ภาพจากชุดข้อมูลก็ตาม ภาพนั้นอยู่ในรูปแบบพิกเซลที่ลดลงแล้ว แต่เราต้อง reshape มันอีกครั้งเพื่อให้เป็น (1,32,32,3) โดยใช้ฟังก์ชัน reshape() เราสามารถเปรียบเทียบผลลัพธ์ที่ทำนายและผลลัพธ์ต้นฉบับได้ เนื่องจากเรากำลังใช้ข้อมูลจากชุดข้อมูลใหม่ ตามโค้ดด้านล่างนี้

labels = '''airplane automobile bird cat deerdog frog horseship truck'''.split()

image_number = 0

plt.imshow(x_test[image_number])

n = np.array(x_test[image_number])

p = n.reshape(1, 32, 32, 3)

predicted_label = labels[model.predict(p).argmax()]

original_label = labels[y_test[image_number]]

print("Original label is {} and predicted label is {}".format(
    original_label, predicted_label))
Enter fullscreen mode Exit fullscreen mode

Image description
เราได้ผลลัพธ์การจำแนกภาพเป็นแมว และภาพจริงๆก็เป็นแมวถูกต้องตามที่เราจำแนกออกมา

แต่ก็จะมีภาพที่มีการจำแนกที่ผิดอยู่เช่นกันอย่างภาพที่ 5722
Image description
โดยในภาพนี้ภาพจริงจะเป็ยภาพของเครื่องบิน แต่ถูกจำแนกเป็นนกนั้นเอง

สรุปผล
ผลลัพธ์ที่ได้คือโมเดลที่สามารถจำแนกประเภทของภาพในชุดข้อมูล CIFAR-10 ได้อย่างมีประสิทธิภาพ โดยมีความแม่นยำที่สูงและมีการพยากรณ์ที่ถูกต้องในหลายๆ คลาส อย่างไรก็ตาม ยังมีการใช้งานการเพิ่มข้อมูลเพื่อเพิ่มประสิทธิภาพของโมเดลได้ เช่นการใช้งาน data augmentation หรือการปรับแก้โครงสร้างของโมเดล เพื่อให้มีประสิทธิภาพมากยิ่งขึ้นในการจำแนกประเภทของภาพในอนาคต

References
https://www.geeksforgeeks.org/cifar-10-image-classification-in-tensorflow/

Top comments (0)