Advertisement
Guest User

Untitled

a guest
Apr 19th, 2018
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.29 KB | None | 0 0
  1. #include <iostream>
  2. #include <fstream>
  3. #include <opencv2/core/core.hpp>
  4. #include <opencv2/imgproc/imgproc.hpp>
  5. #include <opencv2/highgui/highgui.hpp>
  6.  
  7. using namespace std;
  8. using namespace cv;
  9.  
  10. /** classification header **/
  11. #define NUM_ITERATIONS 10000
  12. #define STEP_SIZE 0.4
  13.  
  14. /*
  15. Comment on the effect of the stepsize on the convergence of optimization
  16. ----
  17. The STEP_SIZE has a great effect on the speed of convergence. To make a fair comparison, we will keep the number of iterations NUM_ITERATIONS constant at 1e4.
  18. Starting with small stepsize of 0.1 yields a loss of 0.4139, which decreases as we increment the stepsize by 0.1 (0.3663, 0.3470, 0.3432). For stepsizes of 0.35 and above the loss increases again, and as it turns out quite drastically so: (0.5 ~ 0.362542, 0.6 ~ 0.390917, 0.7 ~ 0.427088, 0.8 ~ 0.4685, 0.9 ~ 0.468582, 1.0 ~ 0.544636).
  19. This behavior was somewhat expected and is most likely caused by overfitting to the training set.
  20. */
  21.  
  22. struct ClassificationParam{
  23. string posTrain, negTrain;
  24. string posTest, negTest;
  25. };
  26.  
  27. // regression class for various regression methods
  28. class LogisticRegression {
  29.  
  30. private:
  31. Mat train, test; // each column is a feature vector
  32. Mat gtLabelTrain, gtLabelTest; // row vector
  33. Mat phi;
  34.  
  35. int loadFeatures(std::string& trainFile, std::string& testFile, Mat& feat, Mat& gtLabel);
  36. Mat calculateGradient(Mat &X, Mat &Y, Mat &phi);
  37. double calculateLoss(Mat &X, Mat &Y, Mat &phi);
  38.  
  39. public:
  40. LogisticRegression(ClassificationParam& param);
  41. int learnClassifier();
  42. int testClassifier();
  43. float sigmoid(float a);
  44. Mat sigmoid(Mat a);
  45. ~LogisticRegression(){}
  46. };
  47.  
  48. /** regression header **/
  49. #define FIN_RBF_NUM_CLUST 300
  50. #define RBF_SIGMA 1e-3
  51.  
  52. // reading input parameters
  53. struct RegressionParam{
  54. std::string regressionTrain;
  55. std::string regressionTest;
  56. };
  57.  
  58. // models for regression
  59. class Model{
  60. public:
  61. Mat phi; // each row models wi
  62. Mat sigma_sq; // column vector
  63. Mat codeBook; // codebook for finite kernel reg.
  64. };
  65.  
  66. // regression class for various regression methods
  67. class Regression{
  68. private:
  69. Mat trainx, trainw;
  70. Mat testx, testw;
  71. Model linear_reg, fin_rbf_reg, dual_reg;
  72.  
  73. int loadFeatures(std::string& fileName, Mat& vecx, Mat& vecw);
  74.  
  75. public:
  76. Regression(RegressionParam& param);
  77. ~Regression(){}
  78. int trainLinearRegression(); // TODO implement
  79. int trainFinite_RBF_KernelRegression(); // TODO implement
  80. int trainDualRegression(); // TODO implement
  81.  
  82. int testLinearRegresssion(); // TODO implement
  83. int testFinite_RBF_KernelRegression(); // TODO implement
  84. int testDualRegression(); // TODO implement
  85.  
  86. };
  87.  
  88. int main() {
  89. RegressionParam rparam;
  90. rparam.regressionTrain = "../../../data/regression_train.txt";
  91. rparam.regressionTest = "../../../data/regression_test.txt";
  92.  
  93. Regression reg(rparam);
  94.  
  95. // linear regression
  96. //reg.trainLinearRegression();
  97. //reg.testLinearRegresssion();
  98. //reg.trainFinite_RBF_KernelRegression();
  99. //reg.testFinite_RBF_KernelRegression();
  100. //reg.trainDualRegression();
  101. //reg.testDualRegression();
  102.  
  103. ClassificationParam cparam;
  104. cparam.posTrain = "../../../data/bottle_train.txt";
  105. cparam.negTrain = "../../../data/horse_train.txt";
  106. cparam.posTest = "../../../data/bottle_test.txt";
  107. cparam.negTest = "../../../data/horse_test.txt";
  108.  
  109. LogisticRegression cls(cparam);
  110. cls.learnClassifier();
  111. cls.testClassifier();
  112.  
  113. return 0;
  114. }
  115.  
  116. /** classification functions **/
  117. LogisticRegression::LogisticRegression(ClassificationParam& param) {
  118. loadFeatures(param.posTrain,param.negTrain,train,gtLabelTrain);
  119. loadFeatures(param.posTest,param.negTest,test,gtLabelTest);
  120. }
  121.  
  122. int LogisticRegression::loadFeatures(string& trainPos, string& trainNeg, Mat& feat, Mat& gtL){
  123.  
  124. ifstream iPos(trainPos.c_str());
  125. if(!iPos) {
  126. cout<<"error reading train file: "<<trainPos<<endl;
  127. exit(-1);
  128. }
  129. ifstream iNeg(trainNeg.c_str());
  130. if(!iNeg) {
  131. cout<<"error reading test file: "<<trainNeg<<endl;
  132. exit(-1);
  133. }
  134.  
  135. int rPos, rNeg, cPos, cNeg;
  136. iPos >> rPos;
  137. iPos >> cPos;
  138. iNeg >> rNeg;
  139. iNeg >> cNeg;
  140.  
  141. if(cPos != cNeg){
  142. cout<<"Number of features in pos and neg classes unequal"<<endl;
  143. exit(-1);
  144. }
  145. feat.create(cPos+1,rPos+rNeg,CV_32F); // each column is a feat vect
  146. gtL.create(1,rPos+rNeg,CV_32F); // row vector
  147.  
  148.  
  149. // load positive examples
  150. for(int idr=0; idr<rPos; ++idr){
  151. gtL.at<float>(0,idr) = 1;
  152. feat.at<float>(0,idr) = 1;
  153. for(int idc=0; idc<cPos; ++idc){
  154. iPos >> feat.at<float>(idc+1,idr);
  155. }
  156. }
  157.  
  158. // load negative examples
  159. for(int idr=0; idr<rNeg; ++idr){
  160. gtL.at<float>(0,rPos+idr) = 0;
  161. feat.at<float>(0,rPos+idr) = 1;
  162. for(int idc=0; idc<cNeg; ++idc){
  163. iNeg >> feat.at<float>(idc+1,rPos+idr);
  164. }
  165. }
  166.  
  167. iPos.close();
  168. iNeg.close();
  169.  
  170. return 0;
  171. }
  172.  
  173. float LogisticRegression::sigmoid(float a){
  174. return 1.0f/(1+exp(-a));
  175. }
  176.  
  177. Mat LogisticRegression::sigmoid(Mat a) {
  178. // Apply Sigmoid elementwise to all elements of matrix a
  179. for (auto y = 0u; y < a.rows; y++) {
  180. for (auto x = 0u; x < a.cols; x++) {
  181. a.at<float>(y, x) = sigmoid(a.at<float>(y, x));
  182. }
  183. }
  184. return a;
  185. }
  186.  
  187.  
  188. double LogisticRegression::calculateLoss(Mat &X, Mat &Y, Mat &phi) {
  189.  
  190. Mat h, h_log, OneMinusTerm_log;
  191. // Sigmoid of the weighted sum
  192. h = sigmoid(phi * X);
  193.  
  194. // Apply logarithm elementwise to h and 1-h respectively
  195. log(h, h_log);
  196. log(1 - h, OneMinusTerm_log);
  197.  
  198. // Calculate Loss according to the function from the lecture
  199. double loss = (-1.0 / X.cols) * sum(Y.mul(h_log) + (1 - Y).mul(OneMinusTerm_log))[0];
  200. return loss;
  201. }
  202.  
  203. Mat LogisticRegression::calculateGradient(Mat &X, Mat &Y, Mat &phi) {
  204.  
  205. Mat h, gradient;
  206. // Sigmoid of the weighted sum
  207. h = sigmoid(phi * X);
  208. // Calulate gradient
  209. gradient = X * (h - Y).t();
  210. return gradient;
  211. }
  212.  
  213. int LogisticRegression::learnClassifier() {
  214.  
  215. // Placeholder for the weights
  216. phi = Mat(1, train.rows, CV_32F, 0.0);
  217.  
  218. cout << "Starting logistic regression training with a learning rate of " << STEP_SIZE << " ..." << endl;
  219. cout << "-----" << endl;
  220.  
  221. // Initialize the loss
  222. double initialLoss = FLT_MAX;
  223. // For every iteration...
  224. for (auto s = 0u; s < NUM_ITERATIONS; s++) {
  225. // ... Take a step in the direction of the negative gradient where the stepsize with which to take that step was determined earlier and stays constant over all iterations
  226. phi = phi - STEP_SIZE * calculateGradient(train, gtLabelTrain, phi).t();
  227. // Calculate loss to evaluate the training performance, which could be visualized somehow
  228. double loss = calculateLoss(train, gtLabelTrain, phi);
  229. if (s % 1000 == 0) {
  230. cout << "Loss on training set after iteration " << s << ": " << loss << endl;
  231. }
  232. }
  233. return 0;
  234. }
  235.  
  236. int LogisticRegression::testClassifier() {
  237.  
  238. Mat h;
  239. // Sigmoid of the weighted sum
  240. h = sigmoid(phi * test);
  241.  
  242. cout << "Starting logistic regression testing ..." << endl;
  243. cout << "-----" << endl;
  244. int testSize = gtLabelTest.cols;
  245. float falsePredictions = 0;
  246. // For every test sample ...
  247. for (auto i = 0u; i < gtLabelTest.cols; i++) {
  248. // Binarize the results by rounding (values above 0.5 become 1, and values below become 0)
  249. float prediction = cvRound(h.at<float>(0, i));
  250. float teacher = gtLabelTest.at<float>(0, i);
  251.  
  252. if (prediction != teacher)
  253. falsePredictions++;
  254. }
  255.  
  256. float accuracy = (testSize - falsePredictions) / testSize;
  257. cout << "Loss on test set: " << calculateLoss(test, gtLabelTest, phi) << endl;
  258. cout << "Accuracy on test set: " << accuracy << endl;
  259.  
  260. return 0;
  261. }
  262.  
  263.  
  264. /** regression functions **/
  265. Regression::Regression(RegressionParam& param){
  266. // load features
  267. loadFeatures(param.regressionTrain,trainx,trainw);
  268. loadFeatures(param.regressionTest,testx,testw);
  269. // cout<<"features loaded successfully"<<endl;
  270.  
  271. // model memory
  272. linear_reg.phi.create(trainx.rows,trainw.rows,CV_32F); linear_reg.phi.setTo(0);
  273. linear_reg.sigma_sq.create(trainw.rows,1,CV_32F); linear_reg.sigma_sq.setTo(0);
  274. fin_rbf_reg.phi.create(FIN_RBF_NUM_CLUST,trainw.rows,CV_32F);
  275. fin_rbf_reg.sigma_sq.create(trainw.rows,1,CV_32F);
  276. dual_reg.phi.create(trainx.cols,trainw.rows,CV_32F);
  277. dual_reg.sigma_sq.create(trainw.rows,1,CV_32F);
  278.  
  279. }
  280. int Regression::loadFeatures(string& fileName, Mat& matx, Mat& matw){
  281.  
  282. // init dimensions and file
  283. int numR, numC, dimW;
  284. ifstream iStream(fileName.c_str());
  285. if(!iStream){
  286. cout<<"cannot read feature file: "<<fileName<<endl;
  287. exit(-1);
  288. }
  289.  
  290. // read file contents
  291. iStream >> numR;
  292. iStream >> numC;
  293. iStream >> dimW;
  294. matx.create(numC-dimW+1,numR,CV_32F); // each column is a feature
  295. matw.create(dimW,numR,CV_32F); // each column is a vector to be regressed
  296.  
  297. for(int r=0; r<numR; ++r){
  298. // read world data
  299. for(int c=0; c<dimW; ++c)
  300. iStream >> matw.at<float>(c,r);
  301. // read feature data
  302. matx.at<float>(0,r)=1;
  303. for(int c=0; c<numC-dimW; ++c)
  304. iStream >> matx.at<float>(c+1,r);
  305. }
  306. iStream.close();
  307.  
  308. return 0;
  309. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement