[PYTHON] Mit ein wenig Präzision wurden die Gewichtsparameter unglaublich reduziert ~ Überraschende Ergebnisse von CNN ~

1. Zuallererst

Wenn es um die Bildidentifikation neuronaler Netze geht, konzentrieren wir uns normalerweise darauf, wie viel Genauigkeit verbessert werden kann, aber da ich ein Teufel bin, werde ich mich darauf konzentrieren, ** wie viel der Gewichtsparameter reduziert werden kann, wenn die Genauigkeit leicht verringert wird **. ..

Ich denke, dass die meisten Ressourcen häufig für neuronale Netze verwendet werden, um die endgültigen 1-2% der Genauigkeit zu erhöhen. Selbst wenn Sie etwa 1-2% der Genauigkeit opfern, sollten Sie in der Lage sein, den Gewichtsparameter erheblich zu reduzieren.

Das in diesem Experiment verwendete Modell verwendet ** MLP (Multilayer Perceptron) ** und ** CNN (Faltungsnetzwerk) **, die MNIST (handschriftliche Zahlen von 0 bis 9) identifizieren, die im Keras-Tutorial beschrieben sind. Da die Genauigkeit dieser beiden Modelle zwischen 98 und 99% liegt, setzen wir die ** Zielgenauigkeit auf 97% ** und versuchen, wie stark der Gewichtsparameter reduziert werden kann.

2.MLP (Multilayer Perceptron)

Hier ist die Grundstruktur von MLP im Keras-Tutorial (eigentlich habe ich zwei Dropouts hinzugefügt, diese aber der Einfachheit halber weggelassen). スクリーンショット 2020-01-22 11.08.38.png Da MNIST 28 * 28 Pixel beträgt, gibt es 28 * 28 = 784 Eingänge. Es gibt zwei versteckte Schichten, die beide vollständig mit n = 512 verbunden sind.

Lassen Sie uns zunächst überprüfen, was mit der Genauigkeit passiert, wenn dieses n allmählich verringert wird. Führen Sie den folgenden Code aus (die Ausführungszeit auf der GPU von Google Colab beträgt ungefähr dreieinhalb Minuten).

from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop

batch_size = 128
num_classes = 10
epochs = 20

# load data
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(60000, 784)
x_test = x_test.reshape(10000, 784)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

# multi Perceptoron_1
def mlp(n):
    model = Sequential()
    model.add(Dense(n, activation='relu', input_shape=(784,)))
    model.add(Dense(n, activation='relu'))
    model.add(Dense(num_classes, activation='softmax'))

    #model.summary()

    model.compile(loss='categorical_crossentropy',
                   optimizer=RMSprop(),
                  metrics=['accuracy'])

    model.fit(x_train, y_train,
              batch_size=batch_size,
              epochs=epochs,
              verbose=0, 
              validation_data=(x_test, y_test))
    
    score = model.evaluate(x_test, y_test, verbose=0)
    return score[1]

# test
list_n = [512, 256, 128, 64, 32, 16]  
x, y = [], []
for n in list_n:
    params = n*n + 796*n + 10
    acc = mlp(n)
    x.append(params)
    y.append(acc)
    print ('n = ', n, ', ', 'params = ', params, ', ', 'accuracy = ', acc)

# graph
import matplotlib.pyplot as plt
plt.scatter(x, y)
plt.xscale('log')
plt.show()

スクリーンショット 2020-01-22 11.05.33.png Die horizontale Achse des Diagramms ist die Anzahl der Gewichtsparameter (log) und die vertikale Achse ist die Genauigkeit. Ist n = 32, params = 26506, Genauigkeit = 0,9711 der Wendepunkt, wenn versucht wird, eine Genauigkeit von 97% sicherzustellen?

Dann ist auf Kosten einer gewissen Genauigkeit 669706/26506 = 25,26, sodass wir die Gewichtsparameter auf etwa 1/25 des Basismodells reduzieren können.

