摘要:问题引入试想,一个对象本身和由对象组成的一个集合都需要支持逻辑上相同的操作,实际实现可能不一样既然在语义这个更高级抽象可以把两者统一,那么如果这两者都继承同一个基类岂不是更好一个可以类比的例子是,目录本身可能包含多个目录,在没有子目录的情况
问题引入
试想,一个对象本身和由对象组成的一个集合都需要支持逻辑上相同的操作,实际实现可能不一样.既然在语义这个更高级抽象可以把两者统一,那么如果这两者都继承同一个基类岂不是更好? 一个可以类比的例子是,目录本身可能包含多个目录,在没有子目录的情况下,目录的遍历是遍历该目录下的文件,反之,则需要递归的遍历子目录了,而对于扫描的目录的客户端来说(调用此API的程序员)实际上不需要关注和区分这两种情况,那么这就是一个抽象的机会,统一两者操作. 这里给出组合模式的本质:
原理So, what is the Composite pattern about? Essentially, we try to give single objects and groups of objects an identical interface
显而易见的处理方式是,定义一个抽象基类componet,并定义原始类和组合类公共操作(一般是遍历操作比如tranverse()),然后原始类和组合类各自继承即可,这种方式暂且不提.
这里提供一个另外个应用更加广泛和通用的组合模式实现方式,以神经网络基本神经元的连接作为例子.
深度学习当前是以什么网络为基础的,所谓神经网络可以理解为由很多层,每层由很多个神经元,且各层神经元之间有特定关系的拓扑,简单的二层神经网络如下:
可以看到这个网络由橙色和绿色两层网络组成,每一层有若干个神经元,层和层之间的神经元存在连接关系,那么在这里,神经元本身就是原始类,而神经网络层则是组合类(若干神经元组成). 那么这两种类有什么公共的操作呢?
以单个神经元来看,一个神经元要和其他神经元建立连接关系 --> build_connection
以单个神经网络层来看,不同的层之间也需要建立连接关系 --> build_connection
单个神经元和层神经元建立连接. 排列组合一下,这种组合的个数是 2*2=4
而这个组合个数实际上就是类的成员函数的个数, 比如两个类A和B,分别代表神经元和层,需要支持两量互相连接操作需要如下几组成员函数:
A a1,a2; B b1,b2; a1.build_connection(a2); a1.build_connection(b1); b1.build_connection(b2); b1.build_connection(a1);
推而广之,如果在来个平面层(由若干个单层神经网络组成),那么个数就是3*3. 随着类的增加,程序的重载成员函数规模失控,这违背了设计模式原则扩展开放,对修改关闭.
怎么做呢?不同神经元(或者层)之间的连接,本质上可以抽象成一个遍历操作:对于单个神经元来说,遍历的结果就是只拿一个元素. 因此可以把抽象操作提升/抽象至基类,其他类继承并提供遍历迭代器接口即可.
先给出神经元和神经网络层的类定义:
// 神经元 struct Neuron { std::vectorin, out; unsigned int id; Neuron(){ static int id = 1; this->id = id++; } // ... }; // 单层神经元 struct NeuronLayer { std::vector neus; NeuronLayer(int count) { while(count-- > 0) { neus.push_back(Neuron()); } } // ... };
然后想一下我们要抽象的操作,obj1.connect_to(obj2), 其中obj1和obj2可能是NeuronLayer或者Neuron之一,connect_to实际上要分别遍历两个对象取到每一个神经元而建立连接. 抽象类如下:
templatetemplate void SomeNeurons ::connect_to(T& other) { for(Neuron &from : *static_cast (this)){ // 直接用*this本身会产生编译错误,因为抽象模板类并没有实现begin()和end(),而遍历需要它们,这里转换成子类解决(子类本来就需要提供,见后面描述) //for(Neuron &from : (*this)){ for(Neuron & to : other) { from.out.push_back(&to); to.in.push_back(&from); } } }
可以看到这个抽象类是一个带模板成员函数的模板类,connect_to分别遍历了this类对象和指向的目标类对象获取元素,因为两个对象不一定一样,因此传入的模板类型也是不一样的. 接下来要干的活就剩下两个了
神经元和神经层继承抽象类,即可以获取connect_to能力
基类使用了Range-based for loop, 因此需要保证各子类都提供begin和end成员函数,因为Range语句的约束条件如下:
any expression that represents a suitable sequence (either an array or an object for which begin and end member functions or free functions are defined, see below) or a braced-init-list.
因此,按照上述描述新增/修改位置如下:
struct Neuron : public SomeNeuronsstruct NeuronLayer : public SomeNeurons // 类Neuron, 各自新增的成员函数,因为神经元不需要遍历,end直接取下一个元素. Neuron *begin() {return this;} Neuron *end() {return this+1;} // 类NeuronLayer,本来就是要遍历vector ,直接用vector的begin和end包装即可. std::vector ::iterator begin() {return neus.begin();} std::vector ::iterator end() {return neus.end();}
好了,主体工作基本完成,看一下当前类图结构如下:
相较于比较基本的组合设计模式的实现方式(基类提供抽象接口,各子类分别实现),这个抽象成都更高,连实现也放到抽象基类当中,而各子类提供的是遍历方式,解耦更加干净彻底;
更加有借鉴意义的是,这个实现方式可以完美的处理神经网络不同元素之间的关系,调用非常舒畅:
// point to layer Neuron n6; NeuronLayer l1(5); n6.connect_to(l1); std::cout<参考 https://leanpub.com/design-pa...
http://en.cppreference.com/w/...
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/20180.html
摘要:问题引入试想,一个对象本身和由对象组成的一个集合都需要支持逻辑上相同的操作,实际实现可能不一样既然在语义这个更高级抽象可以把两者统一,那么如果这两者都继承同一个基类岂不是更好一个可以类比的例子是,目录本身可能包含多个目录,在没有子目录的情况 问题引入 试想,一个对象本身和由对象组成的一个集合都需要支持逻辑上相同的操作,实际实现可能不一样.既然在语义这个更高级抽象可以把两者统一,那么如果...
摘要:机器学习系统被用来识别图像中的物体将语音转为文本,根据用户兴趣自动匹配新闻消息或产品,挑选相关搜索结果。而深度学习的出现,让这些问题的解决迈出了至关重要的步伐。这就是深度学习的重要优势。 借助深度学习,多处理层组成的计算模型可通过多层抽象来学习数据表征( representations)。这些方法显著推动了语音识别、视觉识别、目标检测以及许多其他领域(比如,药物发现以及基因组学)的技术发展。...
摘要:首先,的概念与卷积的概念大部分是独立的。但是,请注意,这个特征的较精确位置已经被丢弃。结合和,这意味着我们的网络使用的是不同于一般类型的非线性。之间的这就是网络如此与众不同的原因。与普通的层相比,层是完全不同的。 首先,capsule 的概念与卷积的概念大部分是独立的。例如,你可以有一个完全连接的capsule网络。但是,它们确实使用了卷积,而且也被与CNN进行比较。但是,我将在接下来解释中...
摘要:在本文中,我将用裸体检测问题来展示训练现代版的卷积神经网络模型与过去的研究有何区别。论文在年代中期发表,它反映了计算机视觉研究者们在使用卷积神经网络之前所做的典型工作。 著名人工智能公司Clarifai近日推出了识别成人内容的模型和API NSFW,该模型能够很准确地识别含有裸体和半裸的图片和视频,在Clarifai的这篇博文中,作者用裸体检测问题来展示训练现代版的卷积神经网络模型 (con...
阅读 2571·2023-04-26 02:23
阅读 1265·2021-11-11 16:55
阅读 2981·2021-10-19 11:47
阅读 3012·2021-09-22 15:15
阅读 1748·2019-08-30 15:55
阅读 886·2019-08-29 15:43
阅读 1151·2019-08-29 13:16
阅读 1990·2019-08-29 12:38