1. ภาพรวม
เราได้อัปเดตบทแนะนำนี้สำหรับ Tensorflow 2.2 แล้ว

ในโค้ดแล็บนี้ คุณจะได้เรียนรู้วิธีสร้างและฝึกโครงข่ายประสาทเทียมที่จดจำตัวเลขที่เขียนด้วยลายมือ ในระหว่างนี้ เมื่อคุณปรับปรุงโครงข่ายประสาทเทียมเพื่อให้ได้ความแม่นยำ 99% คุณจะได้ค้นพบเครื่องมือที่ผู้เชี่ยวชาญด้านดีปเลิร์นนิงใช้ฝึกโมเดลอย่างมีประสิทธิภาพ
โค้ดแล็บนี้ใช้ชุดข้อมูล MNIST ซึ่งเป็นคอลเล็กชันของตัวเลขที่มีป้ายกำกับ 60,000 รายการที่ทำให้ผู้ที่จบปริญญาเอกหลายรุ่นต้องทำงานอย่างหนักมาเกือบ 2 ทศวรรษ คุณจะแก้ปัญหานี้ได้ด้วยโค้ด Python / TensorFlow ไม่ถึง 100 บรรทัด
สิ่งที่คุณจะได้เรียนรู้
- โครงข่ายประสาทเทียมคืออะไรและจะฝึกได้อย่างไร
- วิธีสร้างโครงข่ายประสาทเทียมแบบ 1 เลเยอร์พื้นฐานโดยใช้ tf.keras
- วิธีเพิ่มเลเยอร์
- วิธีตั้งค่ากำหนดเวลาอัตราการเรียนรู้
- วิธีสร้างโครงข่ายประสาทเทียมแบบคอนโวลูชัน
- วิธีใช้เทคนิคการทำให้เป็นปกติ: Dropout, Batch Normalization
- Overfitting คืออะไร
สิ่งที่คุณต้องมี
ใช้แค่เบราว์เซอร์ เวิร์กช็อปนี้สามารถดำเนินการได้ทั้งหมดด้วย Google Colaboratory
ความคิดเห็น
โปรดแจ้งให้เราทราบหากพบสิ่งผิดปกติในห้องทดลองนี้หรือหากคุณคิดว่าควรมีการปรับปรุง เราจัดการความคิดเห็นผ่านปัญหาใน GitHub [feedback link]
2. คู่มือเริ่มต้นฉบับย่อของ Google Colaboratory
แล็บนี้ใช้ Google Colaboratory และคุณไม่จำเป็นต้องตั้งค่าใดๆ คุณเรียกใช้ได้จาก Chromebook โปรดเปิดไฟล์ด้านล่างและเรียกใช้เซลล์เพื่อให้คุ้นเคยกับสมุดบันทึก Colab
วิธีการเพิ่มเติมมีดังนี้
เลือกแบ็กเอนด์ GPU
ในเมนู Colab ให้เลือกรันไทม์ > เปลี่ยนประเภทรันไทม์ แล้วเลือก GPU การเชื่อมต่อกับรันไทม์จะเกิดขึ้นโดยอัตโนมัติเมื่อมีการดำเนินการครั้งแรก หรือคุณจะใช้ปุ่ม "เชื่อมต่อ" ที่มุมขวาบนก็ได้
การดำเนินการ Notebook
เรียกใช้เซลล์ทีละเซลล์โดยคลิกเซลล์และใช้ Shift-ENTER นอกจากนี้ คุณยังเรียกใช้ทั้งสมุดบันทึกได้ด้วยรันไทม์ > เรียกใช้ทั้งหมด
สารบัญ
Notebook ทุกรายการมีสารบัญ คุณเปิดได้โดยใช้ลูกศรสีดำทางด้านซ้าย
เซลล์ที่ซ่อนอยู่
บางเซลล์จะแสดงเฉพาะชื่อ ฟีเจอร์นี้เป็นฟีเจอร์สมุดบันทึกเฉพาะของ Colab คุณดับเบิลคลิกที่ไฟล์เพื่อดูโค้ดภายในได้ แต่โดยปกติแล้วโค้ดจะไม่น่าสนใจนัก โดยปกติจะเป็นฟังก์ชันการสนับสนุนหรือการแสดงภาพ คุณยังคงต้องเรียกใช้เซลล์เหล่านี้เพื่อให้ฟังก์ชันภายในได้รับการกำหนด
3. ฝึกโครงข่ายประสาท
ก่อนอื่นเราจะดูการฝึกโครงข่ายประสาทเทียม โปรดเปิดสมุดบันทึกด้านล่างและเรียกใช้เซลล์ทั้งหมด อย่าเพิ่งสนใจโค้ด เราจะเริ่มอธิบายในภายหลัง
ขณะรัน Notebook ให้โฟกัสที่การแสดงภาพ ดูคำอธิบายด้านล่าง
ข้อมูลการฝึก
เรามีชุดข้อมูลตัวเลขที่เขียนด้วยลายมือซึ่งติดป้ายกำกับไว้เพื่อให้ทราบว่าแต่ละรูปภาพแสดงถึงอะไร นั่นคือตัวเลขระหว่าง 0 ถึง 9 คุณจะเห็นข้อความที่ตัดตอนมาใน Notebook

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

ทางด้านขวา "ความแม่นยำ" คือเปอร์เซ็นต์ของตัวเลขที่จดจำได้อย่างถูกต้อง ซึ่งจะเพิ่มขึ้นเมื่อการฝึกคืบหน้าไปเรื่อยๆ ซึ่งเป็นเรื่องดี
ทางด้านซ้าย เราจะเห็น "การสูญเสีย" เราจะกำหนดฟังก์ชัน "การสูญเสีย" ซึ่งแสดงถึงความผิดพลาดของระบบในการจดจำตัวเลข และพยายามลดการสูญเสียนี้เพื่อขับเคลื่อนการฝึก สิ่งที่คุณเห็นที่นี่คือการสูญเสียจะลดลงทั้งในข้อมูลการฝึกและข้อมูลการตรวจสอบเมื่อการฝึกดำเนินไป ซึ่งเป็นเรื่องดี ซึ่งหมายความว่าโครงข่ายประสาทเทียมกำลังเรียนรู้
แกน X แสดงจํานวน "Epoch" หรือการวนซ้ำผ่านชุดข้อมูลทั้งหมด
การคาดการณ์
เมื่อฝึกโมเดลแล้ว เราจะใช้โมเดลนี้เพื่อจดจำตัวเลขที่เขียนด้วยลายมือได้ ภาพข้อมูลถัดไปแสดงประสิทธิภาพของโมเดลในตัวเลข 2-3 หลักที่แสดงผลจากแบบอักษรในเครื่อง (บรรทัดแรก) และในตัวเลข 10,000 หลักของชุดข้อมูลการตรวจสอบ คลาสที่คาดการณ์จะปรากฏใต้ตัวเลขแต่ละตัวเป็นสีแดงหากไม่ถูกต้อง

ดังที่เห็น โมเดลเริ่มต้นนี้ไม่ค่อยดีนัก แต่ก็ยังจดจำตัวเลขบางตัวได้อย่างถูกต้อง ความแม่นยำในการตรวจสอบขั้นสุดท้ายอยู่ที่ประมาณ 90% ซึ่งถือว่าไม่แย่สำหรับโมเดลที่เรียบง่ายที่เราเริ่มต้นด้วย แต่ก็ยังหมายความว่าโมเดลนี้พลาดตัวเลขการตรวจสอบ 1, 000 ตัวจาก 10,000 ตัว ซึ่งมีมากกว่าจำนวนที่แสดงได้ จึงทำให้ดูเหมือนว่าคำตอบทั้งหมดผิด (สีแดง)
เทนเซอร์
ระบบจะจัดเก็บข้อมูลในเมทริกซ์ รูปภาพระดับสีเทาขนาด 28x28 พิกเซลจะพอดีกับเมทริกซ์ 2 มิติขนาด 28x28 แต่สำหรับรูปภาพสี เราต้องใช้มิติข้อมูลเพิ่มเติม มีค่าสี 3 ค่าต่อพิกเซล (แดง เขียว น้ำเงิน) ดังนั้นจึงต้องใช้ตารางสามมิติที่มีมิติข้อมูล [28, 28, 3] และหากต้องการจัดเก็บรูปภาพสี 128 รูป คุณจะต้องใช้ตาราง 4 มิติที่มีขนาด [128, 28, 28, 3]
ตารางหลายมิตินี้เรียกว่า "เทนเซอร์" และรายการมิติข้อมูลของตารางเรียกว่า "รูปร่าง"
4. [ข้อมูล]: โครงข่ายประสาทเทียมเบื้องต้น
โดยสรุป
หากคุณทราบคำศัพท์ทั้งหมดที่ตัวหนาในย่อหน้าถัดไปแล้ว ให้ไปที่แบบฝึกหัดถัดไป หากคุณเพิ่งเริ่มต้นเรียนรู้เชิงลึก เราขอต้อนรับและโปรดอ่านต่อ

