angle-uparrow-clockwisearrow-counterclockwisearrow-down-uparrow-leftatcalendarcard-listchatcheckenvelopefolderhouseinfo-circlepencilpeoplepersonperson-fillperson-plusphoneplusquestion-circlesearchtagtrashx

Prédiction des valeurs à l'aide de Deep Learning et de Keras

En utilisant Keras, nous pouvons créer une boîte noire Deep Learning capable de prédire les valeurs futures.

28 janvier 2022
post main image

J'ai un ensemble de données, de nombreuses lignes avec N entrées et 1 sortie, et je veux prédire la valeur de sortie pour toute nouvelle combinaison de valeurs d'entrée. Je suis également un noob de la science des données, mais les histoires sur Internet sur Deep Learning suggèrent que nous pouvons facilement créer une sorte de boîte noire avec quelques neurones, des nœuds, en elle, puis utiliser l'ensemble de données pour former la boîte noire. Après cela, nous pouvons introduire n'importe quelle entrée et notre boîte noire nous donne des valeurs de sortie avec une certaine marge d'erreur. Cela semble trop beau pour être vrai ? Est-ce vraiment si facile ?

Commencez par KISS (Keep It Simple Stupid)

Lorsque vous recherchez sur Internet "python data prediction", vous obtenez bien sûr de nombreux résultats. Il y a de nombreux exemples que j'aime bien, mais la plupart sont beaucoup trop complexes pour un débutant. Prédire le prix des actions en utilisant des séries temporelles, trop complexe. Prédire le prix des maisons, beaucoup mieux. Il y a aussi un jeu de données sur la qualité du vin. J'aime le vin. Ça peut être bien, peut-être une autre fois.

Dans ce post, j'essaie de résoudre un problème trivial. Je remplace la fonction :

y = x0 + 2*x1

par :

  • un modèle de Régression Linéaire, et,
  • un Deep Learning, en fait un réseau neuronal, une boîte noire.

Un avantage énorme est que je peux générer moi-même l'ensemble de données. Cela signifie également que je peux comparer les prédictions aux valeurs attendues.

Machine Learning : Régression vs classification

Pour choisir le bon algorithme, il est important de savoir si la tâche Machine Learning est un problème de régression ou de classification. La régression et la classification sont deux types d'algorithmes Supervised Machine Learning . Supervised Machine Learning utilise le concept d'utilisation d'ensembles de données avec des valeurs de sortie connues pour faire des prédictions.

La régression est un algorithme qui peut être entraîné avec un ensemble de données pour prédire les sorties qui sont des valeurs numériques, des nombres. La qualification Class est un algorithme qui peut être entraîné avec un ensemble de données pour prédire les sorties qui sont des étiquettes, des catégories, généralement des 0 et des 1.

Exemple de régression

Nous avons un ensemble de données composé de lignes avec 2 entrées et une sortie de 1, la valeur de sortie est un nombre qui peut avoir n'importe quelle valeur. Prenons l'exemple d'un ensemble de données sur le logement, dont les entrées sont le nombre de personnes pouvant vivre dans la maison et le nombre de pièces, et dont la sortie est le prix.

 persons | rooms | price
---------+-------+--------
  5      |  4    | 20.000
  3      |  2    | 24.000

Si nous disposons d'un ensemble de données suffisamment grand, nous pouvons utiliser un algorithme de régression pour prédire le prix pour toute combinaison de personnes et de pièces. La sortie sera 22.500, 18.100 etc.

Exemple de Classification

Nous disposons d'un ensemble de données composé de lignes avec 3 entrées et 1 sortie, la valeur de sortie étant un nombre égal à 0 ou 1. Considérons un ensemble de données sur le logement où les entrées sont le nombre de personnes pouvant vivre dans la maison, le nombre de pièces, le prix, et la sortie est 0 ou 1 selon que la maison est favorisée, aimée, par les personnes recherchant une maison sur un site Web.

 persons | rooms | price   | liked
---------+-------+---------+--------
  5      |  4    | 20.000  | 0
  3      |  2    | 24.000  | 1

Si nous disposons d'un ensemble de données suffisamment important, nous pouvons utiliser un algorithme de classification pour prédire si une maison est appréciée pour toute combinaison de personnes, de pièces et de prix. Le résultat sera 0 (pas aimé) ou 1 (aimé).

Sous-assignation et sur-assignation

Notre ensemble de données est divisé en un ensemble de données de formation et un ensemble de données de test. Ces deux ensembles de données nous permettent de déterminer la qualité des performances de notre modèle ou algorithme.

