TensorFlow深度学习入门详解

1、深度学习网络概述

1.1 深度学习网络简单介绍

        常见的深度学习网络由卷积层+池化层+全连接层等组成,通过构建多层卷积层和池化层,可以学习到一些有用的模型,一个简单的深度学习模型结构如下所示:

卷积层 -> 池化层 -> ... -> 卷积层 -> 池化层 -> 全连接层 -> 全连接层

        对应的函数层如下所示:

Conv2D -> Pool -> .. -> Conv2D -> Pool -> Flatten -> Dense -> Dense

2、Python代码示例

2.1 准备数据阶段(读入图片转成数组)

2.1.1 代码示例

import tensorflow as tf;
import numpy as np;
from PIL import Image;
import matplotlib.pyplot as plt;

imgObj = Image.open("D:/study/image/1.png");

plt.subplot(2,3,2);
plt.imshow(imgObj);
plt.title(label='layers 1: conv2d',loc='center');

img = np.array(imgObj, dtype='float32');

# 一般彩色图片由RGB三色构成,所以读入图片后数组的原始维度是: HEIGHT * WIDTH * 3,其中3可以理解为图片的通道数
# conv2d函数需要4维的输入,我们需要把图片3维数组转成4维的数组
# 4维数组的维度依次是:BATCH_SIZE,HEIGHT,WIDTH,CHANNELS
x_train = img[tf.newaxis,...];
print("img.shape=", img.shape, ", x_train=", x_train.shape);

2.1.2 代码执行结果

因为图片本身宽和高是1200*675,又是彩色图片,所以数据维度输出如下:

BATCH_SIZE=1,图片只有一张;

HEIGHT=675,图片的高度;

WIDTH=1200,图片的宽度;

CHANNELS=3,彩色图片有RGB三色,所以通道数是3;

下图是运行输出日志:

2.2 第1层:卷积运算Conv2D

2.2.1 代码示例

conv2d_1 = tf.keras.layers.Conv2D(filters=32, kernel_size=3,  strides=(1,1),
                                  padding='same', data_format='channels_last')(x_train);
print("conv2d_1.shape=", conv2d_1.shape);
# 打印卷积运算结果前3个通道的图片
for i in range(3):
    showImg = conv2d_1[0,:,:,i];
    plt.subplot(2,3,4+i);
    plt.imshow(showImg, 'gray');
    plt.title(label="channel"+str((i+1)), loc='center');
plt.show();

2.2.2 代码执行结果

在我们查看输出结果之前,需要简单介绍一下Conv2D函数常用的参数:

1、filters=32,这是通道数。原始彩色图片的通道是3,经过卷积运算后,通道数变成32;

2、kernel_size=3,这是卷积运算的核数。等价于kernel_size=(3,3),卷积运算从图片左上角开始,每次取3*3大小位置的数字,乘以一个3*3大小的过滤器(按元素位置对应相乘求和),重复计算到图片的右下角。

补充:图示卷积运算的计算过程

原始图片左上角4个元素,按位置乘以kernel的4个元素,得到输出的左上角位置的值2;

原始图片上方居中的4个元素,按位置乘以kernel的4个元素,得到输出的上方居中位置的值0;

原始图片右上角的4个元素,按位置乘以kernel的4个元素,得到输出的右上角位置的值-4;

同理,依次从左往右,从上到下读取原始图片的2*2元素,乘以kernel,最终得到一个3*3的输出。


3、strides=(1,1),这是步长。步长是控制读取原始图片的移动步伐,strides=(1,1)的第一个值控制着从左往右的移动速度,1表示每次移动一格;第二个值则控制从上到下的移动速度,1表示每次移动一格;由此可以理解步长越大,移动速度越快,最终输出的尺寸就越小。

