[PYTHON] Versuchen Sie die zufällige Löschung von Daten

Was ist die zufällige Löschung von Daten?

Beim maschinellen Lernen wird häufig eine Datenerweiterung verwendet, die ein Überlernen durch Verarbeitung von Eingabedaten verhindert. In letzter Zeit wurde jedoch ein neues Datenerweiterungsverfahren auf dem Gebiet der Bilderkennung vorgeschlagen.

Beides sind Methoden zum Maskieren eines zufälligen rechteckigen Teilbereichs des Bildes, bei dem es sich um die Lehrerdaten handelt. Der Unterschied besteht darin, dass durch zufälliges Löschen die Größe und das Seitenverhältnis des Rechtecks zufällig ausgewählt werden, während der Ausschnitt eine feste Größe hat. (Cutout experimentiert jedoch auch mit einer Methode zum selektiven Maskieren eines Teils des Zielobjekts. Eine Maske mit fester Größe ist genauso effektiv. Wenn Sie also der Einfachheit halber eine Maske mit fester Größe verwenden Anspruch) Neben der Bildklassifizierung hat Random Erasing auch die Wirksamkeit bei der Objekterkennung und beim Personenabgleich bestätigt.

Bild des zufälligen Löschens

(Das hier verwendete Bild unterscheidet sich von den diesmal verwendeten Daten.)

Vor der Bildverarbeitung Nach der Bildverarbeitung
remove_aug1.jpg remove_aug2.jpg

Versuchen Sie die zufällige Löschung von Daten

Ich beschloss, Random Erasing auszuprobieren. Ich habe dies anstelle von Ausschnitt gewählt, weil es effektiver zu sein scheint, die Rechteckgröße zufällig zu machen.

Die durchgeführte Aufgabe ist die Klassifizierung des CIFAR-10-Datensatzes. Implementiert mit Chainer. Der Quellcode ist unten.

Nach dem Klonen des Quellcodes können Sie mit dem folgenden Befehl trainieren (wenn Sie die letzte Option "-p" beibehalten, werden die gespeicherten Daten überschrieben, daher wird empfohlen, sie bei jedem Training zu ändern).

$ python src/download.py
$ python src/dataset.py
$ python src/train.py -g 0 -m vgg_no_fc -p remove_aug --iter 300 -b 128 --lr 0.1 --lr_decay_iter 150,225

Implementierung des zufälligen Löschens

Hyperparameter

Die Hyperparameter im Zusammenhang mit dem zufälligen Löschen sind wie folgt.

Dieses Mal habe ich einen Wert in der Nähe des Papiers ausgewählt und wie folgt eingestellt.

Hyperparameter Wert
p 0.5
s_l 0.02
s_h 0.4
r_1 1/3
r_2 3

Implementierung

Der tatsächlich verwendete Code lautet wie folgt. Es wird als Methode der geerbten Klasse "chainer.datasets.TupleDataset" implementiert. Die Teile von "# Löschstart entfernen" bis "# Löschende entfernen" sind die Prozesse, die sich auf Löschen entfernen beziehen, und der zufällige rechteckige Bereich wird mit zufälligen Werten gefüllt. (Ich denke, es ist besser, den zu füllenden Wertebereich an den zu verwendenden Datenbereich anzupassen.) x von _transform ist ein Array von Eingabedaten und hat die Größe [Stapelgröße, Anzahl der Kanäle, Höhe, Breite].

    def _transform(self, x):
        image = np.zeros_like(x)
        size = x.shape[2]
        offset = np.random.randint(-4, 5, size=(2,))
        mirror = np.random.randint(2)
        remove = np.random.randint(2)
        top, left = offset
        left = max(0, left)
        top = max(0, top)
        right = min(size, left + size)
        bottom = min(size, top + size)
        if mirror > 0:
            x = x[:,:,::-1]
        image[:,size-bottom:size-top,size-right:size-left] = x[:,top:bottom,left:right]
        # Remove erasing start
        if remove > 0:
            while True:
                s = np.random.uniform(0.02, 0.4) * size * size
                r = np.random.uniform(-np.log(3.0), np.log(3.0))
                r = np.exp(r)
                w = int(np.sqrt(s / r))
                h = int(np.sqrt(s * r))
                left = np.random.randint(0, size)
                top = np.random.randint(0, size)
                if left + w < size and top + h < size:
                    break
            c = np.random.randint(-128, 128)
            image[:, top:top + h, left:left + w] = c
        # Remove erasing end
        return image

