Dieser Artikel führt in die Klassifizierung von MNIST-Datensätzen unter Verwendung der Kaggle-Entwicklungsumgebung (Kernel-Notizbuch) und von Keras als Einführung in die Analyse von Malmönchen ein. Der Kernel ist auf Kaggle für die Öffentlichkeit zugänglich. Schauen Sie also bitte nach, ob Sie ihn selbst ausführen möchten.
Wenn Sie Fehler, Fragen oder Kommentare haben, lassen Sie es uns bitte wissen. Es wird ermutigend sein, wenn Sie LGTM bekommen können!
Kaggle ist der weltweit größte Online-Analysewettbewerb. Darüber hinaus gibt es eine Online-Entwicklungsumgebung namens Kernel Notebook, mit der Sie sofort an der Analyse arbeiten können. Dies ist ideal, um mit der Datenanalyse zu beginnen. Dieser Artikel richtet sich an Personen, die sich bereits bei Kaggle registriert haben und wissen, wie man Kernel verwendet. (Es gibt viele Artikel, die selbst diejenigen, die es nicht wissen, hilfreich sein können. Ich denke, Sie können sie sofort nachholen.)
Siehe unten für weitere Details.
Keras ist eine Deep-Learning-Bibliothek, die auf Tensorflow basiert und dafür bekannt ist, sehr schnell Deep-Learning-Modelle erstellen zu können.
Siehe unten für weitere Details.
Es ist ein sehr berühmter Bilddatensatz, der aus handgeschriebenen Zahlen (0-9) und den Zahlen besteht, die sie wirklich darstellen (korrekte Bezeichnung).
Siehe unten für weitere Details.
Auch dieser Artikel ist auch auf Kaggles Kernel veröffentlicht. Wenn Sie also eine Gabelung wünschen, lesen Sie dies bitte ebenfalls.
Sie sehen, dass die Trainingsdaten aus 42000 Daten bestehen. Obwohl es 785 Spalten gibt, ist die richtige Bezeichnung die erste, sodass Sie sehen können, dass die zum Lernen verwendete Merkmalsmenge aus 784 besteht. Sie können sehen, dass die Beschriftung eine Ganzzahl ist und die Feature-Menge für die meisten Elemente 0 ist.
#Trainingsdaten laden
train = pd.read_csv("../input/train.csv")
print(train.shape)
train.head()
Es gibt 28000 Testdaten. Es gibt keine korrekte Bezeichnung, daher besteht sie aus 784 Spalten.
#Testdaten laden
test= pd.read_csv("../input/test.csv")
print(test.shape)
test.head()
Typkonvertierung und Konvertierung in benutzerfreundliche Numpy-Daten.
#Schneiden Sie den Teil der Merkmalsmenge der Trainingsdaten ohne das richtige Antwortetikett aus.
X_train = train.iloc[:,1:].values.astype('float32')
#Schneiden Sie nur das richtige Antwortetikett aus den Trainingsdaten aus.
y_train = train.iloc[:,0].values.astype('int32')
#Dies sind Testdaten.
X_test = test.values.astype('float32')
Schauen wir uns den Prozentsatz von 0 in den Daten an. Das Verhältnis von 0 beträgt ungefähr 80%, und Sie können sehen, dass die meisten Elemente 0 sind. In diesem Datensatz bedeutet 0 leer = nicht charakterisierter Bereich.
print(f"Der Prozentsatz der Elemente ungleich Null{round((X_train > 0).sum()/(X_train >= 0 ).sum()*100)}%ist")
print(f"Der Prozentsatz von 0 Elementen{round((X_train == 0).sum()/(X_train >= 0 ).sum()*100)}%ist")
Wenn wir uns die Verteilung der korrekten Etiketten ansehen, sehen wir, dass jedes Etikett von 0 bis 9 etwa 10% ausmacht. Daher scheint eine Anpassung aufgrund eines Klassenungleichgewichts nicht erforderlich zu sein.
#Zeigen Sie den Prozentsatz der korrekten Beschriftungen in einem Kreisdiagramm an
f, ax = plt.subplots(1,figsize=(6,6))
y_count = pd.Series(y_train).value_counts().sort_index()
ax.pie(y_count.values ,
labels=y_count.index,
autopct='%1.1f%%',
counterclock = False,
startangle = 90)
plt.show()
Als nächstes transformieren Sie die Daten in ein Formular, das einfach als Bild zu verarbeiten ist. Wie wir zuvor gesehen haben, besteht jedes Bild aus 784 Elementen, aber dies war tatsächlich ein eindimensionaler Zusammenbruch von quadratischen Daten, die aus 28 vertikalen und 28 horizontalen Elementen bestehen. Transformiert für alle Trainingsdaten in 28x28 (42000 = X_train.shape [0]).
#Datentransformation
X_train = X_train.reshape(X_train.shape[0], 28, 28)
Lassen Sie uns die transformierten Rohdaten visualisieren. Um die Bedeutung von Rohdaten zu berücksichtigen, drücken wir die Daten hier als Zeichenfolge aus, ohne eine Bildbibliothek zu verwenden. Zeigen wir den Teil, in dem das Nicht-Null-Element vorhanden ist, als # an. Dann können Sie die Ausgabe wie handgeschriebene Zahlen erhalten.
Die Originaldaten sind eine Liste von Zahlen, die für den Menschen schwer zu verstehen sind, aber es waren tatsächlich Daten, die aus der Absicht der Tinte (ob sie nicht 0 ist oder nicht) und ihrer Dichte (Wert der Zahl) bestehen.
#Daten in Zeichenfolge konvertieren und anzeigen
def visualize_str(d):
d = d.astype("int32").astype("str")
d[d != "0"] = "# "
d[d == "0"] = ". "
d = pd.DataFrame(d)
for i in range(d.shape[0]):
print("".join(d.iloc[i,:]))
print("")
for i in range(1):
visualize_str(X_train[i])
Wenn Sie versuchen, es als Bild anzuzeigen, erhalten Sie immer noch die gleiche Ausgabe wie bei der vorherigen Zeichenfolgenanzeige.
#Mit Bild visualisieren
f, ax = plt.subplots(1,3)
for i in range(3):
ax[i].imshow(X_train[i], cmap=plt.get_cmap('gray'))
Da bei der Bildanalyse manchmal farbige Bilder verwendet werden, wird davon ausgegangen, dass die Eingabe in das Modell eine Dimension aufweist, die als Farbkanal bezeichnet wird und Farbtöne enthält (hauptsächlich Mihara). Da es sich diesmal um eine Graustufe handelt, gibt es keine neuen Daten, aber wir werden den Tensor gemäß der obigen Idee konvertieren. Stellen Sie außerdem vor dem Lernen eine Hot-Codierung und Zufallszahlen als Vorbereitung ein.
#Farbkanal hinzufügen
X_train = X_train.reshape(X_train.shape[0], 28, 28,1)
X_test = X_test.reshape(X_test.shape[0], 28, 28,1)
#Eine heiße Codierung
from keras.utils.np_utils import to_categorical
y_train= to_categorical(y_train)
#Zufällige Zahlen für die Reproduzierbarkeit behoben
seed = 0
np.random.seed(seed)
Es ist endlich Modellierung, aber zuerst versuchen wir es mit einem sehr einfachen linearen Modell.
Definieren Sie zuvor die erforderlichen Funktionen zum Importieren und Standardisieren von Modulen.
from keras.models import Sequential
from keras.layers.core import Lambda , Dense, Flatten, Dropout
#from keras.callbacks import EarlyStopping
from keras.layers import BatchNormalization, Convolution2D , MaxPooling2D
#Definition der Standardisierungsfunktion
mean_X = X_train.mean().astype(np.float32)
std_X = X_train.std().astype(np.float32)
def standardize(x):
return (x-mean_X)/std_X
Nun erstellen wir das Modell.
#Definition des linearen Modells
model_linear= Sequential()
#Standardisierung
model_linear.add(Lambda(standardize,input_shape=(28,28,1)))
#Machen Sie es eindimensional, um es in die vollständig verbundene Ebene zu legen
model_linear.add(Flatten())
#Vollständig verbundene Schicht
model_linear.add(Dense(10, activation='softmax'))
#Modellvisualisierung
print("model_linear")
model_linear.summary()
Keras wird nach dem Definieren des Modells kompiliert. Beim Kompilieren werden der Index angegeben, der durch Lernen = Verlust optimiert werden soll, und der Index, der wirklich optimiert werden soll.
#Modell kompilieren
#Geben Sie den zu optimierenden Index und den zu beobachtenden Index an
from keras.optimizers import Adam ,RMSprop
model_linear.compile(optimizer=RMSprop(lr=0.001),
loss='categorical_crossentropy',
metrics=['accuracy'])
Nachdem das Modell fertig ist, möchte ich das Modell mit Daten füllen, aber ich muss die Daten vorbereiten. Bereiten Sie einen Generator vor und teilen Sie die Daten für die Kreuzvalidierung auf. (Dies sollte als Holdout-Methode bezeichnet werden, aber in Kaggle wird sie üblicherweise als Kreuzvalidierung ausgedrückt, daher bin ich mir des Missverständnisses bewusst und drücke es so aus.)
#Daten für die Eingabe vorbereiten
#Definition des Generators
from keras.preprocessing import image
generator = image.ImageDataGenerator()
#Alle zum Zeitpunkt der Einreichung verwendeten Lerndaten
X = X_train
y = y_train
#Kreuzvalidierung
from sklearn.model_selection import train_test_split
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.15, random_state=seed)
train_generator = generator.flow(X_train, y_train, batch_size=64)
val_generator = generator.flow(X_val, y_val, batch_size=64)
Bereiten Sie auch eine Tensorplatte vor, um die Lernsituation und die Ergebnisse besser erkennen zu können. Die Standardausgabe gibt eine URL aus. Öffnen Sie sie daher in Ihrem Browser.
#Start von Tensorboard
import tensorflow as tf
!rm -rf ./logs/
!mkdir ./logs/
!wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip
!unzip ngrok-stable-linux-amd64.zip
import os
import multiprocessing
import datetime
pool = multiprocessing.Pool(processes = 10)
results_of_processes = [pool.apply_async(os.system, args=(cmd, ), callback = None )
for cmd in [
f"tensorboard --logdir ./logs/ --host 0.0.0.0 --port 6006 &",
"./ngrok http 6006 &","y"
]]
! curl -s http://localhost:4040/api/tunnels | python3 -c \
"import sys, json; print(json.load(sys.stdin)['tunnels'][0]['public_url'])"
log_dir = "logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=0)
Jetzt, da wir bereit sind, ist es Zeit zu lernen. Es zeigt den Lernfortschritt mit dem Fortschrittsbalken und dem durch Kompilieren angegebenen Index.
#Daten lernen mit epoch3
# ~Ich denke, es wird ungefähr 15 Minuten dauern
import tensorflow as tf
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
history_linear=model_linear.fit_generator(generator=train_generator,
steps_per_epoch=train_generator.n,
epochs=3,
validation_data=val_generator,
validation_steps=val_generator.n,
callbacks=[tensorboard_callback]
)
Die obigen Ergebnisse zeigen, wie gelernt wird, aber wir werden die Ergebnisse für ein intuitiveres Verständnis visualisieren.
Wenn wir uns die Verluste ansehen, können wir sehen, dass Überlernen auftritt, weil die Validierungsergebnisse mit fortschreitendem Lernen zunehmen. Beachten Sie andererseits, dass die Validierung von ACC (korrekte Antwortrate) nicht monoton abgenommen hat. Diskontinuierliche Indikatoren wie ACC sind schwer zu handhaben. Stattdessen optimieren Sie mit einer benutzerfreundlichen Verlustfunktion.
#Visualisierung der Ergebnisse
#Definition der Funktion zum Zeichnen des Ergebnisses
def plt_history(history,keys):
history_dict = history.history
n = len(keys)
f, ax = plt.subplots(n,figsize=(8,4*n))
for i in range(n):
train_value = history_dict[keys[i][0]]
val_value = history_dict[keys[i][1]]
epochs = range(1, len(train_value) + 1)
if n==1:
ax.plot(epochs, train_value, 'bo',label = keys[i][0])
ax.plot(epochs, val_value, 'b+',label = keys[i][1])
ax.legend()
ax.set_xlabel('Epochs')
ax.set_ylabel(keys[i][0])
else:
ax[i].plot(epochs, train_value, 'bo',label = keys[i][0])
ax[i].plot(epochs, val_value, 'b+',label = keys[i][1])
ax[i].legend()
ax[i].set_xlabel('Epochs')
ax[i].set_ylabel(keys[i][0])
plt.show()
#Visualisierung
plt_history(history_linear, [["loss","val_loss"],["acc","val_acc"]])
In diesem Modell wird eine vollständig verbundene Ebene hinzugefügt, um die Ebene zu vertiefen. Wir haben auch den Optimierungsalgorithmus in Adam geändert. (Dies sollte experimentell verglichen werden, um das optimale zu bestimmen.)
Obwohl wir Modelle früher nacheinander definiert und verarbeitet haben, definieren wir im Allgemeinen Modelltypen mit Klassen und Funktionen und erstellen verschiedene Trainingsmodelle mit mehreren verschiedenen Parametern und Trainingsdaten. Daher definieren wir ab hier das Modell mit einer Funktion.
#Modelldefinition
def get_fc_model():
model = Sequential()
model.add(Lambda(standardize,input_shape=(28,28,1)))
model.add(Flatten())
model.add(Dense(512, activation='relu'))
model.add(Dense(10, activation='softmax'))
model.compile(optimizer = Adam(),
loss='categorical_crossentropy',
metrics=['accuracy'])
return model
model_fc = get_fc_model()
model_fc.optimizer.lr=0.01
model_fc.summary()
Lernen Sie das Modell auf die gleiche Weise wie zuvor. Wenn Sie mehrere Modelle in kurzer Zeit ausprobieren möchten, müssen Sie einen Kompromiss eingehen, z. B. die Anzahl der Epochen reduzieren. Wenn wir uns die Ergebnisse ansehen, können wir sehen, dass die Validierungs-ACC höher ist als zuvor.
#Modelllernen
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
history_fc=model_fc.fit_generator(generator=train_generator,
steps_per_epoch=train_generator.n,
epochs=1,
validation_data=val_generator,
validation_steps=val_generator.n,
callbacks=[tensorboard_callback]
)
#Lernergebnis
history_dict_fc = history_fc.history
history_dict_fc
Versuchen Sie als nächstes das CNN-Modell, das die Faltschicht und die Poolschicht enthält. Da CNN einen weiten Bereich effizient lernen kann, kann bei Bildanalyseproblemen eine hohe Genauigkeit erwartet werden. Dieses Mal werden wir zwei Arten von Schichttiefen vorbereiten und den Unterschied sehen.
#Modelldefinition
from keras.layers import Convolution2D, MaxPooling2D
#Ein Modell mit zwei Falten und zwei Pools
def get_cnn_model1():
model = Sequential([
Lambda(standardize, input_shape=(28,28,1)),
Convolution2D(32,(3,3), activation='relu'),
MaxPooling2D(),
Convolution2D(64,(3,3), activation='relu'),
MaxPooling2D(),
Flatten(),
Dense(512, activation='relu'),
Dense(10, activation='softmax')
])
model.compile(optimizer = Adam(), loss='categorical_crossentropy',
metrics=['accuracy'])
return model
#Ein Modell mit jeweils 3 Falten und Poolen
def get_cnn_model2():
model = Sequential([
Lambda(standardize, input_shape=(28,28,1)),
Convolution2D(32,(3,3), activation='relu'),
MaxPooling2D(),
Convolution2D(64,(3,3), activation='relu'),
MaxPooling2D(),
Convolution2D(128,(3,3), activation='relu'),
MaxPooling2D(),
Flatten(),
Dense(512, activation='relu'),
Dense(10, activation='softmax')
])
model.compile(optimizer = Adam(), loss='categorical_crossentropy',
metrics=['accuracy'])
return model
model_cnn1 = get_cnn_model1()
model_cnn2 = get_cnn_model2()
model_cnn1.optimizer.lr=0.01
model_cnn2.optimizer.lr=0.01
Das flache Modell lernt 843.658 Parameter
model_cnn1.summary()
Das tiefere Modell lernt 163.850 Parameter, was weniger als model_cnn1 ist. Dies liegt daran, dass der periphere Effekt der Faltschicht und der Poolschicht die Dateneingabe in die vollständig verbundene Schicht stark reduziert. In Bezug auf die Abflachungsdimensionen waren es 1600 für cnn1, aber nur 128 für cnn2. Wenn die Größe des Bildes groß ist, ist es wünschenswert, die Größe der Daten auf diese Weise zu verringern, aber welche Art von Ergebnis wird mit kompakten Daten wie dieser Zeit erzielt?
model_cnn2.summary()
Wir werden jeden studieren.
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
history_cnn1=model_cnn1.fit_generator(generator=train_generator,
steps_per_epoch=train_generator.n,
epochs=1,
validation_data=val_generator,
validation_steps=val_generator.n,
callbacks=[tensorboard_callback]
)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
history_cnn2=model_cnn2.fit_generator(generator=train_generator,
steps_per_epoch=train_generator.n,
epochs=1,
validation_data=val_generator,
validation_steps=val_generator.n,
#callbacks=[tensorboard_callback]
)
Lassen Sie uns das Ergebnis überprüfen.
Im Vergleich zum CNN-Modell mit einer flachen Schicht weist das CNN-Modell mit einer tiefen Schicht sowohl hinsichtlich der Verlust- als auch der Genauigkeitsrate sowohl für Trainingsdaten als auch für Validierungsdaten schlechte Ergebnisse auf. Dafür gibt es mehrere mögliche Gründe.
① Das Modell ist schlecht Der Grund, warum das Modell schlecht ist, ist, dass die Trainingsparameter abgenommen haben. Die Tatsache, dass viele Parameter angepasst werden können, bedeutet, dass Sie einen vielfältigeren Ausdruck erstellen können. Dieses Modell hat eine kleine Anzahl von Parametern, so dass es möglicherweise nicht ausreichend aussagekräftig war.
② Die Lerndaten sind schlecht Übertraining tritt wahrscheinlich auf, wenn die Anzahl der Trainingsdaten nicht ausreicht. Diesmal ist die korrekte Antwortrate der Trainingsdaten nicht so schlecht, aber das Validierungsergebnis weist eine große Divergenz auf, was ein typischer Übertrainingszustand ist. Möglicherweise können Verbesserungen vorgenommen werden, indem die zu testenden Daten von nun an erweitert werden.
③ Mangel an Lernen Möglicherweise wurde das Modell noch nicht vollständig trainiert. In diesem Fall ist der Verlust von Trainingsdaten größer als der von cnn1. Wenn Sie also die Epoche verlängern, kann das Training fortgesetzt werden. Die Abweichung von der Validierung ist jedoch ein weiteres Problem, sodass eine Erhöhung der Epoche in diesem Zustand keine wesentliche Lösung darstellt.
history_cnn1.history
history_cnn2.history
Es wird angenommen, dass je mehr Trainingsdaten vorhanden sind, desto höher ist die Generalisierungsleistung = Überlernen ist weniger wahrscheinlich. Die Datenerweiterung ist eine Methode zum künstlichen Erhöhen von Trainingsdaten aus einer begrenzten Anzahl von Daten. Die Datenerweiterung ist eine Technik zum Aufblasen von Daten, indem geringfügige Änderungen an den angegebenen Daten vorgenommen werden.
#Datenerweiterung
from keras.preprocessing import image
DA_generator =image.ImageDataGenerator(rotation_range=10,
width_shift_range=0.1,
shear_range=0.1,
height_shift_range=0.1,
zoom_range=0.1)
train_DA_generator = DA_generator.flow(X_train, y_train, batch_size=64)
val_DA_generator = DA_generator.flow(X_val, y_val, batch_size=64)
#Beispiel für erweiterte Daten
tmp_gen = DA_generator.flow(X_train[0].reshape((1,28,28,1)), batch_size = 1)
for i, tmp in enumerate(tmp_gen):
plt.subplot(330 + (i+1))
plt.imshow(tmp.reshape((28,28)), cmap=plt.get_cmap('gray'))
if i == 8:
break
Ich denke, das Lernen wird ungefähr 15 Minuten dauern. Durch die Datenerweiterung wurden die Validierungsergebnisse verbessert. Die Trainingsdatenergebnisse und Validierungsergebnisse werden für jede Epoche verbessert. Wenn Sie also Zeit haben, versuchen Sie, die Epoche zu verlängern und zu experimentieren.
#CNN 1 Schicht flache CNN
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
model_cnn1.optimizer.lr=0.005
history_cnn1_DA=model_cnn1.fit_generator(generator=train_DA_generator,
steps_per_epoch=train_DA_generator.n,
epochs=1,
validation_data=val_DA_generator,
validation_steps=val_DA_generator.n,
callbacks=[tensorboard_callback]
)
history_cnn1_DA.history
In den Vorgängermodellen wurde die Eingabe standardisiert. Dies garantiert jedoch nicht, dass die Ausgabe jeder Schicht standardisiert ist. Nach einer bestimmten Schicht wird die Ausgabe sehr groß und die Parameter können sehr klein werden. Oder umgekehrt, die Parameter können sehr groß sein.
In einem solchen Fall kann das Lernen nicht gut durchgeführt werden, aber dieses Problem kann durch Hinzufügen einer Batch-Normalisierungsschicht gelöst werden, die für jede Schicht standardisiert wird. Dies soll sowohl die Generalisierungsleistung als auch die Lerngeschwindigkeit verbessern.
Die Anzahl der Epochen wird auch dieses Mal auf 1 gesetzt. Wenn Sie jedoch Zeit haben, erhöhen Sie die Anzahl der Epochen und beobachten Sie den Zustand des Überlernens.
from keras.layers.normalization import BatchNormalization
def get_bn_model():
model = Sequential([
Lambda(standardize, input_shape=(28,28,1)),
Convolution2D(32,(3,3), activation='relu'),
BatchNormalization(axis=1),
MaxPooling2D(),
BatchNormalization(axis=1),
Convolution2D(64,(3,3), activation='relu'),
BatchNormalization(axis=1),
MaxPooling2D(),
BatchNormalization(axis=1),
Flatten(),
BatchNormalization(),
Dense(512, activation='relu'),
BatchNormalization(),
Dense(10, activation='softmax')
])
model.compile(optimizer = Adam(), loss='categorical_crossentropy', metrics=['accuracy'])
return model
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
model_bn= get_bn_model()
model_bn.optimizer.lr=0.01
history_bn=model_bn.fit_generator(generator=train_DA_generator,
steps_per_epoch=train_DA_generator.n,
epochs=1,
validation_data=val_DA_generator,
validation_steps=val_DA_generator.n,
callbacks=[tensorboard_callback]
)
history_bn.history
Abschließend werde ich das Modell mit der höchsten Punktzahl unter den in diesem Artikel vorgestellten Modellen vorstellen. Das Entwerfen dieses Modells erfordert Versuch und Irrtum, wie das Hinzufügen von Ebenen und das Ändern von Optimierungsfunktionen, wie wir bisher gesehen haben. Dieses optimale Modell ist ein Modell, das eine Reihe von Versuchen und Fehlern durchlaufen hat (in meinen aktuellen Fähigkeiten und meiner Entwicklungsumgebung).
Wir haben eine Dropout-Ebene, die anfängliche Einstellung von He und einen Rückruf hinzugefügt, der die Lernrate Schritt für Schritt ändert.
Infolgedessen markiert die Variation eine korrekte Antwortrate von 99,4%.
from keras.layers import Dense, Dropout, Flatten, Convolution2D, MaxPooling2D
from keras.layers.normalization import BatchNormalization
from keras.callbacks import ReduceLROnPlateau
def get_opt_model():
model = Sequential([
Lambda(standardize, input_shape=(28,28,1)),
Convolution2D(32,(3,3), activation='relu',kernel_initializer='he_normal'),
Convolution2D(32,(3,3), activation='relu',kernel_initializer='he_normal'),
MaxPooling2D(),
Dropout(0.20),
Convolution2D(32,(3,3), activation='relu',kernel_initializer='he_normal'),
Convolution2D(32,(3,3), activation='relu',kernel_initializer='he_normal'),
MaxPooling2D(),
Dropout(0.25),
Convolution2D(32,(3,3), activation='relu',kernel_initializer='he_normal'),
Dropout(0.25),
Flatten(),
Dense(128, activation='relu'),
BatchNormalization(),
Dropout(0.25),
Dense(10, activation='softmax')
])
model.compile(optimizer=Adam(),
loss='categorical_crossentropy',
metrics=['accuracy'])
return model
learning_rate_reduction = ReduceLROnPlateau(monitor='val_loss',
patience=3,
verbose=1,
factor=0.5,
min_lr=0.0001)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
model_opt = get_opt_model()
history_opt = model_opt.fit_generator(generator=train_DA_generator,
steps_per_epoch=train_DA_generator.n,
epochs=3,
validation_data=val_DA_generator,
validation_steps=val_DA_generator.n,
callbacks=[tensorboard_callback, learning_rate_reduction]
)
Y_pred = model_opt.predict_classes(X_val,verbose = 0)
Y_pred_prob = model_opt.predict(X_val,verbose = 0)
#Visualisierung der Ergebnisse
plt_history(history_opt, [["loss","val_loss"],["acc","val_acc"]])
history_opt.history
Selbst im optimalen Modell gab es einige falsche Antworten, aber welche Art von Daten sind falsch? Betrachtet man die gemischte Matrix, so scheint es fast keine falschen Antworten zu geben, aber es gibt einige Fälle, in denen 1 mit 7 und 7 mit 2 verwechselt wird.
#Definition einer Funktion, die eine Verwirrungsmatrix anzeigt
import itertools
def plt_confusion_mtx(confusion_mtx):
cmap=plt.cm.Reds
title='Confusion matrix'
f, ax = plt.subplots(1,figsize=(6,6))
im = ax.imshow(confusion_mtx, interpolation='nearest', cmap=cmap)
ax.set_title(title)
ax.set_xticks(np.arange(10))
ax.set_yticks(np.arange(10))
ax.set_xlabel('Predicted label')
ax.set_ylabel('True label')
f.colorbar(im)
thresh = confusion_mtx.max() / 2
for i, j in itertools.product(range(confusion_mtx.shape[0]), range(confusion_mtx.shape[1])):
ax.text(j, i, confusion_mtx[i, j],
horizontalalignment="center",
color="white" if confusion_mtx[i, j] > thresh else "black")
#Anzeige der Verwirrungsmatrix
from sklearn.metrics import confusion_matrix
Y_true = np.argmax(y_val,axis=1)
confusion_mtx = confusion_matrix(Y_true, Y_pred)
plt_confusion_mtx(confusion_mtx)
#Präzision für jede Weltklasse,Rückrufbestätigung etc.
from sklearn.metrics import classification_report
target_names = ["Class {}".format(i) for i in range(10)]
print(classification_report(Y_true, Y_pred, target_names=target_names))
Wenn Sie sich tatsächlich die falschen Antwortdaten ansehen, gibt es einige Fälle, in denen es für Menschen schwierig ist, sie zu unterscheiden, sondern es wird vermutet, dass die Kennzeichnung falsch ist.
#Bestätigung falscher Antwortdaten
errors = (Y_pred - Y_true != 0)
Y_pred_errors = Y_pred[errors]
Y_pred_prob_errors = Y_pred_prob[errors]
Y_true_errors = Y_true[errors]
X_val_errors = X_val[errors]
def display_errors(errors_index,img_errors,pred_errors, obs_errors):
""" This function shows 6 images with their predicted and real labels"""
n = 0
nrows = 2
ncols = 3
fig, ax = plt.subplots(nrows,ncols, figsize = (8,8))
for row in range(nrows):
for col in range(ncols):
error = errors_index[n]
ax[row,col].imshow((img_errors[error]).reshape((28,28)))
ax[row,col].set_title("Predicted label :{}\nTrue label :{}".format(pred_errors[error],obs_errors[error]))
n += 1
errors = (Y_pred - Y_true != 0)
tmp = Y_pred_prob[errors] - to_categorical(Y_pred[errors])
display_index = np.argsort(tmp.max(axis=1))[:6]
display_errors(display_index, X_val_errors, Y_pred_errors, Y_true_errors)
Man kann sagen, dass das optimale Modell eine ausreichende Leistung aufweist, um dem praktischen Gebrauch standzuhalten.
Damit ist die Einführung in die Deep Learning-Bildanalyse von Keras abgeschlossen. Von hier an können Sie versuchen, mit komplexeren Datensätzen zu trainieren, das Lernen mit trainierten Modellen zu übertragen, berühmte Deep-Learning-Modelle auszuprobieren und vieles mehr. Ich werde. Wenn dieser Artikel für jemanden nützlich ist, möchte ich diese Tutorial-Artikel in Zukunft aktualisieren. Bitte unterstützen Sie mich bei LGTM.
Außerdem bin ich immer auf der Suche nach einem Job. Bitte lassen Sie mich wissen, wenn Sie die Gelegenheit dazu haben.
Recommended Posts