神经网络回顾-感知机
1. 生物的眼睛
眼睛是绝大多数动物必备的器官,其复杂精妙令人惊叹。
在进化过程中,最初的眼应该是从单个感光细胞逐渐扩增分化而来。
以下转自林十之在知乎眼睛是如何进化出来的?的中回答。
嗯哼祖师爷达尔文也承认眼睛这类复杂器官的进化是进化论上的一个难点。他最后作了一个猜想——两个细胞组成的感光器官。一个感光细胞接受光线刺激并转化为电化学信号,另一个色素细胞则遮挡来自另一面的光线使得动物能够感知光线的来源方向。一旦有了这样有功能的结构,自然选择就可以起作用了,可以不断促成器官的进化和完善。
实际上这样的"眼睛“在这之后已经发现了。那就是涡虫的眼睛。
(Gehring, 2011)。图D可以看到仅有两个细胞组成的眼睛结构。
好了,我们现在有了最简单的眼睛。那么新的问题是,怎样从最简单的眼睛进化出各种各样的复杂眼睛呢?直到八十年代,人们仍普遍认为诸如昆虫的复眼和哺乳动物的眼睛这样形态差异巨大的结构,是多次独立起源的结果。但这又带来了进化论解释上的困难。因为这样复杂的结构是多次独立起源的,大自然是不是就太鬼斧神工了一点?
但九十年代结合分子进化的新研究成果表明,所有的眼睛都是单次起源的产物。证据是主导所有动物眼睛的基因都是Pax 6基因家族的同源基因(Gehring, 1999)。Pax 6 基因家族在动物里面非常保守,甚至有实验显示把老鼠的 Pax 6 转移到果蝇里面,仍能介导眼睛的发育(Halder et al., 1995)。
(Gehring, 1999)。从最简单的眼睛到各种高级眼睛的演化。
我们现在知道所有的眼睛都起源于涡虫那样的最简单的眼睛结构,并受到Pax 6基因家族的调控。那么最简单的眼睛到昆虫的复眼和哺乳动物的复杂眼睛,是怎么一步一步进化过来的呢?Gehring提出了插入进化(intercalary evolution)的概念来解释。一旦我们有了最简单的两端的结构,即由Pax 6调控的感光细胞和由Mitf基因调控的色素细胞,这两者之间的结构,就可以在自然选择下通过不断优化插入其间,并不断复杂起来。
从分子层面细化来说,插入进化可以由三种途径达到:首先是基因多倍化和之后的功能分化。调控眼睛发育的很多基因,如ey和toy,都是Pax 6基因家族的同源基因,在该基因多倍化后,不同的拷贝出现了功能的分化(Czerny et al., 1999)。
然后是将其他已有基因整合进眼睛发育的调控通路中。比如晶状体球蛋白中的乳酸脱氢酶和热激蛋白就来自于这样的基因共享(Piatigorsky, 1989)。
最后通过已有调控基因的重组和拼接进行的基因修补(evolutionary tinkering)也能形成新的形态通路(Jacob, 1997)。
再看看眼睛位置的演化。一开始眼睛的部位是不固定的。
(Hou et al., 2007)。中华微网虫(Microdictyon sinicum)化石
比如这种已灭绝的,在云南澄江化石群发现的寒武纪中华微网虫(Microdictyon sinicum),身体的每一节都有一对复眼。而之后随着同源异型基因Hox的分化,动物的眼睛逐渐向头部集中(Gehring, 2011)。
从最简单的眼睛到最完善复杂的眼睛结构的演化所需要的时间,也比人们想象的要短。有研究依据数学模型推导此过程仅需要几十万年(Nilsson & Pelger, 1994)。
该图标示出了每一步所需要的步骤数。
2.最简单的眼的功能
蜗虫作为扁形动物,神经系统比腔肠动物有显著的进步。表现在神经细胞逐渐向前集中,形成脑及从“脑”向后分出若干纵神经索,在纵神经索之间有横神经相连。在高等种类,纵神经索减少,只有一对腹神经索发达,其中有横神经连接如梯形(或称梯式神经系统),脑与神经索都有神经纤维与身体各部分联系。可以说扁形动物出现了原始的中枢神经系统。这种神经系统虽比腔肠动物的网状神经系统高级,但它又是原始的,因为神经细胞不完全集中于“脑’,也分散在神经索中。
假设由三个细胞组成的眼,每个细胞只能判断该方向光线有无。信号如下图所示。
类似于101, 110, 001之类的数字信号。
经过一个感知机模型,便能区分上述不同的类型。
根据之前感知机学习算法中的实现,结果如下。
# coding:utf-8 import numpy as np def percepT(x, y, iter): # 感知机原始形式 n = np.shape(x)[1] m = len(x) theta = np.ones(n) alpha = 0.02 for it in range(iter): l = 0 # print it # 0 1 2 3 4 5 6 7 for k in range(m): if (x[k].dot(theta.T)) * y[k] < 0: l = 1 theta += alpha * y[k] * x[k] if l == 0: break return theta N=3 a=range(2**N) x=[bin(i)[2:].zfill(N) for i in a] data=np.array([[int(i) for i in j ]for j in x]) label=np.array([i[0]+i[2] for i in data]) label[label==0]=-1 for i in zip(data,label): print i """ (array([0, 0, 0]), -1) (array([0, 0, 1]), 1) (array([0, 1, 0]), -1) (array([0, 1, 1]), 1) (array([1, 0, 0]), 1) (array([1, 0, 1]), 2) (array([1, 1, 0]), 1) (array([1, 1, 1]), 2) """ theta = percepT(data, label, 100) print theta # [ 1.00000000e+00 -6.17561557e-16 1.00000000e+00] for i,j in zip(data,label): print i.dot(theta.T) * j>=0 """ True True True True True True True True """
不过感知机是一种线性分类模型。那么异或问题是什么呢?异或可以表示为如下形式:
即异或问题可以分为根据输出可以分为两类,显示在二维坐标系中如上图(右)所示:其中输出结果为1对应右图中红色的十字架,输出为0对应右图中蓝色的圆圈,我们可以发现对于这种情况无法找到一条直线将两类结果分开。即感知机无法找到一个线性模型对异或问题进行划分。
如上例中将i[0]+i[2]改为i[0]*i[2]便无法收敛。
# coding:utf-8 import numpy as np def percepT(x, y, iter): # 感知机原始形式 n = np.shape(x)[1] m = len(x) theta = np.ones(n) alpha = 0.02 for it in range(iter): l = 0 print it # 0 1 2 3 4 5 6 7 for k in range(m): if (x[k].dot(theta.T)) * y[k] < 0: l = 1 theta += alpha * y[k] * x[k] if l == 0: break return theta N=3 a=range(2**N) x=[bin(i)[2:].zfill(N) for i in a] data=np.array([[int(i) for i in j ]for j in x]) label=np.array([i[0]*i[2] for i in data]) label[label==0]=-1 for i in zip(data,label): print i """ (array([0, 0, 0]), -1) (array([0, 0, 1]), -1) (array([0, 1, 0]), -1) (array([0, 1, 1]), -1) (array([1, 0, 0]), -1) (array([1, 0, 1]), 1) (array([1, 1, 0]), -1) (array([1, 1, 1]), 1) """ theta = percepT(data, label, 100) print theta # [ 0.02 -0.02 0.02] for i,j in zip(data,label): print i.dot(theta.T) * j>=0 """ True False True True False True True True """