TensorFlow - 使用Eigen进行矩阵计算

TensorFlow - 使用Eigen进行矩阵计算

flyfish

假设不使用Eigen,是怎样的方式

首先include一些头文件

#include <utility>
#include <vector>
#include <cmath>
#include <limits>
#include <random>
#include "boost\align\aligned_allocator.hpp"
typedef std::vector<double_t, boost::alignment::aligned_allocator<double_t, 128>> Tensor1D;`这里写代码片`
typedef std::vector<Tensor1D> Tensor2D;

//按照128位进行对齐
//根据硬件平台double_t是double 还是long double
//double_t 在corecrt_math.h头文件里

SE或者AltiVec指令集,向量化必须要求向量是以16字节即128bit对齐的方式分配内存空间

声明函数

    void Randn(Tensor2D& t);//
    void InitData(Tensor2D& t, int row, int col);
    void Concatenate(Tensor2D& result, Tensor2D& a, Tensor2D& b);//列相等 两个矩阵的.连结
    void MatirxDot(Tensor2D& result, Tensor2D& a, Tensor2D& b); //矩阵乘法
    void MatirxAddBias(Tensor2D& result, Tensor2D& a, Tensor2D& b);//矩阵+1维偏置

    void ElementWise(Tensor2D& result, Tensor2D& a, Tensor2D& b);//element-wise乘积

实现函数

void Randn(Tensor2D& t)
{
    std::random_device rd;  //Will be used to obtain a seed for the random number engine
    std::mt19937 gen(rd());
    std::normal_distribution<double> dis(0.0f, 1.0f);//使用正太分布生成数据
    for (auto& v : t)
    {
        for (auto& i = v.begin(); i != v.end(); ++i)
        {
            (*i) = dis(gen);
        }
    }
}

void InitData(Tensor2D& t, int row, int col)
{
    t.resize(row);//行大小
    for (int j = 0; j < row; ++j)
        t[j].resize(col);//列大小

    Randn(t);
}

void Concatenate(Tensor2D& result, Tensor2D& a, Tensor2D& b)
{
    result.insert(result.end(), a.begin(), a.end());
    result.insert(result.end(), b.begin(), b.end());
}

void MatirxDot(Tensor2D& result, Tensor2D& a, Tensor2D& b)
{
    //第一个矩阵第一行的每个数字,各自乘以第二个矩阵第一列对应位置的数字,然后将乘积相加
    //只有在第一个矩阵的列数(column)和第二个矩阵的行数(row)相同时才有意义
    //举例    
    //wf 5行8列
    //cancate 8行 10列 第一个矩阵的列数(column)和第二个矩阵的行数(row
    // 
    //结果是a的行数,b的列数
    int row = a.size();
    int col = b.size();

     //假设不为空
    Tensor2D r(row, Tensor1D(col, 0));

    //a[m][x]
    //b[x][n]
    int m= row;
    int n=a[0].size();  
    int x = col;;
    for (int i = 0; i<m; i++)   
        for (int j = 0; j<n; j++)  
        {

            for (int k = 0; k<x; k++)  //k运行3次
                r[i][j] =r[i][j] + a[i][k] * b[k][j];  //a的第i行与b的第j列相乘
        }   

    result.insert(result.end(), r.begin(), r.end());
}

void MatirxAddBias(Tensor2D& result, Tensor2D& matrix, Tensor2D& bias)
{
    //行数相等,列不同的情况 
    //import numpy as np
    //  A = np.array([[1, 1, 2], [3, 4, 5]])
    //  X = np.array([[5], [3]])

    //  print(A.shape)
    //  print(X.shape)
    //  print(A + X)

    //  (2, 3)
    //  (2, 1)
    //  [[6 6 7]
    //  [6 7 8]]

    //bias 默认情况下只有一列



    int n = 0;
    for (auto& v : matrix)
    {

        for (size_t i=0;i<v.size(); i++)
        {
            v[i] = v[i] + bias[n][0];

        }
        n++;

    }

    result.insert(result.end(), matrix.begin(), matrix.end());

}

void ElementWise(Tensor2D& result, Tensor2D& a, Tensor2D& b)
{
    //a==b 还需要处理a和b的大小



    int m = a.size();
    int n = a[0].size();
    for (int i=0;i<m;i++)
        for (int j = 0; j < n; j++)
        {
            result[i][j] = a[i][j] * b[i][j];
        }


}

数学函数例如

void tanh_forward(Tensor2D &y,const Tensor2D &x)  {

            for (auto& i : x)
            {
                Tensor1D y1;
                tanh_forward(y1, i);
                y.push_back(y1);
            }
        }
        void tanh_forward(Tensor1D &y,const Tensor1D &x) 
        {
            for (size_t j = 0; j < x.size(); j++) 
            {
                y.push_back(std::tanh(x[j]));
            }
        }


        void tanh_backward(const Tensor1D &x,const Tensor1D &y,Tensor1D &dx,const Tensor1D &dy)  
        {
            for (size_t j = 0; j < x.size(); j++) {
                // dx = dy * (gradient of tanh)
                dx[j] = dy[j] * (double(1) - std::pow(y[j], 2));


            }
        }

        void sigmond_forward(Tensor2D &y,const Tensor2D &x )  
        { //y是返回值
            for (auto& i : x)
            {
                Tensor1D y1;
                sigmond_forward(y1, i);
                y.push_back(y1);
            }
        }
        void sigmond_forward(Tensor1D &y,const Tensor1D &x) 
        {
            for (size_t j = 0; j < x.size(); j++) 
            {
                y.push_back(float_t(1) / (float_t(1) + std::exp(-x[j])));
            }
        }

        void sigmond_backward(const Tensor1D &x,const Tensor1D &y,Tensor1D &dx,const Tensor1D &dy)  {
            for (size_t j = 0; j < x.size(); j++) {
                // dx = dy * (gradient of sigmoid)
                dx[j] = dy[j] * y[j] * (float_t(1) - y[j]);
            }
        }

