Skip to content

Theano - 数据类型

在深入构建模型之前,理解 Theano 如何表示数据至关重要。Theano 使用符号变量(symbolic variables)工作,这些变量是实际数据的占位符(placeholders)。你需要先定义这些变量的结构和类型,然后使用它们构建表达式(expressions)。实际的数值计算发生在你编译(compile)并运行 Theano 函数(function)时。

Theano 提供了各种类型来定义这些符号变量,主要侧重于 tensor(张量,即多维数组),类似于 NumPy。以下是常见的 Theano tensor 类型总结:

概念常见 Theano 类型 (使用 theano.tensor)描述
标量 (0D Tensor)scalar (generic), bscalar, wscalar, iscalar, lscalar, fscalar, dscalar, cscalar单个值(例如,整数、浮点数)。前缀表示 dtype(数据类型):b=byte, w=int16, i=int32, l=int64, f=float32, d=float64, c=complex64/128。
向量 (1D Tensor)vector (generic), bvector, wvector, ivector, lvector, fvector, dvector, cvector一维数组。
矩阵 (2D Tensor)matrix (generic), bmatrix, wmatrix, imatrix, lmatrix, fmatrix, dmatrix, cmatrix二维数组(行和列)。
行向量 (特殊矩阵)row (generic), brow, wrow, irow, lrow, frow, drow, crow保证只有一行的矩阵。
列向量 (特殊矩阵)col (generic), bcol, wcol, icol, lcol, fcol, dcol, ccol保证只有一列的矩阵。
3D Tensortensor3 (generic), btensor3, wtensor3, itensor3, ltensor3, ftensor3, dtensor3, ctensor3三维数组。
ND Tensor (N > 3)tensor4, tensor5, etc. (generic), btensor4, …, dtensor4, …更高维度的数组。

注意:虽然 Theano 提供了高度特定的类型(如用于 int16 的 wscalar),但现代库通常默认为标准类型,如 int32、int64、float32 和 float64。在 Theano 中,f (float32) 和 d (float64) 类型在机器学习中非常常见。

让我们看看如何声明一些这样的符号变量。通常好的做法是使用别名 tt 来导入 theano.tensor。

import theano
import theano.tensor as tt
import numpy as np

要声明一个符号标量变量(代表一个双精度浮点数):

# 声明一个类型为 float64,名称为 'x' 的符号标量变量
x = tt.dscalar('x')
# 此时,'x' 仅是一个符号。它尚未持有具体数值。
print(type(x))
# 输出将显示类似内容:<class 'theano.tensor.var.TensorVariable'>

你会在稍后运行(run)涉及此变量的 Theano 函数时,为其赋予一个具体数值。

要声明一个包含 float32 值的符号向量(一维数组):

# 声明一个类型为 float32,名称为 'my_vector' 的符号向量
f_vec = tt.fvector('my_vector')
# 同样,这仅是一个占位符。
print(f_vec.type)
# 输出:TensorType(float32, vector)

你可以使用这些符号变量创建表达式:

# 示例表达式:向量的逐元素平方
f_vec_squared = f_vec ** 2
# 要对特定数值实际计算此结果,你需要一个 Theano 函数:
# (Theano 函数将在后续详细介绍)
calculate_square = theano.function(inputs=[f_vec], outputs=f_vec_squared)
# 现在,使用实际数据(一个 NumPy 数组)调用该函数
result = calculate_square(np.array([1.0, 2.0, 3.0], dtype='float32'))
print(result)
# 输出:[1. 4. 9.]

要声明一个包含整数的符号矩阵(二维数组):

# 声明一个类型为 int32,名称为 'int_matrix' 的符号矩阵
i_mat = tt.imatrix('int_matrix')
print(i_mat.type)
# 输出:TensorType(int32, matrix)

我们来定义一个简单的操作:

# 表达式:矩阵转置
i_mat_transposed = i_mat.T
# 编译一个用于计算转置的函数
get_transpose = theano.function(inputs=[i_mat], outputs=i_mat_transposed)
# 使用数据执行
data = np.array([[1, 2, 3], [4, 5, 6]], dtype='int32')
transposed_result = get_transpose(data)
print(transposed_result)
# 输出:
# [[1 4]
# [2 5]
# [3 6]]

你可以类似地声明更高维度的 tensor:

# 声明一个包含 float64 值的 4D tensor
tensor4d = tt.dtensor4('my_4d_tensor')
print(tensor4d.type)
# 输出:TensorType(float64, 4D)

这些对于表示深度学习中的数据至关重要,例如图像批次(Batch、Height、Width、Channels)或序列(sequences)。

除了像 fvector 或 dmatrix 这样特定的类型,你还可以使用 scalar、vector、matrix、tensor3、tensor4 等通用构造函数,并显式指定 dtype。这与 NumPy 和现代库的风格更接近。

# 使用通用构造函数声明一个 float32 向量
generic_vec = tt.vector('generic_vec', dtype='float32')
print(generic_vec.type)
# 输出:TensorType(float32, vector)
# 声明一个 int64 矩阵
generic_mat = tt.matrix('generic_mat', dtype='int64')
print(generic_mat.type)
# 输出:TensorType(int64, matrix)

使用这些通用构造函数并显式指定 dtype 通常更清晰灵活。

虽然理解 Theano 的数据类型和符号特性对于了解历史背景和掌握计算图(computational graphs)等概念很有价值,但 Theano 本身已不再活跃开发。现代深度学习框架,如 TensorFlow、PyTorch 和 JAX,提供了类似的 tensor 功能,并且拥有更精简的 API,以及针对当前硬件更好的性能优化。然而,此处学到的概念依然是相关的。