core | ||
history | ||
other | ||
.gitignore | ||
3d-model.gif | ||
brainstructure.png | ||
command.bat | ||
depth_tree.png | ||
frog.png | ||
LICENSE | ||
logo.png | ||
README1.md | ||
README.md | ||
result1.gif | ||
result2.gif | ||
result3.gif | ||
result4.gif | ||
result5_seesaw.gif | ||
result6_letter.gif | ||
result7_legs.gif | ||
result8_snake.gif | ||
result9_earthquake.gif | ||
result10_drawsnake.gif | ||
result11_letter_test.gif | ||
result12_letter_test2.png | ||
result13_frog3d.gif | ||
result14_wa3d.gif | ||
result15_fish3d.gif | ||
result16_cell_split.gif | ||
result17_tree_grow.gif | ||
result18_yinyan_eatfood.gif | ||
result19_tree4.png | ||
result20_3cells1.gif | ||
result20_3cells2.gif | ||
result20_3cells3.gif | ||
snake.png | ||
talk.png | ||
task1.png |
Frog | 人工生命
这是一个人工生命试验项目,最终目标是创建“有自我意识表现”的模拟生命体。
注:因README篇幅太长,2023年8月之前的内容已归档到README1.md中了,如果第一次看到这个项目的网友,请先从README1.md开始看。如果已经了解这个项目的,请接着往下看即可。
目前进展
2023-08-25 三个细胞一台戏
本次更新在目录history\014_3cells下。在上次更新里已经说过了,为了实现模式识别,可以先从最简单的几个细胞的场景开始做起。于是就一路简化,最终简化到只剩下三个细胞,分别为视细胞、咬细胞、忆细胞。 实验目的是要达到这样一个效果,当食物出现时,视细胞激活,然后视细胞在忆细胞上打个洞,咬细胞则随机激活,然后也在忆细胞上也打个洞,最终实现的效果将会是视细胞激活忆细胞,然后忆细胞在洞上反向发送能量给咬细胞,这样就实现了视细胞到咬细胞的短路,形成一个最简单的条件反射。忆细胞的作用是隔离视细胞和咬细胞,防止形成视细胞直接驱动咬细胞这种简单连接。任务看起来很简单,但做起来就不太美好了,快两个月了才有点进展,先更新上来再说。
上面从左到右三个图,分别是对应三种场景下青蛙的行为:1奖惩值都很大;2奖励值远比惩罚值大;3只有奖励,没有惩罚。
奖励是当咬下时正好有食物;惩罚是当咬下时食物不存在,咬了个空。测试时请修改Genes.java源码第138行,进行不同惩罚值的调整。可以看到,根据奖罚值的不同,三个细胞进化出的神经网络参数是不同的,奖惩值都很大时,细胞就会躺平,多咬多错,还不如不咬,以避免惩罚;奖励值远比惩罚值大时,细胞就会比较活跃,没有食物时也经常空咬;当完全没有惩罚时,细胞就会放飞自我,直接在咬细胞和忆细胞之间进化出信号循环回路锁定,全程都在咬,而且最过分的是干脆忽略掉视觉信号,把视细胞和忆细胞之间的连线(洞)直接用一个负值(蓝色)参数来掐断。
这次更新的主角不是分裂算法(因为就三个细胞,谈不上结构了),而是全局常量。本次程序中控制细胞特性的全局参数有7个,分别是:
视细胞激活后产生多大强度的能量?
咬细胞激活后产生多大强度的能量?
每个细胞激活后能量随时间流逝,每一步会遗失多少能量?
咬细胞激活后向记忆细胞传送多少能量?
视细胞激活后向记忆细胞传送多少能量
忆细胞激活后反向向视细胞传送多少能量?
忆细胞激活后反向向咬细胞传送多少能量?
这些全局参数是跟随青蛙终身的,一旦青蛙孵化出来就不再动了,在程序里把所有常量放在一个数组里,用遗传算法来控制,基本规则是小变动有大概率发生,大变动有小概率发生。青蛙的参数分为两类,一类是与空间位置相关的,如脑细胞是否会出现在某个空间位置,一类是与位置无关的,如每个细胞激活后向其它细胞发送多少能量。前者要放到分裂算法里,用一串8/4/2叉基因树来控制空间分布,后者就没必要这么浪费了,直接用一组全局数字表示即可,并用遗传算法来随机变异和筛选它们。在给神经网络编程时,如果碰到可以用全局常量来控制的参数,尽量不要手工赋值,而要用遗传算法来控制,因为多变量的优化组合筛选靠人力是不可能做好的。就拿这个例子来说,我压根不知道这些参数将会是多大,是正还是负,但是我知道应该有这些参数,这就够了。人工生命项目编程不讲究精准,思维模式要从传统的精细化编程转变为以概率、笼统、可能为导向的思维,大方向人为确定,细节交给电脑去算,这和大自然用遗传算法来筛选出脑细胞的参数是一个道理。
从本次更新可以看到,青蛙是工作在一个连续的信息流下面,信息是以脉冲方式在细胞之间互相传递大小不等的能量,可以说是一个最简单的脉冲神经网络大脑了。这个实验不很实美,没有实现一个不漏地吃掉食物但是又不空咬这个目标,但是人生苦短,我不想继续和这三个细胞缠斗下去了,后面将转到多个视觉细胞和引入苦甜奖惩信号细胞来影响洞(权重)的大小,这个会更有趣、更智能,也更接近模式识别任务。我认为通用智能就是模式识别与行为输出结合起来的系统,如果奖罚细胞和行为输出细胞在一开始就做为这个模式识别系统的一个组成部分,并且由遗传算法来筛选参数,那通用人工智能就不远了。
运行方式 | Run
运行core或history各个子目录下的run.bat批处理文件即可启动运行,history下有多个子目录,按版本号顺序排列,存放着这个项目演化过程中的主要历史版本供演示。
另外如果想要研究这个项目的早期版本,可以结合gitk命令和参考"版本提交记录.md"的介绍,用git reset命令回复到以前任一个版本,例如用:
git reset --hard ae34b07e
可以转回到以前一个分组测试的找食版本。 码云上通常是大版本提交,跑出结果才会更新,GitHub上则是日常提交。
更多关于项目源码的介绍可以参见other目录下的"初学者入门介绍.md"以及history目录下的项目文档。
重要参数 | Parameters
在Env.java类中以下有以下可调整参数,请手工修改这些参数进行不同的测试,前4个参数很重要:
SHOW_SPEED: 调整实验的速度(1~1000),值越小则越慢。
EGG_QTY: 每次允许Frog下多少个蛋,通常下蛋取值在10~1000之间。蛋保存着我们测试的结果。实验的最终目标就是获得一批蛋。
FROG_PER_EGG: 每个蛋可以孵出多少个青蛙。
SCREEN: 分屏测试,一轮测试可以分为多个批次进行,这里是屏数。每轮总的青蛙数量=EGG_QTY * FROG_PER_EGG, 每屏青蛙数=总数/SCREEN
DELETE_EGGS: 每次运行是否先删除保存的蛋,如果设为false,将不删除保存的蛋,会接着上次的测试结果续继运行。
SAVE_EGGS_FILE: 是否允许输出蛋文件到磁盘上
ENV_WIDTH: 虚拟环境的宽度大小,通常取值100~1000左右
ENV_HEIGHT: 虚拟环境高度大小,通常取值100~1000左右
FROG_BRAIN_DISP_WIDTH: Frog的脑图在屏幕上的显示大小,通常取值100~1000左右
STEPS_PER_ROUND: 每轮测试步数, 每一步相当于脑思考的一桢,所有青蛙的脑神经元被遍历一次。
FOOD_QTY:食物的数量,食物越多,则Frog的生存率就越高,能量排名靠前的一批Frog可以下蛋,其余的被淘汰。
版权 | License
期望 | Futures
欢迎发issue、评论等方式提出建议或加入开发组。另外在other目录下可以提交你的文章、项目链接等资源。另外也欢迎给项目捐助,这可以加快项目的开发速度。