深度学习500问——Chapter12:网络搭建及训练(1)

2024-06-16 11:28

本文主要是介绍深度学习500问——Chapter12:网络搭建及训练(1),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

12.1 TensorFlow

12.1.1 TensorFlow 是什么

12.1.2 TensorFlow的设计理念是什么

12.1.3 TensorFlow特点有哪些

12.1.4 TensorFlow的系统架构是怎样的

12.1.5 TensorFlow编程模型是怎样的

12.1.6 如何基于TensorFlow搭建VGG16


12.1 TensorFlow

12.1.1 TensorFlow 是什么

TensorFlow支持各种异构平台,支持多CPU/GPU、服务器、移动设备,具有良好的跨平台的特性;TensorFlow架构灵活,能够支持各种网络模型,具有良好的通用性;此外,TensorFlow架构i具有良好的可扩展性,对OP的扩展支持,Kernel特化方面表现出众。

TensorFlow最初由Google大脑的研究员和工程师开发出来,用于机器学习和神经网络方面的研究,于2015.10宣布开源,在众多深度学习框架中脱颖而出,在Github上获得了最多的Star量。

12.1.2 TensorFlow的设计理念是什么

TensorFlow的设计理念主要体现在两个方面:

(1)将图定义和图运算完全分开。TensorFlow 被认为是一个“符号主义”的库。我们知道,编程模式通常分为命令式编程(imperative style programming)和符号式编程(symbolic style 皮肉gramming)。命令式编程就是编写我们理解的通常意义上的程序,很容易理解和调试,按照原有逻辑执行。符号式编程涉及很多的嵌入和优化,不容易理解和调试,但运行速度相对有所提升。现有的深度学习框架中,Torch是典型的命令式的,Caffe、MXNet采用了两种编程模式混合的方法,而TensorFlow完全采用符号式编程。

符号式计算一般是先定义各种变量,然后建立一个数据流图,在数据流图中规定各个变量间的计算关系,最后需要对数据流图进行编译,但此时的数据流图还是一个空壳,里面没有任何实际数据,只有把需要运算的输入放进去后,才能在整个模型中形成数据流,从而形成输出值。

        例如:

t = 8 + 9
print(t)

  在传统的程序操作中,定义了 t 的运算,在运行时就执行了,并输出 17。而在 TensorFlow中,数据流图中的节点,实际上对应的是 TensorFlow API 中的一个操作,并没有真正去运行:

import tensorflow as tf
t = tf.add(8,9)
print(t)#输出  Tensor{"Add_1:0",shape={},dtype=int32}

(2)TensorFlow 中涉及的运算都要放在图中,而图的运行只发生在会话(session)中。开启会话后,就可以用数据去填充节点,进行运算;关闭会话后,就不能进行计算了。因此,会话提供了操作运行和 Tensor 求值的环境。

  例如:

import tensorflow as tf
#创建图
a = tf.constant([4.0,5.0])
b = tf.constant([6.0,7.0])
c = a * b
#创建会话
sess  = tf.Session()
#计算c
print(sess.run(c))   #进行矩阵乘法,输出[24.,35.]
sess.close()

12.1.3 TensorFlow特点有哪些

1. 高度的灵活性

        TensorFlow并不仅仅是一个深度学习库,只要可以把你的计算过程表示成一个数据流图的过程,我们就可以使用TensorFlow来进行计算。TensorFlow允许我们用计算图的方式建立计算网络,同时又可以很方便的对网络进行操作。用户可以基于TensorFlow的基础上用Python编写自己的上层结构和库,如果TensorFlow没有提供我们需要的API的,我们也可以自己编写底层的C++代码,通过自定义操作将新编写的功能添加到TensorFlow中。

2. 真正的移植性

        TensorFlow 可以在 CPU 和 GPU 上运行,可以在台式机、服务器、移动设备上运行。你想在你的笔记本上跑一下深度学习的训练,或者又不想修改代码,想把你的模型在多个CPU上运行, 亦或想将训练好的模型放到移动设备上跑一下,这些TensorFlow都可以帮你做到。

3. 多语言支持

        TensorFlow采用非常易用的python来构建和执行我们的计算图,同时也支持 C++ 的语言。我们可以直接写python和C++的程序来执行TensorFlow,也可以采用交互式的ipython来方便的尝试我们的想法。当然,这只是一个开始,后续会支持更多流行的语言,比如Lua,JavaScript 或者R语言。

