“การเรียนรู้เชิงลึก”, “การเรียนรู้ของเครื่อง”, “Python”
การจำแนกภาพโดยใช้การเรียนรู้เชิงลึกและ PyTorch: กรณีศึกษาพร้อมข้อมูลภาพดอกไม้
การจำแนกภาพดอกไม้โดยใช้ Convolutional Deep Neural Network พร้อมไลบรารี PyTorch
การจัดประเภทข้อมูลรูปภาพเป็นหนึ่งในการใช้งานเทคนิค Deep Learning ที่ได้รับความนิยมอย่างมาก ในบทความนี้ เราจะหารือเกี่ยวกับการระบุภาพดอกไม้โดยใช้โครงข่ายประสาทเทียมแบบ deep convolutional
สำหรับสิ่งนี้ เราจะใช้ไลบรารี PyTorch, TorchVision และ PIL ของ Python
การสำรวจข้อมูล
ชุดข้อมูลที่จำเป็นสำหรับปัญหานี้สามารถพบได้ที่ "Kaggle" มันมีโครงสร้างโฟลเดอร์และรูปภาพดอกไม้อยู่ข้างใน ดอกไม้มี 5 ชนิด โครงสร้างโฟลเดอร์มีลักษณะดังนี้
ตอนนี้เราจะเห็นตัวอย่างภาพดอกไม้จากโฟลเดอร์ 'rose'
show_image("../data/flowers/rose/537207677_f96a0507bb.jpg")
การประมวลผลข้อมูลล่วงหน้า
PyTorch คาดหวังข้อมูลในรูปแบบของ 'เทนเซอร์' เสมอ 'เทนเซอร์' เหล่านี้ทำงานระหว่างโหนดของโครงข่ายประสาทเทียมและมีข้อมูลต้นฉบับและข้อมูลก่อนหรือหลังการประมวลผล โดยพื้นฐานแล้ว กล่าวโดยย่อว่า 'เทนเซอร์' นั้นคล้ายคลึงกับอาร์เรย์ 'ตัวเลข'
สำหรับข้อมูลรูปภาพ เราต้องอ่านรูปภาพเป็นเทนเซอร์และใช้ขั้นตอนก่อนการประมวลผลหลายๆ ขั้นตอนก่อนที่จะทำการจำแนกประเภทใดๆ
เราสามารถพิจารณารูปภาพเป็นเทนเซอร์สามมิติได้ แต่ละภาพสามารถมีค่าสีของพิกเซลได้ 3 ประเภท ได้แก่ แดง เขียว และน้ำเงิน ตามลำดับ เราเรียกสิ่งนี้ว่าการเข้ารหัสสี RGB อีกสองมิติคือค่าพิกเซลตามความยาวและความกว้าง
โดยทั่วไป ขั้นตอนก่อนการประมวลผลทั่วไปสองขั้นตอนจำเป็นสำหรับข้อมูลภาพตามที่ระบุด้านล่าง:
- ปรับขนาดเป็นเทมเพลต:ปรับขนาดรูปภาพให้เป็นรูปทรงสี่เหลี่ยม ในกรณีของเรา เราจะปรับขนาดภาพแต่ละภาพเป็นภาพขนาด 64x64
- การทำให้เป็นมาตรฐาน:การทำให้เป็นมาตรฐานทางสถิติโดยใช้กลไก (x — ค่าเฉลี่ย)/sd ของแต่ละค่าพิกเซล ช่วยปรับปรุงการแสดงภาพ ปรับปรุงคุณสมบัติ และขยายคอนทราสต์ในภาพ
เมื่อใช้ PyTorch เราจะทำชุดการประมวลผลล่วงหน้านี้
นอกจากนี้เรายังสามารถกำหนดฟังก์ชันเพื่อแสดงชุดของภาพที่แปลงแล้วได้
ตอนนี้เราสามารถเห็นภาพที่แปลงแล้วของชุดแรกได้
show_transformed_image(make_grid(image))
เรายังสามารถมีคลาสเพื่อทำดัชนีพจนานุกรมข้อมูลได้
ซึ่งจะช่วยในการระบุชั้นเรียน
การสร้างแบบจำลอง
หากต้องการสร้างโมเดลแมชชีนเลิร์นนิงสำหรับข้อมูลรูปภาพ การป้อนค่าพิกเซลเพียงอย่างเดียวนั้นไม่เพียงพอ มีคุณสมบัติที่ซ่อนอยู่มากมายในภาพที่จะไม่ถูกค้นพบ สำหรับสิ่งนี้ เราควรใช้การผสมผสานระหว่าง Convolution & Max-Polling Layer เพื่อแยกคุณสมบัติที่สำคัญ
ชั้น Convolution
ในทางคณิตศาสตร์ การดำเนินการบิดระหว่างสองฟังก์ชัน f & g ถูกกำหนดเป็น
ในทางปฏิบัติ ถ้าเราถือว่า f เป็นอิมเมจเทนเซอร์ g ควรเป็นเทนเซอร์อีกตัวหนึ่งที่สามารถทำงานเป็น "เคอร์เนลการบิด" ได้
เป็นการสรุปแบบพิกเซลของค่าคูณของเทนเซอร์สองตัว
แผนภาพด้านล่างแสดงผลของการบิดบนเทนเซอร์อิมเมจตัวอย่าง
เคอร์เนล Convolution ขนาด 3x3 เคลื่อนที่ไปรอบ ๆ เทนเซอร์รูปภาพเป็นหน้าต่างที่เริ่มต้นจากตำแหน่ง (0,0) และผลลัพธ์ตัวอย่างที่ (0,0) ของเทนเซอร์เอาท์พุตมีลักษณะดังนี้การคำนวณด้านล่าง
เอาท์พุต (0,0) = อิมเมจเทนเซอร์ (0,0) x เคอร์เนล (0,0) + เทนเซอร์รูปภาพ (0,1) x เคอร์เนล (0,1) + เทนเซอร์รูปภาพ (0,2) x เคอร์เนล (0,2 ) + เทนเซอร์รูปภาพ (1,0) x เคอร์เนล (1,0) + เทนเซอร์รูปภาพ (1,1) x เคอร์เนล (1,1) + เทนเซอร์รูปภาพ (1,2) x เคอร์เนล (1,2) + เทนเซอร์รูปภาพ ( 2,0) x เคอร์เนล (2,0) + เทนเซอร์รูปภาพ (2,1) x เคอร์เนล (2,1) + เทนเซอร์รูปภาพ (2,2) x เคอร์เนล (2,2) = 1 x 1 + 1 x 0 + 1 x 1 + 0 x 0 + 1 x 1 + 1 x 0 + 0 x 1 + 0 x 0 + 1 x 1 = 4
เคอร์เนลเลื่อนตำแหน่ง 1 ตำแหน่งเพื่อคำนวณค่าของตำแหน่งอื่นๆ ของเอาท์พุตเทนเซอร์ 'การเปลี่ยนแปลง' นี้เรียกว่า 'ก้าวย่าง'
จำเป็นต้องมีเลเยอร์ Convolution เพื่อปรับปรุงและแยกคุณสมบัติที่สำคัญและซ่อนเร้นของภาพ ในกรณีของเรา อาจเกิดขึ้นได้ว่า "ดอกไม้" อยู่ที่ตำแหน่งกึ่งกลางของภาพ ดังนั้นการใช้การบิดงอจะช่วยดึงคุณสมบัติหลักของดอกไม้โดยไม่สนใจวัตถุและสีพื้นหลังอื่นๆ
เนื่องจากแต่ละภาพเป็นไปตามโค้ดสี RGB เราจะใช้การดำเนินการแบบบิดสำหรับแต่ละสี และด้วยเหตุนี้เราจึงได้เอาท์พุตเทนเซอร์สามตัว ผลลัพธ์สุดท้ายจะเป็นผลรวมเทนเซอร์ของทั้งสาม 'รหัสสี' แต่ละรายการเหล่านี้เรียกว่า 'ช่องทาง' ในคำศัพท์เฉพาะของ PyTorch API
ตามหลักคณิตศาสตร์แล้ว หากใช้ฟิลเตอร์ขนาด kxk กับภาพที่มีขนาด WxH มันจะสร้างภาพเอาท์พุต/เทนเซอร์ขนาด (W-k+1)x(H-k+1)
ในกรณีของเรา การบิดตัวถูกสร้างขึ้นเช่นนี้
self.conv1 = nn.Conv2d(in_channels=3, out_channels=12, kernel_size=3,stride=1, padding=1)
"out_channels" ระบุจำนวนตัวกรองที่จะใช้ ที่นี่เราได้ใช้ฟิลเตอร์ 12 ตัว และสิ่งเหล่านี้จะสร้างเทนเซอร์รูปภาพระดับกลาง 12 ตัวขนาด 62x62 รูปภาพแต่ละภาพเหล่านี้มีคุณสมบัติพิเศษอย่างหนึ่งของรูปภาพต้นฉบับ
สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับ 'ตัวกรอง Convolution' ผู้อ่านสามารถไปที่ลิงค์ด้านล่าง
ชั้น ReLU
'ReLU' เป็นฟังก์ชันการเปิดใช้งานที่จับความไม่เป็นเชิงเส้นในเอาต์พุตของฟังก์ชันอื่น ในทางคณิตศาสตร์มันถูกกำหนดให้เป็น
ดังนั้นจึงส่งกลับค่าบวกเสมอ เราสามารถพูดได้ว่ามันคือ 'ตัวกรองเชิงบวก' เราจะใช้เลเยอร์ 'ReLU' หลังจากการบิด
ในกรณีของเรา 'ReLU' จะถูกสร้างขึ้นดังนี้
self.relu1 = nn.ReLU()
แม็กซ์รวมชั้น
โดยทั่วไป 'Max Pooling Layer' จะอยู่หลัง 'ReLU' 'พูลสูงสุด' ขนาด 2 คือหน้าต่าง 2x2 ซึ่งลัดเลาะเทนเซอร์เอาต์พุตของการดำเนินการ 'ReLU' และเลือกค่าพิกเซลสูงสุดภายในหน้าต่าง การดำเนินการนี้สามารถอธิบายได้ด้วยแผนภาพด้านล่าง
วัตถุประสงค์ของเลเยอร์ 'Max Pool' คือการเลือกเฉพาะคุณสมบัติที่มีผลกระทบสูงและมีมูลค่าสูง ช่วยลดมิติของคุณสมบัติต่างๆ
ในกรณีของเรา 'Max Pool' จะถูกสร้างขึ้นดังนี้
self.maxpool1 = nn.MaxPool2d(kernel_size=2)
จะลดขนาดของภาพลง 50% (32 = 64/2)
เลเยอร์ฟังก์ชันเชิงเส้น
ตามชื่อที่แสดงถึง มันเป็นฟังก์ชันเชิงเส้นที่รับเอาต์พุตของ 'Max Pool' เป็นอาร์เรย์แบบแบนและสร้างเอาต์พุตเป็นดัชนีคลาส ค่าเอาต์พุตจาก 'ฟังก์ชันเชิงเส้น' สำหรับดัชนีคลาสที่คาดการณ์ไว้จะเป็นค่าสูงสุด
ในกรณีของเรา 'ฟังก์ชันเชิงเส้น' จะถูกสร้างขึ้นดังนี้
self.lf = nn.Linear(in_features=32 * 32 * 24, out_features=num_classes)
สถาปัตยกรรมโดยรวมของโมเดล
เราจะใช้เลเยอร์ที่แตกต่างกันตามแผนภาพด้านล่าง
เรามีเลเยอร์ 'convolution' และ 'ReLU' สองชุด 'มุมมอง' จะทำให้เทนเซอร์เอาท์พุตแบนราบจากเลเยอร์ 'ReLU' สุดท้าย เรามีอิมเมจเทนเซอร์ขนาด 64x64 เป็นอินพุตซึ่งจะลดลงเหลือ 32x32 เนื่องจากการใช้ 'MaxPool2D' ของเคอร์เนลขนาด 2x2 (32 = 64/2)
ขั้นแรก เราจะแบ่งชุดข้อมูลออกเป็นการฝึกและการทดสอบตามอัตราส่วน 80:20
จากนั้น เราจะเขียนคลาสที่กำหนดเองเพื่อซ้อนเลเยอร์เหล่านี้โดยขยาย 'โมดูล' ที่กำหนดโดยไลบรารี PyTorch
'__init__' กำหนดแต่ละเลเยอร์และพารามิเตอร์ของมัน ในขณะที่ฟังก์ชัน 'ส่งต่อ' ทำการเรียกจริงและการซ้อนเลเยอร์ ผลลัพธ์จากเลเยอร์สุดท้ายจะถูกส่งกลับจากฟังก์ชัน 'ส่งต่อ'
การฝึกอบรมแบบจำลอง
เราจำเป็นต้องมีฟังก์ชัน Optimizer & Loss สำหรับการฝึกโมเดล เราจะใช้ 'Adam Optimizer' & 'Cross-Entropy Loss' สำหรับสิ่งนี้
from torch.optim import Adam cnn_model = FlowerClassifierCNNModel() optimizer = Adam(cnn_model.parameters()) loss_fn = nn.CrossEntropyLoss()
ด้วย PyTorch เราจำเป็นต้องตั้งค่าโมเดลในโหมดการฝึก จากนั้นรันการฝึกโดยวนซ้ำชุดข้อมูลการฝึก คำนวณการสูญเสียและขั้นตอนที่เพิ่มขึ้นของเครื่องมือเพิ่มประสิทธิภาพ
เราสามารถเขียนฟังก์ชันสำหรับสิ่งนี้ได้
การเรียกใช้ฟังก์ชัน 'loss.backward' จะกลับไปที่เลเยอร์และคำนวณการสูญเสียที่เกิดขึ้นระหว่างกระบวนการ
เราจะใช้ 'ยุค' 200 เพื่อฝึกโมเดล
train_and_build(200)
การทดสอบโมเดลและความแม่นยำ
เราควรตั้งค่าโมเดลเป็นโหมด 'ประเมิน' เพื่อทดสอบความแม่นยำบนชุดข้อมูลการทดสอบ
ฟังก์ชัน 'torch.max' ส่งกลับค่าสูงสุดจากเทนเซอร์เอาท์พุตของ 'ฟังก์ชันเชิงเส้น' ค่าสูงสุดอนุมานป้ายกำกับคลาสที่คาดการณ์ไว้
ฟังก์ชัน 'torch.sum' จะรวมค่า '1' ที่มีอยู่ในเทนเซอร์ซึ่งเป็นเอาต์พุตของการดำเนินการ 'AND' ระหว่างเทนเซอร์ 'ที่คาดการณ์ไว้' และ 'เอาต์พุตการทดสอบจริง' ดังนั้นผลรวมนี้จึงทำให้ไม่มีภาพที่ทำนายได้ถูกต้อง
และที่นี่เราได้รับความแม่นยำ
test_accuracy
คิดเป็นเกือบ 70.52% เรามีความแม่นยำที่ดีด้วยแบบจำลองง่ายๆ รุ่นนี้สามารถจูนเพิ่มเติมได้
การใช้แบบจำลองในการทำนายด้วยภาพตัวอย่าง
ตอนนี้เราจะดูวิธีใช้โมเดลนี้กับรูปภาพตัวอย่างจากชุดข้อมูลของเรา
show_image("../data/flowers/dandelion/13920113_f03e867ea7_m.jpg")
นี่คือภาพของ 'ดอกแดนดิไลอัน'
ตอนนี้เราจะอ่านรูปภาพโดยใช้ PIL image API และป้อนลงในไปป์ไลน์การแปลงของเราสำหรับการประมวลผลล่วงหน้าที่จำเป็น และใช้แบบจำลองสำหรับการทำนายในภายหลัง
class_index
ดังนั้น จากพจนานุกรมชั้นเรียนไปจนถึงพจนานุกรมดัชนีดังที่กล่าวข้างต้น เราสามารถยืนยันได้ว่าเป็น 'Dandelion' ดังนั้นโมเดลลักษณนามรูปภาพของเราจึงทำงานได้ดี !!
บทสรุป
เราเรียนรู้วิธีจัดหมวดหมู่รูปภาพโดยใช้ไลบรารี PyTorch ในกระบวนการนี้ เราได้ครอบคลุมถึงการประมวลผลภาพล่วงหน้า การสร้างเลเยอร์ Convolution และการทดสอบโมเดลสำหรับภาพที่นำเข้า
ความแม่นยำของแบบจำลองสามารถปรับปรุงเพิ่มเติมได้โดยการปรับแต่ง 'ไฮเปอร์พารามิเตอร์' เช่น การทดลองด้วยพารามิเตอร์ 'Adam Optimizer' การเพิ่มเลเยอร์การบิดพิเศษ การปรับแต่งด้วยขนาดเคอร์เนลและขนาดหน้าต่างพูลสูงสุด ฯลฯ ผู้อ่านบทความนี้สามารถลองใช้เทคนิคเหล่านี้ได้ด้วยตนเอง .
สมุดบันทึก Jupyter สำหรับสิ่งนี้สามารถพบได้จากลิงค์ด้านล่าง
ล่าสุดฉันเขียนหนังสือเกี่ยวกับ ML (https://twitter.com/bpbonline/status/1256146448346988546)