TensorFlow深度学习入门详解_tensorflow深度学习基础教程-程序员宅基地

技术标签: python  tensorflow  深度学习  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、误差函数,在训练过程可以根据训练误差,调整我们的模型参数;在测试/验证过程,可以记录测试误差,从而重新调整我们的训练模型;

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


 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u010312678/article/details/128638102

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签