您现在的位置是:首页 > 技术教程 正文

算法介绍及实现——基于遗传算法改进的BP神经网络算法(附完整Python实现)

admin 阅读: 2024-03-25
后台-插件-广告管理-内容页头部广告(手机)

目录

一、算法介绍

1.1 遗传算法

1.2 为什么要使用遗传算法进行改进

二、算法原理

三、算法实现

3.1 算子选择

3.2 代码实现


一、算法介绍

1.1 遗传算法

        遗传算法是受启发于自然界中生物对于自然环境 “适者生存”的强大自适应能力,通过对生物演化过程模拟和抽象,构建了以自然界生物演变进化为逻辑基础的遗传算法。遗传算法包括了自然界生物在演变过程中的主要步骤,即选择、(基因)变异和(基因)交叉,对应着遗传算法中的三个运算算子。在具体的优化问题下,遗传算法会产生多个问题的可行解作为种群,然后让种群进行模拟意义上生物进化中的选择、变异、交叉等操作。在种群繁衍(迭代)一定次数之后,通过计算种群的适应度,寻找最终种群中的最优个体,该个体即代表优化问题的近似最优解。上述此即为遗传算法主要思想。其流程图如下:

1.2 为什么要使用遗传算法进行改进

        BP算法原理不多赘述,可见我之前博文BP原理介绍,在BP训练过程中,很容易出现陷入局部最小值的情况,所以引入遗传算法进行优化。遗传作为一种模拟生物进化的全局寻优算法,有着优秀的全局寻优能力,能够以一个种群为基础不断的迭代进化,最后获得问题的最优解或近似最优解。BP算法和遗传算法都是人们广泛使用的算法,而且两算法具有明显的优势互补,故而很多研究者都在探索两个算法的融合方法,以期能提高算法性能、提升算法精度。

二、算法原理

        基于遗传算法改进的BP神经网络算法(GA-BP算法)的主要思想即为:通过遗传算法的全局寻优能力获得最优的BP网络的初始权值和阈值,将寻优算法获得的最优初始权值和阈值作为BP神经网络的初始权值和阈值,然后进行训练以避免陷入局部最小值。遗传算法改进后的BP神经网络权值不是随机产生的,而是遗传算法寻优模块获得的。BP算法中的初始权值和阈值作为遗传算法个体的基因值,个体长度即为BP神经网络中权值和阈值的个数,每个基因即代表一个权值或阈值,基因上的数值就是BP神经网络中连接权值或阈值的真实值,如此便组成了遗传算法中的一个染色体。一定数量的染色体作为遗传算法训练的初始种群,再经过遗传算法的选择运算、交叉运算、变异运算等迭代过程后获得一个最优个体,然后以最优个体作为BP网络的初始参数进行训练,此即为GA-BP算法的原理。流程图如下:

三、算法实现

3.1 算子选择

         对于(e)所述的组织方法,是当影响因子数据和目标数据没有很强的相关性的情况下,用前一时序区间的数据作为该时序数据的影响因子来进行训练。

3.2 代码实现

         实例为基于一段时序监测数据的滑坡位移预测,监测影响因子数据有:温度、降雨、风力、灌溉等,监测的目标数据是坡体的裂缝宽度数据。实验表明影响因子数据和目标数据不具有强相关性,所以选择用目标数据本身作为影响因子数据。

        将整个算法分成如下模块:

  1. chrom_code # 基因编码模块
  2. chrom_mutate # 变异算子模块
  3. chrom_cross # 交叉算子模块
  4. chrom_select # 选择算子模块
  5. chrom_fitness # 染色体适应度计算模块
  6. data_prepare # 数据准备模块
  7. BP_network # BPNN模块
  8. chrom_test # 染色体检测模块
  9. new_GA-BP # 改进算法主程序

chrom_test.py  检测生成的染色体基因有没有超限。

  1. # 染色体检查
  2. # 检查染色体中有没有超出基因范围的基因
  3. def test(code_list,bound):
  4. """
  5. :param code_list: code_list: 染色体个体
  6. :param bound: 各基因的取值范围
  7. :return: bool
  8. """
  9. for i in range(len(code_list)):
  10. if code_list[i] < bound[i][0] or code_list[i] > bound[i][1]:
  11. return False
  12. else:
  13. return True

 chrom_code.py  基因编码。

  1. # 基因编码模块
  2. import random
  3. import numpy as np
  4. import chrom_test
  5. def code(chrom_len,bound):
  6. """
  7. :param chrom_len: 染色体的长度,为一个数,采用实数编码即为基因的个数
  8. :param bound: 取值范围,为一个二维数组,每个基因允许的取值范围
  9. :return: 对应长度的编码
  10. """
  11. code_list = []
  12. count = 0
  13. while True:
  14. pick = random.uniform(0,1)
  15. if pick == 0:
  16. continue
  17. else:
  18. pick = round(pick,3)
  19. temp = bound[count][0] + (bound[count][1] - bound[count][0])*pick
  20. temp = round(temp,3)
  21. code_list.append(temp)
  22. count = count + 1
  23. if count == chrom_len:
  24. if chrom_test.test(code_list,bound):
  25. break
  26. else:
  27. count = 0
  28. return code_list

