Cross-Sampling oder wie man ein paar Tausendstel aus dem Datensatz herausdrückt

Dieser Artikel handelt von Bildern und Klassifizierung. Eine kleine Untersuchung der Eigenschaften, wie die Berührung des Porträts von MNIST (ein Hinweis zur Lösung anderer ähnlicher Probleme).



Es gibt viele Veröffentlichungen im Netzwerk über die Interpretation eines bestimmten neuronalen Netzwerks und die Bedeutung und den Beitrag bestimmter Punkte zum Lernen. Es gibt viele Arbeiten über die Suche nach Whiskern, Schwänzen und anderen Teilen und deren Bedeutung und Bedeutung. Jetzt werde ich keine Bibliothekare ersetzen und eine Liste erstellen. Ich werde nur über mein Experiment sprechen.



Alles begann mit einem ausgezeichneten Video- Bericht „Wie Roboter denken. Interpretation von ML-Modellen “ , die auf Anraten einer klugen Person überprüft wurde und wie jedes vernünftige Unternehmen viele Fragen aufwirft. Zum Beispiel: - Wie eindeutig sind die wichtigsten Punkte des Datensatzes?



Oder eine andere Frage: - Es gibt viele Artikel im Netzwerk darüber, wie das Ändern eines Bildpunkts die Netzwerkvorhersage erheblich verzerren kann. Ich möchte Sie daran erinnern, dass wir in diesem Artikel nur Klassifizierungsprobleme betrachten werden. Wie einzigartig ist dieser heimtückische Punkt? Gibt es solche Punkte in der natürlichen Sequenz von MNIST und wenn sie gefunden und weggeworfen werden, ist die Trainingsgenauigkeit des neuronalen Netzwerks höher?



Der Autor folgte seiner traditionellen Methode, alles Unnötige loszuwerden, und entschied sich, sich nicht in die Gruppe einzumischen, und entschied sich für eine einfache, zuverlässige und effektive Methode, um die gestellten Fragen zu untersuchen:



Wählen Sie als experimentelles Problem, als Beispiel für die Vorbereitung, den bekannten MNIST ( yann.lecun.com/exdb/mnist) ) und seine Klassifizierung.



Als experimentelles Netzwerk wählte ich den für Anfänger empfohlenen Klassiker, ein beispielhaftes Netzwerk des KERAS-Teams

github.com/keras-team/keras/blob/master/examples/mnist_cnn.py.



Und ich beschloss, die Forschung selbst sehr einfach durchzuführen.



Lassen Sie uns das Netzwerk von KERAS mit einem solchen Stoppkriterium wie dem Fehlen einer Erhöhung der Genauigkeit in der Testsequenz trainieren, d. H. Lehren Sie das Netzwerk, bis test_accuracy signifikant größer als validation_accuracy wird und validation_accuracy sich in 15 Epochen nicht verbessert. Mit anderen Worten, das Netzwerk hörte auf zu lernen und die Umschulung begann.



Aus dem MNIST-Datensatz werden 324 neue Datensätze erstellt, indem Punktgruppen verworfen werden, und von demselben Netzwerk unter genau denselben Bedingungen mit denselben Anfangsgewichten unterrichtet.



Fangen wir an, ich denke, es ist richtig und richtig, den gesamten Code von der ersten bis zur letzten Zeile zu gestalten. Auch wenn die Leser ihn offensichtlich schon oft gesehen haben.



Wir laden die Bibliotheken und das Mnist-Dataset, falls es noch nicht geladen wurde.



Dann konvertieren wir es in das 'float32'-Format und normalisieren es auf den Bereich 0. - 1.



Die Vorbereitung ist beendet.



'''Trains a simple convnet on the MNIST dataset.
Gets to 99.25% test accuracy after 12 epochs
(there is still a lot of margin for parameter tuning).
16 seconds per epoch on a GRID K520 GPU.
'''

from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential, load_model
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K
from keras.optimizers import *
from keras.callbacks import EarlyStopping

import numpy as np
import os

num_classes = 10

# input image dimensions
img_rows, img_cols = 28, 28

# the data, shuffled and split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()

if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= np.max(x_train)
x_test /= np.max(x_test)

XX_test = np.copy(x_test)
XX_train = np.copy(x_train)
YY_test = np.copy(y_test)
YY_train = np.copy(y_train)


print('x_train shape:', XX_train.shape)
print('x_test shape:', XX_test.shape)




Erinnern wir uns in den Variablen an den Namen der Modelldateien und Gewichte sowie an die Genauigkeit und den Verlust unseres Netzwerks. Dies ist nicht im Quellcode enthalten, aber für das Experiment erforderlich.



f_model = "./data/mnist_cnn_model.h5"
f_weights = "./data/mnist_cnn_weights.h5"
accu_f = 'accuracy'
loss_f = 'binary_crossentropy'


Das Netzwerk selbst ist genau das gleiche wie auf

github.com/keras-team/keras/blob/master/examples/mnist_cnn.py .



Speichern Sie das Netzwerk und skalieren Sie es auf die Festplatte. Wir werden alle unsere Trainingsversuche mit den gleichen Anfangsgewichten durchführen:



y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

model = Sequential()

model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss=[loss_f], optimizer=Adam(lr=1e-4), metrics=[accu_f])
model.summary()

model.save_weights(f_weights)
model.save(f_model)


Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 26, 26, 32)        320       
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 24, 24, 64)        18496     
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 12, 12, 64)        0         
_________________________________________________________________
dropout (Dropout)            (None, 12, 12, 64)        0         
_________________________________________________________________
flatten (Flatten)            (None, 9216)              0         
_________________________________________________________________
dense (Dense)                (None, 128)               1179776   
_________________________________________________________________
dropout_1 (Dropout)          (None, 128)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 10)                1290      
=================================================================
Total params: 1,199,882
Trainable params: 1,199,882
Non-trainable params: 0
_________________________________________________________________


