Redes neuronales: implementación de la tarea sobre hongos en Tensor Flow y Python

Tensor Flow es un marco para construir y trabajar con redes neuronales de Google. Le permite abstraerse de los detalles internos del aprendizaje automático y centrarse directamente en resolver su problema. Algo muy poderoso, le permite crear, entrenar y usar redes neuronales de cualquier tipo conocido. No encontré un solo texto sensible sobre Habré sobre este tema, así que escribo el mío. A continuación describiremos la implementación de la solución al problema de los hongos utilizando la biblioteca Tensor Flow. Por cierto, el algoritmo descrito a continuación es adecuado para predicciones en casi cualquier campo. Por ejemplo, la probabilidad de cáncer en una persona en el futuro o cartas en un oponente en el póker.

Desafío


La esencia del problema: sobre la base de los parámetros de entrada del hongo para determinar su comestibilidad. La especificidad es que estos parámetros son categóricos, no numéricos. Por ejemplo, el parámetro "forma de sombrero" se puede establecer en "plano" o "convexo" o "en forma de cono". Conjunto de datos de setas para el aprendizaje en red tomado del repositorio de aprendizaje automático . Por lo tanto, la solución al problema se puede llamar una especie de Hello World en el campo del aprendizaje automático, junto con el problema de los iris , donde los parámetros de la flor se expresan en valores digitales.

Código fuente


Puede descargar todas las fuentes desde mi repositorio en Github: enlace . Haga esto para ver el código en acción. Utilice solo códigos fuente, porque allí se observan todas las sangrías y codificaciones necesarias. A continuación se discutirá todo el proceso en detalle.

Preparación


Se supone que tiene una instalación de Tensor Flow preinstalada. Si no, puede instalar el enlace .

Código fuente


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)) 

Descargue y prepare datos del repositorio


Descargaremos los datos para entrenar y probar la red neuronal desde el repositorio de aprendizaje automático especialmente creado para esto. Todos los datos se presentan en dos archivos: agaricus-lepiota.data y agaricus-lepiota.names. Las primeras 8124 filas y 22 columnas. Una línea proporciona un hongo, cada columna es uno de los 22 parámetros del hongo en forma de un carácter de reducción de la palabra de parámetro completa. La leyenda de todos los personajes está en el archivo agarius-lepiota.names.

Los datos del repositorio deben procesarse para llevarlos a una forma aceptable para Tensor Flow. Primero importamos algunas bibliotecas para trabajar

 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 

Luego formaremos un encabezado a partir de los parámetros del hongo para Tensor Flow, de modo que la biblioteca sepa qué columna del archivo de datos corresponde a qué parámetro. El sombrero está pegado al archivo de datos. Nos formamos en forma de matriz, cuyos elementos se toman del archivo 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) 

Ahora necesita lidiar con los datos faltantes. En este caso, el símbolo "?" Se establece en el archivo agaricus-lepiota.data en lugar del parámetro. Existen muchos métodos para manejar estos casos, pero simplemente eliminaremos la línea completa con al menos un parámetro faltante.

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

A continuación, debe reemplazar manualmente el parámetro de edibilidad simbólica por uno digital. Es decir, reemplace "p" y "e" con 0 y 1.

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

Y después de eso, puede convertir el resto de los datos en un dígito. Esto es lo que hace la función get_dummies de la biblioteca de pandas.

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

Cualquier red neuronal necesita entrenamiento. Pero además de esto, también debe calibrarse para aumentar la precisión del trabajo en condiciones reales. Para hacer esto, dividiremos nuestro conjunto de datos en dos: capacitación y calibración. El primero será más grande que el segundo, como debería ser.

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

Y el último. Tensor Flow requiere que se indique el número de filas y columnas del archivo al comienzo de los archivos de datos. Extraeremos manualmente esta información de nuestros conjuntos de datos de entrenamiento y calibración y luego escribiremos en los archivos CSV resultantes.

 #         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()) 

Al final, debería obtener estos archivos: entrenamiento y calibración .

