[PYTHON] Apprentissage parallèle du deep learning par Keras et Kubernetes

Apprentissage parallèle du deep learning par Keras et Kubernetes

J'ai écrit plus tôt que Keras prend en charge CNTK.

Exécutez Keras avec le backend CNTK à partir de CentOS

Keras peut désormais utiliser Theano, TensorFlow et CNTK comme backends pour utiliser différents frameworks dans le même programme. Je pense que l'avantage d'augmenter le backend de Keras est que vous pouvez changer le cadre et apprendre en changeant simplement les variables d'environnement. Changer le cadre ne changera (probablement) pas le modèle de réseau neuronal lui-même si le programme est le même, mais la précision et la vitesse changeront légèrement. Vous pouvez également regrouper et déduire les modèles entraînés dans chaque cadre. Je suis venu avec un ensemble de cadres multiples, donc je l'ai essayé.

Le programme et le yml de Kubernetes se trouvent ci-dessous. https://github.com/shibuiwilliam/keras_multibackend

Apprenez plusieurs backends Keras en parallèle

C'est ennuyeux d'essayer plusieurs frameworks d'apprentissage profond séquentiellement à partir de Keras avec le même programme, j'ai donc essayé de former chaque framework en parallèle à l'aide de Kubernetes. L'image est la suivante.

C'est ennuyeux d'apprendre séquentiellement. 20.png

Apprenons en parallèle. 21.png

Vue d'ensemble

Laissez Kubernetes apprendre l'apprentissage en profondeur en parallèle sur un conteneur Docker. L'image globale est la suivante.

22.png

Des configurations de plate-forme et de programme sont requises.

Plate-forme

Préparez trois machines virtuelles. Cette fois, il s'agit de CentOS 7.3. Faites de VM1 un serveur NFS et montez le répertoire partagé sur VM2 et VM3. Placez les programmes d'apprentissage et d'inférence Keras dans le répertoire partagé. Les VM 1, 2 et 3 pourront toutes accéder aux programmes d'apprentissage et d'inférence Keras.

Formez un cluster Kubernetes avec VM1,2,3. Générez VM1,2,3 avec Keras, Theano, TensorFlow, CNTK et d'autres images Docker installées.

Le Dockerfile utilisé cette fois est ci-dessous.

https://github.com/shibuiwilliam/keras_multibackend

Kubernetes effectue une formation CNN Cifar 10 par chaque framework en tant que travail. Nous préparerons 3 types de yml pour Job. Définissez les valeurs de chaque variable d'environnement KERAS_BACKEND comme Theano, TensorFlow et CNTK.

La définition de Job yml de Kubernetes est la suivante. Tout d'abord, c'est pour apprendre. Bien que CNTK soit illustré, Tensorflow et Theano ne modifient que la valeur de Keras_Backend.

apiVersion: batch/v1
kind: Job
metadata:
  name: kerascntk
spec:
  template:
    spec:
      restartPolicy: Never
      volumes:
        - name: nfstest
          nfs:
            server: 10.249.20.65
            path: "/tmp/nfstest/"
      containers:
        - name: kerascntk
          image: jupyter:1.52
          volumeMounts:
              - name: nfstest
                mountPath: "/tmp/nfstest/"
          env:
              - name: KERAS_BACKEND
                value: "cntk"
          command: ["python"]
          args: ["/tmp/nfstest/cifar_train.py"]

Pour inférence. L'inférence est additionnée avec 3 inférences backend en Python, vous n'en avez donc besoin que d'une ci-dessous.

apiVersion: batch/v1
kind: Job
metadata:
  name: pred
spec:
  template:
    spec:
      restartPolicy: Never
      volumes:
        - name: nfstest
          nfs:
            server: 10.249.20.65
            path: "/tmp/nfstest/"
      containers:
        - name: pred
          image: jupyter:1.52
          volumeMounts:
              - name: nfstest
                mountPath: "/tmp/nfstest/"
          command: ["python"]
          args: ["/tmp/nfstest/cifar_pred.py"]

programme

Préparez un programme d'apprentissage Keras et un programme d'inférence. Il n'est pas nécessaire de créer chaque cadre séparément. Étant donné que la variable d'environnement KERAS_BACKEND est définie et divisée en yml de Kubernetes Job, il existe un programme pour l'apprentissage et un pour l'inférence.

