深度学习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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/30780.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微服务架构:解构现代应用程序的未来

目录 前言1. 微服务架构的基本概念1.1 什么是微服务架构1.2 微服务与单体架构的对比 2. 微服务架构的优势2.1 灵活性与可扩展性2.2 持续交付与部署2.3 技术多样性2.4 故障隔离 3. 微服务架构的挑战3.1 服务间通信和数据一致性3.2 运维复杂度3.3 安全性3.4 开发团队的协作 4. 微…

内核学习——1、list_head

双向循环链表&#xff1a;list_head 头节点head是不使用的&#xff1a; struct list_head { struct list_head *next, *prev; }; 结构体中没有数据域&#xff0c;所以一般把list_head嵌入到其他结构中使用 struct file_node { char c; struct list_head node; }; 此时&#xff…

手机铃声下载2个必备技巧,定制化铃声,彰显个性魅力

手机铃声&#xff0c;就像是独特的信号灯&#xff0c;不仅仅是通知我们来电或信息的方式&#xff0c;更是展现个人品位和魅力的武器。手机铃声下载和定制&#xff0c;让你的手机从千万舰队中脱颖而出。在接下来的文章中&#xff0c;我们将详细探讨铃声下载技巧的具体操作步骤&a…

介绍.NET 6款好看的winform开源UI库

开篇概述 在软件开发的世界里&#xff0c;用户界面&#xff08;UI&#xff09;是连接用户与程序的桥梁。对于使用.NET Framework进行WinForms应用程序开发的开发者来说&#xff0c;拥有一个美观、直观且功能丰富的UI库无疑是提升用户体验的关键。今天&#xff0c;我们将一起探索…

2024人工智能指数报告(二):技术性能

背景 从2017年开始&#xff0c;斯坦福大学人工智能研究所&#xff08;HAI&#xff09;每年都会发布一份人工智能的研究报告&#xff0c;人工智能指数报告&#xff08;AII&#xff09;&#xff0c;对上一年人工智能相关的数据进行跟踪、整理、提炼并进行可视化。这份指数报告被认…

深度学习1 -- 开头

一 前言 感觉用这玩意越来越多&#xff0c;所以想学学。不过没想好怎么学&#xff0c;也没有提纲&#xff0c;买了两本书&#xff0c;一本是深度学习入门&#xff0c;小日子写的。还有一本就是花书。还有就是回Gatech参加线上课程&#xff0c;CS7643。 CS 7643: Deep Learnin…

【stm32-新建工程-寄存器版本】

stm32-新建工程-寄存器版本 ■ 下载相关STM32Cube官方固件包&#xff08;F1&#xff0c;F4&#xff0c;F7&#xff0c;H7&#xff09;■ 1. ST官方搜索STM32Cube■ 2. 搜索 STM32Cube■ 3. 点击获取软件■ 4. 选择对应的版本下载■ 5. 输入账号信息■ 6. 出现下载弹框&#xff…

怎么开启22端口访问权限,让别的机器通过ssh或者向日葵等远程控制工具链接

在Ubuntu 24.04上开启22端口访问权限&#xff0c;并允许其他机器通过SSH或向日葵等远程控制工具进行连接&#xff0c;您需要进行以下几步操作&#xff1a; 1. 安装并配置SSH服务器 安装OpenSSH服务器: sudo apt update sudo apt install openssh-server检查SSH服务状态: sudo …

推荐 2 个 牛哔哄哄 的 GitHub 项目

推荐两个开源的 GitHub 项目&#xff0c;一个基于大模型的企业级知识库问答系统&#xff0c;支持管理企业知识库、对话问答、RAG 等功能。 另外一个是计算机视觉的工具箱&#xff0c;使用它你可以在你电脑上实现人体跟踪、分割、检测等一系列计算机视觉的场景。 01 基于 LLM 大…

CR、 LF、CRLF的区别

一、CR LF CRLF的区别 CR (Carriage Return)&#xff0c;LF (Line Feed)&#xff0c;以及 CRLF (Carriage Return Line Feed) 是用于表示文本中换行的控制字符&#xff0c;它们在不同的操作系统和环境中有着不同的使用习惯&#xff1a; CR (Carriage Return) 含义&#xff1…

