Tensorflow2.0学习笔记

一、Tensor(张量)

1. 创建一个Tensor

import numpy as np
import tensorflow as tf
from tensorflow.keras import layers
#先从1+1=2开始
tf.constant(1)						#创建一个整数型数据
tf.constant(1.)						#创建一个浮点型数据1.0
tf.constant(1.,dtype=tf.double)	#创建一个双精度浮点型数据1.0
tf.constant(Ture)					#创建一个bool型数据Ture
tf.constant('hello')				#创建一个string型数据'hello'

print(tf.constant(1.) + tf.constant(1.))
'''
tf.Tensor(2.0, shape=(), dtype=float32)
'''
#两种创立方法:从numpy转换得到 & 从自己创建的list直接得到

#从numpy转换得到
def ctt(numpy):		#先创建一个直接转换的函数
	  numpy = tf.convert_to_tensor(numpy, dtype=tf.float32)
	  return  numpy
	  
N = ctt(np.ones([2, 3]))
print(N)
'''
tf.Tensor(
[[1. 1. 1.]
 [1. 1. 1.]], shape=(2, 3), dtype=float32)
 '''

#从list得到
M = ctt([[1, 2], [3, 4], [5, 6]])
print(M)
'''
tf.Tensor(
[[1. 2.]
 [3. 4.]
 [5. 6.]], shape=(3, 2), dtype=float32)
 '''
 
#tf.constant()和tf.convert_to_tensor()功能高度重合
print(tf.constant([[2., 2], [3, 3.]]))
'''
tf.Tensor(
[[2. 2.]
 [3. 3.]], shape=(2, 2), dtype=float32)
'''

#3维
L = ctt(np.array([[[1.0, 2.0], [3.0, 4.0],[5.0, 6.0], [7.0, 8.0]],[[1.0, 2.0], [3.0, 4.0],[5.0, 6.0], [7.0, 8.0]]], dtype=np.float32))
'''
tf.Tensor(
[[[1. 2.]
  [3. 4.]
  [5. 6.]
  [7. 8.]]

 [[1. 2.]
  [3. 4.]
  [5. 6.]
  [7. 8.]]], shape=(2, 4, 2), dtype=float32)
  '''
#创建为某个初始化数值
#装满'0'的标量,0维
init0 = tf.zeros([])	#'[]'中是shape,无形便是标量
print(init0)
'''
tf.Tensor(0.0, shape=(), dtype=float32)
'''

#装满'0'的3维Tensor
print(tf.zeros([2, 3, 4]))
'''
tf.Tensor(
[[[0. 0. 0. 0.]
  [0. 0. 0. 0.]
  [0. 0. 0. 0.]]

 [[0. 0. 0. 0.]
  [0. 0. 0. 0.]
  [0. 0. 0. 0.]]], shape=(2, 3, 4), dtype=float32)
'''
#模仿a的形状,装满'0'
print(tf.zeros_like(a))			
print(tf.zeros(tf.shape(a)))

'''
同理,还有:
	tf.ones()
	tf.ones_like()
'''	

#若想用其他数字装满,有:
A1 = tf.fill([3, 5], 3.14)
print(A1)
'''
tf.Tensor(
[[3.14 3.14 3.14 3.14 3.14]
 [3.14 3.14 3.14 3.14 3.14]
 [3.14 3.14 3.14 3.14 3.14]], shape=(3, 5), dtype=float32)
'''

#满足正态分布的随机数
print(tf.random.normal([2, 3], mean = 0, stddev = 1))	#mean:均值	stddev:方差
'''
tf.Tensor(
[[ 1.0786376  -0.618458    0.9053903 ]
 [ 0.09392761  0.8505055  -1.2988913 ]], shape=(2, 3), dtype=float32)
'''
print(tf.random.truncated_normal([3, 4], mean= 0, stddev= 1))	#有截断的正态分布

#均匀分布的随机数
print(tf.random.uniform([2, 3], minval= 0, maxval= 1))	#minval:最小值, maxval:最大值

2. 查看/改变Tensor属性的一些常用方法

with tf.device("cpu"):
	a = tf.constant(1)	#创建Tensor:a在cpu上,同理也可创建在gpu上。

a.device()				#查看Tensor:a的位置(在CPU还是在GPU上)。
aa = a.gpu()			#改变位置

a.shape					#查看a的形状

a.ndim					#查看a的维度
tf.rank(a)				#查看a的维度

tf.is_tensor(a)			#查看a是否为Tensor
isinstance(a,tf.tensor)	#查看a是否为Tensor