Un sous-ajustement signifie que le modèle n'a pas été en mesure de déterminer les relations pertinentes entre les données. Il est probable que le modèle soit trop simple. Par exemple, on peut essayer de représenter des relations non linéaires avec un modèle linéaire.

Sous-adaptation :

  • Fonctionne mal avec les données de formation
  • Fonctionne mal avec les données de test

L'overfitting signifie que le modèle a également déterminé les relations entre les données et les fluctuations aléatoires. Le modèle est probablement trop complexe, il apprend trop bien.

Sur-ajustement :

  • Fonctionne bien avec les données d'apprentissage
  • Fonctionne mal avec les données de test

Les deux cas peuvent également se produire lorsque l'ensemble de données est insuffisant.

Régression linéaire

Je vous suggère de lire les exemples dans l'excellent tutoriel 'Linear Regression in Python', voir les liens ci-dessous. Ci-dessous, je montre ma version avec deux entrées, des données de formation et de test, et la prédiction d'une valeur. Comme nous modélisons avec la régression linéaire, il n'est pas surprenant que le coefficient de détermination soit de 1,0 et que nous n'ayons besoin que d'une très petite quantité de données d'apprentissage.

# Linear regression: y = x0 + 2*x1
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split

# generate dataset
X_items = []
y_items = []
for x0 in range(0, 3):
    for x1 in range(3, 5):
        y = x0 + 2*x1
        X_items.append([x0, x1])
        y_items.append(y)

X = np.array(X_items).reshape((-1, 2))
y = np.array(y_items)
print('X = {}'.format(X))
print('y = {}'.format(y))

# split dataset in training and test data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1)
print('X_train = {}'.format(X_train))
print('y_train = {}'.format(y_train))
print('X_test = {}'.format(X_test))
print('y_test = {}'.format(y_test))

# create model
model = LinearRegression()

# mess up a training value
#X_train[0][0] += 2

# calculate optimal values of weights b0 and b1
model.fit(X_train, y_train)

# show results, mess up test data
print('model result:')
print('- intercept (b0) = {}'.format(model.intercept_))
print('- slope (b1) = {}'.format(model.coef_))
print('- coefficient of determination for training data = {}'.
    format(model.score(X_train, y_train)))
print('- coefficient of determination for test data = {}'.
    format(model.score(X_test, y_test)))

x = np.array([8, 9]).reshape((-1, 2))
y_pred = model.predict(x)
print('predicted response for x = {}: {}'.format(x, y_pred))

Le script donne le résultat suivant :

X = [[0 3]
 [0 4]
 [1 3]
 [1 4]
 [2 3]
 [2 4]]
y = [ 6  8  7  9  8 10]
X_train = [[2 3]
 [0 3]
 [1 4]
 [2 4]]
y_train = [ 8  6  9 10]
X_test = [[1 3]
 [0 4]]
y_test = [7 8]
model result:
- intercept (b0) = -3.552713678800501e-15
- slope (b1) = [1. 2.]
- coefficient of determination for training data = 1.0
- coefficient of determination for test data = 1.0
predicted response for x = [[8 9]]: [26.]

Pour créer un peu d'ennui, j'ai changé une valeur d'entraînement, voir ci-dessus. Cela donne le résultat suivant :

model result:
- intercept (b0) = -2.3529411764705817
- slope (b1) = [0.52941176 2.76470588]
- coefficient of determination for training data = 0.9865546218487395
- coefficient of determination for test data = -0.5570934256055304
predicted response for x = [[8 9]]: [26.76470588]

En ajoutant une plus grande quantité de données d'entraînement, nous obtenons un meilleur ajustement.

Deep Learning avec Keras

Cette approche ressemble davantage à celle de la boîte noire. Je n'ai qu'à ajouter quelques neurones et quelques couches et c'est tout. Mais est-ce vraiment le cas ? J'utilise ici Keras parce qu'il semble être très populaire. L'exemple suivant m'a été très utile : Keras 101: A simple (and interpretable) Neural Network model for House Pricing regression ", voir les liens ci-dessous. Le tracé de la perte et de l'erreur moyenne était très logique.

Nous allons suivre les étapes suivantes :

  • Charger les données
  • Définir le modèle
  • Compiler le modèle
  • Entraîner (ajuster) le modèle
  • Évaluation du modèle
  • Faire des prédictions

Charger les données Ici, nous générons les données nous-mêmes, voir aussi ci-dessus.

