深度哈希-DSH

论文:Deep Supervised Hashing for Fast Image Retrieval CVPR2016
源代码: https://github.com/lhmRyan/deep-supervised-hashing-DSH
论文网络结构似乎是CIFAR-10和Siamese两种网络的结合:
这里写图片描述
个人认为有两个创新点:
1、通过设计损失函数,使得最后一层的输出Binary-like。
论文修改了ContrastIve Loss,加上正则项:
这里写图片描述
这个正则项会使得最终输出的特征b1,b2的取值趋向于-1和+1。
这里写图片描述
2、generate image pairs online
这里一开始以为使用的是类似Siamese的双分支的网络结构。实则不然,只是如图所示的单支网络,重点是在作者设计的损失函数中。网络的训练是Batch为单位的,比如说每次输入n张图片,对应n个标签,在Loss函数中,使用两层循环来不重复的生成所有可能的图片对(i,j),共 n(n1)2 对,当i,j的标签相同即认为相似。这样做的好处自然是节省了很多存储空间和计算成本。文中说:To cover those image pairs across batches, in each iteration the training images are randomly selected from the whole training set.

void HashingLossLayer<Dtype>::Forward_cpu(
    const vector<Blob<Dtype>*>& bottom,
    const vector<Blob<Dtype>*>& top) {
  // initialize parameters
  Dtype* bout = bottom[0]->mutable_cpu_diff();//前向传播计算Loss的同时计算梯度
  const int num = bottom[0]->num();
  const Dtype alpha = top[0]->cpu_diff()[0] / static_cast<Dtype>(num * (num - 1));//top[0]->cpu_diff()[0]保存的是该损失层的权重,默认为1.0
  const Dtype beta = top[0]->cpu_diff()[0] / static_cast<Dtype>(num);
  const int channels = bottom[0]->channels();
  Dtype margin = this->layer_param_.hashing_loss_param().bi_margin();
  Dtype tradeoff = this->layer_param_.hashing_loss_param().tradeoff();//两种损失(ContrastiveLoss与RegularizationLoss)权衡系数
  const int label_num = bottom[1]->count() / num;
  bool sim;
  Dtype loss(0.0);//总损失
  Dtype reg(0.0);//正则化损失
  Dtype data(0.0);//输入向量每维的值
  Dtype dist_sq(0.0);//两向量距离的平方
  caffe_set(channels*num, Dtype(0), bout);
  // calculate loss and gradient
  for (int i = 0; i < num; ++i) {
    for (int j=i+1; j < num; ++j){
      caffe_sub(
    channels,
    bottom[0]->cpu_data()+(i*channels),  // a
    bottom[0]->cpu_data()+(j*channels),  // b
    diff_.mutable_cpu_data());  // a_i-b_j
      dist_sq = caffe_cpu_dot(channels, diff_.cpu_data(), diff_.cpu_data());  //D_w^2
      if (label_num > 1) {  //多标签
        sim = caffe_cpu_dot(label_num, bottom[1]->cpu_data() + (i * label_num), bottom[1]->cpu_data() + (j * label_num)) > 0;
      }
      else {
    sim = ((static_cast<int>(bottom[1]->cpu_data()[i])) == (static_cast<int>(bottom[1]->cpu_data()[j])));
      }
      if (sim) {  // similar pairs
        loss += dist_sq;
        // gradient with respect to the first sample
    caffe_cpu_axpby(
          channels,
          alpha,
          diff_.cpu_data(),
          Dtype(1.0),
          bout + (i*channels));//计算损失函数对输入向量i的梯度
        // gradient with respect to the second sample
        caffe_cpu_axpby(
          channels,
          -alpha,
          diff_.cpu_data(),
          Dtype(1.0),
          bout + (j*channels));//计算损失函数对输入向量j的梯度
      } 
      else {  // dissimilar pairs
        loss += std::max(margin - dist_sq, Dtype(0.0));
        if ((margin-dist_sq) > Dtype(0.0)) {
          // gradient with respect to the first sample
          caffe_cpu_axpby(
            channels,
            -alpha,
            diff_.cpu_data(),
            Dtype(1.0),
            bout + (i*channels));//计算损失函数对输入向量i的梯度
          // gradient with respect to the second sample
          caffe_cpu_axpby(
            channels,
            alpha,
            diff_.cpu_data(),
            Dtype(1.0),
            bout + (j*channels));//计算损失函数对输入向量j的梯度
        }
      }
    }//内层循环结束
    //只针对一个输入向量而言
    for (int k = 0; k < channels;k++){
      data = *(bottom[0]->cpu_data()+(i*channels)+k);
      // gradient corresponding to the regularizer
      //正则化部分的梯度
      *(bout + (i*channels) + k) += beta * tradeoff * (((data>=Dtype(1.0))||(data<=Dtype(0.0)&&data>=Dtype(-1.0)))?Dtype(1.0):Dtype(-1.0));
      data = std::abs(data)-1;
      reg += std::abs(data);//正则化部分的损失
    }
  }//外层循环结束
  //将两段损失各自取平均,然后相加
  loss = loss / static_cast<Dtype>(bottom[0]->num()*(bottom[0]->num()-1));
  loss += tradeoff * reg /static_cast<Dtype>(bottom[0]->num());
  top[0]->mutable_cpu_data()[0] = loss;
}