Wenn Sie den Umriss des Modells mit model.summary () betrachten (es wird angezeigt, indem Sie das führende # nehmen und ausführen), sieht es so aus スクリーンショット 2020-01-22 11.39.14.png Ist es unmöglich, den Gewichtsparameter weiter zu reduzieren? Nein, ich habe noch einen Zug.

Wo verbraucht der Gewichtsparameter am meisten? Bei 784 Eingaben und ** dicht_1 ** werden hier (784 + 1) * 32 = 25120 und 95% der Gesamtgewichtsparameter verbraucht. Übrigens wird es 784 + 1, weil es eine Vorspannung gibt.

Wir stellten die Hypothese auf, dass wir die Zahlen, selbst wenn sie schlecht sind, bis zu einem gewissen Grad identifizieren können, und verwenden einen Filter (Max Pooling), um ein Modell zu erstellen, das einen Filter (Max Pooling) verwendet, um 1/4 von 14 * 14 = 196 zu erhalten. Überlegen. スクリーンショット 2020-01-22 11.51.56.png Führen Sie den Code dieses Modells aus (die Ausführungszeit beträgt auf der GPU von Google Colab etwa dreieinhalb Minuten).

from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop
from keras.layers import MaxPooling2D, Flatten  #hinzufügen

batch_size = 128
num_classes = 10
epochs = 20

# load data
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(60000, 28, 28, 1)  #Veränderung
x_test = x_test.reshape(10000, 28, 28, 1)  #Veränderung
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

# multi Perceptoron_2
def mlp(n):
    model = Sequential()
    model.add(MaxPooling2D(pool_size=(2, 2),input_shape=(28, 28, 1)))  #14 Bilder*Reduziert auf 14
    model.add(Flatten())  #Machen Sie eine vollständige Bindung
    model.add(Dense(n, activation='relu')) 
    model.add(Dense(n, activation='relu'))
    model.add(Dense(num_classes, activation='softmax'))

    #model.summary()

    model.compile(loss='categorical_crossentropy',
                   optimizer=RMSprop(),
                  metrics=['accuracy'])

    model.fit(x_train, y_train,
              batch_size=batch_size,
              epochs=epochs,
              verbose=0, 
              validation_data=(x_test, y_test))
    
    score = model.evaluate(x_test, y_test, verbose=0)
    return score[1]

# test
list_n = [512, 256, 128, 64, 32, 16]  
x, y = [], []
for n in list_n:
    params = n*n + 208*n + 10  #Modellwechsel
    acc = mlp(n)
    x.append(params)
    y.append(acc)
    print ('n = ', n, ', ', 'params = ', params, ', ', 'accuracy = ', acc)

# graph
import matplotlib.pyplot as plt
plt.scatter(x, y)
plt.xscale('log')
plt.show()

スクリーンショット 2020-01-22 12.25.27.png Insgesamt rutschte ich in Richtung einer etwas weniger genauen, aber n = 64, params = 17418, Genauigkeit = 0,9704 war der Wendepunkt.

Dann wurde durch Einbußen bei der Genauigkeit festgestellt, dass der Gewichtsparameter durch 669706/17418 = 38,44 auf etwa 1/38 des Basismodells reduziert werden kann. Es kann erheblich reduziert werden.

3. Erstaunliche Ergebnisse von CNN

Hier ist die Grundstruktur des CNN im Keras-Tutorial (eigentlich habe ich zwei Dropouts hinzugefügt, diese aber der Einfachheit halber weggelassen). スクリーンショット 2020-01-22 12.33.27.png Die beiden Faltungsschichten verwenden einen 3 * 3 = 9-Filter. Danach wird es durch Max Pooling vertikal und horizontal auf 1/2 reduziert und mit der vollständig verbundenen Schicht von n * 4 verbunden.

Schauen wir uns nun die Anzahl und Genauigkeit der Gewichtungsparameter an, wenn n geändert wird. Führen Sie den folgenden Code aus (die Ausführungszeit auf der GPU von Google Colab beträgt ungefähr dreieinhalb Minuten).

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

batch_size = 128
num_classes = 10
epochs = 12
img_rows, img_cols = 28, 28

# load data
(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 /= 255
x_test /= 255
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

# CNN_1
def cnn(n):
    model = Sequential()
    model.add(Conv2D(n, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
    model.add(Conv2D(n*2, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Flatten())
    model.add(Dense(n*4, activation='relu'))
    model.add(Dense(num_classes, activation='softmax'))

    #model.summary()

    model.compile(loss=keras.losses.categorical_crossentropy,
                   optimizer=keras.optimizers.Adadelta(),
                   metrics=['accuracy'])

    model.fit(x_train, y_train,
             batch_size=batch_size,
             epochs=epochs,
             verbose=0,
             validation_data=(x_test, y_test))
    score = model.evaluate(x_test, y_test, verbose=0)
    return score[1]

# test
list_n = [32, 16, 8, 4, 2, 1] 
x, y = [], []
for n in list_n:
    params = 1170*n*n + 56*n + 10
    acc = cnn(n)
    x.append(params)
    y.append(acc)
    print ('n = ', n, ', ', 'params = ', params, ', ', 'accuracy = ', acc)

# graph
import matplotlib.pyplot as plt
plt.scatter(x, y)
plt.xscale('log')
plt.show()

スクリーンショット 2020-01-22 12.52.52.png Das ist großartig! Die Gabel ist n = 2, params = 4802, Genauigkeit = 0,9748.

Dann konnten wir durch Einbußen bei der Genauigkeit die Anzahl der Gewichtsparameter auf etwa 1/250 des Basismodells reduzieren, da 1199882/4802 = 249,8.

Übrigens, wie zuvor, wenn Sie sich den Umriss des Modells mit model.summary () ansehen, スクリーンショット 2020-01-22 13.21.50.png Im Gegensatz zu MLP weisen die Eingabe- und Faltungsteile eine kleine Anzahl von Parametern auf. Für die Parameter der Faltungsschicht werden üblicherweise 3 * 3 = 9 Filter verwendet, so dass die Gewichtsparameter reduziert werden.

Stattdessen macht (12 * 12 * 4 + 1) * 8 = 4616, das von der letzten Faltungsschicht in die vollständige Bindung eintritt, 96% des Gesamtgewichtsparameters aus. Kannst du hier nichts dagegen tun?

Die Faltschicht verbraucht fast keinen Gewichtsparameter. Daher ist das folgende Modell eine gute Idee, nach Max Pooling erneut zwei Faltschichten hinzuzufügen und dann mit Max Pooling zu multiplizieren.

スクリーンショット 2020-01-22 13.14.00.png Lassen Sie uns nun den Code dieses Modells ausführen (die Ausführungszeit auf der GPU von Google Colab beträgt ungefähr dreieinhalb Minuten).

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

batch_size = 128
num_classes = 10
epochs = 12
img_rows, img_cols = 28, 28

# load data
(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 /= 255
x_test /= 255
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

# CNN_2
def cnn(n):
    model = Sequential()
    model.add(Conv2D(n, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
    model.add(Conv2D(n, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Conv2D(n*2, (3, 3), activation='relu'))
    model.add(Conv2D(n*2, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Flatten())
    model.add(Dense(num_classes, activation='softmax'))

    #model.summary()

    model.compile(loss=keras.losses.categorical_crossentropy,
                   optimizer=keras.optimizers.Adadelta(),
                   metrics=['accuracy'])

    model.fit(x_train, y_train,
             batch_size=batch_size,
             epochs=epochs,
             verbose=0,
             validation_data=(x_test, y_test))
    score = model.evaluate(x_test, y_test, verbose=0)
    return score[1]

# test
list_n = [32, 16, 8, 4, 2, 1] 
x, y = [], []
for n in list_n:
    params = 63*n*n + 335*n + 10
    acc = cnn(n)
    x.append(params)
    y.append(acc)
    print ('n = ', n, ', ', 'params = ', params, ', ', 'accuracy = ', acc)

# graph
import matplotlib.pyplot as plt
plt.scatter(x, y)
plt.xscale('log')
plt.show()

スクリーンショット 2020-01-22 13.17.01.png Überraschenderweise konnten wir mit nur 932 Gewichtsparametern eine Genauigkeit von 97% sicherstellen. Diese Anzahl von Gewichtsparametern beträgt weniger als 1/1000 des ** Basismodells! ** ** **

Und im Vergleich zu 17418 MLP wurde festgestellt, dass 17418/932 = 18,68 ** die gleiche Genauigkeit mit dem Gewichtsparameter von etwa 1/18 MLP ** erzielt werden kann.

** Es ist ein Ergebnis, dass Sie sehr gut sehen können, dass die Faltungsschicht von CNN bei der Bilderkennung äußerst effektiv funktioniert. CNN, es ist beängstigend!

Recommended Posts

Mit ein wenig Präzision wurden die Gewichtsparameter unglaublich reduziert ~ Überraschende Ergebnisse von CNN ~
Verstehen Sie die Anzahl der Eingabe- / Ausgabeparameter des Faltungs-Neuronalen Netzes
Implementierung eines zweischichtigen neuronalen Netzwerks 2
Visualisieren Sie die innere Schicht des neuronalen Netzwerks
Mit ein wenig Präzision wurden die Gewichtsparameter unglaublich reduziert ~ Überraschende Ergebnisse von CNN ~
Erhalten Sie eine Liste der Ergebnisse der Parallelverarbeitung in Python mit Starmap
Machen Sie LCD-Screenshots mit Python-LEGO Mindstorms
Visualisieren Sie das charakteristische Vokabular eines Dokuments mit D3.js.
Berechnen Sie das Produkt von Matrizen mit einem Zeichenausdruck?