สำหรับโมเดลที่สร้างเป็นลำดับของเลเยอร์ Keras มี Sequential API ตัวอย่างเช่น คุณเขียนตัวแยกประเภทรูปภาพที่ใช้เลเยอร์แบบหนาแน่น 3 เลเยอร์ใน Keras ได้ดังนี้
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=[28, 28, 1]),
tf.keras.layers.Dense(200, activation="relu"),
tf.keras.layers.Dense(60, activation="relu"),
tf.keras.layers.Dense(10, activation='softmax') # classifying into 10 classes
])
# this configures the training of the model. Keras calls it "compiling" the model.
model.compile(
optimizer='adam',
loss= 'categorical_crossentropy',
metrics=['accuracy']) # % of correct answers
# train the model
model.fit(dataset, ... )

เลเยอร์หนาแน่นเดียว
ตัวเลขที่เขียนด้วยลายมือในชุดข้อมูล MNIST เป็นรูปภาพระดับสีเทาขนาด 28x28 พิกเซล แนวทางที่ง่ายที่สุดในการจัดประเภทคือการใช้ 28x28=784 พิกเซลเป็นอินพุตสำหรับโครงข่ายประสาทเทียมแบบ 1 เลเยอร์

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

เมื่อใช้คอลัมน์แรกของน้ำหนักในเมทริกซ์น้ำหนัก W เราจะคำนวณผลรวมแบบถ่วงน้ำหนักของพิกเซลทั้งหมดในรูปภาพแรก ผลรวมนี้สอดคล้องกับนิวรอนแรก เมื่อใช้คอลัมน์ที่ 2 ของน้ำหนัก เราจะทำเช่นเดียวกันกับนิวรอนที่ 2 และอื่นๆ จนถึงนิวรอนที่ 10 จากนั้นเราก็ทำซ้ำการดำเนินการกับรูปภาพที่เหลืออีก 99 รูป หากเราเรียก X ว่าเมทริกซ์ที่มีรูปภาพ 100 รูป ผลรวมแบบถ่วงน้ำหนักทั้งหมดสำหรับนิวรอน 10 ตัวที่คำนวณจากรูปภาพ 100 รูปก็คือ X.W ซึ่งเป็นการคูณเมทริกซ์
ตอนนี้แต่ละนิวรอนต้องเพิ่มค่าอคติ (ค่าคงที่) เนื่องจากเรามีนิวรอน 10 ตัว เราจึงมีค่าคงที่อคติ 10 ตัว เราจะเรียกเวกเตอร์ของค่า 10 ค่านี้ว่า b โดยต้องเพิ่มลงในแต่ละบรรทัดของเมทริกซ์ที่คำนวณไว้ก่อนหน้านี้ เราจะเขียนสิ่งนี้ด้วยเครื่องหมายบวกง่ายๆ โดยใช้เทคนิคเล็กๆ น้อยๆ ที่เรียกว่า "การออกอากาศ"
สุดท้าย เราจะใช้ฟังก์ชันการเปิดใช้งาน เช่น "softmax" (อธิบายไว้ด้านล่าง) และรับสูตรที่อธิบายเครือข่ายประสาทแบบ 1 เลเยอร์ ซึ่งใช้กับรูปภาพ 100 รูป

ใน Keras
เมื่อใช้ไลบรารีเครือข่ายประสาทระดับสูงอย่าง Keras เราก็ไม่จำเป็นต้องใช้สูตรนี้ อย่างไรก็ตาม สิ่งสำคัญที่ต้องเข้าใจคือเลเยอร์ของโครงข่ายประสาทเทียมเป็นเพียงการคูณและการบวกจำนวนมาก ใน Keras เลเยอร์ Dense จะเขียนได้ดังนี้
tf.keras.layers.Dense(10, activation='softmax')
เจาะลึก
การเชื่อมต่อเลเยอร์ของโครงข่ายประสาทนั้นทำได้ง่ายมาก เลเยอร์แรกจะคำนวณผลรวมแบบถ่วงน้ำหนักของพิกเซล เลเยอร์ถัดไปจะคำนวณผลรวมแบบถ่วงน้ำหนักของเอาต์พุตของเลเยอร์ก่อนหน้า

ความแตกต่างเพียงอย่างเดียว นอกเหนือจากจำนวนนิวรอน คือการเลือกฟังก์ชันการเปิดใช้งาน
ฟังก์ชันการเปิดใช้งาน: relu, softmax และ sigmoid
โดยปกติแล้ว คุณจะใช้ฟังก์ชันการกระตุ้น "relu" สำหรับทุกเลเยอร์ยกเว้นเลเยอร์สุดท้าย เลเยอร์สุดท้ายในตัวแยกประเภทจะใช้การเปิดใช้งาน "softmax"

อีกครั้งที่ "นิวรอน" จะคำนวณผลรวมแบบถ่วงน้ำหนักของอินพุตทั้งหมด เพิ่มค่าที่เรียกว่า "อคติ" และป้อนผลลัพธ์ผ่านฟังก์ชันการกระตุ้น
ฟังก์ชันการเปิดใช้งานที่ได้รับความนิยมมากที่สุดเรียกว่า "RELU" สำหรับ Rectified Linear Unit ฟังก์ชันนี้ใช้งานง่ายมาก ดังที่เห็นในกราฟด้านบน
ฟังก์ชันการเปิดใช้งานแบบเดิมในโครงข่ายประสาทเทียมคือ "sigmoid" แต่ "relu" แสดงให้เห็นว่ามีคุณสมบัติการบรรจบกันที่ดีกว่าเกือบทุกที่และเป็นที่นิยมในปัจจุบัน

การเปิดใช้งาน Softmax สำหรับการจัดประเภท
เลเยอร์สุดท้ายของโครงข่ายประสาทเทียมมีนิวรอน 10 ตัวเนื่องจากเราต้องการจัดประเภทตัวเลขที่เขียนด้วยลายมือเป็น 10 คลาส (0,..9) โดยควรแสดงตัวเลข 10 ตัวระหว่าง 0 ถึง 1 ซึ่งแสดงถึงความน่าจะเป็นที่ตัวเลขนี้จะเป็น 0, 1, 2 และอื่นๆ สำหรับเลเยอร์สุดท้าย เราจะใช้ฟังก์ชันการเปิดใช้งานที่เรียกว่า "softmax"
การใช้ Softmax กับเวกเตอร์ทำได้โดยการหาเลขชี้กำลังของแต่ละองค์ประกอบ แล้วทำให้เวกเตอร์เป็นปกติ โดยปกติจะหารด้วยบรรทัดฐาน "L1" (เช่น ผลรวมของค่าสัมบูรณ์) เพื่อให้ค่าที่ทำให้เป็นปกติมีผลรวมเป็น 1 และสามารถตีความเป็นความน่าจะเป็นได้
บางครั้งเราจะเรียกเอาต์พุตของเลเยอร์สุดท้ายก่อนการเปิดใช้งานว่า "ลอจิท" หากเวกเตอร์นี้คือ L = [L0, L1, L2, L3, L4, L5, L6, L7, L8, L9] จะได้ว่า

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

การไล่ระดับสี
"การฝึก" โครงข่ายประสาทเทียมหมายถึงการใช้รูปภาพและป้ายกำกับการฝึกเพื่อปรับน้ำหนักและอคติเพื่อลดฟังก์ชันการสูญเสียเอนโทรปีแบบครอสให้เหลือน้อยที่สุด วิธีการทำงานมีดังนี้
Cross-entropy เป็นฟังก์ชันของน้ำหนัก อคติ พิกเซลของรูปภาพการฝึก และคลาสที่ทราบ
หากเราคำนวณอนุพันธ์ย่อยของครอสเอนโทรปีเทียบกับน้ำหนักทั้งหมดและอคติทั้งหมด เราจะได้ "การไล่ระดับ" ซึ่งคำนวณสำหรับรูปภาพ ป้ายกำกับ และค่าปัจจุบันของน้ำหนักและอคติที่กำหนด โปรดทราบว่าเรามีค่าถ่วงน้ำหนักและไบแอสได้หลายล้านรายการ ดังนั้นการคำนวณการไล่ระดับจึงดูเหมือนเป็นงานที่ต้องทำมาก โชคดีที่ TensorFlow จัดการเรื่องนี้ให้เรา คุณสมบัติทางคณิตศาสตร์ของเกรเดียนต์คือจะชี้ "ขึ้น" เนื่องจากเราต้องการไปในทิศทางที่ครอสเอนโทรปีต่ำ เราจึงไปในทิศทางตรงกันข้าม เราอัปเดตน้ำหนักและอคติด้วยเศษส่วนของค่าการไล่ระดับ จากนั้นเราจะทำซ้ำไปเรื่อยๆ โดยใช้รูปภาพและป้ายกำกับการฝึกชุดถัดไปในลูปการฝึก หวังว่าสิ่งนี้จะมาบรรจบกันในจุดที่ Cross-Entropy น้อยที่สุด แม้ว่าจะไม่มีอะไรรับประกันว่าค่าต่ำสุดนี้จะไม่ซ้ำกัน

