遗传算法与深度学习实战(26)——编码卷积神经网络架构

遗传算法与深度学习实战(26)------编码卷积神经网络架构

    • [0. 前言](#0. 前言)
    • [1. EvoCNN 原理](#1. EvoCNN 原理)
      • [1.1 工作原理](#1.1 工作原理)
      • [1.2 基因编码](#1.2 基因编码)
    • [2. 编码卷积神经网络架构](#2. 编码卷积神经网络架构)
    • 小结
    • 系列链接

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构建卷积神经网络

相关推荐
盼小辉丶2 小时前
TensorFlow深度学习实战——情感分析模型
深度学习·神经网络·tensorflow
好评笔记2 小时前
AIGC视频生成模型:Stability AI的SVD(Stable Video Diffusion)模型
论文阅读·人工智能·深度学习·机器学习·计算机视觉·面试·aigc
AI街潜水的八角3 小时前
工业缺陷检测实战——基于深度学习YOLOv10神经网络PCB缺陷检测系统
pytorch·深度学习·yolo
坐吃山猪7 小时前
机器学习10-解读CNN代码Pytorch版
pytorch·机器学习·cnn
池央8 小时前
DCGAN - 深度卷积生成对抗网络:基于卷积神经网络的GAN
深度学习·生成对抗网络·cnn
scdifsn8 小时前
动手学深度学习11.6. 动量法-笔记&练习(PyTorch)
pytorch·笔记·深度学习
羊小猪~~8 小时前
深度学习基础--LSTM学习笔记(李沐《动手学习深度学习》)
人工智能·rnn·深度学习·学习·机器学习·gru·lstm
青松@FasterAI9 小时前
Word2Vec如何优化从中间层到输出层的计算?
人工智能·深度学习·自然语言处理·nlp面题
paradoxjun9 小时前
落地级分类模型训练框架搭建(1):resnet18/50和mobilenetv2在CIFAR10上测试结果
人工智能·深度学习·算法·计算机视觉·分类
神经星星9 小时前
登Nature子刊!北大团队用AI预测新冠/艾滋病/流感病毒进化方向,精度提升67%
人工智能·深度学习·机器学习