当前位置: 首页 > 知识库问答 >
问题:

一般乘积的特征自型推导

宰父涵忍
2023-03-14

我有以下一段代码(对于稍大的代码片段,我深表歉意,这是我能够将问题简化为的最小示例):

#include <Eigen/Dense>
#include <complex>
#include <iostream>
#include <typeinfo>

// Dynamic Matrix over Scalar field
template <typename Scalar> 
using DynMat = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>;

// Dynamic column vector over Scalar field
template <typename Scalar>
using DynVect = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>;

// Returns the D x D Identity matrix over the field Derived::Scalar
// deduced from the expression Eigen::MatrixBase<Derived>& A
template<typename Derived>
DynMat<typename Derived::Scalar> Id(const Eigen::MatrixBase<Derived>& A, std::size_t D)
{   
    DynMat<typename Derived::Scalar> result =
            DynMat<typename Derived::Scalar>::Identity(D, D);

    return result;
}

int main()
{
    //using ScalarField = std::complex<double>; // same issue even if I use complex numbers
    using ScalarField = double; // we use doubles in this example

    // A double dynamic matrix (i.e. MatrixXd)
    DynMat<ScalarField> Foo; // used to deduce the type in Id<>()

    // A double dynamic column vector (i.e. VectorXd)
    DynVect<ScalarField> v(4);
    v << 1., 0. , 0. ,0.; // plug in some values into it

    // Make sure that Id(Foo, 4) correctly deduces the template parameters
    std::cout << "Id(Foo, 4) is indeed the 4 x 4 identiy matrix over the ScalarField of "
              << "typeid().name(): " << typeid(ScalarField).name() << std::endl;
    std::cout << Id(Foo, 4) << std::endl; // Indeed the 4 x 4 complex Identity matrix

    // Use auto type deduction for GenMatProduct, junk is displayed. Why?!
    std::cout << std::endl << "Use auto type deduction for GenMatProduct,\
                 sometimes junk is displayed. Why?!" << std::endl;
    auto autoresult = Id(Foo, 4) * v; // evaluated result must be identically equal to v
    for(int i=0; i<10; i++)
    {
            std::cout << autoresult.transpose(); // thought 1 0 0 0 is the result, but NO, junk
            std::cout << " has norm: " << autoresult.norm() << std::endl; // junk
    }

    // Use implicit cast to Dynamic Matrix, works fine
    std::cout << std::endl << "Use implicit cast to Dynamic Matrix, works fine" << std::endl;
    DynMat<ScalarField> castresult = Id(Foo, 4) * v; // evaluated result must be identically equal to v
    for(int i=0; i<10; i++)
    {
            std::cout << castresult.transpose(); // 1 0 0 0, works ok
            std::cout << " has norm: " << castresult.norm() << std::endl; // ok
    }
}

其主要思想是模板函数Id

我在OS X Yosemite上使用Eigen 3.2.2,并在g 4.9.1和苹果LLVM版本6.0(clang-600.0.54)(基于LLVM 3.5svn)中获得相同的奇怪行为

问题:

  • 我不明白在第一个for循环中发生了什么,为什么在我使用std::cout时,甚至在我使用norm方法时,产品都没有进行评估?我错过什么了吗?这里没有涉及别名,我真的对正在发生的事情感到困惑。我知道Eigen使用惰性计算,并在需要时计算表达式,但这里的情况似乎不是这样。这个问题对我来说非常重要,因为我有许多与Id相同的函数

这个问题经常发生,但并不总是如此。但是,如果你运行程序3-4次,你肯定会看到它。

我用来编译和运行它的命令是:

clang++ (g++) -std=c++11 -isystem ./eigen_3.2.2/ testeigen.cpp -otesteigen; ./testeigen

我在实际运行中得到的一个典型输出是:

Id(Foo, 4) is indeed the 4 x 4 identiy matrix over the ScalarField of typeid().name(): d
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

