鱼C论坛

 找回密码
 立即注册
查看: 1084|回复: 10

[已解决]python简单遗传算法处理图片输出结果问题

[复制链接]
发表于 2023-5-21 20:55:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
import numpy as np
from PIL import Image
import random
import matplotlib as plt


# Step 1: 初始化种群
def init_population(pop_size, gene_size):
    population = []
    for i in range(pop_size):
        gene = np.random.randint(256, size=(gene_size, gene_size, 3))
        population.append(gene)
    return population


# Step 2: 计算适应度
def fitness(target, gene):
    diff = target - gene
    return 1 / (1 + np.sum(np.abs(diff)))


# Step 3: 交叉
def crossover(parent1, parent2):
    child1 = parent1.copy()
    child2 = parent2.copy()
    r1, r2 = np.random.randint(0, parent1.shape[0], 2)
    c1, c2 = np.random.randint(0, parent1.shape[1], 2)
    child1[r1:c1, r2:c2] = parent2[r1:c1, r2:c2]
    child2[r1:c1, r2:c2] = parent1[r1:c1, r2:c2]
    return child1, child2


# Step 4: 变异
def mutation(child, mutation_rate):
    for i in range(child.shape[0]):
        for j in range(child.shape[1]):
            for k in range(child.shape[2]):
                if random.random() < mutation_rate:
                    child[i, j, k] = np.random.randint(256)
    return child


# Step 5: 选择
def selection(population, target, mutation_rate, elite_size):
    pop_size = len(population)
    # Step 5.1: 计算适应度
    fitness_scores = [fitness(target, gene) for gene in population]
    # Step 5.2: 选择精英个体
    elite = []
    elite_indices = np.argsort(fitness_scores)[-elite_size:]
    for i in elite_indices:
        elite.append(population[i])
    # Step 5.3: 选择杂交个体
    parents = []
    for i in range(pop_size - elite_size):
        parent1 = population[np.random.randint(pop_size)]
        parent2 = population[np.random.randint(pop_size)]
        child1, child2 = crossover(parent1, parent2)
        child1 = mutation(child1, mutation_rate)
        child2 = mutation(child2, mutation_rate)
        parents.append(child1)
        parents.append(child2)
    # Step 5.4: 合并精英和杂交个体
    next_population = elite + parents
    return next_population


# Step 6: 主函数
def main(target_path, pop_size, gene_size, elite_size, mutation_rate, epochs):
    # Step 6.1: 读取目标图像
    target = np.asarray(Image.open(target_path))
    # Step 6.2: 初始化种群
    population = init_population(pop_size, gene_size)
    for epoch in range(epochs):
        # Step 6.3: 进行选择
        population = selection(population, target, mutation_rate, elite_size)
        # Step 6.4: 打印当前的最佳适应度
        fitness_scores = [fitness(target, gene) for gene in population]
        best_fitness = np.max(fitness_scores)
        print("Epoch: %d, Best Fitness: %f" % (epoch, best_fitness))
        # Step 6.5: 保存当前最佳个体
        best_index = np.argmax(fitness_scores)
        best_gene = population[best_index]
        best_image = Image.fromarray(best_gene.astype(np.uint8))
        best_image.save("best_image_%d.png" % epoch)
    # Step 6.6: 保存最终结果
    best_index = np.argmax(fitness_scores)
    best_gene = population[best_index]
    best_image = Image.fromarray(best_gene.astype(np.uint8))
    best_image.save("final_image.png")
    best_image.show()
    plt.show()


target_path = input("请输入一个图片文件路径(去""):")
pop_size = input("请输入种群大小:")
gene_size = input("请输入个体宽高:")
elite_size = input("请输入保留精英个体数量,10%pop:")
mutation_rate = input("请输入变异率:")
epochs = input("请输入迭代次数(不能设定太小):")

这个是一个遗传算法用于处理图像,当我已经对一张1280*1024像素的图片设定了参数,请输入种群大小:1000,请输入个体宽高:1310720,请输入保留精英个体数量,10%pop:150,请输入变异率:0.15,请输入迭代次数(不能设定太小):400,为什么只显示进程已结束,退出代码,并没有保存图片;后来有在末尾加了plt.show(),还是没有显示或者保存图片。这是什么原因呢?是参数问题吗
最佳答案
2023-5-21 22:42:23
本帖最后由 BrownSugar 于 2023-5-22 21:01 编辑

