TensorFlow入门:合并分割,数据统计,填充复制,张量限幅,网格

合并和分割

a = tf.ones([4,35,8])
b = tf.ones([2,35,8])  # 拼接,axis=0,就是针对第一个元素

c=tf.concat([a,b],axis=0)  # 需要两个维度相同
TensorShape([6, 35, 8])

a = tf.ones([4,32,8]);b=tf.ones([4,3,8])
tf.concat([a,b],axis=1).shape
TensorShape([4, 35, 8])

print(a.shape,b.shape)
tf.concat([a,b],axis=-1).shape   # 合并不会增加一个新的维度
(4, 32, 8) (4, 32, 8)
TensorShape([4, 32, 16])

tf.stack([a,b],axis=0).shape  # stack可以增加一个新的维度
TensorShape([2, 4, 32, 8])

tf.stack([a,b],axis=3).shape   # 可以指定前后,需要拼接的两个维度相同
TensorShape([4, 32, 8, 2])


print(a.shape,b.shape)
c = tf.stack([a,b])
print(c.shape)
aa,bb = tf.unstack(c,axis=0)     # 拆分
aa.shape,bb.shape
(4, 32, 8) (4, 32, 8)
(2, 4, 32, 8)
(TensorShape([4, 32, 8]), TensorShape([4, 32, 8]))

res = tf.unstack(c,axis=3)      # 拆分为8个
res[0].shape,res[1].shape,len(res)
(TensorShape([2, 4, 32]), TensorShape([2, 4, 32])),8


# 分组,灵活性更强
res = tf.split(c,axis=3,num_or_size_splits=2)  
len(res)   # 2

res[0].shape
TensorShape([2, 4, 32, 4])

res = tf.split(c,axis=3,num_or_size_splits=[2,2,4])
for each in res:
    print(each.shape))

(2, 4, 32, 2)
(2, 4, 32, 2)
(2, 4, 32, 4)

数据统计


# 向量的范数
a=tf.ones([2,2])
tf.norm(a)       # 二阶范数,tf.sqrt(tf.reduce_sum(tf.square(a))) 全元素平和开跟
<tf.Tensor: shape=(), dtype=float32, numpy=2.0>

tf.norm(a,ord=2,axis=1)   # 指定维度求范数
<tf.Tensor: shape=(2,), dtype=float32, numpy=array([1.4142135, 1.4142135], dtype=float32)>

tf.norm(a,ord=1)        # 一阶求和
<tf.Tensor: shape=(), dtype=float32, numpy=4.0>

a = tf.random.normal([4,10])  # 最大最小值,均值
tf.reduce_min(a),tf.reduce_max(a),tf.reduce_mean(a)  # 都有 axis 这个属性,前面的reduce 就是提示会降维
(<tf.Tensor: shape=(), dtype=float32, numpy=-1.8088812>,
 <tf.Tensor: shape=(), dtype=float32, numpy=2.0708714>,
 <tf.Tensor: shape=(), dtype=float32, numpy=0.061080307>)


# 默认axis=0,针对 0 维,10组 
 tf.argmax(a).shape,tf.argmax(a)   
 (TensorShape([10]),
 <tf.Tensor: shape=(10,), dtype=int64, numpy=array([2, 2, 2, 3, 0, 2, 2, 1, 3, 3])>)


# 比较操作
a = tf.constant([1,2,3,2,5])
b = tf.range(5)
tf.equal(a,b)
<tf.Tensor: shape=(5,), dtype=bool, numpy=array([False, False, False, False, False])>

res = tf.equal(a,b)    # bool转类型,然后求和
tf.reduce_sum(tf.cast(res,dtype = tf.int32))
<tf.Tensor: shape=(), dtype=int32, numpy=0>

# 唯一值
a = tf.constant([4,2,2,1,4])
tf.unique(a)
Unique(y=<tf.Tensor: shape=(3,), dtype=int32, numpy=array([4, 2, 1], dtype=int32)>, idx=<tf.Tensor: shape=(5,), dtype=int32, numpy=array([0, 1, 1, 2, 0], dtype=int32)>)   

b =tf.unique(a)
b.idx,b.index,b.y   
(<tf.Tensor: shape=(5,), dtype=int32, numpy=array([0, 1, 1, 2, 0], dtype=int32)>,
 <function Unique.index(value, start=0, stop=9223372036854775807, /)>,
 <tf.Tensor: shape=(3,), dtype=int32, numpy=array([4, 2, 1], dtype=int32)>)

tf.gather(b.y,b.idx)              # 复原
<tf.Tensor: shape=(5,), dtype=int32, numpy=array([4, 2, 2, 1, 4], dtype=int32)>


prob = tf.constant([[0.1,0.2,0.7],[0.2,0.7,0.1]])  # 表示可能性
target = tf.constant([2,0])          # 实际值
k_b = tf.math.top_k(prob,3).indices     # 前三个
k_b
<tf.Tensor: shape=(2, 3), dtype=int32, numpy=
array([[2, 1, 0],
       [1, 0, 2]], dtype=int32)>

def accuracy(output, target, topk=(1,)):    
    # 一个用来测精度的函数,指定考虑前几个概率
    # output [b,N], target[b]
    maxk = max(topk)
    batch_size = target.shape[0]

    pred = tf.math.top_k(output, maxk).indices        # 选择排列前面几个的索引(类别)
    pred = tf.transpose(pred, perm=[1, 0])             # 转置,然后广播。。
    target_ = tf.broadcast_to(target, pred.shape)
    # [10, b]
    correct = tf.equal(pred, target_)
    # print(correct)

    res = []
    for k in topk:    # 比较前几行,转换为0,1 在计算个正确率 
        correct_k = tf.cast(tf.reshape(correct[:k], [-1]),  dtype=tf.float32)
        correct_k = tf.reduce_sum(correct_k)
        acc = float(correct_k* (100.0 / batch_size) )
        res.append(acc)

    return res

output = tf.random.normal([10, 6])    # 10个样本,6类
output = tf.math.softmax(output, axis=1)  # 让输出值总和为1
target = tf.random.uniform([10], maxval=6, dtype=tf.int32)  # 标签
print('prob:', output.numpy())
pred = tf.argmax(output, axis=1)
print('pred:', pred.numpy())
print('label:', target.numpy())
# 意思就是考虑前几个概率大的值,有一个对了就对了,当全考虑时,概率就是100了
acc = accuracy(output, target, topk=(1,2,3,4,5,6))  #
print('top-1-6 acc:', acc)

prob: [[0.08726542 0.02225256 0.4912736  0.06410525 0.08286054 0.25224262]
 [0.13055882 0.07061573 0.26486665 0.20455424 0.20469896 0.1247056 ]
 [0.43044326 0.10636217 0.16449806 0.05707863 0.19358431 0.04803355]
 [0.16948995 0.01624216 0.5305888  0.0307715  0.06940161 0.18350598]
 [0.3525269  0.1322329  0.02679942 0.303122   0.1113945  0.07392432]
 [0.06559116 0.09399377 0.26416907 0.16099243 0.1656936  0.24955998]
 [0.25813058 0.07047742 0.20491946 0.06957188 0.27260825 0.12429236]
 [0.28551948 0.16485259 0.10330899 0.09955222 0.30379328 0.0429734 ]
 [0.08291844 0.11529168 0.35974807 0.14822288 0.14078341 0.15303555]
 [0.11123328 0.15178108 0.2656589  0.15466414 0.12525429 0.19140829]]
pred: [2 2 0 2 0 2 4 4 2 2]        
label: [4 5 3 0 5 3 1 0 5 2]
top-1-6 acc: [10.0, 30.0, 40.0, 60.0, 100.0, 100.0]

填充与复制

