Visualizing Kernels and Feature Maps in Deep Learning Model (CNN)

Original article was published by Bringbang_ on Deep Learning on Medium


Visualizing Kernels and Feature Maps in Deep Learning Model (CNN)

วันนี้เรากลับมาอีกครั้งกับ เรื่องแนวคิดของ CNN และทำ Workshop เพื่อดึง Kernel และ Feature Map กันครับ

2D Convolutions Concept

Picture By Medium

2D Convolution เป็นการนำ Matrix ขนาดเล็ก ของ Weight หรือที่เรียกว่า Kernel มา Slide ไปบน 2D Input Image (สีฟ้าด้านบนซ้ายมือ) โดยขณะที่มีการทาบ Kernel บน Input Image มันจะคูณค่าแต่ละ Pixel ของ Input Image กับ Kernel แล้วนำผลลัพธ์ทั้งหมดมาบวกกันเป็น 1 จุด Pixel ของ Feature Map (สีเขียวขวามือ)

2D Convolution ที่มีการสร้าง Feature Map ขึ้นมาด้วยการนำ Kernel Slide ไปบน Input Image จะใช้ Parameter น้อยกว่า Fully Connected Layer

โดยจากตัวอย่าง ในการนำภาพขนาด 5×5 Pixel เข้า Model, 2D Convolution Layer จะใช้จำนวน Parameter เท่ากับขนาดของ Kernel คือ 3×3 = 9 Parameter ขณะที่ถ้าเป็น Fully Connected Layer จะใช้จำนวน Parameter เท่ากับขนาดของ Input Image x 9 = 5x5x9 = 225 Parameter!

Striding

กา Striding เป็นกระบวนการในการทำ Convolution โดยการเลื่อนแผ่น Kernel ไปบน Input Image ซึ่งโดย Default ของ Convolution แล้ว Stride จะมีค่าเท่ากับ 1 คือจะมีการเลื่อน Kernel ไปบน Input Image ครั้งละ 1 Pixel

เราสามารถลดขนาดของภาพที่แต่ละ Pixel มีความสัมพันธ์กันในเชิงพื้นที่ได้โดยการเพิ่มค่า Stride ซึ่งเมื่อมีการกำหนดค่า Stride มากขึ้น จะทำให้การเลื่อมกันของ Kernel ตอนที่มีการทาบกับ Input Image และขนาดของ Feature Map ลดลง

เมื่อกำหนด Stride เท่ากับ 2 แล้ว Kernel ขนาด 3×3 จะถูก Slide ข้าม Pixel ของ Input Image ขนาด 5×5 ทีละ 2 Pixel ทำให้ได้ Feature Map ขนาด 2×2 ดังภาพด้านล่าง

Picture by Stackexchange

Pooling

นอกจากการลดขนาดของภาพด้วยการเพิ่มค่า Stride โดยการ Slide Kernel ข้าม Pixel ของ Input Image ตามระยะทางที่กำหนดแล้ว ยังมีอีกวิธีหนึ่งในการลดขนาดของภาพ คือการทำ Max Pooling หรือ Average Pooling โดย Pooling จะเป็นกระบวนการทำงานภายนอก CNN Layer

Max Pooling หรือ Average Pooling จะเป็นการเลือกตัวแทนของภาพด้วยการหาค่ามากที่สุด หรือค่าเฉลี่ยจาก Pixel ใน Window ตามขนาดที่กำหนด เช่น ขนาด 2×2 ซึ่งจะทำให้มีการลดขนาดของภาพลงได้ครึ่งหนึ่งดังตัวอย่างด้านบน

Multi-channel

อย่างไรก็ตาม ในตัวอย่างที่ผ่านมาจะเป็นการจัดการกับ Input Image แบบ 1 Channel เช่น ภาพแบบ Grayscale แต่บ่อยครั้งที่ Input Image ของเราจะเป็นภาพสี แบบ 3 Channel (โดยทั่วไปจำนวน Channel ของ Input Image จะเพิ่มขึ้นเมื่อมันถูกส่งเข้าสู่ชั้น CNN Layer ที่ลึกขึ้น)

