Fork me on github

python人脸识别项目之学习笔记(五):TensorFlow实现卷积,激励,池化 +全连接

需要学习的知识点

1. 卷积(tf.nn.conv2d)

# conv2d(input, filter, strides, padding, use_cudnn_on_gpu=True, data_format="NHWC", name=None)

每一个参数代表一个形态shape,比如第一个参数【batch, h, w, channels】,里面的元素有4个,说明它是一个4维的张量,也就是4位的数组

如果形态不懂的话可以看看之前写的博客
https://editor.csdn.net/md/?articleId=107565145
如果通过形态得到一个4维的张量

第一个参数是输入,它是一个4维度的张量
【batch, h, w, channels】
batch 就是说一次输入多少张图片, 可以是1, 或者其他数
h 输入的高度
w 输入的宽度
channels 就是一张图片输入的通道数, 彩色是3, 黑白是1

第二个参数是一个卷积核,也是一个4维的张量
【k_h, k_w, in, out】
k_h 卷积核的高度
k_w 卷积核的宽度
in 卷积需要作用输入图片的通道数,可以是第一个参数的 channels 的值
out 卷积核的个数,也可以是输出的通道数

第三个参数是卷积核的移动步长,也是一个4维的张量
【1, s_h, s_w, 1】
s_h 就是高度方向移动的步长
s_w 就是宽度方向移动的步长

第四个参数是补0的方法,可以选择二个之中的其中一个
【“SAME"或者"VALID”】
SAME TensorFlow会自动补0,这样会保证输出大小和输入大小相同
VALID 不会自动补0

输入一张 3 * 3 的图片对他进行卷积操作

import tensorflow as tf

# 这是一张 3 *3 的彩色图片
input = tf.constant(
    [ # 一张图片
        [ # 图片的宽
            [  # 图片的高
                [100., 100., 100.], # 里面那一层就是图片的通道
                [100., 100., 100.],
                [100., 100., 100.]
            ],
            [
                [100., 100., 100.], # 里面那一层就是图片的通道
                [100., 100., 100.],
                [100., 100., 100.]
            ],
            [
                [100., 100., 100.], # 里面那一层就是图片的通道
                [100., 100., 100.],
                [100., 100., 100.]
            ]
        ]
    ]
)

# 做一个过滤器(卷积核)
filter = tf.constant(
    [ # 卷积核的宽度为2
        [ # 卷积核的高度为 2
            [   # 通道数 为 3 (这里的通道就是输入图片的通道)彩色图片为3
                [0.5, 0.1], # 卷积核的个数
                [0.5, 0.1],
                [0.5, 0.1]
            ],
            [
                [0.5, 0.1],
                [0.5, 0.1],
                [0.5, 0.1]
            ]
        ],
        [
            [
                [0.5, 0.1],
                [0.5, 0.1],
                [0.5, 0.1]
            ],
            [
                [0.5, 0.1],
                [0.5, 0.1],
                [0.5, 0.1]
            ]
        ]
    ]
)

# 这是一个封装的函数
def conv2d(x, w):
	# 可以看出每次宽移动1格,高移动1格
	# padding='SAME' 让其主动补0
    return tf.nn.conv2d(x, w, strides=[1, 1, 1, 1], padding='SAME')
result = conv2d(x, filter)

sess = tf.Session()
res = sess.run(result)
print(res)
sess.close()

执行的结果

在这里插入图片描述

可以看出他是一个 4 维的张量
输出是 2 个 3 * 3 的矩阵

为什么是 2 个 3 * 3 的矩阵???

在这里插入图片描述

2. ReLU激励层(tf.nn.relu)

  • 明白为什么需要经过这个激励层,他的作用是什么?

不理解的可以看看这个大佬的博客
https://blog.csdn.net/a6333230/article/details/80887062
他非常请求的解释了激励层的作用。

我的理解:激励层的作用就是将线性的问题变化为非线性的问题。

先说下卷积层,学深度学习的应该都是知道卷积层的,那卷积层具体指什么呢?其实卷积层就是我们所做的一大堆特定的滤波器,该滤波器会对某些特定的特征进行强烈的响应,一般情况下是结果值非常大。而对一些无关特性,其响应很小,大部分是结果相对较小,或者几乎为0。这样就可以看做为激活,当特定卷积核发现特定特征时,就会做出响应,输出大的数值,而响应函数的存在把输出归为0~1,那么大的数值就接近1,小的数值就接近0。因此在最后计算每种可能所占比重时,自然大的数值比重大。

在这里插入图片描述

TF-激活函数 tf.nn.relu

将上面卷积得到的特征值得到,将这个特征值进行激活,代码如下

import tensorflow as tf

