原文教程:tensorflow官方教程
记录关键内容与学习感受。未完待续。。
——这个教程向你介绍如何在tf.contrib.learn创建输入函数。你可以获得一个如果构造input_fn的综述来对你的模型预处理和喂进数据。接着,接着你可以实现一个input_fn,它可以在神经网络回归量提供训练、验证和预测数据,来预测房屋价值中位数。
——当使用tf.contrib.learn训练一个神经网络时,将你的特征和目标数据直接传到fit,,evaluate和predict操作是可能的。这里有一个tf.contrib.learn quickstart tutorial的例子:
training_set = tf.contrib.learn.datasets.base.load_csv_with_header( filename=IRIS_TRAINING, target_dtype=np.int, features_dtype=np.float ) test_set = tf.contrib.learn.datasets.base.load_csv_with_header( filename=IRIS_TEST, target_ftype=np.int, features_dtype=np.float32 ) ... classifier.fit( x=training_set.data, y=training_set.target, steps=2000 )——-当几乎没有对源数据进行一些操作时,这种方法工作的很好。但是,在这种情况下,当需要更多的特征工程,tf.contrib.learn支持使用定制的输入函数(input_fn)来封装模型中预处理和捆绑数据的逻辑。
——下面的代码举例了一个输入函数基本的框架:
def my_input_fn(): # Preprocess your data here... # ...then return # 1) a mapping of feature columns to tensors with the corresponding feature data, # 2) a tensor containing labels return feature_cols,labels——这个输入函数的主体包括对你的数据进行预处理的逻辑,例如清洗坏例子或者feature scaling。
——输入函数必须返回两个值,包括最后的特征和你喂给模型的的标签数据(例如上面代码框架所展示的那样)。
feature_cols:一个包含键值对的字典,将特征列名字映射到一个Tensors或者SparseTensors中。这个Tensors或者SparseTensors包含与之相关联的特征数据。
labels:一个包含你的标签(目标)值的Tensor,这个值是你的模型致力于预测的那个值。
——-如果你的特征/标签数据存储在pandas的数据框架或者是numpy数组中,在从你的input_fn中返回它之前,你需要将其转化为tensor。
——对于连续数据,你可以创建并使用tf.constant填入tensor:
feature_colums_data = [1, 2.4, 0, 9.9, 3, 120] feature_tensor = tf.constant(feature_column_data)——-对于sparse, categorical data(数据中大多数的值是0),你可能想填入一个SparseTensor中,使用3个参数来实例化:
shape:tensor的形状。用一个列表来表明每一个维度元素的数量。例如,shape=[3, 6],指定了二维的3x6的tensor,shape=[2, 3, 4],指定了一个三维的2x3x4的tensor,shape=[9],指定了一个一维的有9个元素的tensor。
indices:在你的tensor中非0元素的索引。用一个关系的列表,每一个关系本身又是一个列表,包含非0元素的坐标。(元素是0–编入索引–也就是说,[0,0]是一个二维tensor中,第一列第一行元素的索引值。)例如,indices=[[1,3], [2,4]],表明,在坐标[1,3]和坐标[2,4]的元素是非0的。
values:一个一维tensor的values。在values中的i与indices中的i是相联系的,并且表明了其值。例如,给定indices=[[1,3], [2,4]],参数values=[18, 3.6],这表明,tensor的[1,3]处的元素的值为18,[2,4]处的元素的值为3.6。
——下面的代码定义了一个二维的3行5列的SparseTensor,在坐标[0,1]处的值为6,在坐标[2,6]处的值为0.5(其他所有的值都为0):
sparse_tensor = tf.SparseTensor( indices=[[0,1],[2,4]], values=[6,0.5], shape=[3,5] )——下面是与之相连的展开的tensor:
[[0, 6, 0, 0, 0] [0, 0, 0, 0, 0] [0, 0, 0, 0, 0.5]]——更多关于SparseTensor,详见TensorFlow API documentation
——为了喂给你的模型数据以进行训练,你简单的将你已经创建好的输入函数传递给fit操作,作为参数input_fn的值,例如:
classifier.fit(input_fn = my_input_fn, steps=2000)——注意,input_fn负责提供给模型特征和标签数据,并且在fit操作中,替代了x和y参数。如果你将一个非None的input_fn的值供给fit,与之相连的无论与x参数,还是y参数,都是非None的(教程中说是非None,感觉并不合逻辑,私以为这里是说x参数或者y参数,有一个为None,才会引起错误),这将引起ValueError。
——也要注意,input_fn参数必须接收一个函数对象(也就是说,input_fn=my_input_fn),而不是函数调用返回的值(input_fn=my_input_fn())。这意味着,在你的fit函数调用中,如果你试图将一个参数传递给输入函数,如以下代码一样,将引起TypeError:
classifier.fit(input_fn = my_input_fn(training_set), steps=2000)——-然而,如果你有能力参数化表示你的输入函数,这里有另一种方法来做这件事。你可以采用一个包装函数,它没有任何参数,作为你的input_fn ,并且使用它调用你的输入函数,你的输入函数可以带有你想要的参数。例如:
classifier.fit(input_fn = my_input_function_trainging_set, steps=2000)——另一种,你可以使用Python的functools.partial函数来构建一个新的函数对象,带有所有固定的参数值:
classifier.fit( input_fn = functools.partial(my_input_function, data_set=training_set), steps=2000 )——第三种选择是,在一个lambda中,封装你的输入函数使用,并且将其传递给input_fn参数:
classifier.fit(input_fn = lambda:my_input_fn(training_set), steps=2000)——上述对于建构你的输入管道一个很大的优势是,接收一个数据集的参数—也就是说你可以用同一个input_fn来进行evaluate和predict操作,仅仅只需要修改数据集参数,例如:
classifier.evaluate(input_fn = lambda:my_input_fn(test_set), steps=2000)——这种方法提高了代码的可维护性,对每个类型的操作,不需要在分开的变量中获取x和y的值(例如,x_train, x_test, y_train,,y_test)。
——在这个教程的剩余部分,你可以写一个输入函数来预处理来自UCI Housing Data Set的波士顿房屋信息的子集,并且使用它喂给神经网络回归器数据,来预测房价中值。
——你训练你的神经网络,将要使用的Boston CSV data sets,包含以下对于波士顿郊区的feature data。
FeatureDescriptionCRIMCrime rate per capita:每capita的犯罪率ZNFraction of residential land zoned to permit 25,000+ sq ft lots:住宅地分区允许25000多平方英尺的分数INDUSFraction of land that is non-retail business:没有零售业务的土地的分数NOXConcentration of nitric oxides in parts per 10 million:每100万区域氮氧化合物的浓度RMAverage Rooms per dwelling:每个寓所的平均房间数AGEFraction of owner-occupied residences built before 1940:在1940年以前建立的物主所拥有的住宅的分数DISDistance to Boston-area employment centers:到波士顿就业中心的距离TAXProperty tax rate per $10,000:每10000美元的房产税PTRATIOStudent-teacher ratio:师生比.
——并且你的模型预测的标签是MEDV(the median value of owner-occupied residences in thousands of dollars),业主自住的住宅的价格中值在成千上万美元左右。
——下载一下数据集:boston_train.csv,boston_test.csv和boston_predict.csv。
——下面部分一步一步提供了如何创建一个输入函数,将这些数据集喂入一个神经网络回归器,训练并验证这个模型,并且做出房屋价值的预测。最终完整的代码可以从这里获取。
——开始,设置你的imports部分(包括pandas和tensorflow),并且set logging verbosity为INFO,以获取更多的日志输出细节。
from __future__ import absolute_import from __future__ import division from __future__ import print_function import pandas as pd import tensorflow as tf tf.logging.set_verbosity(tf.logging.INFO)——在COLUMN中定义数据集列的名字。为了从标签中区分特征,也定义了FEATURES和LABEL。接着读取三个CSV文件(train、test和predict)到pandas的DataFrames中。
COLUMNS = ["crim", "zn", "indus", "nox", "rm", "age", "dis", "tax", "ptratio", "medv" ] FEATURES = ["crim", "zn", "indus", "nox", "rm", "age", "dis", "tax", "ptratio" ] LABEL = "medv" training_set = pd.read_csv( "boston_train.csv", skipinitialspace=True, skiprows=1, names=COLUMNS ) test_set = pd.read_csv( "boston_test.csv", skipinitialspace=True, skiprows=1, names=COLUMNS ) prediction_set = pd.read_csv( "boston_predict.csv", skipinitialspace=True, skiprows=1, names=COLUMNS )——接下来,对于输入数据,创建一个FeatureColumns的列表,可以正式的指明这个特征集是用来训练的。因为在房屋数据集的所有特征包含连续值,你可以通过tf.contrib.layers.real_valued_column()函数创建他们的FeatureColumns。
feature_cols = [ tf.contrib.layers.real_valued_column(k) for k in FEATURES ]——注意,对于特征列更彻底的综述,请看介绍,并且举例证实了对于类别数据,如何定义FeatureColumns,请看Linear Model Tutorial。
——-现在,对于神经网络回归模型,实例化一个DNNRegressor。你需要提供两个参数:hidden_units,一个超参数,表明了在每一个隐藏层的节点数量(这里,两个隐藏层各有10个节点)。feature_columns,包含你刚才定义的FeatureColumns列表。
regressor = tf.contrib.learn.DNNRegressor( feature_columns=feature_cols, hidden_units=[10,10] )——为了将输入数据传给regressor,创建一个输入函数,它将接受一个pandas的Dataframe,并返回一个tensors的特征列和标签值:
def input_fn(data_set): feature_cols = { k:tf.constant(data_set[k].values) for k in FEATURES } labels = tf.constant(data_set[LABEL].values) return feature_cols,labels——注意传给input_fn的输入数据是data_set参数,这意味着,函数可以处理任何你输入的DataFrames:training_set,test_set和prediction_set。
——为了训练神经网络回归器,运行fit函数,将training_set传递给input_fn:
regressor.fit(input_fn=lambda:input_fn(training_set), steps=5000)——你可以看见输出日志类似于如下,每100步记录了训练损失。
INFO:tensorflow:Step 1: loss = 483.179 INFO:tensorflow:Step 101: loss = 81.2072 INFO:tensorflow:Step 201: loss = 72.4354 ... INFO:tensorflow:Step 1801: loss = 33.4454 INFO:tensorflow:Step 1901: loss = 32.3397 INFO:tensorflow:Step 2001: loss = 32.0053 INFO:tensorflow:Step 4801: loss = 27.2791 INFO:tensorflow:Step 4901: loss = 27.2251 INFO:tensorflow:Saving checkpoints for 5000 into /tmp/boston_model/model.ckpt. INFO:tensorflow:Loss for final step: 27.1674.——实际运行截图:
——接下来,如何使训练的模型对测试数据集进行执行。运行evaluate,并且这次将test_set传递给input_fn。
ev = regressor.evaluate(input_fn=lambda:input_fn(test_set), steps=1)——从ev结果中计算损失并打印出来:
print("Loss:{0:f}".format(loss_score))——你将看到类似如下的输出:
INFO:tensorflow:Eval steps [0,1) for training step 5000. INFO:tensorflow:Saving evaluation summary for 5000 step: loss = 11.9221 Loss: 11.922098——实际运行结果:
——最终,你可以使用这个模型,通过prediction_set,来做房屋中值预测。里面有六个例子,只包含特征数据,而没有标签数据。
y = regressor.predict(input_fn=lambda:input_fn(prediction_set)) predictions = list(itertools.islice(y, 6)) print("Predictions:{}".format(str(predictions)))——你的结果应该包括六个例子的房屋中值预测,例如:
Predictions: [ 33.30348587 17.04452896 22.56370163 34.74345398 14.55953979 19.58005714]——实际运行结果:
——这个教程着重与为神经网络回归器创建一个input_fn。为了学习更多的关于其他类型模型的input_fn的使用,可以点击一下资源:
Large-scale Linear Models with TensorFlow:这篇介绍是相对线性模型,tensorflow提供了关于特征列高级别的综述合转换输入数据的技术。
TensorFlow Linear Model Tutorial:这篇教程覆盖了包括,对于线性分类模型(基于人口普查数据可以预测收入),创建FeatureColumns和input_fn。
TensorFlow Wide & Deep Learning Tutorial:基于Linear Model Tutorial,这篇教程覆盖,对于”wide and deep”模型(使用DNNLinearCombinedClassifier,结合了线性模型和神经网络),创建FeatureColumns和input_fn。
——以上,结束。