这里写图片描述
可以看到Online方式相比传统的方式收敛速度更快。这是由于每次输入到网络的图片总数目一致的情况下,比如2n张图片,Online方式可以给出 2n(2n1)2 个图片对的相关信息,而Offline(以 ijsij 方式输入)只能给出n对的相关信息。

论文还提到,最后输出bit位数的设置过大的话容易过拟合,需要先训练bit位数较少的,然后在此基础上微调。
这里写图片描述

### 深度哈希算法概述 深度哈希是一种利用深度学习模型将高维数据(如图像、文本或其他多媒体数据)映射到低维二进制编码的技术。这种技术的核心在于通过神经网络训练得到一种映射函数,使得相似的数据点在二进制空间中具有较小的汉明距离[^1]。 #### 深度哈希的主要特点 深度哈希算法能够在保持原始数据语义信息的同时,显著降低存储需求并提高检索效率。其主要特点是能够生成紧凑的二进制表示形式,适用于大规模数据库中的快速近似最近邻搜索。 --- ### 常见的深度哈希算法及其实现 以下是几种常见的深度哈希算法: #### 1. **DSH (Deep Supervised Hashing)** DSH 是一种监督式的深度哈希方法,它通过最小化成对样本之间的损失来优化哈希码的学习过程。具体来说,该算法的目标是最小化正类样本间的汉明距离,同时最大化负类样本间的汉明距离。 ```python import torch import torch.nn as nn class DSH(nn.Module): def __init__(self, input_dim, hash_bits): super(DSH, self).__init__() self.fc = nn.Linear(input_dim, hash_bits) def forward(self, x): h = self.fc(x) return torch.tanh(h) # 输出范围 [-1, 1] # 初始化模型 model = DSH(input_dim=784, hash_bits=32) ``` #### 2. **DPSH (Deep Pairwise Supervised Hashing)** DPSH 进一步改进了成对标记的处理方式,采用基于三元组损失的方法,在训练过程中更加关注难分样本对的影响。 #### 3. **DHN (Deep Hashing Network)** DHN 提出了端到端的框架设计思路,允许直接从输入数据中提取特征并通过离散约束生成最终的二进制哈希码。 #### 4. **DSDH (Deep Supervised Discrete Hashing)** DSDH 则专注于解决连续松弛问题,引入了一种新的目标函数以确保生成的哈希码尽可能接近理想的离散值。 --- ### 应用场景分析 深度哈希广泛应用于多个领域,特别是在需要高效检索的大规模数据集上表现优异。以下是一些典型的应用案例: #### 图像检索 通过对大量图片进行预处理和编码,可以构建索引结构以便于后续查询操作。例如电商平台的商品推荐系统可能依赖于此技术完成视觉相似商品查找任务。 #### 文本匹配 自然语言处理中的文档摘要生成或者跨语言翻译质量评估都可以借助深度哈希加速候选集合筛选阶段的工作流程。 #### 数据去重 当面对海量日志记录或者其他重复率较高的业务场景时,运用一致性哈希配合深度哈希可有效减少冗余存储开销[^2][^3]。 ---
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值