创建张量1
TensorFlow中的Tensor表示张量,其实就是多维数组。在此之前,我们还学习过
-
python中的列表list
-
Numpy中的数组对象ndarray
它们也都可以作为数据的载体,那么它们有何区别呢? -
Python列表(list)
- 元素可以使用不同的数据类型,可以嵌套
- 在内存中不连续存放,是一个动态的指针数据
- 读写效率低,占用内存空间大
- 不适合做数值计算
-
Numpy数组(ndarray)
- 元素数据类型相同
- 每个元素在内存中占用的空间相同,存储在一个连续的内存区域中
- 存储空间小,读取和写入速度快
- 在CPU中运算,不能够主动检测、利用GPU进行计算
-
TensorFlow张量(Tensor)
- 可以高速运行于GPU和TPI之上
- 支持CPU、嵌入式、单机多卡和多机多卡等多种计算环境
- 高速的实现神经网络和深度学习中的复杂算法
TensorFlow的基本运算、参数命名、运算规则、API的设计与Numpy非常相近。
创建Tensor对象
张量由Tensor类实现,每个张量都是一个Tensor对象,可以使用tf.constant()的函数来创建张量。
tf.constant(value, dtype, shape)
其中参数
value:可以是一个数,一个Python列表也可以是一个Numpy数组参数
dtype:元素的数据类型,可以省略
shape:张量的形状,可以省略
参数为python列表
首先是用python列表来创建张量。这里将value参数指定为一个二维列表,其他参数省略。
这是运行结果
tf.constant([[1, 2], [3, 4]])
"""
<tf.Tensor: id=0, shape=(2, 2), dtype=int32, numpy=
array([[1, 2],
[3, 4]])>
"""
这个尖括号表示这是tensorflow返回的提示信息, tf.tensor表示这是tenseflow中的张量对象,id是张量的序号由系统自动按顺序给出,shape是张量的形状,这是一个二维张量,形状是(2, 2),我们没有给出数据类型,默认为32位整型,最后是这个张量的值,以Numpy数组的形式给出
张量的.numpy()方法
tensorflow中的张量是对Numpy数组的封装,在tensorflow2.0中所有的张量都可以通过numpy方法得到它对应的数组,例如
a = tf.constant([[1, 2], [3, 4]])
a.numpy()
"""
array([[1, 2],
[3, 4]])
"""
type(a)
"""
<class 'tensorflow.python.framework.ops.EagerTensor'>
"""
print(a)
"""
tf.Tensor(
[[1 2]
[3 4]], shape=(2, 2), dtype=int32)
"""
参数为数字
张量也可以是一个数字
tf.constant(1.0)
# <tf.Tensor: id=3, shape=(), dtype=float32, numpy=1.0>
这里形状是一个空括号,表示0维张量,tensorflow创建浮点数张量时,默认是float32类型。
tf.constant(1.)
# <tf.Tensor: id=4, shape=(), dtype=float32, numpy=1.0>
为了方便,这里也可以将小数点后的0省略。
tf.constant(1.0, dtype=tf.float64)
# <tf.Tensor: id=5, shape=(), dtype=float64, numpy=1.0>
张量元素的数据类型
数据类型 | 描述 |
---|---|
tf.int8 | 8位有符号整数 |
tf.int16 | 16位有符号整数 |
tf.int32 | 32位有符号整数 |
tf.int64 | 64位有符号整数 |
tf.uint8 | 8位无符号整数 |
tf.float32 | 32位浮点数 |
tf.float64 | 64位浮点数 |
tf.string | 字符串 |
tf.bool | 布尔型 |
tf.complex64 | 复数,实部和虚部分别为32位浮点数 |
也可以在常见张量时,指定张量的数据类型。
tf.constant(1.0, dtype=tf.float64)
# <tf.Tensor: id=5, shape=(), dtype=float64, numpy=1.0>
tf.constant(1.0, dtype=float64)
"""
Traceback (most recent call last):
File "<input>", line 1, in <module>
NameError: name 'float64' is not defined
"""
是因为在python中是找不到这个数据类型的。
参数为numpy数组
import numpy as np
tf.constant(np.array([1, 2]))
# <tf.Tensor: id=6, shape=(2,), dtype=int32, numpy=array([1, 2])>
tf.constant(np.array([1.0, 2.0]))
# <tf.Tensor: id=7, shape=(2,), dtype=float64, numpy=array([1., 2.])>
tf.constant(np.array([1.0, 2.0]), dtype=tf.float32)
# <tf.Tensor: id=8, shape=(2,), dtype=float32, numpy=array([1., 2.], dtype=float32)>
numpy创建浮点数数组时,默认的浮点型是64位浮点数。当使用Numpy数组创建张量时,TensorFlow会接受数组元素的数据类型,使用64位浮点数保存数据。
在GPU上运行TensorFlow程序处理32位浮点数的速度比处理64位浮点数要快得多,而对于大多数深度学习算法使用32位整数或者32位浮点数就可以满足运算的精度了,因此在使用numpy数组创建张量时,建议指明数据类型为32位浮点数,除非非常确定需要使用64位浮点数的情况。
tf.constant()函数:改变张量中元素的数据类型
在张量创建之后,也可以使用tf.cast()的函数改变张量中元素的数据类型。
tf.cast(x, dtype)
例如
a = tf.constant(np.array([1, 2]))
b = tf.cast(a, dtype=tf.float32)
print(b.dtype)
# tf.float32
a = tf.constant(123456789, dtype=tf.int32)
tf.cast(a, tf.int16)
# <tf.Tensor: id=11, shape=(), dtype=int32, numpy=123456789>
参数为布尔型
0表示False,非0表示True
tf.constant(True)
# <tf.Tensor: id=13, shape=(), dtype=bool, numpy=True>
a = tf.constant([True, False])
tf.cast(a, tf.int32)
# <tf.Tensor: id=16, shape=(2,), dtype=int32, numpy=array([1, 0])>
a = tf.constant([-1, 0, 1, 2])
tf.cast(a, tf.bool)
# <tf.Tensor: id=18, shape=(4,), dtype=bool, numpy=array([ True, False, True, True])>
参数为字符串
tf.constant("hello")
# <tf.Tensor: id=19, shape=(), dtype=string, numpy=b'hello'>
可以看到数据类型是string,这里的b表示,这是一个字节串,因为在python3中字符串,默认是unicode的编码,因此要转换成字节串,就要在原先的字符串前面加上一个b
tf.convert_to_tensor()函数
除了constant的函数之外,还可以使用tf.convert_to_tensor()函数来创建张量参数
tf.convert_to_tensor(数组/列表/数字/布尔型/字符串)
例如
na = np.arange(12).reshape(3, 4)
ta = tf.convert_to_tensor(na)
type(na)
# <class 'numpy.ndarray'>
type(ta)
# <class 'tensorflow.python.framework.ops.EagerTensor'>
可以使用is_tensor()函数来判断变量是不是张量。
is_tensor()
tf.is_tensor(ta)
# True
tf.is_tensor(na)
# False
另外,还可以使用python原生的isinstance()函数来验证。
isinstance(ta, tf.Tensor)
# True
isinstance(na, np.ndarray)
# True
创建张量2
类似于numpy,TensorFlow中也可以直接生成一些特殊的张量,例如全0张量,全1张量,所有元素的值都相同的张量,以及元素取值符合某种随机分布的张量。
创建全0张量和全1张量
创建全0张量和全1张量,分别使用tf.zeros()
和tf.ones()
函数
tf.zeros(shape, dtype=tf.float32)
tf.ones(shape, dtype=tf.float32)
- shape 是张量的形状。
- dtype 是张量数据的数据类型,默认是32位浮点数
例如
tf.ones(shape=(2, 1))
"""
<tf.Tensor: id=23, shape=(2, 1), dtype=float32, numpy=
array([[1.],
[1.]], dtype=float32)>
"""
tf.ones([6])
"""
<tf.Tensor: id=26, shape=(6,), dtype=float32, numpy=array([1., 1., 1., 1., 1., 1.], dtype=float32)>
"""
tf.ones([2, 3], tf.int32)
"""
<tf.Tensor: id=29, shape=(2, 3), dtype=int32, numpy=
array([[1, 1, 1],
[1, 1, 1]])>
"""
zeros的用法和ones的完全相同。
创建元素都相同的张量–tf.fill()函数
tf.fill(dims, value)
dims 是形状
value 是填充的值
tf.fill([2, 3], 9)
"""
<tf.Tensor: id=32, shape=(2, 3), dtype=int32, numpy=
array([[9, 9, 9],
[9, 9, 9]])>
"""
tf.fill([2, 3], 9.0)
"""
<tf.Tensor: id=35, shape=(2, 3), dtype=float32, numpy=
array([[9., 9., 9.],
[9., 9., 9.]], dtype=float32)>
"""
创建元素都相同的张量–tf.constant()函数
tf.constant(value=9, shape=[2, 3])
"""
<tf.Tensor: id=38, shape=(2, 3), dtype=int32, numpy=
array([[9, 9, 9],
[9, 9, 9]])>
"""
tf.fill(dims=[2, 3], value=9)
"""
<tf.Tensor: id=41, shape=(2, 3), dtype=int32, numpy=
array([[9, 9, 9],
[9, 9, 9]])>
"""
创建随机数张量–正态分布
tf.random.normal(shape, mean, stddev, dtype)
shape:张量的形状
mean:均值
stddev:标准差
dtype:元素的数据类型,默认是32位浮点数
当均值和标准差省略时,默认是标准正态分布,均值为0,标准差为1。
例:创建一个2*2的张量,其元素服从标准正态分布的张量
tf.random.normal([2, 2])
"""
<tf.Tensor: id=47, shape=(2, 2), dtype=float32, numpy=
array([[-0.07223961, 1.2670088 ],
[-0.0232278 , -0.44618014]], dtype=float32)>
"""
创建一个三维张量,其元素服从正态分布。
tf.random.normal([3, 3, 3], mean=0.0, stddev=2.0)
"""
<tf.Tensor: id=53, shape=(3, 3, 3), dtype=float32, numpy=
array([[[-2.343591 , -2.5604963 , -3.131829 ],
[-2.6622703 , -2.3248575 , 3.6765773 ],
[-2.0164406 , -0.5749179 , -2.8921757 ]],
[[-0.8125065 , 1.0438641 , -0.51730233],
[ 1.4487618 , -1.4161435 , -1.0760221 ],
[ 1.8550812 , 0.32153162, -0.636167 ]],
[[ 0.84067494, -0.92889154, -2.2943053 ],
[ 0.8124192 , 3.7003622 , -1.2836558 ],
[-2.2072492 , 0.14961068, 3.3054852 ]]], dtype=float32)>
"""
创建随机数张量–截断正态分布
tf.random.truncated_normal(shape, mean, stddev, dtype)
返回一个截断的正态分布
截断的标准是2倍的标准差,也就是说它不会创建任何偏离均值,标准差的值,从而可以防止张量中个别元素和其他元素有太大的差异。
例如当均值为0,标准差为1时,
- 使用
tf.random.truncated_normal()
函数的输出是不可能出现区间[-2, 2]以外的点的 - 而如果形状足够大的时候,使用
tf.random.normal()
,却可能会产生区间[-2, 2]之外的输出
设置随机种子–tf.random.set_seed()函数
tf.random.set_seed(8)
tf.random.normal([2, 2])
"""
<tf.Tensor: id=60, shape=(2, 2), dtype=float32, numpy=
array([[ 1.2074401, -0.7452462],
[ 0.6908678, -0.7635988]], dtype=float32)>
"""
tf.random.set_seed(8)
tf.random.normal([2, 2])
"""
<tf.Tensor: id=60, shape=(2, 2), dtype=float32, numpy=
array([[ 1.2074401, -0.7452462],
[ 0.6908678, -0.7635988]], dtype=float32)>
"""
创建均匀分布张量–tf.random.uniform()函数
tf.random.uniform(shape, minval, maxval, dtype)
shape:形状
minval:最小值
maxval:最大值
dtype:元素的数据类型
这个区间是前闭后开的,不包括最大值。
tf.random.uniform(shape=(3, 3), minval=0, maxval=10, dtype='int32')
"""
<tf.Tensor: id=64, shape=(3, 3), dtype=int32, numpy=
array([[6, 8, 3],
[9, 5, 1],
[8, 6, 1]])>
"""
随机打乱–tf.random.shuffle()函数
x = tf.constant([[1, 2], [3, 4], [5, 6]])
tf.random.shuffle(x)
"""
<tf.Tensor: id=66, shape=(3, 2), dtype=int32, numpy=
array([[1, 2],
[5, 6],
[3, 4]])>
"""
y = [1, 2, 3, 4, 5, 6]
tf.random.shuffle(y)
"""
<tf.Tensor: id=70, shape=(6,), dtype=int32, numpy=array([6, 5, 1, 2, 3, 4])>
"""
z = np.arange(5)
tf.random.shuffle(z)
"""
<tf.Tensor: id=72, shape=(5,), dtype=int32, numpy=array([4, 0, 3, 2, 1])>
"""
随机序列–tf.range()函数
tf.range(start, limit, delta=1, dtype)
start:起始数字
limit:结束数字
delta:步长
tf.range(10)
# <tf.Tensor: id=80, shape=(10,), dtype=int32, numpy=array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])>
tf.range(10, delta=2)
# <tf.Tensor: id=84, shape=(5,), dtype=int32, numpy=array([0, 2, 4, 6, 8])>
tf.range(1, 10, delta=2)
# <tf.Tensor: id=88, shape=(5,), dtype=int32, numpy=array([1, 3, 5, 7, 9])>
小结:创建张量
Tensor对象的属性–ndim、shape、dtype
在创建张量时,就可以在返回结果中看到张量的shape和dtype的属性。
tf.constant([[1, 2], [3, 4]])
"""
<tf.Tensor: id=1, shape=(2, 2), dtype=int32, numpy=
array([[1, 2],
[3, 4]])>
"""
也可以将所创建的张量复制给一个Python变量,然后通过变量名.属性名的方式来查看它。
例如将张量赋值给变量a,然后分别输出这个张量变量的维度,元素数据类型和形状
a = tf.constant([[1, 2], [3, 4]])
print("ndim", a.ndim)
print("dtype", a.dtype)
print("shape", a.shape)
运行结果
ndim 2
dtype <dtype: 'int32'>
shape (2, 2)
Tensor对象的shape()、size()、rank()方法
Tensor和Numpy数组
通过前面的学习,我们已经发现张量和Numpy数组互不相同又紧密相关,张量可以看作是在Numpy数组的基础上又做了一层封装,使它可以执行Tensor flow中的API,并且可以运行于GPU和TPU,支持单机多卡,多机多卡等不同的环境。
- 在Tensor flow中,所有的运算都是在张量之间进行的。
- Numpy数组仅仅是作为输入和输出来使用。
例如在运算之前,通过Numpy数组提供数据生成张量对象,在运算的过程中或者运算结束之后,可以使用张量对象的numpy方法获取张量的值,以numpy数组的形式返回给我们,而在Tensor flow的整个计算过程中,numpy数组是不参与运算的。 - 张量可以运行于CPU,也可以运行于GPU和TPU。
- numpy数组,只能够在CPU中运行。
当张量在CPU中运行时,它和numpy数组其实是共享同一段内存的,只是读出和理解它的方式不同而已。因此这种情况下使用张量的numpy方法可以非常快的得到结果。
而当张量是在GPU上运行时,就把内存中的numpy数组的内容再拷贝一份到GPU的显存中,在GPU中做高速运算,这时如果用numpy方法读取它的值,就需要再从GPU的解存中拷贝到内存中。