CenterLoss---Tensorflow

  • 本文主要讲解自己对CenterLoss的一些理解,想要看原文的请戳这里
    A discriminative feature learning approach for deep face recognition
  • background
    • CenterLoss提出的主要目的是对FaceNet的改进,FaceNet使用的是triple loss,该计算方法需要我们提前计算出三元组,计算量大不说,而且收敛很慢。
    • 所以CenterLoss就被提出来了
  • 自己的理解
    • 其实CenterLoss的想法也很简单,感觉和聚类有异曲同工之妙。
    • 常用的Softmax loss一般只关注于让我们不同的类可以被正确的被分开就可以了,比如下图所示的MNIST数据集使用softmaxloss 训练,提取出来features可视化之后的结果。
      image
    • 我们可以看到,虽然的确不同的类别被分到了不同的地方(cluster),但是每个cluster之间距离较近,而且类内的差距较大,也就是说我们得到的features并不能通过一个较为简单的分类器将其区分开来,需要一个相对较为复杂的分类器才可以得到较好的结果。也就是说,我们得到的features并不是一个很好的特征。
    • 那么怎么改进呢?就像我们上面所说,只要让每个cluster之间的距离相对来说远一些,类内的差距小一下,那么区分起来应该就更容易了。
    • 那么具体来说怎么实现让各个cluster之间的距离远一些,类内的差距小一些呢?我们可以考虑下面的loss函数
      C=12i=1m||xicyi||22
    • 其中 xi 是我们MNIST数据集中样本对应的features, cyi 对应的是第 yi 个中心,其中 i{1,2,...,10}
    • 通过上述函数,我们自然就约束了同一个类别中的样本到质心的距离,这样就可以让同一个cluster里面的数据更加聚集。
    • 文章中也给出了更新质心的公式
      cj=mi=1δ(yi==j)(cjxi)1+mi=1δ(yi==j)cj=ccj

      • 其中 δ(yi==j) 是判断第i个sample的label是不是等于j,如果是则返回1,否则返回0
      • cj 代表的就是第j个类别的质心
      • xi 代表的是第i个样本
    • 最终我们优化的target是 =s+λc
  • 实现

    • 第一点:怎么计算CenterLoss

      • 一种是我自己写的,感觉很蠢。。。

        def calculate_centerloss(x_tensor, label_tensor, centers_tensor, category_num):
                    loss_tensor = tf.Variable(initial_value=0.0, trainable=False, dtype=tf.float32)
                    for i in range(category_num):
                        selected_x = tf.gather(x_tensor, 
                                               tf.cast(
                                                   tf.squeeze(
                                                       tf.where(
                                                           tf.equal(
                                                               label_tensor, 
                                                               [i]
                                                           ), 
                                                           None, 
                                                           None
                                                       )
                                                   ),tf.int32))
                        selected_y = tf.convert_to_tensor(centers_tensor[i], dtype=tf.float32)
                        selected_x2 = tf.multiply(selected_x, selected_x)
                        selected_y2 = tf.multiply(selected_y, selected_y)
                        selected_xy = tf.multiply(selected_x, selected_y)
                        distance_category = tf.abs(tf.subtract(tf.add(selected_x2, selected_y2), 2*selected_xy))
                        distance_category = tf.abs(tf.reduce_sum(0.5 * distance_category))
                        loss_tensor = tf.abs(tf.add(loss_tensor, distance_category))
                    return loss_tensor
      • 还有一种就两行代码,其实他的center loss其实就是l2 loss,所以可以通过下面的代码计算

        def calculate_centerloss(x_tensor, label_tensor, centers_tensor):
            centers_tensor_batch = tf.gather(centers_tensor, label_tensor)
            loss = tf.nn.l2_loss(x_tensor - centers_tensor_batch)
            return loss
      • 大家有兴趣可以跑一跑,两个函数的输出是一样的,不过明显下面的简洁很多
    • 第二点:怎么更新Center?

      • 这里面牵扯两点,1、怎么计算Center更新的值;2、怎么在每次反向传播的时候执行操作1。
      • 先看第一点,怎么计算center的更新值

        def update_centers(centers, data, labels, category_num):
            centers = np.array(centers)
            data = np.array(data)
            labels = np.array(np.argmax(labels, 1))
            centers_batch = centers[labels]
            diff = centers_batch - data
            for i in range(category_num):
                cur_diff = diff[labels == i]
                cur_diff = cur_diff / (1.0 + 1.0 * len(cur_diff))
                cur_diff = cur_diff * _alpha
                for j in range(len(cur_diff)):
                    centers[i, :] -= cur_diff[j, :]
            return centers
      • 接下来我们关注第二点,怎么在每次反向传播的时候执行上述代码

        • tensorflow里面提供了py_func这个函数,通过该函数将普通的python function转化为可以在Graph 上执行的op,该函数的定义是:

          tf.py_func(func, inp, Tout, stateful=True, name=None)

          func就是我们上述的update_centers, inp是tensor类型的变量,Tout是tf.float32(注意,update_centers里面接收到的参数是numpy数组)

      • 然后在每次训练的时候,也执行该函数返回,如下面所示

        owner_step = tf.py_func(update_centers, [centers_tensor, featuresmap, label_tensor, category_num], tf.float32)
        
        # 在每次更新的时候也执行我们自己的step
        
        _, centers_value, = sess.run(
                    [train_op, owner_step], feed_dict={
                        images_tensor: train_images_batch,
                        label_tensor: train_labels_batch,
                        is_training_tensor: True,
                        centers_tensor: centers_value
                    })
  • 结果展示

    • 下面分别是不使用CenterLoss和 λ 分别等于0.01, 0.1, 1.0的结果
      image
      image
      image
      image
  • 具体实现代码:CenterLoss
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
中心损失(center loss)是一种用于人脸识别和人脸验证任务的损失函数。它的目标是学习一个特征空间,使得同一类别的样本在该空间中尽可能接近一个中心点,而不同类别的样本则远离这个中心点。 在TensorFlow中实现center loss可以遵循以下步骤: 1. 定义输入:首先,定义输入的占位符或张量,包括输入图像数据和标签。 ```python input_images = tf.placeholder(tf.float32, [None, 224, 224, 3], name='input_images') input_labels = tf.placeholder(tf.int64, [None], name='input_labels') ``` 2. 定义特征提取网络:使用一个卷积神经网络(例如ResNet或VGG)来提取图像特征。 ```python # 定义卷积神经网络模型 def conv_net(input_images): # 假设使用ResNet作为特征提取网络 # ... return features # 提取图像特征 features = conv_net(input_images) ``` 3. 定义中心点和中心损失:为每个类别定义一个中心点,并计算样本与其对应中心点的欧氏距离。 ```python # 获取类别数量 num_classes = 10 # 初始化中心点矩阵 centers = tf.get_variable('centers', [num_classes, num_features], dtype=tf.float32, initializer=tf.constant_initializer(0), trainable=False) # 计算样本与中心点的欧氏距离 distances = tf.reduce_sum(tf.square(features - tf.gather(centers, input_labels)), axis=1) ``` 4. 定义中心损失的计算方式:使用欧氏距离计算样本与中心点之间的损失,并更新中心点的位置。 ```python # 定义中心损失 center_loss = tf.reduce_mean(distances) # 更新中心点 unique_labels, unique_idx, unique_count = tf.unique_with_counts(input_labels) appear_times = tf.gather(unique_count, unique_idx) diff = features - tf.gather(centers, input_labels) diff_expand_dims = tf.expand_dims(diff, 1) centers_update_op = tf.scatter_sub(centers, input_labels, learning_rate * diff_expand_dims / tf.cast((1 + appear_times), tf.float32)) ``` 5. 定义总体损失:将中心损失和分类损失(例如交叉熵损失)相结合得到总体损失。 ```python # 定义分类损失(例如交叉熵) cross_entropy_loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(labels=input_labels, logits=logits)) # 定义总体损失 total_loss = cross_entropy_loss + alpha * center_loss ``` 6. 进行模型训练:使用优化器最小化总体损失来更新模型的参数。 ```python # 使用优化器最小化总体损失 optimizer = tf.train.AdamOptimizer(learning_rate) train_op = optimizer.minimize(total_loss) ``` 以上就是使用TensorFlow实现中心损失的基本步骤。在训练过程中,你可以通过运行`centers_update_op`来更新中心点的位置,从而将类别间的距离最小化。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值