将矩阵扩展为张量
Expanding a matrix to a tensor
我有一个 (m, n)
矩阵,其中每一行都是具有 n
特征的示例。我想将其扩展为 (m, n, n)
矩阵,即为每个示例创建其特征的外积。我研究了 tensordot
但还没有找到这样做的方法 - 它似乎只收缩张量,而不是扩展它。
a = np.arange(5*3).reshape(5, 3, 1)
b = np.arange(5*3).reshape(1, 3, 5)
c = np.tensordot(a, b, axes=([1,2],[1,0])) # gives a (5,5) matrix
c = np.tensordot(a, b, axes=([1,2],[0,1])) # throws a shape-mismatch error
我将为一行举一个简单的例子。假设你有 col 向量 a = [1, 2, 3]
我想要得到的是 a * a.T
即:
1, 2, 3
2, 4, 6
3, 6, 9
In [220]: a = np.arange(15).reshape(5,3)
In [221]: a
Out[221]:
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11],
[12, 13, 14]])
使用标准numpy
广播:
In [222]: a[:,:,None]*a[:,None,:]
Out[222]:
array([[[ 0, 0, 0],
[ 0, 1, 2],
[ 0, 2, 4]],
[[ 9, 12, 15],
[ 12, 16, 20],
[ 15, 20, 25]],
[[ 36, 42, 48],
[ 42, 49, 56],
[ 48, 56, 64]],
[[ 81, 90, 99],
[ 90, 100, 110],
[ 99, 110, 121]],
[[144, 156, 168],
[156, 169, 182],
[168, 182, 196]]])
In [223]: _.shape
Out[223]: (5, 3, 3)
einsum
被提及:
In [224]: np.einsum('ij,ik->ijk',a,a).shape
Out[224]: (5, 3, 3)
广播作品:
(5,3) => (5,3,1) and (5,1,3) => (5,3,3)
None
索引就像您的 reshape(5,3,1)
,添加一个维度。在广播大小 1 中,维度与其他数组的相应维度相匹配。 reshape
便宜;随意使用。
tensordot
起的不好; 'tensor' 意味着它可以处理大于 2d 的数据(但是所有 numpy 都可以这样做)。 'dot'指的是点积,收缩。对于 einsum
和 matmul/@
,不需要 tensordot
。并且从未用于创建更高维的数组。
我有一个 (m, n)
矩阵,其中每一行都是具有 n
特征的示例。我想将其扩展为 (m, n, n)
矩阵,即为每个示例创建其特征的外积。我研究了 tensordot
但还没有找到这样做的方法 - 它似乎只收缩张量,而不是扩展它。
a = np.arange(5*3).reshape(5, 3, 1)
b = np.arange(5*3).reshape(1, 3, 5)
c = np.tensordot(a, b, axes=([1,2],[1,0])) # gives a (5,5) matrix
c = np.tensordot(a, b, axes=([1,2],[0,1])) # throws a shape-mismatch error
我将为一行举一个简单的例子。假设你有 col 向量 a = [1, 2, 3]
我想要得到的是 a * a.T
即:
1, 2, 3
2, 4, 6
3, 6, 9
In [220]: a = np.arange(15).reshape(5,3)
In [221]: a
Out[221]:
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11],
[12, 13, 14]])
使用标准numpy
广播:
In [222]: a[:,:,None]*a[:,None,:]
Out[222]:
array([[[ 0, 0, 0],
[ 0, 1, 2],
[ 0, 2, 4]],
[[ 9, 12, 15],
[ 12, 16, 20],
[ 15, 20, 25]],
[[ 36, 42, 48],
[ 42, 49, 56],
[ 48, 56, 64]],
[[ 81, 90, 99],
[ 90, 100, 110],
[ 99, 110, 121]],
[[144, 156, 168],
[156, 169, 182],
[168, 182, 196]]])
In [223]: _.shape
Out[223]: (5, 3, 3)
einsum
被提及:
In [224]: np.einsum('ij,ik->ijk',a,a).shape
Out[224]: (5, 3, 3)
广播作品:
(5,3) => (5,3,1) and (5,1,3) => (5,3,3)
None
索引就像您的 reshape(5,3,1)
,添加一个维度。在广播大小 1 中,维度与其他数组的相应维度相匹配。 reshape
便宜;随意使用。
tensordot
起的不好; 'tensor' 意味着它可以处理大于 2d 的数据(但是所有 numpy 都可以这样做)。 'dot'指的是点积,收缩。对于 einsum
和 matmul/@
,不需要 tensordot
。并且从未用于创建更高维的数组。