一个是你的代码没有调用遗传算法主函数main,其次input的结果是字符串,传入main前需要转成int、float,做好这两步后还会有个问题,gene_size的位置是二维图像尺寸,但是直接输入1310720应该是不行的,我对init_population函数进行了修改,现在输入gene_size时候输入图像尺寸,如果你的图像尺寸是1280X1024,就输入1280,1024,然后就可以运行了,至于plt,由于你的代码,仅用了一个plt.show(),所以不会显示任何plt图像,如果不打算用plt,可以直接去掉,改后的代码:
import numpy as np
from PIL import Image
import random


# Step 1: 初始化种群
def init_population(pop_size, gene_size):
    population = []
    gene_size = [int(i) for i in gene_size.split(",")]
    for i in range(pop_size):
        gene = np.random.randint(256, size=(gene_size[1], gene_size[0], 3))
        population.append(gene)
    return population


# Step 2: 计算适应度
def fitness(target, gene):
    diff = target - gene
    return 1 / (1 + np.sum(np.abs(diff)))


# Step 3: 交叉
def crossover(parent1, parent2):
    child1 = parent1.copy()
    child2 = parent2.copy()
    r1, r2 = np.random.randint(0, parent1.shape[0], 2)
    c1, c2 = np.random.randint(0, parent1.shape[1], 2)
    child1[r1:c1, r2:c2] = parent2[r1:c1, r2:c2]
    child2[r1:c1, r2:c2] = parent1[r1:c1, r2:c2]
    return child1, child2


# Step 4: 变异
def mutation(child, mutation_rate):
    for i in range(child.shape[0]):
        for j in range(child.shape[1]):
            for k in range(child.shape[2]):
                if random.random() < mutation_rate:
                    child[i, j, k] = np.random.randint(256)
    return child


# Step 5: 选择
def selection(population, target, mutation_rate, elite_size):
    pop_size = len(population)
    # Step 5.1: 计算适应度
    fitness_scores = [fitness(target, gene) for gene in population]
    # Step 5.2: 选择精英个体
    elite = []
    elite_indices = np.argsort(fitness_scores)[-elite_size:]
    for i in elite_indices:
        elite.append(population[i])
    # Step 5.3: 选择杂交个体
    parents = []
    for i in range(pop_size - elite_size):
        parent1 = population[np.random.randint(pop_size)]
        parent2 = population[np.random.randint(pop_size)]
        child1, child2 = crossover(parent1, parent2)
        child1 = mutation(child1, mutation_rate)
        child2 = mutation(child2, mutation_rate)
        parents.append(child1)
        parents.append(child2)
    # Step 5.4: 合并精英和杂交个体
    next_population = elite + parents
    return next_population


# Step 6: 主函数
def main(target_path, pop_size, gene_size, elite_size, mutation_rate, epochs):
    # Step 6.1: 读取目标图像
    target = np.asarray(Image.open(target_path))
    # Step 6.2: 初始化种群
    population = init_population(pop_size, gene_size)
    for epoch in range(epochs):
        # Step 6.3: 进行选择
        population = selection(population, target, mutation_rate, elite_size)
        # Step 6.4: 打印当前的最佳适应度
        fitness_scores = [fitness(target, gene) for gene in population]
        best_fitness = np.max(fitness_scores)
        print("Epoch: %d, Best Fitness: %f" % (epoch, best_fitness))
        # Step 6.5: 保存当前最佳个体
        best_index = np.argmax(fitness_scores)
        best_gene = population[best_index]
        best_image = Image.fromarray(best_gene.astype(np.uint8))
        best_image.save("best_image_%d.png" % epoch)
    # Step 6.6: 保存最终结果
    best_index = np.argmax(fitness_scores)
    best_gene = population[best_index]
    best_image = Image.fromarray(best_gene.astype(np.uint8))
    best_image.save("final_image.png")
    best_image.show()


target_path = input("请输入一个图片文件路径(去""):")
pop_size = int(input("请输入种群大小:"))
gene_size = input("请输入个体宽高:")
elite_size = int(input("请输入保留精英个体数量,10%pop:"))
mutation_rate = float(input("请输入变异率:"))
epochs = int(input("请输入迭代次数(不能设定太小):"))
main(target_path,pop_size,gene_size,elite_size,mutation_rate,epochs)

