遗传算法与深度学习实战(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) 首先,导入所需库,并加载数据集:
python
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']
def plot_data(num_images, images, labels):
grid = math.ceil(math.sqrt(num_images))
plt.figure(figsize=(grid*2,grid*2))
for i in range(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) 在每个主要网络层内部,我们还需要定义相应的超参数选项,例如滤波器数量和卷积核大小。为了编码多样化数据,我们需要分离主要网络层和相关超参数。设置常量用于定义网络层类型和长度以封装各种相关的超参数。定义总最大网络层数和各种网络层超参数的范围,之后,定义每种类型的块标识符及其相应的大小(该值表示每个层定义的长度,包括超参数):
python
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%
的概率)添加批归一化和池化层:
python
def create_offspring():
ind = []
for i in range(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) 编写用于构建网络层的辅助函数:
python
def generate_neurons():
return random.randint(min_neurons, max_neurons)
def generate_kernel():
part = []
part.append(random.randint(min_kernel, max_kernel))
part.append(random.randint(min_kernel, max_kernel))
return part
def generate_bn_layer():
part = [BN_LAYER]
return part
def generate_pooling_layer():
part = [POOLING_LAYER]
part.append(random.randint(min_pool, max_pool))
part.append(random.randint(min_pool, max_pool))
return part
def generate_dense_layer():
part = [DENSE_LAYER]
part.append(generate_neurons())
return part
def generate_conv_layer():
part = [CONV_LAYER]
part.append(generate_neurons())
part.extend(generate_kernel())
return part
(5) 调用 create_offspring()
生成基因序列,输出如下所示。可以多次调用该函数,观察创建的基因序列的变化:
python
individual = create_offspring()
print(individual)
# [-1, 37, 5, 2, -3, -1, 112, 4, 2, -4, 25]
(6) 获取基因序列后,继续构建模型,解析基因序列并创建 Keras
模型。build_model
的输入是单个基因序列,利用基因序列产生 Keras
模型。定义网络层之后,根据网络层类型添加超参数:
python
def build_model(individual):
model = models.Sequential()
il = len(individual)
i = 0
while 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 += 1
elif 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) 创建一个新的个体基因序列,根据序列构建一个模型,然后训练模型,输出训练/验证过程中模型性能:
python
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构建卷积神经网络