当前位置:   article > 正文

(python)GA(遗传算法)优化LSTM神经网络(亲测成功,速度慢)_ga优化lstm

ga优化lstm

1.项目概述
本文采用的是python编程,使用的数据集是mnist手写数据集,该数据集主要是对0-9的手写数字体识别,虽然说图像识别方面用CNN识别率较高,但这里LSTM也可以获取较高的准确率。

2.优化参数
本文优化的是LSTM的层数参数和各层神经元参数,其中包含了lstm层和Dense层,其中我们规定了神经网络的层数不超过3层,每层的神经元个数在[32,256]之间。

3.注意事项
1.本文的遗传算法编码并非2进制编码,而是由各个参数组成的一维数组。
2.在遗传算法交叉、变异操作中,关于神经网络层数的参数不进行交叉,只对神经网神经元个数进行交叉、变异。
3.文件为两部分每一部分为lstm的部分,一部分为ga部分

LSTM部分

  1. #本章节GA_LSTM是关于遗传算法优化lstm算法的层数和全连接层数及每层神经元的个数
  2. import numpy as np
  3. import pandas as pd
  4. import tensorflow as tf
  5. import matplotlib as plt
  6. from tensorflow.keras.layers import Input,LSTM,Dropout,Dense,BatchNormalization
  7. from tensorflow.keras import optimizers,losses,metrics,models,Sequential
  8. '''
  9. 本文的主要内容如下:
  10. 1.本文章是对lstm网络的优化,优化的参数主要有:lstm层的层数,lstm隐藏层的神经元个数,dense层的层数,dense层的神经元个数
  11. 2.本文章利用的是遗传算法进行优化,其中编码形式并未采用2进制编码,只是将2数组之间的元素交换位置。
  12. 3.本文的lstm和dense的层数都在1-3的范围内,因为3层的网络足以拟合非线性数据
  13. 4.程序主要分为2部分,第一部分是lstm网络的设计,第二部分是遗传算法的优化。
  14. 5.代码的解释已详细写在对应的部分,有问题的同学可以在评论区进行交流
  15. '''
  16. #导入数据集,本文用的是mnist手写数据集,该数据主要是对手写体进行识别0-9的数字
  17. def load_data():
  18. #从tensorflow自带的数据集中导入数据
  19. (x_train,y_train),(x_test,y_test)=tf.keras.datasets.mnist.load_data()
  20. #主要进行归一化操作
  21. x_train, x_test = x_train / 255.0, x_test / 255.0
  22. return x_train,x_test,y_test,y_train
  23. #定义LSTM模型
  24. def lstm_mode(inputs, units_num, sequences_state):
  25. #input主要是用来定义lstm的输入,input的一般是在第一层lstm层之前,units_num即是隐藏层神经元个数,sequence_state即是lstm层输出的方式
  26. lstm=LSTM(units_num,return_sequences=sequences_state)(inputs)
  27. print("lstm:",lstm.shape)
  28. return lstm
  29. #定义全连接层、BN层
  30. def dense_mode(input,units_num):
  31. #这里主要定义全连接层的输入,input参数定义dense的第一次输入,units_num代表隐藏层神经元个数
  32. #这里定义全连接层,采用L2正则化来防止过拟合,激活函数为relu
  33. dense=Dense(units_num,kernel_regularizer=tf.keras.regularizers.l2(0.001),activation='relu')(input)
  34. print("dense:",dense.shape)
  35. #定义dropout层,概率为0.2
  36. drop_out=Dropout(rate=0.2)(dense)
  37. #定义BN层,可以理解为是隐藏层的标准化过程
  38. dense_bn=BatchNormalization()(drop_out)
  39. return dense,drop_out,dense_bn
  40. #这里定义的即是评价lstm效果的函数——也是遗传算法的适应度函数
  41. def aim_function(x_train,y_train,x_test,y_test,num):
  42. #这里传入数据和参数数组num,num保存了需要优化的参数
  43. #这里我们设置num数组中num[0]代表lstm的层数。
  44. lstm_layers=num[0]
  45. #num[2:2 + lstm_layers]分别为lstm各层的神经元个数,有同学不知道num(1)去哪了(num(1)为全连接层的层数)
  46. lstm_units = num[2:2 + lstm_layers]
  47. #将num
  48. lstm_name = list(np.zeros((lstm_layers,)))
  49. # 设置全连接层的参数
  50. #num(1)为全连接的参数
  51. lstm_dense_layers = num[1]
  52. #将lstm层之后的地方作为全连接层各层的参数
  53. lstm_dense_units = num[2 + lstm_layers: 2 + lstm_layers + lstm_dense_layers]
  54. #
  55. lstm_dense_name = list(np.zeros((lstm_dense_layers,)))
  56. lstm_dense_dropout_name = list(np.zeros((lstm_dense_layers,)))
  57. lstm_dense_batch_name = list(np.zeros((lstm_dense_layers,)))
  58. #这主要是定义lstm的第一层输入,形状为训练集数据的形状
  59. inputs_lstm = Input(shape=(x_train.shape[1], x_train.shape[2]))
  60. #这里定义lstm层的输入(如果为第一层lstm层,则将初始化的input输入,如果不是第一层,则接受上一层输出的结果)
  61. for i in range(lstm_layers):
  62. if i == 0:
  63. inputs = inputs_lstm
  64. else:
  65. inputs = lstm_name[i - 1]
  66. if i == lstm_layers - 1:
  67. sequences_state = False
  68. else:
  69. sequences_state = True
  70. #通过循环,我们将每层lstm的参数都设计完成
  71. lstm_name[i] = lstm_mode(inputs, lstm_units[i], sequences_state=sequences_state)
  72. #同理设计全连接层神经网络的参数
  73. for i in range(lstm_dense_layers):
  74. if i == 0:
  75. inputs = lstm_name[lstm_layers - 1]
  76. else:
  77. inputs = lstm_dense_name[i - 1]
  78. lstm_dense_name[i], lstm_dense_dropout_name[i], lstm_dense_batch_name[i] = dense_mode(inputs,units_num=lstm_dense_units[i])
  79. #这里是最后一层:分类层,softmax
  80. outputs_lstm = Dense(10, activation='softmax')(lstm_dense_batch_name[lstm_dense_layers - 1])
  81. print("last_dense",outputs_lstm.shape)
  82. # 利用函数式调试神经网络,调用inputs和outputs之间的神经网络
  83. LSTM_model =tf.keras.Model(inputs=inputs_lstm, outputs=outputs_lstm)
  84. # 编译模型
  85. LSTM_model.compile(optimizer=optimizers.Adam(),
  86. loss='sparse_categorical_crossentropy',
  87. metrics=['accuracy'])
  88. print("训练集形状",x_train.shape)
  89. history = LSTM_model.fit(x_train, y_train,batch_size=32, epochs=1, validation_split=0.1, verbose=1)
  90. # 验证模型,model.evaluate返回的值是一个数组,其中score[0]为loss,score[1]为准确度
  91. acc = LSTM_model.evaluate(x_test, y_test, verbose=0)
  92. return acc[1]