【unity笔记】二、海洋系统Crest Ocean System插件使用

一、介绍 Crest 是 Unity 技术先进的海洋系统。 它专为性能而设计&#xff0c;并大量使用细节级别 &#xff08;LOD&#xff09; 策略和 GPU 加速来实现快速更新和渲染。它还具有高度的灵活性&#xff0c;允许对水形状/泡沫/动态波浪/等进行任何自定义输入&#xff0c;并具有直…

奇迹MU服务器租用一个月需要多少钱?

在网络游戏产业迅猛发展的今天&#xff0c;越来越多的人参与到各种各样的网络游戏当中。其中&#xff0c;《奇迹MU》作为一款经典的多人在线角色扮演游戏&#xff0c;吸引了大量玩家的关注与热爱。为了保证游戏的流畅运行和玩家体验&#xff0c;租用高性能的服务器至关重要。 《…

01 基础入门 编写你的第一个 Go 语言程序

从这节课开始&#xff0c;我会带你走进 Go 语言的世界。我会用通俗易懂的语言&#xff0c;介绍 Go 语言的各个知识点&#xff0c;让你可以从零开始逐步学习&#xff0c;再深入它的世界。不管你以前是否接触过 Go 语言&#xff0c;都可以从这个专栏中受益。 现在&#xff0c;让…

时隔一年,SSD大涨价?

同样产品&#xff0c;2T&#xff0c;去年400多到手&#xff0c;今年700。 去年 今年

【机器学习】MSE和MAE损失函数有什么区别?回归问题的常用损失函数

在机器学习和统计学中&#xff0c;均方误差&#xff08;Mean Squared Error, MSE&#xff09;和平均绝对误差&#xff08;Mean Absolute Error, MAE&#xff09;是两种常用的损失函数&#xff0c;用于评估模型预测值与真实值之间的差异。它们的区别主要体现在对误差的处理方式和…

使用 Netty 自定义解码器处理粘包和拆包问题详解

使用 Netty 自定义解码器处理粘包和拆包问题详解 在网络编程中&#xff0c;粘包和拆包问题是常见的挑战。粘包是指多个数据包在传输过程中粘在一起&#xff0c;而拆包是指一个数据包在传输过程中被拆分成多个部分。Netty 是一个高性能、事件驱动的网络应用框架&#xff0c;提供…

从零开始精通Onvif之录像存储

&#x1f4a1; 如果想阅读最新的文章&#xff0c;或者有技术问题需要交流和沟通&#xff0c;可搜索并关注微信公众号“希望睿智”。 概述 Onvif的录像存储功能主要由Media、Recording和Replay三个关键服务共同支持。它们协同工作&#xff0c;为录像的存储、检索和播放提供了标准…

3ds Max软件下载安装:3D建模软件 轻松开启你的建模之旅!

3ds Max&#xff0c;在建模过程中&#xff0c;网格建模和NURBS建模两大技术发挥着不可或缺的作用。网格建模允许用户通过顶点、边和面等元素的调整&#xff0c;精确地塑造出模型的形态&#xff1b;而NURBS建模则以其优秀的曲线和曲面处理能力&#xff0c;为设计师们提供了更为平…

迅为RK3568驱动教程第十八期-PWM

系统性PWM课程&#xff0c;完全掌握PWM。采用框架学习法&#xff0c;从基础知识、PWM子系统框架、API函数理论由面到点&#xff0c;逐个击破。通过SG90舵机&#xff0c;呼吸灯的控制把理论转为动手能力。最后从零实现输入捕获驱动程序&#xff0c;深入探究&#xff0c;体验一把…

关键字where 、in、not in、or、and、逻辑运算等组合使用

提示&#xff1a;条件筛选所有的关键字都可以进行任意的组合 文章目录 文章目录Mysql数据库内where关键字的常见用法Mysql数据库中几种比较运算符where之比较查询的方法where之逻辑运算【重点 常用】where之模糊查询&#xff08;类似于正则&#xff09;【重点、常用】where之范…