triplet_sample_layer的实现

本文介绍了一个自定义的 Triplet Sample Layer 的实现方法,该层用于将输入 blob 分解为 triplet_loss_layer 所需的三个部分。文章提供了详细的 C++ 和 CUDA 代码示例,并解释了如何设置和调整层的参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://blog.youkuaiyun.com/tangwei2014/article/details/46812153

博客中写了triplet_loss_layer的详细实现过程。但是,很多人(包括我)留言,不知道怎么用?不知道三元组怎么组装?


后来索性仿照网上一个python的实现思路,自己在前面加了一层triplet_sample_layer作为接口的过渡。现分享给大家。

功能就是,实现一个blob分解成对应的triplet_loss_layer需要的三个blob。

输出四个blob中,最后一个blob是为了适应上面博文的接口,作为冗余。

输入两个blob,也有冗余,可以不用输入标签的。

data_layer层读入的应该是三元组顺序正确(而不是随机乱序的)的路径、标签对文件。

其实,本质上仅仅实现了类似slice的功能。并没有做什么计算。

第一次向caffe中添加layer,特开通博客,留作纪念。

希望能对像我一样的菜鸟入门时,有所帮助。


1.triplet_sample_layer.hpp文件:

#ifndef CAFFE_TRIPLET_SAMPLE_LAYER_HPP_

#define CAFFE_TRIPLET_SAMPLE_LAYER_HPP_


#include <vector>
#include "caffe/blob.hpp"
#include "caffe/layer.hpp"
#include "caffe/proto/caffe.pb.h"


namespace caffe {
/**
* @brief Computes the triplet sample
*/
template <typename Dtype>
class TripletSampleLayer : public Layer < Dtype > {
public:
virtual void Reshape(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top);


explicit TripletSampleLayer(const LayerParameter& param)
:Layer<Dtype>(param){}
virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top);


virtual inline int ExactNumBottomBlobs() const { return 2; }
virtual inline int ExactNumTopBlobs() const { return 4; }
virtual inline const char* type() const { return "TripletSample"; }


virtual inline bool AllowForceBackward(const int bottom_index) const {
return bottom_index != 4;
}


protected:
virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top);
virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top);


virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
};


}  // namespace caffe


#endif  // CAFFE_TRIPLET_SAMPLE_LAYER_HPP_


2.triplet_sample_layer.cpp文件:

/*
* triplet_sample_layer.cpp
*
*  Created on: 2016.09.01
*      Author: hecunxin
*/


#include <algorithm>  
#include <vector>  


#include "caffe/layer.hpp"  
#include "caffe/layers/triplet_sample_layer.hpp"  
#include "caffe/util/io.hpp"  
#include "caffe/util/math_functions.hpp"  


namespace caffe {


template <typename Dtype>
void TripletSampleLayer<Dtype>::LayerSetUp(
const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
Layer<Dtype>::LayerSetUp(bottom, top);


CHECK_EQ(bottom[0]->num(), bottom[1]->num());


CHECK_EQ(bottom[0]->height(), 1);
CHECK_EQ(bottom[0]->width(), 1);


CHECK_EQ(bottom[1]->channels(), 1);
CHECK_EQ(bottom[1]->height(), 1);
CHECK_EQ(bottom[1]->width(), 1);

return;
}


template <typename Dtype>
void TripletSampleLayer<Dtype>::Forward_cpu(
const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) 
{
int j = 0;

const Dtype* bottom_data = bottom[0]->cpu_data();
Dtype* top_data_anchor = top[0]->mutable_cpu_data(); //anchor,
Dtype* top_data_positive = top[1]->mutable_cpu_data(); //positive,
Dtype* top_data_negative = top[2]->mutable_cpu_data(); //negative,
Dtype* top_data_w = top[3]->mutable_cpu_data(); //w
const int count = top[0]->num();
for (int i = 0; i < count; ++ i)
{
caffe_copy(top[0]->channels() * top[0]->height() * top[0]->width(), bottom_data + i * 3 + 0, top_data_anchor + i); //anchor,
caffe_copy(top[0]->channels() * top[0]->height() * top[0]->width(), bottom_data + i * 3 + 1, top_data_positive + i); //positive,
caffe_copy(top[0]->channels() * top[0]->height() * top[0]->width(), bottom_data + i * 3 + 2, top_data_negative + i); //negative,
top_data_w[i] = Dtype(1.);
}
}


template <typename Dtype>
void TripletSampleLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom)
{
if (propagate_down[0]) 
{
const int count = top[0]->num();
const Dtype* top_diff_anchor = top[0]->cpu_diff(); //anchor,
const Dtype* top_diff_positive = top[1]->cpu_diff(); //positive,
const Dtype* top_diff_negative = top[2]->cpu_diff(); //negative,
Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
for (int i = 0; i < count; ++ i)
{
caffe_copy(top[0]->channels() * top[0]->height() * top[0]->width(), top_diff_anchor + i, bottom_diff + i * 3 + 0); //anchor,
caffe_copy(top[0]->channels() * top[0]->height() * top[0]->width(), top_diff_positive + i, bottom_diff + i * 3 + 1); //positive,
caffe_copy(top[0]->channels() * top[0]->height() * top[0]->width(), top_diff_negative + i, bottom_diff + i * 3 + 2); //negative,
}
}
}