GA优化部分

  1. #GA优化lstm的遗传算法部分
  2. import GA_LSTM_lstm as ga
  3. import numpy as np
  4. import pandas as pd
  5. import matplotlib as plt
  6. import os
  7. #不显示警告信息
  8. os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
  9. #设置遗传算法的参数
  10. DNA_size = 2
  11. DNA_size_max = 8 # 每条染色体的长度
  12. POP_size = 20 # 种群数量
  13. CROSS_RATE = 0.5 # 交叉率
  14. MUTATION_RATE = 0.01# 变异率
  15. N_GENERATIONS = 40 # 迭代次数
  16. #接收数据
  17. x_train,x_test,y_test,y_train = ga.load_data()
  18. # 定义适用度函数,即aim_function函数,接收返回值
  19. def get_fitness(x):
  20. return ga.aim_function(x_train,y_train,x_test,y_test,num=x)
  21. # 生成新的种群
  22. def select(pop,fitness):
  23. #这里主要是进行选择操作,即从20个种群中随机选取重复随机采样出20个种群进行种群初始化操作,p代表被选择的概率,这里采用的是轮盘赌的方式
  24. idx = np.random.choice(np.arange(POP_size),size=POP_size,replace=True,p=fitness/fitness.sum())
  25. #将选择的种群组成初始种群pop
  26. return pop[idx]
  27. # 交叉函数
  28. def crossover(parent,pop):
  29. #这里主要进行交叉操作,随机数小于交叉概率则发生交叉
  30. if np.random.rand() < CROSS_RATE:
  31. #从20个种群中选择一个种群进行交叉
  32. i_ = np.random.randint(0,POP_size,size=1) # 染色体的序号
  33. #这里将生成一个8维的2进制数,并转换层成bool类型,true表示该位置交叉,False表示不交叉
  34. cross_points = np.random.randint(0,2,size=DNA_size_max).astype(np.bool) # 用TrueFalse表示是否置换
  35. # 这一部分主要是对针对不做变异的部分
  36. for i,point in enumerate(cross_points):
  37. '''
  38. 第一部分:这里是指该位点为神经元个数的位点,本来该交换,但其中位点为0,
  39. 什么意思呢?即[2,3,32,43,34,230,43,46,67]和[2,2,32,54,55,76,74,26,0],末尾的0位置就
  40. 不应该交叉,因为交叉完后,会对前两位的参数产生影响。
  41. 第二部分:即对前两位不进行交叉操作,因为前两位代表的是层数,层数交叉后会对神经元的个数产生影响
  42. '''
  43. #第一部分
  44. if point == True and pop[i_,i] * parent[i] == 0:
  45. cross_points[i] = False
  46. #第二部分
  47. if point == True and i < 2:
  48. cross_points[i] = False
  49. # 将第i_条染色体上对应位置的基因置换到parent染色体上
  50. parent[cross_points] = pop[i_,cross_points]
  51. return parent
  52. # 定义变异函数
  53. def mutate(child):
  54. #变异操作也只是针对后6位参数
  55. for point in range(DNA_size_max):
  56. if np.random.rand() < MUTATION_RATE:
  57. #2位参数之后的参数才才参与变异
  58. if point >= 2:
  59. if child[point] != 0:
  60. child[point] = np.random.randint(32,257)
  61. return child
  62. #初始化2列层数参数
  63. pop_layers = np.zeros((POP_size,DNA_size),np.int32)
  64. pop_layers[:,0] = np.random.randint(1,4,size=(POP_size,))
  65. pop_layers[:,1] = np.random.randint(1,4,size=(POP_size,))
  66. # 种群
  67. #初始化20x8的种群
  68. pop = np.zeros((POP_size,DNA_size_max))
  69. # 将初始化的种群赋值,前两列为层数参数,后6列为神经元个数参数
  70. for i in range(POP_size):
  71. #随机从[32,256]中抽取随机数组组成神经元个数信息
  72. pop_neurons = np.random.randint(32,257,size=(pop_layers[i].sum(),))
  73. #将2列层数信息和6列神经元个数信息合并乘8维种群信息
  74. pop_stack = np.hstack((pop_layers[i],pop_neurons))
  75. #将这些信息赋值给pop种群进行初始化种群
  76. for j,gene in enumerate(pop_stack):
  77. pop[i][j] = gene
  78. # 在迭代次数内,计算种群的适应度函数
  79. for each_generation in range(N_GENERATIONS):
  80. # 初始化适应度
  81. fitness = np.zeros([POP_size,])
  82. # 遍历20个种群,对基因进行操作
  83. for i in range(POP_size):
  84. pop_list = list(pop[i])
  85. # 第i个染色体上的基因
  86. #对赋值为0的基因进行删除
  87. for j,each in enumerate(pop_list):
  88. if each == 0.0:
  89. index = j
  90. pop_list = pop_list[:j]
  91. #将基因进行转换为int类型
  92. for k,each in enumerate(pop_list):
  93. each_int = int(each)
  94. pop_list[k] = each_int
  95. #将计算出来的适应度填写在适应度数组中
  96. fitness[i] = get_fitness(pop_list)
  97. #输出结果
  98. print('第%d代第%d个染色体的适应度为%f'%(each_generation+1,i+1,fitness[i]))
  99. print('此染色体为:',pop_list)
  100. print('Generation:',each_generation+1,'Most fitted DNA:',pop[np.argmax(fitness),:],'适应度为:',fitness[np.argmax(fitness)])
  101. # 生成新的种群
  102. pop = select(pop,fitness)
  103. # 复制一遍种群
  104. pop_copy = pop.copy()
  105. #遍历pop中的每一个种群,进行交叉,变异,遗传操作
  106. for parent in pop:
  107. child = crossover(parent,pop_copy)
  108. child = mutate(child)
  109. parent = child

