Gradient problem with a custom sigmoid function
สืบเนื่องจาก หลายวันก่อน ได้ทำการ Train Data ชื่อว่า Imagenet ซึ่งมี Feature 1000 parameters จริงๆ แล้วมาจาก Image แต่ทำการแตก Feature ออกมาแล้ว 1000 ตัว นำเข้าไป Train โดยทำการปรับ parameter ของ Sigmoid เพียง 4 ตัว คือ A, B,C และ D จากสมการ sigmoid (A/(1+epx(-(x+C)*B) ) +D ซึ่งเป็น สมาการทั่วไปของ Sigmoid
จากนั้นพบปัญหา เปิด nan (not a number) ขบวนการสืบสวนเริ่มขึ้นจากทำไมเกิด nan เริ่มตั้งแต่ check data ว่ามี nan ไหม สุดท้ายไปพบว่า เกิดจากการที่ tensorflow ทำ gradient แล้ว เกิดเป็น nan ทำไมมันเกิดได้ sigmoid เวลาเราหา derivertive สูงสุดก็ได้แค่ 0.25 ทำไมมี gradient nan ขึ้นมา??
จนกระทั้งได้พบสาเหตุเกิดจาก tensorflow ทำการหาgradient จริงๆ แต่ว่า ทำ diff แล้วไม่ได้มีการลดรูป (มันก็ไม่ได้จะทำให้ทุกเรื่องอะนะ) คือ
จากสมการของเรา
จะทำ diff เทียบทีละตัวนะครับ จากสมการเรานี่เหละ
เริ่มจาก D A B และ C ไล่จากซับซ้อนน้อยๆ ไปมากๆ แล้วกันนะครับ ดิฟ เทียบ D เราจะได้ดังรูปด้านล่าง
เทียบ A จะได้
ดิฟเทียบ C จะยากนิดนึงครับ เพราะติดหลายตัว จะทำ Chain rule นะครับ ให้ u = (x+c)B นะครับ จะเขียนใหม่ได้เป็น
ส่วน B ก็จะติดคล้ายกับ C นะครับ ได้เป็น
และแทน u ด้วย (x+c)*B จะได้
จะเห็นว่า parameter B และ C จะมี term ของ Expo e ติดอยู่ครับ ปัญหาอยู่ที่ หากเราให้ Tensorflow ทำ Gradient เอง สมการนี้จะไม่ถูกลดรูปครับ ดังนั้นจะติดค่า e ยกกำลังขโยงนี้ไว้ ตามสมการด้านล่างนี้ครับ
เหมือนไม่มีอะไรแต่ถ้า x และ C และ B มีค่า เยอะๆๆ มากๆ term ทางด้านบน จะเข้าใกล้ infinity และส่วน ด้านล่างจะ เป็น 1/ inf ซึ่งเข้าใกล้ 0 หาก tensorflow นำทั้ง 2 term มาคูณกันจะเป็น nan ทันทีครับ นี่คือเหตุผล ที่เกิด nan หากทำ custom function ขึ้นมาเอง ซึ่ง ไม่ใช่เรื่องที่ผิด แต่เราอาจจะต้องทำการลดรูปเพื่อช่วยในการคำนวน ก่อนที่จะให้ tensorflow คำนวนครับ
แล้วทำไม Sigmoid ของ Tensorflow ไม่เกิด nan
ตอบแบบนี้ครับ เพราะว่า Derivertive ของ sigmoid ที่อยู่ใน tensorflow นั้นถูกลดรูปมาแล้วครับจากสมการด้านบนจะได้เป็น
ซึ่งมันก็คือ สมการ sigmoid คูณ กับ 1- sigmoid แล้วที่ปลอดภัยคือ หาก u หรือ (x+C)*B เป็นเลขมากๆ ค่าของ e^(u) ก็จะวิ่งเข้าใกล้ inf ทำให้ส่วนทั้งหมด เป็น 0 จาก 1/inf -> 0 ดังนั้น จะปลอดภัยกว่า inf / 1+ inf ครับ อันนี้พังแน่นอน
สรุป ทำไม ทำ custom function เองแล้วไม่รอด
- เพราะว่า สมการของ custom sigmoid function ไม่ได้ถูกลดรูป เป็นการคำนวนตรงๆ ครับ ทำให้เกิดปัญหาของ inf/inf ทำให้เกิด nan ตามมา
- เหตุที่ sigmoid ของ Tensorflow ทำการลดรูปมาแล้ว ซึ่งจะได้เป็น 1/inf เลวร้ายสุดก็ เป็น 0 ทำให้ปลอดภัยมากกว่า
- ดังนั้นหากจะทำ custom function หรือ loss function เอง ให้ดิฟและลดรูปให้เรียบร้อยก่อนนะครับ…
ส่วนโค้ดเอาไว้โอกาสหน้าครับผม