神经网络:在Tensor Flow和Python上实现有关蘑菇的任务的实现

Tensor Flow是一个用于构建和使用Google神经网络的框架。 让您从机器学习的内部细节中抽象出来,直接专注于解决问题。 一个非常强大的功能,它允许您创建,训练和使用任何已知类型的神经网络。 在此主题上,我没有找到有关哈布雷的任何明智文章,所以我写了自己的文章。 下面我们将使用Tensor Flow库描述解决蘑菇问题的方法的实现。 顺便说一下,以下描述的算法几乎适用于任何领域的预测。 例如,将来某人患癌症的可能性或在扑克游戏中的对手发牌的可能性。

挑战赛


问题的实质:根据真菌的输入参数确定其食用性。 特异性是这些参数是分类的,而不是数字的。 例如,“帽子形状”参数可以被设置为“平坦”或“凸形”或“圆锥形”。 从机器学习存储库中获取的用于网络学习的蘑菇数据集。 因此,该问题的解决方案可以称为机器学习领域中的“ Hello World”,也可以称为鸢尾花问题 ,其中鸢尾花的花朵参数以数字值表示。

源代码


您可以在Github: link上从我的存储库下载所有资源。 这样做可以查看实际的代码。 仅使用源代码,因为在那里会观察到所有必需的缩进和编码。 下面将对整个过程进行详细讨论。

准备工作


假设您已经预装了Tensor Flow安装。 如果没有,您可以安装链接

源代码


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

从存储库下载并准备数据


我们将从为此专门创建的机器学习存储库中下载用于训练和测试神经网络的数据。 所有数据都显示在两个文件中:agaricus-lepiota.data和agaricus-lepiota.names。 前8124行和22列。 一行提供一个蘑菇,每一列都是蘑菇的22个参数之一,其形式为整个参数字中的归约字符。 所有字符的图例位于agarius-lepiota.names文件中。

需要处理来自存储库中的数据,以使其成为Tensor Flow可接受的形式。 首先,我们导入一些要工作的库

 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 

然后,我们将从Tensor Flow的蘑菇形参数中形成一个标头,以便库知道数据文件中的哪列与哪个参数相对应。 帽子被粘到数据文件上。 我们以数组的形式形成,其元素取自文件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) 

现在,您需要处理丢失的数据。 在这种情况下,在agaricus-lepiota.data文件中设置符号“?”而不是参数。 有许多方法可以处理这种情况,但是我们将删除至少包含一个缺失参数的整行。

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

接下来,您必须使用数字数字手动替换符号可编辑性参数。 也就是说,将“ p”和“ e”替换为0和1。

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

然后,您可以将其余数据转换为数字。 这就是熊猫库的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) 

还有最后一个。 Tensor Flow要求在数据文件的开头指示文件的行数和列数。 我们将从训练和校准数据集中手动提取此信息,然后写入生成的CSV文件。

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

最后,您应该获得以下文件: 培训校准

将生成的数据放入Tensor Flow


现在我们已经从存储库下载并使用蘑菇数据处理了CSV文件,您可以将它们发送到Tensor Flow进行培训。 这是使用框架本身提供的load_csv_with_header()函数完成的:

 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) 

load_csv_with_header()函数用于从上面收集的文件中形成训练数据集。 除了数据文件外,该函数还将target_dtype作为参数,这是最后预测的数据类型。 在我们的情况下,有必要讲授神经网络来预测真菌的可食用性或毒性,可以用值1或0表示。因此,在我们的情况下,target_dtype是整数值。 features_dtype-设置接受训练的参数类型的参数。 在我们的例子中,它也是一个整数(最初它们是字符串,但是,如您所记得,我们将它们改写为数字)。 最后,设置了target_column参数,该参数是具有神经网络要预测的参数的列的索引。 也就是说,带有edibility参数。

创建一个Tensor Flow分类器对象


即,直接参与预测结果的类的对象。 换句话说,神经网络本身的类别。

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

第一个参数是feature_columns。 这些是蘑菇的参数。 请注意,参数值是在此处创建的,稍高一些。 在那里,在输入处获取了维度参数的值98,这意味着蘑菇的98个不同参数(可食性除外)。

hidden_​​units-神经网络每一层中的神经元数量。 在机器学习领域中,正确选择层和神经元的数量是一项技术水平的工作。 仅在经历后才可能正确确定这些值。 我们采用这些数字只是因为它们在Tensor Flow教程之一中列出。 他们工作。

n_classes-要预测的类数。 我们有两个-可食用和不可食用。

model_dir-将保存神经网络的训练模型的路径。 并且将来它将用于预测结果,以免每次都训练网络。

培训课程


为了将来的工作简便,我们将创建两个函数:

 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 

每个功能都提供自己的一组输入数据-用于训练和校准。 x和y是框架需要工作的Tensor Flow常数。 不要赘述,只是接受这些功能应该是数据和神经网络之间的中介。

我们训练一个网络:

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

第一个参数采用刚刚形成的输入数据,第二个参数为训练步骤的数量。 同样,该数字已在Tensor Flow手册之一中使用,并且您会经验丰富地了解此设置。

接下来,校准经过训练的网络。 这是使用上面生成的校准数据集完成的。 工作的结果将是未来网络预测的准确性(accuracy_score)。

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

我们将在


现在神经网络已经准备就绪,您可以尝试借助其预测真菌的可食用性。

 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) 

上面的函数提供了两个全新的蘑菇的数据,这些蘑菇既不在训练中也不在校准集中(实际上,它们只是从后者中提取的)。 例如,想象一下,您在市场上购买了它们,并试图了解它们是否可以食用。 下面的代码将对此进行定义:

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

工作的结果应为:

    : [0, 1] 

这意味着第一个蘑菇有毒,第二个完全食用。 因此,您可以根据任何数据做出预测,无论是蘑菇,人,动物还是其他任何东西。 足以正确形成输入数据。 并例如预测患者将来发生心律失常的可能性或证券交易所的股价走势。

Source: https://habr.com/ru/post/zh-CN419917/


All Articles