专栏总目录

本文目录

  • 归约
  • 范数计算
  • 布尔归约
  • 用户自定义的归约
  • 访问者函数
  • 局部归约
  • 将局部归约与其他操作结合
  • 广播
  • 将广播与其他操作结合

英文原文(Reductions, visitors and broadcasting)

本文介绍了Eigen的归约、访问者和广播,以及它们如何与矩阵和数组一起使用。

归约

在Eigen,归约是把一个矩阵和数组变成一个标量的方法。一个经常用到的归约方法是sum(),它返回给定矩阵或数组内所有系数的总和。

// 代码索引 3-7-1-1
#include <iostream>
#include <Eigen/Dense>using namespace std;
int main()
{Eigen::Matrix2d mat;mat << 1, 2,3, 4;cout << "Here is mat.sum():       " << mat.sum()       << endl;cout << "Here is mat.prod():      " << mat.prod()      << endl;cout << "Here is mat.mean():      " << mat.mean()      << endl;cout << "Here is mat.minCoeff():  " << mat.minCoeff()  << endl;cout << "Here is mat.maxCoeff():  " << mat.maxCoeff()  << endl;cout << "Here is mat.trace():     " << mat.trace()     << endl;
}

输出:

Here is mat.sum():       10
Here is mat.prod():      24
Here is mat.mean():      2.5
Here is mat.minCoeff():  1
Here is mat.maxCoeff():  4
Here is mat.trace():     5

矩阵的迹可以通过trace()来得到,也可以通过a.diagonal().sum()得到。

范数计算

向量的平方范数可以通过 squaredNorm() 来计算。它等于向量本身的点积,等于其系数的绝对值平方和。

Eigen还提供了 norm() 方法,该方法返回squaredNorm()的平方根。

这些方法也可以对矩阵进行操作,在这种情况下,n×p 矩阵被视为大小为(n*p)的向量,因此例如 norm() 方法返回 FrobeniusHilbert-Schmidt 范数,即 L 2 L_2 L2​ 范数。我们避免谈论 Euclidean 范数,因为这可能意味着不同的事情。

如果想要其他系数的范数,可以使用lpNorm<p>()方法。如果你想要 ∞ \infty ∞ 范数,模板参数 p 可以取特殊值 Infinity,这将返回系数绝对值的最大值。如下:

// 代码索引 3-7-2-1
#include <Eigen/Dense>
#include <iostream>int main()
{Eigen::VectorXf v(2);Eigen::MatrixXf m(2,2), n(2,2);v << -1,2;m << 1,-2,-3,4;std::cout << "v.squaredNorm() = " << v.squaredNorm() << std::endl;std::cout << "v.norm() = " << v.norm() << std::endl;std::cout << "v.lpNorm<1>() = " << v.lpNorm<1>() << std::endl;std::cout << "v.lpNorm<Infinity>() = " << v.lpNorm<Eigen::Infinity>() << std::endl;std::cout << std::endl;std::cout << "m.squaredNorm() = " << m.squaredNorm() << std::endl;std::cout << "m.norm() = " << m.norm() << std::endl;std::cout << "m.lpNorm<1>() = " << m.lpNorm<1>() << std::endl;std::cout << "m.lpNorm<Infinity>() = " << m.lpNorm<Eigen::Infinity>() << std::endl;
}

输出:

v.squaredNorm() = 5
v.norm() = 2.23607
v.lpNorm<1>() = 3
v.lpNorm<Infinity>() = 2m.squaredNorm() = 30
m.norm() = 5.47723
m.lpNorm<1>() = 10
m.lpNorm<Infinity>() = 4

1-范数和 ∞ \infty ∞-范数矩阵运算符范数可以很容易地计算如下:

