跳转至

使用 Keras 绘制神经网络结构图

使用keras模块的plot_model绘制神经网络结构图,将神经网络可视化能够帮助理解模型是如何运行的。

基本代码

导入搭建模型和绘制神经网络结构的包

Python
from keras.utils import plot_model
from tensorflow.keras import backend as Keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import (
    Conv2D,
    MaxPool2D,
    Activation,
    Dropout,
    Flatten,
    Dense,
)

定义搭建模型的函数

Python
# 定义添加卷积层的函数,可以添加 input_shape 参数
def add_conv_layer(model, filters, kernel_size, input_shape=None):
    if input_shape:
        model.add(
            Conv2D(
                filters=filters,
                kernel_size=kernel_size,
                padding="same",
                activation="relu",
                input_shape=input_shape,
            )
        )
    else:
        model.add(
            Conv2D(
                filters=filters,
                kernel_size=kernel_size,
                padding="same",
                activation="relu",
            )
        )
    return model


# 定义搭建模型的函数
def build_model(
    block_num,
    layer_num,
    filters_in_each_block,
    kernel_size,
    pool_size,
    strides,
    dropout_rate,
    x_train,
):
    # 清除 Keras 的 session
    Keras.clear_session()
    # 定义一个空的 Sequential 模型
    model = Sequential()
    # 添加所有的 block
    for block in range(1, block_num + 1):
        # 第一个 Block,需要指定输入的形状
        if block == 1:
            # 该 block 的 filters
            filters = filters_in_each_block[block - 1]
            # 添加第一个卷积层,需要指定输入的形状
            model = add_conv_layer(
                model,
                filters=filters,
                kernel_size=kernel_size,
                input_shape=x_train.shape[1:],
            )
            # 添加除第一个卷积层之外的其他卷积层
            for layer in range(2, layer_num + 1):
                model = add_conv_layer(model, filters=filters, kernel_size=kernel_size)
            # 添加池化层
            model.add(MaxPool2D(pool_size=pool_size, strides=strides))
        # 其他 Block
        else:
            # 该 block 的 filters
            filters = filters_in_each_block[block - 1]
            # 添加所有卷积层
            for layer in range(1, layer_num + 1):
                model = add_conv_layer(model, filters=filters, kernel_size=kernel_size)
            # 添加池化层
            model.add(MaxPool2D(pool_size=pool_size, strides=strides))
    # 添加 Flatten 层
    model.add(Flatten())
    # 添加 Dropout 层
    model.add(Dropout(dropout_rate))
    # 添加 Dense 层
    model.add(Dense(7, activation="softmax"))
    return model

搭建模型

Python
model = build_model(
    block_num=4,
    layer_num=2,
    filters_in_each_block=[64, 128, 256, 512],
    kernel_size=3,
    pool_size=4,
    strides=2,
    dropout_rate=0.2,
    x_train=x_train,
)

使用model.summary()查看网络结构

Python
model.summary()
Text Only
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d (Conv2D)             (None, 48, 48, 64)        640       

 conv2d_1 (Conv2D)           (None, 48, 48, 64)        36928     

 max_pooling2d (MaxPooling2D  (None, 23, 23, 64)       0         
 )                                                               

 conv2d_2 (Conv2D)           (None, 23, 23, 128)       73856     

 conv2d_3 (Conv2D)           (None, 23, 23, 128)       147584    

 max_pooling2d_1 (MaxPooling  (None, 10, 10, 128)      0         
 2D)                                                             

 conv2d_4 (Conv2D)           (None, 10, 10, 256)       295168    

 conv2d_5 (Conv2D)           (None, 10, 10, 256)       590080    

 max_pooling2d_2 (MaxPooling  (None, 4, 4, 256)        0         
 2D)                                                             

 conv2d_6 (Conv2D)           (None, 4, 4, 512)         1180160   

 conv2d_7 (Conv2D)           (None, 4, 4, 512)         2359808   

 max_pooling2d_3 (MaxPooling  (None, 1, 1, 512)        0         
 2D)                                                             

 flatten (Flatten)           (None, 512)               0         

 dropout (Dropout)           (None, 512)               0         

 dense (Dense)               (None, 7)                 3591      

=================================================================
Total params: 4,687,815
Trainable params: 4,687,815
Non-trainable params: 0
_________________________________________________________________

我们已经得到了表格样式的模型结构,可以清楚地知道神经网络有多少层、每一层的输入输出形状这些关键信息。下面用plot_model()绘制神经网络结构,通过可视化的方式进一步帮助我们理解神经网络。

使用plot_model()绘制神经网络结构

Python
plot_model(model)

image-20221114170939392

指定输出网络形状,且输出到本地文件

Python
plot_model(model, show_shapes=True, to_file="model.png")

image-20221114171151113

报错解决方法

如果提示

Text Only
('You must install pydot (`pip install pydot`) and install graphviz (see instructions at https://graphviz.gitlab.io/download/) ', 'for plot_model/model_to_dot to work.')

可以将keras绘图的源代码中的pydot改成pydotplus。具体来说,需要找到以下地址:

Text Only
/usr/local/lib/python3.8/dist-packages/tensorflow/python/keras/utils

进入vis_utils.py,如下图所示:

image-20221114165809058

pydot基本上全部改成pydotplus(除了开始的少数代码不用改,因为有些代码原来就是pydotplus,最好保留)之后,即可正常导入包。

image-20221114170020132

本报错解决方法参考了CSDN 的文章

评论