เลเยอร์ Batch Normalization ของ Keras ใช้งาน PlatoBlockchain Data Intelligence เสียหาย ค้นหาแนวตั้ง AI.

เลเยอร์ Batch Normalization ของ Keras เสีย

อัปเดต: น่าเสียดายที่คำขอดึงของฉันไปยัง Keras ที่เปลี่ยนพฤติกรรมของเลเยอร์ Batch Normalization ไม่ได้รับการยอมรับ สามารถอ่านรายละเอียด โปรดคลิกที่นี่เพื่ออ่านรายละเอียดเพิ่มเติม. สำหรับบรรดาผู้ที่กล้าพอที่จะยุ่งกับการปรับใช้แบบกำหนดเอง คุณสามารถค้นหาโค้ดได้ใน สาขาของฉัน. ฉันอาจรักษาและรวมเข้ากับ Keras เวอร์ชันเสถียรล่าสุด (2.1.6, 2.2.2 และ 2.2.4) ตราบเท่าที่ฉันใช้มัน แต่ไม่มีสัญญา

คนส่วนใหญ่ที่ทำงานใน Deep Learning ต่างก็เคยใช้หรือเคยได้ยินเกี่ยวกับ Keras. สำหรับผู้ที่ยังไม่มี มันเป็นห้องสมุดที่ยอดเยี่ยมที่สรุปกรอบการเรียนรู้ลึก ๆ เช่น TensorFlow, Theano และ CNTK และให้ API ระดับสูง สำหรับการฝึกอบรม ANN ใช้งานง่าย ช่วยให้สามารถสร้างต้นแบบได้อย่างรวดเร็ว และมีชุมชนที่เป็นมิตร ฉันใช้มันอย่างหนักและมีส่วนร่วมในโครงการเป็นระยะๆ มาระยะหนึ่งแล้ว และฉันแนะนำให้ทุกคนที่ต้องการทำงานใน Deep Learning อย่างแน่นอน

แม้ว่า Keras จะทำให้ชีวิตฉันง่ายขึ้น หลายครั้งที่ฉันถูกพฤติกรรมแปลกๆ ของเลเยอร์ Batch Normalization กัด พฤติกรรมเริ่มต้นของมันเปลี่ยนไปตามกาลเวลา แต่ก็ยังสร้างปัญหาให้กับผู้ใช้จำนวนมากและด้วยเหตุนี้จึงมีความเกี่ยวข้องหลายประการ เปิดประเด็น บน Github ในบล็อกโพสต์นี้ ฉันจะพยายามสร้างกรณีที่ว่าทำไมเลเยอร์ BatchNormalization ของ Keras ถึงเล่นไม่ดีกับ Transfer Learning ฉันจะให้รหัสที่แก้ไขปัญหาและฉันจะยกตัวอย่างพร้อมผลลัพธ์ของ ปะ.

ในหัวข้อย่อยด้านล่าง ฉันได้แนะนำวิธีการใช้ Transfer Learning ใน Deep Learning, เลเยอร์ Batch Normalization คืออะไร, learnining_phase ทำงานอย่างไร และ Keras เปลี่ยนแปลงพฤติกรรม BN อย่างไรเมื่อเวลาผ่านไป หากคุณทราบสิ่งเหล่านี้แล้ว คุณสามารถข้ามไปยังส่วนที่ 2 ได้โดยตรง

1.1 การใช้ Transfer Learning เป็นสิ่งสำคัญสำหรับ Deep Learning

สาเหตุหนึ่งที่ทำให้ Deep Learning ถูกวิพากษ์วิจารณ์ในอดีตก็คือต้องใช้ข้อมูลมากเกินไป สิ่งนี้ไม่เป็นความจริงเสมอไป มีเทคนิคหลายอย่างในการจัดการกับข้อจำกัดนี้ หนึ่งในนั้นคือ Transfer Learning

สมมติว่าคุณกำลังทำงานกับแอปพลิเคชัน Computer Vision และคุณต้องการสร้างตัวแยกประเภทที่แยก Cats ออกจาก Dogs คุณไม่จำเป็นต้องมีภาพแมว/สุนัขหลายล้านภาพในการฝึกโมเดล คุณสามารถใช้ตัวแยกประเภทที่ฝึกไว้ล่วงหน้าและปรับแต่ง convolutions ระดับบนสุดโดยใช้ข้อมูลน้อยลงได้ แนวคิดเบื้องหลังคือ เนื่องจากโมเดลที่ฝึกไว้ล่วงหน้านั้นพอดีกับรูปภาพ การบิดด้านล่างจึงสามารถรับรู้คุณลักษณะต่างๆ เช่น เส้น ขอบ และรูปแบบที่มีประโยชน์อื่นๆ ซึ่งหมายความว่าคุณสามารถใช้น้ำหนักเป็นค่าเริ่มต้นที่ดีหรือฝึกเครือข่ายบางส่วนใหม่ด้วยข้อมูลของคุณ .
เลเยอร์ Batch Normalization ของ Keras ใช้งาน PlatoBlockchain Data Intelligence เสียหาย ค้นหาแนวตั้ง AI.
Keras มาพร้อมกับโมเดลที่ผ่านการฝึกอบรมมาแล้วหลายรุ่นและตัวอย่างที่ใช้งานง่ายเกี่ยวกับวิธีการปรับแต่งโมเดลอย่างละเอียด คุณสามารถอ่านเพิ่มเติมใน เอกสาร.