你的代码在我的电脑运算有点慢,基本跑不动,所以我没用太大的图像和参数
以下是我的输入:
请输入一个图片文件路径(去):china.jpg
请输入种群大小:100
请输入个体宽高:128,102
请输入保留精英个体数量,10%pop:150
请输入变异率:0.15
请输入迭代次数(不能设定太小):1
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-5-21 21:17:03 | 显示全部楼层
可能是Matplotlib库的导入有问题。在代码中,把import matplotlib as plt改为import matplotlib.pyplot as plt应该就可以了。如果还是没有显示或者保存图片,可以尝试把best_image.show()这行注释掉,只留下plt.show()。另外,因为输入函数获取的是字符串类型的值,需要将其转换为对应的数据类型。例如,需要将pop_size、gene_size等转换为int类型,mutation_rate转换为float类型,epochs转换为int类型。修改后的代码如下:
import numpy as np
from PIL import Image
import random
import matplotlib.pyplot as plt


# Step 1: 初始化种群
def init_population(pop_size, gene_size):
    population = []
    for i in range(pop_size):
        gene = np.random.randint(256, size=(gene_size, gene_size, 3))
        population.append(gene)
    return population


# Step 2: 计算适应度
def fitness(target, gene):
    diff = target - gene
    return 1 / (1 + np.sum(np.abs(diff)))


# Step 3: 交叉
def crossover(parent1, parent2):
    child1 = parent1.copy()
    child2 = parent2.copy()
    r1, r2 = np.random.randint(0, parent1.shape[0], 2)
    c1, c2 = np.random.randint(0, parent1.shape[1], 2)
    child1[r1:c1, r2:c2] = parent2[r1:c1, r2:c2]
    child2[r1:c1, r2:c2] = parent1[r1:c1, r2:c2]
    return child1, child2


# Step 4: 变异
def mutation(child, mutation_rate):
    for i in range(child.shape[0]):
        for j in range(child.shape[1]):
            for k in range(child.shape[2]):
                if random.random() < mutation_rate:
                    child[i, j, k] = np.random.randint(256)
    return child


