如何使用TensorFlow Hub和代码示例

任何深度学习框架,为了获得成功,必须提供一系列最先进的模型,以及在流行和广泛接受的机器学习数据集上训练的权重。许多框架通常将此集合称为Model Zoo。TensorFlow的初始版本通过它的TF-Slim框架提供了这个Model Zoo。但TF-Slim对模型的可用性并不直观,而且随着时间的推移,TF-Slim也被弃用了。

TensorFlow,现在已经提出了一个更好的框架,称为TensorFlow Hub,它非常容易使用,而且组织良好。使用TensorFlow Hub,您可以在几行代码中导入大型且流行的机器学习模型,从而自信地执行广泛使用的迁移学习活动。TensorFlow Hub非常灵活,提供了托管模型供其他用户使用的工具。TensorFlow Hub中的这些模型称为模块。在本文中,让我们看看如何从TensorFlow Hub使用模块的基础知识,它有各种类型和代码示例。

值得注意的是,TensorFlow Hub Module仅为我们提供了包含机器学习模型体系结构的图形以及在某些机器学习数据集上训练的权重。大多数模块可以访问机器学习模型的内部层,可以根据不同的用例使用。但是,有些模块不能精细调整。在开始开发之前,建议您在TensorFlow Hub网站上查看有关该模块的说明。

先决条件的理解

接下来,让我们研究一些重要的aspects和函数,这些aspects和函数可用于了解关于TensorFlow Hub模块的更多细节。

1)模块实例化:由TensorFlow Hub网站托管用于不同目的(图像分类,文本嵌入等)的不同模型(Inception,ResNet,ElMo等)组成的各种模块。用户必须浏览模块目录,然后在完成其目的和模型后,需要复制托管模型的URL。然后,用户可以像这样实例化他的模块:

import tensorflow_hub as hub
module = hub.Module(<<Module URL as string>>, trainable=True)

如何使用TensorFlow Hub和代码示例

除了URL参数,另一个最值得注意的参数是'trainable'。如果用户希望微调/修改模型的权重,则必须将此参数设置为True 。

2)签名:模块的签名指定了使用哪个模块的目的。如果未明确提及签名,则所有模块都带有“默认”签名并使用它。对于大多数模块,当使用“默认”签名时,模型的内部层将从用户中抽象出来。用于列出模块的所有签名名称的函数是get_signature_names()。

import tensorflow_hub as hub
module = hub.Module('https://tfhub.dev/google/imagenet/inception_v3/classification/1')
print(module.get_signature_names())
# ['default', 'image_classification', 'image_feature_vector']

如何使用TensorFlow Hub和代码示例

3)预期输入:根据所使用模块的签名,每个模块都有一组预期输入。虽然大多数模块已经在TensorFlow Hub网站上记录了预期输入集(特别是“默认”签名),但有些模块还没有。在这种情况下,使用get_input_info_dict()更容易获得预期的输入及其大小和数据类型。

import tensorflow_hub as hub
module = hub.Module('https://tfhub.dev/google/imagenet/inception_v3/classification/1')
print(module.get_input_info_dict()) # When no signature is given, considers it as 'default'
# {'images': <hub.ParsedTensorInfo shape=(?, 299, 299, 3) dtype=float32 is_sparse=False>}
print(module.get_input_info_dict(signature='image_feature_vector'))
# {'images': <hub.ParsedTensorInfo shape=(?, 299, 299, 3) dtype=float32 is_sparse=False>}

如何使用TensorFlow Hub和代码示例

4)预期输出:为了在构建TensorFlow Hub模型之后构建图的剩余部分,有必要知道预期的输出类型。get_output_info_dict()函数用于此目的。请注意,对于“默认”签名,通常只有一个输出,但是当您使用非默认签名时,图表的多个图层将向您公开。

import tensorflow_hub as hub
module = hub.Module('https://tfhub.dev/google/imagenet/inception_v3/classification/1')
print(module.get_output_info_dict()) # When no signature is given, considers it as 'default'
# {'default': <hub.ParsedTensorInfo shape=(?, 1001) dtype=float32 is_sparse=False>}
print(module.get_output_info_dict(signature='image_classification'))
# {'InceptionV3/global_pool': <hub.ParsedTensorInfo shape=(?, 1, 1, 2048) dtype=float32 is_sparse=False>,
# 'InceptionV3/Logits': <hub.ParsedTensorInfo shape=(?, 1001) dtype=float32 is_sparse=False>,
# 'InceptionV3/Conv2d_2b_3x3': <hub.ParsedTensorInfo shape=(?, 147, 147, 64) dtype=float32 is_sparse=False>
# ..... Several other exposed layers...... }

