Trap & Active & Chance

This commit is contained in:
Yong Zhu 2019-07-28 03:45:39 -06:00
parent 2add4630e9
commit b090d746be
23 changed files with 555 additions and 130 deletions

BIN
3d-model.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

View File

@ -1,4 +1,5 @@
## Frog | 人工生命
(English introduction please see "README_EN.md")
这是一个人工生命试验项目最终目标是创建“有自我意识表现”的模拟生命体技术架构基于02年提出的 [一个人工脑模型](一个人工脑模型.md)。
这个项目永远没有结束的时候,开始于模拟一个简单的生命体,然后是青蛙、狗......, 结束于有“自我意识表现”的人工脑,或者说,结束于被机器人代替人类的那一天。
@ -9,7 +10,7 @@
从单细胞进化到多细胞、从青蛙进化到人类,这是一个漫长的、随机的进化过程,但在超级电脑上跑可能只要几天时间,就可能得到一个相当不错的脑模型。当然电脑速度越快、容量越大、环境模拟的越真实,则优胜夯汰后形成的脑结构就越复杂,错的脑模型都被自然淘汰掉了。从算法着手搭建,还是从模拟环境着手自动进化,这是创建人工生命的两个大方向,第一个方向有可能走到死胡同里,因为它不具备算法自改进、变异、遗传(算法的压缩)功能,当脑模型复杂到一定地步,可能会超出人脑能理解的范畴。模拟环境方式的难点则在于环境本身必须足够复杂、正确。而且必须循序渐进,与脑的进化同步,如果把一群青蛙扔到猴子的模拟环境中,则所有青蛙都会被自然淘汰掉,项目就无法进行下去了,另一个困难是电脑必须非常快,因为它是用串行方式模拟并行,不断试错前进的过程。 目前的项目只是搭建了一个框架语言为Java利用Swing作图环境构建一个虚拟环境、并模拟一群草履虫的优胜夯汰来获取一个具备自进化功能的人工生命体具体脑(即电脑生成的神经网络)的生成、进化算法还需要以后逐渐加入。欢迎有对神经网络感兴趣的同学加入这个实验项目,大家一起来玩,这个项目不需要多少数学知识,重在实践。
## 短期目标 | Sort-term Goals
目前它的第一个初步目标是:造出一个真正意义上的人工生命:草履虫。它必须具备以下前四个特点:
目前它的第一个初步目标是:造出一个真正意义上的人工生命:草履虫(备注:基本上已完成)。它必须具备以下前四个特点:
* 脑结构由电脑生成:神经网络由电脑算法生成,但是电脑算法仅限于模拟环境,而不是直接参与搭建神经网络,就好象大自然只负责拍死不合格的生命,它从不主动参与设计大脑。
* 脑结构可遗传类似于生物的DNA电脑生成的脑结构(神经网络),可通过简单的算法规则描述,并且此算法规则可以压缩成较短的片段存储,并参与到下一代草履虫的构建。
* 脑结构可变异:算法规则可以变异,下一代生成的草履虫在脑结构上与上一代总体相似,但存在部分变异。
@ -31,7 +32,7 @@ Frog: 这是人工生命的主体,目前起名叫青蛙(Frog),其实叫什
## 技术细节和构思
* 通过数组来模拟神经网络用串行的循环来模拟并行芯片运作方式。用Frog的能量多少来衡量是否将它淘汰还是允许它产生后代(下蛋)参与下一轮的测试,因为这个项目的目的是获取智能体,与一般的生命游戏还是有区别的,并不是适者生存就结束了,而是必须完成一系列程序员设定好的目标,一步步进化,直到表现出自我意识现象为止。脑模型的生成算法通过简单的神经元连接完成,原则上不允行出现任何形式的硬编码(除模式识别外)因为硬编码可能会破坏“随机变异”这一生命特性。为简单起见暂不考虑引入GPU图形芯片进行加速。
* 更多的杂七八拉的一些想法和构思放在“开发思路.md”、“一个人工脑模型.md”等文里。
* 更多的杂的一些想法和构思放在“开发思路.md”、“一个人工脑模型.md”等文里。
## 项目要实现的短期和长远目标
* 脑模型和虚拟环境的初步搭建 [脑模型刚开始搭建。虚拟环境已完成点击run.bat可以查看演示]
@ -66,12 +67,21 @@ Frog: 这是人工生命的主体,目前起名叫青蛙(Frog),其实叫什
![resut3](https://gitee.com/drinkjava2/frog/raw/master/result3.gif)
2019-06-26 找食效率太低又改回到4.12的用连接数量代替权值这个逻辑人为设计的算法居然比不过随机连接。Pain器官的加入没有提高找食效率必须与感光细胞合用才能知道是哪个边界急需引入记忆功能。
2019-06-28 为了让青蛙看到边界又加了个新的眼睛它是一个可自进化的nxn点阵的眼睛将来会取代只有四个象素点(但能看得远)的老眼睛。到目前为止,依然还没有进行模式识别和记忆功能开发。另外脑图可以动态显示了,用一个红圈标记出被动态跟踪显示的青蛙。
2019-07-28
有以下改动1.在Env区中间加了一个陷阱区Trap以增加趣味性自然选择的结果是青蛙会自动绕开陷阱区。2.增加一个Active器官它的作用是一直保持激活发现比Hungry器官驱动更能提高找食效率。3.增加一个Chance器官,它的作用是引入随机扰动,打破青蛙有时候围着一个食物打转就是吃不着的死循环。目前进食奖励信号没用到,白白浪费了。
另外Chance和Eye类里也再次运用了随机试错原理去确定关键参数效果还不错有兴趣的可以看一看源码。
![resut4](https://gitee.com/drinkjava2/frog/raw/master/result4.gif)
另外发现青蛙其实是有记忆能力的,因为连接本身就是一种记忆,只不过它没有复杂的模式识别能力,例如给个蛇的图片它就认不出来。以后的工作将以模式识别为重点(当然随机连接看起来很有用,以后还可能保留)基本原理是见note中提到的仿照波传播及全息存储原理在思维区逆向成像。而且脑可能改成三维结构并根据逆向成像原理要将所有输入输出器官全移到三维结构的同一侧(即思维区)。这将会是一个非常大的改动下面我简单画了一个3D示意图来说明我想象中的这个模式识别和记忆的原理至于对不对还需要实验来验证:
![3d-model](https://gitee.com/drinkjava2/frog/raw/master/3d-model.gif)
这个模型的最顶层表示眼睛的感光细胞(或任意输入输出细胞),同时也是思维区,红色表示一个长条的图形,兰色表示一个三角图形,如果这两个图形经常有规律地同时出现,就会把它们共有的节点撑大,见紫色的节点,当红色图形单独出现,就会强烈激活紫色节点,然后紫色节点的信号反向传播,就会激活三角图形,反之亦然。这就同时解释了模式识别和记忆(或者说回忆)功能的的原理。一个节点可以被多个感光细胞共享,所以它的存储能力是很强的。而且可能这个原理比较符合生物脑结构。当然,实际编程时,虚拟神经元不一定要排成正立方三角,而可能通过胡乱排放,大致上过得去就行了,也许能乱拳打死老师傅,最终要靠电脑自动随机的排放,然后用优胜劣汰来筛选。目前有个难点是这个记忆功能在思维区成像是如何有条不紊地大体上按串行进行工作的,这个问题先放一放。
## 版权 | License
[Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0)
## 期望 | Futures
欢迎发issue提出更好的意见或加入开发组尤其欢迎能接触到超级计算机的同学加入随着虚拟环境的复杂度和神经元数量增多对电脑速度要求会越来越高。
欢迎发issue提出建意或加入开发组尤其欢迎能接触到超级计算机的同学加入随着神经元数量增多对电脑的速度要求会越来越高很快将达到台式机性能瓶颈只能通过拖长运行时间来换取大样本数量了。
另外本项目正式宣布开启哭穷模式比提交一个pull request还能帮助这个项目开发的莫过于提交一个红包了您的赞助将实实在在地转化成我(或其它开发者)的项目开发时间,本项目将建立赞助者名单及收支明细账。
## 作者其它开源项目 | Other Projects
- [Java持久层工具 jSqlBox](https://gitee.com/drinkjava2/jSqlBox)
@ -81,4 +91,5 @@ Frog: 这是人工生命的主体,目前起名叫青蛙(Frog),其实叫什
## 关注我 | About Me
[Github](https://github.com/drinkjava2)
[码云](https://gitee.com/drinkjava2)
[码云](https://gitee.com/drinkjava2)
微信:yong99819981(如想长期关注本项目、交流信息,或想参与具体项目开发的,请留言加入"人工生命群",如果只是想临时私聊也可以加我好友后再删掉,我不介意)

View File

@ -10,8 +10,10 @@ import java.util.Random;
import javax.swing.JPanel;
import com.github.drinkjava2.frog.brain.group.RandomConnectGroup;
import com.github.drinkjava2.frog.egg.Egg;
import com.github.drinkjava2.frog.egg.EggTool;
import com.github.drinkjava2.frog.util.RandomUtils;
/**
* Env is the living space of frog. draw it on JPanel
@ -22,7 +24,7 @@ import com.github.drinkjava2.frog.egg.EggTool;
@SuppressWarnings("serial")
public class Env extends JPanel {
/** Speed of test */
public static int SHOW_SPEED = 5; // 测试速度-1000~1000,可调, 数值越小速度越慢
public static int SHOW_SPEED = 20; // 测试速度-1000~1000,可调, 数值越小速度越慢
/** Delete eggs at beginning of each run */
public static final boolean DELETE_EGGS = true;// 每次运行是否先删除保存的蛋
@ -40,7 +42,7 @@ public class Env extends JPanel {
public static final int ENV_HEIGHT = ENV_WIDTH; // 虚拟环境高度, 可调通常取正方形
/** Frog's brain display width on screen, not important */
public static final int FROG_BRAIN_DISP_WIDTH = 300; // Frog的脑图在屏幕上的显示大小,可调
public static final int FROG_BRAIN_DISP_WIDTH = 400; // Frog的脑图在屏幕上的显示大小,可调
/** Steps of one test round */
public static final int STEPS_PER_ROUND = 2000;// 每轮测试步数,可调
@ -58,6 +60,10 @@ public class Env extends JPanel {
private static final boolean[][] foods = new boolean[ENV_WIDTH][ENV_HEIGHT];// 食物数组定义
private static final int TRAP_WIDTH = 350; // 陷阱高, 0~200
private static final int TRAP_HEIGHT = 10; // 陷阱宽, 0~200
public List<Frog> frogs = new ArrayList<>();
public List<Egg> eggs;
@ -86,8 +92,17 @@ public class Env extends JPanel {
return !(x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT) && Env.foods[x][y];
}
public static boolean foundFoodOrOutEdge(int x, int y) {// 如果指定点看到食物或超出边界
return x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT || Env.foods[x][y];
public static boolean closeToEdge(Frog f) {// 青蛙靠近边界? 离死不远了
return f.x < 20 || f.y < 20 || f.x > (Env.ENV_WIDTH - 20) || f.y > (Env.ENV_HEIGHT - 20);
}
public static boolean inTrap(int x, int y) {// 如果指定点看到食物
return x >= ENV_WIDTH / 2 - TRAP_WIDTH / 2 && x <= ENV_WIDTH / 2 + TRAP_WIDTH / 2
&& y >= ENV_HEIGHT / 2 - TRAP_HEIGHT / 2 && y <= ENV_HEIGHT / 2 + TRAP_HEIGHT / 2;
}
public static boolean foundAnyThing(int x, int y) {// 如果指定点看到食物或超出边界
return x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT || Env.foods[x][y] || inTrap(x, y);
}
public static boolean foundAndDeleteFood(int x, int y) {// 如果x,y有食物将其清0返回true
@ -131,6 +146,14 @@ public class Env extends JPanel {
}
}
private void drawTrap(Graphics g) {// 所有走到陷阱边沿上的的青蛙都死掉
g.fillRect(ENV_HEIGHT / 2 - TRAP_WIDTH / 2, ENV_HEIGHT / 2 - TRAP_HEIGHT / 2, TRAP_WIDTH, TRAP_HEIGHT);
g.setColor(Color.white);
g.fillRect(ENV_HEIGHT / 2 - TRAP_WIDTH / 2 + 3, ENV_HEIGHT / 2 - TRAP_HEIGHT / 2 + 3, TRAP_WIDTH - 6,
TRAP_HEIGHT - 6);
g.setColor(Color.black);
}
static final NumberFormat format100 = NumberFormat.getPercentInstance();
static {
format100.setMaximumFractionDigits(2);
@ -154,10 +177,6 @@ public class Env extends JPanel {
}
}
public static boolean closeToEdge(Frog f) {// 青蛙靠近边界? 离死不远了
return f.x < 20 || f.y < 20 || f.x > (Env.WIDTH - 20) || f.y > (Env.HEIGHT - 20);
}
public void run() throws InterruptedException {
EggTool.loadEggs(this); // 从磁盘加载egg或新建一批egg
int round = 1;
@ -183,6 +202,13 @@ public class Env extends JPanel {
if (frog.active(this))
allDead = false;
for (Frog frog : frogs)
if (frog.alive && RandomUtils.percent(0.2f)) {// 有很小的机率在青蛙活着时就创建新的器官
RandomConnectGroup newConGrp = new RandomConnectGroup();
newConGrp.initFrog(frog);
frog.organs.add(newConGrp);
}
if (SHOW_SPEED > 0 && i % SHOW_SPEED != 0) // 画青蛙会拖慢速度
continue;
@ -197,13 +223,16 @@ public class Env extends JPanel {
frog.show(g);
if (firstFrog.alive) { // 开始显示第一个Frog的动态脑图
g.setColor(Color.red);
g.drawArc(firstFrog.x - 15, firstFrog.y - 15, 30, 30, 0, 360);
g.setColor(Color.BLACK);
if (Application.SHOW_FIRST_FROG_BRAIN) {
g.setColor(Color.red);
g.drawArc(firstFrog.x - 15, firstFrog.y - 15, 30, 30, 0, 360);
g.setColor(Color.BLACK);
}
if (DRAW_BRAIN_AFTER_STEPS > 0 && i % DRAW_BRAIN_AFTER_STEPS == 0)
Application.brainPic.drawBrainPicture(firstFrog);
}
drawTrap(g);
drawFood(g);
Graphics g2 = this.getGraphics();
g2.drawImage(buffImg, 0, 0, this);
@ -213,7 +242,7 @@ public class Env extends JPanel {
EggTool.layEggs(this);
t2 = System.currentTimeMillis();
Application.mainFrame.setTitle("Frog test round: " + round++ + ", 找食效率:" + foodFoundPercent()
+ ", time used: " + (t2 - t1) + " ms, first frog x=" + firstFrog.x + ", y=" + firstFrog.y);
+ ", time used: " + (t2 - t1) + " ms");
} while (true);
}
}

View File

@ -40,8 +40,9 @@ public class Frog {
public int x; // frog在Env中的x坐标
public int y; // frog在Env中的y坐标
public long energy = 1000000; // 青蛙的能量为0则死掉
public long energy = 100000; // 青蛙的能量为0则死掉
public boolean alive = true; // 设为false表示青蛙死掉了将不参与计算和显示以节省时间
public int ateFood = 0;
static Image frogImg;
static {
@ -62,19 +63,14 @@ public class Frog {
}
public boolean active(Env v) {
if (Env.outsideEnv(x, y))
alive = false;
energy -= 20;
if (!alive || energy < 0) {// 如果能量小于0则死
if (!alive || energy < 0 || Env.outsideEnv(x, y) || Env.inTrap(x, y)) {// 如果能量小于0则死
energy -= 100; // 死掉的青蛙也要消耗能量保证淘汰出局
alive = false;
return false;
}
for (Organ o : organs) { // 调用每个Organ的active方法
// energy -= o.organWasteEnergy; // 器官不是越多越好每增加一个器官要多消耗一点能量通过这个方法防止器官无限增多
energy -= 20;
for (Organ o : organs)
o.active(this);
}
return alive;
}

View File

@ -26,6 +26,11 @@ import com.github.drinkjava2.frog.Frog;
public class BrainPicture extends JPanel {
private float brainWidth; // real brain width
private int brainDispWidth; // screen display width
private Color color = Color.BLACK;
public void setColor(Color c) {
color = c;
}
public BrainPicture(int x, int y, float brainWidth, int brainDispWidth) {
super();
@ -35,7 +40,8 @@ public class BrainPicture extends JPanel {
this.setBounds(x, y, brainDispWidth + 1, brainDispWidth + 1);
}
public void drawZone(Graphics g, Zone z) {
public void drawZone( Zone z) {Graphics g = this.getGraphics();
g.setColor(color);
float rate = brainDispWidth / brainWidth;
int x = Math.round(z.x * rate);
int y = Math.round(z.y * rate);
@ -43,14 +49,16 @@ public class BrainPicture extends JPanel {
g.drawRect(x - radius, y - radius, radius * 2, radius * 2);
}
public void drawCircle(Graphics g, Zone z) {
public void drawCircle( Zone z) {Graphics g = this.getGraphics();
g.setColor(color);
float rate = brainDispWidth / brainWidth;
int x = Math.round(z.x * rate);
int y = Math.round(z.y * rate);
g.drawArc(x - 5, y - 5, 10, 10, 0, 360);
}
public void fillZone(Graphics g, Zone z) {
public void fillZone( Zone z) {Graphics g = this.getGraphics();
g.setColor(color);
float rate = brainDispWidth / brainWidth;
int x = Math.round(z.x * rate);
int y = Math.round(z.y * rate);
@ -58,7 +66,9 @@ public class BrainPicture extends JPanel {
g.fillRect(x - radius, y - radius, radius * 2, radius * 2);
}
public void drawLine(Graphics g, Zone z1, Zone z2) {
public void drawLine(Zone z1, Zone z2) {
Graphics g = this.getGraphics();
g.setColor(color);
float rate = brainDispWidth / brainWidth;
int x1 = Math.round(z1.x * rate);
int y1 = Math.round(z1.y * rate);
@ -67,7 +77,8 @@ public class BrainPicture extends JPanel {
g.drawLine(x1, y1, x2, y2);
}
public void drawText(Graphics g, Zone z, String text) {
public void drawText( Zone z, String text) {Graphics g = this.getGraphics();
g.setColor(color);
float rate = brainDispWidth / brainWidth;
int x = Math.round(z.x * rate);
int y = Math.round(z.y * rate);
@ -113,4 +124,5 @@ public class BrainPicture extends JPanel {
for (Organ organ : frog.organs)
organ.drawOnBrainPicture(frog, this); // each organ draw itself
}
}

View File

@ -11,8 +11,8 @@
package com.github.drinkjava2.frog.brain;
import java.awt.Color;
import java.awt.Graphics;
import com.github.drinkjava2.frog.Application;
import com.github.drinkjava2.frog.Frog;
/**
@ -27,7 +27,8 @@ public class Organ extends Zone {
private static final long serialVersionUID = 1L;
public String name; // 显示在脑图上的器官名称可选
public long fat = 0; // 如果活跃多fat值高则保留及变异的可能性大反之则很可能丢弃掉
//public float organWasteEnergy = 0.05f; // 器官在每个测试循环中需要消耗青蛙多少能量可以通过调节这个参数抑制器官数量无限增长
// public float organWasteEnergy = 0.05f; //
// 器官在每个测试循环中需要消耗青蛙多少能量可以通过调节这个参数抑制器官数量无限增长
public float organActiveEnergy = 1; // 输出器官激活需要消耗每个脑细胞多少能量
public float organOutputEnergy = 2; // 感觉器官激活会给每个脑细胞增加多少能量
public boolean initilized; // 通过这个标记判断是否需要手工给定它的参数初值
@ -64,11 +65,12 @@ public class Organ extends Zone {
/** Child class can override this method to drawing picture */
public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来子类可以重写这个方法
Graphics g = pic.getGraphics();// border
g.setColor(Color.BLACK); // 缺省是黑色
pic.drawZone(g, this);
if (!Application.SHOW_FIRST_FROG_BRAIN)
return;
pic.setColor(Color.BLACK); // 缺省是黑色
pic.drawZone(this);
if (this.name != null)
pic.drawText(g, this, String.valueOf(this.name));
pic.drawText(this, String.valueOf(this.name));
}
/** Only call once when frog created , Child class can override this method */

View File

@ -11,7 +11,6 @@
package com.github.drinkjava2.frog.brain.group;
import java.awt.Color;
import java.awt.Graphics;
import com.github.drinkjava2.frog.Env;
import com.github.drinkjava2.frog.Frog;
@ -49,7 +48,7 @@ public class RandomConnectGroup extends Group {
public void initFrog(Frog f) {
if (!initilized) {
initilized = true;
//organWasteEnergy=.05f;
// organWasteEnergy=.05f;
x = Env.FROG_BRAIN_WIDTH / 2;
y = Env.FROG_BRAIN_WIDTH / 2;
r = Env.FROG_BRAIN_WIDTH / 2;
@ -83,19 +82,18 @@ public class RandomConnectGroup extends Group {
}
@Override
public void drawOnBrainPicture(Frog f,BrainPicture pic) {// 把自已这个器官在脑图上显示出来
Graphics g = pic.getGraphics();// border
public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来
if (fat <= 0)
g.setColor(Color.LIGHT_GRAY); // 没用到? 灰色
pic.setColor(Color.LIGHT_GRAY); // 没用到? 灰色
else
g.setColor(Color.red); // 用到了?红色
pic.drawZone(g, this);
pic.drawLine(g, inputZone, outputZone);
pic.drawZone(g, inputZone);
pic.fillZone(g, outputZone);
pic.setColor(Color.red); // 用到了?红色
pic.drawLine(inputZone, outputZone);
pic.drawZone(this);
pic.drawZone(inputZone);
pic.fillZone(outputZone);
if (fat > 0) {
g.setColor(Color.red);
pic.drawCircle(g, outputZone); // 如果胖了表示激活过了下次下蛋少不了这一组
pic.setColor(Color.red);
pic.drawCircle(outputZone); // 如果胖了表示激活过了下次下蛋少不了这一组
}
}

View File

@ -0,0 +1,47 @@
/*
* Copyright 2018 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
* applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
package com.github.drinkjava2.frog.brain.organ;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.Cell;
import com.github.drinkjava2.frog.brain.Input;
import com.github.drinkjava2.frog.brain.Organ;
/**
* Active always keep active
*
* 这个器官永远激活
*/
public class Active extends Organ {//以前的实验发现添加一个始终激活的区比用Hungry来驱动更能提高找食效率
private static final long serialVersionUID = 1L;
@Override
public void initFrog(Frog f) {
if (!initilized) {
initilized = true;
organOutputEnergy = 2;
}
}
@Override
public void active(Frog f) {
for (Cell cell : f.cells) {
if (cell.energy > 0)
cell.energy--;
if (cell.energy < Cell.MAX_ENERGY_LIMIT)
for (Input input : cell.inputs)
if (input.nearby(this)) // if input zone near by happy zone
cell.energy += organOutputEnergy;
}
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright 2018 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
* applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
package com.github.drinkjava2.frog.brain.organ;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.Cell;
import com.github.drinkjava2.frog.brain.Input;
import com.github.drinkjava2.frog.brain.Organ;
import com.github.drinkjava2.frog.util.RandomUtils;
/**
* Chance is a random number generator
*
* 这个器官是一个随机数发生器用来打乱青蛙的思维防止它围着一个食物打转出不来
*/
public class Chance extends Organ { // 至于这个器官能不能被选中是另外一回事听天由命了
private static final long serialVersionUID = 1L;
public int percent; // 初始化的机率为5%
@Override
public void initFrog(Frog f) {
if (!initilized) {
initilized = true;
percent = 5;
}
}
@Override
public Organ[] vary() {
if (RandomUtils.percent(5)) {
percent = percent + 1 - 2 * RandomUtils.nextInt(2);
if (percent < 1)
percent = 1;
if (percent > 98)
percent = 98;
}
return new Organ[] { this };
}
@Override
public void active(Frog f) {
if (RandomUtils.percent(percent)) {// 如果靠近边界痛苦信号生成
for (Cell cell : f.cells) {
if (cell.energy > 0)
cell.energy--;
if (cell.energy < Cell.MAX_ENERGY_LIMIT)
for (Input input : cell.inputs)
if (input.nearby(this)) // if input zone nearby this zone
cell.energy += 30;
}
}
}
}

View File

@ -23,8 +23,9 @@ public class Eat extends Organ {// Eat这个类将食物转化为能量能量
@Override
public void active(Frog f) {
if (Env.foundAndDeleteFood(f.x, f.y)) {
f.ateFood++;
// 所有的硬编码都是bug包括这个1000
f.energy += 1000;// 如果青蛙的坐标与食物重合吃掉food能量境加
f.energy += 1000;// 如果青蛙的坐标与食物重合吃掉food能量境加
// 能量境加青蛙感觉不到但是Happy区激活青蛙能感觉到因为Happy区是一个脑器官

View File

@ -10,6 +10,7 @@
*/
package com.github.drinkjava2.frog.brain.organ;
import com.github.drinkjava2.frog.Application;
import com.github.drinkjava2.frog.Env;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.BrainPicture;
@ -17,27 +18,31 @@ import com.github.drinkjava2.frog.brain.Cell;
import com.github.drinkjava2.frog.brain.Input;
import com.github.drinkjava2.frog.brain.Organ;
import com.github.drinkjava2.frog.brain.Zone;
import com.github.drinkjava2.frog.util.RandomUtils;
/**
* Eye is an organ can see environment, and active brain cells which inputs are
* located in eye range
* Eye can only see 4 direction
*
* @author Yong Zhu
* @since 1.0
*/
public class Eye extends Organ {// Eye类需要重构目前只有4个感光细胞不够Eye要改成Group的子类Eye只负责感光细胞的排列感光细胞自已负责变异
public class Eye extends Organ {// 这个Eye是老版的眼睛只能看到四个方向但它的调节距离会自动随机调整到一个最佳值这就是随机试错算法的一个应用
private static final long serialVersionUID = 1L;
public int seeDistance; // 眼睛能看到的距离
@Override
public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次
if (!initilized) {
initilized = true;
organOutputEnergy = 30;
seeDistance = 8;
}
}
@Override
public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来
if (!Application.SHOW_FIRST_FROG_BRAIN)
return;
super.drawOnBrainPicture(f, pic);
float qRadius = r / 4;
float q3Radius = (float) (r * .75);
@ -45,14 +50,21 @@ public class Eye extends Organ {// Eye类需要重构目前只有4个感光
Zone seeDown = new Zone(x, y - q3Radius, qRadius);
Zone seeLeft = new Zone(x - q3Radius, y, qRadius);
Zone seeRight = new Zone(x + q3Radius, y, qRadius);
pic.drawZone(pic.getGraphics(), seeUp);
pic.drawZone(pic.getGraphics(), seeDown);
pic.drawZone(pic.getGraphics(), seeLeft);
pic.drawZone(pic.getGraphics(), seeRight);
pic.drawZone(seeUp);
pic.drawZone(seeDown);
pic.drawZone(seeLeft);
pic.drawZone(seeRight);
}
@Override
public Organ[] vary() {
if (RandomUtils.percent(5)) {
seeDistance = seeDistance + 1 - 2 * RandomUtils.nextInt(2);
if (seeDistance < 1)
seeDistance = 1;
if (seeDistance > 50)
seeDistance = 50;
}
return new Organ[] { this };
}
@ -72,29 +84,28 @@ public class Eye extends Organ {// Eye类需要重构目前只有4个感光
boolean foodAtLeft = false;
boolean foodAtRight = false;
int seeDist = 10;
for (int i = 1; i < seeDist; i++)
for (int i = 1; i < seeDistance; i++)
if (Env.foundFood(f.x, f.y + i)) {
seeFood = true;
foodAtUp = true;
break;
}
for (int i = 1; i < seeDist; i++)
for (int i = 1; i < seeDistance; i++)
if (Env.foundFood(f.x, f.y - i)) {
seeFood = true;
foodAtDown = true;
break;
}
for (int i = 1; i < seeDist; i++)
for (int i = 1; i < seeDistance; i++)
if (Env.foundFood(f.x - i, f.y)) {
seeFood = true;
foodAtLeft = true;
break;
}
for (int i = 1; i < seeDist; i++)
for (int i = 1; i < seeDistance; i++)
if (Env.foundFood(f.x + i, f.y)) {
seeFood = true;
foodAtRight = true;

View File

@ -10,7 +10,11 @@
*/
package com.github.drinkjava2.frog.brain.organ;
import java.awt.Color;
import com.github.drinkjava2.frog.Application;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.BrainPicture;
import com.github.drinkjava2.frog.brain.Cell;
import com.github.drinkjava2.frog.brain.Input;
import com.github.drinkjava2.frog.brain.Organ;
@ -22,6 +26,23 @@ public class Happy extends Organ { // Happy器官是进食后的产生的快感
private static final long serialVersionUID = 1L;
public float happy = 0; // happy初始值为0, 进食后将由eat器官增加happy值
@Override
public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来
if (!Application.SHOW_FIRST_FROG_BRAIN)
return;
if (happy > 0) {
pic.setColor(Color.red);
pic.fillZone(this);
} else {
pic.setColor(Color.white);
pic.fillZone(this);
pic.setColor(Color.BLACK);
pic.drawZone(this);
}
if (this.name != null)
pic.drawText(this, String.valueOf(this.name));
}
@Override
public void active(Frog f) {
if (happy > 0) {

View File

@ -10,7 +10,11 @@
*/
package com.github.drinkjava2.frog.brain.organ;
import java.awt.Color;
import com.github.drinkjava2.frog.Application;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.BrainPicture;
import com.github.drinkjava2.frog.brain.Cell;
import com.github.drinkjava2.frog.brain.Input;
import com.github.drinkjava2.frog.brain.Organ;
@ -25,11 +29,27 @@ public class Hungry extends Organ {
public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次缺省啥也不干通常用于Organ类的初始化
if (!initilized) {
initilized = true;
//organWasteEnergy = 20f;
// organWasteEnergy = 20f;
organOutputEnergy = 2;
}
}
@Override
public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来
if (!Application.SHOW_FIRST_FROG_BRAIN)
return;
if (f.energy < 10000) {
pic.fillZone(this);
} else {
pic.setColor(Color.white);
pic.fillZone(this);
pic.setColor(Color.BLACK);
pic.drawZone(this);
}
if (this.name != null)
pic.drawText(this, String.valueOf(this.name));
}
@Override
public Organ[] vary() {
// if (RandomUtils.percent(20)) // 有20机率权重变化

View File

@ -10,6 +10,7 @@
*/
package com.github.drinkjava2.frog.brain.organ;
import com.github.drinkjava2.frog.Application;
import com.github.drinkjava2.frog.Env;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.BrainPicture;
@ -26,9 +27,9 @@ import com.github.drinkjava2.frog.util.RandomUtils;
* @author Yong Zhu
* @since 1.0
*/
public class NewEye extends Organ {// 这个眼睛有nxn个感光细胞可以看到青蛙周围nxn网络内有没有食物
public class NewEye extends Organ {// 这个新版的眼睛有nxn个感光细胞可以看到青蛙周围nxn网络内有没有食物
private static final long serialVersionUID = 1L;
public int n = 3; // 眼睛有n x n个感光细胞缺省是3x3点阵,会随机自动变异(加1或减1最小是1)
public int n = 3; // 眼睛有n x n个感光细胞 用随机试错算法自动变异(加1或减1最小是3x3)
@Override
public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次缺省啥也不干通常用于Organ类的初始化
@ -40,6 +41,8 @@ public class NewEye extends Organ {// 这个眼睛有nxn个感光细胞可以
@Override
public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来
if (!Application.SHOW_FIRST_FROG_BRAIN)
return;
super.drawOnBrainPicture(f, pic);
float r2 = r / n; // r2是每个感光细胞的半径
float x0 = x - r;
@ -47,10 +50,10 @@ public class NewEye extends Organ {// 这个眼睛有nxn个感光细胞可以
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
Zone cell = new Zone(x0 + i * 2 * r2 + r2, y0 + j * 2 * r2 + r2, r2);
if (Env.foundFoodOrOutEdge(f.x - n / 2 + i, f.y - n / 2 + j))
pic.fillZone(pic.getGraphics(), cell);
if (Env.foundAnyThing(f.x - n / 2 + i, f.y - n / 2 + j))
pic.fillZone(cell);
else
pic.drawZone(pic.getGraphics(), cell);
pic.drawZone(cell);
}
}
}
@ -74,7 +77,7 @@ public class NewEye extends Organ {// 这个眼睛有nxn个感光细胞可以
float y0 = y - r; // x0,y0是眼睛的左上角
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (Env.foundFoodOrOutEdge(f.x - n / 2 + i, f.y - n / 2 + j)) {
if (Env.foundAnyThing(f.x - n / 2 + i, f.y - n / 2 + j)) {
Zone eyeCell = new Zone(x0 + i * 2 * r2 + r2, y0 + j * 2 * r2 + r2, r2);
for (Cell cell : f.cells)
for (Input input : cell.inputs)

View File

@ -10,14 +10,18 @@
*/
package com.github.drinkjava2.frog.brain.organ;
import java.awt.Color;
import com.github.drinkjava2.frog.Application;
import com.github.drinkjava2.frog.Env;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.BrainPicture;
import com.github.drinkjava2.frog.brain.Cell;
import com.github.drinkjava2.frog.brain.Input;
import com.github.drinkjava2.frog.brain.Organ;
/**
* Pain zone active after some bad thingg happen like close to edge, hurt...
* Pain zone active after some bad thing happen like close to edge, hurt...
*
* 痛是一种惩罚表示青蛙做错了什么但是又不至严重到判其死亡的地步
*/
@ -29,16 +33,25 @@ public class Pain extends Organ { // Pain器官目前激活的条件是离边境
public void initFrog(Frog f) {
if (!initilized) {
initilized = true;
organOutputEnergy = 2;
organOutputEnergy = 5;
}
}
// @Override
// public Organ[] vary() {
// if (RandomUtils.percent(20)) // 有20机率权重变化
// organOutputEnergy = RandomUtils.vary(organOutputEnergy);
// return new Organ[] { this };
// }
@Override
public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来
if (!Application.SHOW_FIRST_FROG_BRAIN)
return;
if (Env.closeToEdge(f)) {
pic.fillZone(this);
} else {
pic.setColor(Color.white);
pic.fillZone(this);
pic.setColor(Color.BLACK);
pic.drawZone(this);
}
if (this.name != null)
pic.drawText(this, String.valueOf(this.name));
}
@Override
public void active(Frog f) {
@ -48,7 +61,7 @@ public class Pain extends Organ { // Pain器官目前激活的条件是离边境
cell.energy--;
if (cell.energy < Cell.MAX_ENERGY_LIMIT)
for (Input input : cell.inputs)
if (input.nearby(this)) // if input zone near by happy zone
if (input.nearby(this)) // if input zone nearby this zone
cell.energy += organOutputEnergy;
}
}

View File

@ -1,14 +0,0 @@
/*
* Copyright 2018 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
* applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
package com.github.drinkjava2.frog.egg;
public class CellGroup {
}

View File

@ -17,7 +17,8 @@ import java.util.List;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.Organ;
import com.github.drinkjava2.frog.brain.group.Group;
import com.github.drinkjava2.frog.brain.group.RandomConnectGroup;
import com.github.drinkjava2.frog.brain.organ.Active;
import com.github.drinkjava2.frog.brain.organ.Chance;
import com.github.drinkjava2.frog.brain.organ.Eat;
import com.github.drinkjava2.frog.brain.organ.Eye;
import com.github.drinkjava2.frog.brain.organ.Happy;
@ -41,9 +42,9 @@ import com.github.drinkjava2.frog.util.RandomUtils;
* @since 1.0
*/
public class Egg implements Serializable {
// 为了缩短时间这个程序随机生成的联结将只落在固定的器官上而不是漫天撒网(见4.12提交)这是程序的优化实现的逻辑和随机漫天撒网定是相同的
// 但是这个优化带来的问题是这个硬编码逻辑不能拷贝到将来的分形结构里去而且下面这个 FIXED_ORGAN_QTY必须每次手工设定
public static int FIXED_ORGAN_QTY = 9;
// 为了缩短时间这个程序随机生成的联结将只落在固定的器官上而不是漫天撒网(见4.12提交)这是程序的优化实现的逻辑和随机漫天撒网定是相同的
// 但是这个优化带来的问题是这是一个硬编码逻辑不利于器官的优胜劣汰 而且下面这个 FIXED_ORGAN_QTY必须每次手工设定以后需要重构这块的代码
public static int FIXED_ORGAN_QTY = 11;
private static final long serialVersionUID = 1L;
@ -53,20 +54,21 @@ public class Egg implements Serializable {
public Egg() {// 无中生有创建一个蛋先有蛋后有蛙
organs.add(new Happy().setXYRN(600, 700, 60, "Happy")); // Happy必须第一个加入
organs.add(new Hungry().setXYRN(300, 100, 100, "Hungry"));
organs.add(new Hungry().setXYRN(300, 100, 60, "Hungry"));
organs.add(new MoveUp().setXYRN(800, 100, 60, "Up"));
organs.add(new MoveDown().setXYRN(800, 400, 60, "Down"));
organs.add(new MoveLeft().setXYRN(700, 250, 60, "Left"));
organs.add(new MoveRight().setXYRN(900, 250, 60, "Right"));
organs.add(new Eye().setXYRN(100, 300, 100, "Eye"));
organs.add(new NewEye().setXYRN(200, 700, 200, "NewEye"));
organs.add(new Pain().setXYRN(800, 700, 60, "Pain")); // 痛苦在靠近边界时触发
organs.add(new Pain().setXYRN(800, 700, 60, "Pain")); // 痛苦在靠近边界时触发
organs.add(new Active().setXYRN(500, 100, 60, "Active")); // 永远激活
organs.add(new Chance().setXYRN(650, 100, 60, "Chance")); // 永远激活
// Pain对提高找食效率没有帮助将来要和记忆功能一起加入,我们的目标不出界吃光所有食物
// 以上为11个, 就是FIXED_ORGAN_QTY值
organs.add(new Eat().setXYRN(0, 0, 0, "Eat")); // EAT不是感觉或输出器官没有位置和大小
addRandomConnectionGroups();
}
/** Create egg from frog */
@ -74,12 +76,6 @@ public class Egg implements Serializable {
for (Organ organ : frog.organs)
for (Organ newOrgan : organ.vary())
organs.add(newOrgan);
addRandomConnectionGroups();
}
private void addRandomConnectionGroups() {// 每次下蛋时新建5个RandomConnectGroup实例
for (int i = 0; i < 5; i++)
organs.add(new RandomConnectGroup());
}
/**

View File

@ -24,6 +24,8 @@ import com.github.drinkjava2.frog.Application;
import com.github.drinkjava2.frog.Env;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.Organ;
import com.github.drinkjava2.frog.brain.organ.Chance;
import com.github.drinkjava2.frog.brain.organ.Eye;
import com.github.drinkjava2.frog.util.FrogFileUtils;
/**
@ -53,14 +55,14 @@ public class EggTool {
+ org.organActiveEnergy + ", outputEnergy=" + org.organOutputEnergy);
}
System.out.print("First frog has " + first.organs.size() + " organs, energy=" + first.energy);
System.out.print(", Last frog has " + last.organs.size() + " organs, energy=" + last.energy);
System.out.println("1st frog has " + first.organs.size() + " organs, energy=" + first.energy + ", seeDist="
+ ((Eye) first.organs.get(6)).seeDistance + ", chance=" + ((Chance) first.organs.get(10)).percent);
System.out.println("Last frog has " + last.organs.size() + " organs, energy=" + last.energy);
try {
List<Egg> newEggs = new ArrayList<>();
for (int i = 0; i < Env.EGG_QTY; i++)
newEggs.add(new Egg(env.frogs.get(i)));
System.out.print(", organs =" + newEggs.get(0).organs.size() + ", ");
FileOutputStream fo = new FileOutputStream(Application.CLASSPATH + "eggs.ser");
ObjectOutputStream so = new ObjectOutputStream(fo);
@ -68,8 +70,8 @@ public class EggTool {
so.close();
env.eggs = newEggs;
System.out.println(
", Saved " + env.eggs.size() + " eggs to file '" + Application.CLASSPATH + "eggs.ser" + "'");
System.out
.println("Saved " + env.eggs.size() + " eggs to file '" + Application.CLASSPATH + "eggs.ser" + "'");
} catch (IOException e) {
System.out.println(e);
}
@ -88,6 +90,24 @@ public class EggTool {
});
}
// private static void sortFrogsOrderByEnergyDesc(Env env) {//
// 按吃到食物数量剩余能量多少给青蛙排序
// Collections.sort(env.frogs, new Comparator<Frog>() {
// public int compare(Frog a, Frog b) {
// if (a.ateFood > b.ateFood)
// return -1;
// else if (a.ateFood == b.ateFood) {
// // if (a.energy > b.energy)
// // return -1;
// // if (a.energy < b.energy)
// // return 1;
// return 0;
// } else
// return 1;
// }
// });
// }
public static void deleteEggs() {
System.out.println("Delete exist egg file: '" + Application.CLASSPATH + "eggs.ser'");
FrogFileUtils.deleteFile(Application.CLASSPATH + "eggs.ser");

View File

@ -1,14 +0,0 @@
/*
* Copyright 2018 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
* applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
package com.github.drinkjava2.frog.env;
public class CellGroup {
}

View File

@ -47,8 +47,8 @@ public class RandomUtils {
}
public static boolean percent(int percent) {
return rand.nextInt(100) < percent;
public static boolean percent(float percent) {
return rand.nextFloat() * 100 < percent;
}

BIN
result4.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 KiB

View File

@ -3,6 +3,7 @@
=======以下是杂七八拉的一些想法,想到什么就记下来==========
* 到达台式机性能瓶颈后如果找不到快的超级计算机只能通过存盘多个文件按文件分组人为地拉长测试时间来换取大样本数量也就是说同一个环境里的Frog数量可以很少这样对于单个测试来说速度可以接受也不会撑爆内存。当然了开发体验就差了。
* 判断Frog胜出可以不用能量而用吃了多少个食物来判断一个测试周期吃的多的胜出用能量多少是不公平的因为吃的多的有可能因为脑细胞或器官多消耗的能量也多最后剩下的能量反而不如那些不运动或死掉的Frog。
* 将来训练者和生物体可以对话表现形式为弹出一个24x24点阵图形每次只能弹出一种图形。训练者由人或电脑操纵生物体则可以任意自主行动和说话(输出任意图形),训练者和生物体具有相似权限的输出(开始阶段输出图形仅限于100个汉字和数字),行动仅限于说话、移动、打击、保存食物、拿出食物。
* 训练者在生物体模拟正确或行为(输出文字或图形,行走,吃,睡等)正确后,给予食物奖励。训练者在生物体说话或行为错误时,不给予奖励或给予打击惩罚。
@ -28,7 +29,215 @@
=======以下是码云上评论的备份,抄在下面,防止万一码云挂掉以前的评论丢失==========
drinkjava2owner3 days ago
看来JQ暂时是搞不完了。下面先清理一下这个项目有些垃圾类要删掉。网格形式的模式识别先不急先把奖励信号利用上目前奖励信号被白白浪费了。要改成每次吃到食物之后近期活跃过的所有神经元的fat值增加就好象训兽师每次在海豹完成一个动作后就给它条鱼吃一样吃完鱼之后海豹就会把刚才的动作记得更牢。另外相应地动态生成随机连接(目前是RandomConnectionGroup)也改成每隔几步step之后就动态生成一些而不是等青蛙死掉后再由它的后代去生成由后代生成新的随机联接虽然可以体现优胜劣汰但是太滞后了根本无法利用上宝贵的奖励信号。创造性思维就是将不相干的神经元联系起来在这里具体就是随机产生新的联接然后由食物奖励来强化(保留)。
Copy URL
5177524_longfer
LongFer3 days ago
我觉得项目很好,请问大佬怎么加群呢
Copy URL
920504_drinkjava2
drinkjava2owner3 days ago
如果想长期关注这个研发方向请加我微信yong99819981并留言人工生命群谢谢
Copy URL
someome
someome6 days ago
大神可以了解一下深度强化学习和OpenAI gym感觉模拟大脑神经元和生物进化的思路是一条歪路。生命的本质无非就是复制和变异实现是很简单的。最重要的是人类的意识和思维这也是人工智能这个学科的最终目的。深度强化学习是目前最有可能取得突破的方向领域大神可以关注一下这方面的信息。“意识从来就不存在意识只是一种现象”我不同意这个观点。我的观点是“意识是一种状态对过去和现在的记忆的自我感觉的一种状态”。其实几百年前笛卡尔就已经解决了意识是什么的问题。是的就是笛卡尔的哲学命题“我思故我在”。
Copy URL
920504_drinkjava2
drinkjava2owner6 days ago
模拟大脑的进化是一种手段,指望让电脑来自动生成复杂的脑结构,这个有投机成份,能不能成功有点靠运气,所以这个项目也不排除人为参与设计,允许吸收其它算法如深度强化学习(这个我是弱项,因为我是外行,等我有时间一定学习,或其它人也可以参与改进这个项目),编程者也需要较高的编程技巧,一条路走不通再试另一条。 至于是不是歪路并不重要,只要能逮着耗子就是好猫。
关于意识是什么的问题,这个项目的看法是认为讨论意识本质之类的话题是无意义的,纯属浪费时间,"杯子"、“自行车”、"意识"、"智能"、“勇气”这些都不是存在的实物,只是人类语言中对一类现象的归纳而已。这个项目只从程序能实现的功能来判断它是否足够"智能",足够有用,直到能够实现解决一些现实问题,例如模拟动物实现一些复杂的工作如模拟一只狗来实现垃圾分类,当然,如这个项目开头所说,"有用"只是暂时的,最终它的目标是要造出有自我意识表现的通用人工智能。
Copy URL
920504_drinkjava2
drinkjava2owner3 days ago
这个OpenAI项目我查了一下它的目标和这个项目的目标是完全一致的就是造出一个通用的人工智能。看来国外已经认识到单纯通过算法来解决开放性的复杂问题(如自动驾驶、翻译等),是一条走不通的路,最终人工智能的解决方案是"通用"智能,一个模型能解决所有问题,也就是说能造出最终智力表现超出人类的机器人。关于如何防止人工智能反制人类,相应地他们的看法就是“更多人拥有同样的能力来达到相互制衡”,这个观点也与我的观点有点接近,只不过没我这么明确彻底地倒向"投降派",人工智能研发不能被阻止,但可以通过人工智能立法保护人工智能人权、防止人类伤害机器人等方式防止人类被灭绝。
另外OpenAI最终实现途径和Frog在算法逻辑上可能是等同的都需要电脑来生成脑结构而不是人来搭建。不同的是Frog给出了具体的研发路线和考核目标每一步人工生命的进展都是可以考核评价的从低等生命的行为一直模拟到高等生命的行为表现就行了。
Copy URL
heychina
heychina14 days ago
伟大的目标,大佬,我想加入开发团队,贡献自己的一点力量.
Copy URL
920504_drinkjava2
drinkjava2owner13 days ago
谢谢你及最近好多同学的点赞,看来大家都对人工生命这个研发方向很感兴趣。但最近关注这个项目的请耐心等待一段时间,不光因为我最近没时间,而是因为这个项目架构方面会有极大调整(添加模式识别和记忆功能,见评论)这可能需要较长的编码时间我一般会在有青蛙的行为有明显改进时才提交到码云防止同学们down下来却看不出什么名堂一头雾水。当然了如果有同学自认为思路和编码能力较强的也可以试着加入模式识别和记忆功能争取能走在我的前面。目前的目标有两个1。青蛙不能出界 2。青蛙要吃光所有食物。第一个目标青蛙必须看到并识别出边界的存在第二个目标要求青蛙的眼睛能进化到看到屏幕上的任一点。
Copy URL
筑梦前行
筑梦前行16 days ago
目标远大,我辈学习之榜样!
Copy URL
小仔
小仔18 days ago
太棒了,持续关注大佬
Copy URL
drinkjava2owner24 days ago
这个项目消停两天这一两周要集中精力完成jSqlBox的分布式事务。
Copy URL
920504_drinkjava2
drinkjava2owner25 days ago
手机收到了如果大家只是想临时私聊的可以加我微信yong99819981聊完删掉好友即可。如果有想加入开发团队或长期关注这个项目的可以留言加入"人工生命群"。
Copy URL
妖孽
妖孽26 days ago
持续关注中
Copy URL
920504_drinkjava2
drinkjava2owner26 days ago
谢谢关注!但这个项目快不起来,一方面作者本人是个外行,另一方面它可能是走在了无人区(至少从这个外行的眼里看来),“外行”+“无人区”注定了它举步为艰,随时卡壳。 这个项目唯一的亮点可能就是作者本人坚信这条路能一直走到头的信心了。现在的神经网络研究要么信心不足,不觉得从模拟蚂蚁脑、青蛙脑可以一直走到模拟人脑。要么就是信心足过了头,连蚂蚁脑都没搞明白,就要上高大上的人脑模拟项目(欧洲人脑项目)。
Copy URL
920504_drinkjava2
drinkjava2owner28 days ago
随机联结只是演示了"会自主运动觅食“的微生物可以简单地通过随机进化中产生,但不能解释模式识别和记忆功能的产生。下面要开始另一种脑细胞分布模型的尝试了,可能要完全推翻目前随机联结这个架构,而且似乎更符合实际生物的脑结构,这就是网状结构:
打比方说目前如果一个眼睛有100个象素点分别对应A,B,C,D....等感光细胞,另外有上、下、左、右四个运动细胞。可以假设每个感光细胞收到光信号后,会象一个波源发生器一样向四周的脑细胞传递信号,越远的细胞收到的信号越弱,如果两个或多个感光细胞的信号同时到达远处的一个细胞,则形成波峰,如果多个波峰同时激活,这几个波峰从波的角度来说,可以看成是独立的信号源,于是又会在更远处形成波峰,于是不同形状的图形就会被大脑归类于一个个特点的波峰激活区,这就是模式识别的基本原理了。 一个波峰形成后会以反指数曲线形式消退,在此期间如果有个别波到达,会很容易再次激活,即使只是图像(或其它内、外信号)的局部信号,也可能使这个波峰激活到很高的值,这就是记忆的基本原理了。如果某个感觉细胞的输入转辗到达了运动细胞,可以说是一种天生的本能反射,如果这个本能反射链被加强或削弱,例如被脑内进食奖励区兴奋(多巴胺产生会加强最近的触突联接)、痛觉信号(可能产生强烈负信号),或是被脑内其它波峰的信号覆盖,那么这种后天形成的信号-运动反应,可以称为后天的条件反射。 对于电脑模拟来说,只需要构造一个模拟波形传播的网装结构即可,一个节点可以接受多个方向的波,也可以向多个方向发送波,这就要求它具备多个输入、输出触突(也可以是电脑虚拟触突),以及对应的奖惩调节机制即可,激活多的脑区,在下次遗传时把网格变异成更密一点就可以了,以体现用进废退。这就是下面要进行的工作的大概思路,这是一个整体化的解决方案。
Copy URL
920504_drinkjava2
drinkjava2owner27 days ago
与波的发散形成多个波峰相反,多个波峰激活会形成脑内的思维区成像(多个波峰激活会在原波源处成像,还有一种可能是在反侧镜像处成像)脑内的思维区就是人脑的CPU快速缓存区它永远不停地被周围的波干扰生成各种图像或声音等),思维区内容永不停止地在变幻,思维成像区驱动着其它脑区,反过来,其它脑区又在思维成像区形成新的图像,这就是大脑工作的流程,在做梦时这个流程更清晰,因为没有了外部信号输入,思维成像区永远不会是空白,所以大脑永远不会当机。
波峰的激活会在思维区成像,但是这个成像是模糊的,这就是为什么大脑中永远不能想象出一幅高清画面的根源(脑部变异者除外)。
现在的问题是,思维区是位于感光细胞区和大脑存贮细胞区之间的,还是之后? 换句话说,视觉光信号是先到达思维成像区神经元还是先到达波峰区神经元? 从波的成像象度来说,个人倾向于前者(因为镜像这个条件很难满足,它要求波峰位于同一个平面上),也就是说外部信号必须先经过思维成像区之后,再传递给波峰(大脑的存贮细胞)在回忆时波峰的信号必须原路逆向返回到思维成像区。这就需要与视觉、听觉信号相关的脑内神经元的信号必须是双向传播的。但我google了一下生物神经元只能单向传播信号如果是这样就只能通过两个相反方向的神经元来模拟一个双向传导功能这是个疑问。先把这个问题放下对于这个电脑模拟项目来说先考虑直接上双向因为目标是找食并不需要全盘照搬生物底层机制。
Copy URL
920504_drinkjava2
drinkjava2owner26 days ago
当然了这里的“波”只是个比喻实际编程时是不可能也没必要模拟波在360度所有角度上的传播的只能用n(可能少到1、2条)条放射线分布在一个小于180度的扇面上来近似代表波的传播路径甚至可以用"横5格竖2格"之类的网格比率来简化射线斜率的传播方向,两个射线的交点就是一个脑细胞存贮单元。而且可以用信号向右(水平方向的分量)传播表示波的扩张,向左表示波峰到原点的逆向信号传播。这适用于单维信号的输入和存贮,二维的(图像)输入还要再想想。
另外,神经元如果处在波的传播链中间,应该也具有波的叠加特性,即使一个神经元已被激活,当另一个信号到达时,它也应当具备将这个信号中继给下一级神经元的能力。 所以处于中点的神经元其饱和值很高(通过用进废退原则进化得来),处于信号末端的神经元饱和值低。
Copy URL
920504_drinkjava2
drinkjava2owner26 days ago
痛苦、愉悦感觉细胞本身也可以视作一个波源,简单说,可以视为图像的一个象素点,和视觉信号发生干涉,在大脑里形成波峰。于是每当看到特定的钉子、刀、针等图像时,这些波峰区被激活,信号再逆向传回到信号源后会激活痛苦成像区(或者说痛苦感受区)。 痛苦区激活可能会回忆到缩手区(缩手区是一个运动细胞,但同时也是一个波输出信号发生源),当这个过程持续足够长或这个回忆检索收集到的信号足够强,就有可能超过缩手区运动细胞的执行阀值,真的作出缩手运动。类似地,看到蛋糕图像会激活愉悦区,愉悦区可能会回忆到伸手区,当蛋糕足够大或在我面前晃动时间足够长时,蛋糕就被抢走了。蛋糕吃到嘴后,大脑会分泌多巴胺奖励所有最近活跃过的脑细胞,好让下次的抢蛋糕反射链发生得更流畅一点。
Copy URL
920504_drinkjava2
drinkjava2owner29 days ago
yeah满300赞了谢谢最后一位点赞的同学。
Copy URL
萧萧雨声
萧萧雨声29 days ago
非常有创意的项目代码中使用的随机数是普通的伪随机数如果有必要可以考虑真随机数这里有个网站可以获取真随机数https://www.random.org
Copy URL
Copy URL
920504_drinkjava2
drinkjava2owner29 days ago
谢谢提醒,不过神经网络应该不在乎伪随机数还是真随机数的,因为从它的需求来看,伪还是真随机数起到的作用是一样的,因为它不象密码一样需要防着人家去破解,只是需要一个均匀分布的随机概率而已。
Copy URL
920504_drinkjava2
drinkjava2owner30 days ago
加了个新的眼睛用nxn点阵形式代表脑图也可以动态显示了。蝼蚁尚且贪生青蛙到了边界就不走了往生咒加上了。
Copy URL
920504_drinkjava2
drinkjava2ownera month ago
找食效率太低,又改回到用连接数量代替权值这个逻辑,看起来舒服多了。权值这种人为设计的算法居然比不过随机试错,失败。
Copy URL
920504_drinkjava2
drinkjava2ownera month ago
猜测:大脑的结构可能是一个分形结构,在宏观上具备的记忆、信号输入和模式识别、条件反射等功能和结构,在微观上也具有相似的结构,也就是说只需要设计出一套脑细胞排布算法就可以了,每一个低层的脑结构就是高一层脑结构的分形式复制,在活跃度高的节点上,分形式遗传变异复制发生的概率高(用进废退),最终形成一个复杂的树状脑结构。这个猜测的意义在于如果能够完成基本的青蛙脑的设计,完成基本的找食、分辨天敌(需要增加感光细胞)等功能,更复杂的如人脑就不用再去单独设计了,利用计算机的虚拟环境训练就可以自动让这个青蛙脑进化成更复杂的人脑了。算法是一样的,只是脑的总细胞数量和分形层数不一样而已。在蛋(Egg)里,只保存着一套算法,和一棵分形树的每个节点。打个比方来说,用最好的条件和环境来训练一群狗、一群猴子、一群恐龙,最终几十万年后它们都会进化成和人一样聪明,因为这些动物的受精卵里保存的脑的进化方案是一样的。
另外现在这个版本的找食效率不如4.12的提交这可能是因为权值虽然可以简化模型但悬殊巨大的权值可能抑制了新连接的建立正在调试将4.12的逻辑照抄到RandomConnectionGroup中去增加细胞数量弱化权值自动调整范围。等到引入记忆器官和利用上 Happy器官的奖励信号之后再说。目前这个青蛙的任务很明确1.遇到边界要掉头,而不是出界或顺着边界往下溜 2.发现并吃光Env中的所有食物。 第一个任务必须引入记忆功能,第二个任务必须进化出感光细胞非常多的眼睛,因为如果测试环境中只有一个食物和一个青蛙时,如果青蛙感光细胞很少就会根本看不到这个食物而饿死。
Copy URL
920504_drinkjava2
drinkjava2ownera month ago
当然,如果食物太多,眼睛的感光细胞可能不会进化出很多,例如矿井里的有一种老鼠眼睛基本看不到,不是因为大自然觉得即然用不到眼睛,就让它退化吧,而是因为有了眼睛的老鼠需要消耗更多的食物,在生存竞争中被淘汰。所以环境决定了生物的形态,环境决定了脑的进化方向。
Copy URL
1320504_fzwise
码瘾少年a month ago
nice job这个想法我之前就想过随机才是王道再复杂的逻辑写出来的人工智能只是人思维的规律总结算不上智能
Copy URL
xinyi
xinyia month ago
求加微信xx17610115570
Copy URL
920504_drinkjava2
drinkjava2ownera month ago
报歉手机坏了,正在等网购的手机到,等拿到手再加你,顺便也会把微信号挂在"关注我"栏里面。这几天可以在这里发评论或私信,我每天都会登录码云看看的。
Copy URL
天崖
天崖a month ago
忍不住推荐一个视频https://www.bilibili.com/video/av54874176/。或者说是推荐这个up主。他的系列视频讲了一些神经网络和人工智能学习机制的科普我觉得讲得太棒了。而且里面关于“意识是客观现象”的观点与楼主不谋而合。
Copy URL
920504_drinkjava2
drinkjava2ownera month ago
受教了才知道草履虫的纤毛能感觉到外界输入up主的生物知识很渊博。我是根据任务来假设生物必须具备某种信号处理能力而生物学家可以直接从内因来解释生物为什么能实现这个任务。
Copy URL
drinkjava2ownera month ago
加了个“初学者入门介绍“方便Java零基础的人看源码。
Copy URL
Master_H
Master_Ha month ago
厉害
Copy URL
Jackchars
Jackcharsa month ago
看着就牛逼哄哄
Copy URL
妖孽
妖孽a month ago
大佬牛逼啊
Copy URL
920504_drinkjava2
drinkjava2ownera month ago
微信号(yong99819981),但正在换手机,请过两天再加。这两天只是想聊天的请发在这里或私信。
Copy URL
1489318_lnsooxd
LnsooXDa month ago
怎么加入你?
Copy URL
920504_drinkjava2
drinkjava2ownera month ago
开了个微信"人工生命群”可以在那聊。我没有QQ你也可以直接在这里评论或发issue、私信。
Copy URL
1727136_sunziren
sunzirena month ago
老弟你QQ多少我对你这个项目很感兴趣咱们应该有的聊的
Copy URL
jdkhome
jdkhomea month ago
带我一个
Copy URL
920504_drinkjava2
drinkjava2ownera month ago
开了个微信"人工生命群”可以在那聊。我没有QQ你也可以直接在这里评论或发issue、私信。
Copy URL
143517_vebai
/vebaia day ago

View File

@ -46,12 +46,14 @@
主要做了一些清理,将所有器官移到单独的类里删除OrganDesc类。将一些类(如Applicaton移到根包下)移到不同的包下。这个版本是比较大的一个重构,最大的进步是将算法当成一个器官引入,当然,这个版本只存在一个随机连接两端的算法,以后会扩充。
另外顺手加上了Happy和Pain两个器官分别对应进食愉快感和痛苦感后者在靠近边界时激发。观查它的表现果然不出所料痛苦感立即生效有一些Frog移动到边界后就不再前进而是顺着边界溜下去了不傻但是Happy器官没有生效这也很显然因为Happy属于进食反射链的一部分在没有记忆器官算法引入之前是没有途径使用上进食奖励信号的。
### 2019-06-13, Commit: Happy & Pain
主要做了一些清理,将所有器官移到单独的类里删除OrganDesc类。将一些类(如Applicaton移到根包下)移到不同的包下。这个版本是比较大的一个重构,最大的进步是将算法当成一个器官引入,当然,这个版本只存在一个随机连接两端的算法,以后会扩充。
另外顺手加上了Happy和Pain两个器官分别对应进食愉快感和痛苦感后者在靠近边界时激发。观查它的表现果然不出所料痛苦感立即生效有一些Frog移动到边界后就不再前进而是顺着边界溜下去了不傻但是Happy器官没有生效这也很显然因为Happy属于进食反射链的一部分在没有记忆器官算法引入之前是没有途径使用上进食奖励信号的。
### 2019-06-26, Commit: Back to many connections
找食效率太低又改回到4.12的用连接数量代替权值这个逻辑权值这种人为设计的算法居然比不过随机试错失败。先暂时去掉Pain器官Pain的加入并没有提高找食效率必须与感光细胞合用才能知道是哪个方向的边界下个版本急需引入记忆功能也就是说要将感光细胞的活跃和痛苦器官的活跃关联起来。
### 2019-06-28, Commit: New eye & dynamic show brain 为了更方便青蛙看到边界又加了个新的眼睛它是一个可自进化的nxn点阵的眼睛将来会取代只有四个象素点(但能看得远)的老眼睛。到目前为止,依然还没有进行模式识别和记忆功能的开发。另外脑图可以动态显示了,用一个红圈标记出被动态跟踪显示的青蛙。另外每次运行前打印往生咒,以示对生命的尊重。
### 2019-07-28, Commit: Trap & Active & Chance
这还是一个常规版本,建立在随机连接、优胜劣汰基础上。主要有以下改动:
1. 在Env区中间加了一个陷阱区Trap以增加趣味性青蛙如果走到陷阱区就死掉结果自然选择的结果是青蛙会绕开陷阱区。
2. 青蛙增加一个Active器官它的作用是一直保持激活如果有神经元触突位于这个区就会驱动神经元兴奋这个器官经实践证明比Hungry器官驱动更能提高找食效率。
3. 青蛙增加一个Chance器官,它的作用是引入随机扰动,打破青蛙有时候围着一个食物打转就是吃不着的死循环。
从当前这个版本可以看出,实际上青蛙是有一定的记忆能力的,连接就=记忆只不过没有模式识别能力以后的工作将以模式识别为重点基本原理是见note中提到的仿照全息存储原理在思维区逆向成像。因为逆向成像的限制以后的版本所有的器官会被移到脑图的同一侧不再是随意分布在脑图上了这将是一个比较明显的改动。当然随机连接这个算法看起来比较有用以后还是可能保留的。