Définir le modèle La première couche dense a besoin du jeu de paramètres input_shape . J'ai commencé avec 100 neurones dans la première couche, 50 dans la deuxième couche, 25 dans la troisième. Pourquoi ? Je n'en ai aucune idée, je n'ai pas encore cherché à le savoir.

Compiler le modèle Pas grand chose à dire à ce sujet.

Entraîner (ajuster) le modèle Nous utilisons le paramètre validation_split, sans lui nous ne pouvons pas tracer. Lorsque validation_split est spécifié, une partie des données d'entraînement est utilisée pour la validation. Les données utilisées pour la validation pendant l'ajustement peuvent changer, il est probablement préférable d'utiliser des données fixes, sinon on obtient un ajustement différent à chaque fois.

Évaluer le modèle Nous utilisons ici les données de test.

Prédictions Utilisez simplement model.predict().

Bien sûr, nous avons besoin de plus de données d'entraînement ici. Mais pas vraiment beaucoup plus. J'ai également ajouté du code pour sauvegarder et charger le modèle. Voici le code que j'ai créé.

# Keras deep learning: y = x0 + 2*x1
from keras.models import Sequential, load_model
from keras.layers import Dense
import numpy as np
from plotly.subplots import make_subplots
import plotly.graph_objects as go
from sklearn.model_selection import train_test_split

use_saved_model = False
#use_saved_model = True

# create dataset
def fx(x0, x1):
    return x0 + 2*x1

X_items = []
y_items = []
for x0 in range(0, 18, 3):
    for x1 in range(2, 27, 3):
        y = fx(x0, x1)
        X_items.append([x0, x1])
        y_items.append(y)

X = np.array(X_items).reshape((-1, 2))
y = np.array(y_items)
print('X = {}'.format(X))
print('y = {}'.format(y))
X_data_shape = X.shape
print('X_data_shape = {}'.format(X_data_shape))

class DLM:
    
    def __init__(
        self,
        model_name='default_model',
    ):
        self.model_name = model_name
        self.dense_input_shape=(2, )
        self.dense_neurons = [100, 50, 25]
        self.fit_params = {
            'epochs': 100, 
            'validation_split': 0.1, 
            'verbose': 0,
        }

    def data_split_train_test(
        self,
        X,
        y,
    ):
        self.X_train, self.X_test, self.y_train, self.y_test = train_test_split(X, y, test_size=0.3, random_state=1)
        print('self.X_train = {}'.format(self.X_train))
        print('self.X_test = {}'.format(self.X_test))
        print('self.y_train = {}'.format(self.y_train))
        print('self.y_test = {}'.format(self.y_test))

        print('training data row count = {}'.format(len(self.y_train)))
        print('test data row count = {}'.format(len(self.y_test)))

        X_train_data_shape = self.X_train.shape
        print('X_train_data_shape = {}'.format(X_train_data_shape))

    def get_model(
        self,
    ):
        self.model = Sequential()
        self.model.add(Dense(self.dense_neurons[0], input_shape=self.dense_input_shape, activation='relu', name='dense_input'))
        for i, n in enumerate(self.dense_neurons[1:]):
            self.model.add(Dense(n, activation='relu', name='dense_hidden_' + str(i)))
        self.model.add(Dense(1, activation='linear', name='dense_output'))
        self.model.compile(optimizer='adam', loss='mse', metrics=['mean_absolute_error'])
        self.model_summary()
        return self.model

    def model_summary(
        self,
    ):
        self.model.summary()

    def train(
        self, 
        model,
        plot=False,
    ):
        history = model.fit(self.X_train, self.y_train, **self.fit_params)

        if plot:

            fig = go.Figure()
            fig.add_trace(go.Scattergl(y=history.history['loss'], name='Train'))
            fig.add_trace(go.Scattergl(y=history.history['val_loss'], name='Valid'))
            fig.update_layout(height=500, width=700, xaxis_title='Epoch', yaxis_title='Loss')
            fig.show()

            fig = go.Figure()
            fig.add_trace(go.Scattergl(y=history.history['mean_absolute_error'], name='Train'))
            fig.add_trace(go.Scattergl(y=history.history['val_mean_absolute_error'], name='Valid'))
            fig.update_layout(height=500, width=700, xaxis_title='Epoch', yaxis_title='Mean Absolute Error')
            fig.show() 

        return history

    def evaluate(
        self, 
        model,
    ):
        mse_nn, mae_nn = model.evaluate(self.X_test, self.y_test)
        print('Mean squared error on test data: ', mse_nn)
        print('Mean absolute error on test data: ', mae_nn)
        return mse_nn, mae_nn

    def predict(
        self,
        model,
        x0,
        x1,
        fx=None,
    ):
        x = np.array([[x0, x1]]).reshape((-1, 2))
        predictions = model.predict(x)
        expected = ''
        if fx is not None:
            expected = ', expected = {}'.format(fx(x0, x1))
        print('for x = {}, predictions = {}{}'.format(x, predictions, expected))
        return predictions

    def save_model(
        self,
        model,
    ):
        model.save(self.model_name)

    def load_saved_model(
        self,
    ):
        self.model = load_model(self.model_name)
        return self.model