Picture by Wikiland

เพื่อจะจัดการกับ Input Image แบบ 3 Channel อย่างเช่นภาพสีในระบบ RGB เราจะต้องใช้ Kernel จำนวน 3 ตัว ในการ Slide ไปบน Input Image แต่ละ Channel ซึ่งเราเรียก Kernel ทั้ง 3 ตัวว่า Filter (ในที่นี้ 1 Filter ประกอบด้วย Kernel 3 Kernel)

Feature Map แต่ละ Version ขนาด 3×3 ที่เกิดจากการ Slide Kernel ไปบน Input Channel ขนาด 5×5 จะถูกนำมารวมกันเป็น Output Channel 1 Channel เพื่อจะส่งต่อไปยัง Neural Network Layer ถัดไป

ซึ่ง Output Channel จะถูกนำมาบวกกับ Bias ในขั้นตอนสุดท้ายของกระบวนการทำ Convolution

เพื่อจะสร้าง Output Channel 1 Channel ดังภาพด้านบน เราจะต้องใช้ Filter 1 Filter ซึ่งแต่ละ Filter ก็จะประกอบด้วยจำนวน Kernel 3 Kernel ดังนั้นในกรณีที่ต้องการสร้าง Output Channel หลาย Channel เราจะต้องมีจำนวน Filter หลาย Filter ครับ

Visualizing CNN

สำหรับผู้อ่านที่มี GPU สามารถ Config การใช้งาน ด้วยคำสั่งต่อไปนี้

Import Library ที่จำเป็น

ต่อไปจะทำการเอาภาพมาทำการสร้าง Model กันครับ ~

แปลงระบบสีจาก BGR ซึ่งเป็นค่า Default ของ OpenCV Library เป็น RGB

แล้วมาทำ Plot ภาพกันครับ~

Create a Model with 2D CNN Layer

นิยาม Model แบบ 2D Convolution โดยรับ Input Image ขนาด 242*203 Pixel แบบ 3 Channel โดยมี Filter ขนาด 3×3 จำนวน 3 Filter เพื่อนำไป Slide บน Input Image ของแต่ละ Channel

จากภาพด้านบน Model ของเราจะมีจำนวน Parameter เท่ากับ (Filter + Bias) 3x3x3x3 + 3 = 84 Parameter

model = Sequential()
model.add(Conv2D(3,(3,3),input_shape=pic.shape))
model.summary()

ขยายมิติของภาพจาก 3 มิติเป็น 4 มิติ เพื่อเตรียมนำเข้า Predict Function

pic_batch = np.expand_dims(pic,axis=0)
pic_batch.shape

Predict Model โดยใช้ค่า Weight และ Bias แบบสุ่มในตอนเริ่มต้น โดยยังไม่มีการ Train Model

เนื่องจากเรามีการนิยาม Model โดยกำหนดจำนวน Filter ไว้ที่ 3 Filter ดังนั้นจึงทำให้ได้ Output Channel ขนาด 240×206 ทั้งหมด 3 Channel ซึ่งขนาดของ Output Channel จะลดลงจากเดิม 242×208 Pixel เนื่องมาจาก มีการ Slide Kernel ขนาด 3×3 ไปบน Input Image โดยไม่มีการทำ Padding

นิยาม visualize_pic Function ที่รับภาพเป็น Matrix, ขยายภาพเป็น 4 มิติ แล้ว Predict ภาพ ก่อนจะหดให้เหลือ 3 มิติเท่าเดิมเพื่อจะ Plot ภาพต่อไป

