张量的概念
TensorFlow中的Tensor就是张量,张量是数学对象,是对标量、向量、矩阵的泛化。我们可以直接理解成张量就是列表,就是多维数组。
张量的维数用阶来表示:
0阶张量 标量 单个值 例:a = 1
1阶张量 向量 1维数组 例:a = [1,2,3]
2阶张量 矩阵 2维数组 例:a = [[1,2,3],[4,5,6]]
n阶张量 张量 n维数组 例:a = [[[[[...n个括号...]]]]]
判断张量有几阶 就看等号右边的方括号有几个 0个就是0阶 2个就是2阶。
多维张量在内存中也是以一维数组的方式连续存储的。
创建张量
tf.constant()方法用来创建一个张量,传入内容,可以是数字、python列表、NumPy数组,第二个参数为指定数据类型,可以省略。
如:
import tensorflow as tf a = tf.constant([1,2,3],dtype=tf.int32) print(a)
打印结果:
tf.Tensor([1 2 3], shape=(3,), dtype=int32)
shape是张量的形状,一个张量有多少阶,就看形状中的逗号隔开了几个数字,比如形状为(3,)的张量 逗号隔开了3这一个数字,所以它的阶数是1阶,里面有3个元素, 再比如形状为(3,3)的张量 逗号隔开了3和3两个数字,所以它的阶数是2阶,并且是一个3行3列的矩阵。
当然,也可以以属性的方式来查看张量信息
print('张量的阶数:', a.ndim) print('张量的形状:', a.shape) print('张量的类型:', a.dtype)
打印结果:
张量的阶数: 1
张量的形状: (3,)
张量的类型: <dtype: 'int32'>
张量的数据类型
在上面创建张量我加了dtype参数指定数据类型为int32,不指定数据类型也是一样的,tensorflow会根据张量内容自动推断类型,如果张量内容是数字,那么默认数据类型是int32,如果张量内容是浮点数,那么默认数据类型是float32,如果需要指定其他位数如int64或float64就需要传递参数手动指定.
张量的数据类型有:
int 有符号整数
float 有符号浮点数
uint 无符号整数
以上这三种都有位数的划分,比如int有 tf.int8、tf.int16、tf.int32、tf.int64。
string 字符串
bool 布尔型
complex 复数 由实数和虚数组成
tf.cast()方法可以将张量的数据类型进行转换,比如:
import tensorflow as tf a = tf.constant([1,2,3],dtype=tf.int32) print(a) b = tf.cast(a,dtype=tf.int64) print(b)
打印结果:
tf.Tensor([1 2 3], shape=(3,), dtype=int32)
tf.Tensor([1 2 3], shape=(3,), dtype=int64)
NumPy数据转换
如果数据是由numpy创建的话,需要使用tf.convert_to_tensor()函数将numpy的数据类型转换成TensorFlow的张量数据类型。
import tensorflow as tf import numpy as np a = np.arange(0,10) print(a) b = tf.convert_to_tensor(a) print(b)
打印结果:
[0 1 2 3 4 5 6 7 8 9]
tf.Tensor([0 1 2 3 4 5 6 7 8 9], shape=(10,), dtype=int32)
注意一点的是,numpy创建浮点数矩阵的时候默认是float64类型,转换的时候tensorflow同样会去接收它的数据类型,因此由numpy数据生成的张量会出现默认浮点数类型是float64位的情况,如下:
import tensorflow as tf import numpy as np a = np.array([1.1,2.2,3.3]) print(a) b = tf.constant(a) print(b) c = tf.convert_to_tensor(a) print(c)
打印结果:
[1.1 2.2 3.3]
tf.Tensor([1.1 2.2 3.3], shape=(3,), dtype=float64)
tf.Tensor([1.1 2.2 3.3], shape=(3,), dtype=float64)
大多数机器学习场景下我们用32位浮点数已经足够满足计算需求,32位浮点数的运算比64位浮点数的运算要快的多,因此用numpy数组生成张量时可以显式的指定数据类型:
import tensorflow as tf import numpy as np a = np.array([1.1,2.2,3.3]) print(a) b = tf.constant(a,dtype=tf.float32) print(b) c = tf.convert_to_tensor(a,dtype=tf.float32) print(c)
打印结果:
[1.1 2.2 3.3]
tf.Tensor([1.1 2.2 3.3], shape=(3,), dtype=float32)
tf.Tensor([1.1 2.2 3.3], shape=(3,), dtype=float32)
固定张量
TensorFlow提供了一些创建固定张量的函数,比如创建值全是0的张量,创建值全是1的张量。
全0张量
tf.zeros(shape,dtype=float32)
参数的写法不止一种,记一种好记的就可以了,比如一维直接写个数,二维写[行数,列数],三维写[行数,列数,高度],多维以此类推 [n,m,k,j,......]
#创建一维张量 4个元素 a = tf.zeros(4) print(a) #创建一维张量 4个元素 aa = tf.zeros([4]) print(aa) #创建3行3列的二维张量 b = tf.zeros([3,3]) print(b) #创建3行3列的二维张量 bb = tf.zeros((3,3)) print(bb) #指定类型 c = tf.zeros([3,3],tf.int8) print(c)
全1张量
tf.ones(shape,dtype=float32)
创建值全是1的张量,除了将zeros函数替换成ones函数之外,创建用法和全0张量完全一致。
元素值相同的张量
tf.fill(shape,value)
fill函数没有dtype参数,它根据value参数自动判断类型。
#创建一维张量 4个元素 aa = tf.fill([4],10) print(aa)
打印结果:
tf.Tensor([10 10 10 10], shape=(4,), dtype=int32)
#创建3行3列的二维张量 c = tf.fill([3,3],4.4) print(c)
打印结果:
tf.Tensor(
[[4.4 4.4 4.4]
[4.4 4.4 4.4]
[4.4 4.4 4.4]], shape=(3, 3), dtype=float32)
tf.fill()方法完全可以让tf.constant()来代替。
随机数张量
正态分布
函数签名:tf.random.normal(shape,mean,stddev,dtype)
shape:张量形状
mean:均值 默认为0
stddev:标准差 默认为1
dtype:存储类型 默认为float32
示例:
#创建2行2列均值为0标准差为1的随机数张量 a = tf.random.normal([2, 2], mean=0, stddev=1) print(a)
打印结果:
tf.Tensor(
[[-0.849204 0.42851505]
[-2.1599882 -0.6131579 ]], shape=(2, 2), dtype=float32)
截断正态分布
函数签名:tf.random.truncated_normal(shape,mean,stddev,dtype)
本函数返回一个截断的正态分布,截断的标准是2倍的标准差,可以保证生成的数据更向均值集中。
示例:
b = tf.random.truncated_normal([2, 2], mean=0, stddev=1) print(b)
打印结果:
tf.Tensor(
[[-0.06899758 1.8015716 ]
[-0.39744875 0.00498725]], shape=(2, 2), dtype=float32)
通俗的说,就是当均值为0,标准差为1时,使用本函数创建出的随机张量中,不可能出现区间[-2,2]以外的点, 而使用tf.random.normal函数则可能出现区间[-2,2]以外的点。
设置随机种子
如果想要保证多次生成的随机数张量完全一致,可以设置相同的随机种子。
tf.random.set_seed(10) a = tf.random.normal([1,5]) print(a) tf.random.set_seed(10) b = tf.random.normal([1,5]) print(b)
打印结果:
tf.Tensor([[-0.8757808 0.3356369 -0.35219625 -0.30314562 -0.03882965]], shape=(1, 5), dtype=float32)
tf.Tensor([[-0.8757808 0.3356369 -0.35219625 -0.30314562 -0.03882965]], shape=(1, 5), dtype=float32)
均匀分布
函数签名:tf.random.uniform(shape,minval,maxval,dtype)
shape:张量形状
minval:最小值 闭区间
maxval:最大值 开区间
dtype:数据类型 默认float32
c = tf.random.uniform([2, 2], minval=0, maxval=1) print(c)
打印结果:
tf.Tensor(
[[0.46760368 0.58308244]
[0.5945486 0.2994659 ]], shape=(2, 2), dtype=float32)
序列张量
函数签名:tf.range(start,limit,delta,dtype)
start:起始数字 闭区间
limit:结束数字 开区间
delta:步长 默认1
dtype:数据类型 默认自动推断
用法如下:
#创建0-9序列 a = tf.range(10) print(a)
打印结果:
tf.Tensor([0 1 2 3 4 5 6 7 8 9], shape=(10,), dtype=int32)
#创建偶数序列 b = tf.range(10,delta=2) print(b)
打印结果:
tf.Tensor([0 2 4 6 8], shape=(5,), dtype=int32)
#创建奇数序列 c = tf.range(1,10,delta=2) print(c)
打印结果:
tf.Tensor([1 3 5 7 9], shape=(5,), dtype=int32)
张量的运算
四则运算
注意,只有阶数相同的张量才可以做四则运算
加法:tf.add
a = tf.constant([1,2,3]) b = tf.constant([1,2,3]) print(tf.add(a,b))
打印结果:
tf.Tensor([2 4 6], shape=(3,), dtype=int32)
减法:tf.subtract
a = tf.constant([2,4,6]) b = tf.constant([0,0,3]) print(tf.subtract(a,b))
打印结果:
tf.Tensor([2 4 3], shape=(3,), dtype=int32)
乘法:ttf.multiply
a = tf.constant([2,4,6]) b = tf.constant([0,0,3]) print(tf.multiply(a,b))
打印结果:
tf.Tensor([ 0 0 18], shape=(3,), dtype=int32)
除法:tf.divide
a = tf.constant([2,4,6]) b = tf.constant([0,0,3]) print(tf.divide(b,a))
打印结果:
tf.Tensor([0. 0. 0.5], shape=(3,), dtype=float64)
平方、次方与开方
对张量求平方:tf.square
a = tf.constant([1,2,3,4,5]) print(tf.square(a))
打印结果:
tf.Tensor([ 1 4 9 16 25], shape=(5,), dtype=int32)
对张量求次方:tf.pow
a = tf.range(5) #创建一个序列张量 0 1 2 3 4 b = tf.pow(a,3) #求序列张量的3次方 print(b)
打印结果:
tf.Tensor([ 0 1 8 27 64], shape=(5,), dtype=int32)
如果说求a张量的b张量次方,那么就等于是将a张量的每个位置的元素求b张量中对应元素的次方。
a = tf.constant([[2,2],[2,2]]) b = tf.constant([[1,2],[3,4]]) print(tf.pow(a,b))
打印结果:
tf.Tensor(
[[ 2 4]
[ 8 16]], shape=(2, 2), dtype=int32)
如果指数是分数,那么就是根号运算。比如指数是0.5的话,那么就是对张量逐元素求平方根。
a = tf.constant([1,4,9,16,25],dtype=tf.float32) print(tf.pow(a,0.5))
打印结果:
tf.Tensor([1. 2. 3. 4. 5.], shape=(5,), dtype=float32)
开根号会涉及小数点,因此张量元素类型必须是浮点数类型
对张量求平方根:tf.sqrt
a = tf.constant([1,4,9,16,25],dtype=tf.float64) print(tf.sqrt(a))
打印结果:
tf.Tensor([1. 2. 3. 4. 5.], shape=(5,), dtype=float64)
其他运算
除了常用的运算之外,tensorflow还提供了其他更广泛的运算。
tf.sign(x) 取符号
tf.abs(x) 求绝对值
tf.negative(x) 求相反数
tf.reciprocal(x) 求倒数
tf.ceil(x) 向上取整
tf.floor(x) 向下取整
tf.round(x) 四舍五入取整
tf.maximum(x,y)返回两个张量中的最大值 (逐个位置比较两张量的元素,取最大值,最终返回一个新张量)
tf.minimum(x,y)返回两个张量中的最小值 (逐个位置比较两张量的元素,取最小值,最终返回一个新张量)
重载运算符
为了使用简便,tensorflow将常用的数学运算符号进行了重载,让我们可以对张量进行直接运算而不用显式调用函数进行运算。
例如加法运算,可以直接把tf.add(a,b)写成a+b
a = tf.constant([1,2,3]) b = tf.constant([1,2,3]) print(tf.add(a,b)) print(a+b)
打印结果:
tf.Tensor([2 4 6], shape=(3,), dtype=int32)
tf.Tensor([2 4 6], shape=(3,), dtype=int32)
矩阵乘法
矩阵乘法是线性代数中很重要的内容,矩阵乘法的条件是第一个矩阵的列数要等于第二个矩阵的行数才可以进行乘法计算。
计算规则是,第一个矩阵的每行的每个数字与第二个矩阵的每列的每个数字对应相乘再相加,计算结果是第一个矩阵的行数第二个矩阵的列数所对应的值。
比如矩阵A:
2 3
4 5
矩阵B:
1 2
3 4
AB两矩阵相乘,得到新矩阵C
C11:2*1 + 3*3 = 11
C12:2*2 + 3*4 = 16
C21:4*1 + 5*3 = 19
C22:4*2 + 5*4 = 28
也就是:
11 16
19 28
可以用tf.matmul(a,b)函数来计算矩阵乘积,也可以用@运算符来进行运算。
a = tf.constant([[2,3],[4,5]]) print(a) b = tf.constant([[1,2],[3,4]]) print(b) print(tf.matmul(a,b))
打印结果:
tf.Tensor(
[[2 3]
[4 5]], shape=(2, 2), dtype=int32)
tf.Tensor(
[[1 2]
[3 4]], shape=(2, 2), dtype=int32)
tf.Tensor(
[[11 16]
[19 28]], shape=(2, 2), dtype=int32)
张量的统计
常用统计函数有如下四种:
tf.reduce_sum(tensor,axis) 求和
tf.reduce_mean(tensor,axis) 求平均值
tf.reduce_max(tensor,axis) 求最大值
tf.reduce_min(tensor,axis) 求最小值
参数axis为0时,代表纵向操作,沿经度方向(也就是按列、跨行),axis为1时,代表横向操作,沿纬度方向(也就是按行、跨列),不指定axis则代表全局操作。
a = tf.constant([[5,3,1],[2,4,6]]) print(a) print('纵向操作:{}'.format(tf.reduce_sum(a,0))) print('横向操作:{}'.format(tf.reduce_sum(a,1))) print('全局操作:{}'.format(tf.reduce_sum(a)))
打印结果:
tf.Tensor(
[[5 3 1]
[2 4 6]], shape=(2, 3), dtype=int32)
纵向操作:[7 7 7]
横向操作:[ 9 12]
全局操作:21
求平均值需要提一下,求出的结果数据类型与原始张量的数据类型会保持一致,也就会出现如下现象:
a = tf.constant([[5,3,1],[2,4,6]]) print(a) print(tf.reduce_mean(a,0))
打印结果:
[[5 3 1]
[2 4 6]], shape=(2, 3), dtype=int32)
tf.Tensor([3 3 3], shape=(3,), dtype=int32)
纵向求平均值第一列5+2=7,除以2得3.5,但是受限于int数据类型,所以最后的值为3
为了解决这个问题,我们可以将张量的数据类型转换成float再进行统计即可。
a = tf.constant([[5,3,1],[2,4,6]]) print(a) print(tf.reduce_mean(tf.cast(a,dtype=tf.float32),0))
打印结果:
tf.Tensor(
[[5 3 1]
[2 4 6]], shape=(2, 3), dtype=int32)
tf.Tensor([3.5 3.5 3.5], shape=(3,), dtype=float32)