1.将数据集打散并依旧保留对应标签:
idx = tf.range(10) idx = tf.random.shuffle(idx) a = tf.gather(a, axis= , idx) b = tf.gather(b, axis= , idx)
2.通过转置来改变tensor的content:
a = tf.random.normal([4, 28, 28, 3]) # [b, w, h, c] # 我们需要[b, h, w, c] a = tf.transpose(a, [0, 2, 1, 3])
3.增加,合并,减少维度:
a = tf.random.normal([4, 28, 28, 3]) b = tf.random.normal([4, 28, 28, 3]) # 增加一个维度 a = tf.expand_dims(a, axis=0) # axis正负皆可只要放对位置就行 b = tf.expand_dims(b, axis=0) # 然后我们可以通过concat合并 c = tf.concat([a, b] , axis=0) # c.shape=[2, 4, 28, 28, 3] # 减少维度(只能压缩为1的维度) a = tf.random.normal([1, 28, 28, 1]) a = tf.squeeze(a) # a.shape = [28, 28] a = tf.squeeze(a, axis=0) # a.shape = [28, 28, 1] # 同样axis也可以为负 a = tf.squeeze(a, axis=-4) # a.shape = [28, 28, 1]
4. tensor的广播机制
不同维度的数据不能相加,因此经常需要扩展维度,如expand_dims方法+tile方法可以实现,但我又不想改变原本的内存占用,让程序运行起来很卡,此时broadcasting应运而生。
举个例子:
首先broadcasting遵循大维度小维度概念,从左到右维度重要性逐渐变低,比如说[4, 32, 8]
4和32对应8来说就是高维度
举个例子:当我的数据的每个维度对应的特征为:[classes, students, scores],[4, 32, 8]意为4个班级,每个班级32个人,每人有八门课的成绩,当我需要为每个人加上5分我该怎么做呢?
[4, 32, 8] + [5.0],注意这里的[5.0]是data不是shape,shape是[1],随着tensorflow的广播机制,tf可以自动将这个[5.0]的data的shape自动扩展成[4, 32, 8]的形式进行相加。
我们来看看代码段:
a = tf.ones([2, 2, 2]) b = tf.ones([2, 2, 2]) a = tf.expand_dims(a, axis=0)# 顺便实现一下expand方法 b = tf.expand_dims(b, axis=0) c = tf.concat([a, b], axis=0) d = c + [5.0] print(d)
总体而言broadcasting是一种内存优化机制,和numpy库的广播机制比较相似。
但他也有限制,只有在维度为1或者没有维度时才能广播(记得右对齐)。
比如说:[1, 3] +[4.0, 3.0]这个是不行的,因为[4.0, 3.0]的shape是[2]就算扩展了也是[1, 2],维度不同的数据不能相加,就像维度不同的矩阵不能相加一个道理啦。
5.介绍一下expand_dims和tile方法如何进行维度扩展
前面介绍了broadcasting,但它有限制这里介绍一种更具通用性的方法。当我们想将维度成整数倍扩展时,就要使用tile方法了。
代码展示如下:
# 将a的维度扩展的和b一样 a = tf.random.normal([3, 2]) b = tf.random.normal([3, 6, 4]) a = tf.expand_dims(a, axis=0) a = tf.tile(a, [3, 2, 2]) # 这里的[3, 2, 2]里边的元素是对应维度扩展的倍数,type不能是float,只能是int32,int64 print(a.shape)
6.一些易忘运算
除法:整除:/ ;余除:%
矩阵相乘:@,matmul(a@b or tf.matmul(a, b))
可以一次性算多个的如[3, 2, 4](3个2*4的矩阵)@[3, 4, 5](3个4@5的矩阵) = [3, 2,5]
某一维度操作:reduce_mean/max/min/sum
自然对数:tf.math.log(这是以e为底的),当我们要实现以10为底2的对数怎么办?
tf.math.log(2.)/tf.math.log(10.) = log(10,2)
7.张量的合并与分割
tf.concat我前面已经用了,大致的感觉也非常直观,就像是把两张纸拼起来,但是注意这个操作是不会增加维度的。
具体用法:
tf.concat([a, b] ,axis=)
当你想要增加维度这里就会用到stack方法
tf.stack([a, b], axis=)
接下来我们对两者进行一个对比:
a = tf.random.normal([3, 2, 2]) b = tf.random.normal([3, 2, 2]) c = tf.concat([a, b], axis=0) d = tf.stack([a, b], axis=0) # 任意维度都可以加,但是一般加大维度都是加在第一个
结果:
tips:对于concat来说相加维度可以不等但是其余维度都得相等,对于stack来说每个维度都得相等
合并讲完了讲一下切割操作:
# 首先明确一下unstack是删除维度 # 假设c的shape是[2, 4, 32, 8] a, b = tf.unstack(c, axis=0) # 相当于是把[2, 4, 32, 8]变成了两个[4, 32, 8] # 当对半开以后维度是1删了也就删了,但维度不是1删完以后会是什么结果呢? res = tf.unstack(c, axis=3) # 这里的res返回的是一个list,等于说res = [[2, 4, 32], [2, 4, 32], [2, 4, 32],...]总共八个元素,需要某一个元素只需要res[i]即可
unstack感觉不是很灵活额,这里就有个更好使的——tf.split
这里直接上例子:
# 对半分
a = tf.random.normal([4, 32, 8])
b = tf.split(a, axis=2, num_or_size_splits=2)
for i in range(len(b)):
print(b[i].shape)
# 任意分
a = tf.random.normal([4, 32, 8])
b = tf.split(a, axis=2, num_or_size_splits=[2, 2, 4])
for i in range(len(b)):
print(b[i].shape)
8.数据统计
8.1范数
a = tf.ones([2, 2]) b = tf.norm(a, ord=,axis=) # ord指定几范数,axis指定维度
8.2最大值最小值索引检索
a = tf.random.truncated_normal([4, 10], stddev=1, seed=1) print(a) a_max = tf.argmax(a, axis=0) # 列方向上的最大值对于的索引 a_min = tf.argmin(a, axis=1) # 行方向上的最小值对于的索引 print(a_max) print(a_min)
结果:
8.3 tf.equal
a = tf.constant([1, 2, 3, 4]) b = tf.range(4) res = tf.equal(a, b) print(res) print(tf.reduce_sum(tf.cast(res, dtype=tf.int32))) # 这个方法可以用来算精确度
结果:
预测准确率的实例:
总体来说用到四个接口argmax, cast, equal, reduce_sum
logits = tf.random.truncated_normal([2, 4], stddev=1, seed=1)
y = [1, 0]
pred = tf.cast(tf.argmax(logits, axis=1), dtype=tf.int32)
correct = tf.equal(pred, y)
res = tf.reduce_sum(tf.cast(correct, dtype=tf.int32))
print(f'accuracy:{res/2*100}%')
结果:
8.4 tf.unique
a = tf.constant([3, 2, 2, 1]) b = tf.unique(a) print(b)
结果:返回一个去掉重复值以后的tensor, 完了再给出一个索引
小tips:这里可以用tf.gather把tf.uniqued的操作还原回去
tf.gather(b[0], b[1])
9. 张量排序
9.1 tf.sort/argsort
代码示例:
a = tf.random.shuffle(tf.constant(range(5))) print(a) print(tf.sort(a)) # 默认从小到大,如需从大到小排序:, direction='DESCENDING' print(tf.argsort(a)) print(tf.gather(tf.sort(a), tf.argsort(a))
结果:
9.2 tf.math.top_k
当你需要选取一个tensor中的某几个最大或最小值,我可以通过此api快速获得
a = tf.random.truncated_normal([4, 4], stddev=0.1, seed=1) print(a) res = tf.math.top_k(a, 2) # 默认以最后一个维度为准 print(res.indices) # 相当于argsort print(res.values) # 相当于sort
结果:



