[技术交流] TensorFlow 基础操作

TensorFlow 基础操作

1.    数据类型

1.1. 常见的数据类型载体

l  Listlist设计非常的灵活,可以随意的**添加和编辑,内存的管理不是很连续。对于高维度数据的读取和写入效率也会很低。

l  np.array专门用来解决同类型数据运算的一个载体,可以很方便的将图片数据进行吞吐和转置等计算操作。弊端:在深度学习之前就已设计和广泛应用的科学计算库,没有很好的GPU计算支持,也不能支持自动求导。因此tensorflow 就应运而生。

l  tf.Tensor: TensorFlow Numpy的地位在某种层面上相似,例如一些拼接,random的操作等等。而且为了方便使用Numpy的开发者,能够更便利的转移到TensorFlow,在一些API的命名上也很相似。只不过功能上更加偏重于神经网络的计算。

1.2. 什么叫tensor

l  Scalar(标量)1.12…,实质是指一个准确的数据类型。如果是标量1.1:维度为0

l  Vector(向量): [1.1], [1.1, 2.2, 3.3]。如果是向量[1.1]:维度是1

l  Matrix(矩阵): [[1.1,2.2],[3.3,4.4],[5.5,6.6]]。维度通常描述为m*n

l  tensor(张量): 数学上用到的定义:一般是指维度大于2的都称为tensor。在TensorFlow中习惯上将标量和一维向量也称为tensor,因此所有的数据都可以称为tensor

1.3. flow

图片.png

很多的数据经过很多的操作从输入到输出完成一个flow的过程,就像水流一样连接每一个管道完成每一个运算。

1.4. V2.0中常用数据类型

TensorFlow中常用的数据类型有:

l  int, float, double:

p  tf.constant(1) : constant沿用1.0版本,可以理解成是一个普通的tensor

       <tf.Tensor: id=4, shape=(), dtype=int32, numpy=1>

p  tf.constant(1.)

       <tf.Tensor: id=4, shape=(), dtype=float32, numpy=1.0>

p  tf.cosntant(2.2, dtype=tf.int32),如果输入2.2 但是指定类型为int类型,则会报错 

p  tf.constant(2., dtype=tf.double)

        <tf.Tensor: id=7, shape=(), dtype=float64, numpy=2.0>,指定双精度类型          double型实质是一个别名,对应的是 float64

l  bool: 布尔类型

p  tf.constant([True, False])

       <tf.Tensor: id=9, shape=(2,), dtype=bool, numpy=array([True, False])

l  string:

p  tf.constant(hello,world)

       <tf.Tensor: id=14, shape(), dtpype=string, numpy=bhello,world>

1.5. V2.0常用的属性(device)

l  device

with tf.device(cpu)

        a=tf.constant(1)

with tf.device(gpe)

        b=tf.range(4)

#可以判断tensor ab分别在哪一个设备上

a.device    #返回:device:CPU:0

b.device    #返回:device:GPU:0

l  如果需要将tensorCPUGPU之间相互转移,操作如下:

aa=a.gpu()     

aa.device #此时返回为:device:GPU:0

bb=b.gpu()    

bb.device #此时返回为:device:CPU:0

1.6. V2.0常用的属性(numpy,ndim)

l  numpy:支持tensor类型直接转换成np.array

b.numpy()     

array([0,1,2,3],dtype=int32)

#直接指定要转换的数据类型

int(a)      #可以直接转换成int,但前提是,a必须是一个scalar

float(a)

l  查看维度的属性有:

b.ndim    #返回数据维度

b.shape

tf.rank(b)

1.7. V2.0常用的属性(判断tensor)

l  判断是否是tensor

a=tf.constant([1.])

b=tf.constant([true,False])

c=tf.constant(hello,world)

d=np.arange(4)

#判断是否是tensor

tf.is_tensor(b)   #return True

isinstance(a,tf.Tensor)  #return True

tf.is_tensor(d)   #return False

l  查看数据类型

a.dtypeb.dtype c.dtype

return    (tf.float32, tf.bool, tf.string)

a.dtype =tf.float32   #return True

b.dtype=tf..string     #return True

1.8. V2.0常用的属性(数据转换)

l  convert

a=np.arrange(5)   #array([0,1,2,3,4,5])

a.dtype

dtype(int64) #numpy中自动生成int64

#np.array转换成tensor, 且需要指定数据类型为inte32

aa=tf.convert_to_tensor(a,dtype=tf.int32)

l  cast:同样可以实现数据转换,且更简洁,只需要指定dtype

tf.cast(aa, dtype=tf.float32) #指定转换成float32

<tf.Tensor:id=23,shape=(5,),dtype=float32,numpy=array([0.,1.,2.,3.,4.]dtype=float32)>

aaa=tf.cast(aa, dtype=tf.double) #指定转换成float64

<tf.Tensor:id=27,shape=(5,),dtype=float64,numpy=array([0.,1.,2.,3.,4.])>

tf.cast(aaa, dtype=tf.int32)

<tf.Tensor:id=28,shape=(5,),dtype=int32,numpy=array([0,1,2,3,4]dtype=int32)>

