遗传算法与深度学习实战(26)——编码卷积神经网络架构
0. 前言
我们已经学习了如何构建卷积神经网络 (Convolutional Neural Network, CNN),在本节中,我们将了解如何将
CNN
模型的网络架构编码为基因,这是将基因序列进化在为给定数据集上训练最佳模型的先决条件。
1. EvoCNN 原理
进化卷积神经网络 (
Evolutionary Convolutional Neural Network
,
EvoCNN
) 是一种结合了进化算法和卷积神经网络的方法。
我们知道进化算法是一类基于生物进化过程中的选择、变异和竞争机制的优化算法。在进化卷积神经网络中,进化算法用来优化卷积神经网络 (
Convolutional Neural Network
,
CNN
) 的结构或超参数,以提升其性能和适应特定任务的能力。
1.1 工作原理
EvoCNN
可以利用进化算法来自动设计
CNN
的网络结构,包括卷积层的数量、每层的卷积核大小、池化操作的类型等。自动设计的过程可以帮助避免人工设计网络结构时的主观偏差,并且可以根据具体任务调整网络结构。
除了网络结构外,进化算法还可以用于优化
CNN
的超参数,如学习率、批处理大小等,以提升训练效率和模型性能。
EvoCNN
的另一个优点是其适应性强,能够适应不同的任务和数据集。通过进化算法,网络可以在训练过程中动态调整,以适应变化的输入数据和任务要求。
1.2 基因编码
EvoCNN
是演化
CNN
模型架构的模型,其定义了一种将卷积网络编码为可变长度基因序列的过程,如下图所示。
2. 编码卷积神经网络架构
(1) 首先,导入所需库,并加载数据集:
import tensorflow as tf
from tensorflow.keras import datasets, layers, models
import numpy as np
import math
import time
import random
import matplotlib.pyplot as plt
from livelossplot import PlotLossesKeras
dataset = datasets.fashion_mnist
(x_train, y_train),(x_test, y_test)= dataset.load_data()# normalize and reshape data
x_train = x_train.reshape(x_train.shape[0],28,28,1).astype("float32")/255.0
x_test = x_test.reshape(x_test.shape[0],28,28,1).astype("float32")/255.0
x_train = x_train[:1000]
y_train= y_train[:1000]
x_test = x_test[:100]
y_test= y_test[:100]
class_names =['T-shirt/top','Trouser','Pullover','Dress','Coat','Sandal','Shirt','Sneaker','Bag','Ankle boot']defplot_data(num_images, images, labels):
grid = math.ceil(math.sqrt(num_images))
plt.figure(figsize=(grid*2,grid*2))for i inrange(num_images):
plt.subplot(grid,grid,i+1)
plt.xticks([])
plt.yticks([])
plt.grid(False)
plt.imshow(images[i].reshape(28,28))
plt.xlabel(class_names[labels[i]])
plt.show()
plot_data(25, x_train, y_train)
构建基因序列时,我们希望定义一个基本规则,所有模型都以卷积层开始,并以全连接层作为输出层结束。为了简化问题,我们无需编码最后的输出层。
(2) 在每个主要网络层内部,我们还需要定义相应的超参数选项,例如滤波器数量和卷积核大小。为了编码多样化数据,我们需要分离主要网络层和相关超参数。设置常量用于定义网络层类型和长度以封装各种相关的超参数。定义总最大网络层数和各种网络层超参数的范围,之后,定义每种类型的块标识符及其相应的大小(该值表示每个层定义的长度,包括超参数):
max_layers =5
max_neurons =128
min_neurons =16
max_kernel =5
min_kernel =2
max_pool =3
min_pool =2
CONV_LAYER =-1
CONV_LAYER_LEN =4
POOLING_LAYER =-2
POOLING_LAYER_LEN =3
BN_LAYER =-3
BN_LAYER_LEN =1
DENSE_LAYER =-4
DENSE_LAYER_LEN =2
下图展示了编码层块及其相应超参数的基因序列。需要注意的是,负值
-1
、
-2
、
-3
和
-4
表示网络层的开始。然后,根据层类型,进一步定义滤波器数量和卷积核大小等超参数。
(3) 构建个体的基因序列(染色体),
create_offspring()
函数是构建序列的基础。此代码循环遍历最大层数次,并检查是否(以
50%
的概率)添加卷积层。如果是,则进一步检查是否(以
50%
的概率)添加批归一化和池化层:
defcreate_offspring():
ind =[]for i inrange(max_layers):if random.uniform(0,1)<.5:#add convolution layer
ind.extend(generate_conv_layer())if random.uniform(0,1)<.5:#add batchnormalization
ind.extend(generate_bn_layer())if random.uniform(0,1)<.5:#add max pooling layer
ind.extend(generate_pooling_layer())
ind.extend(generate_dense_layer())return ind
(4) 编写用于构建网络层的辅助函数:
defgenerate_neurons():return random.randint(min_neurons, max_neurons)defgenerate_kernel():
part =[]
part.append(random.randint(min_kernel, max_kernel))
part.append(random.randint(min_kernel, max_kernel))return part
defgenerate_bn_layer():
part =[BN_LAYER]return part
defgenerate_pooling_layer():
part =[POOLING_LAYER]
part.append(random.randint(min_pool, max_pool))
part.append(random.randint(min_pool, max_pool))return part
defgenerate_dense_layer():
part =[DENSE_LAYER]
part.append(generate_neurons())return part
defgenerate_conv_layer():
part =[CONV_LAYER]
part.append(generate_neurons())
part.extend(generate_kernel())return part
(5) 调用
create_offspring()
生成基因序列,输出如下所示。可以多次调用该函数,观察创建的基因序列的变化:
individual = create_offspring()print(individual)# [-1, 37, 5, 2, -3, -1, 112, 4, 2, -4, 25]
(6) 获取基因序列后,继续构建模型,解析基因序列并创建
Keras
模型。
build_model
的输入是单个基因序列,利用基因序列产生
Keras
模型。定义网络层之后,根据网络层类型添加超参数:
defbuild_model(individual):
model = models.Sequential()
il =len(individual)
i =0while i < il:if individual[i]== CONV_LAYER:
n = individual[i+1]
k =(individual[i+2], individual[i+3])
i += CONV_LAYER_LEN
if i ==0:#first layer, add input shape
model.add(layers.Conv2D(n, k, activation='relu', padding="same", input_shape=(28,28,1)))else:
model.add(layers.Conv2D(n, k, activation='relu', padding="same"))elif individual[i]== POOLING_LAYER:#add pooling layer
k = k =(individual[i+1], individual[i+2])
i += POOLING_LAYER_LEN
model.add(layers.MaxPooling2D(k, padding="same"))elif individual[i]== BN_LAYER:#add batch normal layer
model.add(layers.BatchNormalization())
i +=1elif individual[i]== DENSE_LAYER:#add dense layer
model.add(layers.Flatten())
model.add(layers.Dense(individual[i+1], activation='relu'))
i +=2
model.add(layers.Dense(10))return model
model = build_model(individual)
(7) 创建一个新的个体基因序列,根据序列构建一个模型,然后训练模型,输出训练/验证过程中模型性能:
individual = create_offspring()
model = build_model(individual)
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
history = model.fit(x_train, y_train, epochs=10,
validation_data=(x_test, y_test),
callbacks=[PlotLossesKeras()],
verbose=0)
model.summary()
model.evaluate(x_test, y_test)
模型性能的优略取决于随机初始序列,多次运行代码,以观察不同初始随机个体之间的差异。可以通过完成以下问题进一步了解网络架构编码:
- 通过调用循环中的
create_offspring
函数,创建一个新的基因编码序列列表,打印并比较不同个体 - 修改最大/最小范围超参数,然后生成一个新的后代列表
- 添加一个新输入到
create_offspring
函数,将概率从0.5
更改为其他值。然后,生成一个后代列表进行比较
小结
进化卷积神经网络 (
Evolutionary Convolutional Neural Network
,
EvoCNN
) 通过结合进化算法的优势,提供了一种自动化设计和优化深度学习模型的方法。在本节中,我们介绍了如何将卷积神经网络架构编码为基因序列,为构建进化卷积神经网络奠定基础。
系列链接
遗传算法与深度学习实战(1)——进化深度学习
遗传算法与深度学习实战(2)——生命模拟及其应用
遗传算法与深度学习实战(3)——生命模拟与进化论
遗传算法与深度学习实战(4)——遗传算法(Genetic Algorithm)详解与实现
遗传算法与深度学习实战(5)——遗传算法中常用遗传算子
遗传算法与深度学习实战(6)——遗传算法框架DEAP
遗传算法与深度学习实战(7)——DEAP框架初体验
遗传算法与深度学习实战(8)——使用遗传算法解决N皇后问题
遗传算法与深度学习实战(9)——使用遗传算法解决旅行商问题
遗传算法与深度学习实战(10)——使用遗传算法重建图像
遗传算法与深度学习实战(11)——遗传编程详解与实现
遗传算法与深度学习实战(12)——粒子群优化详解与实现
遗传算法与深度学习实战(13)——协同进化详解与实现
遗传算法与深度学习实战(14)——进化策略详解与实现
遗传算法与深度学习实战(15)——差分进化详解与实现
遗传算法与深度学习实战(16)——神经网络超参数优化
遗传算法与深度学习实战(17)——使用随机搜索自动超参数优化
遗传算法与深度学习实战(18)——使用网格搜索自动超参数优化
遗传算法与深度学习实战(19)——使用粒子群优化自动超参数优化
遗传算法与深度学习实战(20)——使用进化策略自动超参数优化
遗传算法与深度学习实战(21)——使用差分搜索自动超参数优化
遗传算法与深度学习实战(22)——使用Numpy构建神经网络
遗传算法与深度学习实战(23)——利用遗传算法优化深度学习模型
遗传算法与深度学习实战(24)——在Keras中应用神经进化优化
遗传算法与深度学习实战(25)——使用Keras构建卷积神经网络
版权归原作者 盼小辉丶 所有, 如有侵权,请联系我们删除。