BP_network.py    完成网络结构的构建。

  1. # BP模块 借助PyTorch实现
  2. import torch
  3. # 引入了遗传算法参数的BP模型
  4. class BP_net(torch.nn.Module):
  5. def __init__(self, n_feature, n_hidden, n_output, GA_parameter):
  6. super(BP_net, self).__init__()
  7. # 构造隐含层和输出层
  8. self.hidden = torch.nn.Linear(n_feature, n_hidden)
  9. self.output = torch.nn.Linear(n_hidden, n_output)
  10. # 给定网络训练的初始权值和偏执等
  11. self.hidden.weight = torch.nn.Parameter(GA_parameter[0])
  12. self.hidden.bias = torch.nn.Parameter(GA_parameter[1])
  13. self.output.weight = torch.nn.Parameter(GA_parameter[2])
  14. self.output.bias = torch.nn.Parameter(GA_parameter[3])
  15. def forward(self, x):
  16. # 前向计算
  17. hid = torch.tanh(self.hidden(x))
  18. out = torch.tanh(self.output(hid))
  19. return out
  20. # 传统的BP模型
  21. class ini_BP_net(torch.nn.Module):
  22. def __init__(self, n_feature, n_hidden, n_output):
  23. super(ini_BP_net, self).__init__()
  24. # 构造隐含层和输出层
  25. self.hidden = torch.nn.Linear(n_feature, n_hidden)
  26. self.output = torch.nn.Linear(n_hidden, n_output)
  27. def forward(self, x):
  28. # 前向计算
  29. hid = torch.tanh(self.hidden(x))
  30. out = torch.tanh(self.output(hid))
  31. return out
  32. def train(model, epochs, learning_rate, x_train, y_train):
  33. """
  34. :param model: 模型
  35. :param epochs: 最大迭代次数
  36. :param learning_rate:学习率
  37. :param x_train:训练数据(输入)
  38. :param y_train:训练数据(输出)
  39. :return: 最终的loss值(MSE)
  40. """
  41. # path = "log.txt"
  42. # f = open(path, 'w',encoding='UTF-8')
  43. # f.write("train log\n------Train Action------\n"
  44. # "Time:{}\n".format(time.ctime()))
  45. loss_fc = torch.nn.MSELoss(reduction="sum")
  46. optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
  47. loss_list = []
  48. for i in range(epochs):
  49. model.train()
  50. # 前向计算
  51. data = model(x_train)
  52. # 计算误差
  53. loss = loss_fc(data, y_train)
  54. loss_list.append(loss)
  55. # 更新梯度
  56. optimizer.zero_grad()
  57. # 方向传播
  58. loss.backward()
  59. # 更新参数
  60. optimizer.step()
  61. # print("This is {} th iteration,MSE is {}。".format(i+1,loss))
  62. loss_ls = [loss_list[i].detach().numpy() for i in range(len(loss_list))]
  63. return loss_ls

 chrom_fitness.py   适应度计算

  1. # 适应度计算模块
  2. # 功能;传入一个编码,返回一个适应度值
  3. from torchvision.transforms import transforms
  4. import torch
  5. import BP_network
  6. import numpy as np
  7. # 最小二乘思想获得两组数据的误差
  8. def zxec_PC(X, Y):
  9. X = np.array(X, dtype=np.float).flatten()
  10. Y = np.array(Y, dtype=np.float).flatten()
  11. if len(X) != len(Y):
  12. print("Wrong!")
  13. n = len(X)
  14. Wc = 0
  15. for i in range(n):
  16. Wc = Wc + (X[i] - Y[i]) * (X[i] - Y[i])
  17. return Wc
  18. def calculate_fitness(code,n_feature,n_hidden,n_output,epochs
  19. ,learning_rate,x_train,y_train):
  20. """
  21. :param code: 染色体编码
  22. :param n_feature: 输入层个数
  23. :param n_hidden: 隐含层个数
  24. :param n_output: 输出层个数
  25. :param epochs: 最多迭代次数
  26. :param learning_rate: 学习率
  27. :param x_train: 训练(输入)数据
  28. :param y_train: 训练(输出)数据
  29. :return: fitness 适应度值
  30. """
  31. Parameter = code[:]
  32. # 参数提取
  33. hidden_weight = Parameter[0:n_feature * n_hidden]
  34. hidden_bias = Parameter[n_feature * n_hidden:
  35. n_feature * n_hidden + n_hidden]
  36. output_weight = Parameter[n_feature * n_hidden + n_hidden:
  37. n_feature * n_hidden + n_hidden + n_hidden * n_output]
  38. output_bias = Parameter[n_feature * n_hidden + n_hidden + n_hidden * n_output:
  39. n_feature * n_hidden + n_hidden + n_hidden * n_output + n_output]
  40. # 类型转换
  41. tensor_tran = transforms.ToTensor()
  42. hidden_weight = tensor_tran(np.array(hidden_weight).reshape((n_hidden, n_feature))).to(torch.float32)
  43. hidden_bias = tensor_tran(np.array(hidden_bias).reshape((1, n_hidden))).to(torch.float32)
  44. output_weight = tensor_tran(np.array(output_weight).reshape((n_output,n_hidden))).to(torch.float32)
  45. output_bias = tensor_tran(np.array(output_bias).reshape((1, n_output))).to(torch.float32)
  46. # 形装转换
  47. hidden_weight = hidden_weight.reshape((n_hidden,n_feature))
  48. hidden_bias = hidden_bias.reshape(n_hidden)
  49. output_weight = output_weight.reshape((n_output,n_hidden))
  50. output_bias = output_bias.reshape(n_output)
  51. # 带入模型计算
  52. GA = [hidden_weight, hidden_bias, output_weight, output_bias]
  53. BP_model = BP_network.BP_net(n_feature,n_hidden,n_output,GA)
  54. loss = BP_network.train(BP_model,epochs,learning_rate,x_train,y_train)
  55. # 计算适应度
  56. prediction = BP_model(x_train)
  57. fitness = 10 - zxec_PC(prediction.detach().numpy(),y_train.detach().numpy())
  58. return round(fitness,4)

 chrom_mutate.py  选择算子

  1. # 变异算子
  2. import random
  3. def mutate(chrom_sum, size, p_mutate, chrom_len, bound, maxgen, nowgen):
  4. """
  5. :param chrom_sum: 染色体群,即种群,里面为一定数量的染色体 类型为一个二维列表
  6. :param size: 种群规模,即染色体群里面有多少个染色体 为一个数
  7. :param p_mutate: 交叉概率 为一个浮点数
  8. :param chrom_len: 种群长度,即一条染色体的长度,即基因的个数 为一个数
  9. :param bound: 各基因的取值范围
  10. :param maxgen: 最大迭代次数
  11. :param nowgen: 当前迭代次数
  12. :return: 变异算子后的种群
  13. """
  14. count = 0
  15. # print("\n---这是第{}次遗传迭代...".format(nowgen))
  16. while True:
  17. # 随机选择变异染色体
  18. # print("{}-{}".format(nowgen,count+1))
  19. seek = random.uniform(0,1)
  20. while seek == 1:
  21. seek = random.uniform(0,1)
  22. index = int(seek * size)
  23. # print("可能变异的染色体号数为:",index)
  24. # 判断是否变异
  25. flag = random.uniform(0,1)
  26. if p_mutate >= flag:
  27. # 选择变异位置
  28. # print("发生变异中...")
  29. seek1 = random.uniform(0,1)
  30. while seek1 == 1:
  31. seek1 = random.uniform(0,1)
  32. pos = int(seek1 * chrom_len)
  33. # print("变异的基因号数为:",pos)
  34. # 开始变异
  35. seek3 = random.uniform(0,1)
  36. fg = pow(seek3*(1-nowgen/maxgen),2) # 约到迭代后期,其至越接近0,变异波动就越小
  37. # print("变异前基因为:",chrom_sum[index][pos])
  38. if seek3 > 0.5:
  39. chrom_sum[index][pos] = round(chrom_sum[index][pos] +
  40. (bound[pos][1] - chrom_sum[index][pos])*fg,3)
  41. else:
  42. chrom_sum[index][pos] = round(chrom_sum[index][pos] -
  43. (chrom_sum[index][pos] - bound[pos][0])*fg,3)
  44. # print("变异后基因为:", chrom_sum[index][pos])
  45. count = count + 1
  46. else:
  47. # print("未发生变异。")
  48. count = count + 1
  49. if count == size:
  50. break
  51. return chrom_sum

