遗传算法与深度学习实战(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构建卷积神经网络

相关推荐
zm-v-159304339861 小时前
从CNN到Transformer:遥感影像目标检测的未来趋势
目标检测·cnn·transformer
boooo_hhh6 小时前
深度学习笔记16-VGG-16算法-Pytorch实现人脸识别
pytorch·深度学习·机器学习
美狐美颜sdk9 小时前
直播美颜工具架构设计与性能优化实战:美颜SDK集成与实时处理
深度学习·美颜sdk·第三方美颜sdk·视频美颜sdk·美颜api
Fansv58710 小时前
深度学习-6.用于计算机视觉的深度学习
人工智能·深度学习·计算机视觉
deephub11 小时前
LLM高效推理:KV缓存与分页注意力机制深度解析
人工智能·深度学习·语言模型
奋斗的袍子00711 小时前
Spring AI + Ollama 实现调用DeepSeek-R1模型API
人工智能·spring boot·深度学习·spring·springai·deepseek
青衫弦语11 小时前
【论文精读】VLM-AD:通过视觉-语言模型监督实现端到端自动驾驶
人工智能·深度学习·语言模型·自然语言处理·自动驾驶
美狐美颜sdk12 小时前
直播美颜SDK的底层技术解析:图像处理与深度学习的结合
图像处理·人工智能·深度学习·直播美颜sdk·视频美颜sdk·美颜api·滤镜sdk
WHATEVER_LEO12 小时前
【每日论文】Text-guided Sparse Voxel Pruning for Efficient 3D Visual Grounding
人工智能·深度学习·神经网络·算法·机器学习·自然语言处理
Binary Oracle12 小时前
RNN中远距离时间步梯度消失问题及解决办法
人工智能·rnn·深度学习