a  =tf.reshape(tf.range(9),[3,3])
a
<tf.Tensor: shape=(3, 3), dtype=int32, numpy=
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]], dtype=int32)>
       
# a 是二维的,axis=0就是行[1,0] 就是前面加一行,后面不加
# axis =  [0,0] 列的前后都不加
array([[0, 0, 0],
tf.pad(a,[[1,0],[0,0]])
<tf.Tensor: shape=(5, 3), dtype=int32, numpy=
array([[0, 0, 0],
       [0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]], dtype=int32)>
       
tf.pad(a,[[1,1],[1,1]])            # 懂了吗
<tf.Tensor: shape=(5, 5), dtype=int32, numpy=
array([[0, 0, 0, 0, 0],
       [0, 0, 1, 2, 0],
       [0, 3, 4, 5, 0],
       [0, 6, 7, 8, 0],
       [0, 0, 0, 0, 0]], dtype=int32)>

a = tf.random.normal([4,28,28,3])
b = tf.pad(a,[[0,0],[2,2],[2,2],[0,0]])     # 用于图片的填充,NLP中单词数量的padding
b.shape
TensorShape([4, 32, 32, 3])


tf.tile(a,[1,2])             # 第一个维度复制一次,第二个维度复制两次
<tf.Tensor: shape=(3, 6), dtype=int32, numpy=
array([[0, 1, 2, 0, 1, 2],
       [3, 4, 5, 3, 4, 5],
       [6, 7, 8, 6, 7, 8]], dtype=int32)>
       
tf.tile(a,[2,1])
<tf.Tensor: shape=(6, 3), dtype=int32, numpy=
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8],
       [0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]], dtype=int32)>
       
tf.tile(a,[2,2])
<tf.Tensor: shape=(6, 6), dtype=int32, numpy=
array([[0, 1, 2, 0, 1, 2],
       [3, 4, 5, 3, 4, 5],
       [6, 7, 8, 6, 7, 8],
       [0, 1, 2, 0, 1, 2],
       [3, 4, 5, 3, 4, 5],
       [6, 7, 8, 6, 7, 8]], dtype=int32)>

[50]



aa = tf.expand_dims(a,axis=0)       
aa
<tf.Tensor: shape=(1, 3, 3), dtype=int32, numpy=    # 扩维填充
array([[[0, 1, 2],
        [3, 4, 5],
        [6, 7, 8]]], dtype=int32)>
[51]



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

       [[0, 1, 2],
        [3, 4, 5],
        [6, 7, 8]]], dtype=int32)>
[52]



tf.broadcast_to(aa,[2,3,3])
<tf.Tensor: shape=(2, 3, 3), dtype=int32, numpy=     # 效果同上,但性能上面那个更好,不会占据内存
array([[[0, 1, 2],
        [3, 4, 5],
        [6, 7, 8]],

       [[0, 1, 2],
        [3, 4, 5],
        [6, 7, 8]]], dtype=int32)>                  # 但针对一些操作符 +- 之类的可以自动进行广播,还是很方便的

张量限幅

就是值的裁剪,relu函数就是这

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

tf.maximum(a,2)      # 就是限幅。。。。。。。多维也是一样,这个是逐元素操作
<tf.Tensor: shape=(10,), dtype=int32, numpy=array([2, 2, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int32)>

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

tf.clip_by_value(a,2,8)            # 两边一起
<tf.Tensor: shape=(10,), dtype=int32, numpy=array([2, 2, 2, 3, 4, 5, 6, 7, 8, 8], dtype=int32)>

tf.nn.relu(a) == tf.maximum(a,0)          
<tf.Tensor: shape=(10,), dtype=bool, numpy=
array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
        True])>

# 范数限幅
a = tf.random.normal([2,2],mean=10)
a
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[ 9.134853 ,  9.628895 ],
       [10.4377   , 10.5661335]], dtype=float32)>


tf.norm(a)
<tf.Tensor: shape=(), dtype=float32, numpy=19.918583>   # 当前范数