4. 丰富的算法库

        TensorFlow提供了所有开源的深度学习框架里,最全的算法库,并且在不断的添加新的算法库。这些算法库基本上已经满足了大部分的需求,对于普通的应用,基本上不用自己再去自定义实现基本的算法库了。

5. 完善的文档

TensorFlow的官方网站,提供了非常详细的文档介绍,内容包括各种API的使用介绍和各种基础应用的使用例子,也包括一部分深度学习的基础理论。

  自从宣布开源以来,大量人员对TensorFlow做出贡献,其中包括Google员工,外部研究人员和独立程序员,全球各地的工程师对TensorFlow的完善,已经让TensorFlow社区变成了Github上最活跃的深度学习框架。

12.1.4 TensorFlow的系统架构是怎样的

整个系统从底层到上层可分为七层:

设备层:硬件计算资源,支持CPU、GPU

网络层:支持两种通信协议

数值计算层:提供最基础的计算,有线性计算、卷积计算

高维计算层:数据的计算都是以数组的形式参与计算

计算图层:用来设计神经网络的结构

工作流层:提供轻量级的框架调用

构造层:最后构造的深度学习网络可以通过TensorBoard服务端可视化

12.1.5 TensorFlow编程模型是怎样的

TensorFlow 的编程模型:让向量数据在计算图里流动。那么在编程时至少有这几个过程:1、构建图;2、启动图;3、给图输入数据并获取结果。

1. 构建图

TensorFlow 的图的类型是 tf.FGraph,它包含着计算节点和tensor的集合。

这里引用了两个新概念:tensor和计算节点。我们先介绍tensor,一开始我们就介绍了,我们需要把数据输入给启动的图才能获取计算结果。那么问题来了,在构建图时用什么表示中间计算结果?这个时候tensor的概念就需要引入了。类型是 tf.Tensor,代表某个计算节点的输出,一定要看清楚是“代表”。它主要有两个作用:

(1)构建不同计算节点直接的数据流

(2)在启动图时,可以设置某些tensor的值,然后获取指定tensor的值。这样就完成了计算的输入输出功能。

如下代码所示:

inImage = tf.placeholder(tf.float32,[32,32,3],"inputImage")
processedImage = tf.image.per_image_standardization(inImage,"processedImage")

 这里inImage和processedImage都是tensor类型。它们代表着计算节点输出的数据,数据的值具体是多少在启动图的时候才知道。上面两个方法调用都传递了一个字符串,它是计算节点的名字,最好给节点命名,这样我们可以在图上调用get_tensor_by_name(name)获取对应的tensor对象,十分方便。(tensor名字为“<计算节点名字>:<tensor索引>”)

  创建tensor时,需要指定类型和shape。对不同tensor进行计算时要求类型相同,可以使用 tf.cast 进行类型转换。同时也要求 shape (向量维度)满足运算的条件,我们可以使用 tf.reshape 改变shape。

  现在了解计算节点的概念,其功能是对tensor进行计算、创建tensor或进行其他操作,类型是tf.Operation。获取节点对象的方法为get_operation_by_name(name)。

构建图,如下代码:

g=tf.Graph()with g.as_default():input_data=tf.placeholder(tf.float32,[None,2],"input_data")input_label=tf.placeholder(tf.float32,[None,2],"input_label")W1=tf.Variable(tf.truncated_normal([2,2]),name="W1")B1=tf.Variable(tf.zeros([2]),name="B1")output=tf.add(tf.matmul(input_data,W1),B1,name="output")cross_entropy=tf.nn.softmax_cross_entropy_with_logits(logits=output,labels=input_label)train_step=tf.train.AdamOptimizer().minimize(cross_entropy,name="train_step")initer=tf.global_variables_initializer()

上面的代码中我们创建了一个图,并在上面添加了很多节点。我们可以通过调用get_default_graph()获取默认的图。

  Input_data,input_label,W1,B1,output,cross_entropy都是tensor类型,train_step,initer,是节点类型。

有几类tensor或节点比较重要,下面介绍一下:

(1)placeholder

Tensorflow,顾名思义, tensor代表张量数据,flow代表流,其最初的设计理念就是构建一张静态的数据流图。图是有各个计算节点连接而成,计算节点之间流动的便是中间的张量数据。要想让张量数据在我们构建的静态计算图中流动起来,就必须有最初的输入数据流。而placeholder,翻译过来叫做占位符,顾名思义,是给我们的输入数据提供一个接口,也就是说我们的一切输入数据,例如训练样本数据,超参数数据等都可以通过占位符接口输送到数据流图之中。使用实例如下代码:

import tensorflow as tf
x = tf.placeholder(dtype=tf.float32,shape=[],name='x')
y = tf.placeholder(dtpe=tf.float32,shape=[],nmae='y')
z = x*y
with tf.Session() as sess:prod = sess.run(z,feed_dict={x:1.,y:5.2})print(prod)
[out]:5.2

(2)variable

无论是传统的机器学习算法,例如线性支持向量机(Support Vector Machine, SVM),其数学模型为y = <w,x> + b,还是更先进的深度学习算法,例如卷积神经网络(Convolutional Neural Network, CNN)单个神经元输出的模型y = w*x + b。可以看到,w和b就是我们要求的模型,模型的求解是通过优化算法(对于SVM,使用 SMO[1]算法,对于CNN,一般基于梯度下降法)来一步一步更新w和b的值直到满足停止条件。因此,大多数机器学习的模型中的w和b实际上是以变量的形式出现在代码中的,这就要求我们在代码中定义模型变量。

import tensorflow as tf
a = tf.Variable(2.)
b = tf.Variable(3.)
with tf.Session() as sess:sess.run(tf.global_variables_initializer()) #变量初始化print(sess.run(a*b))
[out]:6.

[1] Platt, John. "Sequential minimal optimization: A fast algorithm for training support vector machines." (1998).

(3)initializer

由于tensorflow构建的是静态的计算流图,在开启会话之前,所有的操作都不会被执行。因此为了执行在计算图中所构建的赋值初始化计算节点,需要在开启会话之后,在会话环境下运行初始化。如果计算图中定义了变量,而会话环境下为执行初始化命令,则程序报错,代码如下:

import tensorflow as tf
a = tf.Variable(2.)
b = tf.Variable(3.)
with tf.Session() as sess:#sess.run(tf.global_variables_initializer()) #注释掉初始化命令print(sess.run(a*b))
[Error]: Attempting to use uninitialized value Variable

2. 启动图

先了解session的概念,然后才能更好的理解图的启动。   图的每个运行实例都必须在一个session里,session为图的运行提供环境。Session的类型是tf.Session,在实例化session对象时我们需要给它传递一个图对象,如果不显示给出将使用默认的图。Session有一个graph属性,我们可以通过它获取session对应的图。

代码如下:

numOfBatch=5
datas=np.zeros([numOfBatch,2],np.float32)
labels=np.zeros([numOfBatch,2],np.float32)sess=tf.Session(graph=g)
graph=sess.graph
sess.run([graph.get_operation_by_name("initer")])dataHolder=graph.get_tensor_by_name("input_data:0")
labelHolder=graph.get_tensor_by_name("input_label:0")
train=graph.get_operation_by_name("train_step")
out=graph.get_tensor_by_name("output:0")for i inrange(200):result=sess.run([out,train],feed_dict={dataHolder:datas,labelHolder:labels})if i%100==0:saver.save(sess,"./moules")sess.close()

代码都比较简单,就不介绍了。不过要注意2点:1.别忘记运行初始化节点,2.别忘记close掉session对象以释放资源。

3. 给图输入数据并获取结果

代码:

for i inrange(200):result=sess.run([out,train],feed_dict={dataHolder:datas,labelHolder:labels})

 这里主要用到了session对象的run方法,它用来运行某个节点或tensor并获取对应的值。我们一般会一次传递一小部分数据进行mini-batch梯度下降来优化模型。

  我们需要把我们需要运行的节点或tensor放入一个列表,然后作为第一个参数(不考虑self)传递给run方法,run方法会返回一个计算结果的列表,与我们传递的参数一一对应。

  如果我们运行的节点依赖某个placeholder,那我们必须给这个placeholder指定值,怎么指定代码里面很清楚,给关键字参数feed_dict传递一个字典即可,字典里的元素的key是placeholder对象,value是我们指定的值。值的数据的类型必须和placeholder一致,包括shape。值本身的类型是numpy数组。

这里再解释一个细节,在定义placeholder时代码如下:

input_data=tf.placeholder(tf.float32,[None,2],"input_data")
input_label=tf.placeholder(tf.float32,[None,2],"input_label")

  shape为[None,2],说明数据第一个维度是不确定的,然后TensorFlow会根据我们传递的数据动态推断第一个维度,这样我们就可以在运行时改变batch的大小。比如一个数据是2维,一次传递10个数据对应的tensor的shape就是[10,2]。可不可以把多个维度指定为None?理论上不可以!