a.numpy() 				#将Tensor转换为numpy
tf.convert_to_tensor(a, dtype=tf.float32)		#将a转换为Tensor,顺便改变其数据类型为float32。

a.dtype == tf.float32	#查看a是否为float32的数据类型
'''
	同理,	
	tf.int8:8位整数。
	tf.int16:16位整数。
    tf.int32:32位整数。
    tf.int64:64位整数。
    tf.uint8:8位无符号整数。
    tf.uint16:16位无符号整数。
    tf.float16:16位浮点数。
    tf.float32:32位浮点数。
    tf.float64:64位浮点数。
    tf.double:等同于tf.float64。

    tf.string:字符串。
    tf.bool:布尔型。

    tf.complex64:64位复数。
    tf.complex128:128位复数。
'''
tf.cast(a, dtype = tf.double)	#转换a的数据类型为float64。

3. 不同维度的Tensor的应用场景

#标量,0维
#loss
out = tf.random.uniform([4, 10])	#随机生成一个shape为4*10的输出
y = tf.range(4)						#生成一个标签[1, 2, 3, 4]
y = tf.one_hot(y, depth= 10)		#把标签one-hot编码
loss = tf.keras.losses.mse(y, out)	#求MSE
loss = tf.reduce_mean(loss)			#loss值为MSE平均值,为标量
print(loss)
'''
tf.Tensor(0.3793819, shape=(), dtype=float32)
'''
#1维-矢量 & 2维-矩阵
net = layers.Dense(5)				#创建Dense层,Wx+b,输出节点:3
net.build((2, 4))					#创建Tensor:W、b,输入节点:4
print(net.kernel)					
print(net.bias)
'''

<tf.Variable 'kernel:0' shape=(4, 5) dtype=float32, numpy=
array([[ 0.5922109 , -0.65275455, -0.192119  , -0.22331375,  0.6428822 ],
       [ 0.21424997, -0.78871226, -0.6134677 ,  0.44830847,  0.37566483],
       [-0.36308923,  0.03228235,  0.6797118 ,  0.30566156,  0.21143973],
       [ 0.41775525, -0.6908766 ,  0.01077586, -0.20037097,  0.47520888]],
      dtype=float32)>
<tf.Variable 'bias:0' shape=(5,) dtype=float32, numpy=array([0., 0., 0., 0., 0.], dtype=float32)>
'''
#3维-张量(矩阵组) & 4维-张量(将矩阵组整体看作单位 所组成的向量)
x = tf.random.normal([4, 32, 32, 3])  	# 创建 4张 32*32 的RGB彩色图片作为输入
layer = layers.Conv2D(16, kernel_size=3)  	# 创建卷积神经网络
out = layer(x)  							# 前向计算
print(f'{out.shape}')  						# 输出的shape
print(f'{layer.kernel.shape}')  			# 输出卷积kernel的张量的shape

4. Tensor的索引和切片

4.1 python基本索引方式

