【python】机器学习 多目标遗传算法

import numpy as np

#  --------------------------------------------
#               参数设置
#  --------------------------------------------
DNA_SIZE = 5  # DNA长度
POP_SIZE = 50  # 初始种群数
CROSSOVER_RATE = 0.95  # 交叉概率
MUTATION_RATE = 0.01  # 变异概率
N_GENERATIONS = 100  # 迭代次数
# --------------------------------------------
SAMPLE_SIZE = 123  # 样本数
x1_BOUND = [100000, 1000000]
x2_BOUND = [0.04, 15]


class SAMPLE():  # 单次样本结构--------------------------------------------
    def __init__(self):
        self.sample = []
        self.decode_data = []
        self.num = SAMPLE_SIZE

    def pop_make(self, dna):
        for i in range(len(dna)):
            self.sample.append([])
        for i in range(len(dna)):  # i:种群数
            for j in range(self.num):  # j:每个种群内的个体数
                self.sample[i].append(dna[i][j::self.num])

    def decode(self, bound):
        for i in self.sample:
            a_sample = []
            for j in i:
                a_price = np.dot(j, 2 ** np.arange(DNA_SIZE)[::-1]) / float(2 ** DNA_SIZE - 1) * (bound[1] - bound[0]) + \
                          bound[0]
                a_sample.append(a_price)
            self.decode_data.append(a_sample)


class GA():  # 遗传算法--------------------------------------------
    def __init__(self):
        # 每次迭代中最好的数据
        self.fitness = []
        self.y1 = []
        self.y2 = []
        self.y3 = []
        self.x1 = []
        self.x2 = []

    # 解码过程 ----------------------------------------------------------------------------------------
    def translateDNA(self, DNA, bound):
        sample = SAMPLE()
        sample.pop_make(DNA)
        sample.decode(bound)
        return sample.decode_data

    # 交叉变异 ----------------------------------------------------------------------------------------
    def crossover_and_mutation(self, DNA, CROSSOVER_RATE=CROSSOVER_RATE):
        new_DNA = []
        for father in DNA:
            child = father
            if np.random.rand() < CROSSOVER_RATE:
                mother = DNA[np.random.randint(POP_SIZE)]
                cross_points = np.random.randint(low=0, high=DNA_SIZE * SAMPLE_SIZE)
                child[cross_points:] = mother[cross_points:]
            if np.random.rand() < MUTATION_RATE:
                mutate_point = np.random.randint(0, DNA_SIZE * SAMPLE_SIZE)
                child[mutate_point] = child[mutate_point] ^ 1
            new_DNA.append(child)
        return new_DNA

    # 计算适应值 --------------------------------------------------------------------------------------
    def get_fitness(self, DNA1, DNA2):
        """
        对DNA解码-->x
        x-->y
        y-->fitness
        show函数:
            记录最大的fitness值,便于画图
            记录x和y,便于添加到附件
        """

        x1 = self.translateDNA(DNA1, x1_BOUND)
        x2 = self.translateDNA(DNA2, x2_BOUND)

        y1 = []
        y2 = []

        fitness = []

        self.show(fitness, x1, x2, y1, y2, y3)
        return fitness, y1, y2, y3

    # 选择适应值高的个体 ------------------------------------------------------------------------------
    def select(self, DNA, DNA2, fitness):
        fitness = fitness - np.min(fitness) + 1e-3
        idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True, p=fitness / fitness.sum())
        return DNA[idx], DNA2[idx]

    # 每次迭代的信息print --------------------------------------------
    def show(self, fitness, x1, x2, y1, y2, y3):
        """
        记录最大的fitness到self中,便于画图(fitness[index])
        将对应的x和y也记录到self中,便于储存到本地(x[index],y[index])
        """
        max_fitness = max(fitness)
        index = fitness.index(max_fitness)
        self.fitness.append(max_fitness)
        self.y1.append(y1[index])
        self.y2.append(y2[index])
        self.y3.append(y3[index])
        self.x1.append(x1[index])
        self.x2.append(x2[index])
        print("银行收益:{:.4f}".format(y1[index]))
        print("流失率总和:{:.4f}".format(y3[index]))

    # 每次迭代记录 ---------------------------------------------------
    def load(self):
        path_1 = r"……"
        path_2 = r"……"
        header = ["……", "……"]
        write_excel(self.x1, path_1)
        write_excel(self.x2, path_2)

    # 30次迭代画图 --------------------------------------------
    def draw(self):
        y1_name = "y1"
        y2_name = "y2"
        save_path = r"C:\Users\Administrator\Desktop\a.png"

        import matplotlib.pyplot as plt
        x = range(1, N_GENERATIONS + 1)
        fig = plt.figure(figsize=(20, 10))
        plt.style.use('seaborn-whitegrid')

        ax1 = fig.add_subplot(311)
        plt.legend(fontsize=20)
        ax1.plot(x, self.fitness, linestyle=':', linewidth=1, marker='d', markersize=5, label="适应度")
        plt.ylabel("适应度", fontsize=20)

        ax2 = fig.add_subplot(211)
        ax2.plot(x, self.y1, linestyle='-.', linewidth=1, marker='+', markersize=5, label=y1_name)
        plt.ylabel(y1_name, fontsize=20)
        plt.legend(fontsize=20)

        ax2 = fig.add_subplot(212)
        ax2.plot(x, self.y3, linestyle='-.', linewidth=1, marker='^', markersize=5, label=y2_name)
        plt.xlabel("迭代次数", fontsize=20)
        plt.ylabel(y2_name, fontsize=20)
        plt.legend(fontsize=20)
        plt.savefig(save_path, bbox_inches='tight', dpi=1000)
        plt.show()


if __name__ == "__main__":
    DNA1 = np.random.randint(2, size=(POP_SIZE, DNA_SIZE * SAMPLE_SIZE))
    DNA2 = np.random.randint(2, size=(POP_SIZE, DNA_SIZE * SAMPLE_SIZE))

    ga = GA()
    for i in range(N_GENERATIONS):
        print("迭代第%d次-------------------------------------------- " % (i + 1))
        DNA1 = np.array(ga.crossover_and_mutation(DNA1, CROSSOVER_RATE))
        DNA2 = np.array(ga.crossover_and_mutation(DNA2, CROSSOVER_RATE))
        fitness, y1, y2, y3 = ga.get_fitness(DNA1, DNA2)
        DNA1, DNA2 = ga.select(DNA1, DNA2, fitness)
    ga.draw()
    ga.load()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值