4、padding='same',这是控制上下左右是否填充0,取值same,表示要填充0,取值为valid,表示不填充0。下图是填充0的示意图,因为kernel=3,所以是上下左右各填充多一维0,如果kernel=5,那么上下左右就要各多填充二维0。填充维度计算公式:p = kernel / 2,这样才能保持输出尺寸不变(前提条件是步长为1,否则无法保证输出尺寸大小不变化)。

 

 5、data_format='channels_last',这是指明通道是哪一维。取值channels_last,表示原始数据的通道在高度和宽度之后,数组维度是(BATCH_SIZE,HEIGHT,WIDTH,CHANNELS);取值channels_first,表示原始数据的通道在高度和宽度之前,数组维度是(BATCH_SIZE,CHANNELS,HEIGHT,WIDTH)。

 当然Conv2D还有其他参数,想了解更多知识,自己可以去查阅资料。

下图是运行输出日志:

下图是第1层—卷积运算层,卷积运算结果前3个通道的输出效果图:

        

 2.3 第2层:最大池化运算MaxPool2D

2.3.1 代码示例

pool_1 = tf.keras.layers.MaxPool2D(pool_size=(2,2), strides=(1,1), padding='same')(conv2d_1);
print("pool_1.shape=", pool_1.shape);
plt.subplot(2,3,2);
plt.imshow(imgObj);
plt.title(label='layers 2: pool',loc='center');
# 打印最大池化结果前3通道的图片
for i in range(3):
    showImg = pool_1[0,:,:,i];
    plt.subplot(2,3,4+i);
    plt.imshow(showImg, 'gray');
    plt.title(label="channel"+str((i+1)), loc='center');
plt.show();

2.3.2 代码执行结果

在查看输出日志和效果图之前,先解释一些MaxPool2D函数的参数:

1、pool_size=(2,2),这是指定池化运算过滤器大小。下图是最大池化运算的示意图,从左往右,从上往下,依次取2*2的元素,取出当中的最大值,作为输出的内容。

 2、strides=(1,1),这是步长。步长是控制读取原始图片的移动步伐,strides=(1,1)的第一个值控制着从左往右的移动速度,1表示每次移动一格;第二个值则控制从上到下的移动速度,1表示每次移动一格;由此可以理解步长越大,移动速度越快,最终输出的尺寸就越小。

注意:如果不设置步长,则步长默认取pool_size的值。

3、padding='same',这是控制上下左右是否填充0,取值same,表示要填充0,取值为valid,表示不填充0。pool_size=(2,2),上下左右各填充多一维0,如果pool_size=(4,4),那么上下左右就要各多填充二维0。填充维度计算公式:p = pool_size / 2,这样才能保持输出尺寸不变(前提条件是步长为1,否则无法保证输出尺寸大小不变化)。

下图是填充0的示意图:

 

 下图是运行输出日志:

 下图是第2层—最大池化层,池化运算前3个通道的输出效果图:

 2.4 第3层:卷积运算Conv2D

2.4.1 代码示例

conv2d_2 = tf.keras.layers.Conv2D(filters=16, kernel_size=3, strides=(1,1),
                                  padding='same', data_format='channels_last')(pool_1);
print("conv2d_2.shape=", conv2d_2.shape);
plt.subplot(2,3,2);
plt.imshow(imgObj);
plt.title(label='layers 3: conv2d',loc='center');
# 打印卷积结果前3通道的图片
for i in range(3):
    showImg = conv2d_2[0,:,:,i];
    plt.subplot(2,3,4+i);
    plt.imshow(showImg, 'gray');
    plt.title(label="channel"+str((i+1)), loc='center');
plt.show();

 2.4.2 代码执行结果

前面已经解释过函数的参数了,这里不再重复。

下图是运行输出日志:

 下图是第3层—卷积运算层,卷积运算结果前3个通道的输出效果图:

 2.5 第4层:最大池化运算MaxPool2D

2.5.1 代码示例

pool_2 = tf.keras.layers.MaxPool2D(pool_size=(2,2), strides=(1,1), padding='same')(conv2d_2);
print("pool_2.shape=", pool_2.shape);
plt.subplot(2,3,2);
plt.imshow(imgObj);
plt.title(label='layers 4: pool',loc='center');
# 打印最大池化结果前3通道的图片
for i in range(3):
    showImg = pool_2[0,:,:,i];
    plt.subplot(2,3,4+i);
    plt.imshow(showImg, 'gray');
    plt.title(label="channel"+str((i+1)), loc='center');
