Skip to content

Theano - 矩阵乘法表达式

让我们基于符号变量的概念来定义一个常见的操作:矩阵乘法(matrix multiplication),也称为点积(dot product)。我们将计算两个矩阵的点积,比如矩阵 A(形状 M x K)和矩阵 B(形状 K x N),结果将得到矩阵 C(形状 M x N)。

请记住,在 Theano 中,我们首先定义符号计算,然后编译(compile)一个函数来使用实际数据执行它。

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

我们声明两个符号变量来表示我们的输入矩阵。我们将使用 dmatrix,它代表一个双精度浮点数(float64)的矩阵。重要的是,在此阶段我们不需要指定确切的维度(M、K、N);Theano 会处理符号形状(symbolic shapes)。

# 声明符号矩阵 'A' (float64)
a = tt.dmatrix('A')
# 声明符号矩阵 'B' (float64)
b = tt.dmatrix('B')
print(f"Type of 'a': {a.type}")
print(f"Type of 'b': {b.type}")
# Output:
# Type of 'a': TensorType(float64, matrix)
# Type of 'b': TensorType(float64, matrix)

这些变量 a 和 b 仅仅是占位符。它们知道自己是浮点数矩阵,但尚未持有具体的数值。

现在,我们使用这些符号变量来定义要执行的操作。Theano 提供了 theano.tensor.dot() 函数用于矩阵乘法(以及一般的点积)。

# 定义点积的符号表达式
c = tt.dot(a, b)
# 'c' 也是一个代表结果的符号变量。
# Theano 根据输入类型和操作推断其类型。
print(f"Type of 'c': {c.type}")
# Output:
# Type of 'c': TensorType(float64, matrix)

此时,我们构建了一个小的计算图(computational graph):a 和 b 是输入,dot 是操作,c 是输出。尚未进行任何实际的数值计算。

为了使这个符号表达式可执行,我们将其编译成一个 Theano 函数。theano.function 接受一个符号输入列表和一个符号输出列表。

# 编译函数
# 输入:包含符号变量 'a' 和 'b' 的列表
# 输出:包含符号结果 'c' 的列表
matrix_multiply = theano.function(inputs=[a, b], outputs=c)
print(f"Type of compiled function: {type(matrix_multiply)}")
# Output:
# Type of compiled function: <class 'theano.compile.function_module.Function'>

这个编译步骤是 Theano 执行优化(计算图简化、潜在的 C 代码生成等)以提高执行效率的地方。

现在我们可以使用我们编译好的函数 matrix_multiply 来处理实际的数值数据了。Theano 函数通常期望以 NumPy 数组作为输入。

# 使用 NumPy 定义具体的输入矩阵
matrix_a = np.array([[0., -1., 2.], [4., 11., 2.]], dtype='float64') # 形状 (2, 3)
matrix_b = np.array([[3., -1.], [1., 2.], [6., 1.]], dtype='float64') # 形状 (3, 2)
print(f"Input Matrix A (shape {matrix_a.shape}):\n{matrix_a}")
print(f"Input Matrix B (shape {matrix_b.shape}):\n{matrix_b}")
# 使用 NumPy 数组调用编译好的函数
result_matrix = matrix_multiply(matrix_a, matrix_b)
print(f"\nResult Matrix C (shape {result_matrix.shape}):\n{result_matrix}")
# 预期输出:
# Result Matrix C (shape (2, 2)):
# [[11. 0.]
# [25. 20.]]

该函数接受与符号输入(a、b)对应的 NumPy 数组,并计算出与符号输出(c)对应的结果。

# 使用 Theano 进行矩阵乘法的完整程序
import theano
import theano.tensor as tt
import numpy as np
# 1. 声明符号变量(数据占位符)
a = tt.dmatrix('A') # float64 矩阵
b = tt.dmatrix('B') # float64 矩阵
# 2. 定义符号表达式(计算图)
c = tt.dot(a, b)
# 3. 将表达式编译成可执行函数
matrix_multiply = theano.function(inputs=[a, b], outputs=c)
# 4. 准备具体的输入数据(NumPy 数组)
matrix_a = np.array([[0., -1., 2.], [4., 11., 2.]], dtype='float64') # 形状 (2, 3)
matrix_b = np.array([[3., -1.], [1., 2.], [6., 1.]], dtype='float64') # 形状 (3, 2)
# 5. 使用数据调用函数
result_matrix = matrix_multiply(matrix_a, matrix_b)
# 6. 打印结果
print(f"输入矩阵 A:\n{matrix_a}")
print(f"输入矩阵 B:\n{matrix_b}")
print(f"\n结果矩阵 C (A dot B):\n{result_matrix}")

此示例演示了 Theano 的核心工作流程:定义符号变量,构建表达式图,将其编译成函数,然后使用具体数据(通常是 NumPy 数组)执行该函数。