def visualize_pic(model, pic):
pic_batch = np.expand_dims(pic,axis=0)
conv_pic = model.predict(pic_batch)
conv_pic = np.squeeze(conv_pic, axis=0)
print(conv_pic.shape)
conv_pic = cv2.cvtColor(conv_pic, cv2.COLOR_RGB2BGR)
plt.imshow(conv_pic)

Plot ภาพกันครับ~

นิยาม Model แบบ 2D Convolution โดยรับ Input Image ขนาด 240×206 Pixel แบบ 3 Channel โดยมี Filter ขนาด 10×10 จำนวน 3 Filter เพื่อนำไป Slide บน Input Image แต่ละ Channel

model = Sequential()
model.add(Conv2D(3,(10, 10), input_shape=pic.shape))
model.summary()

Plot ภาพกันครับ~

นิยาม Model แบบ 2D Convolution โดยรับ Input Image ขนาด 242×208 Pixel แบบ 3 Channel โดยมี Filter ขนาด 3×3 จำนวน 1 Filter

นิยาม visualize_cat_one_channel Function ที่รับภาพเป็น Matrix ขยายภาพเป็น 4 มิติ แล้ว Predict ภาพ ก่อนจะหดให้เหลือ 2 มิติ เพื่อจะ Plot ภาพ แบบ 1 Channel ต่อไป

def visualize_pic_one_channel(model, pic):
pic_batch = np.expand_dims(pic,axis=0)
conv_pic2 = model.predict(pic_batch)
conv_pic2 = np.squeeze(conv_pic2, axis=0)
conv_pic2 = conv_pic2.reshape(conv_pic2.shape[:2])
plt.imshow(conv_pic2)

Plot ภาพกันครับ~

นิยาม Model แบบ 2D Convolution โดยรับ Input Image ขนาด 240×206 Pixel แบบ 3 Channel โดยมี Filter ขนาด 20×20 จำนวน 1 Filter

model = Sequential()
model.add(Conv2D(1,(20,20),input_shape=pic.shape))
model.summary()

Plot ภาพกันครับ~

นิยาม Model แบบ 2D Convolution โดยรับ Input Image ขนาด 240×206 Pixel แบบ 3 Channel โดยมี Filter ขนาด 20×20 จำนวน 1 Filter และเพิ่ม Relu Activation Function

model = Sequential()
model.add(Conv2D(1,(20,20),input_shape=pic.shape))
model.add(Activation('relu'))
model.summary()

Plot ภาพกันครับ~

นิยาม Model แบบ 2D Convolution โดยรับ Input Image ขนาด 240×206 Pixel แบบ 3 Channel โดยมี Filter ขนาด 3×3 จำนวน 1 Filter และเพิ่ม Max Pooling ขนาด 5×5

model = Sequential()
model.add(Conv2D(1,(3,3),input_shape=pic.shape))
model.add(MaxPooling2D(pool_size=(5,5)))
model.summary()

Plot ภาพกันครับ~

นิยาม Model แบบ 2D Convolution โดยรับ Input Image ขนาด 1,440×1,080 Pixel แบบ 3 Channel โดยมี Filter ขนาด 3×3 จำนวน 1 Filter เพิ่ม Relu Activation Function และ Max Pooling ขนาด 5×5

model = Sequential()
model.add(Conv2D(1,(3,3),input_shape=pic.shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(5,5)))
model.summary()

Plot รูปออกมาครับ ~

นิยาม Model แบบ 2D Convolution, Relu Activation Function และ Max Pooling อย่างละ 2 Layer

model = Sequential()
model.add(Conv2D(1,(3,3),input_shape=pic.shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(3,3)))
model.add(Conv2D(1,(3,3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(3,3)))
model.summary()

Plot ภาพกันครับ~

ก็จบกันแล้วสำหรับ Blog เรื่องแนวคิดของ CNN และทำ Workshop เพื่อดึง Kernel และ Feature Map แล้วเจอกันใน Blog ถัดไปครับ ~

ฝากเพจครับ ~

https://www.facebook.com/LearnByBringbang

Reference