Tensorflow具有强大的可移植性,支持GPU、CPU、安卓、ios等多计算平台,所以开发者可以在移动平台上开发复杂的深度学习应用;例如谷歌翻译中广受好评的图片即时翻译,即依赖于移动平台上Tensorflow,使用户手机本地完成计算的。
一:神经网络的发展历史:
①:1943仿生机器学习。
②:1958年,发现感知模型,感知机是首个可以根据样例数据来学习特征权重的模型。
③:1969年,不能解决异或问题,只能解决线性可分问题。
④:20世纪80年代,第二波神经网络因分布式知识表达和神经网络反向传播算法的提出而兴起,解决了线性不可分问题。
⑤:在90年代,随着神经网络发展的同时,传统的机器学习算法有了突破性的进展,并超越了神经网络。
⑥:随着大数据云时代等等的到来,神经网络的优势逐渐凸显出来。
语音识别方面,谷歌在2009年时,谷歌启动语音识别应用时,使用的是学术界研究了30年多的高斯混合模型,12年,深度学习在语音识别中的应用取代了GMM,并将错误率降低了百分20.因为不在需要GMM时的手工提取特征。
二:Tensorflow主要有计算模型、数据模型和运行模型。
tf.Graph() 函数非常重要,注意提现在两个方面
1. 它可以通过tensorboard用图形化界面展示出来流程结构
2. 它可以整合一段代码为一个整体存在于一个图中
声明情况大体有三种
1. tensor:通过张量本身直接出graph
计算图是tensorflow的最基本的概念,Tensor是张量,可以被简单的理解为多维数组;Flow则体现它的计算模型,FLow翻译为中文是流的意思,直观地表达了张量之间通过计算相互转化的过程。TensorFlow是通过计算图的形式来表达计算的编程系统。TensorFLow中每一个计算都是计算图中的一个节点,节点之间的边描述了计算之间的依赖关系。
import tensorflow as tf a=tf.constant([1.0,2.0],name="a") b=tf.constant([2.0,3.0],name="b") result=a+b
在计算过程中tensorflow会自动将定义的计算转化为计算图上的节点,并且在tensorflow程序中,系统会自动维护一个默认的计算图。
print(a.graph is tf.get_default_graph())
通过tf.get_default_graph函数获取当前默认的计算图,a.graph可以查看张量所属的计算图,因为没有特意指定,所以这个计算图应该等于当前默认的计算图,所以输出结果为True。
除了使用默认计算图,tensorflow支持通过tf.graph函数来生成新的计算图,不同的是图上的张量和运算都不会共享。
import tensorflow as tf g1=tf.Graph() with g1.as_default(): v=tf.get_variable("v",initializer=tf.zeros_initializer(shape=[1])) g2=tf.Graph() with g2.as_default(): v=tf.get_variable("v",initializer=tf.ones_initializer(shape=[1])) with tf.Session(graph=g1) as sess: tf.initialize_all_variables().run() with tf.variable_scope("",reuse=True): print(sess.run(tf.get_variable("v"))) with tf.Session(graph=g2) as sess: tf.initialize_all_variables().run with tf.variable_scope("",reuse=True): print(sess.run(tf.get_variable("v")))
Tensorflow的计算图不仅仅可以用来隔离张量和计算,还提供了管理张量和计算的机制。计算图可以通过tf.Graph.device函数来制定运行计算的设备,这位Tensoflow使用GPU提供了机制。
g=tf.Graph() with g.device('/gpu:0'): result =a+b
在一个计算图中,可以通过几何(collection)来管理不同类别的资源,比如通过tf.add_to_collection函数可以将资源加入一个或多个集合中,然后通过tf.get_collection获取一个集合里面的所有资源,这里的资源可以是张量、变量或者最常用的集合。
张量是一个重要的概念,在tensorflow程序中,所有数据都通过张量的形式来表达,但是张量在tensorflow中并不是直接采用数组的形式,它只是对tensorflow中运算结果的引用,在张量中并没有真正保存数字,而是这些数字的计算过程。
例如:输出了Tensor("add:0",shape=(2.),dtype=float32)
这个张量Tensor中保存了三个属性:名字(name)、维度(shape)、类型(type)。
张量的名字是张量的唯一标识符,并给出张量是如何计算出来的,计算图上的每一个节点代表一个计算,计算的结果保存在张量中,张量和计算图上的节点所代表的结果是对应的,0代表当前张量来自节点的第几个输出。0代表是第一个输出。
shape(2,)表示张量是一个一维数组,数组的长度为2.维度是张量的一个重要属性。
type表示张量的类型,每个张量都会有唯一的类型。
计算图等都是说的计算模型,与计算模型相比起来,数据模型相对简单。
张量的使用主要分为两大类;
①:对中间计算结果的引用。当一个计算包含很多中间结果时,使用张量可以大大提高代码的可读性。如前面的a,b都是中间计算结果的引用,代替tf.constan();
②:使用张量的第二类情况是当计算图构造完成之后,张量可以用来获得计算结果,也就是得到真实的数字。即通过会话(session),就可以得到具体数字,如tf.Session().run(result)得到最后计算结果。
tensorflow运行模式-会话
tensorflow会话模式用来执行定义好的运算,会话拥有并管理tensorflow程序运行时的资源。当算有计算完成之后需要关闭会话来帮助系统收回资源,否则就可能出现资源泄露的问题。
tensorflow的会话模式有两种:
①:明确定义会话生成函数和关闭会话函数。
sess=tf.Session() sess.run(result) sess.close()
当程序因为异常退出时,关闭会话的函数可能就不会被执行而导致资源遗漏。
②:tensorflow通过python的上下文资源管理器来使用会话。
#创建一个会话,并用python中的上下文资源管理器来管理这个会话。 with tf.Session as sess: sess.run() #当上下文退出时会话关闭和资源释放也自动完成。
如果没有特殊指定,运算会自动加入这个计算图,tensorflow中的会话也有类似的机制,tensorflow不能自动生成会话机制,需要手动指定。
交互式环境下,如(python脚本或者Jupyter的编辑器下),通过设置默认会话的方式来获取张量的取值更加方便,使用tf.InteractiveSession()函数来自动生成的会话注册为默认会话。
tf.InteractiveSession() #函数省去了将产生的会话注册为默认会话的过程,无论使用哪种方式都可以通过COnfigProto Config Buffer来配置生成的会话 config=tf.ConfigProto(allow_soft_placement=True, log_device_placement=True) sess1=tf.InteractiveSession(config=config) sess2=tf.Session(config=config)
通过ConfigProto可以配置类似并行的线程数、GPU分配策略、运算超时时间等参数。
在这些参数中最常用的是两个
①:allow_soft_placement,这是一个布尔型的参数,当它为True的时候,可以在以下任意一个条件成立的时候,GPU上的运算可以放在CPU上进行,即当无法被当前GPU支持时,可以自动调入CPU上,而不是报错:
1.运算无法在GPU上运行
2.没有GPU资源,如运算指定在第二个GPU上运行但是只有一个GPU
3.运算输入包含对CPU计算结果的引用。
过拟合问题的解决
如果一个模型的参数比训练数据还多,或者说特征过多,那么训练数据时这个模型完全可以记住训练集的结果从而损失函数为0,导致过拟合;过度拟合训练数据中的随机噪音虽然可以得到非常小的损失函数,但是无法对新数据得到可靠的判断。
所以为了防止过拟合,提出了一种正则化的思想;
正则化就是在损失函数中加入刻画模型复杂度程度的指标;正则化来刻画模型的复杂度的函数主要有两种L1正则化和L2正则化。
无论哪种正则化方式,基本思想都是希望通过限制权重的大小,使得模型不能任意拟合训练数据中的随机噪声;
两种正则化的区别:
L1正则化会让参数变得稀疏,而L2正则化则不会。岁尾参数变得稀疏是指会有更多参数变为0,这样可以达到类似特征选取的功能。之所以L2正则化不会让参数变得更加稀疏的原因是参数很小时比如0.001,这个参数的平方基本上就可以忽略了,于是模型就不会将其改为0了,其次L1正则化不可导,L2正则化公式可到会更加简洁,通常情况下我们会将L1正则化和L2正则化进行混合使用。
损失函数刻画了我们需要优化的目标。
通过指数衰减系数设置学习率可以加快训练初期的训练速度,同时在训练后期不会出现在损失函数在极小值附近徘徊的情况;