multi-label基本实现方法以及如何提高extreme分类label的训练速度

1 分类任务

1.1 multi-class

在分类任务中,multi-class分类,一个样本只对应一个label。假设分类任务中总label数量为 N N N,则每个样本对应的标签label转成one-hot形式为 [ 0 , 0 , . . , 1..0 ] [0,0,..,1..0] [0,0,..,1..0],是一个长度为 N N N的向量,且只有一个1代表了索引对应的label位置。
tensorflow里针对multi-class计算loss函数主要有三个:

  • tf.nn.softmax_cross_entropy_with_logits
  • tf.nn.softmax_cross_entropy_with_logits_v2
  • tf.losses.softmax_cross_entropy

代码例子如下:

cross_entropy = tf.nn.softmax_cross_entropy_with_logits_v2(logits=logits, labels=one_hot_y)
loss = tf.reduce_mean(cross_entropy)
optimizer = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)

# metric
prob = tf.nn.softmax(logits, name='prob')
predictions = tf.argmax(prob, axis=1, name='predictions')
accuracy = tf.reduce_mean(tf.cast(tf.equal(predictions,y_true), tf.float32))

说明:tf.nn.softmax_cross_entropy_with_logits_v2相对 tf.nn.softmax_cross_entropy_with_logits区别在于BP反向计算梯度的时候,不仅会作用于logits还会作用于labels (比如对抗学习任务),而tf.nn.softmax_cross_entropy_with_logits只会作用于labels。不过当labels是placeholders的时候,用tf.nn.softmax_cross_entropy_with_logits_v2与tf.nn.softmax_cross_entropy_with_logits没区别,因为placeholder形式没有参数可以求梯度的。

1.2 multi-label

在mulit-label分类中,与multi-class的区别是,一个样本可能对应多个label,label转成one-hot形式 [ 0 , 1 , . . , 1..0 ] [0,1,..,1..0] [0,1,..,1..0],长度为 N N N的向量,有1个或者多个1,分别代表了索引位置对应的多个label。
tensorflow提供的计算loss函数如下:

  • tf.nn.sigmoid_cross_entropy_with_logits
  • tf.nn.weighted_cross_entropy_with_logits
  • tf.losses.sigmoid_cross_entropy

代码例子如下:

cross_entropy = tf.nn.sigmoid_cross_entropy_with_logits(logits=logits, labels=one_hot_y)
loss = tf.reduce_mean(tf.reduce_sum(cross_entropy, axis=1))
prediction = tf.sigmoid(logits)
output = tf.cast(prediction >threshold, tf.int32)
train_op = tf.train.AdamOptimizer(0.001).minimize(loss)

2 multi-label分类方法

2.1 多个独立的二分类器

可以把multi-label分类用 N N N个独立的二分类器来做 N N N个multi-label的分类。最后一层包含了 N N N个独立的sigmoi (logistics) 激活函数,通过一个阈值threshold来输出多个类别。如下图所示:
在这里插入图片描述

2.1.1 小结

方法容易理解,模型也较容易训练,但忽视了label与label之间的语义关系,比如在上图中,"Woman"类和“Girl”类就存在一定的相似性,但是因为每个二分类器都是一个独立的分类器,每个label的预测不会考虑其它label之间的关系。

2.2 KNN方式

训练模型学习样本与label是否匹配任务来做分类,主要形式有两种:

  • 第一:将样本和label拼接成一句话输入模型,最后一层是一个二分类器
  • 第二:训练一个双塔模型,提取样本和label的特征向量,计算向量相似性来判断样本与label的匹配
    上面两个方法主要都是让模型有区分样本是否和label匹配的问题,类似问模型这样一个问题:“这张图是狗还是不是?”

2.2.1 小结

样本制作考虑问题较多,比如负样本采样等问题,同时预测的时候需要对样本和每个label组合的pair对都进行一次预测,复杂度较高。

2.3 seq2seq方式

这种方式利用seq2seq框架,类似机器翻译任务,只是这里对输入 x x x进行编码,通过解码器来预测对应的 y y y label序列。该方法可以学习label与label之间的关系,如上面提到的,"woman"类别和"girl"类别是有相关性的,seq2seq在解码阶段可以对label与label之间的关系进行学习

