สรุป Deep Learning ที่เรียนมาจากคลาส ดร.กานต์ — Part 1
วันเสาร์ที่ผ่านมา (23 กันยายน 2561) ได้มีโอกาสไปเรียน Deep Learning โดย ดร.กานต์ ที่ Geeky Base เลยอยากจะมาเขียนบทความสรุปสิ่งที่ได้เรียนมา เพื่อให้คนที่อยากไปเรียนแต่ไม่ได้ไปเรียนในวันนั้นได้อ่าน และเป็นการทบทวนตัวเองไปในตัว
โดยการเรียนในครั้งนี้จะเน้นไปที่การทำ workshop แต่ก่อนที่จะเริ่มลงมือทำ พาร์ทนี้เราจึงมาเรียนทฤษฎีกันก่อนเพื่อความเข้าใจที่มากขึ้น
ทฤษฎีสำหรับคลาสนี้
Deep Learning คือสาขาแขนงหนึ่งของ Machine Learning ที่เลียนแบบการทำงาน จากระบบเซลล์ประสาทในสมองของมนุษย์(Neural Network) โดยโครงสร้างของ Neural Network เนี่ยจะมีลักษณะเหมือนเซลล์ประสาทหลายๆเซลล์เชื่อมต่อกัน เป็นโหนดเชื่อมกัน เราเรียกว่าเจ้าโหนดกลมๆนี้ว่า Perceptron (เพอร์เซปตรอน) เราจะสังเกตว่ามันจะเชื่อมต่อกับเส้นประสาทและเซลล์อื่นอีกหลายๆเส้น
เส้นแต่ละเส้นก็จะเชื่อมต่อไปเป็นชั้นๆ โดยจะแบ่งออกเป็น 3 Layers ได้แก่
- Input Layer ชั้นที่เป็นส่วนของการรับข้อมูล
- Hidden Layer ชั้นที่เป็นเหมือนระบบเซลล์ประสาทในสมอง
- Output Layer ชั้นที่เป็นส่วนตอบสิ่งที่ประมวลผลออกมา
ถ้าจะเปรียบเทียบการทำงานให้เหมือนมนุษย์ก็ประมาณว่า ถ้ามนุษย์กำลังมองไปที่ภูเขา Input Layer ก็คือข้อมูลที่สมองเรารับมาจากตา นั่นก็คือภาพภูเขา จากนั้นก็จะส่งภาพต่อไปที่ Hidden Layer ซึ่งเป็นสมองของเรา จากนั้นสมองของเราก็จะประมวลผลแล้วก็ส่งผลลัพธ์ออกไปที่ Output Layer เพื่อบอกให้เรารู้ว่าภาพนี้น่ะคือภูเขา
ดังนั้นสมองของมนุษย์เรานั้นก็เปรียบเหมือน Hidden Layer ที่เชื่อมต่อระหว่าง Input Layer และ Output Layer นั่นเอง แต่ในชีวิตจริงสมองของมนุษย์เรานั้นซับซ้อนกว่าที่เห็นในภาพนี้มาก เพื่อที่จะทำให้ Neural Network ของเรานั้นสามารถคิดและประมวลผลซับซ้อนได้เหมือนสมองมนุษย์ ชั้นที่เป็น Hidden Layer จึงต้องมีหลายๆชั้น ให้มันส่งข้อมูลประมวลผลต่อๆกันไป ทำให้มันสามารถคำนวนอะไรที่ซับซ้อนได้เยอะขึ้น ซึ่งเราเรียกว่า Deep Learning นั่นเอง
อ้อ เกือบลืมไป Deep Learning ก็เป็นสาขาหนึ่งของ Machine Learning เนาะ เพราะฉะนั้นก็จะมีวิธีการเรียนรู้แบ่งเป็น 2 แบบเหมือนกัน
- Supervised Learning การเรียนรู้แบบมีผู้สอน คือการที่เรากำหนดข้อมูลที่จะส่งให้ Neural ของเราได้เรียนรู้ ด้วยการใส่ข้อมูลเข้าไปพร้อมทั้งบอกว่าข้อมูลนี้คืออะไร เช่น เรามีข้อมูลที่บอกว่า มีหู มีตา มีเขี้ยว เห่าได้ และเราใส่ข้อมูลคำตอบไปว่านี่เป็น สุนัข
- Unsupervised Learning การเรียนรู้แบบไม่มีผู้สอน คือ การที่เรากำหนดข้อมูลเจ้าไปให้ Neural โดยที่เราไม่ได้กำหนดข้อมูลสอนเข้าไปว่ามันคืออะไร แต่เจ้า Neural จะทำการแบ่งแยกประเภทข้อมูล ด้วยตัวเอง เช่นเรามีข้อมูลอยู่ 4 รายการ รายการแรกบอกว่า มีหัว มีตัว มีสองแขน มีสองขา ก็จะถูกแยกไปใส่ไว้เป็นประเภท type 1 รายการสองบอกว่า มีหัว มีตัว ไม่มีแขน มีสี่ขา ก็จะถูกแยกไปไว้ที่ type 2 รายการสามเข้ามาบอกว่า มีหัว มีตัว มีสองแขน มีขาเดียว ก็อาจจะถูกแยกออกไปอยู่ในประเภท type 1 เพราะข้อมูลมีรูปแบบคล้ายกัน มากกว่าแบบ type 2 ส่วนรายการที่สี่เข้ามาบอกว่า มีสองหัว มีตัว มีสิบแขน กับอีกแปดขา โอ้โหพระเจ้าแปลกประหลาดมาก อันนี้ก็ถูกแยกออกเป็นอีกประเภทนึงเลย type 3 เพราะมันไม่เข้าพวก ง่ายๆก็จะเป็นประมาณนี้ครับ
โดยในคลาสนี้จะเป็นแบบ Supervised Learning ครับ
จริงๆแล้ว Perceptron หรือเจ้าโหนดกลมๆเนี่ยมันมีพื้นฐานการทำงานที่ง่ายๆ ไม่ซับซ่อนอะไรมาก มันจะรับข้อมูลเข้ามา และคำนวนด้วยฟังก์ชั่นของมัน แล้วก็ส่งผลลัพธ์ที่ได้ออกไป และมีการนำค่าผลลัพธ์ที่ได้ไปเปรียบเทียบกับค่าข้อมูลที่ได้รับมา เพื่อหาค่าๆหนึ่ง ตรงนี้เค้าเรียกว่าค่า error และตัว Perceptron ก็จะนำค่า error ไปปรับปรุงค่าในฟังก์ชั่นต่อไปเพื่อให้ค่า error มันน้อยลง และฟังก์ชั่นเราทำงานได้แม่นและดียิ่งขึ้น
เรามาลองดูการคำนวนของฟังก์ชั่นข้างใน Perceptron กันดีกว่าครับ
จากตัวอย่างรูปเราจะเห็นว่าตัว Perceptron นั้น มีเส้นประสาทแต่ละเส้นที่เชื่อมเข้ามาโดยจะมีการรับค่าอยู่ 2 อย่างคือ Input และค่า w (Weight) และส่งเข้า Perceptron โดยเราสามารถแทนค่าได้เป็นอย่างนี้
หลังจากแทนค่าไปแล้ว เราก็จะสามารถแปลงเป็นสมการได้ดังนี้
- Output = (Input1 x w1) + (Input2 x w2)
- Output = (12 x 0.5) + (4 x -1)
เมื่อแทนค่าและแปลงค่าเป็นสมการแล้ว เราจะเห็นว่ามันก็คือสมการเส้นตรงนั่นเอง
โอเค เรามาดูกันว่าถ้าหากเรานำข้อมูลที่มีมาเข้า Perceptron ด้วยการเรียนรู้แบบ Supervised Learning เนี่ยมันหน้าตาประมาณไหน
สมมุติเรามีตัวอย่างข้อมูลที่จะใช้เทรน 2 ชุดเพื่อที่จะเอาไปแทนค่าลงสมการข้างบนโดยตัวอย่างข้อมูลที่ให้มาบอกว่าชุดแรก มีเลข 12 กับ 4 เข้ามาแล้วต้องได้คำตอบเป็น -1(ค่าลบ) กับอีกชุดนึงที่มีเลข 5 กับ 9 แล้วต้องได้คำตอบเป็น 1(ค่าบวก)
แต่ว่าเรายังไม่สามารถที่จะเอาไปแทนค่าลงในสมการได้ เพราะเรายังไม่มีค่า w (Weight) ซึ่งค่า Weight เนี่ยแหละคือสิ่งที่เราต้องให้เจ้า Perceptron หรือ Neural Network เนี่ยเป็นคนไปหาและอัพเดทค่าเพื่อที่จะให้ตัวมัน Classified ข้อมูลให้ถูกต้องให้ได้ แต่แน่นอนว่าตอนแรกนั้นให้เราสุ่มค่าขึ้นมาเองก่อนได้เลย
ทำการสุ่มค่า Weight มา 2 ตัวเท่ากับจำนวน Input ที่เรามี จากนั้นเอาค่าแทนลงในสมการ เพื่อที่จะมาดูการทำงานของเจ้า Perceptron กัน
- (12 x 0.5) + (4 x 0.5) = 8
ซึ่งค่าที่ได้จาก Output จะเป็น 8 ซึ่งมีค่าเป็นบวก แต่ข้อมูลที่เรานำมาเทรนนั้น เราคาดหวังผลลัพธ์เป็นค่าลบ เพราะฉะนั้นเท่ากับว่ามันเกิด error ขึ้นแล้ว ซึ่งสมการที่เราจะนำ error มาใช้ในการปรับปรุงค่า weight ของเราเป็นดังนี้
- ΔWeight = Error x Input
- New Weight = Weight + ΔWeight
อ้าว แล้วเราจะเอาค่า Error มาจากไหนล่ะ!!!!
ในคลาสนี้ ดร.กานต์ ใช้ Loss Function เพื่อใช้ในการปรับให้สมการเราเนี่ยมันมี error น้อยที่สุด และใช้วัดผลว่าสมการของเรามี error เหลือน้อยที่สุดแล้วหรือยัง ซึ่งจะใช้เลขจากตารางข้างล่างนี้แทนค่า Error ลงในสมการ
Desired = คำตอบที่เราต้องการ, Guess = ค่าจริงที่ได้
- ในตารางนี้สมมุติคำตอบที่เราต้องการเป็น -1(ค่าลบ) และ Output ที่ได้จาก Perceptron ออกมาเป็น -1(ค่าลบ)เหมือนกันแสดงว่ามันไม่เกิด error เพราะฉะนั้นจะเป็น 0
- คำตอบที่เราต้องการเป็น -1(ค่าลบ) แต่ Output ที่ได้จาก Perceptron ออกมาเป็น +1(ค่าบวก) แสดงว่ามันเกิด error เพราะเราต้องการค่าลบ แต่มันดันได้ค่าบวกเพราะฉะนั้นเราจึงต้องปรับให้ฟังก์ชั่นของเราเนี่ยให้มันมีการคำนวนไปในทางลบมากขึ้นกว่าเดิม เพราะฉะนั้นเนี่ยเราจึงแทนค่า error ไปเป็น -2
- คำตอบที่เราต้องการเป็น +1(ค่าบวก) แต่ Output ที่ได้จาก Perceptron ออกมาเป็น -1(ค่าลบ) แสดงว่ามันเกิด error เพราะเราต้องการค่าบวก แต่มันดันได้ค่าลบเพราะฉะนั้นเราจึงต้องปรับให้ฟังก์ชั่นของเรา ให้มีการคำนวนไปในทางบวกมากขึ้นกว่าเดิม เพราะฉะนั้นเราจึงแทนค่า error ไปเป็น 2
- ส่วนอันล่างสุด เราต้องการคำตอบเป็น +1(ค่าบวก) แลสิ่งที่ ได้จาก Perceptron ออกมาก็เป็น +1(ค่าบวก) เหมือนกันแสดงว่าฟังก์ชั่นของ Perceptron ทำงานถูกแล้วไม่เกิด error เพราะฉะนั้นค่า error ก็เป็น 0 เหมือนอันแรก
** เรื่อง Loss Function อยากรู้รายละเอียดไปหาอ่านเพิ่มเอานะครับ 5555 **
โอเค ตอนนี้เราได้ค่าที่จะมาแทนในฟังก์ชั่นครบแล้ว เรามาแทนค่ากันเลย
- ΔWeight = Error x Input
- New Weight = Weight + ΔWeight
จากสมการแทนค่าได้ดังนี้
- ΔWeight ตัวที่ 1 = ((-2) x 12)
- New Weight ตัวที่ 1 = 0.5 + ((-2) x 12) = -23.5
- ΔWeight ตัวที่ 2= ((-2) x 4)
- New Weight ตัวที่ 2 = 0.5 + ((-2) x 4) = -7.5
หลังจากที่เราได้ค่า Weight มาใหม่ทั้ง 2 ค่าแล้วให้เรานำค่าที่ได้มาใหม่นี้ มาแทนค่า Weight กับข้อมูลแถวต่อไปที่เรากำลังจะนำเข้า คือ Input1 = 5, Input2 = 9, Output = 1 มาลองแทนค่าในสมการกัน
- Output = (Input1 x New Weight 1) + (Input2 x New Weight 2)
- Output = (5 x (-23.5)) + (9 x (-7.5))
- Output = (-117.5) + (-67.5) = -185
จะเห็นว่าค่าออกมาเป็น -185 ซึ่งเป็นค่าลบ แต่ค่าที่เราทำการสอนไป(ค่าที่เราอยากจะให้มันเป็น) คือค่าบวก เพราะฉะนั้นข้อมูลนี้จึงเกิด error เหมือนกัน เราเลยต้องทำการคำนวนเพื่อหาค่า Weight มาใหม่อีก โดยครั้งนี้จะนำค่า error = 2 ที่ได้จาก Loss Function แทนค่า error ของค่า -185 นี้
จากสมการแทนค่าได้ดังนี้
- ΔWeight ตัวที่ 1 = (2 x 5)
- New Weight ตัวที่ 1 = (-23.5)+ (2 x 5) = -13.5
- ΔWeight ตัวที่ 2= (2 x 9)
- New Weight ตัวที่ 2 = (-7.5)+ (2 x 9) = 10.5
เราจะเห็นว่า เมื่อเราเทรนข้อมูลและเกิด error ในแต่ละครั้ง Weight จะมีการปรับค่าใหม่ไปเรื่อยๆ เพื่อให้รองรับกับการ Classified ข้อมูลที่เคยถูกสอนเข้ามาให้ดีที่สุด
งั้นเราลองนำ Weight สุดท้ายที่ได้ นำกลับไปแทนค่าข้อมูลใหม่กันอีกครั้ง
- Output = (12 x (-13.5)) + (4 x 10.5) = -120 (ค่าลบ)
- Output = (5 x (-13.5)) + (9 x10.5) = 27 (ค่าบวก)
จะเห็นว่าหลังจากที่เรานำค่า Weight ที่ถูกการปรับค่ามาแล้วมาแทนค่าลงไป Output ที่ได้ออกจาก Perceptron จะมีความถูกต้องมากขึ้น ตามที่เราคาดหวังไว้
โดยตัวอย่างที่เราใช้ทำกันข้างบนมาเนี่ยเค้าเรียกว่า Backpropagation Algorithm ก็คือการที่คำนวนออกมาในแต่ละโหนดแล้วได้ error ก็จะส่งกลับไปปรับ Weight ใหม่นั่นเอง
แต่นั่นก็ไม่ได้หมายความว่า Backpropagation เนี่ยเป็น Algorithm ที่ดีที่สุดนะ เพราะมันจะมีปัญหาในเรื่องของการอัพเดทข้อมูลในกรณีที่เรามี Hidden Layer หลายๆชั้น และตอนที่เรา propagate ค่า error กลับไป(เอาค่า Weight ใหม่กลับไปปรับ) มันก็คือการนำ error ไปคูณกับข้อมูลใหม่อีกรอบ พอยิ่งคูณกันไปเรื่อยๆเนี่ย จุดทศนิยมมันจะยิ่งมีค่าน้อยลงไปเรื่อยๆ เช่นจาก 13.23 คูณๆไปกลายเป็น 12.402383 พอไปอีกเรื่อยๆกลายเป็น 12.402391 ซึ่งจะเห็นเลยว่าค่ามันเปลี่ยนไปไม่มาก แถมเปลี่ยนในระดับทศนิยมด้วย ทำให้การเรียนรู้ของ Neural Networks มันยิ่งเรียนรู้ได้น้อยลงเรื่อยๆ
เค้าก็เลยมีการปรับเปลี่ยนวิธีการเทรนใหม่ขึ้นมาใหม่ ซึ่งสิ่งที่เราคาดหวังเนี่ย คือเราอยากจะให้ Layer แรกๆของเราเนี่ย เรียนรู้ข้อมูลในระดับ Low Level เท่านั้นและในชั้นต่อๆไปก็จะเอาข้อมูลมาประกอบกัน ถ้าเปรียบเทียบเป็นข้อมูลรูปภาพสุนัข ในชั้น หรือ Layer แรกๆเนี่ยก็อาจจะเห็น Data เป็นพวกจมูกสุขัน หูสุนัข ปากสุนัข และชั้นถัดๆไปเมื่อมันประกอบกันไปเรื่อย ก็จะเห็นเป็นรูปหน้าสุนัข (ง่ายๆก็คือแยกส่วนกันเรียนรู้ในชั้นแรกๆ และนำมาประกอบกันไปเรื่อยๆ ในชั้นที่ลึกขึ้นนั่นเอง)
ติดตั้งเครื่องมือ
สิ่งที่ใช้ทำ workshop ในคลาสนี้คือ
- Python เวอร์ชั่น 3 ขึ้นไป
- Anaconda
- Pip (package manager)
ไลบรารี่ที่ใช้
- NumPy
- OpenCV
- Scikit-Learn
- Keras
แต่ผมคาดว่าผู้อ่านจะสามารติดตั้งเครื่องมือพวกนี้ได้ด้วยตนเอง เพราะฉะนั้นจะไม่อธิบายถึงขั้นตอนในการติดตั้งนะครับ
หลังจากที่เราติดตั้ง Python กับ Anaconda แล้วให้เราเปิดตัว Anaconda Navigator ขึ้นมาแล้วเลือก Launch ตัว jupyter notebook ซึ่งเจ้า jupyter notebook จะคล้าย IDE ที่ให้ผู้ใช้สามารถพิมพ์คำสั่งแล้วให้ประมวลผลคำสั่งนั้นได้ และยังแสดงผลลัพธ์ต่อท้ายชุดคำสั่งของช่องนั้นๆ ตัว notebook สามารถเก็บ code และตัว markdown ที่ช่วยให้แสดงข้อมูลในแบบต่างๆได้ด้วย
หลังจากเราเลือก Launch แล้วเจ้าตัว Anaconda มันจะไปเปิดตัว jupyter notebook ขึ้นมาและ notebook server จะรันที่ http://localhost:8888/
เราก็จะได้ jupyter notebook รันอยู่บน default browser ของเราแล้ว
หลังจากเปิดขึ้นมาได้แล้ว ให้เราสร้าง folder มาสักอันนึงเพื่อที่จะเก็บไฟล์และข้อมูลต่างๆสำหรับการทำ workshop ในครั้งนี้
หลังจากสร้าง folder แล้วให้คลิ๊กที่ New แล้วเลือก Python 3 เพื่อสร้างไฟล์ใหม่
ภายในไฟล์ที่เราสร้างไว้ จะมีหน้าตาแบบนี้
ซึ่งเราสามารถพิมพ์โค้ดลงไปในช่องนี้ได้ และยังเพิ่มเจ้าช่องพวกนี้ขึ้นมาอีกกี่ช่องก็ได้ ด้วยการคลิ๊กไปที่ Insert Cell Above กับ Insert Cell Below
ตัวช่องที่เราเอาไว้เขียนโค้ดนั้น มันจะมีอยู่ 2 สี 2 สถานะคือสีฟ้ากับสีเขียว สีเขียวหมายถึงว่า cursor ของเรากำลังอยู่ในช่องนั้น ซึ่งเราสามารถพิมพ์โค้ดลงไปในช่องนี้ได้ทันที ส่วนสีฟ้าก็คือช่องที่ cursor ของเราไม่ได้อยู่ที่นั่นน่ะเอง ซึ่งเราก็จะไม่สามารถพิมพ์โค้ดลงไปได้ จนกว่าจะเอา cursor เราเข้าไปในนั้น
เราสามารถพิมพ์โค้ดลงไปในช่องได้ทันที และหากเราอยากจะรันโค้ดที่เราพิมพ์ไปให้เรากดปุ่ม Run ข้างบน หรือจะกด Shift + Enter ก็ได้
เราจะเห็นว่า จะมีผลลัพธ์จากการรันโค้ดในช่องๆนั้นออกมาต่อท้ายช่องนั้น
นอกจากจะสามารถรันโค้ดได้แล้ว jupyter notebook ยังสามารถใส่ Markdown ลงไปได้อีกด้วย ด้วยการเลือกให้ Cell Type เป็นแบบ Markdown
หลังจากเปลี่ยนช่องนี้เป็น Markdown จะเห็นว่า In [ ] ที่อยู่ด้านหน้าช่องนี้หายไป นั่นหมายความว่าเมื่อเราทำการรันในช่องนั้นๆ มันจะไม่ถูกนำไป complie ด้วย python นั่นเอง
และเมื่อเรารันเสร็จ แล้วเราจะเห็นสิ่งที่เราพิมพ์ลงไป ขึ้นแทนช่องนั้นๆ
อ่อ เกือบลืม เราสามารถแก้ชื่อไฟล์ได้ โดยตรงนี้คลิ๊กแก้ชื่อไฟล์ได้เลยครับ
โอเค เมื่อเราพอที่จะเริ่มใช้งาน jupyter notebook ได้แล้ว ก็สามารถลงมือทำได้เลย