Lanza los datos generados en Tensor Flow


Ahora que hemos descargado del repositorio y procesado los archivos CSV con datos de hongos, puede enviarlos a Tensor Flow para capacitación. Esto se hace utilizando la función load_csv_with_header () proporcionada por el propio marco:

 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 función load_csv_with_header () se dedica a la formación de un conjunto de datos de entrenamiento a partir de los archivos que hemos recopilado anteriormente. Además del archivo de datos, la función toma target_dtype como argumento, que es un tipo de datos predichos al final. En nuestro caso, es necesario enseñar a la red neuronal a predecir la comestibilidad o toxicidad del hongo, que puede expresarse mediante los valores 1 o 0. Por lo tanto, en nuestro caso, target_dtype es un valor entero. features_dtype: parámetro donde se establece el tipo de parámetros aceptados para el entrenamiento. En nuestro caso, también es un número entero (inicialmente eran cadenas, pero, como recordarán, los superamos en un número). Al final, se establece el parámetro target_column, que es el índice de la columna con el parámetro que la red neuronal debe predecir. Es decir, con el parámetro de edibilidad.

Crear un objeto clasificador de flujo de tensor


Es decir, un objeto de una clase que participa directamente en la predicción del resultado. En otras palabras, la clase de la red neuronal misma.

 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") 

El primer parámetro es feature_columns. Estos son los parámetros de los hongos. Tenga en cuenta que el valor del parámetro se crea allí, un poco más alto. Allí, en la entrada, se toma el valor 98 del parámetro de dimensión, lo que significa 98 parámetros diferentes del hongo, con la excepción de la comestibilidad.

hidden_units: la cantidad de neuronas en cada capa de la red neuronal. La selección correcta del número de capas y neuronas en ellas es algo a nivel de arte en el campo del aprendizaje automático. Es posible determinar correctamente estos valores solo después de la experiencia. Tomamos estos números solo porque están enumerados en uno de los tutoriales de Tensor Flow. Y ellos trabajan.

n_classes: el número de clases para predecir. Tenemos dos de ellos, comestibles y no.

model_dir: la ruta donde se guardará el modelo entrenado de la red neuronal. Y en el futuro se usará para predecir resultados, a fin de no entrenar a la red cada vez.

Entrenamiento


Para facilitar el trabajo en el futuro, crearemos dos funciones:

 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 

Cada función proporciona su propio conjunto de datos de entrada, para entrenamiento y para calibración. xey son las constantes de Tensor Flow que el framework necesita para funcionar. No entre en detalles, solo acepte que estas funciones deben ser intermediarias entre los datos y una red neuronal.

Entrenamos una red:

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

El primer parámetro toma los datos de entrada formados justo arriba, el segundo, el número de pasos de entrenamiento. Nuevamente, el número se usó en uno de los manuales de Tensor Flow, y la comprensión de esta configuración le llegará con experiencia.

Luego, calibre la red entrenada. Esto se realiza utilizando el conjunto de datos de calibración generado anteriormente. El resultado del trabajo será la precisión de las predicciones futuras de la red (precision_score).

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

Vamos a probar en


Ahora la red neuronal está lista, y puede intentar predecir con su ayuda la comestibilidad del hongo.

 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 función anterior proporciona los datos de dos hongos completamente nuevos que no estaban presentes ni en el entrenamiento ni en los conjuntos de calibración (de hecho, simplemente fueron extraídos de este último). Imagine, por ejemplo, que los compró en el mercado y está tratando de entender si se pueden comer. El siguiente código definirá esto:

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

El resultado del trabajo debe ser el siguiente:

    : [0, 1] 

Y esto significa que el primer hongo es venenoso, el segundo es completamente comestible. Por lo tanto, puede hacer predicciones basadas en cualquier dato, ya sean hongos, personas, animales o cualquier cosa. Es suficiente formar correctamente los datos de entrada. Y para predecir, por ejemplo, la probabilidad de arritmia de un paciente en el futuro o el movimiento del precio de las acciones en la bolsa de valores.

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


All Articles