Neural Network 101 : CNN with TensorFlow

Chatchawan Niyomthum
3 min readApr 13, 2018

--

สวัสดีคุณผู้อ่านทุกคน ในวันนี้ผมจะขอออกนอกสโคป Reinforcement Learning(RL) มาเล่าถึง Convolutional Neural Networks(CNN/ConvNet) ซึ่งถ้าคุณผู้อ่านได้ติดตามข่าวสารจะรู้จักเป็นอย่างดี ว่า DQN มีการนำ CNN มาใช้ร่วมกับ RL ในแก้ปัญหา Atari 2600 หรือพูดง่ายๆว่า สร้างบอทมาเล่นเกมแทนมนุษย์นั้นและครับ เราเลยมาปูพื้นฐานและทำความรู้จักกับ CNN กันก่อน เพื่อไม่ให้เป็นการเสียเวลา เรามาลุยกันเลย

What is CNN ?

คือรูปแบบ architecture หนึ่งของ feed-forward neural networks (หลายๆ คนน่าจะร้องอ๋อกันแล้ว ใช่ครับมันคือ NN ที่เราเรียนมากันตั้งแต่ป.ตรี ในวิชา AI นั้นและ) และก็จัดเป็น Deep learning เช่นกัน (เพราะมีหลาย layer เหตุผลที่เรียกว่า deep มีแค่นั้น)

CNN ประสบความสำเร็จในการแก้ปัญหา Classification ที่เกี่ยวข้องกับรูปภาพ อีกทั้งในปัจจุบัน ถูกนำแนวคิดไปใช้ต่อยอดมากมาย แต่ก็ยังมีข้อเสียที่ต้องพึงมนุษย์ในการออกแบบ architecture ของ NN ในการแก้ปัญหาใดปัญหาหนึ่ง (จำนวน feature และ layer)

Inside the box (CNN Structure Design)

Fig 1. The components of CNN [Pic from Deep Learning (Ian Goodfellow, Yoshua Bengio, and Aaron Courville), chap 9, p.336]

จากรูปข้างบน จะเห็นได้ว่าใน 1 layer ประกอบไปด้วย 3 ส่วนใหญ่ๆ

1. Convolution stage

ในขั้นตอนนี้เราจะสร้าง Sliding window(Filter) มาสแกนรูป inputเพื่อทำ Feature map ถ้าพูดในภาษาชาวบ้านทั่วไป คือ ทำการ สแกนรูปเพื่อแยกองค์ประกอบของรูป ออกมา เช่น ขอบ สี รูปทรง เป็นต้น

2. Detector stage

ชั้นนี้จะทำหน้าที่รับ output จาก 1. แปลงให้อยู่ในรูปของ nonlinear โดยใช้ activation อย่างเช่น Rectified Linear Units (ReLU) เพื่อความง่ายในการคำนวณและประสิทธิภาพของผลลัพธ์ ในตำราหรือแหล่งความรู้ส่วนใหญ่จะรวมขั้นตอนไว้ใน 1. ซึ่งไม่ต้องตกใจถ้าผู้เขียนไม่กล่าวถึงส่วนนี้ เพราะ 2. ถือเป็นส่วนประกอบที่ไม่ได้เปลี่ยนแปลงเหมือนส่วนอื่น (ใช้ตามๆ กันนั้นและครับ)

3. Pooling stage

Pooling ทำหน้าที่ resize ข้อมูลให้ขนาดเล็กลงโดยที่รายละเอียดของ input ยังครบถ้วนเหมือนเดิม หลักการทำงานขั้นตอนนี้คล้ายๆ กับ 1. แต่ต่างที่ตรง output ที่ได้จะมีขนาดเล็กลง

Pooling มีประโยชน์ในเรื่องเพิ่มความไวในการคำนวณ และแก้ปัญหา overfitting

ในปัจจุบันที่นิยมใช้กันมากจะเป็น MAX กับ L2

Next Layer and More..

หลังจากที่เรารู้จัก Convolutinal layer แล้ว ใน layer ถัดๆ ไป เราอาจจะทำซ้ำเดิมก็ได้ แต่ส่วนที่จะมาเป็น Final layer นั้นต้องเป็น fully-connected NN (Feed-forward NN) โดยผมจะขอเรียกย่อๆว่า FC นะครับ โดย FC จะทำหน้าที่เป็น model หลักของโปรแกรม