1.2 เลเยอร์ Batch Normalization คืออะไร?

Ioffe และ Szegedy ได้เปิดตัวเลเยอร์ Batch Normalization ในปี 2014 มันแก้ไขปัญหาการไล่ระดับสีที่หายไปโดยการสร้างมาตรฐานเอาต์พุตของเลเยอร์ก่อนหน้า มันเร่งการฝึกอบรมโดยลดจำนวนการวนซ้ำที่จำเป็น และช่วยให้การฝึกอบรมของโครงข่ายประสาทเทียมลึกขึ้น การอธิบายว่ามันทำงานอย่างไรนั้นอยู่นอกเหนือขอบเขตของโพสต์นี้ แต่ฉันขอแนะนำอย่างยิ่งให้คุณอ่าน กระดาษต้นฉบับ. คำอธิบายที่เข้าใจง่ายเกินไปคือมันปรับขนาดอินพุตใหม่โดยลบค่าเฉลี่ยและหารด้วยค่าเบี่ยงเบนมาตรฐาน นอกจากนี้ยังสามารถเรียนรู้ที่จะเลิกทำการเปลี่ยนแปลงหากจำเป็น
เลเยอร์ Batch Normalization ของ Keras ใช้งาน PlatoBlockchain Data Intelligence เสียหาย ค้นหาแนวตั้ง AI.

1.3 learning_phase ใน Keras คืออะไร?

บางเลเยอร์ทำงานแตกต่างกันระหว่างการฝึกและการอนุมาน ตัวอย่างที่โดดเด่นที่สุดคือ Batch Normalization และ Layer Dropout ในกรณีของ BN ระหว่างการฝึก เราใช้ค่าเฉลี่ยและความแปรปรวนของชุดย่อยเพื่อปรับขนาดอินพุตใหม่ ในทางกลับกัน ในระหว่างการอนุมาน เราใช้ค่าเฉลี่ยเคลื่อนที่และความแปรปรวนที่ประมาณไว้ระหว่างการฝึก

Keras รู้ดีว่าควรรันโหมดใดเพราะมีกลไกในตัวที่เรียกว่า การเรียนรู้_เฟส. ขั้นตอนการเรียนรู้จะควบคุมว่าเครือข่ายอยู่ในโหมดรถไฟหรือโหมดทดสอบ หากผู้ใช้ไม่ได้ตั้งค่าด้วยตนเอง ระหว่าง fit() เครือข่ายจะทำงานด้วย learning_phase=1 (โหมดรถไฟ) ในขณะที่สร้างการคาดคะเน (เช่น เมื่อเราเรียกเมธอดทำนาย () & ประเมิน () หรือในขั้นตอนการตรวจสอบความถูกต้องของความพอดี ()) เครือข่ายจะทำงานด้วย learning_phase=0 (โหมดทดสอบ) แม้ว่าจะไม่แนะนำ แต่ผู้ใช้ยังสามารถเปลี่ยน learning_phase เป็นค่าเฉพาะได้ แต่สิ่งนี้จำเป็นต้องเกิดขึ้นก่อนที่จะเพิ่มโมเดลหรือเทนเซอร์ใดๆ ลงในกราฟ หาก learning_phase ถูกตั้งค่าแบบสแตติก Keras จะถูกล็อคไปยังโหมดใดก็ตามที่ผู้ใช้เลือก

1.4 Keras ใช้ Batch Normalization อย่างไรเมื่อเวลาผ่านไป?

Keras ได้เปลี่ยนการทำงานของ Batch Normalization หลายครั้ง แต่การอัปเดตที่สำคัญล่าสุดเกิดขึ้นใน Keras 2.1.3 ก่อน v2.1.3 เมื่อเลเยอร์ BN ถูกแช่แข็ง (ฝึกได้ = เท็จ) มันยังคงอัปเดตสถิติแบทช์อย่างต่อเนื่อง ซึ่งเป็นสิ่งที่ทำให้ผู้ใช้ปวดหัวอย่างมาก

