深度学习与遗传算法的碰撞——利用遗传算法优化深度学习网络结构(详解与实现)
Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照下面的知识点去找对应的学习资源,保证自己学得较为全面。工具都帮大家整理好了,安装就可直接上手!当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。观看全面零基础学习视频,看视频学习是最快捷也
一、Python所有方向的学习路线
Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照下面的知识点去找对应的学习资源,保证自己学得较为全面。


二、Python必备开发工具
工具都帮大家整理好了,安装就可直接上手!
三、最新Python学习笔记
当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。

四、Python视频合集
观看全面零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

五、实战案例
纸上得来终觉浅,要学会跟着视频一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
六、面试宝典


简历模板
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
-
- 前言
-
优化深度学习分类器的架构
-
隐藏层配置的染色体表示
-
评估个体的适应度得分
-
使用遗传算法优化MLP架构
-
- 带精英主义策略的遗传流程函数
-
遗传流程
-
结果分析
近年来,深度学习模型性能取得了飞跃,可以在单个网络中使用大量隐藏层。训练深度学习模型可能会占用大量计算资源,并且通常在图形处理单元(GPU)上进行,同时为了获得最优的模型性能,可能需要网络架构和超参数的反复修改和调整,通常此过程取决于实际问题和网络架构设计人员的经验,而利用遗传算法可以将此过程自动化,同时可以在可接受的时间开销内找到更好的网络架构。专门的深度学习库,例如TensorFlow,能够利用基于GPU的计算平台,本文使用MNIST数据集和Tensorflow构建简单的全连接网络,利用遗传算法优化隐藏层数和每层的节点数。虽然全连接网络是十分基础简单的网络,但是,使用的原理同样适用于更复杂的网络和数据集。
以下是所用库:
-
tensorflow2.x
-
deap
-
matplotlib
在创建神经网络模型可以执行给定的机器学习任务时,一项关键工作是设计网络体系结构的配置。对于多层感知器,输入层和输出层中的节点数取决于当前问题的特征。因此,要做出的选择是关于隐藏层——有多少层以及每层有多少个节点。可以采用一些经验进行尝试,但是在多数情况下,确定最佳架构可能需要反复试验。
处理网络体系结构参数的一种方法是将它们视为模型的超参数,使用这些超参数构建网络,并将训练后网络的性能作为适应度进行评价。接下来,将使用遗传算法找到隐藏层的最佳组合。

由于MLP的体系结构由隐藏层配置决定,在tensorflow.keras中可通过改变Dense层的units参数获得节点数不同的全连接隐藏层:
Dense(units, activation=None,…)
同时,可以通过for来构建所需层数,例如,如果要为MLP配置三个有20个节点的隐藏层,则可以通过以下方式:
self.model = Sequential()
for l in range(3):
self.model.add(layers.Dense(20,activation=‘relu’))
因此,我们需要提出既可以表示层数又可以表示每一层节点数的染色体。
同时,为了能够使用标准遗传算子,使用固定长度的染色体表示形式。使用这种方法时,预先确定最大层数,但为了层数可变,可以在染色体中设置无效位(也可以称为终止参数),使模型构建提前终止。例如,将网络限制为四个隐藏层,则染色体将如下所示:
[ n 1 , n 2 , n 3 , n 4 ] [n_1, n_2, n_3, n_4] [n1,n2,n3,n4]
其中, n i n_i ni表示 i i i层中的节点数。
为了控制网络中隐藏层的实际数量,其中一些值可能为零或负数。该值意味着之后不会再有其他层添加到网络:
-
染色体[10, 20, -5, 15]表示元组(10, 20),因为-5是无效位。
-
染色体[10, 0, -5, 15]表示元组(10, ),因为0是无效位。
-
染色体[10, 20, 5, -15]表示元组(10, 20, 5),因为-15是无效位。
-
染色体[10, 20, 5, 15]表示元组(10, 20, 5, 15)。
为了保证至少有一个隐藏层,可以强制第一个参数始终大于零。其他层参数可以在零附近分布,以便可以控制它们成为终止参数。
另外,由于染色体中值有限定区间,可以选择使用浮点数列表构建染色体。使用浮点数列表使我们能够使用现有的遗传算子。为了构建网络可以使用round()函数可以将浮点数转换回整数:
-
染色体[9.35, 10.71, -2.51, 17.99]可以转化为元组(9, 11)
-
染色体[9.35, 10.71, 2.51, -17.99]可以转化为元组(9, 11, 3)
要评估构建的网络结构,需要创建实现这些层的MLP分类器,对其进行训练并进行评估。
MLPLayers类封装了MNIST数据集的MLP分类器的构建以及模型准确率的评估。
#导入必要库
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers,Sequential,losses,optimizers,datasets
from math import floor
导入优化器,损失函数模块
from tensorflow.keras import optimizers,losses
MLPLayers类主要包括以下方法
-
preprocess(self,x,y)用于构建训练数据集的预处理
-
initDataset(self)用于构建训练数据集
-
convertParams(self,params)将params的列表转换为可以有效构建模型的元组
-
getAccuracy(self,params)构建模型,训练,并返回最后一个epoch的验证准确率,用于适应度评估。
-
testLayer(self),使用经验值构建的分类模型,用于和优化得到的网络进行对比
-
formatParams(self, params)用于格式化输出染色体
class MLPLayers:
def init(self):
self.initDataset()
def preprocess(self,x,y):
x = tf.reshape(x, [-1])
return x,y
def initDataset(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)
def convertParams(self,params):
if round(params[1]) <= 0:
hiddenLayerSizes = round(params[0]),
elif round(params[2]) <= 0:
hiddenLayerSizes = (round(params[0]), round(params[1]))
elif round(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]))
return hiddenLayerSizes
def getAccuracy(self,params):
#将染色体转化为可以有效构建网络的元组
hiddenLayerSizes = self.convertParams(params)
self.model = Sequential()
#构建网络
for l in hiddenLayerSizes:
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训练后的验证准确率,用于适应度评估
return history.history[‘val_accuracy’][-1]
def testLayer(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;采用交叉熵损失函数,包含Softmax
network.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])
def formatParams(self, params):
return “‘hidden_layer_sizes’={}”.format(self.convertParams(params))
现在,我们已经有了MLP的体系结构配置,以及确定每种配置的MLP准确率的方法,接下来,创建基于遗传算法的优化程序以对配置进行搜索——隐藏层的数量以及每层中的节点数量——产生最佳分类准确率。
详细的步骤在注释中进行介绍
from deap import base
from deap import creator
from deap import tools
import random
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
#创建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 = 50
P_CROSSOVER = 0.9
P_MUTATION = 0.5
MAX_GENERATIONS = 20
HALL_OF_FAME_SIZE = 5
CROWDING_FACTOR = 10.0
toolbox = base.Toolbox()
#定义最大化适用度策略:
creator.create(“FitnessMax”,base.Fitness,weights=(1.0,))
#基于列表创建个体类:
creator.create(“Individual”,list,fitness=creator.FitnessMax)
#由于解由一系列不同区间的浮点值表示,因此我们使用以下循环并为每个区间创建一个单独的toolbox运算符(layer_size_attribute),用于在适当范围内生成随机浮点值:
for i in range(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 = ()
for i in range(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()方法进行适应度评估
def classificationAccuracy(individual):
return test.getAccuracy(individual),
一、Python所有方向的学习路线
Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

二、学习软件
工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。

三、入门学习视频
我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)