前一段时间微软收购了GitHub,价值竟然七十多亿美元。而TensorFlow也在18年4月份推出了TensorFlow Hub。

TensorFlow Hub和GitHub类似,只不过它里边是以Module为单元存储TensorFlow的图,权重,assets。Module主要是用来做迁移学习的。

Module里包含了已经基于大量数据训练好的模型参数。在一个相关的任务上,如果你想重用一个module,你可以:

a. 用相对少的数据来训练一个效果不错的模型。
b. 提高模型的泛化能力
c. 显著的提高模型训练的时间。

安装TF Hub

安装的前提是你装的TensorFlow版本必须高于1.7


pip install tensorflow-hub

实例化Module

一个TF hub的module可以通过URL或者文件路径来引入:


module = hub.Module("path/to/a/module_dir")

这样就可以把你设定模型的varibales引入到当前的TensorFlow graph里。运行他们的initializer,可以把它们预先训练好的值读入。同样,还有tables和其他一些状态都会读入到当前的graph里。

缓存Module

当通过URL创建一个module,这个module的内容被下载和保存到当前的系统临时文件里。这个路径可以通过TFHUB_CACHE_DIR来指定。


$ export TFHUB_CACHE_DIR=/my_module_cache

这时如果你再通过URL创建一个module,那么它就会被下载和解压到你指定的路径下:


module = hub.Module("https://tfhub.dev/google/progan-128/1")

调用Module

一旦一个module实例化好,这个module可以被调用0到多次。就像一个python的方法一样,从input tensor到output tensor


output=module(input)

每一个这样的调用,都会给当前的graph上增加从input到output的运算。

Module可以定义多个命名的签名,这样可以让它们有多种途径被调用。一个Module的文档需要描述这些可能的签名。上边演示的调用,实际上是一个名为default的签名。可以通过Module的可选signature参数来指明需要调用的signature。

并且一个signature可以有多个input,这些input必须被放到一个dict里。dict里的key值是signature定义的。如果一个signature的output也是多值的,可以通过传入as_dict=True来以dict的方式来获取多output。default的signature下output是单值的。下边的例子是输入输出都是多值,并且指定了signature的方式:


outputs = module(dict(apples=x1, oranges=x2), signature="fruit_to_pet", as_dict=True)
y1 = outputs["cats"]
y2 = outputs["dogs"]

一个调用必须提供signature要求的所有input。但是并不需要使用所有的output,TensorFlow会根据tf.session.run所依赖的部分。实际上,module的发布者可以选择提供多样的output给专业用户。比如除了最终的output,还可以输出中间层的激活函数的值。Module的用户需要自己合理利用这些output。

创建Module

发布者可以通过hub.create_module_spec()来发布一个新的Module。调用时需要传入一个module_fn方法。这个方法创建了一个graph来表征module内部的结构。使用tf.placehodler来替代调用者需要传入的inputs。然后通过hub.add_signature(name,inputs,outputs)来增加签名。
例子:


def module_fn():
  inputs = tf.placeholder(dtype=tf.float32, shape=[None, 50])
  layer1 = tf.layers.fully_connected(inputs, 200)
  layer2 = tf.layers.fully_connected(layer1, 100)
  outputs = dict(default=layer2, hidden_activations=layer1)
  #添加默认签名
  hub.add_signature(inputs=inputs, outputs=outputs)
...
spec = hub.create_module_spec(module_fn)

hub.create_modele_spec()的结果可以被用来实例化一个module对象。和使用路径或者URL不同,因为这里没有checkpoint,所以这里的module的实例用的是初始化变量,不是预先训练好的变量。

任意的module都可以通过export(path,session)来序列化到磁盘。export一个module会序列化它的定义和当前session下它的variable的值。不光在第一次export时是这样,在模型调优后也可以这样导出。

为了和TesnorFlow的Estimators兼容。hub.LatestModuleExporter 从最后的checkpoint导出模型,就像tf.estimator.LatestExporter从最后一个checkpoint导出整个模型。

模型的发布者最好发布一个通用的签名,这样调用者可以容易的在多个模型之间切换来选择最佳的模型。

Module微调(fine-tuning)

对导入的Moduel我们还可以接着训练它的模型和variable。这就是对Module的fine-tuning。
进行fine-tuning的时候,首先我们用hub.Module(…,trainable=True)来实例化这个module。这样就可以让module里的variables变为可训练的。并且引入了TensorFlow的REGULARIZATION_LOSSES。 如果module里有多个graph,你需要选择合适的grap去训练。一般来说,是tags为{“train”}的graph。

最好选择一个低一点的学习率,这样不会破坏掉已经训练好的weight。

Module 分类

预训练的Module分为Image Module,Text Module,Other Module。 这里我们以Image Module为例。

Image Modules

Image Modules里是一组用来多图像做分类的Module。通过利用它们的特征识别的能力,你可以创建你自己的用来识别你定义的分类的模型。而不需要用太多的数据和时间,达到一个不错的精度。

对于图片分类,有两种Modules:
a. 做图片分类的Module,用之前训练时设定好的分类来进行分类预测。
b. 用来对图片做特征提取的Module,然后用这些提取的特征向量(也被说成bottleneck values)再去做图像分类。

在ImageNet上预训练的Modules:

目前的Modules有:InceptionV1,V2,V3,Inception-ResNet,MobileNet,NASNet,PNASNet,ResNet V1,V2。
这些模型都有做分类的classification和特征提取的feature_vector两种Module。
下边以ResNet V2-50 为例。

ResNet V2-50

同样ResNet V2-50 也有两种模型:
classification
feature_vector

Classification

进入上边的ResNet V2-50 的classification的页面,可以看到:
Module URL: https://tfhub.dev/google/imagenet/resnet_v2_50/feature_vector/1

示例代码


module = hub.Module("https://tfhub.dev/google/imagenet/resnet_v2_50/classification/1")
height, width = hub.get_expected_image_size(module) #获取默认输入的高和宽
images = ...  # 一个训练batch,它的shape为: [batch_size, height, width, 3].
logits = module(images)  # Logits值的shape为 [batch_size, num_classes].

ResNet V2-50是可以进行fine tuning。但是对于多分类的情况,容易过拟合。
Fine-Tuning 需要把tag 设为{“train”}来导入graph,这样就可以在training的时候用BN了。

特征提取

代码示例:


module = hub.Module("https://tfhub.dev/google/imagenet/resnet_v2_50/feature_vector/1")
height, width = hub.get_expected_image_size(module)
images = ...  # image batch 的shape为 [batch_size, height, width, 3].
features = module(images)  # 返回的feature的shape为 [batch_size, num_features].

返回的feature的size为2048。对于这个模型,输入图像的高和宽为固定的224×224。输入图像的color值需要被normalized在区间[0,1]里。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

%d 博主赞过: