TensorFlow中的数据类型

TensorFlow中的数据类型

以下是 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]

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://cangmang.xyz/articles/tensorflow-data-type