#基本索引方式,不行。
a = tf.random.uniform([2,3,4,5])
print(a)
print(a[1])
print(a[1][1])
print(a[1][1][3])
print(a[1][1][3][4])
'''
#print(a)
tf.Tensor(
[[[[0.33411717 0.48148096 0.18575907 0.8725376  0.6655083 ]
   [0.5498291  0.03482103 0.8002987  0.23369777 0.28715873]
   [0.7299801  0.20487225 0.74910486 0.4360664  0.25036836]
   [0.76276076 0.3112259  0.87780917 0.79756415 0.47144926]]

  [[0.08586323 0.92330277 0.57816803 0.5471033  0.56659937]
   [0.56350887 0.08270538 0.90593386 0.503567   0.19969416]
   [0.42795157 0.3153913  0.5015607  0.85127234 0.824203  ]
   [0.18673933 0.7427051  0.11000514 0.6364267  0.23299205]]

  [[0.5058254  0.664479   0.78087616 0.67435    0.7023891 ]
   [0.22264528 0.18501568 0.3295257  0.53643596 0.91570365]
   [0.96100354 0.69153655 0.6295806  0.45655918 0.61393666]
   [0.36681604 0.9363128  0.04159665 0.33299363 0.8064569 ]]]


 [[[0.93899155 0.28074706 0.79151    0.7216141  0.5585122 ]
   [0.72571266 0.63688374 0.44369864 0.5431807  0.69609547]
   [0.86437416 0.5949708  0.20264268 0.5606166  0.7415873 ]
   [0.7937398  0.251693   0.23689067 0.3416158  0.5187868 ]]

  [[0.5987221  0.86099446 0.2801261  0.910594   0.19355798]
   [0.42006958 0.28922737 0.40342855 0.13486373 0.12143862]
   [0.57317936 0.52111506 0.6679357  0.97017336 0.9257324 ]
   [0.01621377 0.42351937 0.42798698 0.43628013 0.11316431]]

  [[0.16628492 0.7290634  0.15835512 0.166273   0.38106108]
   [0.9063903  0.4463179  0.8166605  0.03125465 0.7766534 ]
   [0.69168127 0.4213302  0.25161684 0.11975718 0.47528207]
   [0.4653175  0.18763065 0.30306637 0.6164857  0.04418361]]]], shape=(2, 3, 4, 5), dtype=float32)

#print(a[1])
tf.Tensor(
[[[0.93899155 0.28074706 0.79151    0.7216141  0.5585122 ]
  [0.72571266 0.63688374 0.44369864 0.5431807  0.69609547]
  [0.86437416 0.5949708  0.20264268 0.5606166  0.7415873 ]
  [0.7937398  0.251693   0.23689067 0.3416158  0.5187868 ]]

 [[0.5987221  0.86099446 0.2801261  0.910594   0.19355798]
  [0.42006958 0.28922737 0.40342855 0.13486373 0.12143862]
  [0.57317936 0.52111506 0.6679357  0.97017336 0.9257324 ]
  [0.01621377 0.42351937 0.42798698 0.43628013 0.11316431]]

 [[0.16628492 0.7290634  0.15835512 0.166273   0.38106108]
  [0.9063903  0.4463179  0.8166605  0.03125465 0.7766534 ]
  [0.69168127 0.4213302  0.25161684 0.11975718 0.47528207]
  [0.4653175  0.18763065 0.30306637 0.6164857  0.04418361]]], shape=(3, 4, 5), dtype=float32)

#print(a[1][1])
tf.Tensor(
[[0.5987221  0.86099446 0.2801261  0.910594   0.19355798]
 [0.42006958 0.28922737 0.40342855 0.13486373 0.12143862]
 [0.57317936 0.52111506 0.6679357  0.97017336 0.9257324 ]
 [0.01621377 0.42351937 0.42798698 0.43628013 0.11316431]], shape=(4, 5), dtype=float32)

#print(a[1][1][3])
tf.Tensor([0.01621377 0.42351937 0.42798698 0.43628013 0.11316431], shape=(5,), dtype=float32)

#print(a[1][1][3][4])
tf.Tensor(0.113164306, shape=(), dtype=float32)

'''

4.2 numpy索引方式

#numpy索引,彳亍!
b = tf.random.uniform([2,2,2,3])
print(b)
print(b[1])
print(b[1,1])
print(b[1,1,1])
print(b[1,1,1,2])

'''
tf.Tensor(
[[[[0.9378555  0.31380856 0.5320953 ]
   [0.35451996 0.32003295 0.39626527]]

  [[0.5273626  0.79550326 0.6588979 ]
   [0.883386   0.840286   0.80191684]]]


 [[[0.69900167 0.2728572  0.32990396]
   [0.27973545 0.35294938 0.13254154]]

  [[0.14559793 0.6373651  0.7448201 ]
   [0.54996705 0.96327853 0.62275755]]]], shape=(2, 2, 2, 3), dtype=float32)
tf.Tensor(
[[[0.69900167 0.2728572  0.32990396]
  [0.27973545 0.35294938 0.13254154]]

 [[0.14559793 0.6373651  0.7448201 ]
  [0.54996705 0.96327853 0.62275755]]], shape=(2, 2, 3), dtype=float32)
tf.Tensor(
[[0.14559793 0.6373651  0.7448201 ]
 [0.54996705 0.96327853 0.62275755]], shape=(2, 3), dtype=float32)
tf.Tensor([0.54996705 0.96327853 0.62275755], shape=(3,), dtype=float32)
tf.Tensor(0.62275755, shape=(), dtype=float32)
'''


#切片,写作[start:end:step],step缺省时可以只写一个‘:’
c = tf.range(15)
print(c)
print(c[2:5])
print(c[7:-2])
print(c[-4:-1])
'''
tf.Tensor([ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14], shape=(15,), dtype=int32)
tf.Tensor([2 3 4], shape=(3,), dtype=int32)
tf.Tensor([ 7  8  9 10 11 12], shape=(6,), dtype=int32)
tf.Tensor([11 12 13], shape=(3,), dtype=int32)
'''

