38.3_矩阵的转置
38.3 矩阵的转置
接下来实现进行矩阵转置的函数。矩阵的转置是对矩阵进行图38-3这种变形处理。
如图38-3所示,转置改变了矩阵的形状。下面在DeZero中实现执行转置操作的函数。

图38-3 矩阵转置的例子
本节中实现的转置函数 transpose 只支持输入变量是矩阵(二阶张量)的情况。实际的 DeZero 的 transpose 函数的实现更为通用,它支持轴数据的替换。这部分内容将在本步骤的最后一节介绍。
我们可以使用NumPy的transpose函数执行转置操作,示例如下。
$\mathbf{x} = \mathbf{np}$ .array([[1,2,3],[4,5,6]])
y $=$ np.transpose(x)
print(y)运行结果
[1
[25]
[36]]
上面的代码使 的形状由 (2, 3) 变为 (3, 2)。张量的元素本身没有发生改变,改变的是张量的形状。因此,它的反向传播只改变从输出端传播的梯度的形状。形状的改变方式正好是正向传播的逆向变化。基于以上内容,我们按如下方式实现 DeZero 的 transpose 函数。
dezero/functions.py
class Transpose(Function): def forward(self, x):$\mathsf{y} = \mathsf{np}$ .transpose(x) return y def backward(self, gy): $\mathtt{gx} =$ transpose(gy) return gx def transpose(x): return Transpose() (x)上面的代码在正向传播的过程中使用np.transpose函数进行转置,在反向传播的过程中使用正在实现的transpose函数对从输出端传来的梯度进行转置。因此,反向传播中所做的转置是正向传播的逆转置。下面我们来实际使用一下transpose函数。
steps/step38.py
$\mathbf{x} =$ Variable(np.array([[1,2,3],[4,5,6]]))
y $=$ F.transpose(x)
y.backup()
print(x.grad)运行结果
variable([[1 1 1] [1 1 1]])从上面的代码可以看出,transpose函数可以用于计算,也可以顺利实现反向传播。接下来,为了能够从Variable变量调用transpose函数,我们来添加以下代码。
dezero/core.py
class Variable: def transpose(self): returndezero-functions.transpose(self) @property defT(self): returndezero-functions.transpose(self)上面的代码添加了两个方法。第一个方法可以作为transpose方法使用,第二个方法通过添加@property,可以让自己作为实例变量来使用。由此,我们可以编写如下代码。
$\begin{array}{rl} & {\mathrm{x} = \mathrm{Variable(np.random.randint(2,3))}}\\ & {\mathrm{y} = \mathrm{x}.}\end{array}$ transpose()
$\mathbf{y} = \mathbf{x}.\mathbf{T}$到这里我们就实现了执行转置操作的transpose函数。本节实现的transpose函数只支持矩阵,实际的DeZero的transpose函数在本节内容的基础上增加了一些代码。下面笔者对此进行补充说明。
38.4 实际的transpose函数(补充内容)
NumPy的np.transpose函数有更为通用的用法,这个用法就是改变轴的数据顺序。下面是一个实际的例子。
A,B,C,D=1,2,3,4
x=np.random.randint(A,B,C,D)
y=x.transpose(1,0,3,2)上面的代码中有形状为 的数据,代码中使用 np.transpose 函数改变了形状的轴(为了方便大家理解,这里使用 A 等变量来表示形状的值)。代码中的参数是变换后的轴的顺序。图 38-4 可以帮助我们理解这些内容。

图38-4 np.transpose函数的具体例子
如上图所示,如果指定了轴的顺序,数据的轴就会按照指示重新排序。如果参数为 None,轴就会以相反的顺序重新排序。默认参数是 None。因此,如果 是矩阵,那么 x.transpose() 可以使轴 0 和轴 1 的数据按照轴 1、轴 0 的顺序排列,这正是矩阵的转置操作。
DeZero的transpose函数也支持对轴的数据进行调换。它的反向传播只执行轴的反向调换。这里没有展示相关代码。感兴趣的读者可以参考dezero/functions.py中Transpose类的代码。