Commit fde49f246b2dbed746bddfad3212797d1697d511
1 parent
89676102
integrated Rupali's changes - replaced OpenCV matrix math with LAPACK
Showing
1 changed file
with
67 additions
and
25 deletions
Show diff stats
src/main.cu
... | ... | @@ -50,6 +50,43 @@ typedef struct { |
50 | 50 | }gnome; |
51 | 51 | gnome gnom; |
52 | 52 | |
53 | +//computing matrix determinant using LU decomposition | |
54 | +template<typename T> | |
55 | +T mtxdeterminant(T* M, size_t r, size_t c) { | |
56 | + //----DETERMINANT using LU decomposition using LAPACK | |
57 | + /* DGETRF computes an LU factorization of a general M-by-N matrix A using partial pivoting with row interchanges. | |
58 | + The factorization has the form | |
59 | + A = P * L * U | |
60 | + where P is a permutation matrix, L is lower triangular with unit diagonal elements (lower trapezoidal if m > n), and U is upper triangular (upper trapezoidal if m < n).*/ | |
61 | + int* ipiv = (int*)malloc(sizeof(int) * r); | |
62 | + memset(ipiv, 0, r * sizeof(int)); | |
63 | + LAPACKE_sgetrf(LAPACK_COL_MAJOR, (int)r, (int)c, M, (int)r, ipiv); | |
64 | + | |
65 | + //determinant of U | |
66 | + T product = 1; | |
67 | + for (size_t i = 0; i < r; i++) { | |
68 | + for (size_t j = 0; j < r; j++) { | |
69 | + if (i == j) { | |
70 | + product = product * M[i * r + j]; | |
71 | + } | |
72 | + } | |
73 | + } | |
74 | + | |
75 | + //determinant of P | |
76 | + int j; | |
77 | + double detp = 1.; | |
78 | + for (j = 0; j < r; j++) { | |
79 | + if (j + 1 != ipiv[j]) { | |
80 | + // j+1 : following feedback of ead : ipiv is from Fortran, hence starts at 1. | |
81 | + // hey ! This is a transpose ! | |
82 | + detp = -detp; | |
83 | + } | |
84 | + } | |
85 | + T detSw = product * detp * 1; //det(U)*det(P)*det(L) | |
86 | + if (ipiv != NULL) std::free(ipiv); | |
87 | + return detSw; | |
88 | + | |
89 | +} | |
53 | 90 | |
54 | 91 | void gpuComputeEignS( size_t g, size_t fea){ |
55 | 92 | //eigen value computation will return r = (nC-1) eigen vectors so new projected data will have dimension of r rather than f |
... | ... | @@ -87,7 +124,7 @@ void gpuComputeEignS( size_t g, size_t fea){ |
87 | 124 | int *IPIV = (int*) malloc(sizeof(int) * f); |
88 | 125 | //computing inverse of matrix Sw |
89 | 126 | memset(IPIV, 0, f * sizeof(int)); |
90 | - LAPACKE_sgetrf(LAPACK_COL_MAJOR, (int)f, (int)f, gSw_a, (int)f, IPIV); | |
127 | + LAPACKE_sgetrf(LAPACK_COL_MAJOR, (int)f, (int)f, gSw_a, (int)f, IPIV); | |
91 | 128 | // DGETRI computes the inverse of a matrix using the LU factorization computed by DGETRF. |
92 | 129 | LAPACKE_sgetri(LAPACK_COL_MAJOR, (int)f, gSw_a, (int)f, IPIV); |
93 | 130 | |
... | ... | @@ -146,23 +183,22 @@ void gpuComputeEignS( size_t g, size_t fea){ |
146 | 183 | mtxMul(tempgSw, &gnom.lda[g * r * f], &gnom.Sw[g * f * f], r, f, f,f); |
147 | 184 | float* nSw = (float*)calloc(r * r, sizeof(float)); |
148 | 185 | mtxMultranspose(nSw, tempgSw, &gnom.lda[g * r * f], r, f, r, f); |
149 | - if(debug){ | |
150 | - std::cout<<"From Eigen function: projected Sb sn Sw"<<std::endl; | |
186 | + | |
187 | + //determinant of Sb and Sw | |
188 | + float detSw = mtxdeterminant(nSw, r, r); | |
189 | + float detSb = mtxdeterminant(nSb, r, r); | |
190 | + | |
191 | + if (debug) { | |
192 | + std::cout << "From Eigen function: projected Sb sn Sw" << std::endl; | |
151 | 193 | displayS(nSb, r); //display Sb |
152 | 194 | displayS(nSw, r); //display Sw |
153 | - std::cout<<std::endl; | |
195 | + std::cout << std::endl; | |
196 | + std::cout <<"det(Sb)= "<< detSb<< std::endl; | |
197 | + std::cout << "det(Sw)= " << detSw << std::endl; | |
154 | 198 | } |
155 | 199 | |
156 | - ///DETERMINANT CURRENTLY REQUIRES OPENCV | |
157 | - std::cout<<"ERROR: This code requires a fix to remove an OpenCV dependence."<<std::endl; | |
158 | - mtxOutputFile("newSw.csv", nSw, r, r); | |
159 | - exit(1); | |
160 | - //FIX BY REPLACING THE FOLLOWING THREE LINES OF CODE USING LAPACK | |
161 | - //cv::Mat newSw = cv::Mat((int)r, (int)r, CV_32FC1, nSw); //within scatter of gnome g in the population | |
162 | - //cv::Mat newSb = cv::Mat((int)r, (int)r, CV_32FC1, nSb); //within scatter of gnome g in the population | |
163 | - | |
164 | 200 | //fisher's ratio from ratio of projected sb and sw |
165 | - float fisherRatio = 0;// = cv::determinant(newSb) /cv::determinant(newSw); | |
201 | + float fisherRatio = detSb /detSw; | |
166 | 202 | gnom.S[g] = 1/fisherRatio; |
167 | 203 | if (debug) { |
168 | 204 | std::cout<<"Score["<<g<<"]: "<< gnom.S[g]<<std::endl; |
... | ... | @@ -172,6 +208,7 @@ void gpuComputeEignS( size_t g, size_t fea){ |
172 | 208 | std::cout << ga.P[ga.f * g + i] << ", "; |
173 | 209 | std::cout << std::endl; |
174 | 210 | } |
211 | + | |
175 | 212 | |
176 | 213 | |
177 | 214 | if(IPIV!= NULL) std::free(IPIV); |
... | ... | @@ -430,27 +467,30 @@ int main(int argc, char* argv[]){ |
430 | 467 | |
431 | 468 | |
432 | 469 | //fitness values of best gnome is |
433 | - csv<<"best gnome's fitness value is "<<best_S[ga.gnrtn-1]<<std::endl; //output fitness value of best gnome in last generation | |
434 | - //output gnome i.e. band index of selected featurs | |
470 | + csv<<"fitness value for best gnome: "<<best_S[ga.gnrtn-1]<<std::endl; //output fitness value of best gnome in last generation | |
471 | + /*//output gnome i.e. band index of selected featurs | |
435 | 472 | csv<<(bestgnome.at(0)); //output feature subset |
436 | 473 | for(size_t i = 1; i < ga.f; i++) |
437 | 474 | csv<<","<<(bestgnome.at(i)); |
438 | - csv<<std::endl; | |
475 | + csv<<std::endl;*/ | |
439 | 476 | |
440 | - //output LDA basis of size r X f, r is nC - 1 as LDA projection is rank limited by number of classes - 1 | |
441 | - for (size_t i = 0; i < nC-1; i++){ | |
442 | - csv<<lda[ldaindx + i * ga.f ]; | |
443 | - for (size_t j = 1; j < ga.f; j++){ | |
444 | - csv<<","<<lda[ldaindx + i * ga.f +j]; | |
445 | - } | |
446 | - csv << std::endl; | |
447 | - } | |
448 | 477 | //output actual wavelenths corresponding to those band indices |
478 | + csv << "selected wavenumbers:"<<std::endl; | |
449 | 479 | csv << (wavelengths[bestgnome.at(0)]); |
450 | 480 | for (size_t i = 1; i < ga.f; i++) |
451 | - csv << "," << (wavelengths[bestgnome.at(i)]); | |
481 | + csv << ", " << (wavelengths[bestgnome.at(i)]); | |
452 | 482 | csv << std::endl; |
453 | 483 | |
484 | + //output LDA basis of size r X f, r is nC - 1 as LDA projection is rank limited by number of classes - 1 | |
485 | + csv << "LDA basis:" << std::endl; | |
486 | + for (size_t i = 0; i < nC - 1; i++) { | |
487 | + csv << lda[ldaindx + i * ga.f]; | |
488 | + for (size_t j = 1; j < ga.f; j++) { | |
489 | + csv << ", " << lda[ldaindx + i * ga.f + j]; | |
490 | + } | |
491 | + csv << std::endl; | |
492 | + } | |
493 | + | |
454 | 494 | |
455 | 495 | if (args["trim"].is_set()) { |
456 | 496 | csv << "trim info" << std::endl; |
... | ... | @@ -489,6 +529,8 @@ int main(int argc, char* argv[]){ |
489 | 529 | ////output actual wavelenths corresponding to those trim indices |
490 | 530 | ////these wavenumber are grouped in pairs, check each pair, if duplicated numbers are there in pair delete one and keep other as band to trim, if 2nd wavnumber is smaller than 1st in a pair ignore that pair |
491 | 531 | ////e.g [1, 228, 230, 230, 232, 350,352, 351, 353, 1200] pairas [1(start)-228,230-230, 232-350, 352-351, 353-1200(end)], trimming wavenumbers are [1-228, 230, 233-350, 353-1200] |
532 | + | |
533 | + | |
492 | 534 | csv << (wavelengths[finaltrim_ind.at(0)]); |
493 | 535 | for (size_t i = 1; i < ga.f * + 2 ; i++) |
494 | 536 | csv << "," << (wavelengths[finaltrim_ind.at(i)]); | ... | ... |