बाउंडिंग बॉक्स रिग्रेशन - विफलता में एक साहसिक
मैंने तंत्रिका नेटवर्क के साथ कई समस्याओं को हल किया है, लेकिन शायद ही कभी छवियों के साथ काम करता है। एक बाउंडिंग बॉक्स रिग्रेशन नेटवर्क बनाने में मेरे पास लगभग 18 घंटे हैं और यह पूरी तरह से विफल है। कुछ नुकसान कार्यों के साथ यह प्रशिक्षण और सत्यापन के दौरान 80% सटीकता का दावा करेगा (दोनों पर वास्तव में बड़े पैमाने पर नुकसान के साथ) लेकिन भविष्यवाणियों का परीक्षण करने से एक बाउंडिंग बॉक्स का पता चलता है जो किसी भी दिशा में केवल एक या दो पिक्सेल ले जाता है और डेटा को पूरी तरह से अनदेखा करता है। मैंने अब IoU नुकसान का एक रूप लागू किया है, लेकिन यह पता लगाएं कि IoU शून्य पर पिन किया गया है ... जो स्पष्ट रूप से प्रशिक्षण के बाद आउटपुट पर आधारित है। :)। मैं चाहूंगा कि कोई इसे देख ले और मुझे आगे बढ़ने के बारे में कुछ सलाह दे।
जो मेरे पास है
मैं 200x100x3 छवियों के 40000 उदाहरण उत्पन्न कर रहा हूं जिसमें एक अक्षर को यादृच्छिक रूप से प्रत्येक में रखा गया है। इसके साथ ही मैं प्रत्येक प्रशिक्षण नमूने के लिए जमीनी सच्चाई के बाउंडिंग बॉक्स बना रहा हूं। मैंने पूरी तरह से पुष्टि की है कि यह सब काम करता है और डेटा सही है।
मैं इसे करने के लिए क्या करते हैं
फिर मैं 200x100x1 छवि बनाने के लिए 200x100x3 छवियों को greyscale में परिवर्तित कर रहा हूं। छवियों को फिर से सामान्य किया जाता है और बाउंडिंग बॉक्स को 0 और 1 के बीच गिरने के लिए स्केल किया जाता है। सरलीकृत रूप में, ऐसा होता है:
x_train_normalized = (x_data - 127.5) / 127.5
y_train_scaled = boxes[:TRAIN]/[WIDTH,HEIGHT,WIDTH,HEIGHT]
मैं ध्यान से इस डेटा के माध्यम से किया गया है, यहां तक कि छवियों का पुनर्गठन और इसमें से बक्से को बांधना। यह निश्चित रूप से काम कर रहा है।
प्रशिक्षण
प्रशिक्षण के लिए, कोशिश करने के बाद mse
और कई अन्य, जिनमें से सभी समान रूप से बुरी तरह से विफल हो जाते हैं, मैंने एक सरल कस्टम IOU नुकसान फ़ंक्शन को लागू किया है। यह वास्तव में लौटता है -ln(IoU)
। मैंने यह परिवर्तन एक कागज़ के आधार पर किया था क्योंकि नुकसान (विषम रूप से?) को कई युगों में शून्य पर पिन किया गया था।
(लॉस फंकशन:)
import tensorflow.keras.backend as kb
def iou_loss(y_actual,y_pred):
b1 = y_actual
b2 = y_pred
# tf.print(b1)
# tf.print(b2)
zero = tf.convert_to_tensor(0.0, b1.dtype)
b1_ymin, b1_xmin, b1_ymax, b1_xmax = tf.unstack(b1, 4, axis=-1)
b2_ymin, b2_xmin, b2_ymax, b2_xmax = tf.unstack(b2, 4, axis=-1)
b1_width = tf.maximum(zero, b1_xmax - b1_xmin)
b1_height = tf.maximum(zero, b1_ymax - b1_ymin)
b2_width = tf.maximum(zero, b2_xmax - b2_xmin)
b2_height = tf.maximum(zero, b2_ymax - b2_ymin)
b1_area = b1_width * b1_height
b2_area = b2_width * b2_height
intersect_ymin = tf.maximum(b1_ymin, b2_ymin)
intersect_xmin = tf.maximum(b1_xmin, b2_xmin)
intersect_ymax = tf.minimum(b1_ymax, b2_ymax)
intersect_xmax = tf.minimum(b1_xmax, b2_xmax)
intersect_width = tf.maximum(zero, intersect_xmax - intersect_xmin)
intersect_height = tf.maximum(zero, intersect_ymax - intersect_ymin)
intersect_area = intersect_width * intersect_height
union_area = b1_area + b2_area - intersect_area
iou = -1 * tf.math.log(tf.math.divide_no_nan(intersect_area, union_area))
return iou
संजाल
यह कई, कई पुनरावृत्तियों के माध्यम से किया गया है। जैसा कि मैंने कहा, मैंने एनएन के साथ कई अन्य समस्याओं को हल किया है ... यह मुझे पूरी तरह से अटकाने वाला पहला है। इस बिंदु पर, नेटवर्क नाटकीय रूप से नीचे छीन लिया गया है, लेकिन सभी को प्रशिक्षित करने में विफल रहता है:
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, optimizers
tf.keras.backend.set_floatx('float32') # Use Float32s for everything
input_shape = x_train_normalized.shape[-3:]
model = keras.Sequential()
model.add(layers.Conv2D(4, 16, activation = tf.keras.layers.LeakyReLU(alpha=0.2), input_shape=input_shape))
model.add(layers.MaxPooling2D(pool_size=(3, 3), strides=(2, 2)))
model.add(layers.Dropout(0.2))
model.add(layers.Flatten())
model.add(layers.Dense(200, activation = tf.keras.layers.LeakyReLU(alpha=0.2)))
model.add(layers.Dense(64, activation=tf.keras.layers.LeakyReLU(alpha=0.2)))
model.add(layers.Dense(4, activation="sigmoid"))
model.compile(loss = iou_loss, optimizer = "adadelta", metrics=['accuracy'])
history = model.fit(x_train_normalized, y_train_scaled, epochs=8, batch_size=100, validation_split=0.4)
सभी संकेत स्वागत है! इस बीच मैं यह देखने के लिए एक केंद्र बिंदु हानि फ़ंक्शन लागू कर रहा हूं कि क्या यह बिल्कुल मदद करता है।
जवाब
अंत में, यह समस्या काफी हद तक स्थानीय मिनिमा में धीरे-धीरे गिरते वंश का मामला बन गई।
पश्चाताप के लिए पढ़ने वालों के लिए, एमएल में मुद्दों में से एक जो चारों ओर काम करना मुश्किल है, वह यह है कि हम सहजता से वजन, पूर्वाग्रह और गुठली (सीएनएन में) के लिए उचित प्रारंभिक मूल्यों का चयन नहीं कर सकते हैं। परिणामस्वरूप, हम आम तौर पर उन्हें यादृच्छिक रूप से आरंभ करने की अनुमति देते हैं। यह कुछ चुनौतियां पेश कर सकता है।
सबसे बड़ी चुनौतियों में से एक यह है कि जब आप एक यादृच्छिक प्रारंभिक बिंदु से शुरू करते हैं, तो किसी को यह बताना मुश्किल होता है कि अपने प्रयोगों को पूरी तरह से कैसे दोहराया जाए। यह अंत में बहुत महत्वपूर्ण नहीं है क्योंकि आप उन्हें अपने प्रशिक्षित मॉडल से बचाए गए मापदंडों के साथ प्रदान कर सकते हैं। हालांकि, यह उन नेटवर्क को भी जन्म दे सकता है जो "खराब" प्रतीत होते हैं जो वास्तव में पूरी तरह से ठीक हैं।
इस मामले में, मैंने सीएनएन को एक समान इनिशलाइज़र के साथ आरंभ करने में बहुत समय बिताया था (ऊपर कोड में मौजूद नहीं)। मैं कभी-कभी प्रारंभिक मूल्यों को उत्पन्न करने के लिए एक यादृच्छिक बीज या कुछ अन्य फ़ंक्शन का उपयोग करूंगा ताकि मैं आनुवंशिक खोज टूल के माध्यम से नेटवर्क में बेहतर सुधार कर सकूं।
ऐसा लगता है कि विभिन्न नेटवर्क पुनरावृत्तियों और इस विशेष डेटा के साथ एकरूप आरंभीकरण संयुक्त रूप से पूरी तरह से घृणित प्रशिक्षण प्रदर्शन और गैर-अभिसरण की ओर ले जाता है।
जब मैंने रैंडम इनिशियलाइज़ेशन और एक या दो ट्वीक्स के साथ नेटवर्क को ऊपर की ओर चलाया, तो यह अच्छी तरह से परिवर्तित हो गया। कुछ प्रशिक्षण पुनरावृत्तियों ने किनारे पर बाउंडिंग बॉक्स के दोनों किनारों में से एक को पिन किया, कुछ कभी भी अभिसरण नहीं करेंगे, लेकिन मैंने कई सफल प्रशिक्षण लिए हैं जो 96-98% सटीकता रेंज में मेरे टेस्ट सेट में बाउंडिंग बॉक्स के लिए हैं। 20000, तो सब ठीक है!