如何使用TensorFlow Hub和代码示例

5)收集所需的模块层:实例化模块后,必须从模块中提取所需的层/输出并将其添加到图中。这些是一些方法:

import tensorflow as tf
import tensorflow_hub as hub
images = tf.placeholder(tf.float32, (None, 299, 299, 3))
module = hub.Module('https://tfhub.dev/google/imagenet/inception_v3/classification/1')
logits1 = module(dict(images=images)) # implies default signature
print(logits1)
# Tensor("module_apply_default/InceptionV3/Logits/SpatialSqueeze:0", shape=(?, 1001), dtype=float32)
module_features = module(dict(images=images), signature='image_classification', as_dict=True)
# module_features stores all layers in key-value pairs
logits2 = module_features['InceptionV3/Logits']
print(logits2)
# Tensor("module_apply_image_classification/InceptionV3/Logits/SpatialSqueeze:0", shape=(?, 1001), dtype=float32)
global_pool = module_features['InceptionV3/global_pool']
print(global_pool)
# Tensor("module_apply_image_classification/InceptionV3/Logits/GlobalPool:0", shape=(?, 1, 1, 2048), dtype=float32)

如何使用TensorFlow Hub和代码示例

6)初始化TensorFlow Hub操作:模块中存在的所有操作的结果输出权重/值由TensorFlow Hub以表格格式托管。这需要使用tf.tables_initializer()以及常规变量的初始化来初始化。代码块如下所示:

import tensorflow as tf
with tf.Session() as sess:
 sess.run([tf.tables_initializer(), <<other initializers>>])

如何使用TensorFlow Hub和代码示例

代码骨架块

一旦构建了包含模块,学习算法优化器,目标函数,自定义层等的完整图,这就是代码的图部分的外观。

import tensorflow as tf
import tensorflow_hub as hub
<< Create Placeholders >>
<< Create Dataset and Iterators >>
module1 = hub.Module(<< Module URL >>)
logits1 = module1(<< input_dict >>)
module2 = hub.Module(<< Module URL >>)
module2_features = module2(<< input_dict >>, signature='default', as_dict=True)
logits2 = module2_features['default']
<< Remaining graph, learning algorithms, objective function, etc >>
with tf.Session() as sess:
 sess.run([tf.tables_initializer(), << other initializers >>])
 << Remaining training pipeline >>

如何使用TensorFlow Hub和代码示例

我正在使用两个模块。第一个模块使用最小的代码构建,隐式使用默认签名和层。在第二个模块中,我明确指定了默认签名和图层。以类似的方式,我们可以指定非默认签名和图层。

1)图像分类模块

顾名思义,这些模块集用于图像分类。在这类模块中,给出了完整的网络架构。这包括用于分类的最终dense层。在这个类别的代码示例中,我将使用Inception V3模块将Kaggle的cat - dog分类问题分类为1001个ImageNet类。

import tensorflow as tf
import tensorflow_hub as hub
from Dataset import Dataset
tf.reset_default_graph()
dataset = Dataset()
module = hub.Module('https://tfhub.dev/google/imagenet/inception_v3/classification/1')
logits = module(dict(images=dataset.img_data))
softmax = tf.nn.softmax(logits)
top_predictions = tf.nn.top_k(softmax, top_k, name='top_predictions')

如何使用TensorFlow Hub和代码示例

这是为某些样本生成的输出预测集。

如何使用TensorFlow Hub和代码示例

在狗和猫中产生的分类

如果您打印这些模块的签名,其中大多数将具有总共三个签名,即“default”,“image_classification”和“image_feature_vector”。尽管'image_feature_vector'的签名出现在这类模块中,但该签名将表现出与下面解释的模块的特征向量类别相似的特征。

2)特征向量模块

