特征收缩 vs Numpy Dot

Posted

技术标签:

【中文标题】特征收缩 vs Numpy Dot【英文标题】:Eigen Contraction vs Numpy Dot 【发布时间】:2018-02-07 21:45:06 【问题描述】:

大家好,我在 Numpy 中有以下张量点积:

import numpy as np

tensorA = np.array([[[1,2,3],
                  [4,5,6],
                  [7,8,9]],
                 [[10,11,12],
                  [13,14,15],
                  [16,17,18]],
                 [[19,20,21],
                  [22,23,24],
                  [25,26,27]]])

tensorB = np.array([[1,2],
                       [1,2],
                       [1,2]])

print tensorA.dot(tensorB)

它给出了以下答案:

[[[  6  12]
  [ 15  30]
  [ 24  48]]

 [[ 33  66]
  [ 42  84]
  [ 51 102]]

 [[ 60 120]
  [ 69 138]
  [ 78 156]]]

但是,当我在 C++ Eigen 中做同样的事情时:

Eigen::Tensor<float, 3> tensorA(3,3,3);
tensorA.setValues(1,2,3,
              4,5,6,
              7,8,9,

             10,11,12,
              13,14,15,
              16,17,18,

             19,20,21,
              22,23,24,
              25,26,27);

Eigen::Tensor<float, 2> tensorB(3,2);
tensorB.setValues(1,2,
                   1,2,
                   1,2);

// Compute the traditional matrix product
Eigen::array<Eigen::IndexPair<float>, 1> product_dims =  Eigen::IndexPair<float>(0, 1) ;
Eigen::Tensor<float, 3> AB = tensorA.contract(tensorB, product_dims);

我明白了:

D: 3 R: 3 C: 2
[[12.000     24.000     ]
[15.000     30.000     ]
[18.000     36.000     ]
]
R: 3 C: 2
[[39.000     78.000     ]
[42.000     84.000     ]
[45.000     90.000     ]
]
R: 3 C: 2
[[66.000     132.000     ]
[69.000     138.000     ]
[72.000     144.000     ]
]

为什么会这样。我想要一个相当于 numpy 给我的张量点积。它与c ++中的product_dims参数有关吗?还是涉及其他一些错误?基本上,它需要将深度分量乘以 3 倍。

【问题讨论】:

【参考方案1】:

我无法为您提供 c++ 代码,但我可以用 numpy 的术语来确定发生了什么:

In [1]: A=np.arange(1,28).reshape(3,3,3)
In [3]: A
Out[3]: 
array([[[ 1,  2,  3],
        [ 4,  5,  6],
        [ 7,  8,  9]],

       [[10, 11, 12],
        [13, 14, 15],
        [16, 17, 18]],

       [[19, 20, 21],
        [22, 23, 24],
        [25, 26, 27]]])
In [5]: B=np.repeat([[1,2]],3, axis=0)
In [6]: B
Out[6]: 
array([[1, 2],
       [1, 2],
       [1, 2]])

你的点 - 记住 A 的最后一个和 B 的倒数第二个:

In [7]: A.dot(B)
Out[7]: 
array([[[  6,  12],
        [ 15,  30],
        [ 24,  48]],

       [[ 33,  66],
        [ 42,  84],
        [ 51, 102]],

       [[ 60, 120],
        [ 69, 138],
        [ 78, 156]]])

使用einsum 索引,这很清楚(至少对我而言):

In [8]: np.einsum('ijk,kl',A,B)    # notice the k pair
Out[8]: 
array([[[  6,  12],
        [ 15,  30],
        [ 24,  48]],

       [[ 33,  66],
        [ 42,  84],
        [ 51, 102]],

       [[ 60, 120],
        [ 69, 138],
        [ 78, 156]]])

但如果我将einsum 更改为使用第二个到最后一个,我会得到你的 c++ 结果(我认为):

In [9]: np.einsum('ijk,jl',A,B)    # notice the j pair
Out[9]: 
array([[[ 12,  24],
        [ 15,  30],
        [ 18,  36]],

       [[ 39,  78],
        [ 42,  84],
        [ 45,  90]],

       [[ 66, 132],
        [ 69, 138],
        [ 72, 144]]])

【讨论】:

以上是关于特征收缩 vs Numpy Dot的主要内容,如果未能解决你的问题,请参考以下文章

用 numpy 计算 k 个最大特征值和相应特征向量的最快方法

在 python 中以 numpy.eig 和 scipy.eig 排序的特征值

Numpy库进阶教程

python numpy 特征值 特征向量 算的不对啊,求救!

线代&NumPy第八章 - 特征值和特征向量 | Eigenvalue and Eigenvector | 简述并提供代码

转:numpy.linalg.eig() 计算矩阵特征向量