- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我用遗传算法编写了一个快速实验。它只需要一个正方形网格,并尝试改变它们的颜色,使它们都变成黄色。它悲惨地失败了,我似乎无法弄清楚为什么。我提供了一个指向演示工作代码的 JSFiddle 的链接,以及一份完整的代码副本。
http://jsfiddle.net/mankyd/X6x9L/
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div class="container">
<h1>The randomly flashing squares <i>should</i> be turning yellow</h1>
<div class="row">
<canvas id="input_canvas" width="100" height="100"></canvas>
<canvas id="output_canvas" width="100" height="100"></canvas>
</div>
<div class="row">
<span id="generation"></span>
<span id="best_fitness"></span>
<span id="avg_fitness"></span>
</div>
</div>
</body>
</html>
请注意,下面的 javascript 在一些地方依赖于 jquery。
// A bit of code that draws several squares in a canvas
// and then attempts to use a genetic algorithm to slowly
// make those squares all yellow.
// Knobs that can be tweaked
var mutation_rate = 0.1; // how often should we mutate something
var crossover_rate = 0.6; // how often should we crossover two parents
var fitness_influence = 1; // affects the fitness's influence over mutation
var elitism = 1; // how many of the parent's generation to carry over
var num_offspring = 20; // how many spawn's per generation
var use_rank_selection = true; // false == roulette_selection
// Global variables for easy tracking
var children = []; // current generation
var best_spawn = null; // keeps track of our best so far
var best_fitness = null; // keeps track of our best so far
var generation = 0; // global generation counter
var clear_color = 'rgb(0,0,0)';
// used for output
var $gen_span = $('#generation');
var $best_fit = $('#best_fitness');
var $avg_fit = $('#avg_fitness');
var $input_canvas = $('#input_canvas');
var input_ctx = $input_canvas[0].getContext('2d');
var $output_canvas = $('#output_canvas');
var output_ctx = $output_canvas[0].getContext('2d');
// A spawn represents a genome - a collection of colored
// squares.
var Spawn = function(nodes) {
var _fitness = null; // a cache of our fitness
this.nodes = nodes; // the squares that make up our image
this.fitness = function() {
// fitness is simply a function of how close to yellow we are.
// This is defined through euclidian distance. Smaller fitnesses
// are better.
if (_fitness === null) {
_fitness = 0;
for (var i = 0; i < nodes.length; i++) {
_fitness += Math.pow(-nodes[i].color[0], 2) +
Math.pow(255 - nodes[i].color[1], 2) +
Math.pow(255 - nodes[i].color[2], 2);
}
_fitness /= 255*255*3*nodes.length; // divide by the worst possible distance
}
return _fitness;
};
this.mutate = function() {
// reset our cached fitness to unknown
_fitness = null;
var health = this.fitness() * fitness_influence;
var width = $output_canvas[0].width;
var height = $output_canvas[0].height;
for (var i = 0; i < nodes.length; i++) {
// Sometimes (most times) we don't mutate
if (Math.random() > mutation_rate) {
continue;
}
// Mutate the colors.
for (var j = 0; j < 3; j++) {
// colors can move by up to 32 in either direction
nodes[i].color[j] += 64 * (.5 - Math.random()) * health;
// make sure that our colors stay between 0 and 255
nodes[i].color[j] = Math.max(0, Math.min(255, nodes[i].color[j]));
}
}
};
this.draw = function(ctx) {
// This draw function is a little overly generic in that it supports
// arbitrary polygons.
ctx.save();
ctx.fillStyle = clear_color;
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
for (var i = 0; i < nodes.length; i++) {
ctx.fillStyle = 'rgba(' + Math.floor(nodes[i].color[0]) + ',' + Math.floor(nodes[i].color[1]) + ',' + Math.floor(nodes[i].color[2]) + ',' + nodes[i].color[3] + ')';
ctx.beginPath();
ctx.moveTo(nodes[i].points[0][0], nodes[i].points[0][1]);
for (var j = 1; j < nodes[i].points.length; j++) {
ctx.lineTo(nodes[i].points[j][0], nodes[i].points[j][1]);
}
ctx.fill();
ctx.closePath();
}
ctx.restore();
};
};
Spawn.from_parents = function(parents) {
// Given two parents, mix them together to get another spawn
var nodes = [];
for (var i = 0; i < parents[0].nodes.length; i++) {
if (Math.random() > 0.5) {
nodes.push($.extend({}, parents[0].nodes[i]));
}
else {
nodes.push($.extend({}, parents[1].nodes[i]));
}
}
var s = new Spawn(nodes);
s.mutate();
return s;
};
Spawn.random = function(width, height) {
// Return a complete random spawn.
var nodes = [];
for (var i = 0; i < width * height; i += 10) {
var n = {
color: [Math.random() * 256, Math.random() * 256, Math.random() * 256, 1],
points: [
[i % width, Math.floor(i / width) * 10],
[(i % width) + 10, Math.floor(i / width) * 10],
[(i % width) + 10, Math.floor(i / width + 1) * 10],
[i % width, Math.floor(i / width + 1) * 10],
]
};
nodes.push(n);
}
return new Spawn(nodes);
};
var select_parents = function(gene_pool) {
if (use_rank_selection) {
return rank_selection(gene_pool);
}
return roulette_selection(gene_pool);
};
var roulette_selection = function(gene_pool) {
var mother = null;
var father = null;
gene_pool = gene_pool.slice(0);
var sum_fitness = 0;
var i = 0;
for (i = 0; i < gene_pool.length; i++) {
sum_fitness += gene_pool[i].fitness();
}
var choose = Math.floor(Math.random() * sum_fitness);
for (i = 0; i < gene_pool.length; i++) {
if (choose <= gene_pool[i].fitness()) {
mother = gene_pool[i];
break;
}
choose -= gene_pool[i].fitness();
}
// now remove the mother and repeat for the father
sum_fitness -= mother.fitness();
gene_pool.splice(i, 1);
choose = Math.floor(Math.random() * sum_fitness);
for (i = 0; i < gene_pool.length; i++) {
if (choose <= gene_pool[i].fitness()) {
father = gene_pool[i];
break;
}
choose -= gene_pool[i].fitness();
}
return [mother, father];
};
var rank_selection = function(gene_pool) {
gene_pool = gene_pool.slice(0);
gene_pool.sort(function(a, b) {
return b.fitness() - a.fitness();
});
var choose_one = function() {
var sum_fitness = (gene_pool.length + 1) * (gene_pool.length / 2);
var choose = Math.floor(Math.random() * sum_fitness);
for (var i = 0; i < gene_pool.length; i++) {
// figure out the sume of the records up to this point. if we exceed
// our chosen spot, we've found our spawn.
if ((i + 1) * (i / 2) >= choose) {
return gene_pool.splice(i, 1)[0];
}
}
return gene_pool.pop(); // last element, if for some reason we get here
};
var mother = choose_one();
var father = choose_one();
return [mother, father];
};
var start = function() {
// Initialize our first generation
var width = $output_canvas[0].width;
var height = $output_canvas[0].height;
generation = 0;
children = [];
for (var j = 0; j < num_offspring; j++) {
children.push(Spawn.random(width, height));
}
// sort by fitness so that our best comes first
children.sort(function(a, b) {
return a.fitness() - b.fitness();
});
best_spawn = children[0];
best_fitness = best_spawn.fitness();
best_spawn.draw(output_ctx);
};
var generate = function(spawn_pool) {
// generate a new set of offspring
var offspring = [];
for (var i = 0; i < num_offspring; i++) {
var parents = select_parents(spawn_pool);
// odds of crossover decrease as we get closer
if (Math.random() * best_fitness < crossover_rate) {
var s = Spawn.from_parents(parents);
}
else {
// quick hack to copy our mother, with possible mutation
var s = Spawn.from_parents([parents[0], parents[0]]);
}
offspring.push(s);
}
// select a number of best from the parent pool (elitism)
for (var i = 0; i < elitism; i++) {
offspring.push(spawn_pool[i]);
}
// sort our offspring by fitness (this includes the parents from elitism). Fittest first.
offspring.sort(function(a, b) {
return a.fitness() - b.fitness();
});
// pick off the number that we want
offspring = offspring.slice(0, num_offspring);
best_spawn = offspring[0];
best_fitness = best_spawn.fitness();
best_spawn.draw(output_ctx);
generation++;
return offspring;
};
var average_fitness = function(generation) {
debugger;
var a = 0;
for (var i = 0; i < generation.length; i++) {
a += generation[i].fitness();
}
return a / generation.length;
};
//Draw yellow and then initialize our first generation
input_ctx.fillStyle = 'yellow';
input_ctx.fillRect(0, 0, input_ctx.canvas.width, input_ctx.canvas.height);
start();
// Our loop function. Use setTimeout to prevent things from freezing
var gen = function() {
children = generate(children);
$gen_span.text('Generation: ' + generation);
$best_fit.text('Best Fitness: ' + best_fitness);
$avg_fit.text('Avg. Fitness: ' + average_fitness(children));
if (generation % 100 === 0) {
console.log('Generation', generation);
console.log('Fitness', best_fitness);
}
setTimeout(gen, 1);
};
gen();
我已经对代码进行了注释,以尽量简化解析。基本思想非常简单:
输出永远不会接近黄色。它很快进入一种看起来很糟糕的稳定状态。我哪里出错了?
最佳答案
解决了。它在“from_parents”方法中:
if (Math.random() > 0.5) {
nodes.push($.extend({}, parents[0].nodes[i]));
}
else {
nodes.push($.extend({}, parents[1].nodes[i]));
}
$.extend()
正在执行浅拷贝。显而易见的解决方案是将 true
作为导致深度复制的第一个参数。然而,这在性能方面非常慢。更好的解决方案是从该代码块中完全删除 $.extend()
,而是将其移至 mutate()
方法,我在该方法中调用 $.extend()
仅当节点实际将被更改时。换句话说,它变成了写时复制。
此外,我在适应度函数中输入的颜色是错误的:P
关于genetic-algorithm - 为什么我的遗传算法很糟糕(为什么不收敛)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13887018/
有人有关于基因工程模拟的软件/教程的好来源吗?也许有关基因剪接/克隆模拟的开源软件? 谢谢 最佳答案 这可能正合你的胃口: Genetic Programming - Evolution of Mon
我在遗传算法中执行以下程序来选择锦标赛: choose k random individuals from population & select two best individuals among
如何选择符号回归的特征?我有 30 个特征,我只想使用最敏感的特征进行符号回归。 作为示例,可以使用与我的数据集类似的数据集。 https://scikit-learn.org/stable/modu
我希望有人能就这个话题对我有所了解。如果这被认为是一个愚蠢的问题,我很乐意立即删除这个问题。 我正在设计一个类(class)时间表系统,通过研究,我偶然发现了 GA 和约束编程作为解决我问题的方法。但
This question answers pseudocode for roulette wheel selection .但这是为了最大化问题。但我的问题是最小化适应度函数的值。也就是说,适应度低
我正在阅读一些有关遗传算法的论文,并且他们经常以非常相似的方式提及进化算法。根据维基百科,GA是EA的子集。但是,如果我们仔细观察,我们会发现它们都是基于自然选择(交叉,选择,变异)的元启发式优化算法
我想使用遗传算法基于扩展有限状态机(EFSM)生成测试序列。基于EFSM的测试面临着遗传算法在可行路径上的问题。我的覆盖标准是过渡覆盖。我有一个系统的 EFSM 模型,该模型具有输入参数并保护从一种状
我面临以下问题。 我有一个系统能够根据异常分数对某些操作进行排名。为了提高性能,我实现了一个遗传算法来执行特征选择,这样最异常的操作出现在第一个位置。我所做的并不是完全的特征选择,因为我没有使用二进制
我正在研究一个非常大规模的问题,我有一个启发式算法,除了表现非常好的遗传算法启发式算法之外,它还提供了一个相当好的解决方案。我想知道用启发式解决方案预先播种 GA 是否有任何 yield ,如果有的话
我对比赛选择的理解是: 对于给定的锦标赛规模t,从总体中随机选择t个人,并将该锦标赛的获胜者确定为具有最大适应度函数值的个人。 我的问题是: “二进制锦标赛选择”和“锦标赛选择”之间是否有区别,或者它
我目前正在写一篇关于遗传算法的论文。我想有一个关于终止条件的小部分,它决定了算法何时必须停止。 我发现了这个不错的网站: http://www.nd.com/genetic/termination.h
我正在实现一个稳态遗传算法来执行符号回归。 我的问题是关于变异和交叉算子之间的关系。 在应用变异和锦标赛选择以根据他们的错误选择 parent 之前,我总是咨询变异概率 (Pm)。 第一个问题: 突变
假设我有一个未知函数,我想通过遗传算法来近似它。对于这种情况,我假设它是 y = 2x。 我有一个由 5 个元素组成的 DNA,每个 x 一个 y,从 x = 0 到 x = 4,其中,经过大量试验和
我必须做一个关于遗传算法的学期项目,并且我有调整第一人称射击机器人的特征(即要使用的武器等)的想法。例如,我会以字符串的形式表示特征,前 10 位代表选择武器 1 的概率,接下来的 10 位代表选择武
我需要求解变量在很宽范围内变化的联立线性方程(5 个方程和 7 个未知数,即欠定问题)[0 - 1,00,000]。有人可以建议我应该使用什么健身功能吗? 最佳答案 我猜您指的是具有 7 个变量的 5
我正在用遗传算法在 81 个城市实现 TSPTW(带时间窗的旅行商),我应用了以下步骤: mutation prob=0.03 population size=100 -Generate random
我正在研究国际象棋引擎,并且正在使用基因表达编程方法来改进评估函数。 由于国际象棋没有神谕,我的适应度函数只能找到两个人的相对适应度(通过进行国际象棋比赛)。 因为我没有绝对的适应度测量,我可能会以循
我承担了使用遗传算法创建数独求解器的任务。 初始化 :将给定值存储在每个染色体中,然后随机生成值,使得每一行都是值 1 到 9 的有效排列。 健身 :由每行、列和方格中的“不合适”值的数量相加确定。
我阅读了有关此的各种内容并了解所涉及的原理和概念,但是,没有一篇论文提到如何计算涉及未直接连接的相邻城市(在染色体中)的染色体(代表一条路线)的适应度的细节通过一条边(在图中)。 例如,给定一条染色体
我是遗传算法的新手。我正在尝试预测规则出现的模式。例如,我有一组定义如下的规则。 规则 1,规则 2,规则 3,规则 4,规则 5,规则 6, 对于给定的日期,我只能使用规则 2、规则 3 和规则 6
我是一名优秀的程序员,十分优秀!