นี่ไม่ใช่แค่นโยบายแปลก ๆ มันผิดจริงๆ ลองนึกภาพว่ามีชั้น BN อยู่ระหว่างการบิด หากเลเยอร์ถูกแช่แข็ง ไม่ควรมีการเปลี่ยนแปลง หากเราอัปเดตน้ำหนักบางส่วนและเลเยอร์ถัดไปก็หยุดนิ่งด้วย เลเยอร์เหล่านี้จะไม่มีโอกาสปรับให้เข้ากับการอัปเดตสถิติแบบมินิแบทช์ซึ่งนำไปสู่ข้อผิดพลาดที่สูงขึ้น โชคดีที่เริ่มต้นจากเวอร์ชัน 2.1.3 เมื่อเลเยอร์ BN ถูกตรึงจะไม่อัปเดตสถิติอีกต่อไป แต่นั่นจะเพียงพอหรือไม่? ไม่ใช่ถ้าคุณใช้ Transfer Learning

ด้านล่างฉันอธิบายอย่างชัดเจนว่าปัญหาคืออะไรและฉันร่างการใช้งานทางเทคนิคเพื่อแก้ไขปัญหา ฉันยังให้ตัวอย่างบางส่วนเพื่อแสดงผลกระทบต่อความแม่นยำของแบบจำลองก่อนและหลัง ปะ ถูกนำมาใช้

2.1 คำอธิบายทางเทคนิคของปัญหา

ปัญหาของการนำ Keras ไปใช้งานในปัจจุบันคือเมื่อเลเยอร์ BN ถูกแช่แข็ง มันยังคงใช้สถิติมินิแบตช์ต่อไประหว่างการฝึก ฉันเชื่อว่าแนวทางที่ดีกว่าเมื่อ BN ถูกตรึงคือการใช้ค่าเฉลี่ยเคลื่อนที่และความแปรปรวนที่เรียนรู้ระหว่างการฝึก ทำไม? ด้วยเหตุผลเดียวกันกับที่ไม่ควรอัปเดตสถิติมินิแบตช์เมื่อเลเยอร์ถูกตรึง: อาจทำให้ได้ผลลัพธ์ที่ไม่ดีเพราะเลเยอร์ถัดไปไม่ได้รับการฝึกฝนอย่างเหมาะสม

สมมติว่าคุณกำลังสร้างโมเดล Computer Vision แต่มีข้อมูลไม่เพียงพอ คุณจึงตัดสินใจใช้หนึ่งใน CNN ที่ได้รับการฝึกอบรมล่วงหน้าของ Keras และปรับแต่งให้เหมาะสม น่าเสียดายที่การทำเช่นนี้ คุณจะไม่รับประกันว่าค่าเฉลี่ยและความแปรปรวนของชุดข้อมูลใหม่ของคุณภายในเลเยอร์ BN จะคล้ายกับชุดข้อมูลเดิม โปรดจำไว้ว่าในขณะนี้ ในระหว่างการฝึกอบรม เครือข่ายของคุณจะใช้สถิติมินิแบตช์เสมอ ไม่ว่าเลเยอร์ BN จะหยุดทำงานหรือไม่ก็ตาม นอกจากนี้ ในระหว่างการอนุมาน คุณจะใช้สถิติที่เรียนรู้ก่อนหน้านี้ของเลเยอร์ BN ที่ถูกตรึงไว้ ดังนั้น หากคุณปรับชั้นบนสุดอย่างละเอียด น้ำหนักของพวกมันจะถูกปรับเป็นค่าเฉลี่ย/ความแปรปรวนของ ใหม่ ชุดข้อมูล อย่างไรก็ตาม ในระหว่างการอนุมาน พวกเขาจะได้รับข้อมูลที่มีการปรับขนาด ต่างกัน เพราะค่าเฉลี่ย/ความแปรปรวนของ เป็นต้นฉบับ จะใช้ชุดข้อมูล
เลเยอร์ Batch Normalization ของ Keras ใช้งาน PlatoBlockchain Data Intelligence เสียหาย ค้นหาแนวตั้ง AI.
ด้านบน ฉันมีสถาปัตยกรรมที่เรียบง่าย (และไม่สมจริง) สำหรับการสาธิต สมมติว่าเราปรับแต่งโมเดลจาก Convolution k+1 จนถึงด้านบนของเครือข่าย (ด้านขวา) และตรึงด้านล่าง (ด้านซ้าย) ระหว่างการฝึก BN เลเยอร์ทั้งหมดตั้งแต่ 1 ถึง k จะใช้ค่าเฉลี่ย/ความแปรปรวนของข้อมูลการฝึกของคุณ สิ่งนี้จะส่งผลเสียต่อ ReLU ที่ถูกแช่แข็ง หากค่าเฉลี่ยและความแปรปรวนของ BN แต่ละอันไม่ใกล้เคียงกับค่าที่เรียนรู้ระหว่างการเตรียมการฝึกอบรม นอกจากนี้ยังจะทำให้ส่วนที่เหลือของเครือข่าย (จาก CONV k+1 และใหม่กว่า) ได้รับการฝึกอบรมด้วยอินพุตที่มีมาตราส่วนต่างกันเมื่อเทียบกับสิ่งที่จะได้รับระหว่างการอนุมาน ในระหว่างการฝึกอบรม เครือข่ายของคุณสามารถปรับให้เข้ากับการเปลี่ยนแปลงเหล่านี้ได้ อย่างไรก็ตาม ในขณะที่คุณเปลี่ยนไปใช้โหมดการคาดคะเน Keras จะใช้สถิติการกำหนดมาตรฐานที่แตกต่างกัน บางอย่างที่จะช่วยกระจายอินพุตของเลเยอร์ถัดไปอย่างรวดเร็วซึ่งนำไปสู่ผลลัพธ์ที่ไม่ดี