aa = tf.clip_by_norm(a,15)                    # 指定限幅后的范数
aa
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=    # 计算的过程就是除以原范数,在乘以指定的
array([[6.8791437, 7.2511897],                   # 作用就是保证向量的方向不变,改变膜的大小
       [7.8602734, 7.956992 ]], dtype=float32)>


tf.norm(aa)
<tf.Tensor: shape=(), dtype=float32, numpy=15.0>   

# 应对梯度下降中的梯度爆炸和梯度消失(下降步幅过大,过小)
grads,total_norm  = tf.clip_by_global_norm(grads,25)  # 对网络的整体参数进行等比例缩放(保证所有向量方向不改变)
# 返回缩放后的结果和缩放前向量的范数,参数25是缩放后整体的范数。
# 比如梯度(导数)几百,损失很多的nan,就需要加上这个来缩放梯度。

一些高级操作

a = tf.random.normal([3,3])
a
<tf.Tensor: shape=(3, 3), dtype=float32, numpy=
array([[-0.07731798, -0.78015125,  0.29295778],
       [-0.32711634,  0.5294314 , -0.44531348],
       [ 0.65166456, -0.9208928 ,  0.4694049 ]], dtype=float32)>

mask = a>0
mask
<tf.Tensor: shape=(3, 3), dtype=bool, numpy=
array([[False, False,  True],
       [False,  True, False],
       [ True, False,  True]])>

tf.boolean_mask(a,mask)
<tf.Tensor: shape=(4,), dtype=float32, numpy=array([0.29295778, 0.5294314 , 0.65166456, 0.4694049 ], dtype=float32)>


indices = tf.where(mask)            # 这个就是返回布尔数组中为True的位置,注意shape
indices
<tf.Tensor: shape=(4, 2), dtype=int64, numpy=
array([[0, 2],
       [1, 1],
       [2, 0],
       [2, 2]])>


tf.gather_nd(a,indices)                # 借助where得到的索引,使用这个就可以提取出True的元素
<tf.Tensor: shape=(4,), dtype=float32, numpy=array([0.29295778, 0.5294314 , 0.65166456, 0.4694049 ], dtype=float32)>


mask
<tf.Tensor: shape=(3, 3), dtype=bool, numpy=
array([[False, False,  True],
       [False,  True, False],
       [ True, False,  True]])>


A = tf.ones([3,3])
B = tf.zeros([3,3])
tf.where(mask,A,B)                 # 就相当于一个条件吧,Ture部分用A,False部分就用B 
<tf.Tensor: shape=(3, 3), dtype=float32, numpy=
array([[0., 0., 1.],
       [0., 1., 0.],
       [1., 0., 1.]], dtype=float32)>



indices = tf.constant([[4],[3],[1],[2]])
updates = tf.constant([9,10,11,12])
shape = tf.constant([8])    # 或者多维的
tf.scatter_nd(indices,updates,shape)     # 就是在形状为shape的地板上,根据indices更新数据,其余用0填充
<tf.Tensor: shape=(8,), dtype=int32, numpy=array([ 0, 11, 12, 10,  9,  0,  0,  0], dtype=int32)>\



# 网格

 y = tf.linspace(-2,2,5)
 x = tf.linspace(-2,2,5)
 points_x,points_y = tf.meshgrid(x,y)
 points_x.shape
TensorShape([5, 5])
                 
(<tf.Tensor: shape=(5, 5), dtype=float64, numpy=     # x,y 组合成所有点的坐标
 array([[-2., -1.,  0.,  1.,  2.],
        [-2., -1.,  0.,  1.,  2.],
        [-2., -1.,  0.,  1.,  2.],
        [-2., -1.,  0.,  1.,  2.],
        [-2., -1.,  0.,  1.,  2.]])>,
 <tf.Tensor: shape=(5, 5), dtype=float64, numpy=
 array([[-2., -2., -2., -2., -2.],
        [-1., -1., -1., -1., -1.],
        [ 0.,  0.,  0.,  0.,  0.],
        [ 1.,  1.,  1.,  1.,  1.],
        [ 2.,  2.,  2.,  2.,  2.]])>)