# create & save or used saved
dlm = DLM()
if use_saved_model:
    model = dlm.load_saved_model()    
else:
    dlm.data_split_train_test(X, y)
    model = dlm.get_model()
    dlm.train(model, plot=True)
    dlm.evaluate(model)
    dlm.save_model(model)

# predict
dlm.predict(model, 4, 17, fx=fx)
dlm.predict(model, 23, 79, fx=fx)
dlm.predict(model, 40, 33, fx=fx)

Le script donne la sortie suivante, sans les données d'entrée :

training data row count = 37
test data row count = 17
X_train_data_shape = (37, 2)
2022-01-28 16:00:30.598860: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcuda.so.1'; dlerror: libcuda.so.1: cannot open shared object file: No such file or directory
2022-01-28 16:00:30.598886: W tensorflow/stream_executor/cuda/cuda_driver.cc:269] failed call to cuInit: UNKNOWN ERROR (303)
2022-01-28 16:00:30.598911: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:156] kernel driver does not appear to be running on this host (myra): /proc/driver/nvidia/version does not exist
2022-01-28 16:00:30.599110: I tensorflow/core/platform/cpu_feature_guard.cc:151] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense_input (Dense)         (None, 100)               300       
                                                                 
 dense_hidden_0 (Dense)      (None, 50)                5050      
                                                                 
 dense_hidden_1 (Dense)      (None, 25)                1275      
                                                                 
 dense_output (Dense)        (None, 1)                 26        
                                                                 
=================================================================
Total params: 6,651
Trainable params: 6,651
Non-trainable params: 0
_________________________________________________________________
1/1 [==============================] - 0s 25ms/step - loss: 0.1018 - mean_absolute_error: 0.2752
Mean squared error on test data:  0.10178931057453156
Mean absolute error on test data:  0.27519676089286804
2022-01-28 16:00:33.549267: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
for x = [[ 4 17]], predictions = [[38.0433]], expected = 38
for x = [[23 79]], predictions = [[177.94098]], expected = 181
for x = [[40 33]], predictions = [[103.54724]], expected = 106

Amélioration des performances de Deep Learning

En écrivant ce post, j'ai changé le nombre de neurones, les couches denses, le paramètre validation_split. Tout cela a entraîné des changements, parfois bons, parfois mauvais. La plus grande amélioration est sans aucun doute d'ajouter plus de données d'entraînement, mais quelle quantité est suffisante ?

Résumé

La chose la plus importante que j'ai apprise est que Deep Learning nécessite un grand ensemble de données, le plus grand étant le meilleur. Est-ce que j'aime la boîte noire ? Oui, et jusqu'à présent je n'ai pas vraiment regardé à l'intérieur. Je peux maintenant l'utiliser comme point de départ pour des projets concrets. Il y a aussi des choses comme la normalisation des entrées, l'ajout de poids aux entrées. Beaucoup d'autres choses à lire...

Liens / crédits

How to find the value for Keras input_shape/input_dim?
https://www.machinecurve.com/index.php/2020/04/05/how-to-find-the-value-for-keras-input_shape-input_dim

Keras 101: A simple (and interpretable) Neural Network model for House Pricing regression
https://towardsdatascience.com/keras-101-a-simple-and-interpretable-neural-network-model-for-house-pricing-regression-31b1a77f05ae

Keras examples
https://keras.io/examples

Linear Regression in Python
https://realpython.com/linear-regression-in-python

Predictive Analysis in Python
https://medium.com/my-data-camp-journey/predictive-analysis-in-python-97ca5b64e97f

Regression Tutorial with the Keras Deep Learning Library in Python
https://machinelearningmastery.com/regression-tutorial-keras-deep-learning-library-python

Laissez un commentaire

Commentez anonymement ou connectez-vous pour commenter.

Commentaires

Laissez une réponse

Répondez de manière anonyme ou connectez-vous pour répondre.