[CVPR 2018笔记] Discriminative Learning of Latent Features for Zero-Shot Recognition

零样本学习新进展:使用鉴别性特征实现零样本识别
Discriminative Learning of Latent Features for Zero-Shot Recognition

[CVPR 2018笔记] Discriminative Learning of Latent Features for Zero-Shot Recognition_第1张图片
本文亮点:对人类定义属性进行扩充,学习隐含属性。

ZSL

零样本学习(zero-shot learning, ZSL)详见郑哲东在知乎中的回答。它的目标是通过训练阶段从已见类别中学习到的知识,来识别未见类别。


Abstract

摘要:零样本学习(ZSL)的目标是通过学习图像表示和语义表示之间的嵌入空间来识别未见类图像的。多年来,在现有的研究成果中,中心任务都是学习对齐视觉空间和语义空间的合适映射矩阵,而忽略了学习ZSL 的鉴别性表示表征的重要性。本工作中,我们回顾了已有方法,证明了为 ZSL的视觉实例和语义实例学习鉴别性表示的必要性。我们提出了一种端到端的网络,能够做到:1)通过放大网络自动发现鉴别性区域;2)在引入用户定义属性和隐含属性的增强空间中学习鉴别性语义表示。我们提出的方法在两个很有挑战性的ZSL 数据集上进行了大量测试,实验结果表明我们提出的方法的表现显著优于之前最佳的方法。


Introduction

已有方案的缺点(drawbacks):
1,特征对ZSL任务表示性不足: 在映射前,抽取图像的特征,传统的用预训练模型等方法仍不是针对ZSL特定抽取特征的最优解。
2,用户定义属性不全面: 现有的都是学习用户定义属性,而忽略了隐含表示。
3,分类训练不能充分挖掘潜力: 低层次信息和空间是分离训练的,没有大一统的框架。

本文贡献:

  • 一种级联式放大机制,可用于学习以目标为中心的区域的特征。我们的模型可以自动识别图像中最具鉴别性的区域,然后在一个级联式的网络结构中将其放大以便学习。通过这种方式,我们的模型可以专注于从以目标为焦点的区域中学习特征。
  • 一种用于联合学习隐含属性和用户定义属性的框架。我们将隐含属性的学习问题形式化为了一个类别排序问题,以确保所学习到的属性是鉴别性的。同时,在我们模型中,鉴别性区域的发掘和隐含属性的建模是联合学习的,这两者会互相协助以实现进一步的提升。
  • 一种用于 ZSL 的端到端网络结构。所获得的图像特征可以调整得与语义空间更加兼容,该空间中既包含用户定义的属性,也包含隐含的鉴别性属性。

Latent Discriminative Features Learning(LDF)

[CVPR 2018笔记] Discriminative Learning of Latent Features for Zero-Shot Recognition_第2张图片

Notation:

FNet (The Image Feature Network) :提取图像特征;

ZNet(The Zoom Network): 定位最具判别性的区域并将其放大;

ENet(The Embedding Network): 将图像特征映射到另一个空间。

问题
1. ZNet是如何定位判别性区域的?
循环注意力机制


下面我们先介绍各个子网络

FNet

FNet的目标就是提取图像特征。文章选择了已有的VGG19/GoogleNet。

ZNet

已有研究表明对目标的区域进行学习,有利于图像级的目标分类。受此启发,我们假设图像中存在判别性区域有助于ZSL。

ZNet的目标是定位到能够增强我们提取的特征的辨识度的区域,这个区域同时也要与某一个我们已经定义好了的属性对应。

  1. ZNet的输入是FNet的最后一个卷积层的输出。
  2. 在这里运用某个已有的激活函数方法,将我们定位好了的区域提取出来,即将裁剪操作在网络中直接实现。
  3. 将ZNet的输出与输入图像做按像素的矩阵乘法。
  4. 最后,将区域放大到与输入图像相同的尺寸。

如图2所示,再将ZNet的输出输入到另一个FNet(第一个FNet的拷贝)

ENet

ENet的目的是学习一个能够将视觉和语义信息关联起来的嵌入空间。

作者提出了一个兼容性得分
(5) s = < W T ϕ ( x ) , a y > s = < W^T \phi(x), a^y > \tag{5} s=<WTϕ(x),ay>(5)

其中, ϕ ( x ) \phi(x) ϕ(x)是FNet输出的 d d d维的图像表示, a y a^y ay是属性向量。

兼容性得分的物理意义是什么?
答:The compatibility score measures the similarity between an image and the attribute annotations of classes. It is similar to the classification score in traditional object recognition task.
衡量一张图像在属性空间的投影和类别的定义/隐含属性之间的相似性(兼容性)。

Enet将图像特征映射到 2 k 2k 2k 维度的空间中。其中, 1 k 1k 1k 维对应于用户定义属性(UA),并用softmax loss;另 1 k 1k 1k 维则是对应隐含属性,为了使这些特征具有判别性,作者使用了triplet loss。

为什么UA是softmax loss,而LA是triplet loss?
答:UA是已见类的有属性/标签,隐含属性没有实际的属性。
如何学习2k维属性的?
答:学习一个W,通过调整网络中的参数。


ZSL Prediction