12.1.6 如何基于TensorFlow搭建VGG16

介绍完关于tensorflow的基础知识,是时候来一波网络搭建实战了。虽然网上有很多相关教程,但我想从最标准的tensorflow代码和语法出发(而不是调用更高级的API,失去了原来的味道),向大家展示如何搭建其标准的VGG16网络架构。话不多说,上代码:

import numpy as np
import tensorflow as tfdef get_weight_variable(shape):return tf.get_variable('weight', shape=shape, initializer=tf.truncated_normal_initializer(stddev=0.1))def get_bias_variable(shape):return tf.get_variable('bias', shape=shape, initializer=tf.constant_initializer(0))def conv2d(x, w, padding = 'SAME', s=1):x = tf.nn.conv2d(x, w, strides=[1, s, s, 1], padding = padding)return xdef maxPoolLayer(x):return tf.nn.max_pool(x, ksize = [1, 2, 2, 1],strides = [1, 2, 2, 1], padding = 'SAME')def conv2d_layer(x,in_chs, out_chs, ksize, layer_name):with tf.variable_scope(layer_name):w = get_weight_variable([ksize, ksize, in_chs, out_chs])b = get_bias_variable([out_chs])y = tf.nn.relu(tf.bias_add(conv2d(x,w,padding = 'SAME', s=1), b))return ydef fc_layer(x,in_kernels, out_kernels, layer_name):with tf.variable_scope(layer_name):w = get_weight_variable([in_kernels,out_kernels])b = get_bias_variable([out_kernels])y = tf.nn.relu(tf.bias_add(tf.matmul(x,w),b))return ydef VGG16(x):conv1_1 = conv2d_layer(x,tf.get_shape(x).as_list()[-1], 64, 3, 'conv1_1')conv1_2 = conv2d_layer(conv1_1,64, 64, 3, 'conv1_2')pool_1 = maxPoolLayer(conv1_2)conv2_1 = conv2d_layer(pool1,64, 128, 3, 'conv2_1')conv2_2 = conv2d_layer(conv2_1,128, 128, 3, 'conv2_2')pool2 = maxPoolLayer(conv2_2)conv3_1 = conv2d_layer(pool2,128, 256, 3, 'conv3_1')conv3_2 = conv2d_layer(conv3_1,256, 256, 3, 'conv3_2')conv3_3 = conv2d_layer(conv3_2,256, 256, 3, 'conv3_3')pool3 = maxPoolLayer(conv3_3)conv4_1 = conv2d_layer(pool3,256, 512, 3, 'conv4_1')conv4_2 = conv2d_layer(conv4_1,512, 512, 3, 'conv4_2')conv4_3 = conv2d_layer(conv4_2,512, 512, 3, 'conv4_3')pool4 = maxPoolLayer(conv4_3)conv5_1 = conv2d_layer(pool4,512, 512, 3, 'conv5_1')conv5_2 = conv2d_layer(conv5_1,512, 512, 3, 'conv5_2')conv5_3 = conv2d_layer(conv5_1,512, 512, 3, 'conv5_3')pool5 = maxPoolLayer(conv5_3)pool5_flatten_dims = int(np.prod(pool5.get_shape().as_list()[1:]))pool5_flatten = tf.reshape(pool5,[-1,pool5_flatten_dims])fc_6 = fc_layer(pool5_flatten, pool5_flatten_dims, 4096, 'fc6')fc_7 = fc_layer(fc_6, 4096, 4096, 'fc7')fc_8 = fc_layer(fc_7, 4096, 10, 'fc8')return fc_8

这篇关于深度学习500问——Chapter12:网络搭建及训练(1)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1066333

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

搭建Kafka+zookeeper集群调度

前言 硬件环境 172.18.0.5        kafkazk1        Kafka+zookeeper                Kafka Broker集群 172.18.0.6        kafkazk2        Kafka+zookeeper                Kafka Broker集群 172.18.0.7        kafkazk3

ASIO网络调试助手之一:简介

多年前,写过几篇《Boost.Asio C++网络编程》的学习文章,一直没机会实践。最近项目中用到了Asio,于是抽空写了个网络调试助手。 开发环境: Win10 Qt5.12.6 + Asio(standalone) + spdlog 支持协议: UDP + TCP Client + TCP Server 独立的Asio(http://www.think-async.com)只包含了头文件,不依

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学