// 代码索引 3-7-2-2
#include <Eigen/Dense>
#include <iostream>int main()
{Eigen::MatrixXf m(2,2);m << 1,-2,-3,4;std::cout << "1-norm(m)     = " <是他的::< m.cwiseAbs().colwise().sum().maxCoeff()<< " == "             << m.colwise().lpNorm<1>().maxCoeff() << std::endl;std::cout << "infty-norm(m) = " << m.cwiseAbs().rowwise().sum().maxCoeff()<< " == "             << m.rowwise().lpNorm<1>().maxCoeff() << std::endl;
}

输出:

1-norm(m)     = 6 == 6
infty-norm(m) = 7 == 7

有关这些表达式的语法的更多解释,请参见下文。

布尔归约

下列是关于布尔值的归约操作:

  • all():给定Matrix或Array所有的系数都为true时,该函数返回true
  • any():给定Matrix或Array至少有一个是true,函数返回true
  • count():返回给定Matrix或Array中true的个数

这些操作通常与相等操作符、Array提供的按系数比较操作等一起使用。例如,array>0 是一个数组,它与array大小相同且每一个元素都是布尔值,如果array的某个元素满足大于零,则数组array>0对应位置为true,否则为false。因此,(array>0).all() 检验是否array的所有的系数都是大于0的。

示例如下:

// 代码索引 3-7-3-1
#include <Eigen/Dense>
#include <iostream>int main()
{Eigen::ArrayXXf a(2,2);a << 1,2,3,4;std::cout << "(a > 0).all()   = " << (a > 0).all() << std::endl;std::cout << "(a > 0).any()   = " << (a > 0).any() << std::endl;std::cout << "(a > 0).count() = " << (a > 0).count() << std::endl;std::cout << std::endl;std::cout << "(a > 2).all()   = " << (a > 2).all() << std::endl;std::cout << "(a > 2).any()   = " << (a > 2).any() << std::endl;std::cout << "(a > 2).count() = " << (a > 2).count() << std::endl;
}

输出如下:

(a > 0).all()   = 1
(a > 0).any()   = 1
(a > 0).count() = 4(a > 2).all()   = 0
(a > 2).any()   = 1
(a > 2).count() = 2

用户自定义的归约

这里官方没有给出解释,建议参考函数 DenseBase::redux()

访问者函数

当想要获取元素在 Matrix 或 Array 中的位置时,访问者函数很有用。例如 maxCoeff(&x,&y) 和 minCoeff(&x,&y),它们可用于查找 Matrix 或 Array 中最大或最小元素的位置,位置通过传入要存储行和列位置变量的指针返回。这些变量应该是 Index 类型,如下所示:

// 代码索引 3-7-4-1
#include <iostream>
#include <Eigen/Dense>int main()
{Eigen::MatrixXf m(2,2);m << 1, 2,3, 4;//get location of maximumEigen::Index maxRow, maxCol;float max = m.maxCoeff(&maxRow, &maxCol);//get location of minimumEigen::Index minRow, minCol;float min = m.minCoeff(&minRow, &minCol);std::cout << "Max: " << max <<  ", at: " <<maxRow << "," << maxCol << std::endl;std:: cout << "Min: " << min << ", at: " <<minRow << "," << minCol << std::endl;
}

输出为:

Max: 4, at: 1,1
Min: 1, at: 0,0

这两个函数还会通过函数返回值返回最小或最大元素的值。

局部归约

局部归约是可以对 Matrix 或 Array 按列或行进行操作的归约,对每一列或行应用归约操作并返回具有相应值的列或行向量。使用colwise()或rowwise()方法进行部分归约。

如下示例,获取给定矩阵中每一列中元素的最大值,并将结果存储在行向量中:

// 代码索引 3-7-5-1
#include <iostream>
#include <Eigen/Dense>using namespace std;
int main()
{Eigen::MatrixXf mat(2,4);mat << 1, 2, 6, 9,3, 1, 7, 2;std::cout << "Column's maximum: " << std::endl<< mat.colwise().maxCoeff() << std::endl;
}

输出:

Column's maximum:
3 2 7 9

类似的,可得到每一行中元素的最大值,如下:

// 代码索引 3-7-5-2
#include <iostream>
#include <Eigen/Dense>using namespace std;
int main()
{Eigen::MatrixXf mat(2,4);mat << 1, 2, 6, 9,3, 1, 7, 2;std::cout << "Row's maximum: " << std::endl<< mat.rowwise().maxCoeff() << std::endl;
}

请注意,按列操作返回行向量,而按行操作返回列向量。

将局部归约与其他操作结合

也可以将局部归约的结果做进一步处理。

如下示例,查找矩阵中元素总和最大的列:

// 代码索引 3-7-5-3
#include <iostream>
#include <Eigen/Dense>int main()
{Eigen::MatrixXf mat(2,4);mat << 1, 2, 6, 9,3, 1, 7, 2;Eigen::Index   maxIndex;float maxNorm = mat.colwise().sum().maxCoeff(&maxIndex);std::cout << "Maximum sum at position " << maxIndex << std::endl;std::cout << "The corresponding vector is: " << std::endl;std::cout << mat.col( maxIndex ) << std::endl;std::cout << "And its sum is is: " << maxNorm << std::endl;
}

输出如下:

Maximum sum at position 2
The corresponding vector is:
6
7
And its sum is is: 13

上面示例通过 colwise() 对每一列进行 sum() 归约,得到大小为 1x4 的新矩阵,如:
m = [ 1 2 6 9 3 1 7 2 ] m = \begin{bmatrix} 1 & 2 & 6 & 9 \\ 3 & 1 & 7 & 2 \\ \end{bmatrix} m=[13​21​67​92​]
则有,
m . c o l w i s e ( ) . s u m ( ) = [ 4 3 13 11 ] m.colwise().sum() = \begin{bmatrix} 4 & 3 & 13 & 11 \end{bmatrix} m.colwise().sum()=[4​3​13​11​]
最后,使用 maxCoeff() 方法得到最大总和的列索引。

广播

广播的概念类似于局部归约,不同之处在于广播构造了一个表达式,通过在一个方向上复制向量(列或行)将其解释为矩阵。

如下示例,将某个列向量添加到矩阵中的每一列:

// 代码索引 3-7-6-1
#include <iostream>
#include <Eigen/Dense>using namespace std;
int main()
{Eigen::MatrixXf mat(2,4);Eigen::VectorXf v(2);mat << 1, 2, 6, 9,3, 1, 7, 2;v << 0,1;//add v to each column of mmat.colwise() += v;std::cout << "Broadcasting result: " << std::endl;std::cout << mat << std::endl;
}

输出:

Broadcasting result:
1 2 6 9
4 2 8 3

用两种等价的方式解释语句 mat.colwise() += v。可以解释为它将向量 v 添加到矩阵的每一列,或者,也可以解释为将向量 v 重复四次形成一个 4*2 的矩阵,然后将其加到 mat,如下:
[ 1 2 6 9 3 1 7 2 ] + [ 0 0 0 0 1 1 1 1 ] = [ 1 2 6 9 4 2 8 3 ] \begin{bmatrix} 1 & 2 & 6 & 9 \\ 3 & 1 & 7 & 2 \\ \end{bmatrix} + \begin{bmatrix} 0 & 0 & 0 & 0 \\ 1 & 1 & 1 & 1 \\ \end{bmatrix} = \begin{bmatrix} 1 & 2 & 6 & 9 \\ 4 & 2 & 8 & 3 \\ \end{bmatrix} [13​21​67​92​]+[01​01​01​01​]=[14​22​68​93​]
运算符 -=+- 也可以按列和行使用。在数组中,还可以使用运算符 *=/=*/ 来执行按元素乘法和按列或行进行除法,但这些运算符在矩阵上不能使用。如果要将矩阵 mat 的第 0 列与 v(0) 相乘,第 1 列与 v(1) 相乘,依此类推,可以使用 mat = mat * v.asDiagonal()

