Dokumentation
Python für Deep Learning: Python hat als Programmiersprache die größte Unterstützung für Deep Learning. Deswegen habe ich zuerst Python 3.7 installiert und es in den ersten Tagen gelernt, hauptsächlich anhand dieses vom Betreuer empfohlenen Tutoriums https://www.youtube.com/user/schafer5. Ich habe auch PyCharm(community) installiert. https://www.jetbrains.com/pycharm/download/#section=mac. Das ist eine integrierte Entwicklungsumgebung, die in der Computerprogrammierung speziell für die Python-Sprache verwendet wird.
Tensorflow Installierung: TensorFlow ist eine Open-Source-Bibliothek für numerische Berechnungen und maschinelles Lernen in großem Maßstab. Es kann tiefe neuronale Netze für die handschriftliche Ziffernklassifizierung und Bilderkennung trainieren und ausführen. Dieses Link war für mich helpful bei der Installierung von Tensorflow: https://github.com/jeffheaton/t81_558_deep_learning/blob/master/t81_558_class_01_1_overview.ipynb
Allgemeiner Arbeitsablauf
- Detailliertes Suchen und Verständnis der Aufgabe
- Untersuchen und Verstehen des Codes von ähnlichen Themen
- Extrahieren meiner eigenen Bilder
- Zusammenstellen meines eigenen Modells
- Übertragen des Modells auf die vortrainierten Modelle
- Modell trainieren
- Modell auswerten
1. Detailliertes Suchen und Verständnis der Aufgabe
In einem normalen dichten Netzwerk oder einem mehrschichtigen Perzeptron (vereinfachtes künstliches neuronales Netz) sind alle Neuronen in einer Schicht mit allen Neuronen in der nächsten Schicht verbunden, was bedeutet, dass die Gewichtungsparameter des Netzwerks das Multiplikationsprodukt der Anzahl von Neuronen in den verbundenen Schichten sind. Bei der Verarbeitung von Bildern mit höheren Auflösungen sind die Netzwerkparameter sehr hoch und erfordern eine höhere Rechenleistung. Niemand will Millionen von Params für die kleinen Bilder trainieren.Dieses Problem kann durch die Verwendung eines neuronalen Faltungsnetzwerks (CNN) gelöst werden, bei dem es sich um regulierte Versionen von mehrschichtigen Perzeptronen handelt. Hier bezieht sich die Ausgabe auf die näheren Eingangsneuronen und nicht auf alle in der vorherigen Ebene. Daher werden Faltungs-Neuronale Netze (CNN oder ConvNet), eine Klasse von tiefen Neuronalen Netzen, am häufigsten zur Analyse visueller Bilder verwendet. Faltungsnetzwerke (Convolutional Networks, CNNs) machen die Arbeit leichter, benötigen trotzdem zum Trainieren erhebliche Daten- und Ressourcenmengen. Deshalb, wird ein CNN benötigt, der vorab trainiert wurde ; das sogenannte vortrainierte Modell;, dessen letzten vollständig verbundenen Layer entfernt und durch die benutzerdefinierten vollständig verbundenen Layer ersetzt. So kann man die Vorteile dieser erlernten ‘feature maps‘ nutzen, ohne ein großes Modell mit einem großen Datensatz von Grund auf trainieren zu müssen. Sobald die letzte vollständig verbundene Ebene ersetzt wurde, trainiert man den ‘Classifier‘ für den neuen Datensatz.
3.Extrahieren meiner eigenen Bilder
Die im HDF5 Format Blutzellen Bilder habe ich vom NAS heruntergeladen und anhand dieser Funktion gelesen. HDF5 ist ein Datenmodell, eine Bibliothek und ein Dateiformat zum Speichern und Verwalten von Daten. Es unterstützt eine unbegrenzte Anzahl von Datentypen und ist für große Datenmengen und komplexe Daten konzipiert. Dafür muss man das package h5py, eine Pythonic-Schnittstelle zum HDF5-Binärdatenformat, importieren.
def load_images(path, s=1): with h5py.File(path, 'r') as f: keys = list(f.keys())[:100] n = len(keys) shape = f[keys[0]]['Cell']['image'].shape shape = shape[0] - s * 2, shape[1] - s * 2 shape = 224, 224 labels = np.empty((n,), dtype=np.str) data = np.empty((n, shape[0], shape[1])) for i, key in enumerate(keys): data[i, :] = cv2.resize(f[key]['Cell']['image'][...], shape, interpolation=cv2.INTER_CUBIC) labels[i] = f[key]['Label']['class'][...] f.close() print('[ INFO ] Read {} samples'.format(n)) return data, labels data, labels = load_images('path of the hdf5 data ')
Diese Funktion benutzt man sowohl um die im H5 Datei stehenden Bilder zu lesen als auch deren Klassen. Die Größe der Bilder wurde auch zu [224,224] angepasst ;das wird zunächst nützlich)
4. Zusammenstellen meines eigenen Modells
Ein großer Teil der Vorverarbeitung ist die Codierung. Dies bedeutet, dass jedes Datenelement so dargestellt wird, dass der Computer es verstehen kann. Mit diesem Befehl newlabel = pd.factorize(labels) wurde der erste encoding-Schritt ausgeführt. Die Labels wurden von Buchstaben [‘N‘, ‘L‘,‘E‘,‘B‘,‘M‘] zu [0, 1, 2, 3, 4] geändert. Das heißt Label encoding. Das muss man für die Train_test_split() machen( da diese funktion keine Buchstaben lesen kann) und das erleichtert den zweiten Codierung Schritt : das one-hot-encoding.
# split X and y into training and testing sets X_train, X_test, y_train, y_test = train_test_split(X, y[0], test_size=0.2, random_state=4) 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) X_train /= 255 X_test /= 255
Wenn man an einem Modell arbeitet und es trainieren möchte, hat man offensichtlich einen Datensatz(dataset). Nach dem Training muss das Modell jedoch an einem Testdatensatz getestet werden. Zu diesem Zweck erhält man einen Datensatz, der sich von dem zuvor verwendeten Trainingssatz unterscheidet. Möglicherweise ist es jedoch nicht immer möglich, während der Entwicklungsphase so viele Daten zu haben. Deshalb musste ich vor dem Training, den Datensatz in zwei Sätze aufteilen, einen zum Trainieren und den anderen zum Testen. Das kann man wahrscheinlich manuell nicht machen. Dafür bietet die SciKit-Bibliothek ein Tool namens Model Selection library. In der Bibliothek gibt es eine Klasse mit dem Namen "train_test_split". Mit dieser Klasse kann man den Datensatz einfach in Trainings- und Testdatensätze in verschiedenen Anteilen (anhand test size) aufteilen.
random_state : train_test_split teilt Arrays oder Matrizen in zufällige Zug- und Test-Teilmengen auf. Das bedeutet, dass man jedes Mal, wenn man es ausführt, ohne random_state anzugeben, ein anderes Ergebnis erhält. Wenn man jedoch random_state = eine_zahl (egal welche 0,1..) verwenden, kann man sicherstellen, dass die Ausgabe von Lauf 1 der Ausgabe von Lauf 2 entspricht, d. h., dass ihre Aufteilung immer dieselbe ist.
Um die Bilder einem neuronalen Faltungsnetzwerk zuzuführen, wurde der Datenrahmen in vier Dimensionen transformiert.(X_train =X_train.reshape(X_train.shape[0], img_rows, img_cols,1). Dies kann mithilfe der numpys-Umformungsmethode erfolgen. Dann müssen die Bildpixelwerte (im Bereich von 0 bis 255) normalisiert werden - in diesem Fall zwischen 0 und 1.(X_train /= 255,X_test /= 255).
# convert class vectors to binary class matrices Y_train = to_categorical(y_train, num_classes=5) Y_test = to_categorical(y_test, num_classes=5)
Zunächt wurden die Labels mithilfe der to_categorical-Methode von Keras in eine One-Hot-Codierung umgewandelt. So kommt man jetzt auf dem zweiten codierung schritt. Hier wird die ganzzahlige codierte Variable entfernt und für jeden eindeutigen ganzzahligen Wert eine neue binäre Variable hinzugefügt. Also vom vektor [0, 1, 2, 3, 4] zu einer matrix[[1 0 0 0 0] [0 1 0 0 0] [0 0 1 0 0]..] für num_class=5.
5. Übertragen des Modells auf die vortrainierten Modelle
Beim Transferlernen wird der Lernprozess nicht von Grund auf neu gestartet, sondern anhand von Mustern, die bei der Lösung eines anderen Problems gelernt wurden. Auf diese Weise können Sie frühere Erkenntnisse nutzen und vermeiden, bei Null anzufangen. In der Bildverarbeitung wird das Transferlernen normalerweise durch die Verwendung von vorab trainierten Modellen ausgedrückt. Ein vorab trainiertes Modell ist ein Modell, das anhand eines großen Benchmark-Datensatzes trainiert wurde, um ein Problem zu lösen, das dem Problem ähnelt, das man lösen möchte. Dementsprechend ist es aufgrund der Berechnungskosten für das Training solcher Modelle( z. B. VGG, Inception, MobileNet) zu importieren und zu verwenden. Für meine Analyse habe ich bekannte Modelle wie, Resnet50, VGG16, Inception v3 und Mobilenet, da diese häufig verwendet werden, sehr populär sind und eine niedrige Fehlerwahrscheinlichkeit haben. Man kann ein Modell von diesen [inception_v3, resnet50, mobilenet, vgg16] als input wählen so wird das gewählte Netzwerk geladen. Man gibt include_top = False in diesem Modell an, um die Klassifizierungsebenen der obersten Ebene (top layers) zu entfernen.
def get_model(pre_model): if pre_model == 'inception_v3': base_model=inception_v3.InceptionV3(weights='imagenet',include_top=False) # not load the final classification layers base_model.summary() elif pre_model == 'resnet50': base_model =resnet50.ResNet50(weights='imagenet',include_top=False) base_model.summary() elif pre_model == 'mobilenet': base_model = MobileNet(weights='imagenet', include_top=False) base_model.summary() elif pre_model == 'vgg16': base_model = vgg16.VGG16(weights='imagenet', include_top=False) base_model.summary() # add a global spatial average pooling layer x = base_model.output x = GlobalAveragePooling2D()(x) # let's add a fully-connected layer x = Dense(1024, activation='relu')(x) # and a logistic layer predictions = Dense(nb_classes, activation='softmax')(x) # mark the origional MobileNet layers as non-trainable and our new layers as trainable. model=Model(inputs=base_model.input,outputs=predictions) # train only the top layers for layer in base_model.layers: layer.trainable = False model.compile(optimizer='Adam',loss='categorical_crossentropy',metrics=['accuracy']) return model
# add a global spatial average pooling layer
Das Ziel von Max-Pooling besteht darin, eine Eingabedarstellung (Bild, matrix...) in Abschnitten zu zerlegen, ihre Dimensionen zu verringern und Annahmen über Merkmale zu treffen, die in den gruppierten Unterbereichen enthalten sind.
Beispiel:
# let's add a fully-connected layer # and a logistic layer
Bei einer vollständigen Verbindung wird das Faltungsnetzwerk (convolutional network) mit einem neuronalen Netzwerk verbunden und anschließend wird das Netzwerk kompiliert.Hier wurde ein 2-schichtiges neuronales Netzwerk mit einer Softmax-Funktion als Aktivierungsfunktion für die letzte Schicht erstellt, da die Wahrscheinlichkeit ermittelt werden muss.
Adam optimizer: Adam ist ein Optimierungsalgorithmus, der anstelle des klassischen stochastischen Gradientenabstiegsverfahrens verwendet werden kann, um die iterativen Netzwerkgewichte basierend auf Trainingsdaten zu aktualisieren. Sobald man oben die optimierten Parameter gefunden hat, verwendet man diese „Metrics“, um zu bewerten, wie genau die Vorhersage des Modells mit den tatsächlichen Daten verglichen wird.
Comparison of Adam to Other Optimization Algorithms Training a Multilayer Perceptron. Taken from Adam: A Method for Stochastic Optimization, 2015.Genauigkeit(Accuracy)i:
6. Modell trainieren
Image Data Augmentation
Die Bilddatenerweiterung ist eine Technik, mit der die Größe eines Trainingsdatensatzes künstlich vergrößert werden kann, indem modifizierte Versionen von Bildern im Datensatz erstellt werden. Das Trainieren von Deep-Learning-Neuronalnetzwerkmodellen mit mehr Daten kann zu geschickteren Modellen führen, und die Augmentationstechniken können Variationen der Bilder erzeugen, die die Fähigkeit der Anpassungsmodelle verbessern, das Gelernte auf neue Bilder zu verallgemeinern. Die Keras Deep Learning-Bibliothek für neuronale Netzwerke bietet die Möglichkeit, Modelle mithilfe der ImageDataGenerator-Klasse anzupassen.
# This will do preprocessing and realtime data augmentation: if pre_model == 'inception_v3': from tensorflow.keras.applications.inception_v3 import preprocess_input elif pre_model == 'resnet50': from tensorflow.keras.applications.resnet50 import preprocess_input elif pre_model == 'mobilenet': from tensorflow.keras.applications.mobilenet import preprocess_input elif pre_model == 'vgg16': from tensorflow.keras.applications.vgg16 import preprocess_input print('Using real-time data augmentation.') # reshape to be [samples][width][height][channels] X_train = X_train.reshape((X_train.shape[0], 224, 224, 1)) X_test = X_test.reshape((X_test.shape[0], 224, 224, 1)) print("starting model compile") X_train = to_categorical(X_train,num_classes=3) X_test = to_categorical(X_test,num_classes=3) X_train = X_train.astype('uint8') #for image data generation datagen = ImageDataGenerator(preprocessing_function=preprocess_input, rotation_range=15, shear_range=0.2, zoom_range=0.2, horizontal_flip=True) # fit parameters from data datagen.fit(X_train) max_num_iterations = 1 num_iterations= 0 for X_batch, y_batch in datagen.flow(X_train, Y_train, batch_size=9): X_train = X_train.astype('uint8') X_batch = X_batch.astype('uint8') if num_iterations >= max_num_iterations: break # Show 9 images for i in range(0, 9): plt.subplot(330 + 1 + i) plt.imshow(X_batch[i]) # show the plot plt.show() num_iterations+=1 # break # Fit the model on the batches generated by datagen.flow(). model = get_model(pre_model) model.fit_generator(datagen.flow(X_train, Y_train,batch_size=batch_size),epochs=nb_epoch,validation_data=(X_test, Y_test))
About data augmentation https://machinelearningmastery.com/image-augmentation-deep-learning-keras/, https://keras.io/preprocessing/image/
Aboutkeras.fit() and keras.fit_generator() : https://www.geeksforgeeks.org/keras-fit-and-keras-fit_generator/
7. Modell auswerten
score = model.evaluate(X_test, Y_test, verbose=1) print('Test score:', score[0]) print('Test accuracy:', score[1]) small_x = X_test[1:100] small_y = Y_test[1:100] small_y2 = np.argmax(small_y,axis=1) pred = model.predict(small_x) pred = np.argmax(pred,axis=1) score = metrics.accuracy_score(small_y2, pred) print('Accuracy: {}'.format(score))
#score = model.evaluate(X_test, Y_test,verbose=1)
Score: ist die Bewertung der Verlustfunktion (loss function) für eine bestimmte Eingabe. Beim Training eines Netzwerks werden Parameter gefunden, die eine Verlustfunktion (oder eine Kostenfunktion) minimieren. Die Kostenfunktion ist hier die „categorical_crossentropy“. Das wird häufig im Trainingsprozess verwendet, um die "besten" Parameterwerte für ein Modell zu finden (z. B. Gewichte im neuronalen Netz). Es ist das, was man im Training optimieren möchte, indem man die Gewichte aktualisiert.
np.argmax (small_y, axis = 1): Durch Hinzufügen des Axis-Arguments betrachtet numpy die Zeilen und Spalten einzeln. axis = 1 bedeutet, dass die Operation über die Zeilen von small_y ausgeführt wird.
rollaxis takes the axis you specify, and moves it to a given position (default value is 0):