print(c[-1:])	#切片,取到了向量
print(c[-1])	#索引,取到了标量
'''
tf.Tensor([14], shape=(1,), dtype=int32)
tf.Tensor(14, shape=(), dtype=int32)
'''


#索引:10张256*256的RGB图片,抽出所有的R通道的部分。
d = tf.random.uniform([10,256,256,3])
print(d[1,:,:,:].shape)         #等同于d[1]
print(d[1].shape)

print(d[:,:,:,0].shape)			#抽出所有的R通道的部分
'''
(256, 256, 3)
(256, 256, 3)
(10, 256, 256)
'''

#索引:10张256*256的RGB图片,抽出隔行的128*128的部分。
print(d[:,::2,::2,:].shape)		#按第0、2、4、...、254抽取
print(d[:,1::2,1::2,:].shape)	#按第1、3、5、...、255抽取
'''
(10, 128, 128, 3)
'''

#逆序:‘::-1’
print(c[::-1])
print(c[::-2])
'''
tf.Tensor([14 13 12 11 10  9  8  7  6  5  4  3  2  1  0], shape=(15,), dtype=int32)
tf.Tensor([14 12 10  8  6  4  2  0], shape=(8,), dtype=int32)
'''

#优雅的‘...’
e = tf.random.uniform([4,10,256,256,3])
print(e[...,0].shape)
print(e[0,...].shape)
print(e[1,...,0].shape)
print(e[1,3,...,1].shape)
'''
(4, 10, 256, 256)
(10, 256, 256, 3)
(10, 256, 256)
(256, 256)
'''

4.3 Tensorflow2.0 索引相关的api

#tf自带api索引,yyds!
#tf.gather(),axis:选择你要的维度;indices:从你选的维度抽出数据并按抽出顺序重组,可以倒序&乱序抽出。
f = tf.random.uniform([3,4,5])
print(f)
print(tf.gather(f, axis= 0, indices= [0,2]))
print(tf.gather(f, axis= 1, indices= [1,2]))
print(tf.gather(f, axis= 1, indices= [2,1]))
print(tf.gather(f, axis= 2, indices= [0,2,4]))
'''
tf.Tensor(
[[[0.17248905 0.22548115 0.1765207  0.93963194 0.4110031 ]
  [0.1288836  0.28429163 0.4580847  0.4987197  0.5780771 ]
  [0.7727438  0.5727035  0.98040736 0.42306995 0.2378583 ]
  [0.06211662 0.5772431  0.36141145 0.4378724  0.8489783 ]]

 [[0.32726705 0.4734043  0.54520404 0.44889545 0.36731565]
  [0.18946385 0.8666637  0.42722368 0.9548973  0.3878224 ]
  [0.8239635  0.06546402 0.71385205 0.71219003 0.45652473]
  [0.8948405  0.18633568 0.80878735 0.2369951  0.97140825]]

 [[0.3266915  0.03859806 0.10190225 0.29231548 0.33704495]
  [0.6051146  0.39202964 0.46647668 0.2928431  0.0831188 ]
  [0.4917848  0.75489485 0.6524849  0.65319574 0.31405723]
  [0.01670587 0.32587624 0.95869493 0.8824016  0.32666552]]], shape=(3, 4, 5), dtype=float32)
tf.Tensor(
[[[0.17248905 0.22548115 0.1765207  0.93963194 0.4110031 ]
  [0.1288836  0.28429163 0.4580847  0.4987197  0.5780771 ]
  [0.7727438  0.5727035  0.98040736 0.42306995 0.2378583 ]
  [0.06211662 0.5772431  0.36141145 0.4378724  0.8489783 ]]

 [[0.3266915  0.03859806 0.10190225 0.29231548 0.33704495]
  [0.6051146  0.39202964 0.46647668 0.2928431  0.0831188 ]
  [0.4917848  0.75489485 0.6524849  0.65319574 0.31405723]
  [0.01670587 0.32587624 0.95869493 0.8824016  0.32666552]]], shape=(2, 4, 5), dtype=float32)
tf.Tensor(
[[[0.1288836  0.28429163 0.4580847  0.4987197  0.5780771 ]
  [0.7727438  0.5727035  0.98040736 0.42306995 0.2378583 ]]

 [[0.18946385 0.8666637  0.42722368 0.9548973  0.3878224 ]
  [0.8239635  0.06546402 0.71385205 0.71219003 0.45652473]]

 [[0.6051146  0.39202964 0.46647668 0.2928431  0.0831188 ]
  [0.4917848  0.75489485 0.6524849  0.65319574 0.31405723]]], shape=(3, 2, 5), dtype=float32)
tf.Tensor(
[[[0.7727438  0.5727035  0.98040736 0.42306995 0.2378583 ]
  [0.1288836  0.28429163 0.4580847  0.4987197  0.5780771 ]]

 [[0.8239635  0.06546402 0.71385205 0.71219003 0.45652473]
  [0.18946385 0.8666637  0.42722368 0.9548973  0.3878224 ]]

 [[0.4917848  0.75489485 0.6524849  0.65319574 0.31405723]
  [0.6051146  0.39202964 0.46647668 0.2928431  0.0831188 ]]], shape=(3, 2, 5), dtype=float32)
tf.Tensor(
[[[0.17248905 0.1765207  0.4110031 ]
  [0.1288836  0.4580847  0.5780771 ]
  [0.7727438  0.98040736 0.2378583 ]
  [0.06211662 0.36141145 0.8489783 ]]

 [[0.32726705 0.54520404 0.36731565]
  [0.18946385 0.42722368 0.3878224 ]
  [0.8239635  0.71385205 0.45652473]
  [0.8948405  0.80878735 0.97140825]]

 [[0.3266915  0.10190225 0.33704495]
  [0.6051146  0.46647668 0.0831188 ]
  [0.4917848  0.6524849  0.31405723]
  [0.01670587 0.95869493 0.32666552]]], shape=(3, 4, 3), dtype=float32)
'''

