4、张量的结构和操作
(1)张量的阶和数据类型
- 数组:numpy:ndarray类型,有0维,1维,2维等
- 矩阵:2维
- 张量:一个类型化(tensor类型)的N维数组
①基本数据类型
由三部分组成:名字(即op的类型,后面的0没有什么意义),张量的形状,类型
Tensor("Placeholder:0", shape=(2, 2), dtype=float32)
②张量的阶
③张量的类型,每个类型的精度是不一样的
④张量的属性
●graph 张量所属的默认图
●op 张量的操作名.
●name 张量的字符串描述
●shape 张量形状
1 import tensorflow as tf 2 import os 3 os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' #去掉警告,将警告级别提升 4 5 a = tf.constant([2,2]) #定义一个常量 6 b = tf.constant([4,4]) 7 sum1 = tf.add(a,b) #加法操作 8 9 #a,b,sum都是张量 10 print("a: \n",a) 11 print("_"*50) 12 print("b:\n ",b) 13 print("_"*50) 14 print("sum1\n: ",sum1) 15 print("_"*50) 16 print("a.graph:\n ",a.graph) 17 print("_"*50) 18 print("a.op: \n",a.op) 19 print("_"*50) 20 print("a.name: \n",a.name) 21 print("_"*50) 22 print("a.shape: \n",a.shape)
输出:
a:
Tensor("Const:0", shape=(2,), dtype=int32)
__________________________________________________
b:
Tensor("Const_1:0", shape=(2,), dtype=int32)
__________________________________________________
sum1
: Tensor("Add:0", shape=(2,), dtype=int32)
__________________________________________________
a.graph:
<tensorflow.python.framework.ops.Graph object at 0x0000021A13005F60>
__________________________________________________
a.op:
name: "Const"
op: "Const"
attr {
key: "dtype"
value {
type: DT_INT32
}
}
attr {
key: "value"
value {
tensor {
dtype: DT_INT32
tensor_shape {
dim {
size: 2
}
}
tensor_content: "\002\000\000\000\002\000\000\000"
}
}
}
__________________________________________________
a.name:
Const:0
__________________________________________________
a.shape:
(2,)
⑤形状 (在深度学习中,形状的改变是经常见到的)
-
TensorFlow打印出来的形状表示
0维:()
1维:(2)
2维:(2,3)
3维:(2,3,4),表示2张3维4列的表
-
张量的动态形状与静态形状
TensorFlow中, 张量具有静态形状和动态形状
(1)静态形状:创建一个张量,初始状态的形状
tf.Tensor.get_shape:获取静态形状
tf.Tensor.set_shape():更新Tensor对象的静态形状,通常用于在不能直接推断的情况下
#设置静态形状
1 plt = tf.placeholder(tf.float32,[None, 2]) #用[ ]不用()
2 print(plt) # Tensor("Placeholder:0", shape=(?, 2), dtype=float32)
3 plt.set_shape([3,2])
4 print(plt)
输出:
Tensor("Placeholder:0", shape=(?, 2), dtype=float32)
Tensor("Placeholder:0", shape=(3, 2), dtype=float32)
Φ 对于静态形状来说,一旦张量的形状固定了,那么便不能再次设置静态形状,如果想要需改形状,可以通过动态形状,重新生成一个新的张量。
再次设置形状
1 plt = tf.placeholder(tf.float32,[None, 2]) #用[ ]不用()
2 print(plt) # Tensor("Placeholder:0", shape=(?, 2), dtype=float32)
3 plt.set_shape([3,2])
4 print(plt)
5 plt.set_shape([6,2]) #静态形状不能再次修改
6 print(plt)
输出:
ValueError: Dimension 0 in both shapes must be equal, but are 3 and 6. Shapes are [3,2] and [6,2].
(2)动态形状:一种描述原始张量在执行过程中的一种形状(动态变化)
tf.reshape:创建一个具有不同动态形状的新张量(numpy中的reshape是将原来的数据进行直接修改)
注意:通过静态形状设置维[3,2]
通过reshape可以再次修改张量的形状,但是受限于张量中元素的个数,新的动态张量的元素必须和原张量的元素个数一致,这里首先使用静态形状方法改变形状,再使用动态形状改变
1 plt = tf.placeholder(tf之后.float32,[None, 2]) #用[ ]不用()
2 print(plt) # Tensor("Placeholder:0", shape=(?, 2), dtype=float32)
3 plt.set_shape([3,2])
4 print(plt)
5
6 # plt_reshpe = tf.reshape(plt,[3,4]) #形状固定了之后也只能在固定的元素中调整
7 # print(plt_reshpe)
8
9 plt_reshpe = tf.reshape(plt,[2,3])
10 print(plt_reshpe)
输出:
Tensor("Placeholder:0", shape=(?, 2), dtype=float32)
Tensor("Placeholder:0", shape=(3, 2), dtype=float32)
Tensor("Reshape:0", shape=(2, 3), dtype=float32)
如果原张量没有指定形状,即[None, 2],那么在使用动态形状改变方式reshape后得到新的张量,还是可以再次使用得到不一样总元素的张量
1 import tensorflow as tf
2 import os
3 os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' #去掉警告,将警告级别提升
4
5 plt = tf.placeholder(tf.float32,[None, 2]) #用[ ]不用()
6 print(plt) # Tensor("Placeholder:0", shape=(?, 2), dtype=float32)
7
8 plt_reshpe = tf.reshape(plt,[2,3])
9 print(plt_reshpe)
10
11 plt_reshpe = tf.reshape(plt,[6,2]) #动态数组可以再次修改
12 print(plt_reshpe)
输出:
Tensor("Placeholder:0", shape=(?, 2), dtype=float32)
Tensor("Reshape:0", shape=(2, 3), dtype=float32)
Tensor("Reshape_1:0", shape=(6, 2), dtype=float32)
综上:静态形状和动态形状的区别在于有没有生成一个新的张量数据,静态形状在修改确定后便不能再次进行设置,动态形状的修改受限于原来张量的元素个数,如果原来的张量的元素个数不确定,那么在使用动态形状修改后,仍然可以再次使用动态形状修改,而且不受限于元素的个数,因为动态形状改变就会生成一个新的张量数据,与原来的张量无关,所以再次使用动态形状修改自然也是可以的。
1、转换静态形状的时候,1-D到1-D, 2-D到2-D,不能跨阶数改变形状
2、对于已经固定或者设置静态形状的张量/变量,不能再次设置静态形状
3、tf.reshape()动态 创建新张量时,元素个数不能不匹配
(2)张量的操作
① 生成张量
1、生成固定值张量
- tf.zeros(shape, dtype=tf.float32, name=None) (常见)
创建所有元素设置为零的张量。此操作返回一个dtype具有形状shape和所有元素设置为零的类型的张量。
- tf.zeros_like(tensor, dtype=None, name=None)
给tensor定单张量() ,此操作返回tensor与所有元素设置为零相同的类型和形状的张量。
- tf.ones(shape, dtype=tf.float32, name=None) (常见)
创建一个所有元素设置为1的张量。此操作返回一个类型的张量,dtype形状shape和所有元素设置为1.
- tf.ones_like(tensor, dtype=None, name=None)
给tensor定单张量() ,此操作返回tensor与所有元素设置为1相同的类型和形状的张量。
- tf.fill(dims, value, name=None)
创建一个填充了标量值的张量。此操作创建一个张 量的形状dims并填充它value.
- tf.constant(value, dtype=None, shape=None, name='Const') (常见)
创建一个常数张量。
例:进入交互式操作,然后可以用eval()提取zeros的数据
2、生成随机值张量
一般我们经 常使用的随机数函数Math.random0产生的是服从均匀分布的随机数,能够模拟等概率出现的情况,例如扔一个骰子, 1到6点的概率应该相等,但现实生活中更多的随机现象是符合正态分布的,例如20岁成年人的体重分布等。
假如我们在制作一个游戏, 要随机设定许许多多NPC的身高,如果还用Math.random(),生成从140到220之间的数字,就会发现每个身高段的人数是一-样多的,这是比较无趣的,这样的世界也与我们习惯不同,现实应该是特别高和特别矮的都很少,处于中间的人数最多,这就要求随机函数符合正态分布。
- tf.truncated_normal(shape, mean=0.0, stddev=1.0, dtype =tf.float32, seed=None, name=None) (mean表示平均值,stddev表示标准差)
从截断的正态分布中输出随机值,和tf.random. normal() 一样,但是所有数字都不超过两个标准差
- tf.random_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None)
从正态分布中输出随机值,由随机正态分布的数字组成的矩阵
3、张量的类型转换
提供了如下一些改变张量中数值类型的函数
- tf.string_ to. number(string_ _tensor, out_ _type=None, name=None)
- tf.to double(x, name='ToDouble)
- tf.to_ float(x, name='ToFloat')
- tf.to_ bfloat16(x, name='ToBFloat16')
- tf.to_ _int32(x, name='Tolnt32')
- tf.to_ jint64(x, name= 'Tolnt64')
- tf.cast(x, dtype, name=None) (万能转换)
int32—>float32
4、张量的切片与拓展
tf.concat(values,axis,name='cancat')