Sınırlayıcı Kutu Regresyonu - Başarısızlıkta Bir Macera

Jan 20 2021

Sinir ağlarıyla ilgili birçok sorunu çözdüm, ancak nadiren görüntülerle çalıştım. Bir sınırlayıcı kutu regresyon ağı oluşturmak için yaklaşık 18 saatim var ve tamamen başarısız olmaya devam ediyor. Bazı kayıp işlevleriyle, eğitim ve doğrulama sırasında% 80 doğruluk iddia eder (her ikisinde de gerçekten büyük bir kayıp olur) ancak tahminleri test etmek, herhangi bir yönde yalnızca bir veya iki pikseli hareket ettiren ve verileri tamamen görmezden gelen bir sınırlayıcı kutu ortaya çıkarır. Şimdi bir çeşit IoU kaybı uyguladım, ancak IoU'nun sıfıra sabitlendiğini gördüm ... Bu, eğitimden sonraki çıktılara dayalı olarak açıkça doğrudur. :). Birinin bunu gözden geçirmesini ve bir sonraki adımda nasıl ilerleyeceğime dair bana tavsiyelerde bulunmasını istiyorum.

Neyim var

Her birine rastgele yerleştirilmiş tek bir harfle 200x100x3 resimden 40000 örnek oluşturuyorum. Eşzamanlı olarak, her eğitim örneği için kesin referans sınırlayıcı kutuları oluşturuyorum. Tüm bunların işe yaradığını ve verilerin doğru olduğunu tamamen onayladım.

Ne Yaparım

Ardından, 200x100x1 boyutunda bir görüntü oluşturmak için 200x100x3 görüntüleri gri tonlamaya dönüştürüyorum. Görüntüler daha sonra normalleştirilir ve sınırlayıcı kutular 0 ile 1 arasında olacak şekilde ölçeklenir. Basitleştirilmiş biçimde bu gerçekleşir:

x_train_normalized = (x_data - 127.5) / 127.5
y_train_scaled = boxes[:TRAIN]/[WIDTH,HEIGHT,WIDTH,HEIGHT]

Bu verileri dikkatle inceledim, hatta onlardan görüntüleri ve sınırlayıcı kutuları yeniden oluşturdum. Bu kesinlikle işe yarıyor.

Eğitim

Denedikten sonra mseve hepsi eşit derecede başarısız olan diğerlerini eğitmek için, basit bir özel IOU kaybı işlevi uyguladım. Aslında geri dönüyor -ln(IoU). Bu değişikliği bir kağıda dayanarak yaptım çünkü kayıp (garip bir şekilde?) Birden çok çağda sıfıra sabitlendi.

(Kayıp fonksiyonu :)

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

Bu, birçok yinelemeden geçti. Dediğim gibi, NN'lerle ilgili diğer birçok sorunu çözdüm ... Bu, beni tamamen sıkışıp bırakan ilk sorun. Bu noktada, ağ dramatik bir şekilde sıyrıldı, ancak hiç eğitilmeye devam ediyor:

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)

Tüm işaretçiler açığız! Bu arada, bunun yardımcı olup olmadığını görmek için bir merkez nokta kaybı işlevi uyguluyorum.

Yanıtlar

DavidHoelzer Jan 21 2021 at 07:35

Sonunda, bu problemin büyük ölçüde yerel minimuma düşen gradyan iniş meselesi olduğu ortaya çıktı.

Gelecek nesiller için okuyanlar için, ML'de çözülmesi zor olan konulardan biri, ağırlıklar, önyargılar ve çekirdekler için (CNN'de) sezgisel olarak makul başlangıç ​​değerleri seçemememizdir. Sonuç olarak, genellikle rastgele başlatmalarına izin veririz. Bu bazı zorluklar ortaya çıkarabilir.

En büyük zorluklardan biri, rastgele bir başlangıç ​​noktasından başladığınızda, birisine deneylerinizi nasıl tamamen kopyalayacağını söylemenin zor olmasıdır. Bu, eğitimli modelinizden kaydedilmiş parametreleri onlara sağlayabileceğiniz için sonunda çok önemli değildir. Ancak, bu aynı zamanda "kötü" görünen ve aslında tamamen iyi olan ağlara da yol açabilir.

Bu durumda, CNN'yi tek tip bir başlatıcı ile başlatmak için zamanın çoğunu harcadım (yukarıdaki kodda mevcut değil). Genetik arama araçlarıyla ağları daha iyi iyileştirebilmem için bazen başlangıç ​​değerlerini oluşturmak için rastgele bir tohum veya başka bir işlev kullanacağım.

Görünüşe göre tek tip başlatıcılar, çeşitli ağ yinelemeleri ve bu özel verilerle birleştirilmiş, kesinlikle berbat eğitim performansına ve yakınsamamaya yol açıyor.

Ağı yukarıdaki gibi rastgele başlatmalarla ve bir veya iki ince ayar ile çalıştırdığımda, iyi bir şekilde birleşti. Bazı eğitim yinelemeleri sınırlayıcı kutunun kenarlarından birini kenarda sabitleyecektir, bazıları asla birleşmeyecektir, ancak test setimdeki sınırlayıcı kutular için% 96-98 doğruluk aralığında olan birkaçını başarıyla eğitmeyi başardım. 20000, yani her şey yolunda!