chrom_cross.py  交叉算子

  1. # 交叉算子
  2. import random
  3. import chrom_test
  4. def cross(chrom_sum, size, p_cross, chrom_len, bound):
  5. """
  6. :param chrom_sum:种群集合,为二维列表
  7. :param size:种群总数,即染色体的个数
  8. :param p_cross:交叉概率
  9. :param chrom_len:染色提长度,每个染色体含基因数
  10. :param bound:每个基因的范围
  11. :return: 交叉后的种群集合
  12. """
  13. count = 0
  14. while True:
  15. # 第一步 先选择要交叉的染色体
  16. seek1 = random.uniform(0,1)
  17. seek2 = random.uniform(0,1)
  18. while seek1 == 0 or seek2 == 0 or seek1 == 1 or seek2 == 1:
  19. seek1 = random.uniform(0, 1)
  20. seek2 = random.uniform(0, 1)
  21. # index_1(2)为选中交叉的个体在种群中的索引
  22. index_1 = int(seek1 * size)
  23. index_2 = int(seek2 * size)
  24. if index_1 == index_2:
  25. if index_2 == size - 1:
  26. index_2 = index_2 - 1
  27. else:
  28. index_2 = index_2 + 1
  29. # print("可能交叉的两个染色体为:",index_1,index_2)
  30. # 第二步 判断是否进行交叉
  31. flag = random.uniform(0,1)
  32. while flag == 0:
  33. flag = random.uniform(0,1)
  34. if p_cross >= flag:
  35. # 第三步 开始交叉
  36. # print("开始交叉...")
  37. p_pos = random.uniform(0, 1)
  38. while p_pos == 0 or p_pos == 1:
  39. p_pos = random.uniform(0, 1)
  40. pos = int(p_pos * chrom_len)
  41. # print("交叉的极影位置为:",pos)
  42. var1 = chrom_sum[index_1][pos]
  43. var2 = chrom_sum[index_2][pos]
  44. pick = random.uniform(0,1)
  45. # print("交叉前染色体为:")
  46. # print(chrom_sum[index_1])
  47. # print(chrom_sum[index_2])
  48. chrom_sum[index_1][pos] = round((1-pick) * var1 + pick * var2,3)
  49. chrom_sum[index_2][pos] = round(pick * var1 + (1-pick) * var2,3)
  50. # print("交叉后染色体为:")
  51. # print(chrom_sum[index_1])
  52. # print(chrom_sum[index_2])
  53. if chrom_test.test(chrom_sum[index_1],bound) and chrom_test.test(chrom_sum[index_2],bound):
  54. count = count + 1
  55. else:
  56. continue
  57. else:
  58. # print("没有发生交叉。")
  59. count = count + 1
  60. # print("本次循环结束\n")
  61. if count == size:
  62. break
  63. return chrom_sum