# Step 5: 选择
def selection(population, target, mutation_rate, elite_size):
    pop_size = len(population)
    # Step 5.1: 计算适应度
    fitness_scores = [fitness(target, gene) for gene in population]
    # Step 5.2: 选择精英个体
    elite = []
    elite_indices = np.argsort(fitness_scores)[-elite_size:]
    for i in elite_indices:
        elite.append(population[i])
    # Step 5.3: 选择杂交个体
    parents = []
    for i in range(pop_size - elite_size):
        parent1 = population[np.randomparent1 = population[np.random.randint(0, pop_size)]
        parent2 = population[np.random.randint(0, pop_size)]
        child1, child2 = crossover(parent1, parent2)
        child1 = mutation(child1, mutation_rate)
        child2 = mutation(child2, mutation_rate)
        parents.append(child1)
        parents.append(child2)
    # Step 5.4: 合并精英和杂交个体
    new_population = elite + parents
    return new_population
# Step 6: 主函数
def main(target_path, pop_size, gene_size, elite_size, mutation_rate, epochs):
    # Step 6.1: 读取目标图像
    target = np.asarray(Image.open(target_path))
    # Step 6.2: 初始化种群
    population = init_population(pop_size, gene_size)
    for epoch in range(epochs):
        # Step 6.3: 进行选择
        population = selection(population, target, mutation_rate, elite_size)
        # Step 6.4: 打印当前的最佳适应度
        fitness_scores = [fitness(target, gene) for gene in population]
        best_fitness = np.max(fitness_scores)
        print("Epoch: %d, Best Fitness: %f" % (epoch, best_fitness))
        # Step 6.5: 保存当前最佳个体
        best_index = np.argmax(fitness_scores)
        best_gene = population[best_index]
        best_image = Image.fromarray(best_gene.astype(np.uint8))
        best_image.save("best_image_%d.png" % epoch)
    # Step 6.6: 保存最终结果
    best_index = np.argmax(fitness_scores)
    best_gene = population[best_index]
    best_image = Image.fromarray(best_gene.astype(np.uint8))
    best_image.save("final_image.png")
    best_image.show()
    plt.show()


target_path = input("请输入一个图片文件路径(去""):")
pop_size = input("请输入种群大小:")
gene_size = input("请输入个体宽高:")
elite_size = input("请输入保留精英个体数量,10%pop:")
mutation_rate = input("请输入变异率:")
epochs = input("请输入迭代次数(不能设定太小):")
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-21 21:34:57 | 显示全部楼层
在查看这个代码时,有几个可能的问题需要注意:

1. 内存问题:当你使用的种群大小为1000,每个个体的大小为1310720(这是一个非常大的尺寸,比一般图像的像素多得多),会消耗大量的内存。如果你的计算机内存不足,这可能会导致程序无法正常运行。

2. 超出目标图像的大小:你的个体宽高设置的非常大,远超过目标图片的大小,这可能导致在计算适应度时出现问题。因为你的目标图像和个体的尺寸不匹配,因此当你试图计算两者的差异时,可能会出现错误。

3. 程序运行时间过长:遗传算法需要很长的时间来收敛,尤其是在处理大量数据(例如,大型图片)时。所以,如果你没有看到任何输出,可能是因为程序仍在运行,尚未完成。

4. 图像保存问题:在你的程序中,你试图保存每个世代中最优的基因作为图像。然而,如果这些图像没有正确保存,可能是因为你的工作目录没有写入权限,或者你的磁盘空间不足。

5. 图像显示问题:你在程序的最后加入了plt.show(),但实际上并没有在前面绘制任何matplotlib图形,所以这个调用是不会有任何效果的。如果你想在程序中直接显示图片,应该使用PIL的show()方法,就像你在保存最终图像后所做的那样。

针对以上的问题,你可以尝试以下的解决办法:

· 减小种群大小和个体尺寸,以适应你的计算机的内存限制。

· 确保个体的尺寸和目标图像的尺寸匹配,这样才能正确地计算适应度。

· 给程序一些时间来完成运行,或者添加一些打印语句,以便你能够看到它的进度。

· 检查你的工作目录的权限,确保你有权限写入文件。同时,确保你的磁盘有足够的空间来保存所有生成的图像。

· 如果你想在程序运行过程中看到图像,可以在每个世代保存图像后,使用best_image.show()来显示图像。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-21 22:42:23 | 显示全部楼层    本楼为最佳答案   
本帖最后由 BrownSugar 于 2023-5-22 21:01 编辑

一个是你的代码没有调用遗传算法主函数main,其次input的结果是字符串,传入main前需要转成int、float,做好这两步后还会有个问题,gene_size的位置是二维图像尺寸,但是直接输入1310720应该是不行的,我对init_population函数进行了修改,现在输入gene_size时候输入图像尺寸,如果你的图像尺寸是1280X1024,就输入1280,1024,然后就可以运行了,至于plt,由于你的代码,仅用了一个plt.show(),所以不会显示任何plt图像,如果不打算用plt,可以直接去掉,改后的代码:
import numpy as np
from PIL import Image
import random


# Step 1: 初始化种群
def init_population(pop_size, gene_size):
    population = []
    gene_size = [int(i) for i in gene_size.split(",")]
    for i in range(pop_size):
        gene = np.random.randint(256, size=(gene_size[1], gene_size[0], 3))
        population.append(gene)
    return population


# Step 2: 计算适应度
def fitness(target, gene):
    diff = target - gene
    return 1 / (1 + np.sum(np.abs(diff)))


# Step 3: 交叉
def crossover(parent1, parent2):
    child1 = parent1.copy()
    child2 = parent2.copy()
    r1, r2 = np.random.randint(0, parent1.shape[0], 2)
    c1, c2 = np.random.randint(0, parent1.shape[1], 2)
    child1[r1:c1, r2:c2] = parent2[r1:c1, r2:c2]
    child2[r1:c1, r2:c2] = parent1[r1:c1, r2:c2]
    return child1, child2


# Step 4: 变异
def mutation(child, mutation_rate):
    for i in range(child.shape[0]):
        for j in range(child.shape[1]):
            for k in range(child.shape[2]):
                if random.random() < mutation_rate:
                    child[i, j, k] = np.random.randint(256)
    return child


# Step 5: 选择
def selection(population, target, mutation_rate, elite_size):
    pop_size = len(population)
    # Step 5.1: 计算适应度
    fitness_scores = [fitness(target, gene) for gene in population]
    # Step 5.2: 选择精英个体
    elite = []
    elite_indices = np.argsort(fitness_scores)[-elite_size:]
    for i in elite_indices:
        elite.append(population[i])
    # Step 5.3: 选择杂交个体
    parents = []
    for i in range(pop_size - elite_size):
        parent1 = population[np.random.randint(pop_size)]
        parent2 = population[np.random.randint(pop_size)]
        child1, child2 = crossover(parent1, parent2)
        child1 = mutation(child1, mutation_rate)
        child2 = mutation(child2, mutation_rate)
        parents.append(child1)
        parents.append(child2)
    # Step 5.4: 合并精英和杂交个体
    next_population = elite + parents
    return next_population


# Step 6: 主函数
def main(target_path, pop_size, gene_size, elite_size, mutation_rate, epochs):
    # Step 6.1: 读取目标图像
    target = np.asarray(Image.open(target_path))
    # Step 6.2: 初始化种群
    population = init_population(pop_size, gene_size)
    for epoch in range(epochs):
        # Step 6.3: 进行选择
        population = selection(population, target, mutation_rate, elite_size)
        # Step 6.4: 打印当前的最佳适应度
        fitness_scores = [fitness(target, gene) for gene in population]
        best_fitness = np.max(fitness_scores)
        print("Epoch: %d, Best Fitness: %f" % (epoch, best_fitness))
        # Step 6.5: 保存当前最佳个体
        best_index = np.argmax(fitness_scores)
        best_gene = population[best_index]
        best_image = Image.fromarray(best_gene.astype(np.uint8))
        best_image.save("best_image_%d.png" % epoch)
    # Step 6.6: 保存最终结果
    best_index = np.argmax(fitness_scores)
    best_gene = population[best_index]
    best_image = Image.fromarray(best_gene.astype(np.uint8))
    best_image.save("final_image.png")
    best_image.show()


target_path = input("请输入一个图片文件路径(去""):")
pop_size = int(input("请输入种群大小:"))
gene_size = input("请输入个体宽高:")
elite_size = int(input("请输入保留精英个体数量,10%pop:"))
mutation_rate = float(input("请输入变异率:"))
epochs = int(input("请输入迭代次数(不能设定太小):"))
main(target_path,pop_size,gene_size,elite_size,mutation_rate,epochs)

你的代码在我的电脑运算有点慢,基本跑不动,所以我没用太大的图像和参数
以下是我的输入:
请输入一个图片文件路径(去):china.jpg
请输入种群大小:100
请输入个体宽高:128,102
请输入保留精英个体数量,10%pop:150
请输入变异率:0.15
请输入迭代次数(不能设定太小):1
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-5-22 19:47:10 | 显示全部楼层
本帖最后由 1119625819 于 2023-5-22 19:51 编辑
isdkz 发表于 2023-5-21 21:34
在查看这个代码时,有几个可能的问题需要注意:

1. 内存问题:当你使用的种群大小为1000,每个个体的大 ...


刚刚意识到问题了,但是您说的图像保存问题,解决方法可以详细解释一下吗,就是如何修改权限,可能以后会遇到这个问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-22 20:07:04 | 显示全部楼层
1119625819 发表于 2023-5-22 19:47
刚刚意识到问题了,但是您说的图像保存问题,解决方法可以详细解释一下吗,就是如何修改权限,可能以后 ...

对于图像保存问题,操作系统的权限是决定能否写入文件的一个关键因素。以下是一些关于如何修改文件或文件夹权限的基本指南。

对于Windows用户:

1. 右键单击你希望保存图片的文件夹,然后选择“属性”。
2. 在打开的窗口中,转到“安全”选项卡。
3. 在这里你可以看到各种用户和它们的权限。如果你的用户账户没有写入权限,你可以通过点击“编辑”来更改这个设置。
4. 在新的窗口中,选择你的用户账户,然后在下面的框中选择“完全控制”或至少选择“写入”权限。
5. 点击“确定”来保存你的更改。

对于Linux或Mac用户:

1. 打开终端。
2. 使用 cd 命令进入你希望保存图片的文件夹的父文件夹。
3. 使用 ls -l 命令查看当前文件夹的权限设置。你应该能够看到类似这样的输出: drwxrwxrwx ,这表示所有用户(所有者、组和其他用户)都有读取、写入和执行的权限。
4. 如果你需要修改权限,可以使用 chmod 命令。例如, chmod 777 foldername 会给所有用户读取、写入和执行的权限。注意,这可能不是最安全的做法,因为它给所有用户完全的权限。你可能想要更具体地控制权限,例如 chmod 755 foldername 只会给所有者写入权限,而其他用户只有读取和执行的权限。

请注意,对于权限的修改需要管理员权限,如果你不是管理员,你可能需要在命令前加上 sudo ,例如 sudo chmod 777 foldername 。

在修改了权限后,你的Python程序应该能够在那个文件夹中保存图片了。如果还是不能,那么你可能需要检查你的磁盘空间,确保还有足够的空间来保存新的图片。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-5-22 20:14:44 | 显示全部楼层
BrownSugar 发表于 2023-5-21 22:42
一个是你的代码没有调用遗传算法主函数main,其次input的结果是字符串,传入main前需要转成int、float,做 ...

您这个程序有出结果吗,我按照你那个参数跑了一遍会报错,图片使用相同大小1280*1024

Traceback (most recent call last):
  File "D:\python\Gtext.py", line 100, in <module>
    main(target_path,pop_size,gene_size,elite_size,mutation_rate,epochs)
  File "D:\python\Gtext.py", line 76, in main
    population = selection(population, target, mutation_rate, elite_size)
  File "D:\python\Gtext.py", line 47, in selection
    fitness_scores = [fitness(target, gene) for gene in population]
  File "D:\python\Gtext.py", line 47, in <listcomp>
    fitness_scores = [fitness(target, gene) for gene in population]
  File "D:\python\Gtext.py", line 18, in fitness
    diff = target - gene
ValueError: operands could not be broadcast together with shapes (1170,2532,3) (102,128,3)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-22 20:29:42 | 显示全部楼层
本帖最后由 BrownSugar 于 2023-5-22 21:02 编辑
1119625819 发表于 2023-5-22 20:14
您这个程序有出结果吗,我按照你那个参数跑了一遍会报错,图片使用相同大小1280*1024

Traceback (most ...


能运行。
你看报错信息,因为你训练的图像尺寸是2532X1170的,但是你输入的是128,102,尺寸不匹配,你要用你的图像尺寸做,个体宽高输入2532,1170才行,如果你换了别的图像也要输入对应的图像尺寸。我的那个china.jpg是128X102的,所以我才输入128,102
还有如果图像尺寸大,迭代数多的话,这个代码的运算量和内存消耗是非常大的,可能会迭代一次要很久,我建议你可以先找小点的图像试试,对了,记得用jpg格式,如果用png图像通道数会报错的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-5-24 19:06:58 | 显示全部楼层
BrownSugar 发表于 2023-5-22 20:29
能运行。
你看报错信息,因为你训练的图像尺寸是2532X1170的,但是你输入的是128,102,尺寸不匹配,你 ...

我尝试过,可以运行,确实要消耗很多内存,但是,正常操作的话,迭代次数只设定为1(我设定了为10)应该远远不够的吧,我看到出来的那些图都是颜色散点,一直显示相似度为0.0,可能还有其他问题吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-24 23:22:26 | 显示全部楼层
本帖最后由 BrownSugar 于 2023-5-24 23:27 编辑
1119625819 发表于 2023-5-24 19:06
我尝试过,可以运行,确实要消耗很多内存,但是,正常操作的话,迭代次数只设定为1(我设定了为10)应该 ...



是的,正常图像生成可能要几千、上万次迭代。

我大致看了下,这个代码内存最大的问题在pop_size = len(population)这行上,它会导致每次迭代都会生成新的种群,而且没有淘汰旧的种群,所以种群会越来越大,导致内存占用越来越大。我感觉这里的pop_size既然是初始参数,它应该等于初始设置的那个值,所以我把这行给去掉了做函数参数传入了。

然后变异的三重循环改用了np做,计算适应度那里会计算2次,前一代和后一代,如果只是要打印看下结果,可以把后一代的注释掉。如果只要看最后生成的图像,整个6.5也可以注释掉,这样运算会稍微快点。

最后这个gene_size是图像尺寸的话,不用初始设置也行,它其实就等于图像的shape,稍微改下就是这个:
import numpy as np
from PIL import Image


# Step 1: 初始化种群
def init_population(pop_size, gene_size):
    population = [np.random.randint(256, size=gene_size) for _ in range(pop_size)]
    return population


# Step 2: 计算适应度
def fitness(target, gene):
    diff = target - gene
    return 1 / (1 + np.sum(np.abs(diff)))

# Step 3: 交叉
def crossover(parent1, parent2):
    child1 = parent1.copy()
    child2 = parent2.copy()
    r1, r2 = np.random.randint(0, parent1.shape[0], 2)
    c1, c2 = np.random.randint(0, parent1.shape[1], 2)
    child1[r1:c1, r2:c2] = parent2[r1:c1, r2:c2]
    child2[r1:c1, r2:c2] = parent1[r1:c1, r2:c2]
    return child1, child2


# Step 4: 变异
def mutation(child, mutation_rate):
    shape = child.shape
    mask = np.asarray(np.random.random(shape) < mutation_rate)
    child[mask] = np.random.randint(256, size=mask.sum())
    return child


# Step 5: 选择
def selection(population, pop_size, target, mutation_rate, elite_size):
    # Step 5.1: 计算适应度
    fitness_scores = [fitness(target, gene) for gene in population]

    # Step 5.2: 选择精英个体
    elite_indices = np.argsort(fitness_scores)[-elite_size:]
    elite = [population[i] for i in elite_indices]

    # Step 5.3: 选择杂交个体
    parents = []
    for i in range(pop_size - elite_size):
        parent1 = population[np.random.randint(pop_size)]
        parent2 = population[np.random.randint(pop_size)]
        child1, child2 = crossover(parent1, parent2)
        child1 = mutation(child1, mutation_rate)
        child2 = mutation(child2, mutation_rate)
        parents.append(child1)
        parents.append(child2)
    # Step 5.4: 合并精英和杂交个体
    next_population = elite + parents
    return next_population, fitness_scores


# Step 6: 主函数
def main(target_path, pop_size, elite_size, mutation_rate, epochs):
    # Step 6.1: 读取目标图像
    target = np.asarray(Image.open(target_path))
    # Step 6.2: 初始化种群

    population = init_population(pop_size, target.shape)
    fitness_scores = []
    for epoch in range(epochs):
        # Step 6.3: 进行选择
        population, fitness_scores = selection(population, pop_size, target, mutation_rate, elite_size)
        # Step 6.4: 打印当前的最佳适应度
        # fitness_scores = [fitness(target, gene) for gene in population]
        best_fitness = np.max(fitness_scores)
        print("Epoch: %d, Best Fitness: %0.12f" % (epoch, best_fitness))
        # Step 6.5: 保存当前最佳个体
        # best_index = np.argmax(fitness_scores)
        # best_gene = population[best_index]
        # best_image = Image.fromarray(best_gene.astype(np.uint8))
        # best_image.save("best_image_%d.png" % epoch)
    # Step 6.6: 保存最终结果
    best_index = np.argmax(fitness_scores)
    best_gene = population[best_index]
    best_image = Image.fromarray(best_gene.astype(np.uint8))
    best_image.save("final_image.png")
    best_image.show()



target_path = input("请输入一个图片文件路径(去""):")
pop_size = int(input("请输入种群大小:"))
elite_size = int(input("请输入保留精英个体数量,10%pop:"))
mutation_rate = float(input("请输入变异率:"))
epochs = int(input("请输入迭代次数(不能设定太小):"))
main(target_path, pop_size, elite_size, mutation_rate, epochs)


print("Epoch: %d, Best Fitness: %0.10f" % (epoch, best_fitness)),这行你可以把10调整个12或者再大点,可以看到小数点后十几位,这样它就不是0了,我试了下,这个适应度是会随着迭代不断增加的,只是增长的很缓慢,可能和那些初始参数也有关,我以前的遗传算法是拿deap做的,而你的是从底层实现的,所以我感觉你要是想适应度增长再快一点,你就得再研究研究了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-5-25 14:52:43 | 显示全部楼层
BrownSugar 发表于 2023-5-24 23:22
是的,正常图像生成可能要几千、上万次迭代。

我大致看了下,这个代码内存最大的问题在pop_size = ...

好的,我会研究研究,提前了解遇到一些问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-27 13:56

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表