Chaque programme est le suivant. Tout d'abord, c'est pour apprendre. Je n'ai fait aucun effort particulier. C'est un CNN ordinaire de type VGG. Le nombre d'époques est de 50, mais comme l'arrêt anticipé est également défini, il est censé se terminer dans environ 20 époques. En outre, 100 images de données de test sont exclues de l'évaluation pour une utilisation en inférence.


#Pour apprendre

# see its environment variable
import os
kerasBKED = os.environ["KERAS_BACKEND"]
print(kerasBKED)

# imports
import keras
from keras.models import load_model
from keras.datasets import cifar10
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.callbacks import EarlyStopping, ModelCheckpoint
import pickle
import numpy as np

# variables
batch_size = 32
num_classes = 10
epochs = 50

# loading and reshaping cifar10 data
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255

# leave out 100 images for prediction
x_test1 = x_test[100:,:]
x_test2 = x_test[:100,:]
y_test1 = y_test[100:,:]
y_test2 = y_test[:100,:]
print(x_test1.shape, x_test2.shape, y_test1.shape, y_test2.shape)
# only test1 data is used for validation

# VGG-like neural network model
model = Sequential()
model.add(Conv2D(32, (3, 3), padding='same',
                 input_shape=x_train.shape[1:]))
model.add(Activation('relu'))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes))
model.add(Activation('softmax'))

opt = keras.optimizers.adam()

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


# Add checkpoint and earlystopping
chkpt = '/tmp/nfstest/cifar_weights/' + kerasBKED + '_weights.{epoch:02d}-{loss:.2f}-{val_loss:.2f}.hdf5'
cp_cb = ModelCheckpoint(filepath = chkpt, monitor='val_loss', verbose=1, save_best_only=True, mode='auto')
es_cb = EarlyStopping(monitor='val_loss', patience=1, verbose=1, mode='auto')

# fit the model
history = model.fit(x_train, y_train,
                    batch_size=batch_size,
                    epochs=epochs,
                    verbose=1,
                    validation_data=(x_test1, y_test1),
                    callbacks=[cp_cb, es_cb],
                    shuffle=True)

