[Eigen中文文档] 归约、访问者和广播
专栏总目录
本文目录
- 归约
- 范数计算
- 布尔归约
- 用户自定义的归约
- 访问者函数
- 局部归约
- 将局部归约与其他操作结合
- 广播
- 将广播与其他操作结合
英文原文(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()
方法返回 Frobenius
或 Hilbert-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时,该函数返回trueany()
:给定Matrix或Array至少有一个是true,函数返回truecount()
:返回给定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=[13216792]
则有,
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()=[431311]
最后,使用 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} [13216792]+[01010101]=[14226893]
运算符 -=
、+
和 -
也可以按列和行使用。在数组中,还可以使用运算符 *=
、/=
、*
和 /
来执行按元素乘法和按列或行进行除法,但这些运算符在矩阵上不能使用。如果要将矩阵 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=[−10218447−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()=[15053250]
minCoeff(&index)
:用于获取 m 中最接近 v 的列索引。
[Eigen中文文档] 归约、访问者和广播相关推荐
- [Eigen中文文档] 矩阵与向量运算
专栏总目录 本文目录 介绍 加法与减法 标量的标量乘法与除法 表达式模板 转置与共轭 (矩阵与矩阵)和(矩阵与向量)的乘积 点积和叉积 基本算术的简化运算 操作的有效性 英文原文(Matrix and ...
- [Eigen中文文档] 稀疏矩阵快速参考指南
文档总目录 本文目录 稀疏矩阵初始化 构造 重置大小/预分配内存空间 赋值 逐元素插入 批量插入 指定位置或随机插入 矩阵属性 算术运算 加减 标量积 稀疏矩阵乘积 转置/伴随 排列 组件级操作 其他 ...
- [Eigen中文文档] 按值将Eigen对象传递给函数
文档总目录 本文目录 按值传递和按引用传递 Eigen的处理 英文原文(Passing Eigen objects by value to functions) 按值传递和按引用传递 按值传递:传入函 ...
- [Eigen中文文档] 切片和索引
专栏总目录 本文目录 概述 基本的切片 编译时的大小和步长 倒序 索引序列 自定义索引列表 英文原文(Slicing and Indexing) 本文介绍了如何使用操作运算符operator()索引行 ...
- eigen之eigen中文文档
GitHub - growinguptogether/EigenDocInChinese: Eigen3.3.7 Doc中文版
- ASP.NET Core 中文文档 第三章 原理(3)静态文件处理
原文:Working with Static Files 作者:Rick Anderson 翻译:刘怡(AlexLEWIS) 校对:谢炀(kiler398).许登洋(Seay).孟帅洋(书缘) 静态文 ...
- PyTorch 1.4 中文文档校对活动正式启动 | ApacheCN
一如既往,PyTorch 1.4 中文文档校对活动启动了! 认领须知 请您勇敢地去翻译和改进翻译.虽然我们追求卓越,但我们并不要求您做到十全十美,因此请不要担心因为翻译上犯错--在大部分情况下,我们的 ...
- PyTorch 1.2 中文文档校对活动 | ApacheCN
整体进度:https://github.com/apachecn/pytorch-doc-zh/issues/422 贡献指南:https://github.com/apachecn/pytorch- ...
- socket.io 中文手册 socket.io 中文文档
socket.io 中文手册,socket.io 中文文档转载于:http://www.cnblogs.com/xiezhengcai/p/3956401.html 服务端 io.on('connec ...
最新文章
- In-Sat:今年全球VoIP用户将达5500万
- Shell中的常用操作
- Boost:reference wrapper参考包装的测试程序
- 力扣376. 摆动序列(JavaScript)
- Oracle 11g-R2 SQL Developer连接MSSQL2008
- kubernetes集群Pod详细信息为Failed create pod sandbox,缺失镜像google_containers/pause-amd64.3.0解决方法
- 石子合并,四边形不等式优化(Buy Candy,玲珑杯 Round#6 A lonlife 1066)
- 为什么Java的lambda或匿名内部类中用到的外部局部变量需要声明成final或是effectively final的?
- Python面试宝典(第十二章 企业真题实战)
- html里面的view怎么修改,asp.net mvc 3-在局部视图中修改MVC 3 ViewBag不会保留到_Layout.cshtml...
- 如果一个女人喜欢你,又不跟你在一起,而且只跟你很暧昧,那代表什么
- 针对list集合的操作,按照某一字段,对另一个字段进行归类
- 高等数学上核心概念:谈谈导数,微分,积分之间的关系(导数篇)
- 【图像处理】gamma校正通俗解释及python实现(替代matlab imadjust)
- PCIe系列第四讲、TLP的路由方式
- 网络基础之网络布线、数制转换和子网划分
- SQL Server AlwaysON从入门到进阶(3)——基础架构
- 【爱码物联】“颜值经济”当道,你选的化妆品能溯源么?
- Vue Admin Plus、Vue Shop Vite 官网演示地址文档
- USB充电式暖手宝芯片-DLTAP602SC-杰力科创
热门文章
- [组图]国外专家谈游戏制作
- 图的单源最短路径算法
- Facebook工程师告诉你,如何正确的阅读《算法导论》(CLRS)?
- 深入理解Linux 条件变量2:使用条件变量实现[生产-消费]框架
- Tech Talk 宣传 | 如何高效、极简构造无服务器 Web 应用
- Map集合、 HashMap集合、LinkedHashMap集合、Hashtable集合
- STM32怎样实现延时?
- 16组Sony索尼系列相机Slog2和Slog3常用Vlog电影LTUS调色预设 Slog2 Slog3视频灰片调色预设
- java 读取csv文件乱码_java读取csv文件乱码怎么解决
- svn绿色符号消失的解决办法