Réseaux de neurones: implémentation de la tâche sur les champignons sur Tensor Flow et Python

Tensor Flow est un cadre pour créer et travailler avec des réseaux de neurones de Google. Vous permet d'abstraire des détails internes de l'apprentissage automatique et de vous concentrer directement sur la résolution de votre problème. Une chose très puissante, elle vous permet de créer, former et utiliser des réseaux de neurones de tout type connu. Je n'ai pas trouvé un seul texte sensible sur Habré sur ce sujet, donc j'écris le mien. Ci-dessous, nous décrirons la mise en œuvre de la solution au problème des champignons à l'aide de la bibliothèque Tensor Flow. Soit dit en passant, l'algorithme décrit ci-dessous convient aux prédictions dans presque tous les domaines. Par exemple, la probabilité d'un cancer chez une personne dans le futur ou des cartes chez un adversaire au poker.

Défi


L'essence du problème: sur la base des paramètres d'entrée du champignon pour déterminer sa comestibilité. La spécificité est que ces paramètres sont catégoriels et non numériques. Par exemple, le paramètre «forme de chapeau» peut être réglé sur «plat» ou «convexe» ou «en forme de cône». Ensemble de données Champignon pour l'apprentissage en réseau tiré du référentiel d'apprentissage automatique . Ainsi, la solution au problème peut être appelée une sorte de Hello World dans le domaine de l'apprentissage automatique, avec le problème des iris , où les paramètres des fleurs sont exprimés en valeurs numériques.

Code source


Vous pouvez télécharger toutes les sources de mon référentiel sur Github: lien . Faites cela pour voir le code en action. N'utilisez que des codes source, car tous les retraits et encodages nécessaires y sont observés. Ci-dessous, l'ensemble du processus sera discuté en détail.

La préparation


Il est supposé que vous disposez d'une installation Tensor Flow préinstallée. Sinon, vous pouvez installer le lien .

Code source


from __future__ import absolute_import from __future__ import division from __future__ import print_function import tensorflow as tf import numpy as np import pandas as pd from sklearn.model_selection import train_test_split import os #       . #     CSV-    Tensor Flow       .  ,       (0  1) def prepare_data(data_file_name): header = ['class', 'cap_shape', 'cap_surface', #  CSV-   ,     'agaricus-lepiota.name'   'cap_color', 'bruises', 'odor', 'gill_attachment', 'gill_spacing', 'gill_size', 'gill_color', 'stalk_shape', 'stalk_root', 'stalk_surface_above_ring', 'stalk_surface_below_ring', 'stalk_color_above_ring', 'stalk_color_below_ring', 'veil_type', 'veil_color', 'ring_number', 'ring_type', 'spore_print_color', 'population', 'habitat'] df = pd.read_csv(data_file_name, sep=',', names=header) #   "?"      #        df.replace('?', np.nan, inplace=True) df.dropna(inplace=True) #         #  'e'  'p' .       # ,   0  , 1 -    df['class'].replace('p', 0, inplace=True) df['class'].replace('e', 1, inplace=True) #       , #     . Tensor Flow      # .  Pandas    "get_dummies" #      cols_to_transform = header[1:] df = pd.get_dummies(df, columns=cols_to_transform) #      #    -    () #      () df_train, df_test = train_test_split(df, test_size=0.1) #           num_train_entries = df_train.shape[0] num_train_features = df_train.shape[1] - 1 num_test_entries = df_test.shape[0] num_test_features = df_test.shape[1] - 1 #      csv-, .. #          #  csv,    Tensor Flow df_train.to_csv('train_temp.csv', index=False) df_test.to_csv('test_temp.csv', index=False) #     ,    open("mushroom_train.csv", "w").write(str(num_train_entries) + "," + str(num_train_features) + "," + open("train_temp.csv").read()) open("mushroom_test.csv", "w").write(str(num_test_entries) + "," + str(num_test_features) + "," + open("test_temp.csv").read()) #   ,     os.remove("train_temp.csv") os.remove("test_temp.csv") #        Tensor Flow def get_test_inputs(): x = tf.constant(test_set.data) y = tf.constant(test_set.target) return x, y #        Tensor Flow def get_train_inputs(): x = tf.constant(training_set.data) y = tf.constant(training_set.target) return x, y #        #    ( : , ) #  ,         def new_samples(): return np.array([[0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1]], dtype=np.int) if __name__ == "__main__": MUSHROOM_DATA_FILE = "agaricus-lepiota.data" #     Tensor Flow, #   CSV- (  ) prepare_data(MUSHROOM_DATA_FILE) #    training_set = tf.contrib.learn.datasets.base.load_csv_with_header( filename='mushroom_train.csv', target_dtype=np.int, features_dtype=np.int, target_column=0) test_set = tf.contrib.learn.datasets.base.load_csv_with_header( filename='mushroom_test.csv', target_dtype=np.int, features_dtype=np.int, target_column=0) # ,        ( ) feature_columns = [tf.contrib.layers.real_valued_column("", dimension=98)] #   DNN-  10, 20  10    classifier = tf.contrib.learn.DNNClassifier( feature_columns=feature_columns, hidden_units=[10, 20, 10], n_classes=2, model_dir="/tmp/mushroom_model") #   classifier.fit(input_fn=get_train_inputs, steps=2000) #        accuracy_score = classifier.evaluate(input_fn=get_test_inputs, steps=1)["accuracy"] print("\n : {0:f}\n".format(accuracy_score)) #         predictions = list(classifier.predict_classes(input_fn=new_samples)) print("   : {}\n" .format(predictions)) 