运行结果如下

  1. 1688/1688 [==============================] - 21s 10ms/step - loss: 0.7340 - accuracy: 0.8076 - val_loss: 0.1616 - val_accuracy: 0.9730
  2. 1代第1个染色体的适应度为0.966900
  3. 此染色体为: [1, 1, 151, 248]
  4. lstm: (None, 83)
  5. dense: (None, 200)
  6. last_dense (None, 10)
  7. 训练集形状 (60000, 28, 28)
  8. 1688/1688 [==============================] - 19s 10ms/step - loss: 0.7532 - accuracy: 0.7855 - val_loss: 0.1744 - val_accuracy: 0.9672
  9. 1代第2个染色体的适应度为0.961300
  10. 此染色体为: [1, 1, 83, 200]
  11. lstm: (None, 28, 135)
  12. lstm: (None, 28, 41)
  13. lstm: (None, 126)
  14. dense: (None, 47)
  15. last_dense (None, 10)
  16. 训练集形状 (60000, 28, 28)
  17. 1688/1688 [==============================] - 33s 17ms/step - loss: 0.7534 - accuracy: 0.7755 - val_loss: 0.1258 - val_accuracy: 0.9717
  18. 1代第3个染色体的适应度为0.967800
  19. 此染色体为: [3, 1, 135, 41, 126, 47]
  20. lstm: (None, 28, 247)
  21. lstm: (None, 28, 82)
  22. lstm: (None, 71)
  23. dense: (None, 190)
  24. dense: (None, 161)
  25. dense: (None, 124)
  26. last_dense (None, 10)
  27. 训练集形状 (60000, 28, 28)

欢迎点赞 收藏 加关注

参考链接:

python深度学习之GA(遗传算法)优化LSTM神经网络_柳小葱的博客-CSDN博客_lstm优化上次优化完bp神经网络后,发现用matlab优化高级的神经网络太慢了,于是用tensorflow继续学习GA优化部分。1.项目概述本文采用的是python编程,使用的数据集是mnist手写数据集,该数据集主要是对0-9的手写数字体识别,虽然说图像识别方面用CNN识别率较高,但这里LSTM也可以获取较高的准确率。2.优化参数本文优化的是LSTM的层数参数和各层神经元参数,其中包含了lstm层和Dense层,其中我们规定了神经网络的层数不超过3层,每层的神经元个数在[32,256]之间。3.注意事项https://liuxiaocong.blog.csdn.net/article/details/114830709?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-2.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-2.no_search_link&utm_relevant_index=5

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/167953
推荐阅读
相关标签
  

闽ICP备14008679号