需要指出的是,要按列或行相加的向量必须是 Vector 类型,不能是 Matrix,否则编译时会报错。这也意味着在使用 Matrix 操作时,广播操作只能应用于 Vector 类型的对象。这同样适用于 Array 类,其中 VectorXf 的等效项是 ArrayXf。同样不应该在同一个表达式中混合使用数组和矩阵。

如下示例,按行执行相同的操作:

// 代码索引 3-7-6-2
#include <iostream>
#include <Eigen/Dense>using namespace std;
int main()
{Eigen::MatrixXf mat(2,4);Eigen::VectorXf v(4);mat << 1, 2, 6, 9,3, 1, 7, 2;v << 0,1,2,3;//add v to each row of mmat.rowwise() += v.transpose();std::cout << "Broadcasting result: " << std::endl;std::cout << mat << std::endl;
}

输出:

Broadcasting result: 1  3  8 123  2  9  5

将广播与其他操作结合

广播还可以与其他操作相结合,例如矩阵或数组操作、归约和局部归约。

前面已经介绍了广播、归约和局部归约,现在可以深入研究一个更高级的示例,即在矩阵 m 的列中找到向量 v 的最近邻向量。本例将使用欧几里得距离,使用名为 squaredNorm() 的局部归约计算二次欧几里得距离:

// 代码索引 3-7-7-1
#include <iostream>
#include <Eigen/Dense>int main()
{Eigen::MatrixXf m(2,4);Eigen::VectorXf v(2);m << 1, 23, 6, 9,3, 11, 7, 2;v << 2,3;Eigen::Index index;// find nearest neighbour(m.colwise() - v).colwise().squaredNorm().minCoeff(&index);std::cout << "Nearest neighbour is column " << index << ":" << std::endl;std::cout << m.col(index) << std::endl;
}

输出:

Nearest neighbour is column 0:
1
3

其中,语句 (m.colwise() - v).colwise().squaredNorm().minCoeff(&index); 解释如下:

  • m.colwise() - v: 是一个广播操作,从 m 中的每一列中减去 v。此操作的结果是一个新矩阵,其大小与矩阵 m 相同,如下:

m . c o l w i s e − v = [ − 1 21 4 7 0 8 4 − 1 ] m.colwise - v = \begin{bmatrix} -1 & 21 & 4 & 7 \\ 0 & 8 & 4 & -1 \\ \end{bmatrix} m.colwise−v=[−10​218​44​7−1​]

  • (m.colwise() - v).colwise().squaredNorm():是一个局部归约操作,按列计算平方范数。此操作的结果是一个行向量,其中每个元素是 m 和 v 中每列之间的二次欧几里得距离,如下:

( m . c o l w i s e ( ) − v ) . c o l w i s e ( ) . s q u a r e d N o r m ( ) = [ 1 505 32 50 ] (m.colwise() - v).colwise().squaredNorm() = \begin{bmatrix} 1 & 505 & 32 & 50 \end{bmatrix} (m.colwise()−v).colwise().squaredNorm()=[1​505​32​50​]

  • minCoeff(&index):用于获取 m 中最接近 v 的列索引。

