1. Transfer Learning: Grundlagen und Einsatz Gebiete

  • Transfer Learning ist ein Konzept aus dem Deep Learning, wo vortrainierte Modelle transferiert und in neuen Modellen zum Einsatz bringen
  • Unter Transfer-Learning versteht man das Übertragen der Ergebnisse eines fertig trainierten neuronalen Netzes auf eine neue Aufgabe

Das Training eines neuen neuronalen Netzes mit einer größen Anzahl von Daten ist rechnenintersiv und zeitaufwändig. Wenn man ein neues neuronales Netz trainieren möchte, kann es daher sinnvoll sein, mit der Hilfe von Transfer Learning auf den bereits gelernten Features eines fertig trainierten Netzes aufzubauen. Dabei werden z.B. die fertig trainierten Layer eines CNN’s übernommen und nur der Output-Layer wird auf die Anzahl der zu erkennenden Objektklassen des neuen Netzes angepasst und nachtrainiert (Fine-Tuning).

2. Methoden für Transfer Learning

  • Merkmahle-Extrahierung
  • Fine-Tuning

3. Transfer Learning mit ähnlichen Daten und kleinem Datensatz

Wenn die zu erkenneden Objekte änlichen Strukturen aufweisen (Hunde vs. Katze) und für die neue Aufgabe nur ein kleiner Datensazt zur Verfügung steht, kann man einfach den Output-Layer durch einen neuen ersetzen, dessen Neuronen-Anzahl mit dem Anzahl der neu zu erkennenden Klassen entspricht.

Alle andere Layern werden beibehalten und nicht weiter tranniert. Der neune Output-Layer wird mit zufällig gewählten Gewichten initialisiert un mit den neuen Datensazt traniert. Dabei durchlaufen erstmal

4. Transfer Learning mit unterschiedlichen Daten und kleinem Datensatz

3. Transfer Learning mit Merkmahle Extrahierung

import numpy as np
import tensorflow as tf
import os 
import glob
import argparse
import random
#from resnet import ResNet
import matplotlib.pyplot as plt
from tensorflow.keras.applications import ResNet50
from pysim import config
import importlib
importlib.reload(config)
import glob
import cv2
import shutil
from sklearn.preprocessing import LabelBinarizer, LabelEncoder
from sklearn.model_selection import train_test_split
import random
import pickle
from imutils import paths
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report
#from sklearn.linear_model import LogisticRegression
#from sklearn.metrics import classification_report

A. Datensatz Verzeichniss, Datensatz Verarbeitung

for split in (config.TRAIN, config.VAL, config.TEST):
    print("[INFO] processing '{} split'...".format(split))
    imagePaths = glob.glob(os.path.sep.join([config.ORIG_INPUT_DATASET, split, '*']))
    for imagePath in imagePaths[:96]:
        filename =  imagePath.split(os.path.sep)[-1]
        label = config.CLASSES[int(filename.split("_")[0])]
        #new directory path
        newPath = os.path.sep.join([config.BASE_PATH, split, label])
        # if directory doesn't exist than creat new
        if not os.path.exists(newPath):
            os.makedirs(newPath)
        newPathFile = os.path.sep.join([newPath, filename])
        shutil.copy2(imagePath, newPathFile)
[INFO] processing 'train split'...
[INFO] processing 'val split'...
[INFO] processing 'test split'...

B. Model laden

model = tf.keras.applications.VGG16(weights = "imagenet", include_top = False)
le = None

C. Markmahle extrahieren und speichern

  • Loop over all paths
  • Randommly shuffle paths
  • Construct csv files were features should be written