#tf.gather_nd(),指哪打哪,‘[]’就是indices
g = tf.random.uniform([3,4,5])
print(g)
print(tf.gather_nd(g, [[0,3],[1,2],[2,0]]))	#第0组矩阵的第3行 & 第1组矩阵的第2行 & 第2组矩阵的第0行 组成的矩阵
print(tf.gather_nd(g, [[1,0,3],[0,3,2]]))	#第1组矩阵的第1行第3列的元素 & 第0组矩阵的第3行第2列的元素 组成的矢量
print(tf.gather_nd(g, [1,0,3]))				#不带[]为标量
print(tf.gather_nd(g, [[1,0,3]]))			#带[]为只有一个元素的矢量
'''
tf.Tensor(
[[[0.82274675 0.07276464 0.77141094 0.39593875 0.15459394]
  [0.05569792 0.63008916 0.17403567 0.3682456  0.14402449]
  [0.83676624 0.20886362 0.5995362  0.45421994 0.32322752]
  [0.1855123  0.78585744 0.68906355 0.06304669 0.8689964 ]]

 [[0.81622815 0.49636865 0.94356    0.02599692 0.13918674]
  [0.36283875 0.4461999  0.77089465 0.71432984 0.5966377 ]
  [0.10112762 0.18861508 0.6630845  0.7640343  0.69013476]
  [0.28811002 0.38843358 0.8864492  0.08340657 0.28576016]]

 [[0.9439074  0.7547895  0.47352326 0.4601164  0.6389365 ]
  [0.10654974 0.2743503  0.25620425 0.24315488 0.8051033 ]
  [0.5166451  0.25959492 0.09007645 0.3423128  0.938866  ]
  [0.18806195 0.37779307 0.75381804 0.87400985 0.24452281]]], shape=(3, 4, 5), dtype=float32)

tf.Tensor(
[[0.1855123  0.78585744 0.68906355 0.06304669 0.8689964 ]
 [0.10112762 0.18861508 0.6630845  0.7640343  0.69013476]
 [0.9439074  0.7547895  0.47352326 0.4601164  0.6389365 ]], shape=(3, 5), dtype=float32)

tf.Tensor([0.02599692 0.68906355], shape=(2,), dtype=float32)

tf.Tensor(0.025996923, shape=(), dtype=float32)
tf.Tensor([0.02599692], shape=(1,), dtype=float32)

'''

#tf.boolean_mask(),遮盖用的一块布
#e在上面,是个5维Tensor
print(tf.boolean_mask(e, mask= [True,False,True,False]).shape)		#axis缺省,从最高维开始遮盖
print(tf.boolean_mask(e, mask= [True,True,False], axis= 4).shape)	#遮盖B通道
'''
(2, 10, 256, 256, 3)
(4, 10, 256, 256, 2)
'''