การประมวลผลแบบมินิแบทช์และโมเมนตัม
คุณสามารถคำนวณการไล่ระดับสีในรูปภาพตัวอย่างเพียงรูปเดียวและอัปเดตน้ำหนักและอคติได้ทันที แต่การทำเช่นนั้นในกลุ่มรูปภาพ เช่น 128 รูป จะทำให้ได้การไล่ระดับสีที่แสดงถึงข้อจำกัดที่กำหนดโดยรูปภาพตัวอย่างต่างๆ ได้ดีกว่า และจึงมีแนวโน้มที่จะบรรลุโซลูชันได้เร็วขึ้น ขนาดของมินิแบตช์เป็นพารามิเตอร์ที่ปรับได้
เทคนิคนี้ซึ่งบางครั้งเรียกว่า "การไล่ระดับความชันแบบสุ่ม" มีประโยชน์อีกอย่างที่ใช้งานได้จริงมากกว่า นั่นคือการทำงานกับกลุ่มยังหมายถึงการทำงานกับเมทริกซ์ขนาดใหญ่ขึ้น และโดยปกติแล้วการเพิ่มประสิทธิภาพเมทริกซ์เหล่านี้ใน GPU และ TPU จะทำได้ง่ายกว่า
อย่างไรก็ตาม การบรรจบกันอาจยังคงวุ่นวายเล็กน้อยและอาจหยุดลงได้หากเวกเตอร์การไล่ระดับเป็น 0 ทั้งหมด ซึ่งหมายความว่าเราพบค่าต่ำสุดแล้วใช่ไหม ไม่เสมอไป คอมโพเนนต์การไล่ระดับสีอาจเป็น 0 ในค่าต่ำสุดหรือค่าสูงสุด เวกเตอร์การไล่ระดับที่มีองค์ประกอบหลายล้านรายการ หากองค์ประกอบทั้งหมดเป็น 0 ความน่าจะเป็นที่ 0 ทุกตัวจะสอดคล้องกับจุดต่ำสุดและไม่มีตัวใดสอดคล้องกับจุดสูงสุดจะค่อนข้างน้อย ในพื้นที่ที่มีหลายมิติ จุดอานมักจะพบได้ทั่วไป และเราไม่ต้องการหยุดที่จุดเหล่านั้น