2.3.1 小结

seq2seq模型相对计算复杂度较高,同时由于seq2seq在解码阶段本身存在语言连贯性挑战等问题

3 如何提高extreme multi-label或者multi-class分类速度

extreme multi-label或者multi-class主要挑战任务是需要对样本从很大的一个label空间中预测相关的label集,比如文本分类任务中,维基百科有将近50w的分类label,亚马逊有将近1.3万的label。由于很大的label空间,频率很低的label数据样本不足,导致数据稀疏,类别样本不平衡问题严重,训练复杂度也较高

3.1 候选采样 (Candidate Sampling)

在multi-class或者multi-label任务中,每个训练样本 ( x i , T i ) (x_i, T_i) (xi,Ti),由上下文 x i x_i xi和对应的正labels T i T_i Ti组成,其中 T i T_i Ti是总label集合的 L L L的小部分,我们希望学习一个函数 F ( x , y ) F(x,y) F(x,y),预测 x x x对应每个 y y y类别的概率。由于对每个 y ∈ L y \in L yL,我们都需要计算 F ( x , y ) F(x,y) F(x,y)概率值,当 ∣ L ∣ \begin{vmatrix} L\end{vmatrix} L很大时,计算代价将会十分大。候选集采样方法针对每个样本 ( x i , T i ) (x_i, T_i) (xi,Ti),我们只需要计算 F ( x , y ) F(x,y) F(x,y),对于一小部分的候选类别 C i ⊂ L C_i \subset L CiL的概率值,一般 C i C_i Ci是由其中正label T i T_i Ti和随机采样label S i ⊂ L S_i \subset L SiL组成的,即:
C i = T i ∪ S i C_i = T_i \cup S_i Ci=TiSi
下面是一些候选集不同采样算法的对比情况:

正label 负采样label 训练loss
Noise Contrastive Estimation(NCE) T i T_i Ti S i S_i Si Logistic
Negative Sampling T i T_i Ti S i S_i Si Logistic
Sampled Logistic T i T_i Ti ( S i − T i ) (S_i-T_i) (SiTi) Logistic
Full Logistic T i T_i Ti ( L − T i ) (L-T_i) (LTi) Logistic
Full Softmax T i = t i T_i={t_i} Ti=ti ( L − T i ) (L-T_i) (LTi) Softmax
Sampled Softmax T i = t i T_i={t_i} Ti=ti ( S i − T i ) (S_i-T_i) (SiTi) Softmax

NCE,Negative Sampling和Sampled Softmax都是通过对负label进行采样,缩减 F ( x , y ) F(x,y) F(x,y)在整个label集 ∣ L ∣ \begin{vmatrix} L \end{vmatrix} L的计算。
下面是NCE在tensorflow里提供的计算loss函数形式:

tf.nn.nce_loss(weights = nec_weights,   #[num_classes, dim]最后分类层权重参数
			    biases = nec_biases,    #[num_classes] 分类偏差
			    labels = train_labels,   # [batch_size, num_true] 输入的标签
			    inputs = embed,          #[batch_size, dim] 输入的向量
			    num_sampled = num_sampled,  # int 负采样个数
			    num_classes = num_classes,  # int 分类的总类别数
			    num_true = num_true)        # int 样本的正样本数

3.2 hierarchical softmax

层级softmax速度优化主要思想是对分类label ∣ L ∣ \begin{vmatrix} L \end{vmatrix} L进行哈夫曼编码,则每个label的计算复杂度由 O ( L ) O(L) O(L)降低到 O ( l o g 2 L ) O(log_2L) O(log2L),具体原理和实现可以参考我的上一篇层次softmax (hierarchical softmax)理解 博文

4 参考

Noise-contrastive estimation: A new estimation principle for
unnormalized statistical models

What is Candidate Sampling
https://github.com/tensorflow/tensorflow/blob/r1.2/tensorflow/python/ops/nn_impl.py#L1269

猜你喜欢

转载自blog.csdn.net/BGoodHabit/article/details/109429665