chrom_select.py   选择算子 

  1. # 选择算子
  2. import numpy as np
  3. import random
  4. def select(chrom_sum,fitness_ls):
  5. """
  6. :param chrom_sum:种群
  7. :param fitness_ls: 各染色体的适应度值
  8. :return: 更新后的种群
  9. """
  10. # print("种群适应度分别为:",fitness_ls)
  11. fitness_ls = np.array(fitness_ls,dtype=np.float64)
  12. sum_fitness_ls = np.sum(fitness_ls,dtype=np.float64)
  13. P_inh = []
  14. M = len(fitness_ls)
  15. for i in range(M):
  16. P_inh.append(fitness_ls[i]/sum_fitness_ls)
  17. # 将概率累加
  18. for i in range(len(P_inh)-1):
  19. P_temp = P_inh[i] + P_inh[i+1]
  20. P_inh[i+1] = round(P_temp, 2)
  21. P_inh[-1] = 1
  22. # 轮盘赌算法选择染色体
  23. account = []
  24. for i in range(M):
  25. rand = random.random()
  26. for j in range(len(P_inh)):
  27. if rand <= P_inh[j]:
  28. account.append(j)
  29. break
  30. else:
  31. continue
  32. # 根据索引号跟新种群
  33. # print("轮盘赌的结果为:",account)
  34. new_chrom_sum = []
  35. for i in account:
  36. new_chrom_sum.append(chrom_sum[i])
  37. return new_chrom_sum