Neuronale Netzwerkstruktur

Der Netzwerkcode wird unten angezeigt. Es kombiniert Convolutional und Max Pooling wie VGG. Eine vollständig verbundene Ebene wird jedoch nicht bereitgestellt, und die Anzahl der Parameter wird reduziert, indem stattdessen ein globales Pooling durchgeführt wird.


class BatchConv2D(chainer.Chain):
    def __init__(self, ch_in, ch_out, ksize, stride=1, pad=0, activation=F.relu):
        super(BatchConv2D, self).__init__(
            conv=L.Convolution2D(ch_in, ch_out, ksize, stride, pad),
            bn=L.BatchNormalization(ch_out),
        )
        self.activation=activation

    def __call__(self, x):
        h = self.bn(self.conv(x))
        if self.activation is None:
            return h
        return self.activation(h)

class VGGNoFC(chainer.Chain):
    def __init__(self):
        super(VGGNoFC, self).__init__(
            bconv1_1=BatchConv2D(3, 64, 3, stride=1, pad=1),
            bconv1_2=BatchConv2D(64, 64, 3, stride=1, pad=1),
            bconv2_1=BatchConv2D(64, 128, 3, stride=1, pad=1),
            bconv2_2=BatchConv2D(128, 128, 3, stride=1, pad=1),
            bconv3_1=BatchConv2D(128, 256, 3, stride=1, pad=1),
            bconv3_2=BatchConv2D(256, 256, 3, stride=1, pad=1),
            bconv3_3=BatchConv2D(256, 256, 3, stride=1, pad=1),
            bconv3_4=BatchConv2D(256, 256, 3, stride=1, pad=1),
            fc=L.Linear(256, 10),
        )

    def __call__(self, x):
        h = self.bconv1_1(x)
        h = self.bconv1_2(h)
        h = F.dropout(F.max_pooling_2d(h, 2), 0.25)
        h = self.bconv2_1(h)
        h = self.bconv2_2(h)
        h = F.dropout(F.max_pooling_2d(h, 2), 0.25)
        h = self.bconv3_1(h)
        h = self.bconv3_2(h)
        h = self.bconv3_3(h)
        h = self.bconv3_4(h)
        h = F.dropout(F.max_pooling_2d(h, 2), 0.25)
        h = F.average_pooling_2d(h, 4, 1, 0)
        h = self.fc(F.dropout(h))
        return h

Lernbedingungen

Die Lernbedingungen sind wie folgt.

Ergebnis

Die Genauigkeit wurde durch Verwendung der zufälligen Löschung wie folgt verbessert.

Methode Test Error
Zufälliges Löschen wird nicht verwendet 6.68
Verwenden Sie das zufällige Löschen 5.67

Der Übergang von Trainingsfehler und Testfehler ist wie folgt. Bei Verwendung der zufälligen Löschung ist der Unterschied zwischen Trainingsfehler und Testfehler geringer, und es scheint, dass Überlernen unterdrückt wird.

Zufälliges Löschen nicht verwendet: vgg_no_fc_error.png

Zufälliges Löschen verwendet: vgg_no_fc_remove_aug_error.png

abschließend

Es war eine einfache Methode, das Eingabebild zu maskieren, sodass ich es sofort ausprobieren konnte. Diesmal war es effektiv, aber ich denke, es ist notwendig zu überprüfen, ob es unter verschiedenen Bedingungen eine wirksame Methode ist. Wenn es effektiv ist, kann es in Zukunft zum Standard werden.

Es ist eine so einfache Methode, dass ich mich persönlich frage, ob sie in der Vergangenheit vorgeschlagen wurde.

Verweise

Recommended Posts

Versuchen Sie die zufällige Löschung von Daten
Datenerweiterung mit openCV
Versuchen Sie, IPv6 nach dem Zufallsprinzip zu deaktivieren
Versuchen Sie "100 Schläge auf Data Science" ①
[PyTorch] Datenerweiterung zur Segmentierung
Neue Datenerweiterung? [Grid Mix]
Versuchen Sie, Daten in MongoDB abzulegen
Aufblasen von Daten (Datenerweiterung) mit PyTorch
[Maschinelles Lernen] Versuchen Sie, zufällige Wälder zu studieren
Versuchen Sie Daten parallel zu Distributed TensorFlow