จบแล้วสำหรับความรู้พื้นฐานเกี่ยวกับ CNN เราจะไปต่อที่การลงมือจริง เพื่อจะได้เข้าใจยิ่งขึ้น

Practice with TensorFlow Example

Source Code

ในบทความนี้เราจะใช้ code ตัวอย่างของ TensorFlow เรื่อง MNIST กัน ส่วน Architecture ที่ใช้ ก็ตามด้านล่างเลยครับ

Conv#1> Pool#1 > Conv#2 > Pool#2 > FC

main()

train_input_fn = tf.estimator.inputs.numpy_input_fn(x={"x": train_data}, y=train_labels,batch_size=100, num_epochs=None, shuffle=True)
mnist_classifier.train(input_fn=train_input_fn, steps=20000, hooks=[logging_hook])

ในขั้นตอนการ train เรากำหนดให้ส่งข้อมูลภาพแบบสุ่มไปทีละ 100 และให้การทำงานในแต่ละรอบ(epoch) ไม่เกิน 20000 steps หรือพูดง่ายๆ ว่า train รูปภาพแบบสุ่มทีละ 2 ล้านรูปต่อ 1 loop

eval_input_fn = tf.estimator.inputs.numpy_input_fn(x={"x": eval_data}, y=eval_labels, num_epochs=1, shuffle=False)eval_results = mnist_classifier.evaluate(input_fn=eval_input_fn)print(eval_results)

เมื่อเรา train จบเราก็ต้อง qc คุณภาพถูกไหมครับ ดังนั้น code ส่วนนี้จะทำการ test และแสดงผลลัพธ์ออก console

สรุปสั้นๆ แบบ overview ในส่วน main() โดยเริ่มจากดึงข้อมูลเข้าโปรแกรม, เตรียม logging, สร้าง obj ตัว model จากนั้นก็เริ่ม train test แล้วก็แสดงผลลัพธ์ออกหน้าจอ เป็นอันจบ

cnn_model_fn()

input_layer = tf.reshape(features["x"], [-1, 28, 28, 1])

แปลง input ให้อยู่ใน format ที่พร้อมใช้งานโดย parameters ที่ส่งไปจะมีความหมายดังนี้ (input, shape[batch_size, width, height, color_channel])

เนื่องจากข้อมูลของเราเป็นภาพขาวดำขนาด 28 x 28 เพราะฉะนั้นจึงได้ [-1, 28, 28, 1] สำหรับ -1 ที่กำหนดแบบนี้เพราะให้ทาง TensorFlow ปรับตาม size ของ features[“x”] ที่รับมา ซึ่งถ้าใครจำได้ ใน main() เราระบุ batch_size=100 เพราะฉะนั้นในกรณีนี้ ขนาดจริงๆ จะเป็น [100, 28, 28, 1]

conv1 = tf.layers.conv2d(inputs=input_layer, filters=32, kernel_size=[5, 5], padding="same", activation=tf.nn.relu)

ส่วนถัดมาคือ conv ก่อนอื่นถ้าเราดูตาม API จะเห็นได้ว่า มีให้เลือกใช้ตั้งแต่ 1–3 ทั้งแบบปกติและ transpose สำหรับใครสนใจในรายละเอียดลองอ่าน link ด้านล่างได้ครับ ส่วนโจทย์ของเราใช้เป็น conv2d ต่อไปเราจะมาดูความหมายของ parameters กัน

What do you mean by 1D, 2D and 3D Convolutions in CNN?

What are deconvolutional layers?

Filters: จำนวน feature ที่ต้องการจะแยกออกมา

Kernel size: ขนาดของ Sliding window ที่เราใช้

Padding=same: ระบุเพื่อป้องกันไม่ให้ output มีขนาดเล็กลง เนื่องจาก input เรามีขนาด 28*28 และเราเลือกใช้ kernal 5*5 output ที่ได้จะมีขนาดแค่ 24*24 ตาม concept output ที่ออกมาจาก conv ควรจะมีขนาดเท่าเดิม

Activation: อันนี้ก็คือ Detector stage ที่เราได้อธิบายไปแล้ว ก็ตามสูตรใช้เป็น ReLU

pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)