data_prepare.py  数据准备

  1. # 数据准备
  2. import numpy as np
  3. import pandas as pd
  4. def Data_loader():
  5. # 文件路径
  6. ENU_measure_path = "18-10-25至19-3-25三方向位移数据.xlsx"
  7. t_path = "天气数据.xls"
  8. M_path = "data.csv"
  9. # 三方向数据
  10. df_1 = pd.read_excel(ENU_measure_path)
  11. ENU_df = pd.DataFrame(df_1)
  12. ENU_E = ENU_df["E/m"]
  13. ENU_E = np.array(ENU_E)
  14. ENU_N = ENU_df["N/m"]
  15. ENU_N = np.array(ENU_N)
  16. ENU_U = ENU_df["U/m"]
  17. ENU_U = np.array(ENU_U)
  18. ENU_R = ENU_df['R/m']
  19. ENU_R = np.array(ENU_R)
  20. df_2 = pd.read_excel(t_path)
  21. t_df = pd.DataFrame(df_2)
  22. # 最大温度数据
  23. max_tem = t_df["bWendu"]
  24. max_tem_ls = []
  25. for i in range(len(max_tem)):
  26. temp = str(max_tem[i])
  27. temp = temp.replace("℃","")
  28. max_tem_ls.append(eval(temp))
  29. max_tem = np.array(max_tem_ls)
  30. # 最低温度数据
  31. min_tem = t_df["yWendu"]
  32. min_tem_ls = []
  33. for i in range(len(min_tem)):
  34. temp = str(min_tem[i])
  35. temp = temp.replace("℃","")
  36. min_tem_ls.append(eval(temp))
  37. min_tem =np.array(min_tem_ls)
  38. # 天气数据
  39. tianqi = t_df["Tian_Qi"]
  40. tianqi = np.array(tianqi)
  41. # 风力数据
  42. Feng = t_df["Feng"]
  43. Feng = np.array(Feng)
  44. # 降雨数据
  45. rain = t_df["rainfall"]
  46. rain = np.array(rain)
  47. # 灌溉数据
  48. guangai = t_df["guangai"]
  49. guangai = np.array(guangai)
  50. # 获取时间数据
  51. namels = t_df["ymd"]
  52. name_ls = []
  53. for i in range(len(namels)):
  54. temp = str(namels[i])
  55. temp = temp.replace(" 00:00:00","")
  56. name_ls.append(str(temp))
  57. # 读取另一文件数据,该数据为位移计和GNSS监测数据
  58. df_3 = pd.read_csv(M_path)
  59. M_df = pd.DataFrame(df_3)
  60. M_data = M_df["Measurerel"]
  61. R_data = M_df["R"]
  62. M_data = np.array(M_data)
  63. R_data = np.array(R_data)
  64. return [ENU_R, M_data, R_data, ENU_U, ENU_E, ENU_N,max_tem,min_tem,name_ls]