Beginnen wir mit dem Training auf dem ursprünglichen Mnist, um einen Maßstab für die grundlegende Effizienz zu erhalten.



x_test = np.copy(XX_test)
x_train = np.copy(XX_train)
s0 = 0

if os.path.isfile(f_model):
    model = load_model(f_model)
    model.load_weights(f_weights, by_name=False)

    step = 0
    while True:
        
        fit = model.fit(x_train, y_train,
                  batch_size=batch_size,
                  epochs=1,
                  verbose=0,
                  validation_data=(x_test, y_test)
                )
        
        current_accu = fit.history[accu_f][0]
        current_loss = fit.history['loss'][0]
        val_accu = fit.history['val_'+accu_f][0]
        val_loss = fit.history['val_loss'][0]
        print("\x1b[2K","accuracy {0:12.10f} loss {1:12.10f} step {2:5d} val_accu {3:12.10f} val_loss {4:12.10f}  ".\
                          format(current_accu, current_loss, step, val_accu, val_loss), end="\r")
    
        step += 1
        if val_accu > max_accu:
            s0 = 0
            max_accu = val_accu
        else:
            s0 += 1
        if current_accu * 0.995 > val_accu and s0 > 15:
            break
else:
    print("model not found ")

accuracy 0.9967333078 loss 0.0019656278 step   405 val_accu 0.9916999936 val_loss 0.0054226643  


Beginnen wir nun mit dem Hauptexperiment. Wir nehmen alle 60.000 markierten Bilder aus der ursprünglichen Sequenz zum Training und setzen in ihnen alles außer dem 9x9-Quadrat auf Null. Lassen Sie uns 324 experimentelle Sequenzen erhalten und das Ergebnis des Trainings des Netzwerks mit dem Training der ursprünglichen Sequenz vergleichen. Wir trainieren das gleiche Netzwerk mit den gleichen Anfangsgewichten.



batch_size = 5000
s0 = 0
max_accu = 0.

for i in range(28 - 9):
    for j in range(28 - 9):
        print("\ni= ", i, "  j= ",j)
        x_test = np.copy(XX_test)
        x_train = np.copy(XX_train)

        x_train[:,:i,:j,:] = 0.
        x_test [:,:i,:j,:] = 0.

        x_train[:,i+9:,j+9:,:] = 0.
        x_test [:,i+9:,j+9:,:] = 0.

        if os.path.isfile(f_model):
            model = load_model(f_model)
            model.load_weights(f_weights, by_name=False)
        else:
            print("model not found ")
            break

        step = 0
        while True:
            
            fit = model.fit(x_train, y_train,
                      batch_size=batch_size,
                      epochs=1,
                      verbose=0,
                      validation_data=(x_test, y_test)
                    )
            
            current_accu = fit.history[accu_f][0]
            current_loss = fit.history['loss'][0]
            val_accu = fit.history['val_'+accu_f][0]
            val_loss = fit.history['val_loss'][0]
            print("\x1b[2K","accuracy {0:12.10f} loss {1:12.10f} step {2:5d} val_accu {3:12.10f} val_loss {4:12.10f}  ".\
   format(current_accu, current_loss, step, val_accu, val_loss), end="\r")
        
            step += 1
            if val_accu > max_accu:
                s0 = 0
                max_accu = val_accu
            else:
                s0 += 1
            if current_accu * 0.995 > val_accu and s0 > 15:
                break


Es macht keinen Sinn, alle 324 Ergebnisse hier zu posten. Wenn jemand interessiert ist, kann ich es persönlich senden. Die Berechnung dauert mehrere Tage, wenn jemand sie wiederholen möchte.



Wie sich herausstellte, kann das Netzwerk bei einem 9x9-Ausschnitt schlechter lernen, was offensichtlich ist, aber auch besser, was überhaupt nicht offensichtlich ist.



Zum Beispiel:



i = 0 j = 14

Genauigkeit 0,9972333312 Verlust 0,0017946947 Schritt 450 val_accu 0,9922000170 val_loss 0,0054322388



i = 18, j = 1

Genauigkeit 0,9973166585 Verlust 0,0019487827 Schritt 415 val_accu 0,9922000170 val_loss 0,0053000450



Wir werfen Bilder mit handgeschriebenen Zahlen und 9 Anerkennung verbessert sich bei uns!



Es ist auch klar, dass es mehr als einen solchen speziellen Bereich zur Verbesserung der Netzwerkqualität gibt. Und nicht zwei, diese beiden werden als Beispiel gegeben.



Das Ergebnis dieses Experiments und vorläufige Schlussfolgerungen.



  • Jeder natürliche Datensatz, von dem ich nicht glaube, dass LeCune absichtlich etwas verzerrt hat, enthält nicht nur Punkte, die für das Lernen wesentlich sind, sondern auch Punkte, die das Lernen beeinträchtigen. Die Aufgabe, "schädliche" Punkte zu finden, wird dringend, sie existieren, auch wenn sie nicht sichtbar sind.
  • Sie können nicht nur entlang des Datasets stapeln und mischen, Bilder in Gruppen auswählen, sondern auch quer, Bilderbereiche zum Teilen auswählen und dann wie gewohnt. In diesem Fall verbessert dieser Ansatz die Qualität des Trainings, und es besteht die Hoffnung, dass bei einer ähnlichen Aufgabe die Verwendung eines solchen Stapelns die Qualität erhöht. Und auf derselben kaggle.com können Sie mit einigen Zehntausendstel manchmal (fast immer) Ihre Autorität und Bewertung deutlich erhöhen.


Vielen Dank für Ihre Aufmerksamkeit.



All Articles