j = tf.random.uniform([2,3,4])
print(j)
print(tf.boolean_mask(j, mask= [[True,False,False],[False,True,False]]))
'''
tf.Tensor(
[[[0.34191966 0.9894607  0.08308613 0.2066344 ]
  [0.22433281 0.42450345 0.76914406 0.59016776]
  [0.347659   0.66620135 0.0662353  0.35876334]]

 [[0.99115384 0.48271286 0.41306317 0.3634535 ]
  [0.77332234 0.6244801  0.8165413  0.03342462]
  [0.34548688 0.8062229  0.60222936 0.5424137 ]]], shape=(2, 3, 4), dtype=float32)
tf.Tensor(
[[0.34191966 0.9894607  0.08308613 0.2066344 ]
 [0.77332234 0.6244801  0.8165413  0.03342462]], shape=(2, 4), dtype=float32)
'''

#索引最关键的是搞清楚shape和index的区别

5. Tensor的维度操作

5.1 Tensor的Reshape(重塑)

a = tf.random.uniform([10, 256, 256, 3])
print(a.shape)
print(tf.reshape(a, [10,65536,3]).shape)		#直接写出你想要的shape
print(tf.reshape(a, [10,256*256,3]).shape)		#让计算机帮你算shape
print(tf.reshape(a, [10,-1]).shape)				#用‘-1’省略你想让计算机帮你算的256*256*3
print(tf.reshape(a, [10,-1,3]).shape)			#同上,注意只能出现一个‘-1’
'''
(10, 256, 256, 3)
(10, 65536, 3)
(10, 65536, 3)
(10, 196608)
(10, 65536, 3)
'''

#重塑和恢复
b = tf.random.uniform([2,3,3])
print(b)
print(tf.reshape(tf.reshape(b, [2,3*3]), [2,3,3]))
'''
tf.Tensor(
[[[0.25005996 0.90980554 0.39438653]
  [0.88336563 0.17202067 0.3197198 ]
  [0.61590457 0.35265088 0.7114501 ]]

 [[0.25046253 0.8766279  0.85436213]
  [0.24808586 0.63137877 0.31554437]
  [0.13293493 0.9720093  0.5714165 ]]], shape=(2, 3, 3), dtype=float32)
tf.Tensor(
[[[0.25005996 0.90980554 0.39438653]
  [0.88336563 0.17202067 0.3197198 ]
  [0.61590457 0.35265088 0.7114501 ]]

 [[0.25046253 0.8766279  0.85436213]
  [0.24808586 0.63137877 0.31554437]
  [0.13293493 0.9720093  0.5714165 ]]], shape=(2, 3, 3), dtype=float32)
'''
#注意重塑后恢复可能导致的维度混淆,例如[b,h,w,c]的RGB图像组,经重塑,再经转置等操作后,若恢复原来的维度,可能变为[b,w,h,c],导致图像异常。

5.2 Tensor的Transpose(转置)

c = tf.random.uniform([4,18,24,3])
print(c.shape)
print(tf.transpose(c,perm = [0,2,1,3]).shape)	
'''
(4, 18, 24, 3)
(4, 24, 18, 3)
'''

5.3 Tensor维度的增加与减少

a. 增加维度:tf.expand_dims()

d = tf.random.uniform([128,196,3])
print(d.shape)
print(tf.expand_dims(d, axis= 0).shape)		#在前面增加一个维度
print(tf.expand_dims(d, axis= -4).shape)

print(tf.expand_dims(d, axis= 3).shape)		#在后面增加一个维度
print(tf.expand_dims(d, axis= -1).shape)

'''
(128, 196, 3)
(1, 128, 196, 3)
(1, 128, 196, 3)
(128, 196, 3, 1)
(128, 196, 3, 1)
'''

b. 减少维度:tf.squeeze()

print(tf.squeeze(tf.expand_dims(d, axis= -1), 3).shape)
'''
(128, 196, 3)
'''

注意:只能减少shape为1的维度

6. Tensor的Broadcasting操作

6.1 Broadcasting的概念

Q1. 啥是Broadcasting?

  • 是一种扩张维度的方式,但不在内存中进行数据的复制,操作时不额外占用内存空间。

Q2. 为啥Broadcasting?举个例子:

  • 5个车间,每个车间10个工人,每个工人工资默认5000元,各类补助500元,还有奖金津贴,工资分了3类,符合[5,10,3]的shape,现在国家有政策,工人们每人涨500元工资,不加补助奖金,这就相当于加一个偏移量[500 0 0],这个偏移量shape是[3],维度小,不能直接相加,若想把这个适用所有人,就要将这个shape扩展成为[5,10,3]。
  • 同样的例子,公司老板为追求利润,对车间工人实行绩效制度,前三名增加500元工资,后三名扣500元工资,则有了shape为[10,3]的表一张,若要全员适用,这个表要扩展成[5,10,3]。