l  cast:整型和布尔型之间的转换

b=tf.constant([0,1]) #int32的整型

tf.cast(b,dtype=tf.bool)

<tf.Tensor:id=31,shape=(2,),dtype=bool,numpy=array([False,   True])>

bb=tf.cast(b, dtype=tf.bool) #布尔型

tf.cast(bb, dtype=tf.int32) #布尔型转换成整型

#False对应0True对应1

<tf.Tensor:id=34,shape=(2,),dtype=int32,numpy=array([0,   1]dtype=int32)>  

l  Variable:可求导的属性(专门为神经网络的参数所设计的属性)

a=tf.range(5)

b=tf.Variable(a) #tensor a在进行了variable的包装之后,就具备了可求导的特性。

b.dtype    #tf.int32

b.name    #Varibale:0

iIsinstance(b,tf,tensor)     #False

isinstance(b,tf.Variable)   #True

tf.is_tensor(b)   #True

2.    创建Tensor

2.1. from numpy/list

l  from numpy

tf.convert_to_tensor(np.ones([2,3])) #可以通过dtype来设定为常用的float32int32

<tf.Tensor:id=42,shape=(2,3),dtype=float64,numpy=array([[1.,1.,1.]],[1.,1.,1.]])>

l  from list

#list可转换到tensor的前提是必须能转换成np.array的数据。例如: [1, (12)]不支持转换

tf.convert_to_tensor([1, 2])

<tf.Tensor:id=46,shape=(2,   ),dtype=int32,numpy=array([1, 2], dtype=int32)>

#当数据类型不一致时:一个整型,一个浮点型,返回都是浮点型

tf.convert_to_tensor([1, 2.])

<tf.Tensor:id=48,shape=(2,   ),dtype=float32,numpy=array([1., 2.], dtype=float32)>

2.2. zeros/ones

l  tf.zeros: 初始化全为0

tf.zeros([2,2])  #这里的[2,2]是指shape2*2,区别于convert_to_tensor

<tf.Tensor:id=10,shape=(2,   2),dtype=float32,numpy=array([[0.,0.],[0.,0.]], dtype=float32)>

tf.ones: 类似于tf.zeros,在这里是初始化全为1

tf.ones(1)

<tf.Tensor:id=27,shape=(1,),dtype=float32,numpy=array([1.],   dtype=float32)>

tf.ones([])

<tf.Tensor:id=31,shape=(),dtype=float32,numpy=1.0>

tf.ones([2])

<tf.Tensor:id=31,shape=(),dtype=float32,numpy=array([[1.,   1., 1.], [1., 1., 1.]],dtype=float32>

2.3. normal

l  tf.random.normal(): 随机初始化

tf.random.normal([2,2],mean=1, stddev=1)   #可以指定shape,均值和标准差)

<tf.Tensor:id=57,shape=(2, 2),   dtype=float32, numpy=array([2.3931956, 0.33781087], [1.0709286,   1.1542176]],  dtype=float32)>

tf.ones([])

<tf.Tensor:id=31,shape=(),dtype=float32,numpy=1.0>

tf.ones([2])

<tf.Tensor:id=31,shape=(),dtype=float32,numpy=array([[1.,   1., 1.], [1., 1., 1.]],dtype=float32>

2.4. Uniform/shuffle

l  tf.random.uniform(): 随机均匀分布初始化

#可以指定shape,最小值和最大值。此处以0-1之间的均匀分布为例。

#若不指定均值和标准差,则默认选择均值为0,标准差为1的标准正太分布

tf.random.uniform([2,2],minval=0,   maxval=1)

<tf.Tensor:id=79, shape=(2, 2),   dtype=float32, numpy=array([0.1432991, 0.0267868], [0.08979011,   0.8807217]],  dtype=float32)>

l  tf.random.shuffle(): 将数据顺序打乱

idx=tf.range(10)

idx=tf.random.shuffle(idx)

<tf.Tensor:id=67, shape=(10, ),   dtype=int32, numpy=array([2, 1, 9, 3, 8, 7, 0, 5, 4,6])dtype=float32)>

3.    V2.0索引和切片

l   [start:end]:

a=tf.range(10)

<tf.Tensor:   numpy=array[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])>

a[-1:]

<tf.Tensor:id=48,   shape=(1,), dtype=int32, numpy=array([9])>

a[:2]

<tf.Tensor:id=58,   shape=(2,), dtype=int32, numpy=array([0, 1])>

a[:-1]

<tf.Tensor:id=63,   shape=(2,), dtype=int32, numpy=array([0, 1, 2, 3, 4, 5, 6, 7, 8])>

b=tf.random.normal([4,   28, 28, 3])

b[0,: , :,   :].shape   #TensorShape([28, 28, 3])

l  [start:end:stop]/[::step]

b[:, 0:28:2,   0:28:2, :].shape   #TensorShape([4, 14,   14, 3])

b[:, ::2, ::2,   :].shape         #TensorShape([4, 14,   14, 3])

 

l  [::-1],‘…’: 默认为任意长的冒号