2.2 คุณจะตรวจพบได้อย่างไรว่าคุณได้รับผลกระทบหรือไม่?

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

อีกวิธีหนึ่งในการตรวจจับปัญหาขณะทำงานกับตัวแยกประเภทไบนารีคือการตรวจสอบความถูกต้องและ AUC หากความแม่นยำอยู่ใกล้ 50% แต่ AUC ใกล้เคียงกับ 1 (และคุณสังเกตเห็นความแตกต่างระหว่างโหมดฝึก/ทดสอบในชุดข้อมูลเดียวกัน) อาจเป็นไปได้ว่าความน่าจะเป็นไม่อยู่ในขอบเขตเนื่องจากสถิติ BN ในทำนองเดียวกัน สำหรับการถดถอย คุณสามารถใช้สหสัมพันธ์ของ MSE และ Spearman เพื่อตรวจจับได้

2.3 เราจะแก้ไขได้อย่างไร?

ฉันเชื่อว่าปัญหาสามารถแก้ไขได้หากเลเยอร์ BN ที่แช่แข็งนั้นเป็นจริง: ล็อคอย่างถาวรในโหมดทดสอบ การนำไปใช้อย่างชาญฉลาด แฟล็กที่ฝึกได้จะต้องเป็นส่วนหนึ่งของกราฟการคำนวณ และพฤติกรรมของ BN นั้นจะต้องไม่เพียงแค่ขึ้นอยู่กับระยะการเรียนรู้เท่านั้น แต่ยังขึ้นกับมูลค่าของทรัพย์สินที่ฝึกได้ด้วย คุณสามารถดูรายละเอียดการใช้งานของฉันได้ที่ Github.

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

2.4 การประเมินผลกระทบของโปรแกรมแก้ไข

แม้ว่าฉันจะเขียนการใช้งานข้างต้นเมื่อเร็วๆ นี้ แต่แนวคิดเบื้องหลังได้รับการทดสอบอย่างหนักเกี่ยวกับปัญหาในโลกแห่งความเป็นจริงโดยใช้วิธีแก้ไขปัญหาชั่วคราวต่างๆ ที่มีผลเช่นเดียวกัน ตัวอย่างเช่น ความคลาดเคลื่อนระหว่างโหมดการฝึกและการทดสอบ และสามารถหลีกเลี่ยงได้โดยการแยกเครือข่ายออกเป็นสองส่วน (หยุดนิ่งและยกเลิกการตรึง) และดำเนินการฝึกอบรมที่แคช อย่างไรก็ตาม เนื่องจาก "เชื่อฉันว่าฉันเคยทำสิ่งนี้มาก่อน" มักจะไม่มีน้ำหนัก ด้านล่างนี้ฉันจึงแสดงตัวอย่างบางส่วนที่แสดงผลของการนำไปใช้จริงในทางปฏิบัติ

ต่อไปนี้คือประเด็นสำคัญบางประการเกี่ยวกับการทดสอบ:

  1. ฉันจะใช้ข้อมูลจำนวนเล็กน้อยเพื่อจงใจใส่โมเดลมากเกินไป และฉันจะฝึกและตรวจสอบโมเดลในชุดข้อมูลเดียวกัน เมื่อทำเช่นนั้น ฉันคาดว่าจะมีความแม่นยำและประสิทธิภาพที่ใกล้เคียงกันในชุดข้อมูลรถไฟ/การตรวจสอบความถูกต้อง
  2. หากในระหว่างการตรวจสอบความถูกต้อง ฉันได้รับความแม่นยำที่ต่ำกว่าอย่างเห็นได้ชัดในชุดข้อมูลเดียวกัน ฉันจะมีข้อบ่งชี้ที่ชัดเจนว่านโยบาย BN ปัจจุบันส่งผลกระทบในทางลบต่อประสิทธิภาพของแบบจำลองในระหว่างการอนุมาน
  3. การประมวลผลล่วงหน้าใดๆ จะเกิดขึ้นนอกเครื่องกำเนิด สิ่งนี้ทำเพื่อแก้ไขจุดบกพร่องที่เปิดตัวใน v2.1.5 (ปัจจุบันได้รับการแก้ไขใน v2.1.6 และต้นแบบล่าสุด)
  4. เราจะบังคับให้ Keras ใช้ขั้นตอนการเรียนรู้ที่แตกต่างกันระหว่างการประเมิน หากเราสังเกตเห็นความแตกต่างระหว่างความถูกต้องที่รายงาน เราจะรู้ว่าเราได้รับผลกระทบจากนโยบาย BN ในปัจจุบัน