template <typename Dtype>
void TripletSampleLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
int count_ = bottom[0]->count() / 3;
vector<int> shape;
shape.push_back(bottom[0]->num() / 3);
shape.push_back(bottom[0]->channels());
shape.push_back(bottom[0]->height());
shape.push_back(bottom[0]->width());


for (int i = 0; i < top.size() - 1; ++i)
{
CHECK_NE(top[i], bottom[0]) << this->type() << " Layer does not "
"allow in-place computation.";
top[i]->Reshape(shape);
CHECK_EQ(count_, top[i]->count());
}
vector<int> shape3;
shape3.push_back(bottom[0]->num() / 3);
shape3.push_back(1);
shape3.push_back(1);
shape3.push_back(1);
top[3]->Reshape(shape3);


LOG(INFO) << "bottom0 shape:" << bottom[0]->shape_string();
LOG(INFO) << "bottom1 shape:" << bottom[1]->shape_string();




LOG(INFO) << "Top0 shape:" << top[0]->shape_string();
LOG(INFO) << "Top1 shape:" << top[1]->shape_string();
LOG(INFO) << "Top2 shape:" << top[2]->shape_string();
LOG(INFO) << "Top3 shape:" << top[3]->shape_string();
return;
}


#ifdef CPU_ONLY  
STUB_GPU(TripletSampleLayer);
#endif  


INSTANTIATE_CLASS(TripletSampleLayer);
REGISTER_LAYER_CLASS(TripletSample);


}  // namespace caffe  


3.triplet_sample_layer.cu文件:

/*
* triplet_sample_layer.cpp
*
*  Created on: 2016.09.08
*      Author: hecunxin
*/


#include <algorithm>  
#include <vector>  


#include "caffe/layer.hpp"  
#include "caffe/util/io.hpp"  
#include "caffe/util/math_functions.hpp"  
#include "caffe/layers/triplet_sample_layer.hpp"


namespace caffe {


template <typename Dtype>
void TripletSampleLayer<Dtype>::Forward_gpu(
const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
/*Forward_cpu(bottom, top);
return;*/


int j = 0;


const Dtype* bottom_data = bottom[0]->gpu_data();
Dtype* top_data_anchor = top[0]->mutable_gpu_data(); //anchor,
Dtype* top_data_positive = top[1]->mutable_gpu_data(); //positive,
Dtype* top_data_negative = top[2]->mutable_gpu_data(); //negative,
Dtype* top_data_w = top[3]->mutable_gpu_data(); //w
const int count = top[0]->num();
for (int i = 0; i < count; ++i)
{
caffe_gpu_memcpy(top[0]->channels() * top[0]->height() * top[0]->width(), bottom_data + i * 3 + 0, top_data_anchor   + i); //anchor,
caffe_gpu_memcpy(top[0]->channels() * top[0]->height() * top[0]->width(), bottom_data + i * 3 + 1, top_data_positive + i); //positive,
caffe_gpu_memcpy(top[0]->channels() * top[0]->height() * top[0]->width(), bottom_data + i * 3 + 2, top_data_negative + i); //negative,
caffe_gpu_set(top[3]->channels() * top[3]->height() * top[3]->width(), Dtype(1.), top_data_w + i);
//top_data_w[i] = Dtype(1.);
}
return;
}



template <typename Dtype>
void TripletSampleLayer<Dtype>::Backward_gpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) {

/*Backward_cpu(top, propagate_down, bottom);
return;*/


if (propagate_down[0])
{
const int count = top[0]->num();
const Dtype* top_diff_anchor = top[0]->gpu_diff(); //anchor,
const Dtype* top_diff_positive = top[1]->gpu_diff(); //positive,
const Dtype* top_diff_negative = top[2]->gpu_diff(); //negative,
Dtype* bottom_diff = bottom[0]->mutable_gpu_diff();
for (int i = 0; i < count; ++i)
{
caffe_gpu_memcpy(top[0]->channels() * top[0]->height() * top[0]->width(), top_diff_anchor + i,   bottom_diff + i * 3 + 0); //anchor,
caffe_gpu_memcpy(top[0]->channels() * top[0]->height() * top[0]->width(), top_diff_positive + i, bottom_diff + i * 3 + 1); //positive,
caffe_gpu_memcpy(top[0]->channels() * top[0]->height() * top[0]->width(), top_diff_negative + i, bottom_diff + i * 3 + 2); //negative,
}
}
return;
}