Predition with LA

  1. 对于源类s:
    s在UA空间中的类中心为 a s \mathbf{a}^{s} as
    s在LA空间中的类中心为特征的平均值
    ϕ l a t s ‾ = 1 N ∑ i ϕ l a t ( x i ) \overline{\phi_{lat}^{s}} = \frac{1}{N} \sum_i \phi_{lat}(x_i) ϕlats=N1iϕlat(xi)

  2. 对于一个未见类 u u u,计算 u u u在UA空间中和其他已见类的关系。
    (14) β c u = arg ⁡ min ⁡ ∣ ∣ a u − ∑ β c u a c ∣ ∣ 2 2 + λ ∣ ∣ β c u ∣ ∣ 2 2 , c ∈ Y S \beta_{c}^{u} = \arg \min || \mathbf{a}^{u} - \sum \beta_{c}^{u} \mathbf{a}^{c} ||_{2}^{2} + \lambda || \beta_{c}^{u} ||_{2}^{2}, c \in \mathcal{Y}_S \tag{14} βcu=argminauβcuac22+λβcu22,cYS(14)

  3. 利用已见类和未见类在UA空间的关系以及已见类在LA空间的表示,计算得到LA空间中的表示。
    (15) ϕ l a t u ‾ = ∑ β c u ϕ l a t u ‾ \overline{ \phi_{lat}^u} = \sum \beta_c^u { \overline {\phi_{lat}^u} } \tag{15} ϕlatu=βcuϕlatu(15)

首先,已知UA空间中源类的属性表示和目标类的属性表示,求得关系 β c u \beta_{c}^{u} βcu;然后,学到LA空间中源类的属性表示,应用关系 β c u \beta_{c}^{u} βcu,得到目标类在LA空间中的属性表示。

学已知属性空间中源类和目标类的关系,然后应用到隐含属性空间中的源类表示,得到目标类的隐含表示。


Reference

1.paper
 code
 补充材料
2.论文笔记1 - 知乎
3.论文笔记2 - RexKing6’s Note
4.论文笔记3 - 雪花新闻
5.什么是 One/zero-shot learning?

Q&A

1. 隐含特征的“特征”指的是视觉特征吗?
就是隐含的属性特征。

2. [4.1] Fnet对性能的提升有多大?
表1,AwA(CUB)数据集上有4%(9%)的提升。

3. [4.2] ZNet是如何使得到的区域,既有判别性,又有语义信息?
直观想法:目标区域期望包含一些背景信息来增强属性嵌入。通过放大网络来实现。
判别性,来自注意力机制;语义,来自于视觉语义映射。

4. [4.2] 逐元素乘法的作用?
放大网络里的技巧。

5. [Table 1] VGG比GoogLeNet好?

6. [Appendices] A U → T A_{U \rightarrow T} AUT A S → T A_{S \rightarrow T} AST 是怎么计算的?

7. 实验中,cZSL设定下 M C A MCA MCA在50%左右,为什么gZSL中的 M C A t MCA_t MCAt只有不到20%?

代码阅读

train_ldf.py

        feature = tf.squeeze(feature, axis=[1, 2])
        print('feature shape:', feature)
        feature = slim.dropout(feature, keep_prob=0.5)
        # 计算相容性得分
        logits = slim.fully_connected(feature, num_outputs=2 * FLAGS.attribute_label_cnt, activation_fn=None)
        print('logits shape', logits)

loss.py

def build_multi_loss_3(logits, gt_onehot_labels, whole_attr_labels, num_labels, margin, squared=False,
                       triplet_strategy='batch_hard', optimizer='Adam', freeze=False, variable_to_train=None):
    y_conv = tf.reshape(logits, [-1, 2 * FLAGS.attribute_label_cnt])

    y_conv_softmax = y_conv[:, 0:FLAGS.attribute_label_cnt]
    y_conv_triplet = y_conv[:, FLAGS.attribute_label_cnt:2 * FLAGS.attribute_label_cnt]

    print(y_conv, y_conv_softmax, y_conv_triplet)

    # build softmax loss 分类损失
    # (16,30) x (230,30).T output (16, 230), compatibility score
    whole_inner_product = tf.matmul(y_conv_softmax, tf.transpose(whole_attr_labels))

    with tf.name_scope('softmax_loss_with_score'):
        softmax_loss_with_score = tf.reduce_mean(
            tf.nn.softmax_cross_entropy_with_logits(logits=whole_inner_product, labels=gt_onehot_labels))
        tf.summary.scalar('softmax_loss_with_score', softmax_loss_with_score)

    # Define triplet loss 三元组损失
    with tf.name_scope('triplet_loss'):
        if triplet_strategy == "batch_all":
            triplet_loss, fraction = batch_all_triplet_loss(labels=num_labels,
                                                            embeddings=y_conv_triplet,
                                                            margin=margin,
                                                            squared=squared)
            tf.summary.scalar('triplet_loss', triplet_loss)
        elif triplet_strategy == "batch_hard":
            triplet_loss = batch_hard_triplet_loss(labels=num_labels,
                                                   embeddings=y_conv_triplet,
                                                   margin=margin,
                                                   squared=squared)
            tf.summary.scalar('triplet_loss', triplet_loss)
        else:
            raise ValueError("Triplet strategy not recognized: {}".format(triplet_strategy))

    with tf.name_scope('multi_loss'):
        multi_loss = softmax_loss_with_score + triplet_loss
        tf.summary.scalar('multi_loss', multi_loss)

    with tf.variable_scope('train_multi_loss'):
        global_step = tf.train.get_or_create_global_step()

        lr = tf.train.exponential_decay(FLAGS.learning_rate,
                                        global_step=global_step,
                                        decay_rate=FLAGS.lr_decay_rate,
                                        decay_steps=FLAGS.lr_decay_step)
        tf.summary.scalar('learning_rate_multi', lr)

        if freeze:
            optimizer_2 = tf.train.AdamOptimizer(lr)
            train_op = tf.contrib.slim.learning.create_train_op(multi_loss, optimizer_2,
                                                                variables_to_train=variable_to_train)
        else:
            train_op = tf.contrib.layers.optimize_loss(loss=multi_loss,
                                                       global_step=global_step,
                                                       learning_rate=lr,
                                                       optimizer=optimizer)
        return multi_loss, train_op

你可能感兴趣的:(paper)