使用方法

    int row = 3;
    int col = 4;
    Tensor2D test(row, Tensor1D(col, 0));//初始3行4列数据 ,数值全部为0

Tensor2D    xt;//(3, 10)
    Tensor2D    a_prev;//(5, 10)
    Tensor2D    c_prev;//(5, 10)
    Tensor2D    Wf;//(5, 5 + 3)
    Tensor2D    bf;//(5, 1)
    Tensor2D    Wi;//(5, 5 + 3)
    Tensor2D    bi;//(5, 1)
    Tensor2D    Wo;//(5, 5 + 3)
    Tensor2D    bo;//(5, 1)
    Tensor2D    Wc;//(5, 5 + 3)
    Tensor2D    bc;//(5, 1)
    Tensor2D    Wy;//(2, 5)
    Tensor2D    by;//(2, 1)

    //Concatenate a_prev and xt

    InitData(xt, 3, 10);
    InitData(a_prev, 5, 10);
    InitData(c_prev, 5, 10);
    InitData(Wf, 5, 5 + 3);
    InitData(bf, 5, 1);
    InitData(Wi, 5, 5 + 3);
    InitData(bi, 5, 1);
    InitData(Wo, 5, 5 + 3);
    InitData(bo, 5, 1);
    InitData(Wc, 5, 5 + 3);
    InitData(bc, 5, 1);
    InitData(Wy, 2, 5);
    InitData(by, 2, 1);

    Tensor2D concate;
    Concatenate(concate, a_prev, xt);

    //
    Tensor2D m11;//5行 8列
    MatirxDot(m11, Wf, concate);


    Tensor2D m21;//5行 8列
    MatirxAddBias(m21, m11, bf);


    Tensor2D  ft;//5行 8列
    sigmond_forward(ft, m21);


    //
    Tensor2D m12;//5行 8列
    MatirxDot(m12, Wi, concate);


    Tensor2D m22;//5行 8列
    MatirxAddBias(m22, m12, bi);


    Tensor2D  it;//5行 8列
    sigmond_forward(it, m22);

    //
    Tensor2D m13;//5行 8列
    MatirxDot(m13, Wc, concate);


    Tensor2D m23;//5行 8列
    MatirxAddBias(m23, m13, bc);


    Tensor2D  cct;//5行 8列
    tanh_forward(cct,m23);

使用vs2017 C++17的时候
在eigen文件中增加,C++17有些stl函数是不推荐使用的

//error C4996: 'std::unary_negate<_Fn>': 
//warning STL4008: std::not1(), std::not2(), std::unary_negate, and std::binary_negate are deprecated in C++17.
//They are superseded by std::not_fn(). You can define _SILENCE_CXX17_NEGATORS_DEPRECATION_WARNING or 
//_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.

 #if defined(_MSC_VER)
 #  pragma warning(push)
#  pragma warning(disable: 4996) // error C4996:  std::not1(), std::not2(), std::unary_negate, and std::binary_negate are deprecated in C++17
 #endif

如果使用Eigen,转换函数是这样的

void std_vector2eigen_matrix(Eigen::MatrixXd& r, Tensor2D& a)
{

    for (size_t i = 0; i < a.size(); i++)
        r.row(i) = Eigen::VectorXd::Map(&a[i][0], a[i].size());
}

使用转换函数

    Tensor2D test1;
    InitData(test1, 3, 4);
    Eigen::MatrixXd r(3,4);
    std_vector2eigen_matrix(r, test1);

下面是使用Eigen

#include "stdafx.h"
#include <iostream>
#include <vector>
#include "Eigen\Dense"

int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<float> v{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };

    //同样是3行4列
    Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> m1(v.data(), 3, 4);

    std::cout << "行优先" << '\n' << m1 << std::endl;
    Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>> m2(v.data(), 3, 4);
    std::cout << "列优先" << '\n' << m2 << std::endl;


    Eigen::MatrixXd matrixXd1(3, 3);

    matrixXd1 << 1, 2, 3,
        4, 5, 6,
        7, 8, 9;


    std::cout << "原始矩阵" << '\n' << matrixXd1 << '\n' << std::endl;
    std::cout << " 转置矩阵" << '\n' << matrixXd1.transpose() << '\n' << std::endl;
    std::cout << "共轭矩阵 Hermite阵" << '\n' << matrixXd1.conjugate() << '\n' << std::endl;
    std::cout << "伴随矩阵" << '\n' << matrixXd1.adjoint() << '\n' << std::endl;
    std::cout << "矩阵的行列式 " << '\n' << matrixXd1.determinant() << '\n' << std::endl;
    std::cout << "矩阵的迹" << '\n' << matrixXd1.trace() << '\n' << std::endl;
    std::cout << " 逆矩阵" << '\n' << matrixXd1.inverse() << '\n' << std::endl;


    system("pause");
    return 0;
}

行优先
1 2 3 4
5 6 7 8
9 10 11 12
列优先
1 4 7 10
2 5 8 11
3 6 9 12
原始矩阵
1 2 3
4 5 6
7 8 9

转置矩阵
1 4 7
2 5 8
3 6 9

共轭矩阵 Hermite阵
1 2 3
4 5 6
7 8 9

伴随矩阵
1 4 7
2 5 8
3 6 9

矩阵的行列式
6.66134e-016

矩阵的迹
15

逆矩阵
- 4.5036e+015 9.0072e+015 - 4.5036e+015
9.0072e+015 - 1.80144e+016 9.0072e+015
- 4.5036e+015 9.0072e+015 - 4.5036e+015

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西笑生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值