สำหรับ max pooling ในส่วนของ Pool size จะเหมือนกับ Kernel ของ conv ต่างแค่ชื่อ ส่วนตัวสุดท้าย Strides เป็นตัวบอก Sliding window ของเราว่าให้ขยับทีละกี่ pixels

Tip: max pooling ส่วนมากจะใช้ค่าน้อยๆ เพื่อป้องกันการเกิดปัญหาในเรื่องของขนาดและประสิทธิภาพ

pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 64])dense = tf.layers.dense(inputs=pool2_flat, units=1024, activation=tf.nn.relu)dropout = tf.layers.dropout(inputs=dense, rate=0.4, training=mode == tf.estimator.ModeKeys.TRAIN)logits = tf.layers.dense(inputs=dropout, units=10)

FC layer: เริ่มแรกเราต้องแปลง input(pool2) ให้เป็นแบบ 1D(pool2_flat) แล้วถึงส่งต่อไปยัง hidden layer(dense) ที่มี 1024 node และใช้ dropout regularization(dropout) เพื่อเพิ่มประสิทธิภาพในการ train จากนั้นถึงส่งออกไปยัง output layer(logits)

สำหรับตัวเลขต่างๆ ใน dense กับ dropout มาจากการสุ่มทดลองครับไม่มีตายตัว ส่วนนี้ถ้าใครอ่านแล้วไม่เข้าใจ ลองหาบทความเกี่ยวกับ NN อ่านดูนะครับ

predictions = { "classes": tf.argmax(input=logits, axis=1), "probabilities": tf.nn.softmax(logits, name="softmax_tensor")}

เนื่องจาก logits ให้ค่าออกมาเป็น array[10] เราจึงต้องแปลงออกมาเป็นภาษาคนโดยที่ในครั้งนี้เราจะเอา 2 อย่างคือ ค่าตัวเลข(classes) กับ % ความน่าจะเป็น (probabilities)

onehot_labels = tf.one_hot(indices=tf.cast(labels, tf.int32), depth=10)loss = tf.losses.softmax_cross_entropy(onehot_labels=onehot_labels, logits=logits)if mode == tf.estimator.ModeKeys.TRAIN:  optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)  train_op = optimizer.minimize(loss=loss, global_step=tf.train.get_global_step())

มาถึงส่วนสุดท้ายกันแล้ว นั้นคือการทำ Backpropagation(parameter tuning) โดยใช้ cross entropy หา loss function แล้วปิดท้ายด้วย stochastic gradient descent เพื่อ update parameter

One hot encoder: ใช้แปลงข้อมูลจากรูปแบบหนึ่งไปอีกแบบเพื่อช่วยในเรื่องประสิทธิภาพ (เพิ่มเติม)

Softmax cross entropy: ทำหน้าที่หาระยะห่างระหว่างคำตอบจริงกับผลลัพธ์ที่โปรแกรมคำนวณได้ ดังนั้นค่ายิ่งน้อยยิ่งดี (เพิ่มเติม)

Stochastic gradient descent: คำนวณค่าเพื่ออัพเดท parameter (เพิ่มเติม)

มาถึงตรงนี้เราได้รู้จัก CNN กันแล้ว ว่าคือ Feature extractor รวมทั้งส่วนประกอบสำคัญๆ 3 stage, รายละเอียดปลีกย่อยเกี่ยวกับ FC และอื่นๆ ปิดท้ายด้วยการลองทำจริงด้วย tensorflow เพื่อสอนให้คอมพิวเตอร์เรารู้จักตัวเลข 0–9 ที่เขียนด้วยมือ

สำหรับบทความนี้ก็ขอจบลง ณ ตรงนี้ เนื่องจากมีการใช้ศัพท์เฉพาะเยอะหน่อย อาจจะทำให้ผู้อ่านหลายๆ คนสับสนได้ ก็ขอให้ลองค่อยๆ ศึกษาไปทีละนิดนะครับ ผมคงต้องขอลาไปก่อน ขอบคุณทุกคนที่อ่านกันมาจนถึงจุดนี้ครับ

References

A Guide to TF Layers: Building a Convolutional Neural Network By TensorFlow

CS231n Convolutional Neural Networks for Visual Recognition By Andrej Karpathy@Stanford

Deep learning book — Chapter 9 By Ian Goodfellow, Yoshua Bengio, and Aaron Courville

Neural Networks and Deep Learning — Chapter 6 By Michael Nielsen

--

--