x = tf.constant(
    [ # 一张图片
        [ # 图片的宽
            [  # 图片的高
                [100., 100., 100.], # 里面那一层就是图片的通道
                [100., 100., 100.],
                [100., 100., 100.]
            ],
            [
                [100., 100., 100.], # 里面那一层就是图片的通道
                [100., 100., 100.],
                [100., 100., 100.]
            ],
            [
                [100., 100., 100.], # 里面那一层就是图片的通道
                [100., 100., 100.],
                [100., 100., 100.]
            ]
        ]
    ]
)
filter = tf.constant(
    [ # 卷积核的宽度为2
        [ # 卷积核的高度为 2
            [   # 通道数 为 3
                [0.5, 0.1],
                [0.5, 0.1],
                [0.5, 0.1]
            ],
            [
                [0.5, 0.1],
                [0.5, 0.1],
                [0.5, 0.1]
            ]
        ],
        [
            [
                [0.5, 0.1],
                [0.5, 0.1],
                [0.5, 0.1]
            ],
            [
                [0.5, 0.1],
                [0.5, 0.1],
                [0.5, 0.1]
            ]
        ]
    ]
)


def conv2d(x, w):
    return tf.nn.conv2d(x, w, strides=[1, 1, 1, 1], padding='SAME')

res = conv2d(x, filter)


with tf.Session() as sess:
    print(sess.run(res))
    b = tf.nn.relu(res)
    print(sess.run(b))

执行结果
在这里插入图片描述

3. 池化(tf.nn.max_pool)

tf.nn.max_pool(value, ksize, strides, padding, name=None)

vale 是第一个参数,通常是特征图,一般都经过卷积he激励层得到的特征值

ksize是第二个参数,【1, height, width, 1】

strides第三个参数:和卷积类似,窗口在每一个维度上滑动的步长,一般也是 [1, stride,stride, 1]

padding是第四个参数:和卷积类似,可以取 ‘VALID’ 或者 ‘SAME’

根据上面的代码

import tensorflow as tf

x = tf.constant(
    [ # 一张图片
        [ # 图片的宽
            [  # 图片的高
                [100., 100., 100.], # 里面那一层就是图片的通道
                [100., 100., 100.],
                [100., 100., 100.]
            ],
            [
                [100., 100., 100.], # 里面那一层就是图片的通道
                [100., 100., 100.],
                [100., 100., 100.]
            ],
            [
                [100., 100., 100.], # 里面那一层就是图片的通道
                [100., 100., 100.],
                [100., 100., 100.]
            ]
        ]
    ]
)
filter = tf.constant(
    [ # 卷积核的宽度为2
        [ # 卷积核的高度为 2
            [   # 通道数 为 3
                [0.5, 0.1],
                [0.5, 0.1],
                [0.5, 0.1]
            ],
            [
                [0.5, 0.1],
                [0.5, 0.1],
                [0.5, 0.1]
            ]
        ],
        [
            [
                [0.5, 0.1],
                [0.5, 0.1],
                [0.5, 0.1]
            ],
            [
                [0.5, 0.1],
                [0.5, 0.1],
                [0.5, 0.1]
            ]
        ]
    ]
)


def conv2d(x, w):
    return tf.nn.conv2d(x, w, strides=[1, 1, 1, 1], padding='SAME')

def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

res_conv2d = conv2d(x, filter)
res_relu = tf.nn.relu(res_conv2d)
res_pool = max_pool_2x2(res_relu)

sess = tf.Session()

res = sess.run(res_pool)
print(res)
sess.close()

执行结果
在这里插入图片描述

4. 全连接(tf.layers.dense)

要明白全连接层之前的作用是提取特征,全连接层的作用是分类。

全连接还是非常好理解的

这里有一个大佬的博客,写的非常容易理解
https://www.cnblogs.com/Terrypython/p/11147665.html

tf.layers.dense 函数的学习

tf.layers.dense(
 
    inputs,
 
    units,
 
    activation=None,
 
    use_bias=True,
 
    kernel_initializer=None,
 
    bias_initializer=tf.zeros_initializer(),
 
    kernel_regularizer=None,
 
    bias_regularizer=None,
 
    activity_regularizer=None,
 
    kernel_constraint=None,
 
    bias_constraint=None,
 
    trainable=True,
 
    name=None,
 
    reuse=None
 
)

inputs: 该层的输入
units: 输出的大小(维数),整数或long
activation: 使用什么激活函数(神经网络的非线性层),默认为None,不使用激活函数
use_bias: 使用bias为True(默认使用),不用bias改成False即可

这里有一道题,让我加深如何实现全连接
在这里插入图片描述

import tensorflow as tf

x = tf.constant([[90.0, 80.0, 70.0]])

w1 = tf.constant([[0.1, 0.2, 0.3, 0.4], [0.2, 0.3, 0.4, 0.5], [0.3, 0.4, 0.5, 0.6]])
b1 = tf.constant(0.1)
y1 = tf.matmul(x, w1) + b1

w1 = tf.constant_initializer([[0.1, 0.2, 0.3, 0.4], [0.2, 0.3, 0.4, 0.5], [0.3, 0.4, 0.5, 0.6]])
b1 = tf.constant_initializer(value=0.1)
y2 = tf.layers.dense(x, units=4, kernel_initializer=w1, bias_initializer=b1)


def func1(sess):
    print('TF 矩阵乘法', sess.run(y1))


def func2(sess):
    sess.run(tf.global_variables_initializer())
    print('TF dense()', sess.run(y2))


if __name__ == '__main__':
    with tf.Session() as sess:
        func1(sess)
        func2(sess)

执行结果
在这里插入图片描述

posted @ 2022-01-23 11:59  不想努力的小龙  阅读(187)  评论(0编辑  收藏  举报