赞
踩
在上篇博客:深度学习笔记—线性回归(实战)中,我们使用了常规方法实现Boston房价的预测,效果很明显——费力不讨好,代码实现复杂,基本上是公式的实现,耗费时间长,损失下降不明显,如果我们真拿这个去交付给用户使用,恐怕会被骂个狗血淋头,所以我们得建立一个更好的,效率更高的,更稳定的模型。
人和动物的区别就是是否会使用工具,我们要想更高效的建立和训练模型,也需要学会使用工具—TensorFlow。
TensorFlow是一个基于数据流编程(dataflow programming)的符号数学系统,被广泛应用于各类机器学习(machine learning)算法的编程实现,其前身是谷歌的神经网络算法库DistBelief 。
Tensorflow拥有多层级结构,可部署于各类服务器、PC终端和网页并支持GPU和TPU高性能数值计算,被广泛应用于谷歌内部的产品开发和各领域的科学研究 。
TensorFlow由谷歌人工智能团队谷歌大脑(Google Brain)开发和维护,拥有包括TensorFlow Hub、TensorFlow Lite、TensorFlow Research Cloud在内的多个项目以及各类应用程序接口(Application Programming Interface, API) 。自2015年11月9日起,TensorFlow依据阿帕奇授权协议(Apache 2.0 open source license)开放源代码 (摘自百度百科) 。
简单来说,TensorFlow就是一个核心开源库,可以帮助我们开发和训练机器学习模型,如果想了解具体信息可以访问TensorFlow官网进行了解,在这里我们就不赘述了。
在上一节的代码实现中,我们用了python自带的数据类型和numpy的数据类型,但是这些数据类型都是早于TensorFlow出现的,导致这些数据类型在TensorFlow不能很好的使用,比如numpy中的array数据类型就不能自动求导,也不能支持GPU运算,所以TensorFlow自己定了了一种数据类型tensor,简单来讲,tensor就是TensorFlow可以接受的数据,几乎所有的数据都可以叫做tensor,包括而不仅限于:
标量就是一个单独的数。
一个向量是一列数
矩阵是一个二维数组
一般的,一个数组中的元素分布在若干维坐标的规则网格中,我们称之为张量。
tensor支持的数据类型
action:tensor支持的所有数据类型都要用tf.int或tf.string等这种表示方法。
我们从名字发现一个很有趣的东西,TensorFlow支持的数据类型为tensor,名字为TensorFlow的前一部分单词,剩下的单词为Flow,意为滑动,流动的意思。这生动的解释了TensorFlow的原理,数据在管道中流动处理,再从出口出来,给出我们想要的结果。
TensorFlow提供了大量功能丰富且繁杂的API接口供使用者调用,除了很复杂的操作外,初学者总能很轻易的找到合适的API实现你想要的功能
但是在使用TensorFlow之前,首先要导入TensorFlow库:
import tensorflow as tf
首先我们来创建一个tensor:
From Numpy List
因为TensorFlow的出现要晚于numpy的出现,所以TensorFlow设计的很多功能和API都学习了numpy的设计,并且对numpy的数据结构也专门设计了方法进行转换:
convert_to_tensor()
convert_to_tensor(
value,
dtype=None,
name=None,
preferred_dtype=None
)
from Numpy
tf.convert_to_tensor(np.ones([2,3]))
tf.convert_to_tensor(np.zeros([2,3]))
该API可numpy中的矩阵直接转换为tensor,并且不仅限于numpy中矩阵,对于list也可直接转化:
tf.convert_to_tensor([1,2])
tf.convert_to_tensor([1,2.])
tf.convert_to_tensor([1],[2.])
我们可以观察第一行代码和第二行代码,唯一的区别就是第一行第二列的数据类型不同,该API可自动配合合适的数据类型。而第二行和第三行代码的区别则是数据维度不同,在这里我们不再赘述。
constant()
tf.constant(
value,
dtype=None,
shape=None,
name='Const',
verify_shape=False
)
创建一个张量,传入list或者数值来填充
使用示例:
tf.constant(1)
tf.constant([1])
tf.constant([1,2.])
tf.constant([1,2.],[3.])#错误用法
注意,若传入多维数据,则每个维度上的数据数量必须一致,否则将发生错误。
zeros() and ones()
tf.zeros(
shape,
dtype=tf.float32,
name=None
)
tf.ones(
shape,
dtype=tf.float32,
name=None
)
用法示例
tf.zeros([])
tf.zeros([1])
tf.zeros([2,2])
tf.zeros([2,3,3])
tf.ones(1)
tf.ones([2])
tf.ones([2,3])
zeros()和ones() 就像一对孪生兄弟,输入想要的维度,API自动帮你填充0或1,一目了然。
zeros_like() and ones_like()
tf.zeros_like(
tensor,
dtype=None,
name=None
)
tf.ones_like(
tensor,
dtype=None,
name=None
)
用法示例
a = tf.zeros([2,3,3])
tf.zeros_like(a)
tf.ones_like(a)
除去去ones孪生兄弟外,tensorflow还提供了ones_lie()这对孪生兄弟,但是不同的是,ones兄弟需要给定tensor维度,而ones_like()兄弟则需要给定一个tensor作为参数,该API按照tensor的维度重新建立一个tensor。
fill()
tf.fill(
dims,
value,
name=None
)
dims: 类型为int32的tensor对象,用于表示输出的维度(1-D, n-D),通常为一个int32数组,如:[1], [2,3]等
value: 常量值(字符串,数字等),该参数用于设置到最终返回tensor对象中的值
name: (可选)当前操作别名
用法示例:
tf.fill([2,2],0)
tf.fill([2,2],0.0)
tf.fill([2,2],1)
fill()是一种很灵活的建立tensor的方法,只需要修改填入的数值就可以很轻松的取代ones兄弟和ones_like()兄弟。
random.normal()
用于从服从指定正太分布的数值中取出随机数。一般用于参数初始值的赋值。
tf.random_normal(
shape,
mean=0.0,
stddev=1.0,
dtype=tf.float32,
seed=None,
name=None
)
shape: 输出张量的形状,必选
mean: 正态分布的均值,默认为0
stddev: 正态分布的标准差,默认为1.0
dtype: 输出的类型,默认为tf.float32
seed: 随机数种子,是一个整数,当设置之后,每次生成的随机数都一样
name: 操作的名称
使用示例:
tf.random.normal([2,2],mean=1,stddv=1)#正态分布 均值 方差
tf.random.normal([2,2])#默认均值方差均为0
random.truncated_normal()
输出截断的正态分布的随机值。说的简单些,就是输出正态分布的一部分。
tf.random.truncated_normal(
shape,
mean=0.0,
stddev=1.0,
dtype=tf.dtypes.float32,
seed=None,
name=None
)
shape:一个一维整数张量或Python数组。输出张量的形状。
mean:一个零维张量或Python值,类型为dtype。截断正态分布的均值。均值默认为0
stddev:一个零维张量或Python值,类型为dtype。正态分布的标准偏差,在截断。截断前正态分布的标准偏差,默认为1.0
dtype:输出的类型。
seed:一个Python整数。用于为分布创建随机种子。
名称:操作的名称(可选)。
使用示例:
tf.random.truncated_normal([2,2],mean=0,stddev=1)#截断方差
random.uniform()
random_uniform(
shape,# 生成的张量的形状
minval=0,
maxval=None,
dtype=tf.float32,
seed=None,
name=None
)
shape:一维整数张量或 Python 数组.输出张量的形状
.
minval:dtype 类型的 0-D 张量或 Python 值;生成的随机值范围的下限;默认为0.
maxval:dtype 类型的 0-D 张量或 Python 值.要生成的随机值范围的上限.如果 dtype 是浮点,则默认为1 .
dtype:输出的类型:float16、float32、float64、int32、orint64.
seed:一个 Python 整数.用于为分布创建一个随机种子.查看
tf.set_random_seed 行为.
name:操作的名称(可选).
使用示例:
tf.random.uniform([2,2],minval=0,maxval=1)#均匀分布
tf.random.uniform([2,2],minval=0,maxval=10)
跟random.normal()类似,random.uniform()同样是给出随机值,便于参数更新。
我们在学习java,c,以及python等编程语言时,可以很方便的使用指针或者或者索引解决找位置的为题,在tensorflow中,为了方便寻找数据,也提供了功能强大是索引方法,与java数组中的索引方式类似。
方法一
import tensorflow as tf
import numpy as np
a = tf.ones([1,5,5,3])
#(1, 5, 5, 3)
print(a.shape)
(5, 3)
print(a[0][0].shape)
#(3,)
print(a[0][0][0].shape)
#()
print(a[0][0][0][2].shape)
tensorflow中的索引方式与numpy矩阵中的索引方式类似,用法也极为相像。
方法二
import tensorflow as tf
a = tf.range(10)
print(a)
print(a[3:5].shape)
#(1.)
print(a[-1:].shape)
注意:此方法仅适用于向量。
方法三
import tensorflow as tf
import numpy as np
a = tf.ones([5,5,5,5])
#(5,5,5)
print(a[2,:,:,:].shape)
#(5,5)
print(a[2,2,:,:].shape)
#(5,5,5)
print(a[:,:,:,3].shape)
:用来占位,即表示该维度全选。
方法四
import tensorflow as tf
import numpy as np
a = tf.ones([5,5,5,5])
#(1,5,5,5)
print(a[2:3,:,:,:].shape)
#(3,5,5,5)
print(a[2:,:,:,:].shape)
#(2,1,5,5)
print(a[2:,2,:,:].shape)
实际上这种切片方法很像是方法二和方法三的混合体,实际上效果也是验证了。
以上四种方法虽然能很便捷的截取tensor的一部分,但是都存在局限性,只能选取某一维度上的某一位置的所有数据,或者是某 一维度上的某几个连续位置上的所有数据,这明显不方便我们对数据使用和处理,所以tensor也提供了几个特殊的方法,满足我们的需求。
gather
gather(
params,
indices,
validate_indices=None,
name=None
)
params:是一个tensor,
indices:是个值为int的tensor用来指定要从params取得元素的第0维的index。
validate_indices:针对哪一维度进行的操作。
name:操作的名字。
使用示例:
import tensorflow as tf
import numpy as np
a = tf.random.normal([2,4,28,28,3])
#(2, 2, 28, 28, 3)
print(tf.gather(a,axis=1,indices=[2,3]).shape)
gather一词是收集的意思,从结果上我们可以很清楚的看到,确实是收集,针对某一维度的某几个不连续的位置进行数据提取操作,并且组成一个新的张量。
gather_nd
gather_nd(
params,
indices,
name=None
)
params:张量.这个张量是用来收集数值的.
indices:张量.必须是以下类型之一:int32,int64;索引张量.
name:操作的名称(可选).
使用示例:
import tensorflow as tf import numpy as np a = tf.random.normal([2,4,28,28,3]) #(4, 28, 28, 3) print(tf.gather_nd(a,[0]).shape) #(28, 28, 3) print(tf.gather_nd(a,[0,1]).shape) #(28, 3) print(tf.gather_nd(a,[0,1,2]).shape) #(1, 28, 3) print(tf.gather_nd(a,[[0,1,2]]).shape) #(3, 4, 28, 28, 3) print(tf.gather_nd(a,[[0],[1],[2]]).shape) #(2, 28, 28, 3) print(tf.gather_nd(a,[[0,1],[1,3]]).shape)
从示例中我们可以看到,gather_nd()是一个比gather更为灵活的方法,不仅可以java中索引式取某一维度上所有的数据,还能像gather()方法一样,只取部分数据,并且合并成一个新的张量。
boolean_mask()
tf.boolean_mask(
tensor,
mask,
name='boolean_mask',
axis=None
)
tensor:N维度的tensor,
mask:由布尔值构成的K维度的列表,注意K小于等于N,
name:可选项也就是这个操作的名字,
axis是一个0维度的int型数字,表示的是从参数tensor的哪个axis开始过滤。
使用示例:
a=tf.random.normal([4,28,28,3])
#([2, 28, 28, 3])
print(tf.boolean_mask(a,mask=[True,True,False,False]).shape)
#([4, 28, 28, 2])
print(tf.boolean_mask(a,mask=[True,True,False],axis=3).shape)
boolean_mask 是依据索引出的TRUE和False值判断是否去该维度的数据,如果仅仅只是那么简单,为什么还要设计这个功能呢,岂不是重复了,所以boolean_mask的功能没有那么简单。
import tensorflow as tf
import numpy as np
a = tf.random.normal([2,3,4])
#(4,4)
print(tf.boolean_mask(a,mask=[[True,False,True],[False,True,True]]).shape)
#(3,4)
print(tf.boolean_mask(a,mask=[[True,False,False],[False,True,True]]).shape)
在boolean_mask()函数中,将mask参数换成多维列表,则可以与tensor中的维度相对应取值,更为方便快捷。
tf.reshape(
tensor,
shape,
name=None
)
tensor:需要进行维度变换的的张量。
shape:张量要变成的形状。
name:操作名称。
使用示例:
import tensorflow as tf
import numpy as np
a = tf.random.normal([4,28,28,3])
#(4, 784, 3)
print(tf.reshape(a,[4,28*28,3]).shape)
#(4, 784, 3)
print(tf.reshape(a,[4,-1,3]).shape)
#
print(tf.reshape(a,[4,-1]).shape)
#(4, 1, 784, 3)
print(tf.reshape(tf.reshape(a,[4,-1]),[4,-1,784,3]))
transpose()
tf.transpose(
matrix,
perm=None
)
matrix:待变换的张量。
perm:张量变换方式的具体参数。
使用示例:
import tensorflow as tf
import numpy as np
a = tf.random.normal([4,28,28,3])
#(3, 28, 28, 4)
print(tf.transpose(a).shape)
#(4, 28, 3, 28)
print(tf.transpose(a,perm=[0,1,3,2]).shape)
从使用示例上来看,transpose方法和reshape方法在功能上有些重合,但是在transpose方法更为灵活,在不指定matrix参数时,transpose方法默认将tensor的维度倒序,同时在指定matrix参数指定为列表时,会按照列表排序来变换。
expand_dims()
tf.expand_dims(
input,
axis=None,
name=None,
dim=None
)
input是输入张量。
axis是指定扩大输入张量形状的维度索引值。
dim等同于轴,一般不推荐使用。
使用示例;
import tensorflow as tf
import numpy as np
a = tf.random.normal([4,28,28,3])
#(1, 4, 28, 28, 3)
print(tf.expand_dims(a,axis=0).shape)
#(4, 28, 28, 3, 1)
print(tf.expand_dims(a,axis=-1).shape)
从示例中我们可以很清楚的看出来,expand_dims()方法用于向张量中加入一个新的维度,而axis参数可控制添加维度的位置。
squeeze()
squeeze(
input,
axis=None,
name=None,
squeeze_dims=None
)
input: 需要压缩的tensor
axis: 如果指定,只能挤压列出的维度。维度索引从 0 开始。压缩非 1 的维度是错误的,并且必须在范围内。
name: 操作的名称 (可选)
squeeze_dims: 已弃用的关键字参数,现在是axis。
使用示例:
import tensorflow as tf
import numpy as np
a = tf.random.normal([4,28,28,3])
#(2, 3)
print(tf.squeeze(tf.zeros([1,2,1,1,3])).shape)
b = tf.ones([1,2,1,3])
#(2, 1, 3)
print(tf.squeeze(b,axis=0).shape)
#(1, 2, 3)
print(tf.squeeze(b,axis=2).shape)
该函数返回一个张量,这个张量是将原始input中所有维度为1的那些维都删掉的结果
axis可以用来指定要删掉的为1的维度,此处要注意指定的维度必须确保其是1,否则会报错。如果axis不指定,则默认删除所有为1的维度。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。