ก่อนที่คุณจะอีกครั้งคืองานตรวจจับวัตถุ สิ่งสำคัญคือความรวดเร็วในการทำงานด้วยความแม่นยำที่ยอมรับได้ คุณใช้สถาปัตยกรรม YOLOv3 และฝึกฝนเพิ่มเติม ความแม่นยำ (mAp75) มากกว่า 0.95 แต่อัตราการวิ่งยังต่ำอยู่ อึ.
วันนี้เราจะข้ามการวัดปริมาณ และภายใต้การตัดเราจะดู การตัดแต่งกิ่งแบบจำลอง — ตัดส่วนที่ซ้ำซ้อนของเครือข่ายออกเพื่อเพิ่มความเร็วในการอนุมานโดยไม่สูญเสียความแม่นยำ ชัดเจนว่าจะตัดที่ไหน เท่าไหร่ และอย่างไร มาดูวิธีดำเนินการด้วยตนเองและที่ที่คุณสามารถทำให้เป็นแบบอัตโนมัติได้ ในตอนท้ายจะมีพื้นที่เก็บข้อมูลบน keras
การแนะนำ
ที่ที่ทำงานเดิมของฉัน Macroscop ในเมือง Perm ฉันมีนิสัยอย่างหนึ่งคือคอยติดตามเวลาดำเนินการของอัลกอริทึมอยู่เสมอ และตรวจสอบรันไทม์ของเครือข่ายผ่านตัวกรองที่เพียงพอเสมอ โดยปกติแล้วความล้ำสมัยในการผลิตจะไม่ผ่านตัวกรองนี้ ซึ่งนำฉันไปสู่การตัดแต่งกิ่ง
การตัดแต่งกิ่งเป็นหัวข้อเก่าที่ถูกกล่าวถึงใน
แต่ขอแยกมันออกจากกัน
เหลือบเข้าสู่ชีววิทยา
ฉันชอบเวลาที่ Deep Learning ดูแนวคิดที่มาจากชีววิทยา พวกมันก็เหมือนกับวิวัฒนาการที่สามารถเชื่อถือได้ (คุณรู้ไหมว่า ReLU นั้นคล้ายคลึงกับมาก)
กระบวนการตัดแต่งกิ่งแบบจำลองก็ใกล้เคียงกับชีววิทยาเช่นกัน การตอบสนองของเครือข่ายที่นี่เทียบได้กับความเป็นพลาสติกของสมอง มีตัวอย่างที่น่าสนใจสองสามตัวอย่างในหนังสือเล่มนี้
- สมองของผู้หญิงที่เกิดมามีเพียงซีกเดียวได้ตั้งโปรแกรมตัวเองใหม่เพื่อทำหน้าที่ของซีกที่หายไป
- ชายคนนั้นยิงสมองส่วนที่รับผิดชอบในการมองเห็นออกไป เมื่อเวลาผ่านไป ส่วนอื่นๆ ของสมองก็เข้ามาทำหน้าที่เหล่านี้ (เราไม่ได้พยายามที่จะทำซ้ำ)
ในทำนองเดียวกัน คุณสามารถตัดการโน้มน้าวที่อ่อนแอบางส่วนออกจากโมเดลของคุณได้ ทางเลือกสุดท้าย มัดที่เหลือจะช่วยทดแทนมัดที่ตัดแล้ว
คุณชอบ Transfer Learning หรือคุณกำลังเรียนรู้ตั้งแต่เริ่มต้นหรือไม่?
ตัวเลือกหมายเลขหนึ่ง คุณใช้ Transfer Learning บน Yolov3 Retina, Mask-RCNN หรือ U-Net แต่โดยส่วนใหญ่แล้ว เราไม่จำเป็นต้องจดจำคลาสอ็อบเจ็กต์ 80 คลาสเหมือนใน COCO ในทางปฏิบัติของฉัน ทุกอย่างจำกัดอยู่แค่เกรด 1-2 เท่านั้น อาจมีคนคิดว่าสถาปัตยกรรมสำหรับ 80 คลาสนั้นซ้ำซ้อนที่นี่ สิ่งนี้ชี้ให้เห็นว่าสถาปัตยกรรมจำเป็นต้องทำให้เล็กลง นอกจากนี้ ฉันอยากจะทำเช่นนี้โดยไม่สูญเสียน้ำหนักที่ฝึกไว้ล่วงหน้าที่มีอยู่
ตัวเลือกหมายเลขสอง บางทีคุณอาจมีข้อมูลและทรัพยากรการประมวลผลจำนวนมาก หรือเพียงแค่ต้องการสถาปัตยกรรมแบบพิเศษเฉพาะ ไม่สำคัญ. แต่คุณกำลังเรียนรู้เครือข่ายตั้งแต่เริ่มต้น ขั้นตอนปกติคือการดูโครงสร้างข้อมูล เลือกสถาปัตยกรรมที่ใช้พลังงานมากเกินไป และผลักดันการออกจากการฝึกอบรมใหม่ ฉันเห็นหลุดไป 0.6 คาร์ล
ในทั้งสองกรณี เครือข่ายสามารถลดลงได้ มีแรงบันดาลใจ ทีนี้เรามาดูกันว่าการตัดแต่งกิ่งคืออะไร
อัลกอริธึมทั่วไป
เราตัดสินใจว่าจะลบชุดข้อมูลออกได้ มันดูค่อนข้างง่าย:
การลบการบิดเบี้ยวใดๆ ออกไปสร้างความตึงเครียดให้กับเครือข่าย ซึ่งมักจะนำไปสู่ข้อผิดพลาดที่เพิ่มขึ้น ในแง่หนึ่ง ข้อผิดพลาดที่เพิ่มขึ้นนี้เป็นตัวบ่งชี้ว่าเรากำจัดการโน้มน้าวใจได้อย่างถูกต้องเพียงใด (เช่น การเพิ่มขึ้นอย่างมากบ่งชี้ว่าเรากำลังทำสิ่งผิด) แต่การเพิ่มขึ้นเล็กน้อยก็ค่อนข้างเป็นที่ยอมรับ และมักจะถูกกำจัดโดยการฝึกอบรมเพิ่มเติมเล็กน้อยด้วย LR ขนาดเล็กในเวลาต่อมา เพิ่มขั้นตอนการฝึกเพิ่มเติม:
ตอนนี้เราต้องหาคำตอบว่าเมื่อใดเราต้องการหยุดการเรียนรู้<->การตัดแต่งกิ่ง อาจมีตัวเลือกแปลกใหม่ที่นี่เมื่อเราต้องการลดเครือข่ายให้มีขนาดและความเร็วที่แน่นอน (เช่น สำหรับอุปกรณ์มือถือ) อย่างไรก็ตาม ตัวเลือกที่พบบ่อยที่สุดคือดำเนินวงจรต่อไปจนกว่าข้อผิดพลาดจะสูงกว่าที่ยอมรับได้ เพิ่มเงื่อนไข:
ดังนั้นอัลกอริธึมจึงชัดเจน ยังคงต้องหาวิธีพิจารณาการโน้มน้าวใจที่ถูกลบ
ค้นหาชุดข้อมูลที่ถูกลบ
เราจำเป็นต้องลบการโน้มน้าวใจบางส่วนออก การรีบเร่งและ "ยิง" ใครก็ตามเป็นความคิดที่ไม่ดีถึงแม้ว่ามันจะได้ผลก็ตาม แต่เนื่องจากคุณมีหัว คุณจึงสามารถคิดและลองเลือกการโน้มน้าวใจที่ "อ่อนแอ" เพื่อนำออกได้ มีหลายตัวเลือก:
การวัด L1 ที่เล็กที่สุดหรือการตัดแต่งกิ่งที่มีขนาดต่ำที่สุด . แนวคิดที่ว่าการโน้มน้าวใจด้วยน้ำหนักน้อยมีส่วนช่วยในการตัดสินใจขั้นสุดท้ายเพียงเล็กน้อย- การวัด L1 ที่น้อยที่สุดโดยคำนึงถึงค่าเฉลี่ยและส่วนเบี่ยงเบนมาตรฐาน เราเสริมด้วยการประเมินลักษณะของการจำหน่าย
กำบังการโน้มน้าวใจและไม่รวมการโน้มน้าวใจที่มีอิทธิพลต่อความแม่นยำขั้นสุดท้ายน้อยที่สุด . การระบุการโน้มน้าวใจที่ไม่มีนัยสำคัญที่แม่นยำยิ่งขึ้น แต่ใช้เวลานานและสิ้นเปลืองทรัพยากรมาก- คนอื่น ๆ
แต่ละตัวเลือกมีสิทธิ์ในการมีชีวิตและคุณสมบัติการใช้งานของตัวเอง ที่นี่เราจะพิจารณาตัวเลือกที่มีการวัด L1 ที่เล็กที่สุด
กระบวนการด้วยตนเองสำหรับ YOLOv3
สถาปัตยกรรมดั้งเดิมประกอบด้วยบล็อกที่เหลือ แต่ไม่ว่าพวกเขาจะเจ๋งแค่ไหนสำหรับเครือข่ายระดับลึก พวกมันก็จะขัดขวางเราบ้าง ปัญหาคือคุณไม่สามารถลบการกระทบยอดที่มีดัชนีต่างกันในเลเยอร์เหล่านี้ได้:
ดังนั้น เรามาเลือกเลเยอร์ที่เราสามารถลบการกระทบยอดได้อย่างอิสระ:
ตอนนี้เรามาสร้างวงจรการทำงานกันดีกว่า:
- กำลังอัพโหลดการเปิดใช้งาน
- ตัดสินใจว่าจะตัดขนาดไหน
- ตัดออก
- เรียนรู้ 10 ยุคด้วย LR=1e-4
- การทดสอบ
การขนถ่ายการโน้มน้าวใจมีประโยชน์ในการประมาณจำนวนส่วนที่เราสามารถเอาออกได้ในขั้นตอนหนึ่ง ตัวอย่างการขนถ่าย:
เราเห็นว่าเกือบทุกที่ 5% ของการโน้มน้าวใจมี L1-norm ต่ำมากและเราสามารถลบมันออกได้ ในแต่ละขั้นตอน การขนถ่ายนี้จะถูกทำซ้ำ และทำการประเมินว่าชั้นใดและจำนวนเท่าใดที่สามารถตัดออกได้
กระบวนการทั้งหมดเสร็จสิ้นใน 4 ขั้นตอน (ตัวเลขที่นี่และทุกที่สำหรับ RTX 2060 Super):
ขั้นตอน | mAp75 | จำนวนพารามิเตอร์ ล้าน | ขนาดเครือข่าย, MB | ตั้งแต่เริ่มต้น % | รันไทม์, นางสาว | สภาพการเข้าสุหนัต |
---|---|---|---|---|---|---|
0 | 0.9656 | 60 | 241 | 100 | 180 | - |
1 | 0.9622 | 55 | 218 | 91 | 175 | 5% ของทั้งหมด |
2 | 0.9625 | 50 | 197 | 83 | 168 | 5% ของทั้งหมด |
3 | 0.9633 | 39 | 155 | 64 | 155 | 15% สำหรับเลเยอร์ที่มีการโน้มน้าวใจมากกว่า 400 ครั้ง |
4 | 0.9555 | 31 | 124 | 51 | 146 | 10% สำหรับเลเยอร์ที่มีการโน้มน้าวใจมากกว่า 100 ครั้ง |
มีการเพิ่มผลเชิงบวกอย่างหนึ่งในขั้นตอนที่ 2 - ขนาดแบตช์ 4 ที่พอดีกับหน่วยความจำ ซึ่งช่วยเร่งกระบวนการฝึกอบรมเพิ่มเติมได้อย่างมาก
ในขั้นตอนที่ 4 กระบวนการหยุดลงเนื่องจาก แม้แต่การฝึกอบรมเพิ่มเติมในระยะยาวก็ไม่ได้เพิ่ม mAp75 ให้เป็นค่าเดิม
ด้วยเหตุนี้ เราจึงสามารถเร่งการอนุมานได้เร็วขึ้น ลด 15%, ลดขนาดลงโดย ลด 35% และไม่แพ้อย่างแน่นอน
ระบบอัตโนมัติสำหรับสถาปัตยกรรมที่เรียบง่าย
สำหรับสถาปัตยกรรมเครือข่ายที่เรียบง่ายกว่า (โดยไม่ต้องเพิ่มเงื่อนไข เชื่อมต่อและบล็อกที่เหลือ) ค่อนข้างเป็นไปได้ที่จะมุ่งเน้นไปที่การประมวลผลเลเยอร์ Convolutional ทั้งหมดและทำให้กระบวนการตัด Convolution เป็นแบบอัตโนมัติ
ฉันใช้ตัวเลือกนี้
ง่ายมาก: คุณเพียงต้องการฟังก์ชันการสูญเสีย เครื่องมือเพิ่มประสิทธิภาพ และเครื่องกำเนิดไฟฟ้าแบบแบตช์:
import pruning
from keras.optimizers import Adam
from keras.utils import Sequence
train_batch_generator = BatchGenerator...
score_batch_generator = BatchGenerator...
opt = Adam(lr=1e-4)
pruner = pruning.Pruner("config.json", "categorical_crossentropy", opt)
pruner.prune(train_batch, valid_batch)
หากจำเป็น คุณสามารถเปลี่ยนพารามิเตอร์การกำหนดค่าได้:
{
"input_model_path": "model.h5",
"output_model_path": "model_pruned.h5",
"finetuning_epochs": 10, # the number of epochs for train between pruning steps
"stop_loss": 0.1, # loss for stopping process
"pruning_percent_step": 0.05, # part of convs for delete on every pruning step
"pruning_standart_deviation_part": 0.2 # shift for limit pruning part
}
นอกจากนี้ ยังมีการใช้ข้อจำกัดตามค่าเบี่ยงเบนมาตรฐานอีกด้วย เป้าหมายคือการจำกัดส่วนที่ถูกนำออก ไม่รวมการโน้มน้าวใจด้วยการวัด L1 ที่ "เพียงพอ" แล้ว:
ดังนั้นเราจึงอนุญาตให้คุณลบเฉพาะการโน้มน้าวที่อ่อนแอจากการแจกแจงที่คล้ายกับอันที่ถูกต้องและไม่ส่งผลกระทบต่อการลบออกจากการแจกแจงที่คล้ายกับอันซ้าย:
เมื่อการกระจายเข้าใกล้ปกติ คุณสามารถเลือกค่าสัมประสิทธิ์การตัดแต่งกิ่ง_มาตรฐาน_ส่วนเบี่ยงเบนได้จาก:
ฉันขอแนะนำสมมติฐานของ 2 ซิกมา หรือคุณสามารถเพิกเฉยต่อคุณลักษณะนี้ได้ โดยปล่อยให้ค่า < 1.0
ผลลัพธ์คือกราฟขนาดเครือข่าย การสูญเสีย และรันไทม์ของเครือข่ายสำหรับการทดสอบทั้งหมด ปรับให้เป็นมาตรฐานเป็น 1.0 ตัวอย่างเช่น ที่นี่ขนาดเครือข่ายลดลงเกือบ 2 เท่าโดยไม่สูญเสียคุณภาพ (เครือข่าย Convolutional ขนาดเล็กที่มีน้ำหนัก 100):
ความเร็วในการวิ่งขึ้นอยู่กับความผันผวนตามปกติและแทบจะไม่เปลี่ยนแปลง มีคำอธิบายสำหรับสิ่งนี้:
- จำนวนการโน้มน้าวใจเปลี่ยนจากสะดวก (32, 64, 128) เป็นไม่สะดวกที่สุดสำหรับการ์ดแสดงผล - 27, 51 เป็นต้น ฉันอาจจะผิดที่นี่ แต่น่าจะมีผลกระทบมากที่สุด
- สถาปัตยกรรมไม่กว้างแต่มีความสม่ำเสมอ การลดความกว้างจะไม่ส่งผลต่อความลึก ดังนั้นเราจึงลดภาระแต่ไม่เปลี่ยนความเร็ว
ดังนั้น การปรับปรุงจึงแสดงให้เห็นในการลดภาระ CUDA ในระหว่างการรันลง 20-30% แต่ไม่ลดเวลาในการรัน
ผลของการ
ลองไตร่ตรองดู เราพิจารณา 2 ตัวเลือกสำหรับการตัดแต่งกิ่ง - สำหรับ YOLOv3 (เมื่อคุณต้องทำงานด้วยมือ) และสำหรับเครือข่ายที่มีสถาปัตยกรรมที่เรียบง่ายกว่า จะเห็นได้ว่าในทั้งสองกรณี มีความเป็นไปได้ที่จะลดขนาดเครือข่ายและเร่งความเร็วได้โดยไม่สูญเสียความแม่นยำ ผลลัพธ์:
- การลดขนาด
- การเร่งความเร็ว
- การลดภาระ CUDA
- ส่งผลให้เป็นมิตรต่อสิ่งแวดล้อม (เราเพิ่มประสิทธิภาพการใช้ทรัพยากรคอมพิวเตอร์ในอนาคต ที่ไหนสักแห่งที่มีความสุข
เกรต้า ธันเบิร์ก )
ภาคผนวก
- หลังจากขั้นตอนการตัดแต่งกิ่ง คุณจะเพิ่มการหาปริมาณได้ (เช่น ด้วย TensorRT)
- Tensorflow ให้ความสามารถสำหรับ
การตัดแต่งกิ่งต่ำ . ได้ผล ที่เก็บ ฉันต้องการที่จะพัฒนาและยินดีที่จะช่วยเหลือ
ที่มา: will.com