INSTANTIATE_LAYER_GPU_FUNCS(TripletSampleLayer);


}  // namespace caffe  



C:\Users\wsco\anaconda3\envs\py3.9_torch11.3.1_cuda11.3\python.exe C:\Users\wsco\Desktop\HREM-main\train.py Some weights of the model checkpoint at bert-base-uncased were not used when initializing BertModel: ['cls.predictions.bias', 'cls.predictions.transform.dense.weight', 'cls.seq_relationship.weight', 'cls.seq_relationship.bias', 'cls.predictions.transform.LayerNorm.bias', 'cls.predictions.decoder.weight', 'cls.predictions.transform.LayerNorm.weight', 'cls.predictions.transform.dense.bias'] - This IS expected if you are initializing BertModel from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model). - This IS NOT expected if you are initializing BertModel from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model). GraphLoss( (base_loss): TripletLoss() (gnn_loss): TripletLoss() (gnn): TransformerEncoder( (layers): ModuleList( (0): TransformerEncoderLayer( (self_attn): MultiheadAttention( (out_proj): NonDynamicallyQuantizableLinear(in_features=1024, out_features=1024, bias=True) ) (linear1): Linear(in_features=1024, out_features=1024, bias=True) (dropout): Dropout(p=0.1, inplace=False) (linear2): Linear(in_features=1024, out_features=1024, bias=True) (norm1): LayerNorm((1024,), eps=1e-05, elementwise_affine=True) (norm2): LayerNorm((1024,), eps=1e-05, elementwise_affine=True) (dropout1): Dropout(p=0.1, inplace=False) (dropout2): Dropout(p=0.1, inplace=False) ) ) ) (adj_model): AdjacencyModel( (adj_learning): AdjacencyLearning( (mlp_t2i): Sequential( (0): Linear(in_features=10, out_features=10, bias=True) (1): ReLU(inplace=True) (2): Dropout(p=0.0, inplace=False) (3): Linear(in_features=10, out_features=1, bias=True) ) (mlp_i2t): Sequential( (0): Linear(in_features=10, out_features=10, bias=True) (1): ReLU(inplace=True) (2): Dropout(p=0.0, inplace=False) (3): Linear(in_features=10, out_features=1, bias=True) ) ) ) ) Traceback (most recent call last): File "C:\Users\wsco\Desktop\HREM-main\train.py", line 271, in <module> main() File "C:\Users\wsco\Desktop\HREM-main\train.py", line 83, in main train(opt, train_loader, model, epoch) File "C:\Users\wsco\Desktop\HREM-main\train.py", line 143, in train for i, train_data in enumerate(train_loader): File "C:\Users\wsco\anaconda3\envs\py3.9_torch11.3.1_cuda11.3\lib\site-packages\torch\utils\data\dataloader.py", line 368, in __iter__ return self._get_iterator() File "C:\Users\wsco\anaconda3\envs\py3.9_torch11.3.1_cuda11.3\lib\site-packages\torch\utils\data\dataloader.py", line 314, in _get_iterator return _MultiProcessingDataLoaderIter(self) File "C:\Users\wsco\anaconda3\envs\py3.9_torch11.3.1_cuda11.3\lib\site-packages\torch\utils\data\dataloader.py", line 927, in __init__ w.start() File "C:\Users\wsco\anaconda3\envs\py3.9_torch11.3.1_cuda11.3\lib\multiprocessing\process.py", line 121, in start self._popen = self._Popen(self) File "C:\Users\wsco\anaconda3\envs\py3.9_torch11.3.1_cuda11.3\lib\multiprocessing\context.py", line 224, in _Popen return _default_context.get_context().Process._Popen(process_obj) File "C:\Users\wsco\anaconda3\envs\py3.9_torch11.3.1_cuda11.3\lib\multiprocessing\context.py", line 327, in _Popen return Popen(process_obj) File "C:\Users\wsco\anaconda3\envs\py3.9_torch11.3.1_cuda11.3\lib\multiprocessing\popen_spawn_win32.py", line 93, in __init__ reduction.dump(process_obj, to_child) File "C:\Users\wsco\anaconda3\envs\py3.9_torch11.3.1_cuda11.3\lib\multiprocessing\reduction.py", line 60, in dump ForkingPickler(file, protocol).dump(obj) OSError: [Errno 22] Invalid argument Traceback (most recent call last): File "<string>", line 1, in <module> File "C:\Users\wsco\anaconda3\envs\py3.9_torch11.3.1_cuda11.3\lib\multiprocessing\spawn.py", line 116, in spawn_main exitcode = _main(fd, parent_sentinel) File "C:\Users\wsco\anaconda3\envs\py3.9_torch11.3.1_cuda11.3\lib\multiprocessing\spawn.py", line 126, in _main self = reduction.pickle.load(from_parent) _pickle.UnpicklingError: pickle data was truncated 进程已结束,退出代码1 如何解决这个报错’
最新发布
08-07
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值