以下是 TensorFlow 中常见的数据类型
数据类型 | TensorFLow 定义 | 描述 |
---|---|---|
DT_FLOAT |
tf.float32 |
32 位浮点数 |
DT_DOUBLE |
tf.float64 |
64 位浮点数 |
DT_INT64 |
tf.int64 |
64 位有符号整型 |
DT_INT32 |
tf.int32 |
32 位有符号整型 |
DT_INT16 |
tf.int16 |
16 位有符号整型 |
DT_INT8 |
tf.int8 |
8 位有符号整型 |
DT_UINT8 |
tf.uint8 |
8 位无符号整型 |
DT_STRING |
tf.string |
可变长度的字节数组,每个张量元素都是一个字节数组 |
DT_BOOL |
tf.bool |
布尔型 |
DT_COMPLEX64 |
tf.complex64 |
由两个 32 位浮点组成的复数:实数和虚数 |
DT_QINT32 |
tf.qint32 |
用于量化 Ops 的 32 位有符号整型 |
DT_QINT8 |
tf.qint8 |
用于量化 Ops 的 8 位有符号整型 |
数值类型
数值类型张量是 TensorFlow 中的主要数据载体,可以参与加减乘除等数值运算。
python 数据转换为 TensorFlow 张量
我们可以利用 tf.constant()
方法将 python 内置数据类型转换为数值类型张量:
import tensorflow as tf
py_value = 3.14 # python 内置数据类型:浮点数
tf_tensor = tf.constant(py_value) # 创建只含有一个元素的标量
print(py_value)
print(tf_tensor)
print(type(py_value)) # 查看 python 数据类型
print(type(tf_tensor)) # 查看 TensorFlow 数据类型
上述代码运行结果为:
3.14
tf.Tensor(3.14, shape=(), dtype=float32)
<class 'float'>
<class 'tensorflow.python.framework.ops.EagerTensor'>
判断是否为张量
同时可以利用 tf.is_tensor()
方法判断变量是否为张量:
import tensorflow as tf
py_value = 3.14
tf_tensor = tf.constant(py_value)
print(tf.is_tensor(py_value))
print(tf.is_tensor(tf_tensor))
上述代码运行结果为:
False
True
字符串类型
创建字符串类型张量
在 TensorFlow
中,直接传入字符串即可创建字符串类型的张量:
import tensorflow as tf
tf_tensor = tf.constant('Hello, TensorFlow!')
print(tf_tensor)
上述代码运行结果为:
tf.Tensor(b'Hello, TensorFlow!', shape=(), dtype=string)
从上述输出可以看到字符串的值为 b'Hello, TensorFlow!'
,前缀 b
表示这个字符串是一个字符数组(Byte Array
)。
提取子串
在 TensorFlow 中,无法直接对字符串进行切片操作,可以通过 tf.strings.substr()
方法来提取子串:
import tensorflow as tf
a_str = tf.constant("Hello, TensorFlow!")
print(a_str)
a_str_sub = tf.strings.substr(a_str, 0, 3)
print(a_str_sub)
上述代码运行结果为:
tf.Tensor(b'Hello, TensorFlow!', shape=(), dtype=string)
tf.Tensor(b'Hel', shape=(), dtype=string)
tf.strings.substr(a_str, 0, 3)
表示在 a_str
字符串对象中从下标 0
开始,提取长度为 3
的子串,其结果为 'Hel'
。
在 TensorFlow 中,还可以利用张量批量提取多个字符串的子串,而不必通过 for
循环实现:
import tensorflow as tf
# 字符串张量
input_strs = [
[b"ten", b"eleven", b"twelve"],
[b"thirteen", b"fourteen", b"fifteen"],
[b"sixteen", b"seventeen", b"eighteen"],
]
# 起始位置张量
position = [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
# 长度张量
length = [[2, 3, 4], [4, 3, 2], [5, 5, 5]]
# 批量提取子串
output = tf.strings.substr(input=input_strs, pos=position, len=length)
print(output)
上述代码中的
input_strs
是需要提取的原字符串数组,position
是保存起始位置的张量,length
是保存截取长度的张量。批量提取子串的整体思路就是将所有需要提取的字符串,每个字符串的起始位置和截取长度都用数组保存起来,最后调用substr()
方法完成批量提取子串的操作。
上述代码运行结果为:
tf.Tensor(
[[b'en' b'eve' b'lve']
[b'hirt' b'urt' b'te']
[b'ixtee' b'vente' b'hteen']], shape=(3, 3), dtype=string)
布尔类型
创建布尔型张量
TensorFlow 也支持布尔类型的张量,直接传入 Python 中的布尔类型即可:
import tensorflow as tf
vec_bool = tf.constant([True, False])
print(vec_bool)
上述代码运行结果为:
tf.Tensor([ True False], shape=(2,), dtype=bool)
布尔型张量的批处理操作
我们还可以利用布尔类型张量的批处理操作来计算分类算法的准确率:
import tensorflow as tf
vec_actual = tf.constant([1, 1, 2, 0, 1]) # 假设为分类实际值
vec_pre = tf.constant([1, 0, 1, 0, 1]) # 假设为算法预测的分类值
acc_bool = vec_actual == vec_pre # 判断预测是否准确
print(acc_bool)
acc_float = tf.cast(acc_bool, tf.float32) # 将布尔型转换成浮点型
acc_rate = tf.math.reduce_mean(acc_float) # 计算平均值(平均值即为准确率)
print(acc_rate)
上述代码运行结果为:
tf.Tensor([ True False False True True], shape=(5,), dtype=bool)
tf.Tensor(0.6, shape=(), dtype=float32)
数值类型转换
有时为了保证计算时数据类型和精度的准确性,需要对数值类型进行转换,我们可以采用 tf.cast()
方法:
tf.cast(x, dtype, name=None)
上述代码中的 x
表示要进行类型转换的变量,dtype
表示转换后的数值类型,name
表示操作的名称。
我们来看一个例子:
import numpy as np
import tensorflow as tf
a_const = tf.constant(np.pi, dtype=tf.float16) # 创建 tf.float16 低精度张量
a_double = tf.cast(a_const, tf.double) # 转换为 tf.double 双精度张量
print(a_const)
print(a_double)
上述代码运行结果为:
tf.Tensor(3.14, shape=(), dtype=float16)
tf.Tensor(3.140625, shape=(), dtype=float64)
上述代码中的
np.pi
表示π
,默认为双精度浮点数,通过指定默认数值类型tf.float16
来改变其数值类型,再调用tf.cast(a_const, tf.double)
方法将其转换为tf.double
双精度的张量,从输出信息中可以看出,张量的精度不同,所保存数据的小数点位数也是不同的。将张量从低精度张量转换到高精度张量是安全的,但反过来是不安全的,因为高精度的张量所占的存储空间更大,将高精度张量转换成低精度张量,存储空间会减小,可能会导致数据精度降低或溢出。
TensorFlow 中的张量和 Numpy 数组
TensorFlow 和 Numpy 数据类型的关系
TensorFlow 中的很多数值类型,正是基于 Numpy 数值类型的,我们来验证一下:
import numpy as np
import tensorflow as tf
print(np.int8 == tf.int8)
print(np.int16 == tf.int16)
print(np.int64 == tf.int64)
上述代码运行结果为:
True
True
True
Numpy 数据转换为 TensorFlow 张量
从上面的测试结果可以看出,TensorFlow 的数据类型与 Numpy 的数据类型是一致的,因此 Numpy 数据类型可以传递给 TensorFlow 来构建张量,我们利用一段代码进行验证:
import numpy as np
import tensorflow as tf
# 创建 Numpy 变量
n0 = np.array(20, dtype=np.int32)
n1 = np.array([b"Tensor", b"flow", b"is", b"great"])
n2 = np.array([[True, False, False], [False, True, False]], dtype=np.bool)
# 从 Numpy 变量构建 TensorFlow 张量
tensor0D = tf.Variable(n0, name="t_0")
tensor1D = tf.Variable(n1, name="t_1")
tensor2D = tf.Variable(n2, name="t_2")
print("tensor0D: {0}".format(tensor0D))
print("tensor1D: {0}".format(tensor1D))
print("tensor2D: {0}".format(tensor2D))
上述代码运行结果为:
tensor0D: <tf.Variable 't_0:0' shape=() dtype=int32, numpy=20>
tensor1D: <tf.Variable 't_1:0' shape=(4,) dtype=string, numpy=array([b'Tensor', b'flow', b'is', b'great'], dtype=object)>
tensor2D: <tf.Variable 't_2:0' shape=(2, 3) dtype=bool, numpy=
array([[ True, False, False],
[False, True, False]])>
TensorFlow 张量转换为 Numpy 数据
我们可以利用 numpy()
方法将 TensorFlow 张量转换为 Numpy 数据类型,如下:
import numpy as np
import tensorflow as tf
# 创建 Numpy 变量
n0 = np.array(20, dtype=np.int32)
n1 = np.array([b"Tensor", b"flow", b"is", b"great"])
n2 = np.array([[True, False, False], [False, True, False]], dtype=np.bool)
# 从 Numpy 变量构建 TensorFlow 张量
tensor0D = tf.Variable(n0, name="t_0")
tensor1D = tf.Variable(n1, name="t_1")
tensor2D = tf.Variable(n2, name="t_2")
print("tensor0D: {0}".format(tensor0D))
print("tensor1D: {0}".format(tensor1D))
print("tensor2D: {0}".format(tensor2D))
# 将 TensorFlow 张量转换为 Numpy 变量
tensor0D_np = tensor0D.numpy()
tensor1D_np = tensor1D.numpy()
tensor2D_np = tensor2D.numpy()
print("tensor0D_np: {0}".format(tensor0D_np))
print("tensor1D_np: {0}".format(tensor1D_np))
print("tensor2D_np: {0}".format(tensor2D_np))
上述代码运行结果为:
tensor0D_np: 20
tensor1D_np: [b'Tensor' b'flow' b'is' b'great']
tensor2D_np: [[ True False False]
[False True False]]
Python 数组和张量类型转换
我们可以利用 tf.convert_to_tensor()
方法将 Python 列表或元祖转换为张量,如下:
import tensorflow as tf
a_list = list([1, 2, 3]) # 创建一个列表
b_tuple = (11.0, 22.2, 33) # 创建一个元祖
c_str_tuple = ("a", "b", "c", "d") # 创建一个字符串元祖
# 将 python 数据类型转换为 TensorFlow 张量
tensor_a = tf.convert_to_tensor(a_list, dtype=tf.float32)
tensor_b = tf.convert_to_tensor(b_tuple)
tensor_c = tf.convert_to_tensor(c_str_tuple)
tensor_add = tf.math.add(tensor_a, tensor_b)
# 输出数据类型
print(type(a_list))
print(type(tensor_a))
print(type(b_tuple))
print(type(tensor_b))
print(type(c_str_tuple))
print(type(tensor_c))
print(type(tensor_add))
# 利用 tf.print() 方法输出张量的值
tf.print(tensor_c)
tf.print(tensor_add)
上述代码运行结果为:
<class 'list'>
<class 'tensorflow.python.framework.ops.EagerTensor'>
<class 'tuple'>
<class 'tensorflow.python.framework.ops.EagerTensor'>
<class 'tuple'>
<class 'tensorflow.python.framework.ops.EagerTensor'>
<class 'tensorflow.python.framework.ops.EagerTensor'>
["a" "b" "c" "d"]
[12 24.2 36]