这与图像分类模块非常相似,唯一的区别是模块不包括最终的密集分类层。在这个类别的代码示例中,我将针对Hackerearth的多标签动物属性分类问题微调Resnet-50模块。 在微调操作期间,经常需要优化模块的最后一层,除了您自定义添加的密集层。在这些场景中,您必须找到希望进行微调的范围或变量的名称。我附上了相关的代码部分,在Feature Vector模块中执行这个过程。

module = hub.Module('https://tfhub.dev/google/imagenet/resnet_v2_50/feature_vector/1',
 trainable=True) # Trainable is True since we are going to fine-tune the model
module_features = module(dict(images=dataset.image_data), signature="image_feature_vector",
 as_dict=True)
features = module_features["default"]
with tf.variable_scope('CustomLayer'):
 weight = tf.get_variable('weights', initializer=tf.truncated_normal((2048, n_class)))
 bias = tf.get_variable('bias', initializer=tf.ones((n_class)))
 logits = tf.nn.xw_plus_b(features, weight, bias)
# Find out the names of all variables present in graph
print(tf.all_variables())
# After finding the names of variables or scope, gather the variables you wish to fine-tune
var_list = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='CustomLayer')
var_list2 = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='module/resnet_v2_50/block4')
var_list.extend(var_list2)
# Pass this set of variables into your optimiser
optimizer = tf.train.AdamOptimizer(learning_rate=lr).minimize(loss, var_list=var_list)

如何使用TensorFlow Hub和代码示例

如果模块图中的节点没有直观地命名(非常不可能的情况),则必须弄清楚模块的体系结构,然后将它们映射到正在打印的节点。

在代码示例中,我已经调整了最后几层变量属于'resnet_v2_50 / block4'变量范围的变量。通过10个epochs的训练,你可以毫不费力地获得这个问题的F1分数0.95819。

3)视频分类模块

视频分类是指对视频片段中发生的活动的性质进行分类。在代码示例中,我已经在Inception 3D模块上训练了包含27个类的20BN-Jester机器学习数据集。再次,只有3个训练epochs,我的准确率达到了91.45%。模块代码的相关部分如下所示。

import tensorflow as tf
import tensorflow_hub as hub
from Dataset import Dataset
dataset = Dataset()
module = hub.Module("https://tfhub.dev/deepmind/i3d-kinetics-400/1", trainable=True)
features = module(dict(rgb_input=dataset.image_data))
n_class = 27
with tf.variable_scope('CustomLayer'):
 weight = tf.get_variable('weights',
 initializer=tf.truncated_normal((400, n_class)))
 bias = tf.get_variable('bias', initializer=tf.ones((n_class)))
 logits = tf.nn.xw_plus_b(features, weight, bias)

如何使用TensorFlow Hub和代码示例

为了测试模型的准确性,我构建了一个简单的实时视频分类应用程序,这里是一个小视频。

如何使用TensorFlow Hub和代码示例

使用TensorFlow Hub构建的实时视频分类

4)文本嵌入模块

TensorFlow Hub不仅提供了英语文本嵌入模块,还提供了德语、韩语、日语等其他语言的文本嵌入模块(撰写本文时),其中许多模块在句子级别而不是单词级别生成嵌入。在代码示例中,我研究了Kaggle对电影评论的情感分析。利用ELMO嵌入式模块,分别对网络进行了句子级和单词级的嵌入式训练。该网络由单层双向LSTM构成。在句子层面,经过6个epochs的训练,准确率达到65%。附加模块代码的相关部分。

module = hub.Module('https://tfhub.dev/google/elmo/2', trainable=True)
embeddings = module(dict(text=dataset.text_data))
embeddings = tf.expand_dims(embeddings, axis=1)
with tf.variable_scope('Layer1'):
 cell_fw1 = tf.nn.rnn_cell.LSTMCell(num_units=128, state_is_tuple=True)
 cell_bw1 = tf.nn.rnn_cell.LSTMCell(num_units=128, state_is_tuple=True)
 outputs1, states1 = tf.nn.bidirectional_dynamic_rnn(
 cell_fw=cell_fw1,
 cell_bw=cell_bw1,
 inputs=embeddings)
rnn_output = tf.reshape(outputs1[0], (-1, 128))
with tf.variable_scope('Layer2'):
 weight2 = tf.get_variable('weight', initializer=tf.truncated_normal((128, n_class)))
 bias2 = tf.get_variable('bias', initializer=tf.ones(n_class))
 logits = tf.nn.xw_plus_b(rnn_output, weight2, bias2)