Use GenMatProduct, sometimes junk is displayed. Why?!
1 0 0 0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323            0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323            0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323            0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323            0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323            0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323            0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323            0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323            0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323            0 has norm: inf

Use implicit cast to Dynamic Matrix, works fine
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1

即使我使用ava()

  std::cout << autoresult.eval().transpose(); // thought 1 0 0 0 is the result, but NO, junk
  std::cout << " has norm: " << autoresult.eval().norm() << std::endl; // junk

我也有同样奇怪的行为。


共有2个答案

庄子平
2023-03-14

它可能有一个懒惰的求值类型,只能安全地求值一次。您可以通过以下方式捕获它:

auto autoresultmatrix = autoresult.eval()
卫博雅
2023-03-14

问题是Id()返回一个临时的,它通过引用存储在表示表达式Id(Foo,4)*v的对象中。因此,在自动语句之后,自动结果存储对死对象的引用。如果您不想要抽象表达式,而是实际结果,请不要使用auto或调用ava来强制执行计算:

auto autoresult = (Id(Foo, 4) * v).eval();

第三个选项是使Id()返回的对象可用于进一步计算:

auto id4 = Id(Foo,4);
auto autoresult = id4 * v;

但在这种情况下,只要您使用autoresult,产品就会被重新评估,以下内容将输出不同的结果:

cout << autoresult;
v.setRandom();
cout << autoresult;
 类似资料:
  •   ElementwiseProduct对每一个输入向量乘以一个给定的“权重”向量。换句话说,就是通过一个乘子对数据集的每一列进行缩放。这个转换可以表示为如下的形式:   下面是一个使用的实例。 import org.apache.spark.SparkContext._ import org.apache.spark.mllib.feature.ElementwiseProduct import

  • 我有一个多类分类问题。假设我有一个特征矩阵: 和标签: 我想尝试使用Keras沿每个特征行应用卷积核。假设nb\u filter=2,batch\u size=3。所以我希望卷积层的输入形状是(3,4),输出形状是(3,3)(因为它适用于AB、BC、CD)。 下面是我对Keras的尝试(v1.2.1,Theano后端): 形状: 输出: 当我尝试运行此代码时,我得到和异常: 我试图重塑y\U列车:

  • 我正在使用卷积自动编码器。我的autoenoder配置有一个带stride(2,2)或avg pooling和relu激活的卷积层和一个带stride(2,2)或avg Unmooling和relu激活的反卷积层。 我用MNIST数据集训练自动编码器。 当我在第一个卷积层(20个过滤器,过滤器大小为3)后查看特征图时,我得到了一些黑色特征图,而学习到的过滤器不是黑色的。如果更改过滤器数量或过滤器大

  • 我希望有一个类型特征,对于任何在使用前不需要内存初始化的类型返回true,并且其复制构造函数可以作为memcpy实现。 我想让它回到真实 < li >整数类型(char、short int、int、long int等) < li >浮点数类型(float,double) < li>il::array (il::array是我自己对std::array的实现)for T是int、double、il:

  • 问题内容: 所以, 问题 我对行乘法有问题。在SQL中,有一个函数可以计算一组行中某个字段的总和。我想得到乘法,即表 这将是作为一个结果。我正在使用 DOUBLE 数据类型来存储我的数据值。 我的方法 从学校数学知道,-可以用来创建所需的表达式,例如: -在这里您会看到此方法的弱点-由于何时未定义-我需要在计算整个表达式之前计算负号。该小提琴提供了示例数据和对此的查询。另一个缺点是,我们需要确定列

  • 模型是什幺? 每当需要取回、操纵或删除资料时,应始终藉由模型来完成。模型是一些类型资料与变更它们的方法的代表。 例如:你不会把 SQL 查询放在一个控制器,这些查询被放在模型里,且控制器会在呼叫模型后执行它们。 如此一来,如果你的资料库改变,你将只要变更后面作用的模型,而不需要变更你所有的控制器。 模型如何使用? 在 Fuel 里,模型就像任何其他的 类别 一样。它们做的也不比函式库多, 但模组前