2017-05-02 64 views
0

我在執行矩陣乘法時似乎遇到了精度損失,並且想知道如何防止這種情況。例如,假設壯舉和β是適當的尺寸,犰狳:矩陣乘法損失的精度

Y = feat*beta.rows(0,N); 

我一起工作的數字是相當小的值,多數數字是小於1E-3所以有可能是什麼我想實現是不可能的。我還應該注意到這是一個調用C++函數的MATLAB函數,因此涉及到MEX編譯器。當他們到達時,我確實檢查了mex函數中的數字,他們是正確的,只有在上面的這一行後,我纔得到令人難以置信的錯誤答案。

編輯:我決定這不會給程序的完整背景帶來傷害。這是我到目前爲止。我有一條線,精度的損失來自一個評論。

編輯2:下面是一些有關矩陣的例子。
Feat_2d是5x4608

 0   0   0   0   0 
    0   0   0   0   0 
    0   0   0   0 4.8146 
    0   0 19.0266   0   0 
    0   0   0   0   0 

Beta_2d是4609x4。我把最後一排的壯舉*的乘法Beta_2d

-7.1486e-05 -1.6801e-04 1.0970e-05 3.7837e-04 
-8.7524e-05 1.8275e-04 -6.7857e-04 2.6267e-04 
-9.1812e-05 -6.5495e-05 -1.7687e-03 -3.2168e-04 
    0e+00  0e+00  0e+00  0e+00 
-4.5089e-04 -5.6013e-05 1.4841e-04 2.4912e-04 

Y =

6.8995e-310  0e+00 4.7430e-322 1.7802e-306 
6.8995e-310  0e+00 4.9407e-322 1.4463e-307 
0e+00  0e+00  0e+00 1.4463e-307 
0e+00  0e+00 1.2352e-322 1.2016e-306 
6.8996e-310 6.8996e-310 6.8995e-310 1.7802e-306 

下面是從EDIT1

#include <mex.h> 
#include <iostream> 
#include <armadillo> 

using namespace arma; 

void predict_bbox_reg(double *beta, int beta_dim[2], double *t_inv, int tinv_dim[2], double mu, double *feat, int feat_dim[2], double *boxes, int box_dim[2]){ 


    //convert pointers 
    //beta 
    arma::mat beta_2d = mat(beta_dim[0], beta_dim[1]); 
    for(int i = 0; i<beta_dim[0]; i++){ 
     for(int j = 0; j<beta_dim[1]; j++){ 
      beta_2d(i, j) = beta[i+beta_dim[0]*j]; 
     } 
    } 

    //t_inv 
    arma::mat tinv_2d = mat(tinv_dim[0], tinv_dim[1]); 
    for(int i = 0; i<tinv_dim[0]; i++){ 
     for(int j = 0; j<tinv_dim[1]; j++){ 
      tinv_2d(i, j) = t_inv[i+tinv_dim[0]*j]; 
     } 
    } 
    //feadoublet_2d 
    arma::mat feat_2d = mat(feat_dim[0], feat_dim[1]); 
    for(int i = 0; i<feat_dim[0]; i++){ 
     for(int j = 0; j<feat_dim[1]; j++){ 
      feat_2d(i, j) = feat[i+feat_dim[0]*j]; 
     } 
    } 

    //boxes 
    arma::mat box_2d = mat(box_dim[0], box_dim[1]); 
    for(int i = 0; i<box_dim[0]; i++){ 
     for(int j = 0; j<box_dim[1]; j++){ 
      box_2d(i, j) = boxes[i+box_dim[0]*j]; 
     } 
    } 


    arma::mat Y = mat(feat_dim[0], beta_dim[1]); 

    Y = feat_2d*beta_2d.rows(0,beta_dim[0]-2);// this is the precision loss 

    arma::mat y1 = beta_2d.row(beta_2d.n_rows-1); 
    Y.each_row() += y1.row(0); 

    //RETURNS SOMETHING 


}   

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { 

    int M = mxGetM(prhs[0]); 
    int N = mxGetN(prhs[0]); 

    int beta_dim[2] = {M,N}; 
    double *beta = mxGetPr(prhs[0]); 


    M = mxGetM(prhs[1]); 
    N = mxGetN(prhs[1]); 
    int tinv_dim[2] = {M,N}; 
    double *t_inv = mxGetPr(prhs[1]); 


    double mu = *mxGetPr(prhs[2]);  

    M = mxGetM(prhs[3]); 
    N = mxGetN(prhs[3]); 

    int feat_dim[2] = {M,N}; 
    double *feat = mxGetPr(prhs[3]); 

    M = mxGetM(prhs[4]); 
    N = mxGetN(prhs[4]); 

    int box_dim[2] = {M,N}; 
    double *ex_boxes = mxGetPr(prhs[4]); 

    predict_bbox_reg(beta, beta_dim, t_inv, tinv_dim, 
      mu, feat, feat_dim, ex_boxes, box_dim); 

    //RETURNS results to matlab 
} 
+0

我們需要更多的信息。你能展示一些矩陣的最小例子嗎?另外,你如何定義「精度損失」?你怎麼知道你實際上失去了精確度?如果你做得很好,你無法將它與計算機的功能進行比較....也許你的比較矩陣不好,不是你自己的。 –

+0

@AnderBiguri我做了一些顯示某些矩陣的編輯,似乎有一個問題,其中Y導致基本爲零操作。當我在matlab中進行操作時,結果不一樣。 –

回答

0

的代碼,我看不到任何直接失誤你的代碼,但我懷疑犰狳有精度問題。我懷疑這可能是您指向無用數據轉換的東西。我會使用犰狳在.../mex_interface/armaMex.hpp文件中提供的功能。

矩陣乘法(mult_test.cpp)的一個簡單的例子:

#include <armadillo> 
#include "armaMex.hpp" 

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
{  
    // Convert to Armadillo 
    mat x1 = conv_to<mat>::from(armaGetPr(prhs[0],true)); 
    mat x2 = conv_to<mat>::from(armaGetPr(prhs[1],true)); 
    mat y(x1.n_rows,x2.n_cols); 

    // Do your stuff here: 
    y = x1*x2; 

    // Convert back to Matlab 
    plhs[0] = armaCreateMxMatrix(y.n_rows, y.n_cols, mxDOUBLE_CLASS, mxREAL); 
    armaSetPr(plhs[0], conv_to<mat>::from(y)); 
    return; 
} 

與.m文件

X1 = [1 2 3 ; 4 5 6]; 
X2 = 1e-7*rand(3,2); 

Y = mult_test(X1,X2); 

disp('Matlab:') 
disp(X1*X2) 
disp('Armadillo:') 
disp(Y) 

給輸出

Matlab: 
1.0e-06 * 

0.240798243020273 0.410716970485213 
0.559953800808707 0.974915983937571 

Armadillo: 
1.0e-06 * 

0.240798243020273 0.410716970485213 
0.559953800808707 0.974915983937571