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()
【python】机器学习 多目标遗传算法
最新推荐文章于 2024-08-23 11:00:00 发布