精华内容
下载资源
问答
  • 西部数码(west.cn)3月12日消息,新一期的DN交易榜昨天发布,...整体上,由于该域名辨识度较高,且没有特殊行业倾向,可广泛适用于游戏、娱乐、旅游等领域,市场价值不错。据了解,free.co.uk不仅今年目前为止成...

    西部数码(west.cn)3月12日消息,新一期的DN交易榜昨天发布,国别域名free.co.uk以205,000美元成交价居于榜首,约合人民币143万元。

    2116b023eda82399eef50f276f78eaa4.png

    域名free.co.uk主体是通用英文单词,是“自由”的意思,后缀.co.uk是英国国家域名。整体上,由于该域名辨识度较高,且没有特殊行业倾向性,可广泛适用于游戏、娱乐、旅游等领域,市场价值不错。据了解,free.co.uk不仅是今年目前为止成交价最高的国别域名,也是近三年来价格最高的.co.uk域名。

    域名ready.org也是常见英文单词域名,有“准备好、已完成、可利用”的意思,交易价为169,888美元,约合人民币118万元。这个域名注册于2003年10月,距今已超16年历史,目前对应有为中国消费者服务的平台ChinaReady,官网域名为chinaready.com.cn。

    国别域名download.it以85,500美元成交,约合人民币59.5万元,是“下载”的意思。这个域名的主体辨识度很高,可以说是大部分网民都会使用到的网络行为,适合搭建资源下载平台。

    域名heloc.com交易价为82,500美元,约合人民币5.7万元。这枚域名注册于1996年,当前的whois信息显示其所有者为Freedom Mortgage Corporation,应该是一家从事金融借贷的终端。

    两声母域名RS.de成交价为79,800美元,约合人民币55.5万元。两字母的短域名可挖掘的含义十分丰富,在建站方面没有什么限制,适合诸多领域建站使用。

    除此以外,本期DN榜上还有多枚国别域名,比如以50,000美元成交的primera.es(第一次);以22,800美元成交的breitbrand.de,这个域名在德语里是“宽频带”的意思。

    更多域名交易,详见下表:

    e163b618be96434881b980b73bc9c2e8.png
    展开全文
  • 目录一类为了浏览和搜索数据的特殊的数据库,目录服务按照树状形式存储信息的,目录包含基于属性的描述信息,并支持高级的过滤功能,例如:最知名的的微软公司的活动目录(active directory)就是目录数据库的...

    2.OpenLDAP
    2.1.什么是目录服务
    2.2.OpenLDAP简介
    2.3.LDAP的基本模型
    2.3.1.目录树概念
    2.3.2.DC、UID、OU、CN、SN、DN、RDN、c、o
    2.4.LDAP的使用

    2.OpenLDAP

    2.1.什么是目录服务

    目录是一类为了浏览和搜索数据的特殊的数据库,目录服务是按照树状形式存储信息的,目录包含基于属性的描述性信息,并支持高级的过滤功能,例如:最知名的的微软公司的活动目录(active directory)就是目录数据库的一种。目录服务时按照梳妆形式存储信息的,目录包含基于属性的描述性信息,并且支持高级的过滤功能。
    一般来说,目录不支持大多数事务性数据库所支持的高吞吐量和复杂的更新操作,目录服务适合的业务应用在于提供大量的查询和搜索操作,而不是大量的写入。LDAP可以说是活动目录在Linux上的一个开源实现。
    为了保证目录数据的可用性和卡可靠性,她们在确保提供快速的查询和搜索操作的同时,还提供了主从服务器同步目录数据信息的能力,这相当于传统的Mysql数据库的主从同步一样,可以最大限度的确保基于目录业务的持续可用性。
    广义的目录服务概念,可以有多重不同的方式来提供目录服务,不同的目录所允许存储的信息是不同的,在信息如何被引用,查询,更新以及防止未经守群的访问等问题上,不同的目录所允许存储的信息是不同的,在信息如何被引用,查询,更新以及防止未经授权的访问等问题上,不同的目录的处理方式也有诸多的不同。一些目录服务时为本地的,只提供受限的服务,(比如,单机上的finger服务)。另一些服务时大范围的(global),提供广阔得多的服务(比如面向整个因特网)。大范围的服务通常是分布式的,这也就意味着数据是分布在多台机器上的,这些计数器一起来提供目录服务。典型的大范围服务定义一个统一的名称空间(namespace)来给出一个相同的数据试图(data view),而不管你相对于数据所在的位置。DNS是一个典型的大范围分布式目录服务的例子。

    2.2.OpenLDAP简介

    LDAP是一款轻量级目录访问协议(Lightweight Directory Access Protocol,简称LDAP),属于开源集中账号管理架构的实现,且支持众多系统版本,被广大互联网公司所采用。

    LDAP提供并实现目录服务的信息服务,目录服务是一种特殊的数据库系统,对于数据的读取、浏览、搜索有很好的效果。目录服务一般用来包含基于属性的描述性信息并支持精细复杂的过滤功能,但OpenLDAP目录服务不支持通用数据库的大量更新操作所需要的复杂的事务管理或回滚策略等。

    LDAP具有两个标准,分别是X.500和LDAP。OpenLDAP是基于X.500标准的,而且去除了X.500复杂的功能并且可以根据自我需求定制额外扩展功能,但与X.500也有不同之处,例如OpenLDAP支持TCP/IP协议等,目前TCP/IP是Internet上访问互联网的协议。

    OpenLDAP可以直接运行在更简单和更通用的TCP/IP或其他可靠的传输协议层上,避免了在OSI会话层和表示层的开销,使连接的建立和包的处理更简单、更快,对于互联网和企业网应用更理想。

    OpenLDAP目录中的信息是以树状的层次结构来存储数据(这很类同于DNS),最顶层即根部称作“基准DN”,形如“dc=mydomain,dc=org”或者“o=mydomain.org”,前一种方式更为灵活也是Windows AD中使用的方式。在根目录的下面有很多的文件和目录,为了把这些大量的数据从逻辑上分开,OpenLDAP像其它的目录服务协议一样使用OU(Organization Unit,组织单元),可以用来表示公司内部机构,如部门等,也可以用来表示设备、人员等。同时OU还可以有子OU,用来表示更为细致的分类。

    OpenLDAP中每一条记录都有一个唯一的区别于其它记录的名字DN(Distinguished Name),其处在“叶子”位置的部分称作RDN(用户条目的相对标识名)。如dn:cn=tom,ou=animals,dc=ilanni,dc=com中cn即为RDN,而RDN在一个OU中必须是唯一的。

    OpenLDAP默认以Berkeley DB作为后端数据库,BerkeleyDB数据库主要以散列的数据类型进行数据存储,如以键值对的方式进行存储。

    BerkeleyDB是一类特殊的面向查询进行优化、面向读取进行优化的数据库,主要用于搜索、浏览、更新查询操作,一般对于一次写入数据、多次查询和搜索有很好的效果。BerkeleyDB不支持事务型数据库(MySQL、MariDB、Oracle等)所支持的高并发的吞吐量以及复杂的事务操作。

    2.3.LDAP的基本模型

    每一个系统、协议都会有属于自己的模型,LDAP也不例外,在了解LDAP的基本模型之前我们需要先了解几个LDAP的目录树的概念:

    2.3.1.目录树概念

    1、目录树:在一个目录服务系统中,整个目录信息集可以表示为一个目录信息树,树中的每个节点是一个条目。
    2、条目:每个条目就是一条记录,每个条目有自己的唯一可区别的名称(DN)。
    3、对象类:与某个实体类型对应的一组属性,对象类是可以继承的,这样父类的必须属性也会被继承下来。
    4、属性:描述条目的某个方面的信息,一个属性由一个属性类型和一个或多个属性值组成,属性有必须属性和非必须属性。

    2.3.2.DC、UID、OU、CN、SN、DN、RDN、c、o

    关键字 英文全称 含义
    dc Domain Component 域名的部分,其格式是将完整的域名分成几部分,如域名为example.com变成dc=example,dc=com(一条记录的所属位置)
    uid User Id 用户Id zuoquantu (一条记录的ID)
    ou Organization Unit 组织单位,组织单位可以包含在其他各种对象(包括其他组织单位),如”oa组” (一条记录的所属组)
    cn Common Name 公共名称,如“Thomas Johansson”(一条记录的名称)
    sn Surname 姓,如”许”
    dn Distinguished Name “uid=songtao.xu,ou=oa组,dc=example,dc=com”,一条记录的位置(唯一)
    rdn Relative dn 相对辨别名,类似于文件系统中的相对路径,它是与目录树结构无关的部分,如“uid=tom”或“cn= Thomas Johansson”
    c Country 国家,如”CN”或”US”等
    o Organization 组织名,如:”中华人民共和国质检总局”

    2.3.3.基本模型

    2.3.3.1.信息模型

    在LDAP中信息以树状方式组织,在树状信息中的,基本数据单元是条目,而每个条目由属性构成,属性中存储有属性值

    2.3.3.2.命名模型

    LDAP中的命名模型,也即LDAP中的条目定位方式。在LDAP中每个条目均有自己的DN。DN是该条目在整个树中的唯一名称标识,如同文件系统中,带路径的文件名就是DN。
    在这里插入图片描述

    2.3.3.3.功能模型

    在LDAP中共有四类10中操作:查询类操作,如搜索、比较;更新类操作,如添加条目、删除条目、修改条目名;认证类操作,如绑定、解绑定;其它操作,如放弃和扩展操作。除了扩展操作,另外9种是LDAP的标准操作;扩展操作是LDAP中为了增加新的功能,提供的一种标准的扩展框架,当前已经成为了LDAP标准的扩展操作,有修改密码和StartTLS扩展,在新的RFC标准和草案中增加一些新的扩展操作,不同LDAP厂商也均定义了自己的扩展操作。

    2.3.3.4.安全模型

    LDAP中的安全模型主要通过身份认证、安全通道和访问控制来实现。

    2.4.LDAP的使用

    那我们是如何访问LDAP的数据库服务器呢?
    在这里插入图片描述

    统一身份认证主要是改变原有的认证策略,使需要认证的软件都通过LDAP进行认证,在统一身份认证之后,用户的所有信息都存储在AD Server中。终端用户在需要使用公司内部服务的时候,都需要通过AD服务器的认证。
    那么程序中是如何访问的呢? 我们以PHP脚本作为例子:

    $ldapconn = ldap_connect(“10.1.8.78")
    $ldapbind = ldap_bind($ldapconn, 'username', $ldappass);
    $searchRows= ldap_search($ldapconn, $basedn, "(cn=*)");
    $searchResult = ldap_get_entries($ldapconn, $searchRows);
    ldap_close($ldapconn);
    

    1、连接到LDAP服务器
    2、绑定到LDAP服务器
    3、在LDAP服务器上执行所需的任何操作
    4、释放LDAP服务器的连接

    2.5.相关网址

    官网首页:https://www.openldap.org/

    下载地址:https://www.openldap.org/software/download/

    展开全文
  • 发育网络(DN): 一个涌现的图灵机

    千次阅读 热门讨论 2019-06-09 23:19:55
    因为,前后两时期的工作没有太大的关联【尽管如此,IHDR仍一个很棒的增量式学习模型,值得深入学习与理解】。为什么IHDR不能作为机器人最终的发育模型(大脑)?翁教授的回答:人的大脑没有一个中央的控制器,...

    发育网络(DN): 一个涌现的图灵机

    如果一定得划分,翁教授的工作可以划分成两个时期:1)CCIPCA+IHDR;2)CCILCA+DN。IHDR作为一种偿试实现机器人大脑,显然是失败了。因为,前后两时期的工作没有太大的关联性【尽管如此,IHDR仍是一个很棒的增量式学习模型,值得深入学习与理解】。为什么IHDR不能作为机器人最终的发育模型(大脑)?翁教授的回答是:人的大脑没有一个中央的控制器,而IHDR有一个中央控制器调控所有的学习过程【IHDR是一种全局的学习模型,DN是一种局部的学习模型:::MAYBE】。结合背景,言外之意是发育网络(DN)没有中央调控。本文结合翁教授的讲座与相关论文介绍DN。首先系统的介绍发育网络的思想,然后介绍方法,接着利用一个发育网络的实现例子Where-what-network来进一步理解发育网络,最后对实验结果以及全文进行分析总结。本文例子python程序已经上传github。

    1. 大脑

    1.1 来自肌肉的上下文(Context from motor)

    翁教授认为 自主意图是从自上到下的上下文(top-down contexts)中学到的;进一步的,作为意图的上下文是来自肌肉(motor)。 下面是翁教授给的几个例子,方便理解上面那句话。

    1. 将一只刚出生的猫放在只有垂直边界线的环境中一段时间,然后将它放在正常环境中,我们发现它的V1区的神经细胞对水平边缘没有响应(具体表现就是:它不会盯着水平边缘看)。【Blakemore & Cooper, Nature 1970】
      在这里插入图片描述
    2. 下图显示的是左视皮层的视神经细胞被右眼或左眼输入主导的情况。正常情况如下面的左图所示。相对来说,左视皮层神经细胞大多被右眼输入主导,也有不可忽略的一部分被左眼主导。现在把一个刚出生10天的小猫的右眼蒙上,经过21天后(也即出生后的第31天),情况如中间图所示。右眼的主导降低。再过6天,结果如右图所示。基本上全部由左眼主导了。【备注:正常情况下,左眼输入到右半脑,右眼输入到左半脑】

    在这里插入图片描述
    3. 将视觉神经切断,经过一段时间发现,视觉神经自动与听觉区域的神经元连接在了一起。也即,用听觉区域来“看”。【Sur, Angelucci and Sharm, Nature 1999】

    在这里插入图片描述

    1.2 大脑不是级联结构

    深度学习利用深度神经网络作为学习模型,是一种级联结构。但是,大脑并不是级联的结构,各个神经元之间的突触连接方式错综复杂。
    在这里插入图片描述

    1.3 符号与联接的统一

    大脑利用神经元相互连接实现知识的学习与存储,同时也具备逻辑推理能力。这说明大脑是符号主义与联接主义的统一体。
    在这里插入图片描述

    1.4 自主发育

    人类从一枚受精卵发育成婴儿,从婴儿发育成成年人,这个过程是自主发育。很自然的想法是,如果给机器人造一个身体并给一个自主发育程序,机器人便会像人类一样通过自主的与环境以及其他智能体的交互进行发育,慢慢学到越来越多的知识,也越来越聪明。这也是翁教授研究自主心智发育理论的最核心驱动目标。
    在这里插入图片描述

    2. 涌现通用图灵机(Emergent Universal Turing Machines)

    2.1 有限自动机(FA)

    有限自动机或称为有限状态的机器,我们首先了解一下与FA非常相近的有限状态机(FSM)。有限状态机(FSM)由有限个状态及状态转换关系组成。如下图所示的有限状态机由6个状态组成,图中也明确给出状态到状态之间的转换条件。例如,当前状态为2,此时输入字符I,则转换到状态6。在这里插入图片描述
    然而,有限自动机由一个有限的内部状态集和一组控制规则组成,这些规则是用来控制在当前状态下读入输入符号后应转向什么状态。

    【图灵机的控制就是一个有限自动机】

    2.2 图灵机

    图灵机是图灵在他24岁发表的论文《论可计算数及其在判定问题中的应用》中提出的一种抽象模型。该抽象模型很大程度上模仿了人类处理问题的过程:它拥有一个类似人眼和手的读写头能够读取信息以及输出信息;一条无限长的纸带,源源不断地提供信息以及供输出结果;一个类似于我们大脑的控制,能够根据问题的不同,进行不同的处理。

    在这里插入图片描述
    人类也可以抽象成图灵机。每一个会决策、会思考的人就可以被抽象的看成一个图灵机,每个人都有自己的操作系统。输入状态集合就是你所处的环境中能够看到、听到、闻到、感觉到的所有信息,可能的输出集合就是你的一言一行,以及你能够表达出来的表情动作。内部状态集合则要复杂得多。因为我们可以把任意一个神经细胞的状态组合看作是一个内部状态,那么所有可能的神经细胞的状态组合将是天文数字。这是人类的记忆。只要图灵机具有了内部状态,它就具有了记忆。
    在这里插入图片描述

    如果将图灵机与人进行类比,那么人脑就是图灵机的内部状态存储器与控制程序指令。

    2.3 通用图灵机

    我们可以将上面介绍的图灵机编码为字符串< M>。我们可以进一步构造出一个特殊的图灵机,它以任意图灵机M的编码< M>作为输入【图灵机以数据作为输入,通用图灵机以图灵机作为输入】,然后模拟M的运作,这样的图灵机称为通用图灵机。现代电子计算机其实就是这样一种通用图灵机的模拟,它能接受一段描述其他图灵机的程序,并运行程序实现该程序所描述的算法。

    在这里插入图片描述

    2.4 涌现通用图灵机(Emergent UTM)

    在这里插入图片描述
    上图为一个传统的有限自动机,可以表示成如下具有同样意义的符号查找表:
    在这里插入图片描述
    我们进一步编码:A-00;B-01;C-10;D-11。可得如下查找表。该查找表就是一个涌现有限自动机。

    在这里插入图片描述
    我们以Z作为状态,X作为输入。在初始状态00时,输入为01时,会到达下一个状态01,然后输入10时,又会跳到状态10,继续输入10,会跳到关态10,此时输入11,会跳入状态11。这已经非常接近本文的主角【发育网络(DN)】。
    在这里插入图片描述

    3. 发育网络(Delevelopment Network)

    3.1 从涌现UTM到发育网络

    还请紧盯着上面的查找表与转换例子。我们把状态Z当作人类的感知输入信息,而输入X当作人类的肌肉运动信息。我们将X与Z绑定成记忆图(发育网络)中的一个结点。Y是隐含在人类或机器人自身模型中的,不需要学习。

    【 备注:人类或者设计好的机器人,不需要学习他的转换关系(也即控制器)。因为,对于特定的肌肉动作,机器人或者人肯定按照自身的运动模型运行,从而自动的进入到下一步状态,在该状态感知新的信息,并输出绑定的肌肉动作信息。】

    学习的过程可以描述为,对于新的感知输入信息Z【bottom】,假定机器人或者人类能够通过示教或者自主学习的方式得到当前合适的肌肉动作信息X【up】。我们将X与Z绑定在一起形成发育网络的一个记忆节点。

    【备注:为了更好理解涌现图灵机与发育网络的关系,此处简化了发育网络的学习与利用过程,真实的发育网络的学习过程考虑了信息之间的相似性,是一个有效的①聚类过程 :叶成分分析(LCA),并按照②Hebbian 规则 来更新网络的参数。】

    一个形象的例子如下图所示:【理解发育网络的重点是图灵机的控制规则是隐含在人类与机器人本体中的,不需要学习。人类与机器人本身就是一个模型,采取某一个动作,自然会显式的作用到环境】
    在这里插入图片描述

    3.2 发育网络的特点

    翁教授认为机器人的自主发育程序应该具备以下八个特点:

    1. 接地地:感知物理世界,并作用到物理世界;
    2. 涌现地:内在的表述是自动生成的;
    3. 自然地:是自然编码,而不是手动编码;
    4. 增量地:不是批处理学习,没有数据集;
    5. 脑颅封闭地:人类不能改变颅内的参数;
    6. 注意地:对感知特征与电机特征具有注意机制;
    7. 有动机地:避免痛苦,寻找快东,好奇心等;
    8. 具有抽象能力地:能够从上下文中提取观念与规则;

    还有一点是没有疑问的:发育网络统一了监督学习与无监督学习。

    3.3 自主发育程序

    通过以上介绍,我们可以大概知道发育网络的单个节点模式以及整个发育网络具有的特性。机器人需要自主发育程序自主在线构建发育网络:网络节点的增加、网络参数的更新等。翁教授提出的自主发育程序具有以下几个特点:

    1. In-place learning (在位学习) :每个神经元通过自身内部的生理机制以及与其它神经元的交互来处理自身的学习。每个神经元都拥有同样一套发育程序,具有同等的发育能力。在位学习是以神经细胞为中心的学习。

    【笔记:因此,只需要介绍清楚一个神经细胞的学习过程,就知道整个发育网络的学习,不管发育网络多么复杂。发育网络的每个神经元细胞的响应由三部分构成:a) 自底向上(上一层到当前层的输入)的响应yy;b)自顶向下(下一层到当前层的输入)的响应aa;c)同层间其它神经元的抑制响应hh。总的响应为z=g(wby+wpawhh)z=g(w_b y+w_p a -w_h h),其中gg为任意激活函数。下图绿色的圆与粗直线表示一个完整的神经元细胞,与圆相连的不带箭头实线为自底向上的输入,与粗直线相连的实线为自顶向下的输入,与粗直线相连的虚线为同层间神经元的抑制输入。】
    在这里插入图片描述

    1. Lateral inhibition (侧向抑制) :生物的神经网络中,例如人的视网膜中,存在着一种“侧向抑制”现象,即一个神经细胞兴奋后,通过它的分支会对周围其他神经细胞产生抑制。侧向抑制是同层的神经元竞争的一种机制。为了使侧向抑制更加有效的作用到发育网络中:a)强响应的神经元能够有效的抑制弱响应的神经元;b)弱响应的神经元不影响强响应的神经元。翁教授利用top-k竞争规则,也即同一层的神经元按响应程度从强到弱排序,排在前k的神经元有一个非零的权值更新,其他的神经元的权值不作改变。

    【笔记:对于预先固定神经元数量的网络,竞争机制会使得之前所学到的模式被最近的模式替代,也即会产生遗忘。通过与翁教授的交流,也确认了这种遗忘的存在,并且翁教授认为这种遗忘与人脑的特性很像,是合理的。与翁教授的观点不同,本人坚持遗忘不是好的特性,我认为人具有的特性不一定都是好的。】

    1. Hebbian learning(赫布学习) :赫布理论描述了突触可塑性的基本原理,即突触前神经元向突触后神经元的持续重复的刺激可以导致突触传递效能的增加。这一理论由唐纳德.赫布于1949年提出,又被称为赫布定律。赫布理论可以用于触释“联合学习”,在这种学习中,由对神经元的重复刺激,使得神经元之间的突触强度增加。这样的学习方法被称为赫布学习。赫布理论也成为非监督学习的生物学基础。

    【笔记:假定当前竞争胜利的神经元权值为vjt1v_j^{t-1},当前的输入为y(t)y(t),则按以下公式对该胜利神经元进行更新:
    vjt=αvjt1+(1α)y(t)(1)v_j^{t}=\alpha v_j^{t-1}+(1-\alpha) y(t) \tag{1}
    其中,1α1-\alpha为学习率,α\alpha为遗忘率。】

    1. Lobe components(叶成分) :叶成分分析将样本空间分为C个互相不重叠的区域,也即叶区域。顾名思义,就像树枝上的同一个芽点长出的几片树叶。一个二维空间的叶成分如下图所示:

    在这里插入图片描述

    【笔记:叶成分是由叶成分分析算法|详细推导与应用参见该博客得到的,叶成分分析是一个聚类算法,每个聚类中心由其个方向上的方向向量表示。说的再明白点,这个聚类算法中的距离是由两向量的cos(θ)cos(\theta)表示,其中θ\theta表示两向量的夹角。我们知道,距离度量的方式对聚类算法效果影响非常大,某一距离度量可能只适用于某一些特定的数据。翁教授以叶成分分析作为距离度量,并且效果都还不错,主要原因是,它的输入为图片数据,维度非常高,在如此高维的输入空间,数据基本上是分布在一个超球面上的,所以用叶成分是合适的。但是,对于一些低维的,或者数据分布散布整个状态空间的,叶成分并不合适。如下图,是一个二维的数据集,我们无法用叶成分分析将它聚成合适的类。】
    在这里插入图片描述

    小结: 上面给出自主发育程序的主要特点,并对每个特点进行了详细的解释。侧向抑制、赫布学习以及叶成分并不是完全独立的个体,它们是你中有我,我中有你,互相依存的关系。单个神经元细胞的发育程序可以看成是叶成分分析,然而叶成分分析算法是由赫布规则以及侧向抑制胜利的聚类中心向量(神经元的权值参数)进行更新的。这是一套自成体系的算法,并且实验也验证了算法的有效性。本人对此算法抱有保持态度的地方主要有两个:1)遗忘是否合理?2)叶成分的聚类是否对所有数据分布都通用?关于聚类距离度量的选择,有一句话这么说:which one to use depends on what type of data we have and what our notion of similar is.当然,我自己也在偿试将其他距离度量方式融合到自主发育程序中。但是,当前的自主发育程序就是以叶成分分析为核心的,也即换了距离度量,就得重新推导一个新的自主发育程序。这个还是挺有挑战的。

    3.4 发育网络的例子

    Where-What Networks(WWNs)
    在这里插入图片描述

    4. DN的一个例子:Where-what-network

    4.1 数据准备

    学习时 :Where-What-network利用图片数据(Input)以及对象的种类标签(What motor)和对象在图片的位置标签(Where motor)作为训练数据,训练得到发育网络。
    利用时 :对于训练中遇到的相似样本,发育网络能够得到对象的种类与所在图片的位置信息。

    4.1.1 构造过程说明

    首先介绍怎么构造Where-what-network训练所需要的数据。我们可以实景拍摄照片,然后加上位置与种类标签。但是,这个过程非常繁琐。本部分主要目的是为形象理解发育网络,真实应用性的说明居于其后。因此,本部分采用人工构造的数据来训练DN。人工构造的图片数据,可以自动的得到对象的种类与位置标签,省去了人工定标签的麻烦。下面简单给出人工构造训练数据的方法。
    在这里插入图片描述

    • 背景图片:为了模拟真实场景图片,一个对象一般都具有背景作为依托。例如,一只沙发上的猫,沙发就是猫的背景。本部分的背景大小为19x19,通过对上图左边的13张真实场景图片进行随机切割19x19的小块产生。
    • 对象图片:本部分采用五种动物的大小为11x11的低分辨率图片作为对象。分别为1-猫、2-狗、3-大象、4-猪、5-卡车五种图片。
    • Input:随机选择一种对象图片,随机的放置于随机选择的某一背景图片的某一位置(此处有25个可选位置,上面中间图蓝色格子为可选的对象图片中心位置)。(如上图中间所示)
    • Where-What motors:将构造时的位置与种类作为Input的Where motor 和 What motor。

    每次训练时,通过以上方式,随机得到一组训练样本:[Image,type,position],下面给出相关的样本构造的Python程序。

    4.1.2 样本构造程序

    • 1.对实景图片进行随机切割,得到19x19的背景图片。
    def get_background(background_height, background_width):
        epsilon_error = 1.0/(256*sqrt(12))
        f = open('backgrounds/backgrounds_to_use.txt')
        splitData = f.read().split("\n")
        curr_num = np.random.randint(len(splitData) - 2) + 1
        img_file = 'backgrounds/'+splitData[curr_num]+'.'+splitData[0]
        curr_img = np.array(Image.open(img_file))
        rows, cols = curr_img.shape
        ul_row = np.random.randint(rows-background_height)
        ul_col = np.random.randint(cols-background_width)
        bg = curr_img[ul_row:ul_row + background_height, ul_col:ul_col + background_width]
        bg1 = copy.deepcopy(bg)
        samplemin = np.min(bg1)
        samplemax = np.max(bg1)
        bg = (bg - samplemin)/(samplemax-samplemin+epsilon_error)
        plt.imshow(bg)
        plt.show()
        ul_img = Image.fromarray(np.uint8(bg))
        ul_img.show()
        return bg
    
    • 2.随机选择一个对象作为前景图片加入背景图片中。
    def add_foreground(background, training_type):  # 01:cat; 02:dog; 03:elephant; 04:pig; 05:truck
        f = open('foregrounds/foregrounds_to_use.txt')
        splitData = f.read().split("\n")
        curr_num = np.random.randint(training_type) + 1
        img_type = curr_num - 1
        img_file = 'foregrounds/'+splitData[curr_num]+'.'+splitData[0] 
        curr_img = Image.open(img_file, 'r')
        fg = np.array(curr_img.convert('L'))
        obj_width, obj_height = fg.shape
        fg1 = copy.deepcopy(fg)
        samplemin = np.min(fg1)
        samplemax = np.max(fg1)
        fg = (fg - samplemin)/(samplemax-samplemin)
    #     plt.imshow(fg)
    #     plt.show()
        p_r = np.random.randint(5)
        p_c = np.random.randint(5)
        r = (p_r)*2
        c = (p_c)*2
        position = p_r*5+p_c
        background[r:r+obj_width, c:c+obj_width] = fg
    #     plt.imshow(background)
    #     plt.show()
        return background, img_type, position
    
    • 3.利用构造的输入图片,进一步得到 where and what motors,并封装成标准样本数据格式<x,y>。
    def get_image(input_dim, z_neuron_num):
        """
        1: cat; 2:dot; 3:elephant; 4:pig; 5:truck
        position: (row-1)*col
        """
        epsilon_error = 1/(256*sqrt(12))
        background_width = input_dim[0]
        background_height = input_dim[1]
        
        bg = get_background(background_height, background_height)
        
        
        training_type = 1
        if len(z_neuron_num) != 1:
            training_type = z_neuron_num[0]
        
        training_image, img_type, position = add_foreground(bg, training_type)
        true_z = []
        if len(z_neuron_num) != 1:
            true_z.append(img_type)
            true_z.append(position)
        else:
            true_z.append(position)
        true_z = np.array(true_z)
        return training_image, true_z
    

    4.1.3 构造的样本例子

    下图为随机选择的背景,随机选择的对象,随机安放的位置,得到最终的输出图片与Where and What motors。【备注:由于图片经过归一化,并用matplotlib的plt.imshow展示,所以显示与真实灰度图片有差异】
    在这里插入图片描述

    4.2 Where-What network介绍

    本文介绍的Where-What network一个简单例子如下图所示【应该是最简单的形式了,但是麻雀虽小,该有的部分一样不少】。该网络由输入[Input],发育网络的核心部分[DN]以及输出[Motors]三层组成。最核心的是红框标出的DN,该部分存储学习到的所有知识。并且,在本演示例子中,DN的网络神经元个数是自适应增长的,发育层的神经元个数等于25x(3^split_times),其中,split_times为满足分裂的次数【有点像细胞的有丝分裂哈,与细胞只能一个分成两个不同,这里的一个节点可以分成我们设定的值,此处为3】。输入层的神经元个数为输入图片向量化后的长度19x19=361。What motor有5个神经元,Where motor有25个神经元。输入层与motor层的神经元个数都是直接由样本确定的。
    在这里插入图片描述

    4.3 Where-What network训练

    DN的第一个特点便是in-place。所谓的in-place即,网络是局部的,单个神经元的更新只与它本身以及周围的神经元有关,并且每个神经元的更新是共用同一套发育程序【类似于人身体的细胞共用同一套DNA一样】。因此,我们只需要解释清楚DN中一个神经元的参数、输出计算以及权值更新即可。所有神经元的更新方法与步骤都是一样的。

    4.3.1 权值初始化

    DN神经元总共有五种参数:①bottom up weight;②top down weight;③lateral weight;④inhibit weight;⑤synapse factor。前三个参数的解释说明可见下图。我们先不考虑后两组参数,只利用前三个参数计算得到某一神经元的输出如下图所示【请仔细阅读下图】。先计算X的响应,Y的响应,然后将两者的响应加权求和得到临时的响应Temp Y,然后考虑侧向参数得到侧向神经元对该神经元的响应,并将其与Temp Y进行加权求和得到最终的神经元响应Y。
    在这里插入图片描述
    第四个参数:inhibit weight是同层抑制参数,也即当某一神经元被激活,只有附近的神经元会被相应比例激活,其他稍远的神经元则被抑制【对于当前样本,参数不被更新】。
    第五个参数:synapse factor是注意力选择因子。对于不同的神经元,输入的不同维度的重要性不一样,因此,对于特定输入【X或Z】,每个Y中的神经元都附有一个因子向量,该因子向量与输入向量的维度一至,因子向量上每个元素表示对应输入向量元素的重要性,值越大,表示越重要。【这有点类似特征选择】

    在本例子中,第四个参数用在top-k竞争函数中;第五个参数只用在了Y对输入X的注意力选择中,使发育网络能够自适应的选择感知数据的重要维度【特征选择】。

    以下是本例中网络参数定义及初始的函数。

        def dn_create(self):
            self.y_lsn_flag = np.zeros((1, self.y_neuron_num))
            self.y_firing_age = np.zeros((1, self.y_neuron_num))
            self.y_inhibit_age = np.zeros((1, self.y_neuron_num))
            
            self.y_bottom_up_weight = np.ones((self.x_neuron_num, self.y_neuron_num))
            self.y_top_down_weight = []
            for i in range(self.z_area_num):
                self.y_top_down_weight.append(np.ones((self.z_neuron_num[i], self.y_neuron_num)))
            self.y_lateral_weight = np.zeros((self.y_neuron_num, self.y_neuron_num))
            self.y_inhibit_weight = np.ones((self.y_neuron_num, self.y_neuron_num))
            
            self.y_synapse_flag = 1
            """
            1: only bottom-up
            2: bottom-up + top-down
            3: bottom-up + top-down + lateral
            4: bottom-up + top-down + lateral + inhibit
            """
            self.y_synapse_coefficient = [0.8, 1.2, 5.0]
            self.y_synapse_age = 20
            
            self.y_bottom_up_synapse_diff = np.zeros(self.y_bottom_up_weight.shape)
            self.y_bottom_up_synapse_factor = np.ones(self.y_bottom_up_weight.shape)
            
            self.y_top_down_synapse_diff = []
            self.y_top_down_synapse_factor = []
            for i in range(self.z_area_num):
                self.y_top_down_synapse_diff.append(np.zeros(self.y_top_down_weight[i].shape))
                self.y_top_down_synapse_factor.append(np.ones(self.y_top_down_weight[i].shape))
                
            self.y_lateral_synapse_diff = np.zeros(self.y_lateral_weight.shape)
            self.y_lateral_synapse_factor = np.ones(self.y_lateral_weight.shape)
            
            self.y_inhibit_synapse_diff = np.zeros(self.y_inhibit_weight.shape)
            self.y_inhibit_synapse_factor = np.ones(self.y_inhibit_weight.shape)
            
            # z weights
            self.z_bottom_up_weight = []
            self.z_firing_age = []
            for i in range(self.z_area_num):
                self.z_bottom_up_weight.append(np.zeros((self.y_neuron_num, self.z_neuron_num[i])))
                self.z_firing_age.append(np.zeros((1, self.z_neuron_num[i])))
            # responses
            self.x_response = np.zeros((1, self.x_neuron_num))
            # pre lateral response is bottom up + top down, used to get lateral
            # pre response is bottom up + top down + lateral
            self.y_bottom_up_percent = 1/2
            self.y_top_down_percent = 1/2
            self.y_lateral_percent = 1/2
            
            self.y_bottom_up_response = np.zeros((1, self.y_neuron_num))
            self.y_top_down_response = np.zeros((self.z_area_num, self.y_neuron_num))
            self.y_pre_lateral_response = np.zeros((1, self.y_neuron_num))
            self.y_lateral_response = np.zeros((1, self.y_neuron_num))
            self.y_pre_response = np.zeros((1, self.y_neuron_num))
            
            self.y_response = np.zeros((1, self.y_neuron_num))
            self.z_response = []
            for i in range(self.z_area_num):
                self.z_response.append(np.zeros((1, self.z_neuron_num[i])))
    

    4.3.2 响应计算

    综合上图以及上节说明,一个完整的响应计算函数的输入包括:输入向量input_vec、权值向量weight_vec、注意力因子synapse_factor。首先,将注意力因子的每项元素与输入向量的对应元素相乘,再计算其归一化的单位向量,然后将归一化的融合注意力因子的输入向量与同样归一化的权值向量点乘得到最终的响应【两个归一化向量的点乘就是原向量的夹角余弦值cos(θ)cos(\theta)】。

    def compute_response(input_vec, weight_vec, synapse_factor):
        """
        input_vec is of shape 1x input_dim
        weight_vec is of shape input_dim x neuron_num
        syanpse_factor is of shape input_dim x neuron_num
        """
        
        _, neuron_num = weight_vec.shape
        _, input_dim = input_vec.shape
        
        # reshape input to neuron_num x input_dim
        temp_input = np.tile(input_vec, (neuron_num, 1))
        temp_input = temp_input*synapse_factor.T
        
        # normalize input
        temp_input_norm = np.sqrt(np.sum(temp_input*temp_input, axis=1))
        temp_input_norm[temp_input_norm == 0] = 1
        
        temp_input = temp_input/np.tile(temp_input_norm.reshape(-1, 1), (1, input_dim))
        
        # normalize weight
        weight_vec_normalized = weight_vec*synapse_factor
    #     plt.imshow(weight_vec_normalized)
    #     plt.show()
        weight_vec_norm = np.sqrt(np.sum(weight_vec_normalized*weight_vec_normalized, axis=0))
        weight_vec_norm[weight_vec_norm == 0] = 1
        
        weight_vec_normalized = weight_vec_normalized/np.tile(weight_vec_norm, (input_dim, 1))
        
        output_vec = np.zeros((1, neuron_num))
        for i in range(neuron_num):
            output_vec[0, i] = np.dot(temp_input[i,:].reshape(1, -1), weight_vec_normalized[:, i].reshape(-1, 1))[0,0]
        return output_vec
    

    4.3.3 top-k竞争响应

    假定我们利用以上响应计算函数分别得到各输入的响应,并加权求和得到最终的神经元响应。
    函数相关代码如下

            self.x_response = training_image.reshape(1, -1)
            for i in range(self.z_area_num):
                self.z_response[i] = np.zeros(self.z_response[i].shape)
                self.z_response[i][0,true_z[i]] = 1
            self.x_response = preprocess(self.x_response)
             # compute response
            self.y_bottom_up_response = compute_response(self.x_response, 
                                                         self.y_bottom_up_weight, 
                                                         self.y_bottom_up_synapse_factor)
            for i in range(self.z_area_num):
                self.y_top_down_response[i] = compute_response(self.z_response[i], 
                                                              self.y_top_down_weight[i],
                                                              self.y_top_down_synapse_factor[i])
            # top-down + bottom-up response    
            self.y_pre_lateral_response = (self.y_bottom_up_percent*self.y_bottom_up_response + 
                                           self.y_top_down_percent*np.mean(self.y_top_down_response, axis=0).reshape(1,-1))/(self.y_bottom_up_percent + self.y_top_down_percent)
            
    
            # 侧边响应    
            self.y_lateral_response = compute_response(self.y_pre_lateral_response,
                                                      self.y_lateral_weight,
                                                      self.y_lateral_synapse_factor)
            self.y_pre_response = ((self.y_bottom_up_percent + self.y_top_down_percent)*self.y_pre_lateral_response + 
                                   self.y_lateral_percent*self.y_lateral_response)
            
            self.y_response = top_k_competition(self.y_pre_response,
                                                self.y_top_down_response,
                                                self.y_inhibit_weight,
                                                self.y_inhibit_synapse_factor,
                                                self.y_top_k)
            
    

    我们需要进一步通过top-k竞争计算激活的神经元,从而知道哪些神经元可以利用当前样本进行参数更新。top-k竞争计算就利用了inhibit weight
    程序如下:

    def top_k_competition(response_input, top_down_response, inhibit_weight, inhibit_synapse_factor, top_k):
        """
        TODO: there are two ways to do things
        1: if a neuron is within the synapse, then include that neuron in top-k
        2: if a neuron is within the synapse and the weight is > 0.5, then
        include that neuron in top-k
        this version does things in the 1st way
        
        response_input is of size 1xneuron_num
        """
        response_output = np.zeros(response_input.shape)
        _, neuron_num = response_input.shape
        top_down_flag = np.ones((1, neuron_num))
        for i in range(len(top_down_response)):
            top_down_flag = top_down_flag*top_down_response[i]
        for i in range(neuron_num):
            curr_response = response_input[0,i]
            curr_mask = (inhibit_synapse_factor[:,i] > 0)
            compare_response = response_input*curr_mask.T.reshape(1, -1)
            compare_response[0,i] = curr_response
            neuron_id = np.argsort(-compare_response.reshape(-1))      
            
            for j in range(top_k):
                if len(top_down_response) != 0:
                    if neuron_id[j] == i and top_down_flag[0,i]>0:
                        response_output[0,i] = 1
                        break
                elif neuron_id[j] == i:
                    response_output[0,i] = 1
                    break            
        return response_output
    

    4.3.4 参数更新

    按上top-k竞争函数计算得到当前激活的神经元,就可根据赫布学习规则对各个权值进行更新。

    此处需要说明两点

    1. 本例子只对X进行了注意力选择,也即bottom_up_synapse_factor是有意义的,并且是在线更新的,通过synapse diff中间变量更新;输入Z没有注意力选择,synapse_factor所有元素都固定为1。
    2. 学习率lr是关于访问频次以及遗忘参数的函数,是随学习自适应调整的,不利用静态固定的学习率是为了合理分配历史数据与当前数据的权值,从而更好的跟踪输入环境的动态性。本例获取学习率的函数为(firing_age为该神经元的激活次数):
      在这里插入图片描述

    程序如下:

            # hebbian learning and synapse maitenance
            for i in range(self.y_neuron_num):
                if self.y_response[0,i] == 1: # firing neuron, currently set response to 1
                    if self.y_lsn_flag[0,i] == 0:
                        self.y_lsn_flag[0,i] = 1
                        self.y_firing_age[0,i] = 0
                    lr = get_learning_rate(self.y_firing_age[0,i]) # learning rate
                    # bottom-up weight and synapse factor
                    self.y_bottom_up_weight[:,i] = (1-lr)*self.y_bottom_up_weight[:,i] + lr*self.x_response.reshape(-1)
                    self.y_bottom_up_synapse_diff[:,i] = ((1-lr)*self.y_bottom_up_synapse_diff[:,i]+
                                                          lr*(np.abs(self.y_bottom_up_weight[:,i]-self.x_response.reshape(-1))))
                    if self.y_synapse_flag>0 and self.y_firing_age[0,i] > self.y_synapse_age:
                        self.y_bottom_up_synapse_factor[:,i] = get_synapse_factor(self.y_bottom_up_synapse_diff[:,i],
                                                                                  self.y_bottom_up_synapse_factor[:,i],
                                                                                  self.y_synapse_coefficient)
                    
                    # top-down weight and synapse factor
                    for j in range(self.z_area_num):
                        self.y_top_down_weight[j][:,i] = (1-lr)*self.y_top_down_weight[j][:,i] + lr*self.z_response[j].reshape(-1)
                        self.y_top_down_synapse_diff[j][:,i] = ((1-lr)*self.y_top_down_synapse_diff[j][:,i] + 
                                                                lr*np.abs(self.y_top_down_weight[j][:,i]-self.z_response[j].reshape(-1)))
                        if (self.y_synapse_flag>1) and (self.y_firing_age[0,i]>self.y_synapse_age):
                            self.y_top_down_synapse_factor[j][:,i] = get_synapse_factor(self.y_top_down_synapse_diff[j][:,i],
                                                                                        self.y_top_down_synapse_factor[j][:,i],
                                                                                        self.y_synapse_coefficient)
                    # lateral weight and synapse factor
                    # lateral exitation connection only exists within firing neurons
                    self.y_lateral_weight[:,i] = (1-lr)*self.y_lateral_weight[:,i]+lr*self.y_response.reshape(-1)
                    self.y_lateral_synapse_diff[:,i] = ((1-lr)*self.y_lateral_synapse_diff[:,i] + 
                                                        lr*np.abs(self.y_lateral_weight[:,i] - self.y_response.reshape(-1)))
                    if (self.y_synapse_flag > 2) and (self.y_firing_age[0,i]>self.y_synapse_age):
                        self.y_lateral_synapse_factor[:,i] = get_synapse_factor(self.y_lateral_synapse_diff[:,i],
                                                                               self.y_lateral_synapse_factor[:,i],
                                                                               self.y_synapse_coefficient)
                    self.y_firing_age[0,i] = self.y_firing_age[0,i] + 1
                elif self.y_lsn_flag[0,i] == 0: # initialization stage neuron is always updating
                    lr = get_learning_rate(self.y_firing_age[0,i])
                    normed_input = self.x_response.reshape(-1, 1)*self.y_bottom_up_synapse_factor[:,i].reshape(-1, 1)
                    self.y_bottom_up_weight[:,i] = (1-lr)*self.y_bottom_up_weight[:,i]+lr*normed_input.reshape(-1)
                    self.y_bottom_up_weight[:,i] = self.y_bottom_up_weight[:,i]*self.y_bottom_up_synapse_factor[:,i]
                    self.y_bottom_up_synapse_diff[:,i] = ((1-lr)*self.y_bottom_up_synapse_diff[:,i] +
                                                         lr*np.abs(self.y_bottom_up_weight[:,i] - normed_input.reshape(-1)))
                    
                    if self.y_synapse_flag>0 and self.y_firing_age[0,i] > self.y_synapse_age:
                        self.y_bottom_up_synapse_factor[:,i] = get_synapse_factor(self.y_bottom_up_synapse_diff[:,i],
                                                                              self.y_bottom_up_synapse_factor[:,i],
                                                                              self.y_synapse_coefficient)  
                    # top-down weight and synapse factor
                    for j in range(self.z_area_num):
                        self.y_top_down_weight[j][:,i] = (1-lr)*self.y_top_down_weight[j][:,i] + lr*self.z_response[j].reshape(-1)
                        self.y_top_down_synapse_diff[j][:,i] = ((1-lr)*self.y_top_down_synapse_diff[j][:,i] + 
                                                                lr*np.abs(self.y_top_down_weight[j][:,i]-self.z_response[j].reshape(-1)))
                        if (self.y_synapse_flag>1) and (self.y_firing_age[0,i]>self.y_synapse_age):
                            self.y_top_down_synapse_factor[j][:,i] = get_synapse_factor(self.y_top_down_synapse_diff[j][:,i],
                                                                                        self.y_top_down_synapse_factor[j][:,i],
                                                                                        self.y_synapse_coefficient)
                            
                    # lateral weight and synapse factor
                    # lateral exitation connection only exists within firing neurons
                    self.y_lateral_weight[:,i] = (1-lr)*self.y_lateral_weight[:,i]+lr*self.y_response.reshape(-1)
                    self.y_lateral_synapse_diff[:,i] = ((1-lr)*self.y_lateral_synapse_diff[:,i] + 
                                                        lr*np.abs(self.y_lateral_weight[:,i] - self.y_response.reshape(-1)))
                    if (self.y_synapse_flag > 2) and (self.y_firing_age[0,i]>self.y_synapse_age):
                        self.y_lateral_synapse_factor[:,i] = get_synapse_factor(self.y_lateral_synapse_diff[:,i],
                                                                               self.y_lateral_synapse_factor[:,i],
                                                                               self.y_synapse_coefficient)   
                else:
                    lr = get_learning_rate(self.y_inhibit_age[0,i])
                    temp = np.zeros(self.y_inhibit_synapse_factor.shape)
                    for j in range(self.y_neuron_num):
                        temp[:,j] = self.y_pre_lateral_response.reshape(-1)*self.y_inhibit_synapse_factor[:,j]
                        temp[:,j] = (temp[:,j] > self.y_pre_lateral_response[0,i])
                    self.y_inhibit_weight[:,i] = (1-lr)*self.y_inhibit_weight[:,i]+lr*temp[:,i]
                    self.y_inhibit_synapse_diff[:,i] = ((1-lr)*self.y_inhibit_synapse_diff[:,i] + 
                                                       lr*np.abs(self.y_inhibit_weight[:,i]-temp[:,i]))
                    if (self.y_synapse_flag > 3) and (self.y_firing_age[0,i]>self.y_synapse_age):
                        self.y_inhibit_synapse_factor[:,i] = get_synapse_factor(self.y_inhibit_synapse_diff[:,i],
                                                                               self.y_inhibit_synapse_factor[:,i],
                                                                               self.y_synapse_coefficient)
                    self.y_inhibit_age[0,i] = self.y_inhibit_age[0,i] + 1
            ## z neuron learning
            for area_idx in range(self.z_area_num):
                for i in range(self.z_neuron_num[area_idx]):
                    if self.z_response[area_idx][0,i] == 1:
                        lr = get_learning_rate(self.z_firing_age[area_idx][0,i])
                        self.z_bottom_up_weight[area_idx][:,i] = (1-lr)*self.z_bottom_up_weight[area_idx][:,i]+lr*self.y_response.reshape(-1)
                        self.z_firing_age[area_idx][0,i] = self.z_firing_age[area_idx][0,i] + 1
    

    4.3.5 DN利用

    如果,我们觉得DN训练的可以,或者中途测试DN的学习效果,我们需要看看DN对于某一输入X,输出的where motor与what motor的准确与否。如果准确率很高,说明DN对于当前样本的学习效果很好,可以用来预测。

    已知输入X,计算输出Z的程序如下:

        def dn_test(self, test_image):
            self.x_response = test_image.reshape(1, -1)
            self.x_response = preprocess(self.x_response)
            self.y_bottom_up_response = compute_response(self.x_response, 
                                                         self.y_bottom_up_weight, 
                                                         self.y_bottom_up_synapse_factor)
            self.y_pre_lateral_response = self.y_bottom_up_response
            self.y_lateral_response = compute_response(self.y_pre_lateral_response,
                                                       self.y_lateral_weight,
                                                       self.y_lateral_synapse_factor)
            self.y_pre_response = ((self.y_bottom_up_percent*self.y_pre_lateral_response+
                                   self.y_lateral_percent*self.y_lateral_response)/(self.y_bottom_up_percent+
                                                                                   self.y_lateral_percent))
            self.y_response = top_k_competition(self.y_pre_response, 
                                                [], 
                                                self.y_inhibit_weight, 
                                                self.y_inhibit_synapse_factor, 
                                                self.y_top_k)
            z_output = []
            for i in range(self.z_area_num):
                self.z_response[i] = compute_response(self.y_response,
                                                      self.z_bottom_up_weight[i],
                                                      np.ones(self.z_bottom_up_weight[i].shape))
                z_output_i = np.argmax(self.z_response[i])
                z_output.append(z_output_i)
            return np.array(z_output)
    

    4.3.5 DN神经元自适应增长

    本例中的发育程序会自适应的对发育网络的神经元个数进行增加,当某一神经元被连续激活超过某一次数时,程序中为20,则对神经元进行有丝分裂,一个神经元分裂成三个。
    分裂函数如下:

    def dn_split(dn, split_num, split_firing_age):
        input_dim = dn.x_neuron_num
        y_top_k = dn.y_top_k
        z_neuron_num = dn.z_neuron_num
        y_neuron_num = dn.y_neuron_num*split_num
    
        new_to_old_index = np.zeros(y_neuron_num, dtype=np.int)
        for i in range(dn.y_neuron_num):
            start_ind = i*split_num
            end_ind = (i+1)*split_num
            new_to_old_index[start_ind:end_ind] = i
        new_to_old_index = new_to_old_index.tolist()
        new_dn = DN(input_dim, y_neuron_num, y_top_k, z_neuron_num)
        for i in range(new_dn.y_neuron_num):
            j = new_to_old_index[i]
            new_dn.y_lsn_flag[0,i] = dn.y_lsn_flag[0,j]
            new_dn.y_firing_age[0,i] = split_firing_age
            new_dn.y_inhibit_age[0,i] = split_firing_age
            
            new_dn.y_bottom_up_weight[:,i] = (dn.y_bottom_up_weight[:,j] + 
                                              generate_rand_mutate(dn.y_bottom_up_weight[:,j].shape))
            new_dn.y_bottom_up_weight[:,i] = (dn.y_bottom_up_weight[:,j])/np.max(new_dn.y_bottom_up_weight[:,j])
            for z_ind in range(new_dn.z_area_num):
                new_dn.y_top_down_weight[z_ind][:,i] = (dn.y_top_down_weight[z_ind][:,j]+
                                                        generate_rand_mutate(dn.y_top_down_weight[z_ind][:,j].shape))
                new_dn.y_top_down_weight[z_ind][:,i] = new_dn.y_top_down_weight[z_ind][:,i]/np.max(new_dn.y_top_down_weight[z_ind][:,i])
            new_dn.y_lateral_weight[:,i] = dn.y_lateral_weight[new_to_old_index, j]
            new_dn.y_inhibit_weight[:,i] = (dn.y_inhibit_weight[new_to_old_index, j]+
                                           generate_rand_mutate(dn.y_inhibit_weight[new_to_old_index, j].shape))
            new_dn.y_inhibit_weight[:,i] = new_dn.y_inhibit_weight[:,i]/np.max(new_dn.y_inhibit_weight[:,i])
            
            new_dn.y_bottom_up_synapse_diff[:,i] = dn.y_bottom_up_synapse_diff[:,j]
            new_dn.y_bottom_up_synapse_factor[:,i] = np.ones(dn.y_bottom_up_synapse_factor[:,j].shape)
            
            for z_ind in range(new_dn.z_area_num):
                new_dn.y_top_down_synapse_diff[z_ind][:,i] = dn.y_top_down_synapse_diff[z_ind][:,j]
                new_dn.y_top_down_synapse_factor[z_ind][:,i] = np.ones(dn.y_top_down_synapse_factor[z_ind][:,j].shape)
            new_dn.y_lateral_synapse_diff[:,i] = dn.y_lateral_synapse_diff[new_to_old_index, j]
            new_dn.y_lateral_synapse_factor[:,i] = np.ones(dn.y_lateral_synapse_factor[new_to_old_index, j].shape)
            
            new_dn.y_inhibit_synapse_diff[:,i] = dn.y_inhibit_synapse_diff[new_to_old_index, j]
            new_dn.y_inhibit_synapse_factor[:,i] = np.ones(dn.y_inhibit_synapse_factor[new_to_old_index,j].shape)
            
            for z_ind in range(new_dn.z_area_num):
                new_dn.z_bottom_up_weight[z_ind][i,:] = dn.z_bottom_up_weight[z_ind][j,:]
                
        for z_ind in range(new_dn.z_area_num):
            new_dn.z_firing_age[z_ind] = np.ones(dn.z_firing_age[z_ind].shape)
        return new_dn
        
    

    4.4 结果

    每步的训练效果如下所示,我们发现中间有三次分裂操作,最终DN神经元个数为2533=225,最终的测试准确率为[0.99 0.962]。我们注意会发现,每当网络的性能遇到瓶颈时,发生分裂后,网络的性能重新被提升了。
    500 training, current performance:
    [0.226 0.054]
    1000 training, current performance:
    [0.278 0.068]
    1500 training, current performance:
    [0.362 0.164]
    2000 training, current performance:
    [0.41 0.17]
    2500 training, current performance:
    [0.4 0.172]
    3000 training, current performance:
    [0.442 0.182]
    3500 training, current performance:
    [0.476 0.212]
    4000 training, current performance:
    [0.48 0.226]
    4500 training, current performance:
    [0.486 0.206]
    5000 training, current performance:
    [0.466 0.242]
    5500 training, current performance:
    [0.462 0.204]
    6000 training, current performance:
    [0.48 0.232]
    6500 training, current performance:
    [0.436 0.174]
    7000 training, current performance:
    [0.522 0.256]
    splitting at 7263
    7500 training, current performance:
    [0.444 0.292]
    8000 training, current performance:
    [0.776 0.558]
    8500 training, current performance:
    [0.8 0.558]
    9000 training, current performance:
    [0.78 0.59]
    9500 training, current performance:
    [0.8 0.574]
    10000 training, current performance:
    [0.784 0.6 ]
    10500 training, current performance:
    [0.794 0.586]
    11000 training, current performance:
    [0.82 0.596]
    11500 training, current performance:
    [0.824 0.614]
    12000 training, current performance:
    [0.826 0.602]
    12500 training, current performance:
    [0.818 0.58 ]
    splitting at 12804
    13000 training, current performance:
    [0.688 0.444]
    13500 training, current performance:
    [0.802 0.696]
    14000 training, current performance:
    [0.922 0.882]
    14500 training, current performance:
    [0.934 0.908]
    15000 training, current performance:
    [0.92 0.9 ]
    15500 training, current performance:
    [0.924 0.876]
    16000 training, current performance:
    [0.96 0.922]
    16500 training, current performance:
    [0.974 0.928]
    17000 training, current performance:
    [0.988 0.954]
    17500 training, current performance:
    [0.97 0.956]
    18000 training, current performance:
    [0.984 0.95 ]
    18500 training, current performance:
    [0.992 0.984]
    19000 training, current performance:
    [0.988 0.956]
    19500 training, current performance:
    [0.988 0.97 ]
    20000 training, current performance:
    [0.996 0.97 ]
    20500 training, current performance:
    [0.986 0.958]
    21000 training, current performance:
    [0.99 0.956]
    21500 training, current performance:
    [0.994 0.972]
    22000 training, current performance:
    [0.994 0.978]
    22500 training, current performance:
    [0.992 0.982]
    23000 training, current performance:
    [0.992 0.978]
    23500 training, current performance:
    [0.992 0.966]
    24000 training, current performance:
    [0.99 0.958]
    24500 training, current performance:
    [0.99 0.962]
    testing error is [0.996 0.975]
    DN y_bottom_up_weight按15x15的矩阵点打印输出如下,每个矩阵点是一个19x19的小矩阵。
    在这里插入图片描述

    4.5 程序[已上传github]

    声明:本例子的程序是参照翁教授的学生Zejia Zheng的matlab代码写的。
    附上源码地址github/ZejiaZheng/multiresolutionDN[matlab]

    本人通过将matlab代码改写成python代码的方式来加深入理解发育网络。本人是基于jupyter notebook交互式编译框架下写的python程序,现已上传到github。
    github/huyanmingtoby/multiresolutionDN[python]

    4.6 分析与讨论

    本节(第4节)利用一个实现例子【Where-What-Network】来补充说明发育网络。利用构造的图片数据以及对象的位置与种类标答作为WWN的输入,对网络进行训练。在训练过程中,发育网络自己对发育层的神经元进行两次有丝分裂,最终形成225个神经元。每次分裂都能使测试的正确率大幅度提升。最后还将y_bottom_up_weight打印了出来,每个神经元与X输入相关的权值按19x19打印,发现它们是一系列与输入的图片非常相似的模式。对于所有对象可能出现的所有位置为5x25=125。最理想的神经元个数为125便能把所有可能的模式存储。初始化时DN的神经元个数为25个,显然不够;经过一次有丝分裂变成25x3=75个,也还不够;再经过一次有丝分裂75x3=225个,理论上是够了【实际实验结果也表明是够了,测试准确率非常高[0.99 0.962]】。但是,有一点需要说明,那就是背景是随机选的,对于同一个对象在同一个位置放入随机的背景中,那还是无数多种。最终发育网络的神经元在225时的效果就已经很好了,说明发育网络能够将抓住重要的信息(对象相关的像素点),忽略那些背景像素点,这是注意力选择起作用了。神经元注意力选择权值让其只对输入的对应区域有响应,从而避免了背景噪声的影响。

    个人观点:我自己看论文,特别是机器学习方面的论文,看完感觉懂了,实则不然,很多重要的思想都掩藏在真实的实现过程中。如果真得觉得手头那篇论文非常有价值,最好能找到作者实现的程序读一读,并自己动手编程实现。很多难以言表却又重要的思想,作者为了可读性可能不会写进论文,但是肯定藏在程序里。如果觉得发育网络很有价值,建议完整程序git下来,自己看一遍,动手写一写,跑一跑程序。

    5. 结语

    本文在思想、方法、算法、程序等四个层面对发育网络进行了系统的介绍。发育网络具有in-place特点,每个神经元包含全部的发育程序,因此,我们着重对一个神经元的初始化、训练、利用进行说明。每个神经元的发育程序都是一个CCILCA,本文为了描述清楚DN的思想,将叶成分分析拆分开了,很难看到完成LCA的身影。但我认为这对于DN思想与方法的介绍是有益的。我将在另一篇博客将本文打碎的LCA还原成完整的算法。最后,利用发育网络的一个列子WWN加深DN的理解,并借此透露更多DN的细节。DN的发育层神经元个数自适应调整,最终的学习效果也是非常不错的。
    另外,本文也掺入大量个人见解。不一定合适,欢迎交流。现将本人对DN的疑惑整理如下:

    • DN中的遗忘是否合理,人类具有的特质是否就是好的?
    • 能否在不大改自主发育程序的前提下,用其他距离度量替代cos(θ)cos(\theta)
    • DN归根结底还是以查找表的形式存储学习到的知识,也即<x, z>,人类大脑中的知识是否真的就是这种以一个个记忆状态存在?像深度学习、RBF网络会用非线性函数拟合x到z的关系,这显然是更加有效率的方式【先抛开人类增量式、序列式学习】,这种函数表征的方式能够对信息进行更有效的编码,从而使得同样的信息量,函数表示所需要的模型容量会更小。
    展开全文
  • 最近准备慢慢自学ROS机器人,从闲鱼上入手了和二手微型电脑,本来准备买一个树莓派什么的开发板学习,后来大神推荐价格差不多的可以直接从X86框架的微型计算机开始,同样的价格,功能更为强大,系统的可移植也很...

    @Intel NUC DN2820微型计算机装机过程

    最近准备慢慢自学ROS机器人,从闲鱼上入手了和二手微型电脑,本来准备买一个树莓派什么的开发板学习,后来大神推荐价格差不多的可以直接从X86框架的微型计算机开始,同样的价格,功能更为强大,系统的可移植性也很高。长话短说,就此开始了自己的ROS小白之路,学习之路还望各位大神指点一二。
    这是2014年的产品,感觉就是处理器还是略差了一点,赛扬N2820的,处理器性能各方面感觉还是差了不少,初次使用心里还是没有谱。不过对于本机的内存和硬盘倒是很满意,4G的内存配上120G的固态,感觉作为普通的家庭电脑和ROS小车的上位机及足够的。

    1 ,U盘安装系统

    以前在使用个人笔记本的时候,对于U盘装系统还是挺熟悉的,我有两个U盘,因为内存很大,所以常年都是作U盘启动盘和普通存储U盘使用,制作U盘启动盘的过程就不讲述了,安装WIN系统老毛桃和大白菜装机都可以,安装Ubuntu系统是使用UltraISO工具。由于自己有这两个系统的U盘启动盘,所以就直接进入安装过程。

    2,进入BIOS menu

    在开机的时候长按开关3秒,等一下,便进入了BIOS menu,首先我自己按照以前的装机经验,根据提示按F10,进入BIOS menu,然后选择U盘启动。这里注意,似乎USB3.0的接口无法识别,不知道怎么回事,建议出现无法识别U盘启动盘的时候,将U盘插在USB2.0的接口上。顺利从U盘启动了计算机,但是后来发生的事情让人困惑,安装WIN系统时,先的进入WIN8PE系统操作,可是选择操作系统的时候,中文都是乱码,不知道是什么文字,选择了PE系统,等待良久也无法进入,让人很无措。
    后来就想直接装ubuntu,但是按照同样的操作,选择了U盘启动,进入ubuntu的安装,也是在安装界面就不动力,尝试了很多遍,都没有成功,让人对这微型计算机的性能产生了怀疑。
    (对于如何进入BIOS menu,网上说是开机F2,但是进去的menu菜单完全是另外一回事,找了一圈,还是没有找到哪里可以从U盘启动的。后来找到了,在这里强调一下和其他计算机开机直接按谋键不太一样,这是BIOS软件落后的缘故,开机按住开机键3秒,开机按住开机键3秒,开机按住开机键3秒,重要的事情多说几遍)

    3,更新BIOS系统

    转头想了一想,既然计算机都能跑WIN7系统(计算机自带的),那应该在性能上没有什么毛病,肯定能跑ubuntu系统,但是为啥就是安装不上?这里已经尝试了N遍,将进入BIOS menu路上的所有英文看了一遍,隐隐感觉需要update bios,于是待着尝试的态度,就百度了怎么更新NUC微型计算机的BIOS,结果一路尝试过来,https://www.intel.cn/content/www/cn/zh/support/articles/000005532/mini-pcs.html上下载了FY0069.bio文件,将它拷进U盘首层目录,这个很重要,待会要用。
    现在就想办法更新BIOS了,当然都是带着尝试的态度,开机按3秒进入选项,按照提示F7,update bios,选择从U盘更新,选择首层目录中的FY0069.bio,然后确定,计算机就开始更新BIOS了,这个过程有点长,中间还有一段时间画面不动,切记它在更新,更新完了的会在最后写上done,不要断电。

    4,更新完

    更新完了,计算机会自动重新启动,现在看上去的启动画面比之前的只有屏幕上方有文字的启动画面好很多,更新完之后,开机会面会有一个Intel的标志,其中Intel NUC 的字样也很大,并在开机时会提示你按F2,F7,F10会进入到哪里,当然我们是会按照提示按F10来进入BIOS menu,选择我们需要的U盘启动盘来安装我们的系统

    5 安装双系统

    我个人觉得计算机安装双系统比较好用,首先这么大的内存一个Ubuntu系统就太浪费了,有时也需要win系统娱乐。装机的具体过程就不累述了,主要是说一下内存空间的分配。
    在PE装机系统中,安装之前先用分盘工具简单的分一下盘,WIN如果常用的话,就分两个盘,C + D共70G~80G左右,当然一个C盘80也是不错的 ,毕竟是固态啊,留下3040G不要分,给下个一Ubuntu系统。在安装Ubuntu系统的时候,也会出现一个分盘过程,但是前提是你的选择自动安装,有的就直接选择自动安装可能就没有这个过程了。自定义安装的时候,就将留下来得3040G的内存分了,首先boot挂载的分区300M就可以了,很少,然后交换空间挂载一个5G的分区,其他的都可以的根目录挂载的分区了,当然自己的喜好不一样呢,我还将home挂载了20G的分区上,其他的都是根目录。
    其分区的目的最主要将两个系统的内存分开,对于统一系统的各个分区,说是要分开,但是我还没有理解到那一层,没有遇到过相关的问题设置等,也是很糊涂,以后遇到麻烦了再来谈论。
    总结,这也算是我学习之路的第一篇记录了,跟踪自己的学习之路,也慢慢的积累,若有大神浏览中看到有错误的地方,希望谅解和留言,更正学习交流。

    展开全文
  • 首先,需要明白两种系统分别是什么。水冷系统指利用冷却水来冷却LED灯的温度,它的原理是利用水(或防冻液)作为冷却介质带走高温机件的热量。风冷是利用风扇吹风或者吸风冷却,它的原理是采用空气作冷却介质,高速流动...
  • 首先,需要明白两种系统分别是什么。1、水冷系统指利用冷却水来冷却LED灯的温度,它的原理是利用水(或防冻液)作为冷却介质带走高温机件的热量。2、风冷是利用风扇吹风或者吸风冷却,它的原理是采用空气作冷...
  • 这个公式读作“关系 R 定义域 D1, D2, …, Dn 的笛卡儿积的子集”。 公式很简洁,为了便于理解,我们再举个简单的例子解释一下。首先假设 有 3 个属性 a1、 a2、 a3,然后我们描述一下它们的定义域。这里说的定义 ...
  • 我们大多数的客户在他们的服务器上使用Apache作为Web服务器,...鉴于扩张和性能方面的原因,我们通常会建议他们改用Nginx和FPM。 https://dn-linuxcn.qbox.me/data/attachment/album/201303/24/160019nbnlkqb0n0l...
  • linux搭建开源ldap服务器方法

    千次阅读 2019-03-15 15:11:41
    ldap条目概念:基准DN,例如dc=company,dc=com,DN,例如cn=test,dc=company,dc=com,一个DN就是一个条目,RDN相对DN,具有唯一,上面例子的DN的RDN就是cn=test 2.下载openldap openld...
  • DataNode工作机制

    2021-02-14 09:15:54
    1.dn中数据块的存储方式为数据块+数据块的元数据,数据块的元数据包括:数据块长度、检验和、时间戳。...为什么是10分钟+30秒判定dn故障? hdfs-site.xml配置文件中,配置了心跳机制的间隔时间和重连超时时间,如果该.
  • 私有协议是什么?PolarDB-X作为阿里巴巴自主研发的云原生分布式数据库,通过将数据拆分到多个基于MySQL发展而来的存储节点DN,每个存储节点DN承担合适的并发、数据存储和计算负载,计算节点处理分布式逻辑,最终得到...
  • 2.1 什么是HDFS 2.2 设计目标 2.3 HDFS架构 2.3.1NN: 2.3.2DN: 三、YARN 3.1Yarn产生背景 3.2 yarn产生  3.3 Yarn的架构: 四、MapReduce 4.1MapReduce概述 4.2MapReduce编程模型 五、hadoop优势 1...
  • HDFS介绍及简单操作

    2019-09-25 02:37:20
    1.HDFS是什么? 2.HDFS设计基础与目标 3.HDFS体系结构 3.1 NameNode(NN)3.2 DataNode(DN)3.3 SecondaryNameNode(SNN)3.4 块(Block)的概念3.5 文件安全 3.读取数据流程 4.HDFS的可靠 4.1 冗余副本...
  • [图片说明](https://img-ask.csdn.net/upload/201805/14/1526269677_709702.png)我尝试了并行三个温度传感器 但是温度一直显示不对,然后试了下只编程一个 也27.9不知道为什么 然后我自己做的按钮,编程好像也有点...
  • 如果深入到运维的世界,你会发现大部分工具还活在上个世纪,产品设计完全反人类,比如cn, dc, dn, ou这样的命名方式,如果不钻研个一天两天,鬼知道它在说什么,比如说dns,dns是什么鬼?域名吗?不是,它只是某个...
  • 关于dns预解析

    2017-02-27 20:05:00
    DNS 实现域名到IP的映射。...什么是 DNS Prefetch ?DNS Prefetch 一种DNS 预解析技术,当你浏览网页时,浏览器会在加载网页时对网页中的域名进行解析缓存,这样在你单击当前网页中的连接时就无需进行DN...
  • 一、什么是阿姆斯特朗数?如果一个正整数等于其各个数字的立方和,则称该数为阿姆斯特朗数(亦称为自恋数)。一个正整数称为阿姆斯特朗阶数。例:abcd... = an + bn + cn + dn + ...如果3位的阿姆斯特朗数字,则...
  • 一、什么是阿姆斯特朗数?如果一个正整数等于其各个数字的立方和,则称该数为阿姆斯特朗数(亦称为自恋数)。一个正整数称为阿姆斯特朗阶数。例:abcd...=an+bn+cn+dn+...如果3位的阿姆斯特朗数字,则每个数字的...
  • 一、什么是阿姆斯特朗数?如果一个正整数等于其各个数字的立方和,则称该数为阿姆斯特朗数(亦称为自恋数)。一个正整数称为阿姆斯特朗阶数。例:abcd...=an+bn+cn+dn+...如果3位的阿姆斯特朗数字,则每个数字的...
  • DNS Prefetch

    2016-04-06 09:58:00
    DNS 实现域名到IP的映射。...什么是 DNS Prefetch ?DNS Prefetch 一种DNS 预解析技术,当你浏览网页时,浏览器会在加载网页时对网页中的域名进行解析缓存,这样在你单击当前网页中的连接时就无需进行DN...
  • 1,首先要先了解下什么是rack(机架)集群,一个集群有多个机架,一个机架有多个机器,一个机器一个datanode或namenode节点。通常一个机架内的机器之间的网络速度会高于跨机架机器之间的网络速度。 2,但是要同时...
  • 一、 实验目的 进一步熟悉keil开发环境,阅读和学习数据手册,学习并理解FTM,PDB中断定时器,进一步巩固定时器的用途和实现。 二、实验内容 ...1. 查找资料并回答:PDB,FTM在实际应用中主要用途是什么
  • ##一、什么是阿姆斯特朗数? 如果一个正整数等于其各个数字的立方和,则称该数为阿姆斯特朗数(亦称为自恋数)。 一个正整数称为阿姆斯特朗阶数。 例: abcd... = an + bn + cn + dn + ...如果3位的阿姆斯特朗数字...
  • 一、什么是阿姆斯特朗数? 如果一个正整数等于其各个数字的立方和,则称该数为阿姆斯特朗数(亦称为自恋数)。 一个正整数称为阿姆斯特朗阶数。 推荐一下我建的python学习交流qun:850973621,群里有免费的视频教程...
  • 承插贯通感导水力性能,DN管道,SN竖向位移mm万次,存储和命名文额件的结构无冲垮Hz。机器进行缠绕的口碑的采光瓦品牌,操作步骤玻璃钢保温罩质量怎么样,这样的市面上玻璃钢夹砂管哪个而一般的聚烯烃管不能。...
  • 警告:如果您不知道torrent是什么,或者不确定要下载的torrent的合法,则不要使用cliflix 。 安装 $ npm install -g cliflix 用法 巫师 执行cliflix以运行向导,它将询问您所需的一切:搜索查询,要流式传输的...
  • 而你又不想降低安全,这里的 csrf_token() 函数将会给你巨大的帮助。 后端接收数据 我们在页面中填入了一些数据,点击了提交按钮,这条请求会被分配到那里呢? <p><img alt="" src=...
  • Andrew Koenig的《Accelerated C++》一本真正具有实践的入门书。该书传承了《Ruminations On C++》的阐述方法,通过一个又一个具体的设计实例充分体现使用C++进行开发的真正优势之所在。事实上,笔者觉得Andy的...
  • Andrew Koenig的《Accelerated C++》一本真正具有实践的入门书。该书传承了《Ruminations On C++》的阐述方法,通过一个又一个具体的设计实例充分体现使用C++进行开发的真正优势之所在。事实上,笔者觉得Andy的...

空空如也

空空如也

1 2 3
收藏数 45
精华内容 18
关键字:

性dn是什么