e97f602dfec6d29b39d37236a6f3c3eee921601d
[profile/ivi/opencv.git] / samples / cpp / logistic_regression.cpp
1 /*//////////////////////////////////////////////////////////////////////////////////////
2 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
3
4 //  By downloading, copying, installing or using the software you agree to this license.
5 //  If you do not agree to this license, do not download, install,
6 //  copy or use the software.
7
8 // This is a implementation of the Logistic Regression algorithm in C++ in OpenCV.
9
10 // AUTHOR:
11 // Rahul Kavi rahulkavi[at]live[at]com
12 //
13
14 // contains a subset of data from the popular Iris Dataset (taken from
15 // "http://archive.ics.uci.edu/ml/datasets/Iris")
16
17 // # You are free to use, change, or redistribute the code in any way you wish for
18 // # non-commercial purposes, but please maintain the name of the original author.
19 // # This code comes with no warranty of any kind.
20
21 // #
22 // # You are free to use, change, or redistribute the code in any way you wish for
23 // # non-commercial purposes, but please maintain the name of the original author.
24 // # This code comes with no warranty of any kind.
25
26 // # Logistic Regression ALGORITHM
27
28 //                           License Agreement
29 //                For Open Source Computer Vision Library
30
31 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
32 // Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved.
33 // Third party copyrights are property of their respective owners.
34
35 // Redistribution and use in source and binary forms, with or without modification,
36 // are permitted provided that the following conditions are met:
37
38 //   * Redistributions of source code must retain the above copyright notice,
39 //     this list of conditions and the following disclaimer.
40
41 //   * Redistributions in binary form must reproduce the above copyright notice,
42 //     this list of conditions and the following disclaimer in the documentation
43 //     and/or other materials provided with the distribution.
44
45 //   * The name of the copyright holders may not be used to endorse or promote products
46 //     derived from this software without specific prior written permission.
47
48 // This software is provided by the copyright holders and contributors "as is" and
49 // any express or implied warranties, including, but not limited to, the implied
50 // warranties of merchantability and fitness for a particular purpose are disclaimed.
51 // In no event shall the Intel Corporation or contributors be liable for any direct,
52 // indirect, incidental, special, exemplary, or consequential damages
53 // (including, but not limited to, procurement of substitute goods or services;
54 // loss of use, data, or profits; or business interruption) however caused
55 // and on any theory of liability, whether in contract, strict liability,
56 // or tort (including negligence or otherwise) arising in any way out of
57 // the use of this software, even if advised of the possibility of such damage.*/
58
59 #include <iostream>
60
61 #include <opencv2/core/core.hpp>
62 #include <opencv2/ml/ml.hpp>
63 #include <opencv2/highgui/highgui.hpp>
64
65 using namespace std;
66 using namespace cv;
67 using namespace cv::ml;
68
69 int main()
70 {
71     const String filename = "data01.xml";
72     cout << "**********************************************************************" << endl;
73     cout << filename
74          << " contains digits 0 and 1 of 20 samples each, collected on an Android device" << endl;
75     cout << "Each of the collected images are of size 28 x 28 re-arranged to 1 x 784 matrix"
76          << endl;
77     cout << "**********************************************************************" << endl;
78
79     Mat data, labels;
80     {
81         cout << "loading the dataset" << endl;
82         FileStorage f;
83         if(f.open(filename, FileStorage::READ))
84         {
85             f["datamat"] >> data;
86             f["labelsmat"] >> labels;
87             f.release();
88         }
89         else
90         {
91             cerr << "File can not be opened: " << filename << endl;
92             return 1;
93         }
94         data.convertTo(data, CV_32F);
95         labels.convertTo(labels, CV_32F);
96         cout << "read " << data.rows << " rows of data" << endl;
97     }
98
99     Mat data_train, data_test;
100     Mat labels_train, labels_test;
101     for(int i = 0; i < data.rows; i++)
102     {
103         if(i % 2 == 0)
104         {
105             data_train.push_back(data.row(i));
106             labels_train.push_back(labels.row(i));
107         }
108         else
109         {
110             data_test.push_back(data.row(i));
111             labels_test.push_back(labels.row(i));
112         }
113     }
114     cout << "training/testing samples count: " << data_train.rows << "/" << data_test.rows << endl;
115
116     // display sample image
117 //    Mat bigImage;
118 //    for(int i = 0; i < data_train.rows; ++i)
119 //    {
120 //        bigImage.push_back(data_train.row(i).reshape(0, 28));
121 //    }
122 //    imshow("digits", bigImage.t());
123
124     Mat responses, result;
125
126 //    LogisticRegression::Params params = LogisticRegression::Params(
127 //        0.001, 10, LogisticRegression::BATCH, LogisticRegression::REG_L2, 1, 1);
128     // params1 (above) with batch gradient performs better than mini batch
129     // gradient below with same parameters
130     LogisticRegression::Params params = LogisticRegression::Params(
131         0.001, 10, LogisticRegression::MINI_BATCH, LogisticRegression::REG_L2, 1, 1);
132
133     // however mini batch gradient descent parameters with slower learning
134     // rate(below) can be used to get higher accuracy than with parameters
135     // mentioned above
136 //    LogisticRegression::Params params = LogisticRegression::Params(
137 //        0.000001, 10, LogisticRegression::MINI_BATCH, LogisticRegression::REG_L2, 1, 1);
138
139     cout << "training...";
140     Ptr<StatModel> lr1 = LogisticRegression::create(params);
141     lr1->train(data_train, ROW_SAMPLE, labels_train);
142     cout << "done!" << endl;
143
144     cout << "predicting...";
145     lr1->predict(data_test, responses);
146     cout << "done!" << endl;
147
148     // show prediction report
149     cout << "original vs predicted:" << endl;
150     labels_test.convertTo(labels_test, CV_32S);
151     cout << labels_test.t() << endl;
152     cout << responses.t() << endl;
153     result = (labels_test == responses) / 255;
154     cout << "accuracy: " << ((double)cv::sum(result)[0] / result.rows) * 100 << "%\n";
155
156     // save the classfier
157     cout << "saving the classifier" << endl;
158     const String saveFilename = "NewLR_Trained.xml";
159     lr1->save(saveFilename);
160
161     // load the classifier onto new object
162     cout << "loading a new classifier" << endl;
163     Ptr<LogisticRegression> lr2 = StatModel::load<LogisticRegression>(saveFilename);
164
165     // predict using loaded classifier
166     cout << "predicting the dataset using the loaded classfier" << endl;
167     Mat responses2;
168     lr2->predict(data_test, responses2);
169     // calculate accuracy
170     cout << "accuracy using loaded classifier: "
171          << 100 * (float)cv::countNonZero(labels_test == responses2) / responses2.rows << "%"
172          << endl;
173
174     waitKey(0);
175     return 0;
176 }