# score and save the model
score = model.evaluate(x_test1, y_test1, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

saveDir = "/tmp/nfstest/cifar_model/"
if not os.path.isdir(saveDir):
    os.makedirs(saveDir)
modelName = "{0}_{1}_model.hdf5".format(kerasBKED, score[1])
model_path = os.path.join(saveDir, modelName)
model.save(model_path)

À la fin de la formation, enregistrez le modèle dans le répertoire NFS. Par conséquent, trois types de modèles sont stockés dans le répertoire NFS. L'inférence utilise ces trois modèles. Pour l'inférence, utilisez 100 images extraites des données de test. Inférer en appelant les trois types de fichiers de modèle (Theano, Tensorflow, CNTK) créés par apprentissage. Puisqu'il y a une différence dans la précision de l'entraînement dans chaque modèle, l'inférence est multipliée par la précision et finalement divisée par la somme de la précision. Cela ressemble à un modèle d'ensemble, mais il n'a aucun support théorique.


#Pour raisonner

# import
import keras
from keras.models import load_model
from keras.datasets import cifar10
import os

# variables
batch_size = 32
num_classes = 10

# load and reshape data
(x_train, y_train), (x_test, y_test) = cifar10.load_data()

y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255

x_test1 = x_test[100:,:]
x_test2 = x_test[:100,:]
y_test1 = y_test[100:,:]
y_test2 = y_test[:100,:]
# test2 data is used for prediction

# get a list of model files
backList = ["cntk", "tensorflow", "theano"]
saveDir = "/tmp/nfstest/cifar_model/"
files = os.listdir(saveDir)
filesList = [f for f in files if os.path.isfile(os.path.join(saveDir, f))]
filesList

# predict using each model
prediction = 0
sumAcc = 0
for bk in backList:
    os.environ["KERAS_BACKEND"] = bk
    kerasBKED = os.environ["KERAS_BACKEND"]
    modelName = [m for m in filesList if bk in m][0]
    modelAcc = float(modelName.split("_")[1])
    print("MODELNAME {0} \t for BACKEND {1} \t with ACCURACY {2}".format(modelName, kerasBKED, modelAcc))
    model = load_model(os.path.join(saveDir, modelName))
    prediction += model.predict(x_test2, batch_size=batch_size, verbose=0) * modelAcc
    sumAcc += modelAcc
prediction = prediction / sumAcc
print(prediction)

# output predictions to csv
import csv
with open("/tmp/nfstest/cifar_model/preds.csv", 'w') as f:
    writer = csv.writer(f, lineterminator='\n')
    writer.writerows(prediction)


predlist = []
for i in prediction:
    pred = max(enumerate(i), key=lambda x: x[1])[0]
    predlist.append([pred, i[pred]])
print(predlist)


# output overall summary to csv
import csv
with open("/tmp/nfstest/cifar_model/pred.csv", 'w') as f:
    writer = csv.writer(f, lineterminator='\n')
    writer.writerow(predlist)


Le résultat d'essayer

Lors de l'apprentissage, les trois cadres se sont installés sur presque la même précision.

Backend Accuracy Loss
Theano 0.785 0.62
TensorFlow 0.772 0.63
CNTK 0.771 0.67

C'est naturel parce que nous apprenons avec le même réseau neuronal.

Cependant, en ce qui concerne le raisonnement, il y a une légère différence dans le back-end. Vous trouverez ci-dessous une liste de 10 données de test déduites par chaque backend. (Dans le programme ci-dessus, nous déduisons à partir de 100 données d'image, mais comme c'est trop, nous le limiterons à 10.) Pour les premières données d'image, CNTK en déduit 4 à 49,498%, tandis que Tensorflow et Theano en déduisent 3 à 55,225% et 67,820%, respectivement. En multipliant l'inférence et la précision de chaque backend et en les divisant par le total de la précision, on en déduit que 3 est 57,855%. La réponse correcte pour chaque donnée d'image est répertoriée comme réponse à gauche de l'ensemble.


\frac{0.49498 * 0.771 + 0.55225 * 0.772 + 0.67820 * 0.785}{0.771 + 0.772 + 0.785} \\
= 0.57855

Les secondes données d'image sont 8 pour CNTK, Tensorflow et Theano. Cependant, dans les troisièmes données, CNTK est de 0 à 41,421%, Tensorflow de 8 à 72,917% et Theano de 1 à 52,288%.

data backends 0 1 2 3 4 5 6 7 8 9
1 cntk 0.039% 0.053% 2.518% 11.623% 49.498% 6.068% 4.404% 2.736% 0.075% 0.108%
tensorflow 0.049% 0.002% 0.289% 55.225% 0.055% 20.520% 0.399% 0.143% 0.495% 0.015%
theano 0.002% 0.005% 0.028% 67.820% 0.068% 3.543% 6.598% 0.017% 0.027% 0.347%
answer:3 ensemble 0.039% 0.026% 1.218% 57.855% 21.318% 12.945% 4.898% 1.244% 0.257% 0.202%
2 cntk 19.015% 6.447% 0.027% 0.125% 0.007% 0.001% 0.001% 0.004% 51.443% 0.052%
tensorflow 0.000% 0.019% 0.000% 0.000% 0.000% 0.000% 0.000% 0.000% 77.173% 0.000%
theano 0.045% 2.147% 0.000% 0.000% 0.000% 0.000% 0.000% 0.000% 76.233% 0.030%
answer:8 ensemble 8.188% 3.700% 0.012% 0.053% 0.003% 0.000% 0.000% 0.002% 88.006% 0.035%
3 cntk 41.421% 2.234% 0.902% 0.223% 1.573% 0.006% 0.062% 0.070% 21.528% 9.104%
tensorflow 1.056% 3.040% 0.000% 0.028% 0.000% 0.000% 0.002% 0.000% 72.917% 0.147%
theano 0.356% 52.288% 0.012% 0.305% 0.005% 0.000% 0.001% 0.001% 23.977% 1.508%
answer:8 ensemble 18.402% 24.729% 0.393% 0.239% 0.678% 0.003% 0.028% 0.031% 50.876% 4.622%
4 cntk 44.158% 6.019% 1.613% 4.033% 1.339% 0.091% 0.133% 0.150% 11.250% 8.334%
tensorflow 68.420% 0.740% 0.175% 0.296% 0.010% 0.004% 0.029% 0.006% 6.932% 0.580%
theano 37.302% 2.057% 0.594% 2.029% 0.348% 0.086% 0.043% 0.029% 33.511% 2.455%
answer:0 ensemble 64.391% 3.788% 1.023% 2.731% 0.729% 0.078% 0.088% 0.079% 22.208% 4.884%
5 cntk 0.005% 0.001% 27.413% 1.284% 8.657% 0.023% 39.720% 0.001% 0.017% 0.001%
tensorflow 0.000% 0.000% 0.020% 0.884% 71.491% 0.001% 4.796% 0.000% 0.000% 0.000%
theano 0.000% 0.000% 2.550% 0.190% 1.722% 0.000% 73.993% 0.000% 0.000% 0.000%
answer:6 ensemble 0.002% 0.000% 12.881% 1.013% 35.172% 0.011% 50.913% 0.000% 0.007% 0.000%
6 cntk 0.001% 0.000% 3.774% 23.424% 8.258% 0.708% 40.913% 0.036% 0.001% 0.005%
tensorflow 0.002% 0.000% 0.401% 41.210% 1.115% 4.864% 29.589% 0.006% 0.004% 0.001%
theano 0.000% 0.000% 0.009% 0.263% 0.005% 0.072% 78.107% 0.000% 0.000% 0.000%
answer:6 ensemble 0.001% 0.000% 1.797% 27.881% 4.029% 2.425% 63.844% 0.018% 0.002% 0.003%
7 cntk 3.350% 0.113% 14.258% 12.193% 0.190% 4.802% 0.295% 41.802% 0.021% 0.097%
tensorflow 0.048% 41.460% 0.462% 9.073% 0.000% 0.737% 0.079% 0.602% 0.044% 24.686%
theano 0.008% 49.193% 0.053% 2.381% 0.001% 0.065% 0.183% 0.015% 0.024% 26.531%
answer:1 ensemble 1.463% 38.994% 6.347% 10.159% 0.082% 2.408% 0.240% 18.224% 0.038% 22.045%
8 cntk 0.014% 0.001% 14.742% 5.123% 42.021% 0.048% 15.141% 0.020% 0.008% 0.004%
tensorflow 0.108% 0.000% 9.300% 6.686% 31.076% 0.310% 29.625% 0.072% 0.008% 0.007%
theano 0.023% 0.000% 33.777% 0.185% 1.431% 0.096% 42.927% 0.013% 0.002% 0.000%
answer:6 ensemble 0.062% 0.000% 24.840% 5.153% 32.018% 0.195% 37.674% 0.046% 0.007% 0.005%
9 cntk 0.005% 0.000% 4.104% 43.597% 17.353% 5.953% 5.485% 0.624% 0.000% 0.001%
tensorflow 0.000% 0.000% 0.067% 70.856% 2.242% 3.932% 0.091% 0.004% 0.000% 0.000%
theano 0.000% 0.000% 0.001% 78.418% 0.011% 0.021% 0.002% 0.003% 0.000% 0.000%
answer:3 ensemble 0.002% 0.000% 1.792% 82.860% 8.423% 4.256% 2.396% 0.271% 0.000% 0.000%
10 cntk 8.810% 7.715% 8.225% 13.706% 6.575% 3.413% 8.631% 4.522% 5.751% 9.773%
tensorflow 0.482% 68.974% 0.012% 0.014% 0.001% 0.001% 0.213% 0.000% 4.088% 3.405%
theano 0.480% 48.363% 0.000% 0.000% 0.000% 0.000% 0.000% 0.000% 3.134% 26.477%
answer:1 ensemble 4.199% 53.724% 3.539% 5.895% 2.825% 1.467% 3.799% 1.943% 5.574% 17.036%

Ce qui est intéressant à regarder, c'est que même si les backends individuels sont incorrects, l'ensemble sera correct. Par exemple, dans l'image 3, CNTK, Tensorflow et Theano font des inférences séparées, mais Tensorflow déduit 8 avec la probabilité la plus élevée, donc l'ensemble est également 8.

Résumé

Dans la phase d'apprentissage, les deux backends étaient tout aussi précis. Cependant, si vous essayez de déduire, chacun peut donner des résultats différents. Un autre ensemble semble donner la bonne réponse avec une plus grande précision que l'inférence avec un seul backend.

Nous avons réussi un apprentissage parallèle avec Kubernetes. Kubernetes Job exécute le programme spécifié dans le cluster, ce qui est très pratique. Kubernetes dispose également d'un Cron Job, qui semble être capable d'exécuter des Jobs de manière chronométrée. Lors de la planification d'une étude d'apprentissage en profondeur, je trouve utile de l'automatiser avec Cron Job de Kubernetes. Donc, la prochaine fois, je vérifierai l'exécution automatique de l'apprentissage profond par Kubernetes Cron Job.

Recommended Posts

Apprentissage parallèle du deep learning par Keras et Kubernetes
Signification des modèles et paramètres d'apprentissage en profondeur
Détection d'objets par apprentissage profond pour comprendre en profondeur par Keras
Chainer et deep learning appris par approximation de fonction
Un mémorandum d'étude et de mise en œuvre du Deep Learning
Apprentissage profond appris par mise en œuvre (segmentation) ~ Mise en œuvre de SegNet ~
Analyse d'images par apprentissage profond à partir de Kaggle et Keras
Classer les visages d'anime par suite / apprentissage profond avec Keras
Bibliothèque DNN (Deep Learning): Comparaison de chainer et TensorFlow (1)
Collecte et automatisation d'images érotiques à l'aide du deep learning
Deep running 2 Réglage de l'apprentissage profond
Apprentissage par renforcement profond 2 Mise en œuvre de l'apprentissage par renforcement
[Pour les débutants en apprentissage profond] Implémentation d'une classification binaire simple par couplage complet à l'aide de Keras
[Deep Learning from scratch] Implémentation de la méthode Momentum et de la méthode AdaGrad
Compréhension de base de l'estimation de la profondeur par caméra mono (Deep Learning)
Importance de l'apprentissage automatique et de l'apprentissage par mini-lots
Organisez des plateformes d'apprentissage automatique et d'apprentissage en profondeur
Apprentissage profond appris par l'implémentation 1 (édition de retour)
Deep learning 2 appris par l'implémentation (classification d'images)
Graphique de l'historique du nombre de couches de deep learning et du changement de précision
[Mémo d'apprentissage] Bases de la classe par python
Othello-De la troisième ligne de "Implementation Deep Learning" (3)
Introduction au Deep Learning ~ Pliage et mise en commun ~
Produisez de belles vaches de mer par apprentissage profond
Essayez l'apprentissage profond de la génomique avec Kipoi
Visualisez les effets de l'apprentissage profond / de la régularisation
Analyse émotionnelle des tweets avec apprentissage en profondeur
J'ai essayé de classer Oba Hanana et Otani Emiri par apprentissage profond
L'apprentissage en profondeur
Enregistrement d'apprentissage de la lecture "Deep Learning from scratch"
Informer Slack de la manière dont Keras apprend
Examen de la méthode de prévision des échanges utilisant le Deep Learning et la conversion en ondelettes
Othello-De la troisième ligne de "Implementation Deep Learning" (2)
[Pour les débutants en intelligence artificielle] Parcours d'apprentissage et de référence en apprentissage automatique / programmation en profondeur
Prédire les travaux de courte durée de Weekly Shonen Jump par apprentissage automatique (Partie 2: Apprentissage et évaluation)
J'ai essayé de classer Hanana Oba et Emiri Otani par apprentissage profond (partie 2)
L'histoire de l'apprentissage profond avec TPU
Apprentissage profond / rétropropagation d'erreur de la fonction sigmoïde
Tournoi Numerai - Fusion de quants traditionnels et apprentissage automatique -
Apprentissage profond appris par la mise en œuvre ~ Détection d'anomalies (apprentissage sans enseignant) ~
[Mémo d'apprentissage] Apprentissage profond à partir de zéro ~ Mise en œuvre de l'abandon ~
Approximation de bas rang des images par HOSVD et HOOI
Compréhension de base de l'estimation de la profondeur stéréo (Deep Learning)
Développez et gonflez votre propre ensemble de données Deep Learning
Interpolation d'images vidéo par apprentissage en profondeur, partie 1 [Python]
Calcul des indicateurs techniques par TA-Lib et pandas
Amélioration de la metrix de performance par modèle d'apprentissage en 2 étapes
Introduction à l'apprentissage profond ~ Fonction de localisation et de perte ~
Analyse de l'utilisation de l'espace partagé par l'apprentissage automatique
[Français] scikit-learn 0.18 Introduction de l'apprentissage automatique par le didacticiel scikit-learn
Estimation raisonnable du prix de Mercari par apprentissage automatique
Classification des images de guitare par apprentissage automatique, partie 2
Implémentation du modèle Deep Learning pour la reconnaissance d'images
À propos des copies superficielles et profondes de Python / Ruby
Déterminez s'il s'agit de mon enfant à partir de l'image du chien Shiba par apprentissage profond (4) Visualisation par Grad-CAM et Grad-CAM guidé
Feuille de route d'apprentissage et livres recommandés enseignés par les étudiants OB du Département des Systèmes d'Information ~ N ° 2 ~
Mémorandum d'apprentissage profond
Commencer l'apprentissage en profondeur
Python vs Ruby "Deep Learning from scratch" Chapitre 1 Graphique de la fonction sin et de la fonction cos