การจัดประเภทรูปภาพของ CNN ใน TensorFlow พร้อมขั้นตอนและตัวอย่าง
⚡ สรุปอย่างชาญฉลาด
โครงข่ายประสาทเทียมแบบคอนโวลูชัน (Convolutional Neural Networks) สแกนภาพด้วยตัวกรองขนาดเล็กแทนที่จะให้น้ำหนักทุกพิกเซลเท่ากัน ซึ่งเป็นเหตุผลที่ทำให้โครงข่ายนี้เป็นที่นิยมในด้านคอมพิวเตอร์วิชัน บทความนี้จะอธิบายแต่ละเลเยอร์และจำแนกตัวเลข MNIST ด้วย TensorFlow
Convolutional Neural Network คืออะไร?
โครงข่ายประสาทเทียมโครงข่ายประสาทเทียมแบบคอนโวลูชัน (ConvNets หรือ CNN) เป็นวิธีการที่รู้จักกันดีในด้านการประยุกต์ใช้คอมพิวเตอร์วิชัน เป็นโครงข่ายประสาทเทียมเชิงลึกประเภทหนึ่งที่ใช้ในการวิเคราะห์ภาพ สถาปัตยกรรมประเภทนี้มีความโดดเด่นในการจดจำวัตถุจากภาพหรือวิดีโอ มีการใช้งานในแอปพลิเคชันต่างๆ เช่น การจดจำภาพหรือวิดีโอ การประมวลผลภาษาธรรมชาติ และระบบแนะนำ
Archiการสอนโครงข่ายประสาทเทียมแบบ Convolutional
ลองนึกถึง Facebook เมื่อไม่กี่ปีก่อน หลังจากที่คุณอัปโหลดรูปภาพไปยังโปรไฟล์ของคุณแล้ว คุณจะถูกขอให้เพิ่มชื่อให้กับใบหน้าบนรูปภาพด้วยตนเอง ปัจจุบัน Facebook ใช้ Convnet เพื่อแท็กเพื่อนของคุณในภาพโดยอัตโนมัติ
เครือข่ายประสาทเทียมแบบ Convolution สำหรับการจำแนกภาพนั้นเข้าใจได้ไม่ยาก ภาพอินพุตจะถูกประมวลผลในระหว่างขั้นตอนการ Convolution จากนั้นจึงกำหนดป้ายกำกับในภายหลัง
สถาปัตยกรรมโครงข่ายประสาทเทียมแบบ Convolutional (ConvNet) ทั่วไปสามารถสรุปได้ดังภาพด้านล่าง ขั้นแรก ภาพจะถูกส่งเข้าไปในโครงข่าย ซึ่งเรียกว่าภาพอินพุต จากนั้น ภาพอินพุตจะผ่านขั้นตอนต่างๆ ซึ่งเป็นส่วนของโครงข่ายประสาทเทียมแบบ Convolutional สุดท้าย โครงข่ายประสาทเทียมจะสามารถทำนายตัวเลขในภาพได้