a=tf.random.normal([2,   4, 28, 28, 3])

a[0, ].shape  #TensorShape([4, 28, 28, 3])

a[, 0].shape  #TensorShape([2, 4, 28, 28])

a[1, 0, , 0].shape  #TensorShape([28, 28])

l  tf.gather

data=tf.random.normal([4, 35, 8])

tf.gather(data, axis=0, indices=[2,   3]).shape #参数分别代表:数据源、维度、对应维度的索引号

TensorShape([2, 35, 8])

tf.gather(data, axis=0, indices=[2, 1, 3,   0]).shape  #可以理解为抽取第一个维度的索引所对应的顺序为2,1,3,0

TensorShape([4, 35, 8])

4.    V2.0维度变换

4.1. reshape

reshape的使用方法:

a=tf.random.normal([4, 28, 28, 3])

TensorShape([4, 28, 28, 3])

a.shape, a.ndim #分别返回数据形状和总维度数

TensorShape([4, 28, 28, 3]), 4)

#传入的参数分别为:数据源、目标获得view的方式。784=28*28

tf.reshape(a, [4, 784, 3]).shape  #可以理解为[batch, pixel, channel]

TesorShape([4, 784, 3]), 4)

tf.reshape(a, [4, -1, 3]).shape  #要保证4*-1*3要等于原数据大小,因此-1会自动计算出结果

TesorShape([4, 784, 3]), 4)

tf.reshape(a, [4, 784*3]).shape

TensorShape([4, 2352])

4.2. 转置

l  tf.transpose[w,h] [h, w]

a=tf.random.normal([4, 3, 2, 1])

a.shape

TesorShape([4, 3, 2, 1])

tf.transpose(a).shape

TensorShape([1, 2, 3, 4])

l  指定转置的维度

#指定参数perm,可以指定转置后的维度顺序

tf.transpose(a, perm=[0, 1, 3,   2]).shape  #前两给维度保持不变,交换后两个维度的顺序

TensorShape([4, 3, 1, 2])

4.3. 增加维度

l  维度扩张:expand dim

l  a: [classes, students, classes] [4, 35, 8]: 可以描述为4个班级,每个班级有35个学生,每个学生有8门课程。

l  增加学校的维度: [1, 4, 35, 8]+[1, 4, 35, 8] [2, 4, 35, 8]

a=tf.random.normal([4, 35, 8])

tf.expand_dims(a, axis=0).shape #axis参数来制定要增加维度的位置

TensorShape([1, 4, 35, 8])

tf.expand_dims(a, axis=3).shape #等同于axis=-1

TensorShape([4, 35, 8, 1])

4.4. 减少维度

l  维度压缩:

p  squeeze dim

tf.squeeze(tf.zeros([1, 2, 1, 1,   3])).shape  #默认将维度唯一的维度压缩

TensorShape([2, 3])

p  通过axis参数来指定要压缩的维度:

a=tf.zeros([1, 2, 1, 3])

Tf.squeeze(a, axis=0).shape

TensorShape([2, 1, 3])

4.5. broadcasting(广播)

l  Broadcasting:本质是张量维度扩张的一个手段,指对某一个维度上重复n次但是确没有真正的复制一个数据。

p  扩张

p  没有复制数据

p  通过tf.broadcast_to来实现

p  广播的方法:

p  在需要的时候添加维度,且添加维度的初始size1

p  扩张初始化为1的维度大小与需要进行计算的维度大小相同。

p  : [4, 32, 32, 3]+[3], [3]进行broadcasting,方法如下:[3][1, 1, 1, 3] [4, 32, 32, 3]

4.5.1.广播的优势

l  为什么使用broadcasting

p  编辑代码更加简洁:

[classes, students, scores] : +5 score

[4, 32, 8] + [4, 32, 8],通过expand的方式需要先把维度扩张到相同size 再进行计算。

[4, 32, 8] + [5.0] (此处的5.0为数值,shape8),广播的方式则是在后台自动进行扩张计算。

p  节省内存:不需要复制数据,不占内存。

[4, 32, 8] 1024*4

[8] 8*4

4.5.2.广播的实现

l  广播的实现:不需要输入tf.broadcast_to的命令,而是自动判断该操作符是否支持broadcastng, 如果支持会自动进行广播并完成计算。

a=tf.random.normal([4, 32, 32, 3])

(a+tf.random.normal([3])).shape

TensorShape([4, 32, 32, 3])

b=tf.broadcast_to(tf.random.normal([4, 1,   1, 1]), [4, 32, 32, 3])

b.shape      #TensorShape([4, 32, 32, 3])

l  若无法复制成相同维度大小,则无法进行广播运算。

(a+tf.random.normal([1, 4, 1, 1])).shape   #第二维度因为已经给出4,而目标数据的第二个维度为32

InvalidArgumentError: Incompatible   shapes: [4, 32, 32, 3] Vvs. [1, 4, 1, 1]

 

 

本实验利用网上已有的北京房价数据集预测了北京的房价,实现了TensorFlow的线性回归应用。

更多的技术内容,请访问腾科公司网站 www.togogo.net