手动实现卷积运算、最大池化运算、全局平均池化运算

概述

本文通过代码实现卷积运算、最大池化运算、全局平均池化运算,帮助理解卷积神经网络中各层的运算过程

为了简单易于理解,采用灰度图,如下:

建立模型运算并显示结果

导入模块

import tensorflow as tf
from tensorflow.keras import Model
from tensorflow.keras.layers import Input,Conv2D, MaxPool2D,GlobalAveragePooling2D,BatchNormalization
from tensorflow.keras.layers import Activation
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np

读取图片

path=r"C:\Users\mym\Desktop\文件接收柜\aodaili.jpg"
im = Image.open(path)
img=np.array(im)
print('输入图shape:',img.shape)
print('输入图:',img)

转换图片形状

img_batch = img.reshape(1,img.shape[0],img.shape[1],1)
print('输入图shape:',img_batch.shape)

建立模型

为了查看各层的结果,这里采用model函数式api

inp=Input(shape=img_batch.shape[1:])
conv=Conv2D(1, (3, 3))(inp)
mp=MaxPool2D(pool_size=(2, 2))(conv)
gap=GlobalAveragePooling2D()(mp)

model=Model(inputs=inp,outputs=[conv,mp,gap])
model.summary()

预测

prd=model.predict(img_batch)
len(prd)

查看卷积结果

# 转成2维
conv_result=prd[0].reshape(prd[0].shape[1:3])
conv_result

查看卷积核的值

w,b=model.layers[1].get_weights()
# 转成2维
w2=w.reshape(w.shape[0:2])

查看最大池化结果

mp_result=prd[1].reshape(prd[1].shape[1:3])
mp_result

查看全局平均池化结果

prd[2]

手动实现卷积运算

定义卷积运算函数

# 卷积运算
def run_conv(data,kernel):
    """
    img:要计算的图像数据
    kernel:卷积核值
    """
#     卷积核大小
    kernel_size=kernel.shape[0]
#     图像大小,要求宽高相同
    img_size=img.shape[0]
#     结果大小
    result_size=img_size-kernel_size+1

#     输入数据的滑块索引
    data_w_index=0
    data_h_index=0

    result_data=np.zeros((result_size,result_size))

    for res_w_index in range(result_size):
        for res_h_index in range(result_size):
            img_area=data[data_w_index:data_w_index+kernel_size,data_h_index:data_h_index+kernel_size]
            result=np.sum(img_area*kernel)
            result_data[res_w_index][res_h_index]=result

            data_h_index+=1

        data_w_index+=1
        data_h_index=0
    return result_data

运算

my_conv=run_conv(img,w2)
my_conv

手动实现最大池化结果

def run_mp(data,mp_size=2,step=2):
    data_size=data.shape[0]
#     结果大小
    result_size=(data_size-mp_size)//step+1
    result_data=np.zeros((result_size,result_size))

#     在输入数据的滑动块索引
    data_w_index=0
    data_h_index=0


    for res_w_index in range(result_size):
        for res_h_index in range(result_size):
            img_area=data[data_w_index:data_w_index+mp_size,data_h_index:data_h_index+mp_size]
            result=np.max(img_area)
            result_data[res_w_index][res_h_index]=result

            data_h_index+=step

        data_w_index+=step
        data_h_index=0
    return result_data

运算

my_mp=run_mp(my_conv)
my_mp.shape

手动实现全局平均池化结果

np.sum(my_mp)/(my_mp.shape[0]*my_mp.shape[1])

原文出处:/show_1EF4Yx7v8m7C.html