引言
tensorflow主流的编程姿势有三种:
- 使用low level api
- 使用keras
- 使用estimator
一个比较好的机器学习程序是data与model的分离。data作为数据流流入model从而训练model。tensorflow的这三种编程姿势也是按照这个趋势来走的。特别是在这几天出来的tensorflow2.0版本里面将tf.Session编程tf.function,更是将这一思想表现的淋漓尽致。而在estimator、keras这些高阶api里面,这一思想更不用说。
我们都知道做实验都需要将材料放入反应堆里面,不同的材料从不同的入口流进反应堆。同样在tensorflow里面也是这样的,一条数据(比如说seq2seq模型,一条数据经过处理达到可以直接灌入模型前通常会被处理成三部分, ids, text_len, masks)灌入模型,数据的不同部分需要从不同的入口进入模型。
所以模型入口和数据的不同部分(特征)是一一对应的。
在tensorflow里面,所有的编程姿势都离不开上面这句话。本篇博客将简要介绍一下上面的这个思想,从模型入口、数据的不同部分、他们如何一一对应这三要素讲解如上三种tensorflow编程姿势。
low level api
这部分是tensorflow早期(1.x时代的)一种编程模式
其模型入口使用tf.placeholder来定义,需要指定shape, type。
其数据的不同部分编程者心里有数就行, 每一部分都使用list来表示
而他们如何一一对应使用的是tf.Session.run这个方法的feed_dict参数来实现的,这个参数接受一个dict, dict的key是tf.placeholder的实例,这个实例定义了从这个入口进入的数据的type及类型。
如下是tensorflow1.1.0版本的mnist官方实现的feed_dict,
1 | def fill_feed_dict(data_set, images_pl, labels_pl): |
我们可以看到其就是使用placeholder同数据的不同部分的一一对应来实现模型的训练的
keras
其模型入口使用keras.Input来定义,需要指定shape, type。
其数据的不同部分编程者心里有数就行, 每一部分都使用list或者generator来表示
而他们如何一一对应使用的是keras.Model.fit这个方法的x、y参数来实现的,这两个参数接受一个dict或者list, 或者单个的数据array。
如果为dict的话,那么在模型入口这个keras.Input必须指定name参数,这个name参数就是这个dict的key, value为从这个入口进去的数据。
如果为list的话,那么在model=Model(inputs, outputs)里面,inputs必须为list,且同x必须长度相等,同一个index位置代表着入口和一一对应的数据
如果为单个array的话,那么自然就一一对应了
如下是keras的编程的一个example
1 | data = np.random.random((1000, 32)) |
estimator
在estimator里面需要实例化一个Estimator来编程。实例化的时候需要传入model_fn来定义模型。而在Estimator.train里面传入input_fn来给模型传入数据。那么如何实现上面的三要素的呢
其模型入口使用model_fn来实现,model_fn签名为model_fn(features, labels, mode, parmas, config),features, labels应该为单输入或者是dict。单输入则为tf.Tensor,dict的的key为一个字符串,value为tf.Tensor。
其数据的不同部分需要input_fn来实现,这个函数需要返回features,labels。如果模型单输入就无所谓了,直接返回。如果是多输入则需要features和labels各自返回dict,dict的key为字符串,value为数据的不同部分。
而他们如何一一对应。如果是单输入自然不存在一一对应的问题。如果多输入的话,从上面我们可以看到,model_fn的features同input_fn的返回的features都为dict, 他们的key即是一一对应的标识符。input_fn的features数据的各部分根据他们的key寻找model_fn的features里面对应的key的value(即tf.Tensor)。根据这个key实现两个value的一一对应。
这个地方需要注意的是,在写model_fn的时候需要在config参数里面定义feature_columns。
在1.x里面通过
tf.feature_columns.input_layer来实现model_fn的features与feature_columns绑定。feature_columns定义了各个key(这里model_fn与input_fn的key相同就不用解释了)的类型与shape。在2.0时代
tf.feature_columns.input_layer这个函数不存在了,取而代之是InputLayer这个函数。主要原因是tensorflow的趋势是一切皆keras编程,所以这个函数只接受feature_columns,然后模仿的是keras的Layer行为,在call函数里面去传入features,所以行为演变成了keras的行为,即Input与model=Model(inputs, outputs)定义了模型的入口。
在custom_estimator.py里面有如何使用estimator编程,注意这是1.x版本的tensorflow。