如何使用TensorFlow Hub和代码示例

5)图像增强模块

图像增强是训练管道中必不可少的组成部分,可提高机器学习模型的准确性。没有任何图像增强模块(在编写本文时)中有任何变量,因此,这些模块不是精细可调/可训练的。使用'from_decoded_images'的签名,您可以直接将图像提供给这些模块。下面显示了示例代码块以及生成的增强图像。

import tensorflow as tf
import tensorflow_hub as hub
import tensorflow.contrib.image # Needed for Image Augmentation modules
from Dataset import Dataset
dataset = Dataset()
module = hub.Module('https://tfhub.dev/google/image_augmentation/nas_svhn/1')
input_dict = dict(image_size=image_size, # Output Image size
 images=dataset.img_data, # Has the image in Numpy data format 
 augmentation=True)
aug_images = module(input_dict, signature='from_decoded_images')

如何使用TensorFlow Hub和代码示例

如何使用TensorFlow Hub和代码示例

增强图像

当您将这个模块与管道中来自图像分类、特征向量等的其他模块结合在一起时,图像增强的真正实用就会出现。在之前使用特征向量模块训练的多标签动物属性分类问题中,我增加了crop_color图像增强模块,在相同的次数下,我的F1分数提高到了0.96244。在这个代码示例中,我使用了默认签名,它期望以编码形式的图像作为输入。现在,由于我的图像增强模块将输入图像的大小调整为固定的大小,以便由Resnet50模块进行进一步处理,我已经保存了之前自己显式调整图像大小的工作。

import tensorflow as tf
import tensorflow_hub as hub
import tensorflow.contrib.image # Needed for Image Augmentation modules
aug_module = hub.Module('https://tfhub.dev/google/image_augmentation/crop_color/1')
aug_features = aug_module(dict(encoded_images=dataset.encoded_img_data,
 image_size=image_size,
 augmentation=is_training)) # No augmentation needed for test and validation pipeline
resnet_module = hub.Module('https://tfhub.dev/google/imagenet/resnet_v2_50/feature_vector/1',
 trainable=True) 
img_features = resnet_module(dict(images=aug_features))
with tf.variable_scope('CustomLayer'):
 weight = tf.get_variable('weights', initializer=tf.truncated_normal((2048, n_class)))
 bias = tf.get_variable('bias', initializer=tf.ones((n_class)))
 logits = tf.nn.xw_plus_b(img_features, weight, bias)

如何使用TensorFlow Hub和代码示例

6)对象检测模块

对象检测模块不支持微调,因此如果您有自己的机器学习数据集,则必须从头开始执行训练。目前也不支持批量处理数据。在代码示例中,我将仅使用Inception-ResNet V2模块上的FasterRCNN对图像进行推断。我附上了下面模块生成的代码和图像的模块部分。

import tensorflow as tf
import tensorflow_hub as hub
from Dataset import Dataset
dataset = Dataset()
module = hub.Module('https://tfhub.dev/google/faster_rcnn/openimages_v4/inception_resnet_v2/1')
detector = module(dict(images=dataset.image_data), as_dict=True)
class_entities = detector['detection_class_entities']
boxes = detector['detection_boxes']
scores = detector['detection_scores']
class_labels = detector['detection_class_labels']
class_names = detector['detection_class_names']

如何使用TensorFlow Hub和代码示例

如何使用TensorFlow Hub和代码示例

物体检测模块

7)Generator模块

这些对应于生成性对抗网络(GAN)。一些模块没有暴露其网络的Discriminator部分。就像对象检测一样,即使在代码示例中,我也只是在进行推理。使用在CelebA数据集上训练的Progressive GAN模块,我将生成新面孔。我附上了下面模块生成的代码和图像的模块部分。

import tensorflow as tf
import tensorflow_hub as hub
from Dataset import Dataset
dataset = Dataset()
module = hub.Module("https://tfhub.dev/google/progan-128/1")
images = module(dataset.latent_vector_space)

如何使用TensorFlow Hub和代码示例

如何使用TensorFlow Hub和代码示例

从Generator模块的渐进式GAN生成的图像

相关推荐