Téléchargez et préparez les données du référentiel


Nous téléchargerons les données pour la formation et le test du réseau neuronal à partir du référentiel d'apprentissage automatique spécialement créé à cet effet. Toutes les données sont présentées dans deux fichiers: agaricus-lepiota.data et agaricus-lepiota.names. Les 8124 premières lignes et 22 colonnes. Une ligne fournit un champignon, chaque colonne est l'un des 22 paramètres du champignon sous la forme d'un caractère de réduction du mot de paramètre entier. La légende de tous les personnages se trouve dans le fichier agarius-lepiota.names.

Les données du référentiel doivent être traitées afin de les amener à une forme acceptable pour Tensor Flow. Nous importons d'abord quelques bibliothèques pour le travail

 from __future__ import absolute_import from __future__ import division from __future__ import print_function import tensorflow as tf import numpy as np import pandas as pd from sklearn.model_selection import train_test_split import os 

Ensuite, nous formerons un en-tête à partir des paramètres du champignon pour Tensor Flow, afin que la bibliothèque sache quelle colonne du fichier de données correspond à quel paramètre. Le chapeau est collé au fichier de données. Nous formons un tableau dont les éléments sont extraits du fichier agaricus-lepiota.names.

 header = ['class', 'cap_shape', 'cap_surface', 'cap_color', 'bruises', 'odor', 'gill_attachment', 'gill_spacing', 'gill_size', 'gill_color', 'stalk_shape', 'stalk_root', 'stalk_surface_above_ring', 'stalk_surface_below_ring', 'stalk_color_above_ring', 'stalk_color_below_ring', 'veil_type', 'veil_color', 'ring_number', 'ring_type', 'spore_print_color', 'population', 'habitat'] df = pd.read_csv(data_file_name, sep=',', names=header) 

Vous devez maintenant gérer les données manquantes. Dans ce cas, le symbole "?" Est défini dans le fichier agaricus-lepiota.data au lieu du paramètre. Il existe de nombreuses méthodes pour gérer de tels cas, mais nous supprimerons simplement la ligne entière avec au moins un paramètre manquant.

 df.replace('?', np.nan, inplace=True) df.dropna(inplace=True) 

Ensuite, vous devez remplacer manuellement le paramètre de comestibilité symbolique par un paramètre numérique. Autrement dit, remplacez «p» et «e» par 0 et 1.

 df['class'].replace('p', 0, inplace=True) df['class'].replace('e', 1, inplace=True) 

Et après cela, vous pouvez convertir le reste des données en un chiffre. C'est ce que fait la fonction get_dummies de la bibliothèque pandas.

 cols_to_transform = header[1:] df = pd.get_dummies(df, columns=cols_to_transform) 

Tout réseau de neurones doit être formé. Mais en plus de cela, il doit également être calibré afin d'augmenter la précision du travail en conditions réelles. Pour ce faire, nous diviserons notre ensemble de données en deux: formation et étalonnage. Le premier sera plus grand que le second, comme il se doit.

 df_train, df_test = train_test_split(df, test_size=0.1) 

Et le dernier. Tensor Flow requiert que le nombre de lignes et de colonnes du fichier soit indiqué au début des fichiers de données. Nous allons extraire manuellement ces informations de nos ensembles de données de formation et d'étalonnage, puis écrire dans les fichiers CSV résultants.

 #         num_train_entries = df_train.shape[0] num_train_features = df_train.shape[1] - 1 num_test_entries = df_test.shape[0] num_test_features = df_test.shape[1] - 1 #     CSV df_train.to_csv('train_temp.csv', index=False) df_test.to_csv('test_temp.csv', index=False) #       CSV,      open("mushroom_train.csv", "w").write(str(num_train_entries) + "," + str(num_train_features) + "," + open("train_temp.csv").read()) open("mushroom_test.csv", "w").write(str(num_test_entries) + "," + str(num_test_features) + "," + open("test_temp.csv").read()) 

Au final, vous devriez obtenir ces fichiers: formation et calibration .

Jetez les données générées dans Tensor Flow


Maintenant que nous avons téléchargé à partir du référentiel et traité les fichiers CSV avec des données de champignon, vous pouvez les envoyer à Tensor Flow pour la formation. Cela se fait en utilisant la fonction load_csv_with_header () fournie par le framework lui-même:

 training_set = tf.contrib.learn.datasets.base.load_csv_with_header( filename='mushroom_train.csv', target_dtype=np.int, features_dtype=np.int, target_column=0) test_set = tf.contrib.learn.datasets.base.load_csv_with_header( filename='mushroom_test.csv', target_dtype=np.int, features_dtype=np.int, target_column=0) 