主程序!!!!

  1. # 改进算法主程序
  2. import sys
  3. import chrom_code # 基因编码模块
  4. import chrom_mutate # 变异算子模块
  5. import chrom_cross # 交叉算子模块
  6. import chrom_select # 选择算子模块
  7. import chrom_fitness # 染色体适应度计算模块
  8. import data_prepare # 数据准备模块
  9. import BP_network # BPNN模块
  10. import torch
  11. import torch.nn.functional as F
  12. from torchvision.transforms import transforms
  13. import numpy as np
  14. import matplotlib.pyplot as plt
  15. import time
  16. plt.rcParams['font.sans-serif'] = ['SimHei']
  17. plt.rcParams['axes.unicode_minus'] = False
  18. # -----参数设置-----
  19. epochs = 300 # 神经网络最大迭代次数
  20. learning_rate = 0.01 # 学习率
  21. n_feature = 6 # 输入层个数
  22. n_hidden = 9 # 隐含层个数
  23. n_output = 1 # 输出层个数
  24. chrom_len = n_feature * n_hidden + n_hidden + n_hidden * n_output + n_output # 染色体长度
  25. size = 15 # 种群规模
  26. bound = np.ones((chrom_len, 2))
  27. sz = np.array([[-1, 0], [0, 1]])
  28. bound = np.dot(bound, sz) # 各基因取值范围
  29. p_cross = 0.4 # 交叉概率
  30. p_mutate = 0.01 # 变异概率
  31. maxgen = 30 # 遗传最大迭代次数
  32. # 数据准备
  33. # ========================================= #
  34. data_set = data_prepare.Data_loader()
  35. displace = data_set[1]
  36. name_ls = data_set[-1]
  37. in_train_data = []
  38. in_test_data = []
  39. # 数目分配
  40. train_num = 120
  41. test_num = len(displace) - train_num - n_feature
  42. for i in range(len(displace)):
  43. temp = []
  44. if i <= train_num-1: # 用于控制训练数据和预测数据的分配
  45. temp = [round(displace[i + j], 5) for j in range(n_feature)]
  46. in_train_data.append(temp)
  47. else:
  48. temp = [round(displace[i + j], 5) for j in range(n_feature)]
  49. in_test_data.append(temp)
  50. if i == len(displace)-n_feature-1:
  51. break
  52. # 格式转化
  53. in_train_data = np.array(in_train_data)
  54. in_test_data = np.array(in_test_data)
  55. # 数据分割,用于建模和预测
  56. out_train_data = displace[n_feature:train_num+n_feature]
  57. out_test_data = displace[train_num+n_feature:len(displace)]
  58. # 测试输出
  59. # print(in_train_data)
  60. # print(out_train_data)
  61. # print(in_test_data)
  62. # print(out_test_data)
  63. # print(train_num)
  64. # print(test_num)
  65. # 数据格式转换及数据归一化
  66. tensor_tran = transforms.ToTensor()
  67. # 训练过程中的输入层数据
  68. in_train_data = tensor_tran(in_train_data).to(torch.float)
  69. in_train_data = F.normalize(in_train_data)
  70. in_train_data = in_train_data.reshape(train_num, n_feature)
  71. # 预测过程中的输入层数据
  72. in_test_data = tensor_tran(in_test_data).to(torch.float)
  73. in_test_data = F.normalize(in_test_data)
  74. in_test_data = in_test_data.reshape(test_num, n_feature)
  75. # 训练过程中的输出层数据
  76. out_train_data = out_train_data.reshape(len(out_train_data), 1)
  77. out_train_data = tensor_tran(out_train_data).to(torch.float)
  78. un_norm1 = out_train_data[0][0]
  79. out_train_data = F.normalize(out_train_data)
  80. norm1 = out_train_data[0][0]
  81. out_train_data = out_train_data.reshape(train_num, n_output)
  82. fanshu_train = round(float(un_norm1 / norm1), 4) # 建模时,训练数据中输出数据的范数
  83. # 预测中用于检验的输出层数据
  84. out_test_data = out_test_data.reshape(len(out_test_data), 1)
  85. out_test_data = tensor_tran(out_test_data).to(torch.float)
  86. un_norm = out_test_data[0][0] # 归一化前
  87. out_test_data = F.normalize(out_test_data)
  88. norm = out_test_data[0][0] # 归一化后
  89. out_test_data = out_test_data.reshape(test_num, n_output)
  90. fanshu = round(float(un_norm / norm), 4) # 预测时,测试数据中输出数据的范数
  91. # 建模训练数据
  92. x_train = in_train_data
  93. y_train = out_train_data
  94. x_test = in_test_data
  95. y_label = out_test_data
  96. # ========================================== #
  97. chrom_sum = [] # 种群,染色体集合
  98. for i in range(size):
  99. chrom_sum.append(chrom_code.code(chrom_len, bound))
  100. account = 0 # 遗传迭代次数计数器
  101. best_fitness_ls = [] # 每代最优适应度
  102. ave_fitness_ls = [] # 每代平均适应度
  103. best_code = [] # 迭代完成适应度最高的编码值
  104. # 适应度计算
  105. fitness_ls = []
  106. for i in range(size):
  107. fitness = chrom_fitness.calculate_fitness(chrom_sum[i], n_feature, n_hidden, n_output,
  108. epochs, learning_rate, x_train, y_train)
  109. fitness_ls.append(fitness)
  110. # 收集每次迭代的最优适应值和平均适应值
  111. fitness_array = np.array(fitness_ls).flatten()
  112. fitness_array_sort = fitness_array.copy()
  113. fitness_array_sort.sort()
  114. best_fitness = fitness_array_sort[-1]
  115. best_fitness_ls.append(best_fitness)
  116. ave_fitness_ls.append(fitness_array.sum() / size)
  117. while True:
  118. # 选择算子
  119. # print("\n这是第{}次遗传迭代。".format(account+1))
  120. # print("平均适应度为:",fitness_array.sum()/size)
  121. chrom_sum = chrom_select.select(chrom_sum, fitness_ls)
  122. # 交叉算子
  123. chrom_sum = chrom_cross.cross(chrom_sum, size, p_cross, chrom_len, bound)
  124. # 变异算子
  125. chrom_sum = chrom_mutate.mutate(chrom_sum, size, p_mutate, chrom_len, bound, maxgen, account + 1)
  126. # 适应度计算
  127. fitness_ls = []
  128. for i in range(size):
  129. fitness = chrom_fitness.calculate_fitness(chrom_sum[i], n_feature, n_hidden, n_output,
  130. epochs, learning_rate, x_train, y_train)
  131. fitness_ls.append(fitness)
  132. # 收集每次迭代的最优适应值和平均适应值
  133. fitness_array = np.array(fitness_ls).flatten()
  134. fitness_array_sort = fitness_array.copy()
  135. fitness_array_sort.sort()
  136. best_fitness = fitness_array_sort[-1] # 获取最优适应度值
  137. best_fitness_ls.append(best_fitness)
  138. ave_fitness_ls.append(fitness_array.sum() / size)
  139. # 计数器加一
  140. account = account + 1
  141. if account == maxgen:
  142. index = fitness_ls.index(max(fitness_ls)) # 返回最大值的索引
  143. best_code = chrom_sum[index] # 通过索引获得对于染色体
  144. break
  145. # 参数提取
  146. hidden_weight = best_code[0:n_feature * n_hidden]
  147. hidden_bias = best_code[n_feature * n_hidden:
  148. n_feature * n_hidden + n_hidden]
  149. output_weight = best_code[n_feature * n_hidden + n_hidden:
  150. n_feature * n_hidden + n_hidden + n_hidden * n_output]
  151. output_bias = best_code[n_feature * n_hidden + n_hidden + n_hidden * n_output:
  152. n_feature * n_hidden + n_hidden + n_hidden * n_output + n_output]
  153. # 类型转换
  154. tensor_tran = transforms.ToTensor()
  155. hidden_weight = tensor_tran(np.array(hidden_weight).reshape((n_hidden, n_feature))).to(torch.float32)
  156. hidden_bias = tensor_tran(np.array(hidden_bias).reshape((1, n_hidden))).to(torch.float32)
  157. output_weight = tensor_tran(np.array(output_weight).reshape((n_output, n_hidden))).to(torch.float32)
  158. output_bias = tensor_tran(np.array(output_bias).reshape((1, n_output))).to(torch.float32)
  159. # 形装转换
  160. hidden_weight = hidden_weight.reshape((n_hidden, n_feature))
  161. hidden_bias = hidden_bias.reshape(n_hidden)
  162. output_weight = output_weight.reshape((n_output, n_hidden))
  163. output_bias = output_bias.reshape(n_output)
  164. GA = [hidden_weight, hidden_bias, output_weight, output_bias]
  165. # 带入模型计算
  166. BP_model = BP_network.BP_net(n_feature, n_hidden, n_output, GA)
  167. ini_BP_model = BP_network.ini_BP_net(n_feature, n_hidden, n_output)
  168. # 网络训练
  169. loss = BP_network.train(BP_model, epochs, learning_rate, x_train, y_train)
  170. ini_loss = BP_network.train(ini_BP_model, epochs, learning_rate, x_train, y_train)
  171. # 建模效果
  172. model_x = BP_model(x_train)
  173. ini_model_x = ini_BP_model(x_train)
  174. # 网络预测
  175. prediction = BP_model(x_test)
  176. ini_prediction = ini_BP_model(x_test)
  177. # 建模数据反归一化(都换算到厘米级)
  178. y_train = y_train.detach().numpy() * fanshu_train
  179. model_x = model_x.detach().numpy() * fanshu_train
  180. ini_model_x = ini_model_x.detach().numpy() * fanshu_train
  181. # 建模绘图
  182. train_name_ls = name_ls[6:126]
  183. xlabel = [i for i in range(0, 120, 14)]
  184. plt.plot(y_train, markersize=4, marker='.', label="真值", c='r')
  185. plt.plot(model_x, markersize=4, marker='.', label="GA-BP预测值", c='b')
  186. plt.title("GA-BP算法建模情况")
  187. plt.ylabel("累计裂缝宽度(mm)")
  188. plt.xticks(xlabel, [train_name_ls[i] for i in xlabel], rotation=25)
  189. plt.grid(linestyle='-.') # 设置虚线
  190. plt.legend()
  191. f2 = plt.figure()
  192. plt.plot(y_train, markersize=4, marker='.', label="真值", c='r')
  193. plt.plot(ini_model_x, markersize=4, marker='.', label="BP预测值", c='g')
  194. plt.title("BP算法建模情况")
  195. plt.ylabel("累计裂缝宽度(mm)")
  196. plt.xticks(xlabel, [train_name_ls[i] for i in xlabel], rotation=25)
  197. plt.grid(linestyle='-.')
  198. plt.legend()
  199. # 预测数据格式转换(厘米级)
  200. GABP_prediction = prediction.detach().numpy()
  201. BP_prediction = ini_prediction.detach().numpy()
  202. y_label = y_label.detach().numpy()
  203. # 预测数据反归一化(厘米级)
  204. GABP_prediction = GABP_prediction * fanshu
  205. BP_prediction = BP_prediction * fanshu
  206. y_label = y_label * fanshu
  207. # 计算预测结果的SSE误差
  208. def get_MSE(argu1, argu2):
  209. if len(argu1) != len(argu2):
  210. return 0
  211. error = 0
  212. for i in range(len(argu1)):
  213. error = error + pow((argu1[i] - argu2[i]), 2)
  214. error = float(error[0])
  215. return round(error, 5)
  216. error_BP = get_MSE(y_label, BP_prediction)
  217. error_GA_BP = get_MSE(y_label, GABP_prediction)
  218. print("BP算法预测MSE误差为:", error_BP)
  219. print("GA-BP算法预测MSE误差为:", error_GA_BP)
  220. # 将巡行情况和运行结果写入日志
  221. f = open("log.txt",'a',encoding='UTF-8') # 追加写打开文件
  222. f.write("运行时间:" + str(time.ctime()) + '\n')
  223. f.write("训练数据长度为:" + str(train_num) + '\n'
  224. + "测试数据长度为:" + str(test_num) + '\n')
  225. f.write("网络结构层数为:{}、{}、{}\n".format(n_feature,n_hidden,n_output))
  226. f.write("遗传迭代所获得的最优权值为:" + str(best_code) + "\n")
  227. f.write("======预测结果如下======\n真值数据为:" + str(y_label.flatten()) + '\n')
  228. f.write("BP预测结果为:" + str(BP_prediction.flatten()) + "\n"
  229. + "GA-BP预测结果为:" + str(GABP_prediction.flatten()) + '\n')
  230. f.write("-->>BP预测MSE误差为:" + str(error_BP) + '平方厘米\n'
  231. + "-->>GA-BP预测MSE误差为:" + str(error_GA_BP) + '平方厘米\n\n')
  232. f.close()
  233. # 预测绘图
  234. test_name_ls = name_ls[126:152]
  235. xlabel2 = [i for i in range(0, 26, 4)]
  236. f3 = plt.figure()
  237. plt.plot(y_label, markersize=4, marker='.', label="真值", c='r')
  238. plt.plot(GABP_prediction, markersize=4, marker='*', label="GA-BP预测值", c='b')
  239. plt.plot(BP_prediction, markersize=4, marker='^', label="BP预测值", c='g')
  240. plt.title("算法预测情况对比")
  241. plt.ylabel("累计裂缝宽度(mm)")
  242. plt.xticks(xlabel2, [test_name_ls[i] for i in xlabel2], rotation=20)
  243. plt.legend()
  244. plt.grid(linestyle='-.')
  245. f4 = plt.figure()
  246. plt.plot(y_label, markersize=4, marker='.', label="真值", c='r')
  247. plt.plot(BP_prediction, markersize=4, marker='^', label="BP预测值", c='g')
  248. plt.title("BP算法预测情况")
  249. plt.ylabel("累计裂缝宽度(mm)")
  250. plt.xticks(xlabel2, [test_name_ls[i] for i in xlabel2], rotation=20)
  251. plt.legend()
  252. plt.grid(linestyle='-.')
  253. f5 = plt.figure()
  254. plt.plot(y_label, markersize=4, marker='.', label="真值", c='r')
  255. plt.plot(GABP_prediction, markersize=4, marker='*', label="GA-BP预测值", c='b')
  256. plt.title("GA-BP算法预测情况")
  257. plt.ylabel("累计裂缝宽度(mm)")
  258. plt.xticks(xlabel2, [test_name_ls[i] for i in xlabel2], rotation=20)
  259. plt.legend()
  260. plt.grid(linestyle='-.')
  261. plt.show()

对比结果确实有提升:

 资源获取:

链接:https://pan.baidu.com/s/1ZiqgN98bhnyEdoQxuDB3SQ?pwd=ervf 
提取码:ervf 
--来自百度网盘超级会员V4的分享


才疏学浅,水平有限。敬请批评指正!

共勉!


标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

在线投稿:投稿 站长QQ:1888636

后台-插件-广告管理-内容页尾部广告(手机)
关注我们

扫一扫关注我们,了解最新精彩内容

搜索
排行榜