for split in (config.TRAIN, config.VAL, config.TEST):
        print("[INFO] processing '{} split'...".format(split))
        p = os.path.sep.join([config.BASE_PATH, split])
        imagePaths = list(paths.list_images(p))
        # random shuffle the image paths and extract class labels for the file path
        random.shuffle(imagePaths)
        labels = [p.split(os.path.sep)[-2] for p in imagePaths]
        if le is  None:
                le = LabelEncoder()
                le.fit(labels)
        cvsPath = os.path.sep.join([config.BASE_CSV_PATH, "{}.csv".format(split)]) 
        csv = open(cvsPath, "w")
        for (b, i) in enumerate(range(0, len(imagePaths), config.BATCH_SIZE)):
                    print("[INFO] processing batch {}/{}".format(b + 1,\
                                        int(np.ceil(len(imagePaths) / float(config.BATCH_SIZE)))))
                    batchPaths = imagePaths[i:i + config.BATCH_SIZE] 
                    batchLabels = le.fit_transform(labels[i:i + config.BATCH_SIZE])
                    batchImages = []
                    # loop over the images and labels in the current batch
                    for imagePath in batchPaths:
                    # load the input image using the Keras helper utility
                    # while ensuring the image is resized to 224x224 pixels
                        image = tf.keras.preprocessing.image.load_img(imagePath, target_size=(224, 224))
                        image = tf.keras.preprocessing.image.img_to_array(image)
                        # preprocess the image by (1) expanding the dimensions and
                        # (2) subtracting the mean RGB pixel intensity from the ImageNet dataset
                        image = np.expand_dims(image, axis=0)
                        image = tf.keras.applications.vgg16.preprocess_input(image)
                        # add the image to the batch
                        batchImages.append(image) 
                    # pass the images through the network and use the outputs a
                    # our actual features, then reshape the features into a flattened volume
                    batchImages = np.vstack(batchImages)
                    features = model.predict(batchImages, batch_size=config.BATCH_SIZE)
                    features = features.reshape((features.shape[0], 7 * 7 * 512))

                    # loop over the class labels and extracted features
                    for (label, vec) in zip(batchLabels, features):
                        # construct a row that exists of the class label and
                        # extracted features
                        vec = ",".join([str(v) for v in vec])
                        csv.write("{},{}\n".format(label, vec))
# close the CSV file
        csv.close()  
# serialize the label encoder to disk
f = open(config.LE_PATH, "wb")
f.write(pickle.dumps(le))
f.close() 
print("Done")
[INFO] processing 'train split'...
[INFO] processing batch 1/3
[INFO] processing batch 2/3
[INFO] processing batch 3/3
[INFO] processing 'val split'...
[INFO] processing batch 1/3
[INFO] processing batch 2/3
[INFO] processing batch 3/3
[INFO] processing 'test split'...
[INFO] processing batch 1/3
[INFO] processing batch 2/3
[INFO] processing batch 3/3
Done

D. CSV-Dateien mit gespeicherten Merkmahlen laden

trainingPath = os.path.sep.join([config.BASE_CSV_PATH,"{}.csv".format(config.TRAIN)])
testingPath = os.path.sep.join([config.BASE_CSV_PATH, "{}.csv".format(config.TEST)])
print(trainingPath, testingPath)
output/train.csv output/test.csv
def load_data_split(splitPath):
# initialize the data and labels
    data = []
    labels = []

# loop over the rows in the data split file
    for row in open(splitPath):
# extract the class label and features from the row
        row = row.strip().split(",")
        label = row[0]
        features = np.array(row[1:], dtype="float")

# update the data and label lists
        data.append(features)
        labels.append(label)

# convert the data and labels to NumPy arrays
    data = np.array(data)
    labels = np.array(labels)

# return a tuple of the data and labels
    return (data, labels)
trainingPath = os.path.sep.join([config.BASE_CSV_PATH,"{}.csv".format(config.TRAIN)])
testingPath = os.path.sep.join([config.BASE_CSV_PATH,"{}.csv".format(config.TEST)])
# load the data from disk
print("[INFO] loading data...")
(trainX, trainY) = load_data_split(trainingPath)
(testX, testY) = load_data_split(testingPath)

# load the label encoder from disk
le = pickle.loads(open(config.LE_PATH, "rb").read())
[INFO] loading data...

E. Modell für classification

print("[INFO] training model...")
model = LogisticRegression(solver="lbfgs", multi_class="auto",max_iter=150)
model.fit(trainX, trainY)

# evaluate the model
print("[INFO] evaluating...")
preds = model.predict(testX)
print(classification_report(testY, preds, target_names=le.classes_))

# serialize the model to disk
print("[INFO] saving model...")
f = open(config.MODEL_PATH, "wb")
f.write(pickle.dumps(model))
f.close()
[INFO] training model...
[INFO] evaluating...
              precision    recall  f1-score   support

        food       1.00      0.94      0.97        51
    non_food       0.94      1.00      0.97        45

    accuracy                           0.97        96
   macro avg       0.97      0.97      0.97        96
weighted avg       0.97      0.97      0.97        96

[INFO] saving model...