Eigen中Tensor的使用技巧

目录:

    • 使用Eigen的Tensor缘由
    • Tensor的矩阵乘法操作
    • Tensor的reshape操作
    • Tensor的堆叠(stack)操作
    • Tensor的find(where)操作

使用Eigen的Tensor缘由

之所以使用Eigen的Tensor,主要是因为Tensorflow中的一个C++项目中,需要对graph中得到的Tensor进行数据后处理。而tensorflow的C++API中用到了Eigen这个矩阵运算库中的Tensor,所做了些笔记。该笔记主要参考Eigen-unsupport这个官方的文档(英文),并以此为基础记录一些与numpy对应的函数与技巧。

中文方面可以参考以下三篇文章:
Eigen Tensor详解一
Eigen Tensor详解二
Eigen Tensor详解三

Tensor的矩阵乘法操作

Eigen中的Tensor中重载了*并用于实现点对点相乘和与标量相乘。关于点对点相乘,需要注意的是两个tensor的shape必须相同才能相乘,如果需要像numpy那样实现大小矩阵相乘(广播机制),需要自己设置广播,如下:

#include 
Eigen::Tensor a(3, 2);
Eigen::Tensor b(1, 2);
a.setConstant(2.0);
b.setConstant(3.0);
Eigen::array bcast = { 3, 1 };//第一维复制3倍
auto ab = a*b.broadcast(bcast);
cout<

如果是要实现Tensor的内积,则需要使用tensor的contract函数,可以实现高维的矩阵内积,如下:

Eigen::Tensor a(2, 3);
a.setValues({{1, 2, 3}, {6, 5, 4}});
Eigen::Tensor b(3, 2);
b.setValues({{1, 2}, {4, 5}, {5, 6}});
Eigen::array, 1> product_dims = { Eigen::IndexPair(1, 0) };
Eigen::Tensor AB = a.contract(b, product_dims);
cout<

Tensor的reshape操作

Tensor中的reshape靠TensorMap这种数据类型实现。

float nums[12] = { 0, 100, 200 , 300, 400, 500,600, 700, 800,900, 1000, 1100 };
Eigen::TensorMap> a(nums, 4, 3);
Eigen::TensorMap> b(a.data(), 2, 6);
----------------------
a
   0  100  200
 300  400  500
 600  700  800
 900 1000 1100
b
   0  100  200  300  400  500
 600  700  800  900 1000 1100

Tensor的堆叠(stack)操作

Tensor的堆叠,如两个(2,2)的tensor堆叠为(2,2,2),也可以实现拼接(4,2),(2,4)。

Eigen::Tensor a(2, 2);
Eigen::Tensor b(2, 2);
a.setConstant(1,0);
b.setConstant(2.0);
auto ab = a.concatenate(b,0);   //(4,2)
auto ab1 = a.concatenate(b,1);  //(2,4)
Eigen::DSizes three_dim(3,2,1);
Eigen::Tensor ab2 = a.reshape(three_dim).concatenate(b.reshape(three_dim), 2)  //(2,2,2)

Tensor的find(where)操作

Tensor中没有matlab中的find或者python中numpy里的where,用于寻找满足条件的元素的下标。这里用到的思路是首先通过比较(><的符号Eigen已经重载),考虑到tensor的内存是连续存储的,通过遍历每个元素,计算满足的元素的下标。由于下面的代码中已经设置了Tensor为行优先存储,下标计算如下所示。

class getthree_index
{
public:
	vector* fir_dim;
	vector* sec_dim;
	vector* thi_dim;
	int fir, sec, thi;
	int idx = 0;

	getthree_index(vector* f, vector* s, vector* t, int fn, int sn, int tn)
	{
		fir_dim = f; sec_dim = s; thi_dim = t; fir = fn; sec = sn; thi = tn;
	};
	void operator()(bool i);
};

float nums[12] = { 0, 100, 200 , 300, 400, 500,600, 700, 800,900, 1000, 1100 };
Eigen::TensorMap> a(nums, 2, 3, 2);
auto threshold = a.constant(400);
Eigen::Tensor res = a>threshold.eval();
vector fir_dim;
vector sec_dim;
vector thi_dim;
auto shape = a.dimensions();
for_each(res.data(), res.data() + res.size(), getthree_index(&fir_dim, &sec_dim, &thi_dim, 
			int(shape[0]), int(shape[1]), int(shape[2])));

暂时这么多,后面再来补充。

你可能感兴趣的:(Tensorflow)