Q3.Broadcasting的优点?

  1. 实用:能实现用低维度的内容和高维度的内容相加,可以减少大量重复工作,写起来也简洁,不用[5,10,3]+[5,10,3],[5,10,3]+[3]即可。

  2. 节约内存:tf.expand_dims()和tf.tile()也可以完成同样的操作,但是这样会占用大量内存,tf.tile()是实打实的在内存中复制,Broadcasting仅仅是个优化的手段,一样完成了以上工作的步骤,却没有在内存中复制,不占用内存。

Q4.能否进行Broadcasting?

  1. 首先,按最低维度对齐。
  2. 如果空缺处不存在维度,加一个维度,shape值为‘1’,然后把这个维度扩张成相同与高维度的。
  3. 如果存在维度,且在这个维度上shape为‘1’,然后把这个维度扩张成相同与高维度的。
  4. 其它情况不能Broadcasting。

Broadcasting的操作:

e1 = tf.random.uniform([5,10,3])
e2 = tf.ones([3])
e3 = tf.ones([10,3])
e4 = tf.ones([2])

print((e1 + e2).shape)
print((e1 + e3).shape)
#print((e1 + e4).shape)		#会报错
'''
(5, 10, 3)
(5, 10, 3)
'''

6.2 ‘‘tf.broadcast_to()’’ 和 ‘‘tf.tile()’’ 做比较

tf.broadcast_to(),扩张维度,但不复制数据,是一种数据优化的手段,不占用内存空间。
tf.tile()与tf.expand_dims()配合,既扩张维度,又复制数据,占用了较多内存空间。

f0 = tf.ones([3,4])
print(f0)
print(tf.broadcast_to(f0, [2,3,4]))	#tf.broadcast_to()操作

f1 = tf.expand_dims(f0, axis= 0)	#首先增加一个维度在axis 0
print(f1)
print(tf.tile(f1,[2,1,1]))			#复制最高维度
'''
tf.Tensor(
[[1. 1. 1. 1.]
 [1. 1. 1. 1.]
 [1. 1. 1. 1.]], shape=(3, 4), dtype=float32)
tf.Tensor(
[[[1. 1. 1. 1.]
  [1. 1. 1. 1.]
  [1. 1. 1. 1.]]

 [[1. 1. 1. 1.]
  [1. 1. 1. 1.]
  [1. 1. 1. 1.]]], shape=(2, 3, 4), dtype=float32)
tf.Tensor(
[[[1. 1. 1. 1.]
  [1. 1. 1. 1.]
  [1. 1. 1. 1.]]], shape=(1, 3, 4), dtype=float32)
tf.Tensor(
[[[1. 1. 1. 1.]
  [1. 1. 1. 1.]
  [1. 1. 1. 1.]]

 [[1. 1. 1. 1.]
  [1. 1. 1. 1.]
  [1. 1. 1. 1.]]], shape=(2, 3, 4), dtype=float32)
'''

7. Tensor前向传播

7.1 梯度下降

7.2 实战和所需函数

import tensorflow as tf
import numpy as np
from tensorflow import keras
from tensorflow.keras import datasets

(x , y), _ = datasets.mnist.load_data()

x = tf.convert_to_tensor(x, dtype= tf.float32) / 255.0  #优化数据[0-255]=>[0-1]
y = tf.convert_to_tensor(y, dtype= tf.int32)    #y,在计算前需要onehot编码

print(x.shape, y.shape, x.dtype, y.dtype)
print(tf.reduce_min(x),tf.reduce_max(x))
print(tf.reduce_min(y),tf.reduce_max(y))

train_db = tf.data.Dataset.from_tensor_slices((x , y)).batch(128)
train_iter = iter(train_db)
sample = next(train_iter)

print("batch:",sample[0].shape,sample[1].shape)

w1 = tf.Variable(tf.random.truncated_normal([784, 256], stddev= 0.1))    #为什么tf.Variable()?tf.GradientTape()默认跟踪一个Variable类型变量
b1 = tf.Variable(tf.zeros([256]))
w2 = tf.Variable(tf.random.truncated_normal([256, 128], stddev= 0.1))
b2 = tf.Variable(tf.zeros([128]))
w3 = tf.Variable(tf.random.truncated_normal([128, 10], stddev= 0.1))
b3 = tf.Variable(tf.zeros([10]))

lr = 1e-3   #学习率 = 0.001

