网站优化怎么看,人防门电气图纸符号大全久久建筑网,在苏州找学生做家教在哪个网站,85同城找工作招聘今天要讲的这一注册机制用到了设计模式中的工厂模式和单例模式#xff0c;所以这节课也是对两大设计模式的一个合理应用和实践。KuiperInfer的注册表是一个map数据结构#xff0c;维护了一组键值对#xff0c;key是对应的OpType#xff0c;用来查找对应的value#xff0c;…今天要讲的这一注册机制用到了设计模式中的工厂模式和单例模式所以这节课也是对两大设计模式的一个合理应用和实践。KuiperInfer的注册表是一个map数据结构维护了一组键值对key是对应的OpType用来查找对应的valuevalue是用于创建该层的对应方法(Creator)。我们可以看一下KuiperInfer中的Layer注册表实现 typedef std::mapOpType, Creator CreateRegistry;OpType就是头文件中对应的索引
创建该层的对应方法相当于一个工厂(Creator)Creator如下的代码所示是一个函数指针类型我们将存放参数的Oprator类传入到该方法中然后该方法根据Operator内的参数返回具体的Layer.
typedef std::shared_ptrLayer (*Creator)(const std::shared_ptrOperator op);代表的是返回值为std::shared_ptrLayer 然后参数为const std::shared_ptrOperator op的一类函数
只要返回值和参数的类型\个数都满足 creator就可以指向对应的函数
对应函数就是创建层layer的一个具体方法
所以目前就是这个样子
ReluLayer定义完成---LayerRegistererWrapper --- RegisterCreator
接下来我们再看这个registor注册方法
void LayerRegisterer::RegisterCreator(OpType op_type, const Creator creator) {CHECK(creator ! nullptr) Layer creator is empty;CreateRegistry registry Registry(); //实现单例的关键// 根据operator typeCHECK_EQ(registry.count(op_type), 0) Layer type: int(op_type) has already registered!;// ReluLayer::CreateInstance 没有被注册过,就塞入到注册表当中registry.insert({op_type, creator});
} 先来补充一下单例模式 单例设计编程模式 全局当中有且只有一个变量 任意次和任意一方去调用都会得到这个唯一的变量 这里的唯一变量是全局的注册表 存的时候是这个,取得时候也需要是这个 这里的Registry也写上了就是实现单例的关键
LayerRegisterer::CreateRegistry LayerRegisterer::Registry() {// C程序员高频面试点static CreateRegistry *kRegistry new CreateRegistry();// 没有static 那就是调用一次初始化一次// 不构成单例CHECK(kRegistry ! nullptr) Global layer register init failed!;return *kRegistry; // 返回了这个注册表
} static CreateRegistry *kRegistry new CreateRegistry(); 这个其实只会被初始化一次 简单来说第一次,调用的时候 new CreateRegistry 存放到一个kRegistry (static) 后续调用的时候,只会返回kRegistry (static) 这是一种C的特性。 如果没有static那就是调用一次就初始化一次就自然构不成单例模式。
layer_factory.cpp: namespace kuiper_infer {
// OpType::kOperatorRelu 就是刚才还说的OpType
// ReluLayer::CreateInstance就是一个函数指针,用来初始化层的方法// 单例设计编程模式
// 全局当中有且只有一个变量
// 任意次和任意一方去调用都会得到这个唯一的变量
// 这里的唯一变量是全局的注册表 存的时候是这个,取得时候也需要是这个
// typedef std::mapOpType, Creator CreateRegistry
// 全局当中有且只有一个 CreateRegistry 的实例
// 什么方法来控制这个变量唯一呢
void LayerRegisterer::RegisterCreator(OpType op_type, const Creator creator) {CHECK(creator ! nullptr) Layer creator is empty;CreateRegistry registry Registry(); //实现单例的关键// 根据operator typeCHECK_EQ(registry.count(op_type), 0) Layer type: int(op_type) has already registered!;// ReluLayer::CreateInstance 没有被注册过,就塞入到注册表当中registry.insert({op_type, creator});
}CreateRegistry registry Registry(); //实现单例的关键
这个就是上面的Registry之后作检查如果已经有过的话那count之后就该报错啦。 CHECK_EQ(registry.count(op_type), 0) Layer type: int(op_type) has already registered!;
没有注册机制的create
然后我们来看一下没有注册机制前的createrelu是怎么做到的
TEST(test_layer, forward_relu1) {using namespace kuiper_infer;float thresh 0.f;// 初始化一个relu operator 并设置属性std::shared_ptrOperator relu_op std::make_sharedReluOperator(thresh);// 有三个值的一个tensorfloatstd::shared_ptrTensorfloat input std::make_sharedTensorfloat(1, 1, 3);input-index(0) -1.f; //output对应的应该是0input-index(1) -2.f; //output对应的应该是0input-index(2) 3.f; //output对应的应该是3// 主要第一个算子经典又简单我们这里开始std::vectorstd::shared_ptrTensorfloat inputs; //作为一个批次去处理std::vectorstd::shared_ptrTensorfloat outputs; //放结果inputs.push_back(input);ReluLayer layer(relu_op);// 因为是4.1 所以没有作业 4.2才有
// 一个批次是1layer.Forwards(inputs, outputs);ASSERT_EQ(outputs.size(), 1);
//记得切换分支!!!!!for (int i 0; i outputs.size(); i) {ASSERT_EQ(outputs.at(i)-index(0), 0.f);ASSERT_EQ(outputs.at(i)-index(1), 0.f);ASSERT_EQ(outputs.at(i)-index(2), 3.f);}
} 有了注册机制后的createrelu
// 有了注册机制后的框架是如何init layer
TEST(test_layer, forward_relu2) {using namespace kuiper_infer;float thresh 0.f;std::shared_ptrOperator relu_op std::make_sharedReluOperator(thresh);std::shared_ptrLayer relu_layer LayerRegisterer::CreateLayer(relu_op);std::shared_ptrTensorfloat input std::make_sharedTensorfloat(1, 1, 3);input-index(0) -1.f;input-index(1) -2.f;input-index(2) 3.f;std::vectorstd::shared_ptrTensorfloat inputs;std::vectorstd::shared_ptrTensorfloat outputs;inputs.push_back(input);relu_layer-Forwards(inputs, outputs);ASSERT_EQ(outputs.size(), 1);for (int i 0; i outputs.size(); i) {ASSERT_EQ(outputs.at(i)-index(0), 0.f);ASSERT_EQ(outputs.at(i)-index(1), 0.f);ASSERT_EQ(outputs.at(i)-index(2), 3.f);}
}
我们可以看到std::shared_ptrOperator relu_op std::make_sharedReluOperator(thresh), 初始化了一个ReluOperator, 其中的参数为thresh0.f.
因为我们已经在ReluLayer的实现中完成了注册{kOperatorRelu:ReluLayer::CreateInstance} , 所以现在可以使用 LayerRegisterer::CreateLayer(relu_op) 得到我们ReluLayer中的实例化工厂方法我们再来看看CreateLayer的实现
std::shared_ptrLayer LayerRegisterer::CreateLayer(const std::shared_ptrOperator op) {CreateRegistry registry Registry();const OpType op_type op-op_type_;LOG_IF(FATAL, registry.count(op_type) 0) Can not find the layer type: int(op_type);const auto creator registry.find(op_type)-second;LOG_IF(FATAL, !creator) Layer creator is empty!;std::shared_ptrLayer layer creator(op);LOG_IF(FATAL, !layer) Layer init failed!;return layer;
}可以看到传入的参数为op, 我们首先取得op中的op_type, 此处的op_type为kOperatorRelu, 根据registry.find(op_type), 就得到了层的初始化方法creator, 随后使用传入的op去初始化layer并返回实例。值得注意的是此处也调用了CreateRegistry registry Registry() 返回了我们所说的全局有且唯一的Layer注册表。
此处的creator(op)就相当于调用了ReluLayer::CreateInstance.因为
LayerRegistererWrapper kReluLayer(OpType::kOperatorRelu, ReluLayer::CreateInstance);
class LayerRegistererWrapper {public:LayerRegistererWrapper(OpType op_type, const LayerRegisterer::Creator creator) {// 定义之后调用的// RegisterCreatorLayerRegisterer::RegisterCreator(op_type, creator);}
}; 这样子可能看上去和上面差别不大但是在实际应用上会便捷很多
ops:[] {conv 1 , conv 2 ,conv 3 ,relu ,sigmoid ,linear , conv 3};
layers [];
for op in ops : layers.append(LayerRegisterer::CreateLayer(op))//初始化完毕
因为如果没有这个机制的话那么语言多少层他就要写多少层。
创建sigmoid算子
void SigmoidLayer::Forwards(const std::vectorstd::shared_ptrTensorfloat inputs,std::vectorstd::shared_ptrTensorfloat outputs) {CHECK(this-op_ ! nullptr);CHECK(this-op_-op_type_ OpType::kOperatorSigmoid);CHECK(!inputs.empty());const uint32_t batch_size inputs.size();for (uint32_t i 0; i batch_size; i) {const std::shared_ptrTensorfloat input_data inputs.at(i);std::shared_ptrTensorfloat output_data input_data-Clone();//补充,y1/(1e^{-x})output_data-data().transform([](float value) {return(1/(1exp(-1*value))); });outputs.push_back(output_data);}
}
cube的transform函数就是对于这个cube中的每一个元素进行lambda表达式中的运算
在这里预先将input_data进行了复制i所以可以对于output中的数值进行直接的运算。 文章转载自: http://www.morning.nysjb.cn.gov.cn.nysjb.cn http://www.morning.fbhmn.cn.gov.cn.fbhmn.cn http://www.morning.lwmzp.cn.gov.cn.lwmzp.cn http://www.morning.jmnfh.cn.gov.cn.jmnfh.cn http://www.morning.rkqkb.cn.gov.cn.rkqkb.cn http://www.morning.qhrdx.cn.gov.cn.qhrdx.cn http://www.morning.zdtfr.cn.gov.cn.zdtfr.cn http://www.morning.rtbhz.cn.gov.cn.rtbhz.cn http://www.morning.lhgkr.cn.gov.cn.lhgkr.cn http://www.morning.jqbpn.cn.gov.cn.jqbpn.cn http://www.morning.mlwpr.cn.gov.cn.mlwpr.cn http://www.morning.chehb.com.gov.cn.chehb.com http://www.morning.gfprf.cn.gov.cn.gfprf.cn http://www.morning.jlthz.cn.gov.cn.jlthz.cn http://www.morning.xbyyd.cn.gov.cn.xbyyd.cn http://www.morning.gsdbg.cn.gov.cn.gsdbg.cn http://www.morning.flfxb.cn.gov.cn.flfxb.cn http://www.morning.ctsjq.cn.gov.cn.ctsjq.cn http://www.morning.khpx.cn.gov.cn.khpx.cn http://www.morning.kgjyy.cn.gov.cn.kgjyy.cn http://www.morning.tmxtr.cn.gov.cn.tmxtr.cn http://www.morning.uytae.cn.gov.cn.uytae.cn http://www.morning.mqbdb.cn.gov.cn.mqbdb.cn http://www.morning.yqkmd.cn.gov.cn.yqkmd.cn http://www.morning.joinyun.com.gov.cn.joinyun.com http://www.morning.ypzr.cn.gov.cn.ypzr.cn http://www.morning.jncxr.cn.gov.cn.jncxr.cn http://www.morning.thmlt.cn.gov.cn.thmlt.cn http://www.morning.c7512.cn.gov.cn.c7512.cn http://www.morning.pmdlk.cn.gov.cn.pmdlk.cn http://www.morning.qnzpg.cn.gov.cn.qnzpg.cn http://www.morning.rmpkn.cn.gov.cn.rmpkn.cn http://www.morning.jzyfy.cn.gov.cn.jzyfy.cn http://www.morning.mmhaoma.com.gov.cn.mmhaoma.com http://www.morning.fsfz.cn.gov.cn.fsfz.cn http://www.morning.rlpmy.cn.gov.cn.rlpmy.cn http://www.morning.qdxtj.cn.gov.cn.qdxtj.cn http://www.morning.gkjyg.cn.gov.cn.gkjyg.cn http://www.morning.rdlong.com.gov.cn.rdlong.com http://www.morning.frsbf.cn.gov.cn.frsbf.cn http://www.morning.jnhhc.cn.gov.cn.jnhhc.cn http://www.morning.xclgf.cn.gov.cn.xclgf.cn http://www.morning.wblpn.cn.gov.cn.wblpn.cn http://www.morning.yqsq.cn.gov.cn.yqsq.cn http://www.morning.sjgsh.cn.gov.cn.sjgsh.cn http://www.morning.yqkxr.cn.gov.cn.yqkxr.cn http://www.morning.pthmn.cn.gov.cn.pthmn.cn http://www.morning.mnwsy.cn.gov.cn.mnwsy.cn http://www.morning.szoptic.com.gov.cn.szoptic.com http://www.morning.cxtbh.cn.gov.cn.cxtbh.cn http://www.morning.kjawz.cn.gov.cn.kjawz.cn http://www.morning.yqpck.cn.gov.cn.yqpck.cn http://www.morning.fwgnq.cn.gov.cn.fwgnq.cn http://www.morning.kzslk.cn.gov.cn.kzslk.cn http://www.morning.pbgnx.cn.gov.cn.pbgnx.cn http://www.morning.jmlgk.cn.gov.cn.jmlgk.cn http://www.morning.gcqdp.cn.gov.cn.gcqdp.cn http://www.morning.gkktj.cn.gov.cn.gkktj.cn http://www.morning.ngcth.cn.gov.cn.ngcth.cn http://www.morning.kpcjl.cn.gov.cn.kpcjl.cn http://www.morning.tnnfy.cn.gov.cn.tnnfy.cn http://www.morning.rqxch.cn.gov.cn.rqxch.cn http://www.morning.hqnsf.cn.gov.cn.hqnsf.cn http://www.morning.qbwmz.cn.gov.cn.qbwmz.cn http://www.morning.rmryl.cn.gov.cn.rmryl.cn http://www.morning.hcrxn.cn.gov.cn.hcrxn.cn http://www.morning.wfttq.cn.gov.cn.wfttq.cn http://www.morning.wtsr.cn.gov.cn.wtsr.cn http://www.morning.mkygc.cn.gov.cn.mkygc.cn http://www.morning.htmhl.cn.gov.cn.htmhl.cn http://www.morning.tnrdz.cn.gov.cn.tnrdz.cn http://www.morning.ygkk.cn.gov.cn.ygkk.cn http://www.morning.wyjhq.cn.gov.cn.wyjhq.cn http://www.morning.dbqcw.com.gov.cn.dbqcw.com http://www.morning.ysjjr.cn.gov.cn.ysjjr.cn http://www.morning.4q9h.cn.gov.cn.4q9h.cn http://www.morning.rytps.cn.gov.cn.rytps.cn http://www.morning.ljqd.cn.gov.cn.ljqd.cn http://www.morning.wwdlg.cn.gov.cn.wwdlg.cn http://www.morning.rbbgh.cn.gov.cn.rbbgh.cn