深度学习与遗传算法的碰撞——利用遗传算法优化深度学习网络结构(详解与实现)

简介: 本文使用MNIST数据集和Tensorflow构建简单的全连接网络,利用遗传算法优化隐藏层数和每层的节点数,使用的原理同样适用于更复杂的网络和数据集。

前言

近年来,深度学习模型性能取得了飞跃,可以在单个网络中使用大量隐藏层。训练深度学习模型可能会占用大量计算资源,并且通常在图形处理单元(GPU)上进行,同时为了获得最优的模型性能,可能需要网络架构和超参数的反复修改和调整,通常此过程取决于实际问题和网络架构设计人员的经验,而利用遗传算法可以将此过程自动化,同时可以在可接受的时间开销内找到更好的网络架构。专门的深度学习库,例如 TensorFlow,能够利用基于 GPU 的计算平台,本文使用 MNIST 数据集和 Tensorflow 构建简单的全连接网络,利用遗传算法优化隐藏层数和每层的节点数。虽然全连接网络是十分基础简单的网络,但是,使用的原理同样适用于更复杂的网络和数据集。

以下是所用库:

  1. tensorflow2.x
  2. deap
  3. matplotlib

优化深度学习分类器的架构

在创建神经网络模型可以执行给定的机器学习任务时,一项关键工作是设计网络体系结构的配置。对于多层感知器,输入层和输出层中的节点数取决于当前问题的特征。因此,要做出的选择是关于隐藏层——有多少层以及每层有多少个节点。可以采用一些经验进行尝试,但是在多数情况下,确定最佳架构可能需要反复试验。

处理网络体系结构参数的一种方法是将它们视为模型的超参数,使用这些超参数构建网络,并将训练后网络的性能作为适应度进行评价。接下来,将使用遗传算法找到隐藏层的最佳组合。

20210106143317224.png

隐藏层配置的染色体表示

由于 MLP 的体系结构由隐藏层配置决定,在 tensorflow.keras 中可通过改变 Dense 层的 units 参数获得节点数不同的全连接隐藏层:

Dense(units, activation=None,...)

同时,可以通过 for 来构建所需层数,例如,如果要为 MLP 配置三个有 20 个节点的隐藏层,则可以通过以下方式:

self.model=Sequential()
forlinrange(3):  
self.model.add(layers.Dense(20,activation='relu'))

因此,我们需要提出既可以表示层数又可以表示每一层节点数的染色体。

同时,为了能够使用标准遗传算子,使用固定长度的染色体表示形式。使用这种方法时,预先确定最大层数,但为了层数可变,可以在染色体中设置无效位(也可以称为终止参数),使模型构建提前终止。例如,将网络限制为四个隐藏层,则染色体将如下所示:

[n1, n2, n3, n4]

其中,ni 表示 i 层中的节点数。

为了控制网络中隐藏层的实际数量,其中一些值可能为零或负数。该值意味着之后不会再有其他层添加到网络:

1. 染色体 [10, 20, -5, 15] 表示元组 (10, 20),因为 -5 是无效位。

2. 染色体 [10, 0, -5, 15] 表示元组 (10, ),因为 0 是无效位。

3. 染色体 [10, 20, 5, -15] 表示元组 (10, 20, 5),因为 -15 是无效位。

4. 染色体 [10, 20, 5, 15] 表示元组 (10, 20, 5, 15)。

为了保证至少有一个隐藏层,可以强制第一个参数始终大于零。其他层参数可以在零附近分布,以便可以控制它们成为终止参数。

另外,由于染色体中值有限定区间,可以选择使用浮点数列表构建染色体。使用浮点数列表使我们能够使用现有的遗传算子。为了构建网络可以使用round()函数可以将浮点数转换回整数:

1. 染色体 [9.35, 10.71, -2.51, 17.99] 可以转化为元组 (9, 11)

2. 染色体 [9.35, 10.71, 2.51, -17.99] 可以转化为元组 (9, 11, 3)

要评估构建的网络结构,需要创建实现这些层的 MLP 分类器,对其进行训练并进行评估。

评估个体的适应度得分

MLPLayers 类封装了 MNIST 数据集的 MLP 分类器的构建以及模型准确率的评估。

MLPLayers 类主要包括以下方法:

1. preprocess(self,x,y) 用于构建训练数据集的预处理

2. initDataset(self) 用于构建训练数据集

3. convertParams(self,params) 将 params 的列表转换为可以有效构建模型的元组

4. getAccuracy(self,params) 构建模型,训练,并返回最后一个 epoch 的验证准确率,用于适应度评估。

5. testLayer(self),使用经验值构建的分类模型,用于和优化得到的网络进行对比

6. formatParams(self, params) 用于格式化输出染色体