plt.show();

2.5.2 代码执行结果

下图是运行输出日志:

 下图是第4层—最大池化运算层,最大池化运算结果前3个通道的输出效果图:

 2.6 Flatten函数

2.6.1 代码示例

flatten = tf.keras.layers.Flatten(data_format='channels_last')(pool_2);
print("flatten.shape=", flatten.shape);

2.6.1 代码执行结果

在看输出结果之前,先解释一下Flatten函数的参数:

1、data_format='channels_last',这是指明通道是哪一维。取值channels_last,表示原始数据的通道在高度和宽度之后,数组维度是(BATCH_SIZE,HEIGHT,WIDTH,CHANNELS);取值channels_first,表示原始数据的通道在高度和宽度之前,数组维度是(BATCH_SIZE,CHANNELS,HEIGHT,WIDTH)。

下图是运行输出日志:

 2.7 第5层:全连接运算Dense

2.7.1 代码示例

dense_1 = tf.keras.layers.Dense(units=16, activation='relu')(flatten);
print("dense_1.shape=", dense_1.shape);

2.7.2 代码执行结果

在看输出结果之前,先解释一下Dense函数的参数:

1、units=16, 这是表示输出的维度,就是输出多少个节点;

2、activation='relu',这是激活函数,常见的激活函数在tf.keras.activations里面定义,这里使用relu激活函数。

下图是运行输出日志:

2.8 第6层:全连接运算Dense

2.8.1 代码示例

y_pred = tf.keras.layers.Dense(units=1, activation='sigmoid')(dense_1);
print("y_pred.shape=", y_pred.shape, ", y_pred=", y_pred);

2.8.2 代码执行结果

Dense函数之前已经解释过了,这里不再重复;

因为这已经模型是最后一层,所以我们直接输出模型预测结果。

下图是运行输出日志:

2.9 计算误差

2.9.1 代码示例

# 标记图片是否是风景图
y_true = np.array([1]);
print("y_true.shape=", y_true.shape, ", y_true=", y_true);

# 平均绝对误差
loss = tf.keras.losses.MAE(y_true, y_pred);
print("loss.shape=", loss.shape, ",loss=", loss);

2.9.2 代码运行结果

在看输出结果之前,我们先解释一下上面的代码:

1、y_true=[1],因为我们输入只有一张图片,所以只需要定义长度为1的数组,来标记图片的分类,我们约定值为1表示图片是风景图,那么值为0就不是风景图;

2、我们使用MAE(平均绝对误差),计算最终的误差值;常见的误差函数,定义在tf.keras.losses,大家可以阅读,选择合适的误差函数。

下图是运行输出日志:

 3 总结

1、Conv2D卷积层,负责学习图片一些特征。靠前的卷积网络层,可以学习到简单的特征(边界,位置等),后面的卷积层则在简单特征上,学习更复杂的特征(线条,形状等),从而实现功能强大的系统;

2、MaxPool2D池化层,一是可以放大占主导位置的特征,二是能够有效减少运算,本文设置strides=(1,1),所以没有缩小输出尺寸,实际应用过程中可以设置strides=(2,2),这样输出尺寸直接缩小为原图片的一半,极大地减少运算量;

3、可以在深度学习网络中,添加多层卷积层和池化层,让网络学习到更复杂的特征;

4、Flatten函数,是把多维数组平铺成1维数组,为了后续的全连接层而准备;

5、Dense全连接层,构造合适的输出结果;

6、误差函数,在训练过程可以根据训练误差,调整我们的模型参数;在测试/验证过程,可以记录测试误差,从而重新调整我们的训练模型;

文中只用极少的一部分函数和功能,更多的用法需要大家自行摸索。


 

  • 9
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值