前言
图像标注是计算机视觉和自然语言处理领域交叉的一个热点研究方向。它的主要任务是将一张图像自动转化为自然语言的文字描述。本文主要介绍了使用 CNN 、Transformer 等技术实现图像标注的任务。相关技术有:
-
自然语言处理 NLP
-
计算机视觉 CV
-
注意力机制 Attention And Self-Attention
-
变形金刚 Transformer
-
序列到序列模型 Seq2Seq
数据集和数据预处理
数据介绍
在本文中,我们使用的数据集是 Flickr8k ,它包含了 8000 张不同主题的图像,每张图像有 5 个不同的文本描述。
数据预处理
- 图像尺寸调整:读取图像文件,并将其调整为统一的大小(例如,299x299像素)。这个统一的大小确保了输入图像的一致性。
- 图像归一化:图像像素值被标准化为 0 到 1 之间的浮点数,以便在神经网络中处理。
- 文本向量化:将文本分词,并将每个 token 转化为整数,整个文本也会转为 token 序列。我们限制了词汇表的大小为 10000 ,并设置了最大序列长度为 25 个词。
- 构造数据:每个文本序列都以
<start>
标记开头,以<end>
标记结尾,以便解码器模型知道何时开始和结束生成描述。我们将图像和文本描述配对,创建一个数据集。数据集中的每个样本包含一张图像和一个与之相关的文本序列。
结果展示
-
图像数据:已经被调整为统一大小(299x299像素)和标准化的图像张量。 图像数据示例:
lua<tf.Tensor: shape=(299, 299, 3), dtype=float32, numpy=array([[[0.43137255, 0.43529412, 0.44313726], [0.43137255, 0.43529412, 0.44313726], ... [0.43137255, 0.43529412, 0.44313726], [0.43137255, 0.43529412, 0.44313726]]], dtype=float32)>
-
文本数据:已经被分词、标记化,并转化为整数序列。每个序列以
<start>
和<end>
标记开头和结尾。 文本数据示例:xml<tf.Tensor: shape=(25,), dtype=int64, numpy= array([ 3, 2, 7, 8, 9, 10, 11, 5, 12, 13, 14, 15, 16, 17, 18, 19, 4, 0, 0, 0, 0, 0, 0, 0, 0])> (在这个示例中,`3`表示`<start>`标签,`4`表示`<end>`标签,其余数字代表词汇表中的不同单词的索引。)
模型结构
使用图像特征提取器、编码器、解码器这三个组件,可以使得模型能够从输入图像中提取信息,将其编码为一种有意义的表示,然后解码为自然语言文本,从而实现了图像标注的任务。
图像特征提取器
图像特征提取器的任务是将输入的图像转化为一种有意义的特征表示,以便编码器能够理解和处理图像信息。在本文中,我们使用了一个预训练的 EfficientNetB0 作为图像特征提取器,这是一个轻量级但性能出色的 CNN 模型。
编码器
编码器的任务是将图像特征表示进一步转化为一种语义上丰富的表示,以供解码器使用。在本文中,我们使用了 Transformer 架构的编码器。Transformer 编码器的主要内容包括:
- 自注意力机制
- 多头注意力机制
- 前馈神经网络层
- Layer Normalization
编码器的输出将被传递给解码器,用于生成文本描述。
解码器
解码器的任务是接收编码器的输出,并逐步生成图像标注的文本描述。在本文中,我们同样使用了 Transformer 架构的解码器。 Transformer 解码器的主要内容和上面类似,不同之处这里需要使用各种掩码来进行注意力特征提取和转换,并且在中间的过程中要接收来自编码器的输出作为 key 和 value 。
解码器在推理的时候从 <start>
开始逐步生成词汇表中的单词,直到生成特殊的<end>
标签,这样就得到了图像对应的文本描述。
模型的编译和训练
这里使用最常见的配置即可:
-
优化器使用 Adam
-
损失函数使用 SparseCategoricalCrossentropy
-
观察指标使用 Loss 和 Acc
结果展示
在训练了 12 epoch 后检测到了观察指标无法精进所以停止了训练,验证集准确率 0.39 ,日志打印为:
arduino
...
Epoch 12/200
96/96 [==============================] - 25s 260ms/step - 损失: 10.1508 - 准确率: 0.5445 - val_损失: 15.7716 - val_准确率: 0.3978
我们随机选择了三张图片进行了图像文本生成,下面看一下结果,虽然看起来准确率不高,但是对于文本的输出效果我还是比较满意的。
yaml
Image : Flicker8k_Dataset\3209523192_05a4cef844.jpg
Predicted Caption: a man in a blue and red pants is skiing down a hill
yaml
Image : Flicker8k_Dataset\3285993030_87b0f1d202.jpg
Predicted Caption: a small dog runs through the sand
yaml
Image : Flicker8k_Dataset\3394070357_cb2a3243fc.jpg
Predicted Caption: a dog is running through the water
挑战
- 语义准确性:生成的描述应该准确传达图像的语义信息,确保生成的描述与图像内容一致,而不仅仅是表面的含糊其辞地特征。
- 数据量:训练需要大规模的图像和文本数据,这在某些领域可能会受限。
详细实现过程可以看代码:github.com/wangdayaya/...