[Eigen中文文档] 归约、访问者和广播相关推荐

  1. [Eigen中文文档] 矩阵与向量运算

    专栏总目录 本文目录 介绍 加法与减法 标量的标量乘法与除法 表达式模板 转置与共轭 (矩阵与矩阵)和(矩阵与向量)的乘积 点积和叉积 基本算术的简化运算 操作的有效性 英文原文(Matrix and ...

  2. [Eigen中文文档] 稀疏矩阵快速参考指南

    文档总目录 本文目录 稀疏矩阵初始化 构造 重置大小/预分配内存空间 赋值 逐元素插入 批量插入 指定位置或随机插入 矩阵属性 算术运算 加减 标量积 稀疏矩阵乘积 转置/伴随 排列 组件级操作 其他 ...

  3. [Eigen中文文档] 按值将Eigen对象传递给函数

    文档总目录 本文目录 按值传递和按引用传递 Eigen的处理 英文原文(Passing Eigen objects by value to functions) 按值传递和按引用传递 按值传递:传入函 ...

  4. [Eigen中文文档] 切片和索引

    专栏总目录 本文目录 概述 基本的切片 编译时的大小和步长 倒序 索引序列 自定义索引列表 英文原文(Slicing and Indexing) 本文介绍了如何使用操作运算符operator()索引行 ...

  5. eigen之eigen中文文档

    GitHub - growinguptogether/EigenDocInChinese: Eigen3.3.7 Doc中文版

  6. ASP.NET Core 中文文档 第三章 原理(3)静态文件处理

    原文:Working with Static Files 作者:Rick Anderson 翻译:刘怡(AlexLEWIS) 校对:谢炀(kiler398).许登洋(Seay).孟帅洋(书缘) 静态文 ...

  7. PyTorch 1.4 中文文档校对活动正式启动 | ApacheCN

    一如既往,PyTorch 1.4 中文文档校对活动启动了! 认领须知 请您勇敢地去翻译和改进翻译.虽然我们追求卓越,但我们并不要求您做到十全十美,因此请不要担心因为翻译上犯错--在大部分情况下,我们的 ...

  8. PyTorch 1.2 中文文档校对活动 | ApacheCN

    整体进度:https://github.com/apachecn/pytorch-doc-zh/issues/422 贡献指南:https://github.com/apachecn/pytorch- ...

  9. socket.io 中文手册 socket.io 中文文档

    socket.io 中文手册,socket.io 中文文档转载于:http://www.cnblogs.com/xiezhengcai/p/3956401.html 服务端 io.on('connec ...

最新文章

  1. In-Sat:今年全球VoIP用户将达5500万
  2. Shell中的常用操作
  3. Boost:reference wrapper参考包装的测试程序
  4. 力扣376. 摆动序列(JavaScript)
  5. Oracle 11g-R2 SQL Developer连接MSSQL2008
  6. kubernetes集群Pod详细信息为Failed create pod sandbox,缺失镜像google_containers/pause-amd64.3.0解决方法
  7. 石子合并,四边形不等式优化(Buy Candy,玲珑杯 Round#6 A lonlife 1066)
  8. 为什么Java的lambda或匿名内部类中用到的外部局部变量需要声明成final或是effectively final的?
  9. Python面试宝典(第十二章 企业真题实战)
  10. html里面的view怎么修改,asp.net mvc 3-在局部视图中修改MVC 3 ViewBag不会保留到_Layout.cshtml...
  11. 如果一个女人喜欢你,又不跟你在一起,而且只跟你很暧昧,那代表什么
  12. 针对list集合的操作,按照某一字段,对另一个字段进行归类
  13. 高等数学上核心概念:谈谈导数,微分,积分之间的关系(导数篇)
  14. 【图像处理】gamma校正通俗解释及python实现(替代matlab imadjust)
  15. PCIe系列第四讲、TLP的路由方式
  16. 网络基础之网络布线、数制转换和子网划分
  17. SQL Server AlwaysON从入门到进阶(3)——基础架构
  18. 【爱码物联】“颜值经济”当道,你选的化妆品能溯源么?
  19. Vue Admin Plus、Vue Shop Vite 官网演示地址文档
  20. USB充电式暖手宝芯片-DLTAP602SC-杰力科创

热门文章

  1. [组图]国外专家谈游戏制作
  2. 图的单源最短路径算法
  3. Facebook工程师告诉你,如何正确的阅读《算法导论》(CLRS)?
  4. 深入理解Linux 条件变量2:使用条件变量实现[生产-消费]框架
  5. Tech Talk 宣传 | 如何高效、极简构造无服务器 Web 应用
  6. Map集合、 HashMap集合、LinkedHashMap集合、Hashtable集合
  7. STM32怎样实现延时?
  8. 16组Sony索尼系列相机Slog2和Slog3常用Vlog电影LTUS调色预设 Slog2 Slog3视频灰片调色预设
  9. java 读取csv文件乱码_java读取csv文件乱码怎么解决
  10. svn绿色符号消失的解决办法