ภาพ: จุดอานม้า การไล่ระดับเป็น 0 แต่ไม่ใช่ค่าต่ำสุดในทุกทิศทาง (การระบุแหล่งที่มาของรูปภาพ Wikimedia: By Nicoguaro - Own work, CC BY 3.0)
วิธีแก้คือการเพิ่มโมเมนตัมให้กับอัลกอริทึมการเพิ่มประสิทธิภาพเพื่อให้ผ่านจุดอานม้าไปได้โดยไม่ต้องหยุด
อภิธานศัพท์
กลุ่มหรือกลุ่มย่อย: การฝึกจะดำเนินการกับกลุ่มข้อมูลการฝึกและป้ายกำกับเสมอ การทำเช่นนี้จะช่วยให้อัลกอริทึมบรรจบกัน มิติข้อมูล "กลุ่ม" มักจะเป็นมิติข้อมูลแรกของเทนเซอร์ข้อมูล เช่น เทนเซอร์ที่มีรูปร่าง [100, 192, 192, 3] มีรูปภาพ 100 รูปขนาด 192x192 พิกเซล โดยมีค่า 3 ค่าต่อพิกเซล (RGB)
การสูญเสียแบบครอสเอนโทรปี: ฟังก์ชันการสูญเสียพิเศษที่มักใช้ในตัวแยกประเภท
เลเยอร์หนาแน่น: เลเยอร์ของนิวรอนที่นิวรอนแต่ละตัวเชื่อมต่อกับนิวรอนทั้งหมดในเลเยอร์ก่อนหน้า
ฟีเจอร์: บางครั้งอินพุตของโครงข่ายประสาทเทียมเรียกว่า "ฟีเจอร์" ศิลปะในการพิจารณาว่าควรป้อนส่วนใดของชุดข้อมูล (หรือการรวมกันของส่วนต่างๆ) ลงในโครงข่ายประสาทเทียมเพื่อให้ได้การคาดการณ์ที่ดีเรียกว่า "การออกแบบฟีเจอร์"
ป้ายกำกับ: ชื่ออื่นของ "คลาส" หรือคำตอบที่ถูกต้องในปัญหาการแยกประเภทภายใต้การดูแล
อัตราการเรียนรู้: เศษส่วนของค่าการไล่ระดับที่ใช้ในการอัปเดตน้ำหนักและอคติในแต่ละการทำซ้ำของลูปการฝึก
ลอจิท: เอาต์พุตของเลเยอร์ของนิวรอนก่อนที่จะใช้ฟังก์ชันการเปิดใช้งานเรียกว่า "ลอจิท" คำนี้มาจาก "ฟังก์ชันโลจิสติก" หรือที่เรียกว่า "ฟังก์ชันซิกมอยด์" ซึ่งเคยเป็นฟังก์ชันกระตุ้นที่ได้รับความนิยมมากที่สุด "เอาต์พุตของนิวรอนก่อนฟังก์ชันลอจิสติก" เปลี่ยนชื่อเป็น "ลอจิท"
loss: ฟังก์ชันข้อผิดพลาดที่เปรียบเทียบเอาต์พุตของโครงข่ายประสาทกับคำตอบที่ถูกต้อง
นิวรอน: คำนวณผลรวมแบบถ่วงน้ำหนักของอินพุต เพิ่มอคติ และป้อนผลลัพธ์ผ่านฟังก์ชันการเปิดใช้งาน
การเข้ารหัสแบบ One-hot: ระบบจะเข้ารหัสคลาส 3 จาก 5 เป็นเวกเตอร์ที่มีองค์ประกอบ 5 รายการ ซึ่งเป็น 0 ทั้งหมด ยกเว้นรายการที่ 3 ซึ่งเป็น 1
relu: หน่วยเชิงเส้นที่แก้ไขแล้ว ฟังก์ชันการเปิดใช้งานยอดนิยมสำหรับนิวรอน
sigmoid: ฟังก์ชันกระตุ้นอีกฟังก์ชันหนึ่งที่เคยได้รับความนิยมและยังคงมีประโยชน์ในกรณีพิเศษ
softmax: ฟังก์ชันการกระตุ้นพิเศษที่ทำงานกับเวกเตอร์ เพิ่มความแตกต่างระหว่างคอมโพเนนต์ที่ใหญ่ที่สุดกับคอมโพเนนต์อื่นๆ ทั้งหมด และยังปรับเวกเตอร์ให้มีผลรวมเป็น 1 เพื่อให้ตีความได้เป็นเวกเตอร์ของความน่าจะเป็น ใช้เป็นขั้นตอนสุดท้ายในตัวแยกประเภท
เทนเซอร์: "เทนเซอร์" คล้ายกับเมทริกซ์ แต่มีจำนวนมิติข้อมูลเท่าใดก็ได้ เทนเซอร์ 1 มิติคือเวกเตอร์ เทนเซอร์ 2 มิติคือเมทริกซ์ จากนั้นคุณก็จะมีเทนเซอร์ที่มี 3, 4, 5 หรือมากกว่านั้น
5. มาดูโค้ดกัน
กลับไปที่สมุดบันทึกการศึกษา แล้วมาอ่านโค้ดกัน
มาดูเซลล์ทั้งหมดในสมุดบันทึกนี้กัน
เซลล์ "พารามิเตอร์"
กำหนดขนาดกลุ่ม จำนวนรอบการฝึก และตำแหน่งของไฟล์ข้อมูลที่นี่ ไฟล์ข้อมูลโฮสต์อยู่ใน Bucket ของ Google Cloud Storage (GCS) ซึ่งเป็นสาเหตุที่อยู่ของไฟล์ขึ้นต้นด้วย gs://
เซลล์ "การนำเข้า"
เราจะนำเข้าไลบรารี Python ที่จำเป็นทั้งหมดที่นี่ รวมถึง TensorFlow และ matplotlib สำหรับการแสดงภาพ
เซลล์ "visualization utilities [RUN ME]****"
เซลล์นี้มีโค้ดภาพที่น่าสนใจ โดยจะยุบอยู่โดยค่าเริ่มต้น แต่คุณสามารถเปิดและดูโค้ดได้เมื่อมีเวลาด้วยการดับเบิลคลิก
เซลล์ "tf.data.Dataset: แยกวิเคราะห์ไฟล์และเตรียมชุดข้อมูลการฝึกและชุดข้อมูลการตรวจสอบ"
เซลล์นี้ใช้ tf.data.Dataset API เพื่อโหลดชุดข้อมูล MNIST จากไฟล์ข้อมูล คุณไม่จำเป็นต้องใช้เวลากับเซลล์นี้มากเกินไป หากสนใจ tf.data.Dataset API โปรดดูบทแนะนำที่อธิบายเรื่องนี้ที่ไปป์ไลน์ข้อมูลที่รวดเร็วของ TPU ในตอนนี้ หลักการพื้นฐานมีดังนี้
ระบบจะจัดเก็บรูปภาพและป้ายกำกับ (คำตอบที่ถูกต้อง) จากชุดข้อมูล MNIST ไว้ในบันทึกที่มีความยาวคงที่ใน 4 ไฟล์ คุณโหลดไฟล์ได้โดยใช้ฟังก์ชันบันทึกแบบคงที่โดยเฉพาะ ดังนี้
imagedataset = tf.data.FixedLengthRecordDataset(image_filename, 28*28, header_bytes=16)
ตอนนี้เรามีชุดข้อมูลไบต์ของรูปภาพแล้ว โดยต้องถอดรหัสเป็นรูปภาพ เรากำหนดฟังก์ชันเพื่อดำเนินการดังกล่าว โดยจะไม่มีการบีบอัดรูปภาพ ดังนั้นฟังก์ชันจึงไม่จำเป็นต้องถอดรหัสใดๆ (decode_raw ไม่ได้ทำอะไรเลย) จากนั้นระบบจะแปลงรูปภาพเป็นค่าทศนิยมระหว่าง 0 ถึง 1 เราสามารถปรับรูปร่างที่นี่เป็นรูปภาพ 2 มิติได้ แต่จริงๆ แล้วเราจะเก็บไว้เป็นอาร์เรย์พิกเซลแบบแบนขนาด 28*28 เนื่องจากเป็นสิ่งที่เลเยอร์หนาแน่นเริ่มต้นของเราคาดหวัง
def read_image(tf_bytestring):
image = tf.io.decode_raw(tf_bytestring, tf.uint8)
image = tf.cast(image, tf.float32)/256.0
image = tf.reshape(image, [28*28])
return image
เราใช้ฟังก์ชันนี้กับชุดข้อมูลโดยใช้ .map และรับชุดข้อมูลรูปภาพ
imagedataset = imagedataset.map(read_image, num_parallel_calls=16)
เราจะอ่านและถอดรหัสป้ายกำกับในลักษณะเดียวกัน และ.zipรูปภาพและป้ายกำกับเข้าด้วยกัน.zip
dataset = tf.data.Dataset.zip((imagedataset, labelsdataset))
ตอนนี้เรามีชุดข้อมูลของคู่ (รูปภาพ ป้ายกำกับ) แล้ว ซึ่งเป็นสิ่งที่โมเดลของเราคาดหวัง เรายังไม่พร้อมที่จะใช้ฟีเจอร์นี้ในฟังก์ชันการฝึกอบรม
dataset = dataset.cache()
dataset = dataset.shuffle(5000, reshuffle_each_iteration=True)
dataset = dataset.repeat()
dataset = dataset.batch(batch_size)
dataset = dataset.prefetch(tf.data.experimental.AUTOTUNE)
API tf.data.Dataset มีฟังก์ชันยูทิลิตีที่จำเป็นทั้งหมดสำหรับการเตรียมชุดข้อมูล
.cache จะแคชชุดข้อมูลใน RAM นี่คือชุดข้อมูลขนาดเล็ก จึงจะใช้งานได้ .shuffle จะสับเปลี่ยนเพลงโดยใช้บัฟเฟอร์ที่มีองค์ประกอบ 5,000 รายการ ข้อมูลการฝึกต้องมีการสับเปลี่ยนอย่างดี .repeat จะวนซ้ำชุดข้อมูล เราจะฝึกโมเดลหลายครั้ง (หลายยุค) .batch จะดึงรูปภาพและป้ายกำกับหลายรายการมารวมกันเป็นมินิแบทช์ สุดท้าย .prefetch สามารถใช้ CPU เพื่อเตรียมชุดข้อมูลถัดไปขณะที่ GPU กำลังฝึกชุดข้อมูลปัจจุบัน
ระบบจะจัดเตรียมชุดข้อมูลการตรวจสอบในลักษณะที่คล้ายกัน ตอนนี้เราพร้อมที่จะกำหนดโมเดลและใช้ชุดข้อมูลนี้เพื่อฝึกโมเดลแล้ว
เซลล์ "โมเดล Keras"
โมเดลทั้งหมดของเราจะเป็นลำดับเลเยอร์ตรงๆ เพื่อให้เราใช้สไตล์ tf.keras.Sequential ในการสร้างโมเดลได้ ในตอนแรกจะเป็นเลเยอร์แบบหนาแน่นชั้นเดียว มีนิวรอน 10 ตัวเนื่องจากเราจัดประเภทตัวเลขที่เขียนด้วยลายมือเป็น 10 คลาส โดยใช้การเปิดใช้งาน "softmax" เนื่องจากเป็นเลเยอร์สุดท้ายในตัวแยกประเภท
โมเดล Keras ยังต้องทราบรูปร่างของอินพุตด้วย tf.keras.layers.Input ใช้เพื่อกำหนดได้ ในที่นี้ เวกเตอร์อินพุตคือเวกเตอร์แบบแบนของค่าพิกเซลที่มีความยาว 28*28
model = tf.keras.Sequential(
[
tf.keras.layers.Input(shape=(28*28,)),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='sgd',
loss='categorical_crossentropy',
metrics=['accuracy'])
# print model layers
model.summary()
# utility callback that displays training curves
plot_training = PlotTraining(sample_rate=10, zoom=1)
การกำหนดค่าโมเดลทำได้ใน Keras โดยใช้ฟังก์ชัน model.compile ในที่นี้เราใช้ตัวเพิ่มประสิทธิภาพพื้นฐาน 'sgd' (Stochastic Gradient Descent) โมเดลการแยกประเภทต้องใช้ Loss Function แบบ Cross-Entropy ซึ่งเรียกว่า 'categorical_crossentropy' ใน Keras สุดท้าย เราขอให้โมเดลคำนวณเมตริก 'accuracy' ซึ่งเป็นเปอร์เซ็นต์ของรูปภาพที่จัดประเภทอย่างถูกต้อง
Keras มีmodel.summary()ยูทิลิตีที่ยอดเยี่ยมซึ่งจะพิมพ์รายละเอียดของโมเดลที่คุณสร้างขึ้น ผู้สอนได้เพิ่มยูทิลิตี PlotTraining (กำหนดไว้ในเซลล์ "ยูทิลิตีการแสดงภาพ") ซึ่งจะแสดงเส้นโค้งการฝึกต่างๆ ในระหว่างการฝึก
เซลล์ "ฝึกและตรวจสอบโมเดล"
ซึ่งเป็นจุดที่การฝึกเกิดขึ้นโดยการเรียกใช้ model.fit และส่งทั้งชุดข้อมูลการฝึกและชุดข้อมูลการตรวจสอบ โดยค่าเริ่มต้น Keras จะเรียกใช้รอบการตรวจสอบเมื่อสิ้นสุดแต่ละ Epoch
model.fit(training_dataset, steps_per_epoch=steps_per_epoch, epochs=EPOCHS,
validation_data=validation_dataset, validation_steps=1,
callbacks=[plot_training])
ใน Keras คุณสามารถเพิ่มลักษณะการทำงานที่กำหนดเองในระหว่างการฝึกได้โดยใช้การเรียกกลับ เราจึงใช้พล็อตการฝึกที่อัปเดตแบบไดนามิกสำหรับเวิร์กช็อปนี้
เซลล์ "แสดงภาพการคาดการณ์"
เมื่อฝึกโมเดลแล้ว เราจะรับการคาดการณ์จากโมเดลได้โดยการเรียกใช้ model.predict():
probabilities = model.predict(font_digits, steps=1)
predicted_labels = np.argmax(probabilities, axis=1)
เราได้เตรียมชุดตัวเลขที่พิมพ์ออกมาซึ่งแสดงผลจากแบบอักษรในเครื่องเพื่อใช้ในการทดสอบ โปรดทราบว่าโครงข่ายประสาทเทียมจะแสดงผลเวกเตอร์ของความน่าจะเป็น 10 รายการจาก "Softmax" สุดท้าย หากต้องการป้ายกำกับ เราต้องดูว่าความน่าจะเป็นใดสูงที่สุด np.argmax จากไลบรารี numpy จะทำหน้าที่ดังกล่าว
หากต้องการทราบเหตุผลที่ต้องใช้พารามิเตอร์ axis=1 โปรดทราบว่าเราประมวลผลรูปภาพ 128 รูปพร้อมกัน ดังนั้นโมเดลจึงแสดงผลเวกเตอร์ความน่าจะเป็น 128 รายการ รูปร่างของเทนเซอร์เอาต์พุตคือ [128, 10] เรากำลังคำนวณ argmax ในความน่าจะเป็น 10 รายการที่แสดงผลสำหรับแต่ละรูปภาพ ดังนั้น axis=1 (แกนแรกคือ 0)
โมเดลอย่างง่ายนี้จดจำตัวเลขได้ถึง 90% ไม่แย่ แต่ตอนนี้คุณจะปรับปรุงสิ่งนี้ได้อย่างมาก

6. การเพิ่มเลเยอร์

เราจะเพิ่มเลเยอร์ลงในโครงข่ายประสาทเพื่อปรับปรุงความแม่นยำในการจดจำ

เราใช้ Softmax เป็นฟังก์ชันกระตุ้นในเลเยอร์สุดท้ายเนื่องจากเป็นฟังก์ชันที่เหมาะกับการจัดประเภทมากที่สุด แต่ในเลเยอร์กลาง เราจะใช้ฟังก์ชันกระตุ้นที่คลาสสิกที่สุด นั่นคือ ซิกมอยด์

เช่น โมเดลของคุณอาจมีลักษณะดังนี้ (อย่าลืมใส่คอมมา tf.keras.Sequential รับรายการเลเยอร์ที่คั่นด้วยคอมมา)
model = tf.keras.Sequential(
[
tf.keras.layers.Input(shape=(28*28,)),
tf.keras.layers.Dense(200, activation='sigmoid'),
tf.keras.layers.Dense(60, activation='sigmoid'),
tf.keras.layers.Dense(10, activation='softmax')
])
ดู "สรุป" ของโมเดล ตอนนี้มีพารามิเตอร์มากกว่าเดิมอย่างน้อย 10 เท่า ซึ่งควรจะดีกว่าเดิมถึง 10 เท่า แต่ไม่รู้ทำไมมันถึงไม่เป็นแบบนั้น ...

ดูเหมือนว่าการขาดทุนจะพุ่งสูงขึ้นด้วย มีบางอย่างที่ไม่ค่อยถูกต้อง
7. การดูแลเป็นพิเศษสำหรับเครือข่ายแบบลึก
คุณเพิ่งได้สัมผัสกับโครงข่ายประสาทเทียม ซึ่งเป็นสิ่งที่ผู้คนเคยออกแบบไว้ในยุค 80 และ 90 จึงไม่แปลกใจเลยว่าทำไมพวกเขาจึงล้มเลิกแนวคิดนี้ ซึ่งนำไปสู่สิ่งที่เรียกว่า "ยุคน้ำแข็งของ AI" ยิ่งคุณเพิ่มเลเยอร์มากเท่าใด เครือข่ายประสาทก็จะยิ่งพบปัญหาในการบรรจบกันมากขึ้นเท่านั้น
ปรากฏว่าโครงข่ายประสาทแบบลึกที่มีหลายชั้น (ปัจจุบันมี 20, 50 หรือแม้แต่ 100 ชั้น) สามารถทำงานได้ดีมาก เพียงแค่ใช้เทคนิคทางคณิตศาสตร์เล็กๆ น้อยๆ เพื่อให้โครงข่ายประสาทแบบลึกทำงานร่วมกัน การค้นพบเคล็ดลับง่ายๆ เหล่านี้เป็นเหตุผลหนึ่งที่ทำให้เกิดการฟื้นฟูดีพลึกนิงในช่วงปี 2010
การเปิดใช้งาน RELU

ฟังก์ชันการกระตุ้นแบบซิกมอยด์มีปัญหาค่อนข้างมากในเครือข่ายแบบลึก โดยจะบีบอัดค่าทั้งหมดระหว่าง 0 ถึง 1 และเมื่อทำซ้ำๆ เอาต์พุตของนิวรอนและค่าการไล่ระดับสีอาจหายไปทั้งหมด มีการกล่าวถึงด้วยเหตุผลทางประวัติศาสตร์ แต่เครือข่ายสมัยใหม่ใช้ RELU (Rectified Linear Unit) ซึ่งมีลักษณะดังนี้

ในทางกลับกัน relu มีอนุพันธ์เป็น 1 อย่างน้อยก็ทางด้านขวา การเปิดใช้งาน RELU จะทำให้มีนิวรอนอื่นๆ ที่ให้การไล่ระดับที่ไม่ใช่ 0 อย่างชัดเจนเสมอ แม้ว่าการไล่ระดับที่มาจากนิวรอนบางตัวจะเป็น 0 ก็ตาม และการฝึกก็สามารถดำเนินต่อไปได้ในอัตราที่ดี
เครื่องมือเพิ่มประสิทธิภาพที่ดีขึ้น
ในพื้นที่ที่มีมิติสูงมาก เช่น ที่นี่ ซึ่งมีน้ำหนักและอคติประมาณ 10,000 รายการ "จุดอานม้า" มักจะเกิดขึ้นบ่อย จุดเหล่านี้ไม่ใช่จุดต่ำสุดเฉพาะที่ แต่เป็นจุดที่การไล่ระดับเป็น 0 และเครื่องมือเพิ่มประสิทธิภาพการไล่ระดับแบบไล่ลงจะติดอยู่ที่จุดนั้น TensorFlow มีตัวเพิ่มประสิทธิภาพที่พร้อมใช้งานครบทุกรูปแบบ ซึ่งรวมถึงตัวเพิ่มประสิทธิภาพบางตัวที่ทำงานร่วมกับค่าความเฉื่อยและจะผ่านจุดอานได้อย่างปลอดภัย
การเริ่มต้นแบบสุ่ม
ศิลปะในการเริ่มต้นค่าไบแอสของน้ำหนักก่อนการฝึกเป็นสาขาการวิจัยในตัวของมันเอง โดยมีเอกสารจำนวนมากที่เผยแพร่ในหัวข้อนี้ คุณดูตัวเริ่มต้นทั้งหมดที่มีใน Keras ได้ที่นี่ โชคดีที่ Keras ทำสิ่งที่ถูกต้องโดยค่าเริ่มต้นและใช้'glorot_uniform'ตัวเริ่มต้น ซึ่งดีที่สุดในเกือบทุกกรณี
คุณไม่ต้องดำเนินการใดๆ เนื่องจาก Keras ทำสิ่งที่ถูกต้องอยู่แล้ว
NaN ???
สูตรครอสเอนโทรปีเกี่ยวข้องกับลอการิทึม และ log(0) ไม่ใช่ตัวเลข (NaN ซึ่งเป็นข้อขัดข้องทางตัวเลขหากคุณต้องการ) อินพุตของ Cross-Entropy เป็น 0 ได้ไหม อินพุตมาจาก Softmax ซึ่งเป็นฟังก์ชันเลขชี้กำลัง และฟังก์ชันเลขชี้กำลังจะไม่มีค่าเป็น 0 เราจึงปลอดภัย
จริงเหรอ ในโลกที่สวยงามของคณิตศาสตร์ เราจะปลอดภัย แต่ในโลกคอมพิวเตอร์ exp(-150) ซึ่งแสดงในรูปแบบ float32 จะเป็น 0 และ Cross-Entropy จะหยุดทำงาน
โชคดีที่คุณไม่ต้องทำอะไรที่นี่เช่นกัน เนื่องจาก Keras จะจัดการเรื่องนี้และคำนวณ Softmax ตามด้วย Cross-Entropy อย่างระมัดระวังเป็นพิเศษเพื่อให้มั่นใจถึงความเสถียรทางตัวเลขและหลีกเลี่ยง NaN ที่น่ากลัว
สำเร็จไหม

ตอนนี้คุณควรมีความแม่นยำถึง 97% เป้าหมายในการเวิร์กช็อปนี้คือการทำให้ได้มากกว่า 99% อย่างเห็นได้ชัด ดังนั้นมาลุยกันต่อเลย
หากคุณติดขัด โปรดดูวิธีแก้ปัญหาในตอนนี้
8. การลดอัตราการเรียนรู้
เราอาจลองฝึกให้เร็วขึ้นได้ไหม อัตราการเรียนรู้เริ่มต้นในตัวเพิ่มประสิทธิภาพ Adam คือ 0.001 มาลองเพิ่มกัน
การขับเร็วขึ้นดูเหมือนจะไม่ช่วยอะไรมาก แล้วเสียงดังทั้งหมดนี้คืออะไร

เส้นโค้งการฝึกนั้นมีสัญญาณรบกวนมาก และดูเส้นโค้งการตรวจสอบทั้ง 2 เส้น ซึ่งจะขึ้นๆ ลงๆ ซึ่งหมายความว่าเรากำลังเดินหน้าเร็วเกินไป เราอาจกลับไปใช้ความเร็วเดิมได้ แต่ก็มีวิธีที่ดีกว่า

วิธีแก้ปัญหาที่ดีคือการเริ่มต้นอย่างรวดเร็วและลดอัตราการเรียนรู้แบบเอ็กซ์โปเนนเชียล ใน Keras คุณทำได้โดยใช้tf.keras.callbacks.LearningRateSchedulerการเรียกกลับ
โค้ดที่มีประโยชน์สำหรับการคัดลอกและวาง
# lr decay function
def lr_decay(epoch):
return 0.01 * math.pow(0.6, epoch)
# lr schedule callback
lr_decay_callback = tf.keras.callbacks.LearningRateScheduler(lr_decay, verbose=True)
# important to see what you are doing
plot_learning_rate(lr_decay, EPOCHS)
อย่าลืมใช้ lr_decay_callback ที่คุณสร้างขึ้น เพิ่มลงในรายการการเรียกกลับใน model.fit โดยทำดังนี้
model.fit(..., callbacks=[plot_training, lr_decay_callback])
การเปลี่ยนแปลงเล็กๆ น้อยๆ นี้ส่งผลลัพธ์ที่น่าทึ่ง คุณจะเห็นว่าเสียงรบกวนส่วนใหญ่หายไปแล้ว และความแม่นยำของการทดสอบตอนนี้สูงกว่า 98% อย่างต่อเนื่อง

9. Dropout, Overfitting
ตอนนี้โมเดลดูเหมือนจะบรรจบกันได้ดี มาเจาะลึกกันอีก
วิธีนี้ช่วยได้ไหม

ไม่จริง ความแม่นยำยังคงอยู่ที่ 98% และดูการสูญเสียการตรวจสอบ กำลังเพิ่มขึ้น อัลกอริทึมการเรียนรู้จะทำงานกับข้อมูลการฝึกเท่านั้นและเพิ่มประสิทธิภาพการสูญเสียการฝึกตามนั้น โมเดลไม่เคยเห็นข้อมูลการตรวจสอบ ดังนั้นจึงไม่น่าแปลกใจที่หลังจากผ่านไปสักระยะหนึ่ง งานของโมเดลจะไม่มีผลต่อการสูญเสียการตรวจสอบอีกต่อไป ซึ่งจะหยุดลดลงและบางครั้งอาจเพิ่มขึ้นด้วย
ซึ่งจะไม่ส่งผลต่อความสามารถในการจดจำในโลกแห่งความเป็นจริงของโมเดลในทันที แต่จะทำให้คุณไม่สามารถเรียกใช้การทำซ้ำหลายครั้งได้ และโดยทั่วไปแล้วจะเป็นสัญญาณว่าการฝึกไม่ส่งผลดีอีกต่อไป

การแยกส่วนนี้มักเรียกว่า "Overfitting" และเมื่อเห็นการแยกส่วนนี้ คุณสามารถลองใช้เทคนิคการทำให้เป็นปกติที่เรียกว่า "Dropout" เทคนิค Dropout จะยิงนิวรอนแบบสุ่มในการวนซ้ำการฝึกแต่ละครั้ง
ทำงานได้ดีหรือไม่

เสียงรบกวนจะกลับมาอีกครั้ง (ไม่น่าแปลกใจเนื่องจากวิธีที่การหยุดทำงานเกิดขึ้น) การสูญเสียการตรวจสอบดูเหมือนจะไม่เพิ่มขึ้นอีกต่อไป แต่โดยรวมแล้วสูงกว่ากรณีที่ไม่มี Dropout และความแม่นยำในการตรวจสอบก็ลดลงเล็กน้อย ซึ่งเป็นผลลัพธ์ที่ค่อนข้างน่าผิดหวัง
ดูเหมือนว่าการดรอปเอาต์ไม่ใช่โซลูชันที่ถูกต้อง หรืออาจเป็นเพราะ "การฟิตมากเกินไป" เป็นแนวคิดที่ซับซ้อนกว่า และสาเหตุบางอย่างไม่สามารถแก้ไขได้ด้วยการ "ดรอปเอาต์"
"Overfitting" คืออะไร Overfitting เกิดขึ้นเมื่อโครงข่ายประสาทเทียมเรียนรู้ "ไม่ดี" ในลักษณะที่ใช้ได้กับตัวอย่างการฝึก แต่ใช้ได้ไม่ดีนักกับข้อมูลในโลกแห่งความเป็นจริง มีเทคนิคการทำให้เป็นปกติ เช่น ดรอปเอาต์ ซึ่งบังคับให้โมเดลเรียนรู้ได้ดีขึ้น แต่การฟิตมากเกินไปยังมีรากฐานที่ลึกกว่านั้น

การเกิด Overfitting ขั้นพื้นฐานเกิดขึ้นเมื่อโครงข่ายประสาทเทียมมีระดับอิสระมากเกินไปสำหรับปัญหาที่กำลังพิจารณา ลองนึกภาพว่าเรามีนิวรอนจำนวนมากจนเครือข่ายสามารถจัดเก็บรูปภาพการฝึกทั้งหมดไว้ในนิวรอนเหล่านั้น แล้วจดจำรูปภาพได้ด้วยการจับคู่รูปแบบ แต่จะใช้งานกับข้อมูลจริงไม่ได้เลย โครงข่ายประสาทเทียมต้องมีข้อจำกัดบางอย่างเพื่อให้ต้องสรุปสิ่งที่เรียนรู้ระหว่างการฝึก
หากมีข้อมูลการฝึกน้อยมาก แม้แต่เครือข่ายขนาดเล็กก็สามารถจดจำข้อมูลนั้นได้ และคุณจะเห็น "การปรับมากเกินไป" โดยทั่วไปแล้ว คุณต้องมีข้อมูลจำนวนมากเสมอเพื่อฝึกโครงข่ายประสาทเทียม
สุดท้ายนี้ หากคุณทำทุกอย่างตามที่แนะนำ ทดลองใช้เครือข่ายขนาดต่างๆ เพื่อให้แน่ใจว่ามีการจำกัดระดับอิสระ ใช้ Dropout และฝึกโมเดลด้วยข้อมูลจำนวนมาก คุณอาจยังคงติดอยู่ที่ระดับประสิทธิภาพที่ดูเหมือนว่าจะไม่มีอะไรปรับปรุงได้ ซึ่งหมายความว่าโครงข่ายประสาทเทียมในรูปแบบปัจจุบันไม่สามารถดึงข้อมูลเพิ่มเติมจากข้อมูลของคุณได้ ดังเช่นกรณีของเราที่นี่
คุณยังจำได้ไหมว่าเราใช้รูปภาพโดยแปลงเป็นเวกเตอร์เดียวได้อย่างไร นั่นเป็นความคิดที่ไม่ดีเลย ตัวเลขที่เขียนด้วยลายมือประกอบด้วยรูปร่างต่างๆ และเราทิ้งข้อมูลรูปร่างเมื่อทำให้พิกเซลแบน อย่างไรก็ตาม มีโครงข่ายประสาทเทียมประเภทหนึ่งที่ใช้ประโยชน์จากข้อมูลรูปร่างได้ นั่นคือ โครงข่ายประสาทแบบคอนโวลูชัน มาลองใช้กัน
หากคุณติดขัด โปรดดูวิธีแก้ปัญหาในตอนนี้
10. [INFO] เครือข่าย Convolutional
โดยสรุป
หากคุณทราบคำศัพท์ทั้งหมดที่ตัวหนาในย่อหน้าถัดไปแล้ว ให้ไปที่แบบฝึกหัดถัดไป หากคุณเพิ่งเริ่มต้นใช้งาน Convolutional Neural Network โปรดอ่านต่อ

ภาพประกอบ: การกรองรูปภาพด้วยฟิลเตอร์ 2 รายการที่ต่อเนื่องกันซึ่งสร้างจากน้ำหนักที่เรียนรู้ได้ขนาด 4x4x3=48
เครือข่ายประสาทแบบคอนโวลูชันอย่างง่ายใน Keras มีลักษณะดังนี้
model = tf.keras.Sequential([
tf.keras.layers.Reshape(input_shape=(28*28,), target_shape=(28, 28, 1)),
tf.keras.layers.Conv2D(kernel_size=3, filters=12, activation='relu'),
tf.keras.layers.Conv2D(kernel_size=6, filters=24, strides=2, activation='relu'),
tf.keras.layers.Conv2D(kernel_size=6, filters=32, strides=2, activation='relu'),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(10, activation='softmax')
])

ในเลเยอร์ของเครือข่าย Convolutional "นิวรอน" จะทำการหาผลรวมแบบถ่วงน้ำหนักของพิกเซลที่อยู่เหนือขึ้นไปในบริเวณเล็กๆ ของรูปภาพเท่านั้น โดยจะเพิ่มอคติและป้อนผลรวมผ่านฟังก์ชันการเปิดใช้งาน เช่นเดียวกับที่นิวรอนในเลเยอร์ Dense ปกติจะทำ จากนั้นจะดำเนินการนี้ซ้ำทั่วทั้งรูปภาพโดยใช้น้ำหนักเดียวกัน โปรดทราบว่าในเลเยอร์แบบหนาแน่น นิวรอนแต่ละตัวจะมีน้ำหนักของตัวเอง ในที่นี้ "แพตช์" เดียวของน้ำหนักจะเลื่อนไปทั่วรูปภาพในทั้ง 2 ทิศทาง ("การสังวัตนาการ") เอาต์พุตมีค่ามากเท่ากับจำนวนพิกเซลในรูปภาพ (แม้ว่าอาจต้องมีการเว้นขอบบ้าง) ซึ่งเป็นการดำเนินการกรอง ในภาพด้านบน จะใช้ตัวกรองที่มีน้ำหนัก 4x4x3=48
อย่างไรก็ตาม น้ำหนัก 48 รายการจะไม่เพียงพอ หากต้องการเพิ่มระดับอิสระ เราจะทำซ้ำการดำเนินการเดียวกันกับชุดน้ำหนักใหม่ ซึ่งจะสร้างเอาต์พุตตัวกรองชุดใหม่ เราจะเรียกเอาต์พุตนี้ว่า "แชแนล" โดยเปรียบเทียบกับแชแนล R,G,B ในรูปภาพอินพุต

คุณสามารถรวมชุดน้ำหนัก 2 ชุด (หรือมากกว่า) เป็นเทนเซอร์เดียวได้โดยการเพิ่มมิติข้อมูลใหม่ ซึ่งจะทำให้เราได้รูปร่างทั่วไปของเทนเซอร์น้ำหนักสำหรับเลเยอร์ Convolutional เนื่องจากจำนวนช่องอินพุตและเอาต์พุตเป็นพารามิเตอร์ เราจึงเริ่มซ้อนและเชื่อมต่อเลเยอร์ Convolutional ได้

ภาพ: เครือข่ายประสาทแบบคอนโวลูชันจะเปลี่ยน "ก้อน" ข้อมูลให้เป็น "ก้อน" ข้อมูลอื่นๆ
การสังวัตน์แบบก้าวกระโดด การรวมสูงสุด
การดำเนินการ Convolution ด้วย Stride 2 หรือ 3 จะช่วยให้เราลดขนาด Data Cube ที่ได้ในมิติแนวนอนได้ด้วย ซึ่งมีวิธีทั่วไป 2 วิธีดังนี้
- การสังวัตน์แบบมีระยะก้าวกระโดด: ตัวกรองแบบเลื่อนตามที่อธิบายไว้ข้างต้น แต่มีระยะก้าวกระโดด > 1
- Max Pooling: หน้าต่างเลื่อนที่ใช้การดำเนินการ MAX (โดยปกติจะใช้กับแพตช์ 2x2 ซึ่งทำซ้ำทุกๆ 2 พิกเซล)

ภาพประกอบ: การเลื่อนหน้าต่างการคำนวณ 3 พิกเซลจะทำให้ค่าเอาต์พุตน้อยลง การสังวัตน์แบบก้าวย่างหรือการรวมสูงสุด (ค่าสูงสุดในหน้าต่าง 2x2 ที่เลื่อนตามก้าวย่าง 2) เป็นวิธีลดขนาดก้อนข้อมูลในมิติข้อมูลแนวนอน
เลเยอร์สุดท้าย
หลังจากเลเยอร์ Convolutional สุดท้าย ข้อมูลจะอยู่ในรูปแบบ "ก้อน" การป้อนผ่านเลเยอร์แบบหนาแน่นสุดท้ายทำได้ 2 วิธี
วิธีแรกคือการทำให้คิวบ์ข้อมูลแบนราบเป็นเวกเตอร์ แล้วป้อนไปยังเลเยอร์ Softmax บางครั้งคุณอาจเพิ่มเลเยอร์แบบหนาแน่นก่อนเลเยอร์ Softmax ได้ด้วย ซึ่งมักจะมีค่าใช้จ่ายสูงในแง่ของจำนวนน้ำหนัก เลเยอร์หนาแน่นที่ส่วนท้ายของเครือข่าย Convolutional อาจมีน้ำหนักมากกว่าครึ่งหนึ่งของเครือข่ายประสาททั้งหมด
นอกจากจะใช้เลเยอร์แบบหนาแน่นที่มีราคาแพงแล้ว เรายังสามารถแบ่ง "ก้อน" ข้อมูลขาเข้าออกเป็นหลายส่วนตามจำนวนคลาส เฉลี่ยค่าของข้อมูล และป้อนค่าเหล่านี้ผ่านฟังก์ชันการเปิดใช้งาน Softmax ได้ด้วย การสร้างส่วนหัวการแยกประเภทด้วยวิธีนี้จะไม่มีค่าใช้จ่าย ใน Keras มีเลเยอร์สำหรับสิ่งนี้: tf.keras.layers.GlobalAveragePooling2D()

ข้ามไปยังส่วนถัดไปเพื่อสร้างเครือข่าย Convolutional สำหรับปัญหาที่กำลังพิจารณา
11. เครือข่าย Convolutional
มาสร้างเครือข่าย Convolutional สำหรับการจดจำตัวเลขที่เขียนด้วยลายมือกัน เราจะใช้เลเยอร์ Convolutional 3 เลเยอร์ที่ด้านบน เลเยอร์ Softmax Readout แบบเดิมที่ด้านล่าง และเชื่อมต่อเลเยอร์เหล่านั้นด้วยเลเยอร์ Fully-Connected 1 เลเยอร์

โปรดสังเกตว่าเลเยอร์ Convolutional ที่ 2 และ 3 มีระยะก้าวยาว 2 ซึ่งอธิบายได้ว่าเหตุใดเลเยอร์ดังกล่าวจึงลดจำนวนค่าเอาต์พุตจาก 28x28 เป็น 14x14 และจากนั้นเป็น 7x7
มาเขียนโค้ด Keras กัน
ต้องพิจารณาเป็นพิเศษก่อนเลเยอร์ Convolutional แรก ซึ่งคาดหวังว่าจะมี "ลูกบาศก์" ข้อมูล 3 มิติ แต่ชุดข้อมูลของเราได้รับการตั้งค่าสำหรับเลเยอร์หนาแน่นและพิกเซลทั้งหมดของรูปภาพจะแบนเป็นเวกเตอร์ เราต้องปรับรูปร่างกลับเป็นรูปภาพขนาด 28x28x1 (1 ช่องสำหรับรูปภาพระดับสีเทา)
tf.keras.layers.Reshape(input_shape=(28*28,), target_shape=(28, 28, 1))
คุณสามารถใช้บรรทัดนี้แทนเลเยอร์ tf.keras.layers.Input ที่คุณมีอยู่จนถึงตอนนี้
ใน Keras ไวยากรณ์สำหรับเลเยอร์ Convolutional ที่เปิดใช้งาน "relu" คือ

tf.keras.layers.Conv2D(kernel_size=3, filters=12, padding='same', activation='relu')
สำหรับการ Convolution ที่มีระยะก้าวนั้น คุณจะเขียนได้ดังนี้
tf.keras.layers.Conv2D(kernel_size=6, filters=24, padding='same', activation='relu', strides=2)
วิธีแปลงข้อมูลลูกบาศก์ให้เป็นเวกเตอร์เพื่อให้เลเยอร์หนาแน่นใช้ได้
tf.keras.layers.Flatten()
และสำหรับเลเยอร์หนาแน่น ไวยากรณ์จะยังคงเหมือนเดิม
tf.keras.layers.Dense(200, activation='relu')
โมเดลของคุณทำลายกำแพงความแม่นยำ 99% ได้หรือไม่ เกือบถูกแล้ว... แต่ดูที่เส้นโค้งการสูญเสียการตรวจสอบ คุ้นๆ ไหม

และดูการคาดการณ์ด้วย ในครั้งแรก คุณจะเห็นว่าระบบจดจำตัวเลขทดสอบ 10,000 ตัวส่วนใหญ่ได้อย่างถูกต้องแล้ว เหลือเพียงประมาณ 4½ แถวที่ตรวจจับผิด (ประมาณ 110 หลักจาก 10,000 หลัก)

หากคุณติดขัด โปรดดูวิธีแก้ปัญหาในตอนนี้
12. Dropout again
การฝึกก่อนหน้านี้แสดงให้เห็นสัญญาณที่ชัดเจนของการฟิตมากเกินไป (และยังมีความแม่นยำไม่ถึง 99%) เราควรลองใช้ Dropout อีกครั้งไหม
ครั้งนี้เป็นอย่างไรบ้าง

ดูเหมือนว่าการดรอปเอาต์จะใช้ได้ในครั้งนี้ การสูญเสียการตรวจสอบไม่เพิ่มขึ้นอีกต่อไป และความแม่นยำสุดท้ายควรสูงกว่า 99% ยินดีด้วย
ครั้งแรกที่เราพยายามใช้ Dropout เราคิดว่าเรามีปัญหา Overfitting แต่จริงๆ แล้วปัญหาอยู่ที่สถาปัตยกรรมของโครงข่ายประสาทเทียม เราไม่สามารถดำเนินการต่อได้หากไม่มีเลเยอร์ Convolutional และไม่มีอะไรที่ Dropout จะทำได้
คราวนี้ดูเหมือนว่าการปรับมากเกินไปเป็นสาเหตุของปัญหา และการดรอปเอาต์ช่วยได้จริง โปรดทราบว่ามีหลายสิ่งหลายอย่างที่อาจทำให้เส้นโค้งการสูญเสียการฝึกและเส้นโค้งการสูญเสียการตรวจสอบไม่สอดคล้องกัน โดยการสูญเสียการตรวจสอบจะเพิ่มขึ้น การปรับมากเกินไป (มีระดับอิสระมากเกินไป ซึ่งเครือข่ายใช้ไม่ดี) เป็นเพียงหนึ่งในนั้น หากชุดข้อมูลมีขนาดเล็กเกินไปหรือสถาปัตยกรรมของโครงข่ายประสาทไม่เพียงพอ คุณอาจเห็นลักษณะการทำงานที่คล้ายกันในเส้นโค้งการสูญเสีย แต่ Dropout จะไม่ช่วย
13. การแปลงเป็นรูปแบบมาตรฐานแบบกลุ่ม
สุดท้าย ลองเพิ่มการทําให้เป็นปกติแบบกลุ่ม
ในทางทฤษฎีแล้ว คุณเพียงแค่ต้องจำกฎ 2-3 ข้อต่อไปนี้
ตอนนี้เรามาทำตามตำรากันก่อนและเพิ่มเลเยอร์ Batch Norm ในแต่ละเลเยอร์ของโครงข่ายประสาทเทียม ยกเว้นเลเยอร์สุดท้าย อย่าเพิ่มลงในเลเยอร์ "softmax" สุดท้าย ซึ่งจะไม่มีประโยชน์ในกรณีดังกล่าว
# Modify each layer: remove the activation from the layer itself.
# Set use_bias=False since batch norm will play the role of biases.
tf.keras.layers.Conv2D(..., use_bias=False),
# Batch norm goes between the layer and its activation.
# The scale factor can be turned off for Relu activation.
tf.keras.layers.BatchNormalization(scale=False, center=True),
# Finish with the activation.
tf.keras.layers.Activation('relu'),
ตอนนี้ความแม่นยำเป็นอย่างไร

เพียงปรับแต่งเล็กน้อย (BATCH_SIZE=64, พารามิเตอร์การลดอัตราการเรียนรู้ 0.666, อัตราการหลุดบนเลเยอร์หนาแน่น 0.3) และโชคดีเล็กน้อย คุณก็จะได้ 99.5% การปรับอัตราการเรียนรู้และการปรับการหยุดเรียนรู้ดำเนินการตาม "แนวทางปฏิบัติแนะนำ" สำหรับการใช้ Batch Normalization ดังนี้
- Batch Norm ช่วยให้โครงข่ายประสาทเทียมบรรจบกันและมักจะช่วยให้คุณฝึกได้เร็วขึ้น
- Batch Norm เป็นตัวควบคุม โดยปกติแล้ว คุณสามารถลดจำนวนการดรอปเอาต์ที่ใช้ หรือแม้แต่ไม่ใช้การดรอปเอาต์เลยก็ได้
สมุดบันทึกโซลูชันมีการฝึก 99.5% ดังนี้
14. ฝึกโมเดลในระบบคลาวด์บนฮาร์ดแวร์ประสิทธิภาพสูง: AI Platform

คุณจะเห็นโค้ดเวอร์ชันที่พร้อมใช้งานในระบบคลาวด์ในโฟลเดอร์ mlengine บน GitHub พร้อมกับวิธีการเรียกใช้ใน AI Platform ของ Google Cloud ก่อนที่จะเรียกใช้ส่วนนี้ คุณจะต้องสร้างบัญชี Google Cloud และเปิดใช้การเรียกเก็บเงิน ทรัพยากรที่จำเป็นในการทำแล็บควรมีมูลค่าไม่เกิน 2 ดอลลาร์ (สมมติว่าใช้เวลาฝึก 1 ชั่วโมงใน GPU เครื่องเดียว) วิธีเตรียมบัญชี
- สร้างโปรเจ็กต์ Google Cloud Platform ( http://cloud.google.com/console)
- เปิดใช้การเรียกเก็บเงิน
- ติดตั้งเครื่องมือบรรทัดคำสั่งของ GCP ( GCP SDK ที่นี่)
- สร้าง Bucket ของ Google Cloud Storage (วางไว้ในภูมิภาค
us-central1) ระบบจะใช้ Bucket นี้เพื่อจัดเตรียมโค้ดการฝึกและจัดเก็บโมเดลที่ฝึกแล้ว - เปิดใช้ API ที่จำเป็นและขอโควต้าที่จำเป็น (เรียกใช้คำสั่งการฝึก 1 ครั้ง แล้วคุณจะได้รับข้อความแสดงข้อผิดพลาดที่บอกให้คุณเปิดใช้)
15. ยินดีด้วย
คุณได้สร้างโครงข่ายประสาทเทียมแรกและฝึกให้มีความแม่นยำถึง 99% เทคนิคที่ได้เรียนรู้ตลอดเส้นทางไม่ได้เจาะจงเฉพาะชุดข้อมูล MNIST แต่จริงๆ แล้วเทคนิคเหล่านี้มีการใช้กันอย่างแพร่หลายเมื่อทำงานกับโครงข่ายประสาทเทียม และในตอนท้ายนี้ เราขอส่งการ์ด "สรุปย่อ" สำหรับห้องทดลองในเวอร์ชันการ์ตูนให้คุณ คุณสามารถใช้เพื่อจดจำสิ่งที่ได้เรียนรู้ดังนี้

ขั้นตอนถัดไป
- หลังจากเครือข่ายที่เชื่อมต่ออย่างสมบูรณ์และเครือข่าย Convolutional แล้ว คุณควรดูเครือข่ายประสาทแบบเกิดซ้ำ
- Google Cloud มี AI Platform เพื่อให้คุณเรียกใช้การฝึกหรือการอนุมานในระบบคลาวด์บนโครงสร้างพื้นฐานแบบกระจายได้
- สุดท้ายนี้ เรายินดีรับฟังความคิดเห็น โปรดแจ้งให้เราทราบหากพบสิ่งผิดปกติในห้องทดลองนี้หรือหากคุณคิดว่าควรมีการปรับปรุง เราจัดการความคิดเห็นผ่านปัญหาใน GitHub [feedback link]

|
|
ภาพการ์ตูนทั้งหมดในห้องทดลองนี้มีลิขสิทธิ์ของ alexpokusay / 123RF stock photos
ผู้เขียน: Martin GörnerTwitter: 