classMLPLayers:
def__init__(self):
self.initDataset()
defpreprocess(self,x,y):
x=tf.reshape(x, [-1])  
returnx,ydefinitDataset(self):
        (self.X_train,self.y_train),(self.X_test,self.y_test) =datasets.mnist.load_data()
self.X_train=tf.convert_to_tensor(self.X_train,dtype=tf.float32) /255.self.X_test=tf.convert_to_tensor(self.X_test,dtype=tf.float32) /255.self.y_train=tf.convert_to_tensor(self.y_train,dtype=tf.int32)
self.y_test=tf.convert_to_tensor(self.y_test,dtype=tf.int32)
self.y_train=tf.one_hot(self.y_train,depth=10)
self.y_test=tf.one_hot(self.y_test,depth=10)
self.train_db=tf.data.Dataset.from_tensor_slices((self.X_train,self.y_train))
self.validation_db=tf.data.Dataset.from_tensor_slices((self.X_test,self.y_test))
self.train_db=self.train_db.shuffle(1000).map(self.preprocess).batch(128)
self.validation_db=self.validation_db.shuffle(1000).map(self.preprocess).batch(128)
defconvertParams(self,params):
ifround(params[1]) <=0:
hiddenLayerSizes=round(params[0]),
elifround(params[2]) <=0:
hiddenLayerSizes= (round(params[0]), round(params[1]))
elifround(params[3]) <=0:
hiddenLayerSizes= (round(params[0]), round(params[1]), round(params[2]))
else:
hiddenLayerSizes= (round(params[0]), round(params[1]), round(params[2]), round(params[3]))
returnhiddenLayerSizesdefgetAccuracy(self,params):
#将染色体转化为可以有效构建网络的元组hiddenLayerSizes=self.convertParams(params)
self.model=Sequential()
#构建网络forlinhiddenLayerSizes:
self.model.add(layers.Dense(l,activation='relu'))
self.model.add(layers.Dense(10,activation='relu'))
self.model.build(input_shape=(4,28*28))
self.model.summary()
self.model.compile(optimizer=optimizers.Adam(lr=0.01),
loss=losses.CategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
# 指定训练集为db,验证集为val_db,训练5个epochs,每1个epoch验证一次history=self.model.fit(self.train_db, epochs=5, validation_data=self.validation_db, validation_freq=1,verbose=2)
#返回最后一个epoch训练后的验证准确率,用于适应度评估returnhistory.history['val_accuracy'][-1]
deftestLayer(self):
# 创建5层的全连接层网络network=Sequential([layers.Dense(256, activation='relu'),
layers.Dense(128, activation='relu'),
layers.Dense(64, activation='relu'),
layers.Dense(32, activation='relu'),
layers.Dense(10)])
network.build(input_shape=(4, 28*28))
network.summary()
# 采用Adam优化器,学习率为0.01;采用交叉熵损失函数,包含Softmaxnetwork.compile(optimizer=optimizers.Adam(lr=0.01),
loss=losses.CategoricalCrossentropy(from_logits=True),
metrics=['accuracy'] # 设置测量指标为准确率        )
# 指定训练集为db,验证集为val_db,训练5个epochs,每1个epoch验证一次history=network.fit(self.train_db, epochs=5, validation_data=self.validation_db, validation_freq=1,verbose=2)
#打印结果print(history.history['val_accuracy'][-1])
defformatParams(self, params):
return"'hidden_layer_sizes'={}".format(self.convertParams(params))

使用遗传算法优化MLP架构

现在,我们已经有了 MLP 的体系结构配置,以及确定每种配置的 MLP 准确率的方法,接下来,创建基于遗传算法的优化程序以对配置进行搜索——隐藏层的数量以及每层中的节点数量——产生最佳分类准确率。

详细的步骤在注释中进行介绍:

#创建MlpLayersTest类的实例,用于测试隐藏层架构的各种组合test=MLPLayers()
# 首先为代表隐藏层的每个float值设置上下边界。第一个隐藏层的范围为[100,300],而其余的层则从负值开始,增加终止层数的机会:BOUNDS_LOW= [100,-25,-50,-75]
BOUNDS_HIGH= [300,200,100,50]
NUM_OF_PARAMS=len(BOUNDS_LOW)
#超参数:POPULATION_SIZE=50P_CROSSOVER=0.9P_MUTATION=0.5MAX_GENERATIONS=20HALL_OF_FAME_SIZE=5CROWDING_FACTOR=10.0toolbox=base.Toolbox()
#定义最大化适用度策略:creator.create("FitnessMax",base.Fitness,weights=(1.0,))
#基于列表创建个体类:creator.create("Individual",list,fitness=creator.FitnessMax)
#由于解由一系列不同区间的浮点值表示,因此我们使用以下循环并为每个区间创建一个单独的toolbox运算符(layer_size_attribute),用于在适当范围内生成随机浮点值:foriinrange(NUM_OF_PARAMS):
#"layer_size_attribute_0","layer_size_attribute_1"...toolbox.register("layer_size_attribute_"+str(i),
random.uniform,
BOUNDS_LOW[i],
BOUNDS_HIGH[i])
#创建layer_size_attributes元组,其中包含我们刚刚为每个隐藏层创建的单独的浮点数生成器:layer_size_attributes= ()
foriinrange(NUM_OF_PARAMS):
layer_size_attributes=layer_size_attributes+ (toolbox.__getattribute__("layer_size_attribute_"+str(i)),)
#将此layer_size_attributes元组与DEAP的内置initCycle()运算符结合使用,以创建一个新的individualCreator运算符,该运算符将随机生成的隐藏层值组合起来填充单个实例toolbox.register("individualCreator",tools.initCycle,creator.Individual,layer_size_attributes,n=1)
#定义种群创建运算符:toolbox.register("populationCreator",tools.initRepeat,list,toolbox.individualCreator)
#使用类的getAccuracy()方法进行适应度评估defclassificationAccuracy(individual):
returntest.getAccuracy(individual),
toolbox.register("evaluate",classificationAccuracy)
#遗传算子定义:对于选择运算符,使用锦标赛大小为2的锦标赛选择,使用专门用于有界浮动列表染色体的交叉和变异运算符,并为它们提供定义的上下限:toolbox.register("select",tools.selTournament,tournsize=2)
toolbox.register("mate",tools.cxSimulatedBinaryBounded,low=BOUNDS_LOW,up=BOUNDS_HIGH,eta=CROWDING_FACTOR)
toolbox.register("mutate",tools.mutPolynomialBounded,low=BOUNDS_LOW,up=BOUNDS_HIGH,eta=CROWDING_FACTOR,indpb=1.0/NUM_OF_PARAMS)

带精英主义策略的遗传流程函数

使用名人堂可以用来保留进化过程中种群中曾经存在的最佳个体,并不会由于选择,交叉或变异而失去了它们,HallOfFame 类在 tools 模块中实现。

将Halloffame对象用于实现精英主义。 Halloffame对象中包含的个体被直接注入下一代,并且不受选择,交叉和突变的遗传算子的影响。

遗传流程

defmain():
#创建初始种群:population=toolbox.populationCreator(n=POPULATION_SIZE)
#注册要监听的统计数据:stats=tools.Statistics(lambdaind:ind.fitness.values)
stats.register("max",np.max)
stats.register("avg",np.mean)
#定义名人堂对象:hof=tools.HallOfFame(HALL_OF_FAME_SIZE)
#使用精英主义策略执行遗传流程:population,logbook=eaSimpleWithElitism(population,toolbox,
cxpb=P_CROSSOVER,mutpb=P_MUTATION,
ngen=MAX_GENERATIONS,
stats=stats,halloffame=hof,verbose=True)
# 打印找到的最佳解:print("- Best solution is: ",test.formatParams(hof.items[0]),", accuracy = ",hof.items[0].fitness.values[0])
# 获取统计数据:maxFitnessValues, meanFitnessValues=logbook.select("max", "avg")
if__name__=="__main__":
main()

结果分析

查看找到的最佳解

- Best solution is:  'hidden_layer_sizes'=(135,) , accuracy =0.9731000065803528

可以到,仅使用一层具有 135 个节点的隐藏层,准确率就达到了 97.31.

算法运行过程中统计结果如下:

绘图98.png

而依靠经验设计的网络结构及其准确率如下

Layer (type)                 Output Shape              Param #    =================================================================dense_2812 (Dense)           (4, 256)                  200960_________________________________________________________________
dense_2813 (Dense)           (4, 128)                  32896_________________________________________________________________
dense_2814 (Dense)           (4, 64)                   8256_________________________________________________________________
dense_2815 (Dense)           (4, 32)                   2080_________________________________________________________________
dense_2816 (Dense)           (4, 10)                   330=================================================================Total params: 244,522
Trainable params: 244,522
Non-trainable params: 0...
469/469 - 1s - loss: 0.0911 - accuracy: 0.9754 - val_loss: 0.1547 - val_accuracy: 0.9653

可以看出,相比于精心设计的网络结构,遗传算法得到的网络结构,在 MNIST 数据集上有更高的准确率,虽然提升并不十分明显,但是考虑到:MNIST 数据集较简单,以及相比精心设计的网络的参数量(244522),遗传算法找到的最佳解的参数量仅为 107335(28*28*135+135*10+135+10),参数量减少一倍以上,可以说遗传算法的优化已经达到预期。可以通过将更多超参数加入遗传算法优化的列表中,查看不同效果。

