本文接着上一篇继续来聊Tensorflow
的接口,上一篇中用较低层的接口实现了线性模型,本篇中将用更高级的API——tf.estimator
来改写线性模型。python
还记得以前的文章《机器学习笔记2 - sklearn之iris数据集》吗?本文也将使用tf.estimator
改造该示例。算法
本文代码都是基于API版本r1.4
。本文中本地开发环境为Pycharm
,在文中再也不赘述。数组
比起用底层API“较硬”的编码方式,tf.estimator
的在使用时更像是对模型描述(或定义)的过程。Tensorflow
把训练
、评估
、数据处理
等这些过程所有封装起来,让开发人员更专一于解决实际问题的建模过程,而不是纠结于代码实现过程。若是用tf.estimator
改造上一篇中的线性模型的话,完整代码以下:机器学习
本例中使用的库numpy
是一个开源工具,是一个功能很是强大且执行效率很高的库,主要用做数值处理及矩阵操做等。工具
import numpy as np import tensorflow as tf # 定义特性列,线性模型中特性是列是x,shape=[1],所以定义以下: feature_columns = [tf.feature_column.numeric_column("x", shape=[1])] # 使用tf.estimator内置的LinearRegressor来完成线性回归算法 # tf.estimator提供了不少常规的算法模型以便用户调用,不须要用户本身重复造轮子 # 到底为止,短短两行代码咱们的建模工做就已经完成了 estimator = tf.estimator.LinearRegressor(feature_columns=feature_columns) # 有了模型以后,咱们要使用模型完成训练->评估->预测这几个步骤 # 训练数据依旧是(1.,0.),(2.,-1.),(3.,-2.),(4.,-3.)这几个点,拆成x和y两个维度的数组 x_train = np.array([1., 2., 3., 4.]) y_train = np.array([0., -1., -2., -3.]) # 评估数据为(2.,-1.01),(5.,-4.1),(8.,-7.),(1.,0.)这四个点,一样拆分红x和y两个维度的数组 x_eval = np.array([2., 5., 8., 1.]) y_eval = np.array([-1.01, -4.1, -7., 0.]) # 用tf.estimator.numpy_input_fn方法生成随机打乱的数据组,每组包含4个数据 input_fn = tf.estimator.inputs.numpy_input_fn({"x": x_train}, y_train, batch_size=4, num_epochs=None, shuffle=True) # 循环1000次训练模型 estimator.train(input_fn=input_fn, steps=1000) # 生成训练数据,分红1000组,每组4个数据 train_input_fn = tf.estimator.inputs.numpy_input_fn({"x": x_train}, y_train, batch_size=4, num_epochs=1000, shuffle=False) # 生成评估数据,分红1000组,每组4个数据 eval_input_fn = tf.estimator.inputs.numpy_input_fn({"x": x_eval}, y_eval, batch_size=4, num_epochs=1000, shuffle=False) # 训练数据在模型上的预测准确率 train_metrics = estimator.evaluate(input_fn=train_input_fn) # 评估数据在模型上的预测准确率 eval_metrics = estimator.evaluate(input_fn=eval_input_fn) print("train metrics: %r"% train_metrics) print("eval metrics: %r"% eval_metrics)
输出结果以下:学习
train metrics: {'average_loss': 4.4709815e-08, 'loss': 1.7883926e-07, 'global_step': 1000} eval metrics: {'average_loss': 0.0025470245, 'loss': 0.010188098, 'global_step': 1000}
虽然tf.estimator
内置了大量的经常使用模型,但也并不表明咱们必须使用内置模型。若有须要,咱们能够用底层API实现自定义模型,同时,继续使用tf.estimator
提供的高级特性。如上例中,咱们须要定义本身的线性回归模型,仅须要按以下步骤操做:测试
# 下面这行替换了原先的estimator = tf.estimator.LinearRegressor(feature_columns=feature_columns) estimator = tf.estimator.Estimator(model_fn=model_fn)
... def model_fn(features, labels, mode): # 用底层API构建线性模型 W = tf.get_variable("W", [1], dtype=tf.float64) b = tf.get_variable("b", [1], dtype=tf.float64) y = W * features['x'] + b loss = tf.reduce_sum(tf.square(y - labels)) # 获取训练全局参数step global_step = tf.train.get_global_step() # 梯度降低算法,学习率是0.01 optimizer = tf.train.GradientDescentOptimizer(0.01) # 将优化器和全局step的累加方法打包成一个方法组,至关于把若干个方法打包成事务执行的模式 train = tf.group(optimizer.minimize(loss), tf.assign_add(global_step, 1)) # 将全部内容封装成符合tf.estimator.Estimator规范的对象 return tf.estimator.EstimatorSpec( mode=mode, predictions=y, loss=loss, train_op=train) ...
在tf.estimator
中,生成TensorBoard
的方法也被集成在了底层,咱们要作的,仅仅是传入参数model_dir
而已:优化
在LinearRegressor例中代码以下:google
... estimator = tf.estimator.LinearRegressor(feature_columns=feature_columns, model_dir='d1') ...
... estimator = tf.estimator.Estimator(model_fn=model_fn, model_dir='d2') ...
TensorBoard
的启动和上一篇文章中同样,在Pycharm
的控制台中执行:阿里云
# 以LinearRegressor的代码为例 tensorboard --logdir=d1
启动TensorBoard
大体效果以下:
如今咱们来改造以前用sklearn
实现的IRIS
数据集。以前用了决策树
和邻近算法
两种算法来实现,此次用的是Tensorflow
提供的深度学习模型DNNClassifier
,完整代码以下(代码是官网提供的Demo代码,仅仅将DNNClassifier
中参数model_dir
改成了当前目录下iris_model
目录):
from __future__ import absolute_import from __future__ import division from __future__ import print_function import os from six.moves.urllib.request import urlopen import numpy as np import tensorflow as tf # 数据集 IRIS_TRAINING = "iris_training.csv" IRIS_TRAINING_URL = "http://download.tensorflow.org/data/iris_training.csv" IRIS_TEST = "iris_test.csv" IRIS_TEST_URL = "http://download.tensorflow.org/data/iris_test.csv" def main(): # 先将数据集保存到本地 if not os.path.exists(IRIS_TRAINING): raw = urlopen(IRIS_TRAINING_URL).read() with open(IRIS_TRAINING, "wb") as f: f.write(raw) if not os.path.exists(IRIS_TEST): raw = urlopen(IRIS_TEST_URL).read() with open(IRIS_TEST, "wb") as f: f.write(raw) # 读取数据集 training_set = tf.contrib.learn.datasets.base.load_csv_with_header( filename=IRIS_TRAINING, target_dtype=np.int, features_dtype=np.float32) test_set = tf.contrib.learn.datasets.base.load_csv_with_header( filename=IRIS_TEST, target_dtype=np.int, features_dtype=np.float32) feature_columns = [tf.feature_column.numeric_column("x", shape=[4])] # 建立一个三层的DNN深度学习分类器,三层分别有十、20、10个神经元 classifier = tf.estimator.DNNClassifier(feature_columns=feature_columns, hidden_units=[10, 20, 10], n_classes=3, model_dir="iris_model") # 定义训练用的数据集输入 train_input_fn = tf.estimator.inputs.numpy_input_fn( x={"x": np.array(training_set.data)}, y=np.array(training_set.target), num_epochs=None, shuffle=True) # 训练模型 classifier.train(input_fn=train_input_fn, steps=2000) # 定义测试用的数据集输入 test_input_fn = tf.estimator.inputs.numpy_input_fn( x={"x": np.array(test_set.data)}, y=np.array(test_set.target), num_epochs=1, shuffle=False) # 评估准确率 accuracy_score = classifier.evaluate(input_fn=test_input_fn)["accuracy"] print("\nTest Accuracy: {0:f}\n".format(accuracy_score)) # 预测两个新样本 new_samples = np.array( [[6.4, 3.2, 4.5, 1.5], [5.8, 3.1, 5.0, 1.7]], dtype=np.float32) predict_input_fn = tf.estimator.inputs.numpy_input_fn( x={"x": new_samples}, num_epochs=1, shuffle=False) predictions = list(classifier.predict(input_fn=predict_input_fn)) predicted_classes = [p["classes"] for p in predictions] print( "New Samples, Class Predictions: {}\n" .format(predicted_classes)) if __name__ == "__main__": main()
运行结果:
Test Accuracy: 0.966667 New Samples, Class Predictions: [array([b'1'], dtype=object), array([b'2'], dtype=object)] Process finished with exit code 0
能够看到,用tf.estimator
提供的DNNClassifier
,仅须要以下代码便可实现一个三层的DNN,并将模型保存在本地的iris_model
文件夹下:
classifier = tf.estimator.DNNClassifier(feature_columns=feature_columns, hidden_units=[10, 20, 10], n_classes=3, model_dir="iris_model")
启动TensorBoard
,看到的效果以下:
前面几篇文章中,我在本地运行代码的以后,同时在阿里云PAI
上执行了一次代码。原本我也是想在PAI
上再进行本文中的示例代码的,不过我花了一天多的时间,最后仍是失败了,主要缘由以下:
PAI
目前只支持到Tensorflow 1.2
,而官方目前已经出到Tensorflow 1.4
(立刻要出1.5了),而Tensorflow 1.2
是不支持tf.estimator.DNNClassifier
的(代码中须要用到)
PAI
虽然是可视化拖拽,可是代码仍是须要按照PAI
的要求进行少许改造,不便于本地代码直接放到云端执行
PAI
的相关文档太少,遇到问题很难解决,就算提交工单技术支持也比较敷衍,这让我这样的初学者感到很是大的挫折感
说来也好笑,个人代码不管如何调整在PAI
中运行都会报错,在PAI
官方的技术QQ群里寻求帮助,半天没人搭理,而后有一个群友说PAI
确实很差用,建议我用Google Cloud Platform
。备受挫折的我就注册了一个Google Cloud Platform
,果真,即使是全英文的文档,也让我在不到2小时
的时间里,从注册帐号到执行代码成功。这真不是我崇洋媚外或者故意黑阿里,我仅仅叙述了我本身的亲身经历而已。相比PAI
,Google Cloud Platform
的ML Engine
就是一个虚拟云主机(Linux),能够直接用Google的Web版远程控制台进行操做,就跟操做一台真实的Linux同样的体验。所以本地代码也能够直接拷贝过去就能执行,不须要任何修改。运行速度上,我以为比PAI
快不少(没有数据,只是感受)。
使用Google Cloud Platform
的ML Engine
,须要一些前提条件:
收费,须要绑定信用卡(VISA或MASTER),不过注册帐号是送300美金体验1年(也就是一年内不超过300美金的消费是免费的),官方承诺,免费体验额度用完,若是要产生后续扣信用卡费用的行为,须要用户确认以后才会继续扣款
较好的英文阅读能力(能基本看懂英文技术、帮助文档)
FQ(你懂的)
会操做Linux系统
如下就是我在Google Cloud Platform
的ML Engine
的Web控制台中操做的动图(注册过程略):
注意:
我事先作过了实验,因此代码已经放在文件~/cloudml-samples-master/mymltest/tensorflowdemo3/code.py
中,动图中仅仅是复制了一份代码到新的执行目录下。
Google Cloud Platform
的帮助文档我放在了最后的参考文档
中。
官方文档:
https://www.tensorflow.org/get_started/get_started
https://www.tensorflow.org/get_started/estimator
ML Engine帮助文档:
https://cloud.google.com/ml-engine/docs/getting-started-training-prediction