รหัสสำหรับการทดสอบแสดงอยู่ด้านล่าง:

import numpy as np
from keras.datasets import cifar10
from scipy.misc import imresize

from keras.preprocessing.image import ImageDataGenerator
from keras.applications.resnet50 import ResNet50, preprocess_input
from keras.models import Model, load_model
from keras.layers import Dense, Flatten
from keras import backend as K


seed = 42
epochs = 10
records_per_class = 100

# We take only 2 classes from CIFAR10 and a very small sample to intentionally overfit the model.
# We will also use the same data for train/test and expect that Keras will give the same accuracy.
(x, y), _ = cifar10.load_data()

def filter_resize(category):
   # We do the preprocessing here instead in the Generator to get around a bug on Keras 2.1.5.
   return [preprocess_input(imresize(img, (224,224)).astype('float')) for img in x[y.flatten()==category][:records_per_class]]

x = np.stack(filter_resize(3)+filter_resize(5))
records_per_class = x.shape[0] // 2
y = np.array([[1,0]]*records_per_class + [[0,1]]*records_per_class)


# We will use a pre-trained model and finetune the top layers.
np.random.seed(seed)
base_model = ResNet50(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
l = Flatten()(base_model.output)
predictions = Dense(2, activation='softmax')(l)
model = Model(inputs=base_model.input, outputs=predictions)

for layer in model.layers[:140]:
   layer.trainable = False

for layer in model.layers[140:]:
   layer.trainable = True

model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit_generator(ImageDataGenerator().flow(x, y, seed=42), epochs=epochs, validation_data=ImageDataGenerator().flow(x, y, seed=42))

# Store the model on disk
model.save('tmp.h5')


# In every test we will clear the session and reload the model to force Learning_Phase values to change.
print('DYNAMIC LEARNING_PHASE')
K.clear_session()
model = load_model('tmp.h5')
# This accuracy should match exactly the one of the validation set on the last iteration.
print(model.evaluate_generator(ImageDataGenerator().flow(x, y, seed=42)))


print('STATIC LEARNING_PHASE = 0')
K.clear_session()
K.set_learning_phase(0)
model = load_model('tmp.h5')
# Again the accuracy should match the above.
print(model.evaluate_generator(ImageDataGenerator().flow(x, y, seed=42)))


print('STATIC LEARNING_PHASE = 1')
K.clear_session()
K.set_learning_phase(1)
model = load_model('tmp.h5')
# The accuracy will be close to the one of the training set on the last iteration.
print(model.evaluate_generator(ImageDataGenerator().flow(x, y, seed=42)))

ตรวจสอบผลลัพธ์ของ Keras v2.1.5:

Epoch 1/10
1/7 [===>..........................] - ETA: 25s - loss: 0.8751 - acc: 0.5312
2/7 [=======>......................] - ETA: 11s - loss: 0.8594 - acc: 0.4531
3/7 [===========>..................] - ETA: 7s - loss: 0.8398 - acc: 0.4688 
4/7 [================>.............] - ETA: 4s - loss: 0.8467 - acc: 0.4844
5/7 [====================>.........] - ETA: 2s - loss: 0.7904 - acc: 0.5437
6/7 [========================>.....] - ETA: 1s - loss: 0.7593 - acc: 0.5625
7/7 [==============================] - 12s 2s/step - loss: 0.7536 - acc: 0.5744 - val_loss: 0.6526 - val_acc: 0.6650

Epoch 2/10
1/7 [===>..........................] - ETA: 4s - loss: 0.3881 - acc: 0.8125
2/7 [=======>......................] - ETA: 3s - loss: 0.3945 - acc: 0.7812
3/7 [===========>..................] - ETA: 2s - loss: 0.3956 - acc: 0.8229
4/7 [================>.............] - ETA: 1s - loss: 0.4223 - acc: 0.8047
5/7 [====================>.........] - ETA: 1s - loss: 0.4483 - acc: 0.7812
6/7 [========================>.....] - ETA: 0s - loss: 0.4325 - acc: 0.7917
7/7 [==============================] - 8s 1s/step - loss: 0.4095 - acc: 0.8089 - val_loss: 0.4722 - val_acc: 0.7700

Epoch 3/10
1/7 [===>..........................] - ETA: 4s - loss: 0.2246 - acc: 0.9375
2/7 [=======>......................] - ETA: 3s - loss: 0.2167 - acc: 0.9375
3/7 [===========>..................] - ETA: 2s - loss: 0.2260 - acc: 0.9479
4/7 [================>.............] - ETA: 2s - loss: 0.2179 - acc: 0.9375
5/7 [====================>.........] - ETA: 1s - loss: 0.2356 - acc: 0.9313
6/7 [========================>.....] - ETA: 0s - loss: 0.2392 - acc: 0.9427
7/7 [==============================] - 8s 1s/step - loss: 0.2288 - acc: 0.9456 - val_loss: 0.4282 - val_acc: 0.7800

Epoch 4/10
1/7 [===>..........................] - ETA: 4s - loss: 0.2183 - acc: 0.9688
2/7 [=======>......................] - ETA: 3s - loss: 0.1899 - acc: 0.9844
3/7 [===========>..................] - ETA: 2s - loss: 0.1887 - acc: 0.9792
4/7 [================>.............] - ETA: 1s - loss: 0.1995 - acc: 0.9531
5/7 [====================>.........] - ETA: 1s - loss: 0.1932 - acc: 0.9625
6/7 [========================>.....] - ETA: 0s - loss: 0.1819 - acc: 0.9688
7/7 [==============================] - 8s 1s/step - loss: 0.1743 - acc: 0.9747 - val_loss: 0.3778 - val_acc: 0.8400

Epoch 5/10
1/7 [===>..........................] - ETA: 3s - loss: 0.0973 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0828 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0851 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0897 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0928 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0936 - acc: 1.0000
7/7 [==============================] - 8s 1s/step - loss: 0.1337 - acc: 0.9838 - val_loss: 0.3916 - val_acc: 0.8100

Epoch 6/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0747 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0852 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0812 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0831 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0779 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0766 - acc: 1.0000
7/7 [==============================] - 8s 1s/step - loss: 0.0813 - acc: 1.0000 - val_loss: 0.3637 - val_acc: 0.8550

Epoch 7/10
1/7 [===>..........................] - ETA: 1s - loss: 0.2478 - acc: 0.8750
2/7 [=======>......................] - ETA: 2s - loss: 0.1966 - acc: 0.9375
3/7 [===========>..................] - ETA: 2s - loss: 0.1528 - acc: 0.9583
4/7 [================>.............] - ETA: 1s - loss: 0.1300 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.1193 - acc: 0.9750
6/7 [========================>.....] - ETA: 0s - loss: 0.1196 - acc: 0.9792
7/7 [==============================] - 8s 1s/step - loss: 0.1084 - acc: 0.9838 - val_loss: 0.3546 - val_acc: 0.8600

Epoch 8/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0539 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.0900 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0815 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0740 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0700 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0701 - acc: 1.0000
7/7 [==============================] - 8s 1s/step - loss: 0.0695 - acc: 1.0000 - val_loss: 0.3269 - val_acc: 0.8600

Epoch 9/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0306 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0377 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0898 - acc: 0.9583
4/7 [================>.............] - ETA: 1s - loss: 0.0773 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.0742 - acc: 0.9750
6/7 [========================>.....] - ETA: 0s - loss: 0.0708 - acc: 0.9792
7/7 [==============================] - 8s 1s/step - loss: 0.0659 - acc: 0.9838 - val_loss: 0.3604 - val_acc: 0.8600

Epoch 10/10
1/7 [===>..........................] - ETA: 3s - loss: 0.0354 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0381 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0354 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0828 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.0791 - acc: 0.9750
6/7 [========================>.....] - ETA: 0s - loss: 0.0794 - acc: 0.9792
7/7 [==============================] - 8s 1s/step - loss: 0.0704 - acc: 0.9838 - val_loss: 0.3615 - val_acc: 0.8600

DYNAMIC LEARNING_PHASE
[0.3614931714534759, 0.86]

STATIC LEARNING_PHASE = 0
[0.3614931714534759, 0.86]

STATIC LEARNING_PHASE = 1
[0.025861846953630446, 1.0]

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

หลังจากการฝึกอบรมเสร็จสิ้น เราจะประเมินแบบจำลองโดยใช้การกำหนดค่า learning_phase ที่แตกต่างกัน 3 แบบ: ไดนามิก สแตติก = 0 (โหมดทดสอบ) และสแตติก = 1 (โหมดการฝึก) ดังที่เราเห็นการกำหนดค่าสองรายการแรกจะให้ผลลัพธ์ที่เหมือนกันในแง่ของการสูญเสียและความถูกต้อง และค่าของการกำหนดค่านั้นตรงกับความถูกต้องที่รายงานของแบบจำลองในชุดการตรวจสอบความถูกต้องในการทำซ้ำครั้งล่าสุด อย่างไรก็ตาม เมื่อเราเปลี่ยนไปใช้โหมดการฝึก เราจะสังเกตเห็นความคลาดเคลื่อนอย่างมาก (การปรับปรุง) ทำไมถึงเป็นเช่นนั้น? ดังที่เราได้กล่าวไว้ก่อนหน้านี้ น้ำหนักของเครือข่ายได้รับการปรับโดยคาดหวังว่าจะได้รับข้อมูลที่ปรับขนาดด้วยค่าเฉลี่ย/ความแปรปรวนของข้อมูลการฝึกอบรม น่าเสียดายที่สถิติเหล่านั้นแตกต่างจากสถิติที่จัดเก็บไว้ในเลเยอร์ BN เนื่องจากเลเยอร์ BN ถูกระงับ สถิติเหล่านี้จึงไม่ได้รับการอัปเดต ความคลาดเคลื่อนระหว่างค่าของสถิติ BN นี้ทำให้ความแม่นยำลดลงในระหว่างการอนุมาน

มาดูกันว่าจะเกิดอะไรขึ้นเมื่อเราใช้ ปะ:

Epoch 1/10
1/7 [===>..........................] - ETA: 26s - loss: 0.9992 - acc: 0.4375
2/7 [=======>......................] - ETA: 12s - loss: 1.0534 - acc: 0.4375
3/7 [===========>..................] - ETA: 7s - loss: 1.0592 - acc: 0.4479 
4/7 [================>.............] - ETA: 4s - loss: 0.9618 - acc: 0.5000
5/7 [====================>.........] - ETA: 2s - loss: 0.8933 - acc: 0.5250
6/7 [========================>.....] - ETA: 1s - loss: 0.8638 - acc: 0.5417
7/7 [==============================] - 13s 2s/step - loss: 0.8357 - acc: 0.5570 - val_loss: 0.2414 - val_acc: 0.9450

Epoch 2/10
1/7 [===>..........................] - ETA: 4s - loss: 0.2331 - acc: 0.9688
2/7 [=======>......................] - ETA: 2s - loss: 0.3308 - acc: 0.8594
3/7 [===========>..................] - ETA: 2s - loss: 0.3986 - acc: 0.8125
4/7 [================>.............] - ETA: 1s - loss: 0.3721 - acc: 0.8281
5/7 [====================>.........] - ETA: 1s - loss: 0.3449 - acc: 0.8438
6/7 [========================>.....] - ETA: 0s - loss: 0.3168 - acc: 0.8646
7/7 [==============================] - 9s 1s/step - loss: 0.3165 - acc: 0.8633 - val_loss: 0.1167 - val_acc: 0.9950

Epoch 3/10
1/7 [===>..........................] - ETA: 1s - loss: 0.2457 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.2592 - acc: 0.9688
3/7 [===========>..................] - ETA: 2s - loss: 0.2173 - acc: 0.9688
4/7 [================>.............] - ETA: 1s - loss: 0.2122 - acc: 0.9688
5/7 [====================>.........] - ETA: 1s - loss: 0.2003 - acc: 0.9688
6/7 [========================>.....] - ETA: 0s - loss: 0.1896 - acc: 0.9740
7/7 [==============================] - 9s 1s/step - loss: 0.1835 - acc: 0.9773 - val_loss: 0.0678 - val_acc: 1.0000

Epoch 4/10
1/7 [===>..........................] - ETA: 1s - loss: 0.2051 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.1652 - acc: 0.9844
3/7 [===========>..................] - ETA: 2s - loss: 0.1423 - acc: 0.9896
4/7 [================>.............] - ETA: 1s - loss: 0.1289 - acc: 0.9922
5/7 [====================>.........] - ETA: 1s - loss: 0.1225 - acc: 0.9938
6/7 [========================>.....] - ETA: 0s - loss: 0.1149 - acc: 0.9948
7/7 [==============================] - 9s 1s/step - loss: 0.1060 - acc: 0.9955 - val_loss: 0.0455 - val_acc: 1.0000

Epoch 5/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0769 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.0846 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0797 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0736 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0914 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0858 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0808 - acc: 1.0000 - val_loss: 0.0346 - val_acc: 1.0000

Epoch 6/10
1/7 [===>..........................] - ETA: 1s - loss: 0.1267 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.1039 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0893 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0780 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0758 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0789 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0738 - acc: 1.0000 - val_loss: 0.0248 - val_acc: 1.0000

Epoch 7/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0344 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0385 - acc: 1.0000
3/7 [===========>..................] - ETA: 3s - loss: 0.0467 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0445 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0446 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0429 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0421 - acc: 1.0000 - val_loss: 0.0202 - val_acc: 1.0000

Epoch 8/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0319 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0300 - acc: 1.0000
3/7 [===========>..................] - ETA: 3s - loss: 0.0320 - acc: 1.0000
4/7 [================>.............] - ETA: 2s - loss: 0.0307 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0303 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0291 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0358 - acc: 1.0000 - val_loss: 0.0167 - val_acc: 1.0000

Epoch 9/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0246 - acc: 1.0000
2/7 [=======>......................] - ETA: 3s - loss: 0.0255 - acc: 1.0000
3/7 [===========>..................] - ETA: 3s - loss: 0.0258 - acc: 1.0000
4/7 [================>.............] - ETA: 2s - loss: 0.0250 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0252 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0260 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0327 - acc: 1.0000 - val_loss: 0.0143 - val_acc: 1.0000

Epoch 10/10
1/7 [===>..........................] - ETA: 4s - loss: 0.0251 - acc: 1.0000
2/7 [=======>......................] - ETA: 2s - loss: 0.0228 - acc: 1.0000
3/7 [===========>..................] - ETA: 2s - loss: 0.0217 - acc: 1.0000
4/7 [================>.............] - ETA: 1s - loss: 0.0249 - acc: 1.0000
5/7 [====================>.........] - ETA: 1s - loss: 0.0244 - acc: 1.0000
6/7 [========================>.....] - ETA: 0s - loss: 0.0239 - acc: 1.0000
7/7 [==============================] - 9s 1s/step - loss: 0.0290 - acc: 1.0000 - val_loss: 0.0127 - val_acc: 1.0000

DYNAMIC LEARNING_PHASE
[0.012697912137955427, 1.0]

STATIC LEARNING_PHASE = 0
[0.012697912137955427, 1.0]

STATIC LEARNING_PHASE = 1
[0.01744014158844948, 1.0]

ประการแรก เราสังเกตว่าเครือข่ายมาบรรจบกันเร็วขึ้นอย่างมากและได้ความแม่นยำที่สมบูรณ์แบบ เรายังเห็นว่าไม่มีความคลาดเคลื่อนในแง่ของความแม่นยำอีกต่อไปเมื่อเราสลับระหว่างค่า learning_phase ที่แตกต่างกัน

2.5 แพตช์ทำงานอย่างไรกับชุดข้อมูลจริง

ดังนั้นโปรแกรมแก้ไขทำงานอย่างไรในการทดลองที่สมจริงยิ่งขึ้น? ลองใช้ ResNet50 ที่ได้รับการฝึกฝนล่วงหน้าของ Keras (แต่เดิมพอดีกับ imagenet) ลบเลเยอร์การจัดหมวดหมู่ด้านบนและปรับแต่งแบบมีและไม่มีโปรแกรมแก้ไขและเปรียบเทียบผลลัพธ์ สำหรับข้อมูล เราจะใช้ CIFAR10 (การแบ่งรถไฟมาตรฐาน/การทดสอบที่จัดเตรียมโดย Keras) และเราจะปรับขนาดภาพเป็น 224×224 เพื่อให้เข้ากันได้กับขนาดอินพุตของ ResNet50

เราจะทำ 10 ยุคเพื่อฝึกเลเยอร์การจัดหมวดหมู่บนสุดโดยใช้ RSMprop จากนั้นเราจะทำอีก 5 ครั้งเพื่อปรับแต่งทุกอย่างหลังจากเลเยอร์ที่ 139 โดยใช้ SGD(lr=1e-4, โมเมนตัม=0.9) หากไม่มีโปรแกรมแก้ไข โมเดลของเรามีความแม่นยำถึง 87.44% เมื่อใช้แพตช์นี้ เราได้รับความแม่นยำ 92.36% ซึ่งสูงกว่าเกือบ 5 คะแนน

2.6 เราควรใช้โปรแกรมแก้ไขเดียวกันกับเลเยอร์อื่น ๆ เช่น Dropout หรือไม่?

Batch Normalization ไม่ใช่เลเยอร์เดียวที่ทำงานแตกต่างกันระหว่างโหมดฝึกและโหมดการทดสอบ การออกกลางคันและรูปแบบต่างๆ ก็มีผลเช่นเดียวกัน เราควรใช้นโยบายเดียวกันกับเลเยอร์เหล่านี้ทั้งหมดหรือไม่ ฉันไม่เชื่อ (แม้ว่าฉันจะชอบที่จะได้ยินความคิดของคุณเกี่ยวกับเรื่องนี้) เหตุผลก็คือว่า Dropout ถูกใช้เพื่อหลีกเลี่ยงการ overfit ดังนั้นการล็อคมันอย่างถาวรไปยังโหมดการทำนายระหว่างการฝึกจะทำให้จุดประสงค์ของมันเสียไป คุณคิดอย่างไร?

ฉันเชื่ออย่างยิ่งว่าความคลาดเคลื่อนนี้ต้องได้รับการแก้ไขใน Keras ฉันได้เห็นเอฟเฟกต์ที่ลึกซึ้งยิ่งขึ้น (จากความแม่นยำ 100% เหลือ 50%) ในแอปพลิเคชันในโลกแห่งความเป็นจริงที่เกิดจากปัญหานี้ ผม วางแผนที่จะส่ง ส่งแล้ว PR ถึง Keras ด้วยการแก้ไขและหวังว่าจะได้รับการยอมรับ

หากคุณชอบบล็อกโพสต์นี้ โปรดสละเวลาสักครู่เพื่อแชร์บน Facebook หรือ Twitter 🙂

ประทับเวลา:

เพิ่มเติมจาก กล่องข้อมูล