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的优点?
-
实用:能实现用低维度的内容和高维度的内容相加,可以减少大量重复工作,写起来也简洁,不用[5,10,3]+[5,10,3],[5,10,3]+[3]即可。
-
节约内存:tf.expand_dims()和tf.tile()也可以完成同样的操作,但是这样会占用大量内存,tf.tile()是实打实的在内存中复制,Broadcasting仅仅是个优化的手段,一样完成了以上工作的步骤,却没有在内存中复制,不占用内存。
Q4.能否进行Broadcasting?
- 首先,按最低维度对齐。
- 如果空缺处不存在维度,加一个维度,shape值为‘1’,然后把这个维度扩张成相同与高维度的。
- 如果存在维度,且在这个维度上shape为‘1’,然后把这个维度扩张成相同与高维度的。
- 其它情况不能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>
'''