La fonction load_csv_with_header () est engagée dans la formation d'un ensemble de données d'entraînement à partir des fichiers que nous avons collectés ci-dessus. En plus du fichier de données, la fonction prend target_dtype comme argument, qui est un type de données prévu à la fin. Dans notre cas, il est nécessaire d'apprendre au réseau neuronal à prédire la comestibilité ou la toxicité du champignon, qui peut être exprimée par les valeurs 1 ou 0. Ainsi, dans notre cas, target_dtype est une valeur entière. features_dtype - paramètre où le type de paramètres acceptés pour la formation est défini. Dans notre cas, il s'agit également d'un entier (au départ, il s'agissait de chaîne, mais, comme vous vous en souvenez, nous les avons dépassés en nombre). À la fin, le paramètre target_column est défini, qui est l'indice de la colonne avec le paramètre que le réseau neuronal doit prédire. Autrement dit, avec le paramètre de comestibilité.

Créer un objet classificateur de flux de tenseur


C'est-à-dire, un objet d'une classe qui est directement impliqué dans la prédiction du résultat. En d'autres termes, la classe du réseau neuronal lui-même.

 feature_columns = [tf.contrib.layers.real_valued_column("", dimension=98)] classifier = tf.contrib.learn.DNNClassifier( feature_columns=feature_columns, hidden_units=[10, 20, 10], n_classes=2, model_dir="/tmp/mushroom_model") 

Le premier paramètre est feature_columns. Ce sont les paramètres des champignons. Veuillez noter que la valeur du paramètre est créée juste là, un peu plus haut. Là, à l'entrée, la valeur 98 du paramètre de dimension est prise, ce qui signifie 98 paramètres différents du champignon, à l'exception de la comestibilité.

hidden_units - le nombre de neurones dans chaque couche du réseau neuronal. La sélection correcte du nombre de couches et de neurones en leur sein est quelque chose au niveau de l'art dans le domaine de l'apprentissage automatique. Il n'est possible de déterminer correctement ces valeurs qu'après expérience. Nous avons pris ces chiffres simplement parce qu'ils sont répertoriés dans l'un des didacticiels Tensor Flow. Et ils fonctionnent.

n_classes - le nombre de classes à prévoir. Nous en avons deux - comestibles et non.

model_dir - le chemin où le modèle formé du réseau neuronal sera enregistré. Et à l'avenir, il sera utilisé pour prévoir les résultats, afin de ne pas entraîner le réseau à chaque fois.

La formation


Pour faciliter le travail à l'avenir, nous allons créer deux fonctions:

 def get_test_inputs(): x = tf.constant(test_set.data) y = tf.constant(test_set.target) return x, y def get_train_inputs(): x = tf.constant(training_set.data) y = tf.constant(training_set.target) return x, y 

Chaque fonction fournit son propre ensemble de données d'entrée - pour la formation et pour l'étalonnage. x et y sont les constantes Tensor Flow dont le framework a besoin pour fonctionner. N'entrez pas dans les détails, acceptez simplement que ces fonctions doivent être un intermédiaire entre les données et un réseau neuronal.

Nous formons un réseau:

 classifier.fit(input_fn=get_train_inputs, steps=2000) 

Le premier paramètre prend les données d'entrée formées juste au-dessus, le second - le nombre d'étapes de formation. Encore une fois, le numéro a été utilisé dans l'un des manuels Tensor Flow, et la compréhension de ce paramètre vous viendra avec l'expérience.

Ensuite, calibrez le réseau formé. Cela se fait en utilisant l'ensemble de données d'étalonnage généré ci-dessus. Le résultat du travail sera la précision des futures prévisions du réseau (precision_score).

 accuracy_score = classifier.evaluate(input_fn=get_test_inputs, steps=1)["accuracy"] print("\n : {0:f}\n".format(accuracy_score)) 

Nous testerons dans


Maintenant, le réseau neuronal est prêt, et vous pouvez essayer de prédire avec son aide la comestibilité du champignon.

 def new_samples(): return np.array([[0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1]], dtype=np.int) 

La fonction ci-dessus donne les données de deux champignons complètement nouveaux qui n'étaient présents ni dans l'entraînement ni dans les jeux d'étalonnage (en fait, ils ont simplement été extraits de ces derniers). Imaginez, par exemple, que vous les ayez achetés sur le marché et que vous essayez de comprendre s'ils peuvent être consommés. Le code ci-dessous définira ceci:

 predictions = list(classifier.predict(input_fn=new_samples)) print("   : {}\n" .format(predictions)) 

Le résultat du travail devrait être le suivant:

    : [0, 1] 

Et cela signifie que le premier champignon est toxique, le second est complètement comestible. Ainsi, vous pouvez faire des prédictions basées sur toutes les données, que ce soit des champignons, des personnes, des animaux ou quoi que ce soit. Il suffit de former correctement les données d'entrée. Et pour prédire, par exemple, la probabilité d'une arythmie d'un patient à l'avenir ou le mouvement du cours de bourse en bourse.

Source: https://habr.com/ru/post/fr419917/


All Articles