Tim*_*gue 4 python genetic-algorithm
我正在尝试实施最初由Roger Alsing创建的程序.我对其他人的实施做了很多研究.我决定在python中编写我的程序,并使用基本三角形作为形状.当我运行程序时,它在多代之后并没有显示出改进(三角形往往会消失).我假设我的mutate函数有问题.谁能告诉我为什么它产生不太令人满意的结果呢?
我的代码:
import random
import copy
from PIL import Image, ImageDraw
optimal = Image.open("mona_lisa.png")
optimal = optimal.convert("RGBA")
size = width, height = optimal.size
num_shapes = 128
generations = 50000
def random_genome():
elements = []
for i in range(num_shapes):
x = (random.randint(0, width), random.randint(0, height))
y = (random.randint(0, width), random.randint(0, height))
z = (random.randint(0, width), random.randint(0, height))
r = random.randint(0, 255)
g = random.randint(0, 255)
b = random.randint(0, 255)
alpha = random.randint(10, 255)
elements.append([x, y, z, r, g, b, alpha])
return elements
def render_daughter(dna):
image = Image.new("RGBA", (width, height), "white")
draw = ImageDraw.Draw(image)
for item in dna:
x = item[0]
y = item[1]
z = item[2]
r = item[3]
g = item[4]
b = item[5]
alpha = item[6]
color = (r, g, b, alpha)
draw.polygon([x, y, z], fill = color)
return image
def mutate(dna):
dna_copy = copy.deepcopy(dna)
shape_index = random.randint(0, len(dna) - 1)
roulette = random.random() * 2
if roulette < 1:
if roulette < 0.25:
dna_copy[shape_index][3] = int(random.triangular(255, dna_copy[shape_index][3]))
elif roulette < 0.5:
dna_copy[shape_index][4] = int(random.triangular(255, dna_copy[shape_index][4]))
elif roulette < 0.75:
dna_copy[shape_index][5] = int(random.triangular(255, dna_copy[shape_index][5]))
elif roulette < 1.0:
dna_copy[shape_index][6] = int(0.00390625 * random.triangular(255, dna_copy[shape_index][6] * 255))
else:
if roulette < 1.25:
dna_copy[shape_index][0] = (int(random.triangular(width, dna_copy[shape_index][0][0])), int(random.triangular(height, dna_copy[shape_index][0][1])))
elif roulette < 1.5:
dna_copy[shape_index][2] = (int(random.triangular(width, dna_copy[shape_index][3][0])), int(random.triangular(height, dna_copy[shape_index][4][1])))
elif roulette < 1.75:
dna_copy[shape_index][3] = (int(random.triangular(width, dna_copy[shape_index][4][0])), int(random.triangular(height, dna_copy[shape_index][5][1])))
return dna_copy
def fitness(original, new):
fitness = 0
for x in range(0, width):
for y in range(0, height):
r1, g1, b1, a1 = original.getpixel((x, y))
r2, g2, b2, a2 = new.getpixel((x, y))
deltaRed = r1 - r2
deltaGreen = g1 - g2
deltaBlue = b1 - b2
deltaAlpha = a1 - a2
pixelFitness = deltaRed + deltaGreen + deltaBlue + deltaAlpha
fitness += pixelFitness
return fitness
def generate():
mother = random_genome()
best_genome = mother
best_fitness = fitness(optimal, render_daughter(best_genome))
for i in range(generations):
daughter = copy.deepcopy(best_genome)
daughter = mutate(daughter)
daughter_fitness = fitness(optimal, render_daughter(daughter))
if daughter_fitness < best_fitness:
best_genome = daughter
best_fitness = daughter_fitness
if i % 50 == 0:
print i
if i % 1000 == 0:
render_daughter(best_genome).save("iterations/output_" + str(i) + ".png")
if __name__ == "__main__":
generate()
Run Code Online (Sandbox Code Playgroud)
我正在使用的开始图像:

1000代后的输出图像:

5000代后的输出图像:

小智 6
您正在检查新适应度是否小于当前适应度:
if daughter_fitness < best_fitness:
Run Code Online (Sandbox Code Playgroud)
但是,你计算的适应度可能是负的:
deltaRed = r1 - r2
deltaGreen = g1 - g2
deltaBlue = b1 - b2
deltaAlpha = a1 - a2
pixelFitness = deltaRed + deltaGreen + deltaBlue + deltaAlpha
fitness += pixelFitness
Run Code Online (Sandbox Code Playgroud)
各种delta*变量可以是消极的或积极的; 您的测试将有利于负增量,增加了"最佳"图像(白度的较高值r2,g2等等,健身越低,越白的形象,直到他们都在255,255,255.我不知道知道增加alpha是增加还是降低透明度).
因此,您应该采取差异的绝对值:
deltaRed = abs(r1 - r2)
deltaGreen = abs(g1 - g2)
deltaBlue = abs(b1 - b2)
deltaAlpha = abs(a1 - a2)
Run Code Online (Sandbox Code Playgroud)
您还可以考虑平方和的平方或平方和的总和(基本上,它将其转换为最小二乘拟合例程):
deltaRed = r1 - r2
deltaGreen = g1 - g2
deltaBlue = b1 - b2
deltaAlpha = a1 - a2
pixelFitness = math.sqrt(deltaRed**2 + deltaGreen**2 + deltaBlue**2 + deltaAlpha**2)
fitness += pixelFitness
Run Code Online (Sandbox Code Playgroud)
最后,我注意到你的程序对我不起作用.它位于mutate()函数的后半部分,您可以在其中为x,y或z分配新值,但使用大于2的索引random_genome()表示您尝试访问颜色值,而不是整数,甚至尝试对这些值进行索引.
这会导致异常,所以我甚至不知道如何让这个程序运行.它或者从未在第一时间运行,或者您没有正确地复制粘贴.我改变了
if roulette < 1.25:
dna_copy[shape_index][0] = (int(random.triangular(
width, dna_copy[shape_index][0][0])), int(
random.triangular(height, dna_copy[shape_index][0][1])))
elif roulette < 1.5:
dna_copy[shape_index][1] = (int(random.triangular(
width, dna_copy[shape_index][1][0])), int(
random.triangular(height, dna_copy[shape_index][1][1])))
elif roulette < 1.75:
dna_copy[shape_index][2] = (int(random.triangular(
width, dna_copy[shape_index][2][0])), int(
random.triangular(height, dna_copy[shape_index][2][1])))
Run Code Online (Sandbox Code Playgroud)
这似乎做你想要的.
| 归档时间: |
|
| 查看次数: |
797 次 |
| 最近记录: |