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.
Hier ist die Grundstruktur von MLP im Keras-Tutorial (eigentlich habe ich zwei Dropouts hinzugefügt, diese aber der Einfachheit halber weggelassen). 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()
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 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. 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()
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.
Hier ist die Grundstruktur des CNN im Keras-Tutorial (eigentlich habe ich zwei Dropouts hinzugefügt, diese aber der Einfachheit halber weggelassen). 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()
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, 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.
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()
Ü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