ภาพประกอบด้วยอาร์เรย์ของพิกเซลที่มีความสูงและความกว้าง ภาพขาวดำมีเพียงช่องสัญญาณเดียว ในขณะที่ภาพสีมีสามช่องสัญญาณ (แต่ละช่องสำหรับสีแดง สีเขียว และสีน้ำเงิน) ช่องสัญญาณเหล่านี้เรียงซ้อนกัน ในบทเรียนนี้ คุณจะใช้ภาพขาวดำที่มีเพียงช่องสัญญาณเดียว พิกเซลแต่ละพิกเซลมีค่าตั้งแต่ 0 ถึง 255 เพื่อสะท้อนความเข้มของสี ตัวอย่างเช่น พิกเซลที่มีค่าเท่ากับ 0 จะแสดงสีขาว ในขณะที่พิกเซลที่มีค่าใกล้เคียงกับ 255 จะมีสีเข้มกว่า
เรามาดูภาพที่เก็บไว้ใน ชุดข้อมูล MNISTภาพด้านล่างแสดงวิธีการนำเสนอภาพทางซ้ายในรูปแบบเมทริกซ์ โปรดสังเกตว่าเมทริกซ์ต้นฉบับได้รับการปรับมาตรฐานให้มีค่าอยู่ระหว่าง 0 ถึง 1 สำหรับสีที่เข้มกว่า ค่าในเมทริกซ์จะมีค่าประมาณ 0.9 ในขณะที่พิกเซลสีขาวมีค่าเป็น 0
การดำเนินการแบบคอนโวลูชั่น
ส่วนประกอบที่สำคัญที่สุดในโมเดลนี้คือเลเยอร์การแปลงแบบคอนโวลูชัน (Convolutional Layer) ส่วนนี้มีจุดประสงค์เพื่อลดขนาดของภาพเพื่อให้คำนวณน้ำหนักได้เร็วขึ้นและปรับปรุงความสามารถในการสรุปผลได้ดีขึ้น
ในระหว่างส่วนที่บิดเบี้ยว เครือข่ายจะเก็บคุณลักษณะที่สำคัญของภาพไว้และแยกสัญญาณรบกวนที่ไม่เกี่ยวข้องออก ตัวอย่างเช่น แบบจำลองกำลังเรียนรู้วิธีจดจำช้างจากภาพที่มีภูเขาอยู่เบื้องหลัง หากคุณใช้โครงข่ายประสาทเทียมแบบเดิม โมเดลจะกำหนดน้ำหนักให้กับพิกเซลทั้งหมด รวมถึงพิกเซลที่มาจากภูเขาซึ่งไม่จำเป็นและอาจทำให้เครือข่ายเข้าใจผิดได้
แทน Keras โครงข่ายประสาทเทียมแบบคอนโวลูชันจะใช้เทคนิคทางคณิตศาสตร์เพื่อแสดงผลtracเลือกเฉพาะพิกเซลที่เกี่ยวข้องมากที่สุดเท่านั้น การดำเนินการทางคณิตศาสตร์นี้เรียกว่าการคอนโวลูชัน เทคนิคนี้ช่วยให้เครือข่ายเรียนรู้คุณลักษณะที่ซับซ้อนขึ้นเรื่อยๆ ในแต่ละชั้น การคอนโวลูชันจะแบ่งเมทริกซ์ออกเป็นชิ้นเล็กๆ เพื่อเรียนรู้องค์ประกอบที่สำคัญที่สุดภายในแต่ละชิ้น
ส่วนประกอบของโครงข่ายประสาทเทียมแบบ Convolutional (ConvNet หรือ CNN)
โครงข่ายประสาทเทียมแบบคอนโวลูชัน (ConvNet) ประกอบด้วยส่วนประกอบสี่ส่วน ได้แก่:
- บิด
- ไม่เป็นเชิงเส้น (ReLU)
- Pooling หรือการสุ่มตัวอย่างย่อย
- การจำแนกประเภท (เลเยอร์ที่เชื่อมต่ออย่างเต็มที่)
บิด
จุดประสงค์ของการคอนโวลูชันคือเพื่อ...tracโดยจะเรียนรู้ลักษณะเฉพาะของวัตถุในภาพในระดับท้องถิ่น นั่นหมายความว่าเครือข่ายจะเรียนรู้รูปแบบเฉพาะภายในภาพและสามารถจดจำรูปแบบเหล่านั้นได้ทุกที่ในภาพ
การคอนโวลูชันคือการคูณแบบทีละองค์ประกอบ แนวคิดนี้เข้าใจง่าย คอมพิวเตอร์จะสแกนส่วนหนึ่งของภาพ โดยปกติจะมีขนาด 3×3 และคูณด้วยตัวกรอง ผลลัพธ์ของการคูณแบบทีละองค์ประกอบเรียกว่าแผนที่ฟีเจอร์ ขั้นตอนนี้จะทำซ้ำจนกว่าจะสแกนภาพทั้งหมด โปรดทราบว่าหลังจากทำการคอนโวลูชันแล้ว ขนาดของภาพจะลดลง
แผนภาพด้านล่างแสดงให้เห็นส่วนหนึ่งของภาพที่ถูกคูณด้วยตัวกรองเพื่อสร้างเซลล์เดียวในแผนที่คุณลักษณะ
ภาพเคลื่อนไหวด้านล่างแสดงให้เห็นการแปลงแบบคอนโวลูชันเดียวกันที่เกิดขึ้นทั่วทั้งภาพ
มีตัวกรองมากมายให้เลือกใช้ ด้านล่างนี้เราได้รวบรวมตัวอย่างบางส่วนไว้ คุณจะเห็นว่าตัวกรองแต่ละตัวมีวัตถุประสงค์เฉพาะ โปรดสังเกตว่าในภาพด้านล่าง คำว่า "kernel" เป็นคำพ้องความหมายของตัวกรอง
เลขคณิตเบื้องหลังการบิด
ขั้นตอนการคอนโวลูชันจะใช้ฟิลเตอร์กับกลุ่มพิกเซลขนาดเล็กภายในภาพ ฟิลเตอร์จะเคลื่อนที่ไปตามภาพอินพุตด้วยรูปร่างทั่วไป 3×3 หรือ 5×5 ซึ่งหมายความว่าเครือข่ายจะเลื่อนหน้าต่างเหล่านี้ไปทั่วทั้งภาพอินพุตและคำนวณการคอนโวลูชัน ภาพเคลื่อนไหวด้านล่างแสดงวิธีการทำงานของการคอนโวลูชัน ขนาดของแพทช์คือ 3×3 และเมทริกซ์เอาต์พุตเป็นผลลัพธ์ของการดำเนินการแบบองค์ประกอบต่อองค์ประกอบระหว่างเมทริกซ์ภาพและฟิลเตอร์
คุณสังเกตเห็นว่าความกว้างและความสูงของผลลัพธ์อาจแตกต่างจากความกว้างและความสูงของอินพุต มันเกิดขึ้นเพราะเอฟเฟกต์เส้นขอบ
เอฟเฟกต์เส้นขอบ
ภาพนี้มีแผนที่ฟีเจอร์ขนาด 5×5 และตัวกรองขนาด 3×3 โดยมีเพียงหน้าต่างเดียวตรงกลางที่ตัวกรองสามารถกรองตารางขนาด 3×3 ได้ แผนที่ฟีเจอร์ที่ได้จะหดลงสองช่องในแต่ละแกน ทำให้เหลือขนาด 3×3
เพื่อให้ได้มิติของผลลัพธ์เท่ากับมิติของอินพุต คุณต้องเพิ่มการเติมขอบ (padding) การเติมขอบประกอบด้วยการเพิ่มจำนวนแถวและคอลัมน์ที่เหมาะสมในแต่ละด้านของเมทริกซ์ ซึ่งจะช่วยให้การคำนวณแบบคอนโวลูชันจัดวางไทล์อินพุตแต่ละไทล์ให้อยู่ตรงกลางพอดี ในภาพด้านล่าง เมทริกซ์อินพุตและเอาต์พุตมีมิติเท่ากันคือ 5×5
เมื่อคุณกำหนดเครือข่าย คุณลักษณะที่สับสนจะถูกควบคุมโดยพารามิเตอร์สามตัว:
ความลึก: ค่านี้กำหนดจำนวนฟิลเตอร์ที่จะใช้ระหว่างการคำนวณคอนโวลูชัน ในตัวอย่างก่อนหน้านี้ คุณเห็นความลึกเท่ากับ 1 ซึ่งหมายความว่าใช้ฟิลเตอร์เพียงตัวเดียว ในกรณีส่วนใหญ่จะมีฟิลเตอร์มากกว่าหนึ่งตัว ภาพเคลื่อนไหวข้างล่างแสดงการทำงานที่เกิดขึ้นในสถานการณ์ที่มีฟิลเตอร์สามตัว
ก้าวย่าง: ค่า stride กำหนดจำนวน "การกระโดดของพิกเซล" ระหว่างสองส่วน หากค่า stride เท่ากับ 1 หน้าต่างจะเคลื่อนที่โดยมีระยะห่างหนึ่งพิกเซล หากค่า stride เท่ากับ 2 หน้าต่างจะกระโดดไป 2 พิกเซล หากคุณเพิ่มค่า stride คุณจะได้ feature map ที่เล็กลง แผนภาพสองภาพด้านล่างเปรียบเทียบค่า stride เท่ากับ 1 กับค่า stride เท่ากับ 2
ตัวอย่างก้าวที่ 1
ก้าว 2
การเติมเลขศูนย์นำหน้า: การเติมขอบ (Padding) คือการเพิ่มจำนวนแถวและคอลัมน์ที่เท่ากันในแต่ละด้านของแผนที่ฟีเจอร์อินพุต ในกรณีนี้ ผลลัพธ์จะมีมิติเท่ากับอินพุต
ไม่เป็นเชิงเส้น (ReLU)
เมื่อสิ้นสุดการดำเนินการคอนโวลูชัน ผลลัพธ์จะถูกนำไปใช้กับฟังก์ชันการกระตุ้นเพื่อให้เกิดความไม่เป็นเชิงเส้น ฟังก์ชันการกระตุ้นที่ใช้กันทั่วไปสำหรับโครงข่ายประสาทเทียมแบบคอนโวลูชันคือ ReLU พิกเซลทั้งหมดที่มีค่าเป็นลบจะถูกแทนที่ด้วยศูนย์
Pooling Operaการ
ขั้นตอนนี้นั้นเข้าใจง่าย จุดประสงค์ของการทำพูลลิ่งคือการลดมิติของภาพอินพุต ขั้นตอนนี้ทำขึ้นเพื่อลดความซับซ้อนในการคำนวณของกระบวนการ เมื่อลดมิติลง เครือข่ายก็จะมีน้ำหนักที่ต้องคำนวณน้อยลง จึงช่วยป้องกันการเกิดโอเวอร์ฟิตติ้งได้
ในขั้นตอนนี้ คุณต้องกำหนดขนาดและระยะก้าว วิธีการมาตรฐานในการพูลภาพอินพุตคือการใช้ค่าสูงสุดของแผนที่ฟีเจอร์ ดูภาพด้านล่าง การพูลจะคัดกรองเมทริกซ์ย่อยสี่เมทริกซ์ของแผนที่ฟีเจอร์ขนาด 4×4 และส่งคืนค่าสูงสุด การพูลจะใช้ค่าสูงสุดของอาร์เรย์ขนาด 2×2 แล้วเลื่อนหน้าต่างนี้ไปสองพิกเซล ตัวอย่างเช่น เมทริกซ์ย่อยแรกคือ [3,1,3,2] ดังนั้นการพูลจะส่งคืนค่าสูงสุด ซึ่งก็คือ 3
มีการดำเนินการรวมกลุ่มอีกอย่างหนึ่ง เช่น ค่าเฉลี่ย
การดำเนินการนี้จะลดขนาดของแผนที่ฟีเจอร์ลงอย่างมาก
เลเยอร์ที่เชื่อมต่ออย่างเต็มที่
ขั้นตอนสุดท้ายประกอบด้วยการสร้างแบบดั้งเดิม โครงข่ายประสาทเทียม เหมือนที่คุณทำในบทช่วยสอนก่อนหน้านี้ คุณเชื่อมต่อเซลล์ประสาททั้งหมดจากเลเยอร์ก่อนหน้าไปยังเลเยอร์ถัดไป คุณใช้ฟังก์ชันการเปิดใช้งาน softmax เพื่อจัดประเภทหมายเลขบนรูปภาพอินพุต
สรุป:
โครงข่ายประสาทเทียมแบบ Convolutional ของ TensorFlow จะรวบรวมเลเยอร์ต่างๆ ก่อนที่จะทำการทำนาย โครงข่ายประสาทเทียมประกอบด้วย:
- ชั้นที่บิดเบี้ยว
- ฟังก์ชั่นการเปิดใช้งาน ReLU
- Poolinชั้นกรัม
- ชั้นที่เชื่อมต่อกันอย่างหนาแน่น
เลเยอร์คอนโวลูชันจะใช้ตัวกรองที่แตกต่างกันกับส่วนย่อยของภาพ ฟังก์ชันการกระตุ้น ReLU เพิ่มความไม่เป็นเชิงเส้น และเลเยอร์พูลลิ่งจะลดมิติของแผนที่คุณลักษณะ
ชั้นทั้งหมดเหล่านี้ เช่นtracข้อมูลสำคัญจากภาพ สุดท้ายแล้ว แผนที่ลักษณะเฉพาะจะถูกส่งไปยังเลเยอร์เชื่อมต่อเต็มรูปแบบที่มีฟังก์ชันซอฟต์แม็กซ์เพื่อทำการทำนาย
ฝึกอบรม CNN ด้วย TensorFlow
เมื่อคุณคุ้นเคยกับส่วนประกอบพื้นฐานของโครงข่ายประสาทเทียมแบบคอนโวลูชันแล้ว คุณก็พร้อมที่จะสร้างโครงข่ายดังกล่าวได้แล้ว TensorFlow- เราจะใช้ชุดข้อมูล MNIST สำหรับการจำแนกรูปภาพของ CNN
การเตรียมข้อมูลจะเหมือนกับบทช่วยสอนก่อนหน้านี้ คุณสามารถรันโค้ดและข้ามไปยังสถาปัตยกรรมของ CNN ได้โดยตรง
คุณจะทำตามขั้นตอนด้านล่างเพื่อจัดหมวดหมู่รูปภาพโดยใช้ CNN:
- ขั้นตอนที่ 1: อัปโหลดชุดข้อมูล
- ขั้นตอนที่ 2: เลเยอร์อินพุต
- ขั้นตอนที่ 3: เลเยอร์ Convolutional
- ขั้นตอนที่ 4: Poolinชั้นกรัม
- ขั้นตอนที่ 5: เลเยอร์ Convolutional ที่สองและ Poolinก. เลเยอร์
- ขั้นตอนที่ 6: ชั้นหนาแน่น
- ขั้นตอนที่ 7: Logit Layer
หมายเหตุเกี่ยวกับเวอร์ชัน: รายการด้านล่างนี้กำหนดเป้าหมายไปที่ TensorFlow 1.x ใน TensorFlow 2 เนมสเปซ tf.layers และ tf.estimator.inputs.numpy_input_fn ไม่มีอยู่อีกต่อไปแล้ว ตัวเลือกที่เทียบเท่าคือ tf.keras.layers.Conv2D, MaxPooling2D, Dense และ Dropout ถูกรวมเข้าด้วยกันใน tf.keras.Model และฝึกฝนด้วย model.fit() อ่านขั้นตอนเกี่ยวกับกลไกของแต่ละเลเยอร์ จากนั้นแมปขั้นตอนเหล่านั้นเข้ากับ API ของ Keras
ขั้นตอนที่ 1: อัปโหลดชุดข้อมูล
ชุดข้อมูล MNIST สามารถดาวน์โหลดได้จาก scikit-learn โปรดดาวน์โหลดและบันทึกไว้ในโฟลเดอร์ดาวน์โหลด คุณสามารถอัปโหลดได้โดยใช้คำสั่ง fetch_mldata('MNIST original')
หมายเหตุเกี่ยวกับเวอร์ชัน: เว็บไซต์ mldata.org ปิดตัวลงแล้ว และฟังก์ชัน fetch_mldata() ถูกลบออกใน scikit-learn เวอร์ชัน 0.22 ในการติดตั้งเวอร์ชันปัจจุบันใดๆ ก็ตาม ให้โหลดตัวเลขชุดเดียวกันโดยใช้ ดึงข้อมูลเปิด ml แทนที่จะใช้ fetch_openml('mnist_784', version=1) ส่วนที่เหลือของไปป์ไลน์ยังคงเหมือนเดิม
สร้างชุดฝึก/ชุดทดสอบ
คุณต้องแบ่งชุดข้อมูลโดยใช้คำสั่ง train_test_split
ปรับขนาดคุณสมบัติ
สุดท้าย คุณสามารถปรับขนาดฟีเจอร์ด้วย MinMaxScaler ดังแสดงในตัวอย่างการจำแนกภาพโดยใช้ TensorFlow CNN ด้านล่าง
import numpy as np import tensorflow as tf from sklearn.datasets import fetch_mldata #Change USERNAME by the username of your machine ## Windows USER mnist = fetch_mldata('C:\\Users\\USERNAME\\Downloads\\MNIST original') ## Mac User mnist = fetch_mldata('/Users/USERNAME/Downloads/MNIST original') print(mnist.data.shape) print(mnist.target.shape) from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(mnist.data, mnist.target, test_size=0.2, random_state=42) y_train = y_train.astype(int) y_test = y_test.astype(int) batch_size =len(X_train) print(X_train.shape, y_train.shape,y_test.shape ) ## resclae from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler() # Train X_train_scaled = scaler.fit_transform(X_train.astype(np.float64)) # test X_test_scaled = scaler.fit_transform(X_test.astype(np.float64)) feature_columns = [tf.feature_column.numeric_column('x', shape=X_train_scaled.shape[1:])] X_train_scaled.shape[1:]
กำหนดซีเอ็นเอ็น
โครงข่ายประสาทเทียมแบบ CNN ใช้ตัวกรองกับพิกเซลดิบของภาพเพื่อเรียนรู้รูปแบบรายละเอียด ซึ่งแตกต่างจากรูปแบบโดยรวมที่เรียนรู้โดยโครงข่ายประสาทเทียมแบบดั้งเดิม ในการสร้าง CNN คุณต้องกำหนดสิ่งต่อไปนี้:
- ชั้นคอนโวลูชัน: ใช้ตัวกรองจำนวน n ตัวกับแผนที่ฟีเจอร์ หลังจากคอนโวลูชันแล้ว คุณต้องใช้ฟังก์ชันการกระตุ้น ReLU เพื่อเพิ่มความไม่เป็นเชิงเส้นให้กับเครือข่าย
- Poolinเลเยอร์ g: ขั้นตอนถัดไปหลังจากคอนโวลูชันคือการลดขนาดแผนที่ฟีเจอร์ จุดประสงค์คือเพื่อลดมิติของแผนที่ฟีเจอร์เพื่อป้องกันการโอเวอร์ฟิตติ้งและปรับปรุงความเร็วในการคำนวณ เทคนิคที่นิยมใช้คือการรวมค่าสูงสุด (Max pooling) ซึ่งแบ่งแผนที่ฟีเจอร์ออกเป็นส่วนย่อย (โดยปกติจะมีขนาด 2×2) และเก็บเฉพาะค่าสูงสุดไว้
- เลเยอร์ที่เชื่อมต่อกันอย่างสมบูรณ์: นิวรอนทั้งหมดจากเลเยอร์ก่อนหน้าจะเชื่อมต่อกับเลเยอร์ถัดไป CNN จะจัดประเภทป้ายกำกับตามคุณลักษณะจากเลเยอร์คอนโวลูชั่นและลดลงด้วยเลเยอร์การรวมกลุ่ม
สถาปัตยกรรม CNN
- เลเยอร์คอนโวลูชัน: ใช้ฟิลเตอร์ขนาด 5x5 จำนวน 14 ตัว (เช่นtrac(แบ่งพื้นที่ออกเป็น 5×5 พิกเซล) โดยใช้ฟังก์ชันการกระตุ้น ReLU
- Poolinเลเยอร์ g: ดำเนินการรวมกลุ่มสูงสุดด้วยตัวกรอง 2×2 และก้าวที่ 2 (ซึ่งระบุว่าภูมิภาคที่รวมกลุ่มจะไม่ทับซ้อนกัน)
- Convolutional Layer: ใช้ตัวกรอง 36 5×5 พร้อมฟังก์ชันการเปิดใช้งาน ReLU
- Pooling เลเยอร์ #2: ทำการรวมค่าสูงสุดอีกครั้งด้วยตัวกรอง 2×2 และก้าว 2
- เซลล์ประสาท 1,764 ตัว โดยมีอัตราการทำให้เป็นมาตรฐานของการหยุดกลางคันที่ 0.4 (ความน่าจะเป็น 0.4 ที่องค์ประกอบที่กำหนดจะถูกทิ้งระหว่างการฝึก)
- เลเยอร์หนาแน่น (Logits Layer): 10 เซลล์ประสาท หนึ่งเซลล์สำหรับแต่ละคลาสเป้าหมายหลัก (0–9)
มีโมดูลที่สำคัญสามโมดูลที่ใช้ในการสร้าง CNN:
- Conv2d() สร้างเลเยอร์ Convolutional สองมิติโดยมีจำนวนตัวกรอง ขนาดเคอร์เนลตัวกรอง ช่องว่างภายใน และฟังก์ชันการเปิดใช้งานเป็นอาร์กิวเมนต์
- max_pooling2d() สร้างเลเยอร์การรวมกลุ่มสองมิติโดยใช้อัลกอริทึม max-pooling
- หนาแน่น(). สร้างชั้นที่หนาแน่นด้วยชั้นและหน่วยที่ซ่อนอยู่
คุณจะกำหนดฟังก์ชันเพื่อสร้างโครงข่ายประสาทเทียมแบบ CNN มาดูรายละเอียดวิธีการสร้างแต่ละส่วนประกอบก่อนที่จะจบลงกันping ทุกอย่างรวมกันอยู่ในฟังก์ชันนั้น
ขั้นตอนที่ 2: เลเยอร์อินพุต
def cnn_model_fn(features, labels, mode): input_layer = tf.reshape(tensor = features["x"],shape =[-1, 28, 28, 1])
คุณต้องกำหนดเทนเซอร์ด้วยรูปร่างของข้อมูล เพื่อสิ่งนั้น คุณสามารถใช้โมดูล tf.reshape ในโมดูลนี้ คุณจะต้องประกาศเทนเซอร์เพื่อปรับรูปร่างและรูปร่างของเทนเซอร์ อาร์กิวเมนต์แรกคือคุณลักษณะของข้อมูล ซึ่งกำหนดไว้ในอาร์กิวเมนต์ของฟังก์ชัน
รูปภาพประกอบด้วยความสูง ความกว้าง และช่องสี ชุดข้อมูล MNIST เป็นรูปภาพขาวดำขนาด 28×28 พิกเซล เราตั้งค่าขนาดแบตช์เป็น -1 ในอาร์กิวเมนต์รูปร่างเพื่อให้มีรูปร่างตามคุณลักษณะ [“x”] ข้อดีคือการทำให้ขนาดแบตช์เป็นพารามิเตอร์ที่สามารถปรับแต่งได้ หากตั้งค่าขนาดแบตช์เป็น 7 เทนเซอร์จะป้อนค่า 5,488 ค่า (28*28*7)
ขั้นตอนที่ 3: เลเยอร์ Convolutional
# first Convolutional Layer conv1 = tf.layers.conv2d( inputs=input_layer, filters=14, kernel_size=[5, 5], padding="same", activation=tf.nn.relu)
เลเยอร์การแปลงแบบคอนโวลูชันแรกมีฟิลเตอร์ 14 ตัว โดยมีขนาดเคอร์เนล 5×5 และมีการเติมขอบเท่ากัน การเติมขอบเท่ากันหมายความว่าเทนเซอร์เอาต์พุตและเทนเซอร์อินพุตควรมีความสูงและความกว้างเท่ากัน TensorFlow จะเพิ่มศูนย์ให้กับแถวและคอลัมน์เพื่อให้แน่ใจว่ามีขนาดเท่ากัน
คุณใช้ฟังก์ชันการกระตุ้น ReLU ขนาดของผลลัพธ์จะเป็น [28, 28, 14]
ขั้นตอนที่ 4: Poolinชั้นกรัม
ขั้นตอนถัดไปหลังจากคอนโวลูชันคือการคำนวณพูลลิ่ง การคำนวณพูลลิ่งจะลดมิติของข้อมูล คุณสามารถใช้โมดูล max_pooling2d โดยกำหนดขนาดเป็น 2×2 และ stride เป็น 2 โดยใช้เลเยอร์ก่อนหน้าเป็นอินพุต ขนาดของเอาต์พุตจะเป็น [batch_size, 14, 14, 14]
# first Pooling Layer
pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)
ขั้นตอนที่ 5: เลเยอร์ Convolutional ที่สองและ Poolinก. เลเยอร์
เลเยอร์การแปลงแบบคอนโวลูชันที่สองใช้ฟิลเตอร์ 36 ตัว ทำให้ได้ขนาดเอาต์พุตเป็น [batch_size, 14, 14, 36] เลเยอร์พูลลิ่งใช้หน้าต่าง 2×2 และสเต็ป 2 เช่นเดียวกับก่อนหน้า ดังนั้นจึงลดขนาดแกนเชิงพื้นที่แต่ละแกนลงครึ่งหนึ่ง และรูปร่างเอาต์พุตจะกลายเป็น [batch_size, 7, 7, 36]
conv2 = tf.layers.conv2d(
inputs=pool1,
filters=36,
kernel_size=[5, 5],
padding="same",
activation=tf.nn.relu)
pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)
ขั้นตอนที่ 6: ชั้นหนาแน่น
จากนั้น คุณต้องกำหนดเลเยอร์เชื่อมต่อแบบเต็ม (fully-connected layer) ฟีเจอร์แมป (feature map) จะต้องถูกทำให้แบนราบก่อนที่จะเชื่อมต่อกับเลเยอร์หนาแน่น (dense layer) คุณสามารถใช้โมดูลปรับรูปร่าง (reshape) ด้วยขนาด 7*7*36 ได้
เลเยอร์หนาแน่นจะเชื่อมต่อเซลล์ประสาท 1,764 เซลล์ คุณเพิ่มฟังก์ชันการกระตุ้น ReLU นอกจากนี้ คุณยังเพิ่มเทอมการควบคุมแบบดรอปเอาต์ (dropout regularization term) ด้วยอัตรา 0.3 ซึ่งหมายความว่า 30 เปอร์เซ็นต์ของการกระตุ้นจะถูกตั้งค่าเป็น 0 โปรดทราบว่าดรอปเอาต์จะเกิดขึ้นเฉพาะในระหว่างขั้นตอนการฝึกอบรมเท่านั้น ฟังก์ชัน cnn_model_fn มีอาร์กิวเมนต์ mode เพื่อประกาศว่าโมเดลจำเป็นต้องได้รับการฝึกอบรมหรือประเมินผล ดังแสดงในตัวอย่างการจำแนกภาพ CNN ใน TensorFlow ด้านล่าง
pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 36])
dense = tf.layers.dense(inputs=pool2_flat, units=7 * 7 * 36, activation=tf.nn.relu)
dropout = tf.layers.dropout(
inputs=dense, rate=0.3, training=mode == tf.estimator.ModeKeys.TRAIN)
ขั้นตอนที่ 7: Logit Layer
สุดท้ายนี้ ในตัวอย่างการจำแนกภาพด้วย TensorFlow คุณสามารถกำหนดเลเยอร์สุดท้ายด้วยการทำนายของโมเดลได้ โดยรูปร่างของเอาต์พุตจะเท่ากับขนาดของแบทช์และ 10 ซึ่งเป็นจำนวนคลาสเป้าหมายทั้งหมด
# Logits Layer
logits = tf.layers.dense(inputs=dropout, units=10)
คุณสามารถสร้างพจนานุกรมที่มีคลาสและความน่าจะเป็นของแต่ละคลาสได้ ฟังก์ชัน tf.argmax() จะส่งคืนดัชนีของค่าสูงสุดในเลเยอร์ logits ฟังก์ชัน softmax จะส่งคืนความน่าจะเป็นของแต่ละคลาส
predictions = {
# Generate predictions
"classes": tf.argmax(input=logits, axis=1),
"probabilities": tf.nn.softmax(logits, name="softmax_tensor") }
คุณต้องการให้แสดงเฉพาะพจนานุกรมการทำนายเมื่อตั้งค่าโหมดเป็นการทำนายเท่านั้น คุณเพิ่มโค้ดนี้เพื่อแสดงผลการทำนาย
if mode == tf.estimator.ModeKeys.PREDICT: return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions)
ขั้นตอนต่อไปคือการคำนวณค่าความสูญเสียของโมเดล ในบทเรียนที่แล้ว คุณได้เรียนรู้ว่าฟังก์ชันความสูญเสียสำหรับโมเดลแบบหลายคลาสคือเอนโทรปีแบบไขว้ ซึ่งสามารถคำนวณได้ง่ายๆ ด้วยโค้ดต่อไปนี้:
# Calculate Loss (for both TRAIN and EVAL modes)
loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)
ขั้นตอนสุดท้ายของตัวอย่าง TensorFlow CNN คือการปรับแต่งโมเดลให้เหมาะสมที่สุด นั่นคือการหาค่าที่ดีที่สุดของน้ำหนัก สำหรับการนี้ คุณใช้ตัวปรับแต่งแบบลดระดับความชัน (gradient descent optimizer) โดยมีอัตราการเรียนรู้ (learning rate) เท่ากับ 0.001 เป้าหมายคือการลดค่าความสูญเสีย (loss) ให้เหลือน้อยที่สุด
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
train_op = optimizer.minimize(
loss=loss,
global_step=tf.train.get_global_step())
คุณสร้าง CNN เสร็จแล้ว แต่คุณต้องการแสดงตัวชี้วัดประสิทธิภาพระหว่างโหมดการประเมินผล ตัวชี้วัดประสิทธิภาพสำหรับโมเดลแบบหลายคลาสคือความแม่นยำ TensorFlow มีโมดูลความแม่นยำที่รับอาร์กิวเมนต์สองตัว คือป้ายกำกับและค่าที่ทำนายได้
eval_metric_ops = {
"accuracy": tf.metrics.accuracy(labels=labels, predictions=predictions["classes"])}
return tf.estimator.EstimatorSpec(mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)
แค่นั้นแหละ. คุณสร้าง CNN แรกและพร้อมที่จะรวมทุกอย่างไว้ในฟังก์ชันเพื่อใช้ในการฝึกและประเมินโมเดล
def cnn_model_fn(features, labels, mode): """Model function for CNN.""" # Input Layer input_layer = tf.reshape(features["x"], [-1, 28, 28, 1]) # Convolutional Layer conv1 = tf.layers.conv2d( inputs=input_layer, filters=32, kernel_size=[5, 5], padding="same", activation=tf.nn.relu) # Pooling Layer pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2) # Convolutional Layer #2 and Pooling Layer conv2 = tf.layers.conv2d( inputs=pool1, filters=36, kernel_size=[5, 5], padding="same", activation=tf.nn.relu) pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2) # Dense Layer pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 36]) dense = tf.layers.dense(inputs=pool2_flat, units=7 * 7 * 36, activation=tf.nn.relu) dropout = tf.layers.dropout( inputs=dense, rate=0.4, training=mode == tf.estimator.ModeKeys.TRAIN) # Logits Layer logits = tf.layers.dense(inputs=dropout, units=10) predictions = { # Generate predictions (for PREDICT and EVAL mode) "classes": tf.argmax(input=logits, axis=1), "probabilities": tf.nn.softmax(logits, name="softmax_tensor") } if mode == tf.estimator.ModeKeys.PREDICT: return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions) # Calculate Loss loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits) # Configure the Training Op (for TRAIN mode) 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()) return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op) # Add evaluation metrics Evaluation mode eval_metric_ops = { "accuracy": tf.metrics.accuracy( labels=labels, predictions=predictions["classes"])} return tf.estimator.EstimatorSpec( mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)
หมายเหตุเกี่ยวกับฟังก์ชันที่ประกอบขึ้น: เวอร์ชันที่ห่อหุ้มไว้ด้านบนตั้งค่าเลเยอร์การแปลงแบบคอนโวลูชันแรกเป็น 32 ฟิลเตอร์และดรอปเอาต์เป็น 0.4 ในขณะที่ตัวอย่างแบบทีละขั้นตอนใช้ 14 ฟิลเตอร์และ 0.3 ทั้งสองแบบทำงานได้ แต่ให้เลือกค่าคู่ใดคู่หนึ่งแล้วใช้ค่าเดียวกันตลอดเพื่อให้รูปร่างที่พิมพ์ออกมาตรงกับตารางเลเยอร์
ขั้นตอนด้านล่างนี้เหมือนกับบทช่วยสอนก่อนหน้านี้
ก่อนอื่น คุณกำหนดตัวประมาณด้วยโมเดล CNN สำหรับการจัดหมวดหมู่ภาพ
# Create the Estimator mnist_classifier = tf.estimator.Estimator( model_fn=cnn_model_fn, model_dir="train/mnist_convnet_model")
โครงข่ายประสาทเทียมแบบ CNN ใช้เวลานานในการฝึกฝน ดังนั้นคุณจึงสร้างกลไกการบันทึกเพื่อจัดเก็บค่าของเลเยอร์ softmax ทุกๆ 50 รอบการฝึกฝน
# Set up logging for predictions tensors_to_log = {"probabilities": "softmax_tensor"} logging_hook = tf.train.LoggingTensorHook(tensors=tensors_to_log, every_n_iter=50)
คุณพร้อมที่จะประเมินโมเดลแล้ว คุณตั้งค่าขนาดแบตช์เป็น 100 และสุ่มข้อมูล โปรดทราบว่าเราตั้งค่าขั้นตอนการฝึกฝนไว้ที่ 16,000 ซึ่งอาจใช้เวลานานมาก โปรดอดทน
# Train the model train_input_fn = tf.estimator.inputs.numpy_input_fn( x={"x": X_train_scaled}, y=y_train, batch_size=100, num_epochs=None, shuffle=True) mnist_classifier.train( input_fn=train_input_fn, steps=16000, hooks=[logging_hook])
เมื่อฝึกฝนโมเดลเสร็จแล้ว คุณสามารถประเมินผลและพิมพ์ผลลัพธ์ได้
# Evaluate the model and print results eval_input_fn = tf.estimator.inputs.numpy_input_fn( x={"x": X_test_scaled}, y=y_test, num_epochs=1, shuffle=False) eval_results = mnist_classifier.evaluate(input_fn=eval_input_fn) print(eval_results)
การประเมินผลจะแสดงจุดตรวจสอบที่กู้คืน ขั้นตอนที่หยุดลง และพจนานุกรมเมตริกสุดท้าย
INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Starting evaluation at 2018-08-05-12:52:41 INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from train/mnist_convnet_model/model.ckpt-15652 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Finished evaluation at 2018-08-05-12:52:56 INFO:tensorflow:Saving dict for global step 15652: accuracy = 0.9589286, global_step = 15652, loss = 0.13894269 {'accuracy': 0.9689286, 'loss': 0.13894269, 'global_step': 15652}
ด้วยสถาปัตยกรรมปัจจุบัน พจนานุกรมประเมินผลรายงานความแม่นยำที่ 0.9689286 หรือประมาณ 97% คุณสามารถเปลี่ยนสถาปัตยกรรม ขนาดแบตช์ และจำนวนรอบการทำซ้ำเพื่อปรับปรุงความแม่นยำได้ โครงข่ายประสาทเทียมแบบ CNN ทำงานได้ดีกว่ามากเมื่อเทียบกับ... โครงข่ายประสาทเทียม หรือการถดถอยโลจิสติก: ในบทเรียนเกี่ยวกับโครงข่ายประสาทเทียม คุณได้ความแม่นยำ 96% ซึ่งต่ำกว่า CNN ประสิทธิภาพของ CNN นั้นน่าประทับใจเมื่อใช้กับชุดภาพขนาดใหญ่ ทั้งในแง่ของความเร็วในการคำนวณและความแม่นยำ