相关文章
|
9天前
|
算法
基于遗传优化算法的风力机位置布局matlab仿真
本项目基于遗传优化算法(GA)进行风力机位置布局的MATLAB仿真,旨在最大化风场发电效率。使用MATLAB2022A版本运行,核心代码通过迭代选择、交叉、变异等操作优化风力机布局。输出包括优化收敛曲线和最佳布局图。遗传算法模拟生物进化机制,通过初始化、选择、交叉、变异和精英保留等步骤,在复杂约束条件下找到最优布局方案,提升风场整体能源产出效率。
|
9天前
|
机器学习/深度学习 数据采集 算法
基于WOA鲸鱼优化的CNN-GRU-SAM网络时间序列回归预测算法matlab仿真
本项目基于MATLAB 2022a实现时间序列预测,采用CNN-GRU-SAM网络结构,结合鲸鱼优化算法(WOA)优化网络参数。核心代码含操作视频,运行效果无水印。算法通过卷积层提取局部特征,GRU层处理长期依赖,自注意力机制捕捉全局特征,全连接层整合输出。数据预处理后,使用WOA迭代优化,最终输出最优预测结果。
|
1天前
|
机器学习/深度学习 数据采集 算法
基于GA遗传优化的CNN-LSTM-SAM网络时间序列回归预测算法matlab仿真
本项目使用MATLAB 2022a实现时间序列预测算法,完整程序无水印。核心代码包含详细中文注释和操作视频。算法基于CNN-LSTM-SAM网络,融合卷积层、LSTM层与自注意力机制,适用于金融市场、气象预报等领域。通过数据归一化、种群初始化、适应度计算及参数优化等步骤,有效处理非线性时间序列,输出精准预测结果。
|
10天前
|
传感器 算法
基于GA遗传算法的多机无源定位系统GDOP优化matlab仿真
本项目基于遗传算法(GA)优化多机无源定位系统的GDOP,使用MATLAB2022A进行仿真。通过遗传算法的选择、交叉和变异操作,迭代优化传感器配置,最小化GDOP值,提高定位精度。仿真输出包括GDOP优化结果、遗传算法收敛曲线及三维空间坐标点分布图。核心程序实现了染色体编码、适应度评估、遗传操作等关键步骤,最终展示优化后的传感器布局及其性能。
|
7天前
|
存储 算法 数据可视化
Weevil-Optimizer象鼻虫优化算法的matlab仿真实现
本项目实现了Weevil-Optimizer(象鼻虫优化算法)的MATLAB仿真,展示算法在不同适应度函数下的优化收敛曲线。程序通过智能搜索策略模拟象鼻虫觅食行为,在解空间中寻找最优解。核心代码包括排序、选择、更新操作,并绘制结果图示。测试环境为MATLAB 2022A,支持Ackley、Beale、Booth、Rastrigin和Rosenbrock函数的对比分析。 虽然Weevil-Optimizer是一个虚构的概念,但其设计思路展示了如何基于自然界生物行为模式开发优化算法。完整程序运行后无水印,提供清晰的可视化结果。
|
10天前
|
机器学习/深度学习 运维 资源调度
深度学习在资源利用率优化中的应用:让服务器更聪明
深度学习在资源利用率优化中的应用:让服务器更聪明
42 6
|
2月前
|
SQL 安全 网络安全
网络安全与信息安全:知识分享####
【10月更文挑战第21天】 随着数字化时代的快速发展,网络安全和信息安全已成为个人和企业不可忽视的关键问题。本文将探讨网络安全漏洞、加密技术以及安全意识的重要性,并提供一些实用的建议,帮助读者提高自身的网络安全防护能力。 ####
90 17
|
2月前
|
存储 SQL 安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
随着互联网的普及,网络安全问题日益突出。本文将介绍网络安全的重要性,分析常见的网络安全漏洞及其危害,探讨加密技术在保障网络安全中的作用,并强调提高安全意识的必要性。通过本文的学习,读者将了解网络安全的基本概念和应对策略,提升个人和组织的网络安全防护能力。
|
2月前
|
SQL 安全 网络安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
随着互联网的普及,网络安全问题日益突出。本文将从网络安全漏洞、加密技术和安全意识三个方面进行探讨,旨在提高读者对网络安全的认识和防范能力。通过分析常见的网络安全漏洞,介绍加密技术的基本原理和应用,以及强调安全意识的重要性,帮助读者更好地保护自己的网络信息安全。
64 10
|
2月前
|
SQL 安全 网络安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
在数字化时代,网络安全和信息安全已成为我们生活中不可或缺的一部分。本文将介绍网络安全漏洞、加密技术和安全意识等方面的内容,并提供一些实用的代码示例。通过阅读本文,您将了解到如何保护自己的网络安全,以及如何提高自己的信息安全意识。
76 10

热门文章

最新文章