for epoch in range(10):

    for step, (x, y) in enumerate(train_db):    #enumerate()返回值step,train_db每进行1个batch,step+1
        x = tf.reshape(x, [-1, 28*28])   #运算前数据预处理shape为[128,784]

        with tf.GradientTape() as tape:
            h1 = x@w1 + b1
            h1 = tf.nn.relu(h1) #tf.nn.relu()大于零不变,小于零为零,目的是做非线性转换
            h2 = h1@w2 + b2
            h2 = tf.nn.relu(h2)
            out = h2@w3 + b3

            #loss计算
            y_onehot = tf.one_hot(y, depth= 10)

            loss = tf.square(y_onehot - out)    #均方差mse计算
            loss = tf.reduce_mean(loss)

        grads = tape.gradient(loss, [w1, b1, w2, b2, w3, b3])

        #w1 = w1 - lr * grads[0]        #‘=’右面的Variable类型通过运算后赋值给左边变成了Tensor类型,会报错
        w1.assign_sub(lr * grads[0])    #为什么w1.assign_sub()?assign、assign_sub、assign_add作用是更新w1的值,可以继承数据类型为Variable
        #b1 = b1 - lr * grads[1]
        b1.assign_sub(lr * grads[1])
        #w2 = w2 - lr * grads[2]
        w2.assign_sub(lr * grads[2])
        #b2 = b2 - lr * grads[3]
        b2.assign_sub(lr * grads[3])
        #w3 = w3 - lr * grads[4]
        w3.assign_sub(lr * grads[4])
        #b3 = b3 - lr * grads[5]
        b3.assign_sub(lr * grads[5])

        if step % 100 == 0:
            print('epoch:', epoch,'step:', step,'loss:', float(loss))

tf.Variable():TensorFlow的可训练变量

#tf.Variable()作用:将值转化成为Variable类型
import tensorflow as tf
a = tf.zeros([2,3])
print(a)
a_Variable = tf.Variable(a)					#将张量封装为可训练变量
print(a_Variable)
print(isinstance(a, tf.Variable))
print(isinstance(a_Variable, tf.Variable))	#是否为Variable类型变量
print(a_Variable.trainable)					#是否为可训练变量
'''
tf.Tensor(
[[0. 0. 0.]
 [0. 0. 0.]], shape=(2, 3), dtype=float32)

<tf.Variable 'Variable:0' shape=(2, 3) dtype=float32, numpy=
array([[0., 0., 0.],
       [0., 0., 0.]], dtype=float32)>
False
True
True
'''

tf.GradientTape():TensorFlow自动求导机制,梯度带

#格式
with GradientTape() as tape:
函数表达式
grads = tape.gradient(函数,自变量)
#TensorFlow的自动求导机制
x=tf.Variable(5.)			#Variable类型
with tf.GradientTape() as tape:
    y = tf.square(x)		#y = x ^ 2 = 25
dy_dx = tape.gradient(y, x)	#dy_dx = 2 * x = 2 * 5 = 10

print(y)
print(dy_dx)
'''
tf.Tensor(25.0, shape=(), dtype=float32)
tf.Tensor(10.0, shape=(), dtype=float32)
'''

tf.nn.relu():大于零不变,小于零为零,目的是做非线性转换

a = tf.constant([[-2, -1, 0, 2, 3],[0, 4, -5, -9, 1]])
print(tf.nn.relu(a))

'''
[[0 0 0 2 3]
 [0 4 0 0 1]], shape=(2, 5), dtype=int32)
'''

x.one_hot:将变量onehot编码

x = [4, 6, 3, 2, 9]
print(x)
x_onehot = tf.one_hot(x, depth= 10)		#深度为10
print(x_onehot)
'''
[4, 6, 3, 2, 9]
tf.Tensor(
[[0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
 [0. 0. 0. 1. 0. 0. 0. 0. 0. 0.]
 [0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]], shape=(5, 10), dtype=float32)
'''

x.assign_sub():当Variable型变量做通常加减法时,得到的结果为Tensor型,若想保持其为Variable型,需要使用此函数,此函数作用为仅更新值的减法运算,不更新数据类型。

a1 = tf.Variable(5)
b1 = tf.constant(1)
b2 = tf.Variable(1)
print(a1 - b1)
print(a1 - b2)
print(a1.assign_sub(b1))	#a1 = a1 - b1
'''
tf.Tensor(4, shape=(), dtype=int32)
tf.Tensor(4, shape=(), dtype=int32)
<tf.Variable 'UnreadVariable' shape=() dtype=int32, numpy=4>
'''
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值