points = tf.stack([points_x,points_y],axis=2)     # 要得到坐标,堆叠一下组合
points
<tf.Tensor: shape=(5, 5, 2), dtype=float64, numpy=
array([[[-2., -2.],
        [-1., -2.],
        [ 0., -2.],
        [ 1., -2.],
        [ 2., -2.]],

       [[-2., -1.],
        [-1., -1.],
        [ 0., -1.],
        [ 1., -1.],
        [ 2., -1.]],  。。。。
        
# 用途就是绘图吧,,,等高线之类的
import tensorflow as tf

import matplotlib.pyplot as plt

# z = sin(x) + sin(y)
def func(x):
    z = tf.math.sin(x[...,0]) + tf.math.sin(x[...,1])
    return z

x = tf.linspace(0., 2*3.14, 500)
y = tf.linspace(0., 2*3.14, 500)
# [50, 50]
point_x, point_y = tf.meshgrid(x, y)
# [50, 50, 2]
points = tf.stack([point_x, point_y], axis=2)
# points = tf.reshape(points, [-1, 2])
print('points:', points.shape)
z = func(points)
print('z:', z.shape)

plt.figure('plot 2d func value')
plt.imshow(z, origin='lower', interpolation='none')   # 不知道叫啥
plt.colorbar()

plt.figure('plot 2d func contour')
plt.contour(point_x, point_y, z)    # 等高线
plt.colorbar()
plt.show()

总结

函数 用法 备注
tf.concat(a,b,axis) 拼接(不会增加新的维度) (4,35,8),(2,35,8)-axis=0-> (6,35,8)
tf.stack([a,b],axis) 堆叠(可以前后增加新的维度axis=0/-1) (4,35,8),(4,35,8)-axis=0-> (2,8,35,8)
tf.unstack(c,axis) 拆分为多个 (2, 4, 32, 8) -axis=3-> 8个(2,4,32)
tf.split(c,axis=3,num_or_size_splits=[2,2,4]) 分组灵活性更强
tf.norm(a,ord,axis) 范数
tf.reduce_min\max\mean(a, axis) 最大最小值,均值
tf.argmax\argmin(a,axis) } 最值的索引
tf.equal(a,b) 比较,返回布尔值 tf.reduce_sum(tf.cast(res,dtype = tf.int32))转换为整形在求和
b = tf.unique(a) 唯一值 b.idx, b.index, b.y,tf.agther(b,y, b.idx) 复原
tf.math.top_k(p,3) 考虑前3个值 .indices 得到索引
tf.pad(a,[[0,0],[2,2],[2,2],[0,0]]) 在维度前后添加值为0的行/列 [4,28,28,3]-》[4, 32, 32, 3]
tf.tile(a,[1,2]) 第一个维度不变,第二个维度复制堆叠
tf.expand_dims(a,axis=0) 扩维 (3,3) -> (1,3,3),在进行title([2,1,1])就是广播了
tf.maximum(a,2)\minimum(a,8)clip_by_value(a,2,8) 下限幅,上限幅,双边
tf.clip_by_norm(a,15) 范数限幅,限幅后范数为15 保证向量方向不变
grads,total_norm = tf.clip_by_global_norm(grads,25) 整体参数限幅 应对梯度消失爆炸
tf.boolean_mask(a,mask) 返回mask为真对应a 的值
indices = tf.where(mask) 返回bool数组中为真的位置 tf.gather_nd(a,indices)作用同上
tf.scatter_nd(indices,updates,shape) 在形状为shape的地板上,根据indices更新数据,其余用0填充
x,y = tf.meshgrid(x,y) 网格 points = tf.stack([points_x,points_y],axis=2)得到坐标

你可能感兴趣的:(深度学习,python,深度学习,tensorflow)