Ejemplo n.º 1
0
        public SVM()
        {
            // CvSVM
            // SVMを利用して2次元ベクトルの3クラス分類問題を解く

            const int S = 1000;
            const int SIZE = 400;
            CvRNG rng = new CvRNG((ulong)DateTime.Now.Ticks);

            // (1)画像領域の確保と初期化
            using (IplImage img = new IplImage(SIZE, SIZE, BitDepth.U8, 3))
            {
                img.Zero();
                // (2)学習データの生成
                CvPoint[] pts = new CvPoint[S];
                int[] res = new int[S];
                for (int i = 0; i < S; i++)
                {
                    pts[i].X = (int)(rng.RandInt() % SIZE);
                    pts[i].Y = (int)(rng.RandInt() % SIZE);
                    if (pts[i].Y > 50 * Math.Cos(pts[i].X * Cv.PI / 100) + 200)
                    {
                        img.Line(new CvPoint(pts[i].X - 2, pts[i].Y - 2), new CvPoint(pts[i].X + 2, pts[i].Y + 2), new CvColor(255, 0, 0));
                        img.Line(new CvPoint(pts[i].X + 2, pts[i].Y - 2), new CvPoint(pts[i].X - 2, pts[i].Y + 2), new CvColor(255, 0, 0));
                        res[i] = 1;
                    }
                    else
                    {
                        if (pts[i].X > 200)
                        {
                            img.Line(new CvPoint(pts[i].X - 2, pts[i].Y - 2), new CvPoint(pts[i].X + 2, pts[i].Y + 2), new CvColor(0, 255, 0));
                            img.Line(new CvPoint(pts[i].X + 2, pts[i].Y - 2), new CvPoint(pts[i].X - 2, pts[i].Y + 2), new CvColor(0, 255, 0));
                            res[i] = 2;
                        }
                        else
                        {
                            img.Line(new CvPoint(pts[i].X - 2, pts[i].Y - 2), new CvPoint(pts[i].X + 2, pts[i].Y + 2), new CvColor(0, 0, 255));
                            img.Line(new CvPoint(pts[i].X + 2, pts[i].Y - 2), new CvPoint(pts[i].X - 2, pts[i].Y + 2), new CvColor(0, 0, 255));
                            res[i] = 3;
                        }
                    }
                }

                // (3)学習データの表示
                Cv.NamedWindow("SVM", WindowMode.AutoSize);
                Cv.ShowImage("SVM", img);
                Cv.WaitKey(0);

                // (4)学習パラメータの生成
                float[] data = new float[S * 2];
                for (int i = 0; i < S; i++)
                {
                    data[i * 2] = ((float)pts[i].X) / SIZE;
                    data[i * 2 + 1] = ((float)pts[i].Y) / SIZE;
                }

                // (5)SVMの学習
                using (CvSVM svm = new CvSVM())
                {
                    CvMat data_mat = new CvMat(S, 2, MatrixType.F32C1, data);
                    CvMat res_mat = new CvMat(S, 1, MatrixType.S32C1, res);
                    CvTermCriteria criteria = new CvTermCriteria(1000, float.Epsilon);
                    CvSVMParams param = new CvSVMParams(SVMType.CSvc, SVMKernelType.Rbf, 10.0, 8.0, 1.0, 10.0, 0.5, 0.1, null, criteria);
                    svm.Train(data_mat, res_mat, null, null, param);

                    // (6)学習結果の描画
                    for (int i = 0; i < SIZE; i++)
                    {
                        for (int j = 0; j < SIZE; j++)
                        {
                            float[] a = { (float)j / SIZE, (float)i / SIZE };
                            CvMat m = new CvMat(1, 2, MatrixType.F32C1, a);
                            float ret = svm.Predict(m);
                            CvColor color = new CvColor();
                            switch ((int)ret)
                            {
                                case 1:
                                    color = new CvColor(100, 0, 0); break;
                                case 2:
                                    color = new CvColor(0, 100, 0); break;
                                case 3:
                                    color = new CvColor(0, 0, 100); break;
                            }
                            img[i, j] = color;
                        }
                    }

                    // (7)トレーニングデータの再描画
                    for (int i = 0; i < S; i++)
                    {
                        CvColor color = new CvColor();
                        switch (res[i])
                        {
                            case 1:
                                color = new CvColor(255, 0, 0); break;
                            case 2:
                                color = new CvColor(0, 255, 0); break;
                            case 3:
                                color = new CvColor(0, 0, 255); break;
                        }
                        img.Line(new CvPoint(pts[i].X - 2, pts[i].Y - 2), new CvPoint(pts[i].X + 2, pts[i].Y + 2), color);
                        img.Line(new CvPoint(pts[i].X + 2, pts[i].Y - 2), new CvPoint(pts[i].X - 2, pts[i].Y + 2), color);
                    }

                    // (8)サポートベクターの描画
                    int sv_num = svm.GetSupportVectorCount();
                    for (int i = 0; i < sv_num; i++)
                    {
                        var support = svm.GetSupportVector(i);
                        img.Circle(new CvPoint((int)(support[0] * SIZE), (int)(support[1] * SIZE)), 5, new CvColor(200, 200, 200));
                    }

                    // (9)画像の表示
                    Cv.NamedWindow("SVM", WindowMode.AutoSize);
                    Cv.ShowImage("SVM", img);
                    Cv.WaitKey(0);
                    Cv.DestroyWindow("SVM");

                }
            }

        }
Ejemplo n.º 2
0
        /// <summary>
        /// SVM
        /// </summary>
        /// <param name="dataFilename"></param>
        /// <param name="filenameToSave"></param>
        /// <param name="filenameToLoad"></param>
        private void BuildSvmClassifier(string dataFilename, string filenameToSave, string filenameToLoad)
        {
            //C_SVCのパラメータ
            const float SvmC = 1000;
            //RBFカーネルのパラメータ
            const float SvmGamma = 0.1f;

            CvMat data = null;
            CvMat responses = null;
            CvMat sampleIdx = null;

            int nsamplesAll = 0, ntrainSamples = 0;
            double trainHr = 0, testHr = 0;

            CvSVM svm = new CvSVM();
            CvTermCriteria criteria = new CvTermCriteria(100, 0.001);

            try
            {
                ReadNumClassData(dataFilename, 16, out data, out responses);
            }
            catch
            {
                Console.WriteLine("Could not read the database {0}", dataFilename);
                return;
            }
            Console.WriteLine("The database {0} is loaded.", dataFilename);

            nsamplesAll = data.Rows;
            ntrainSamples = (int)(nsamplesAll * 0.2);

            // Create or load Random Trees classifier
            if (filenameToLoad != null)
            {
                // load classifier from the specified file
                svm.Load(filenameToLoad);
                ntrainSamples = 0;
                if (svm.GetSupportVectorCount() == 0)
                {
                    Console.WriteLine("Could not read the classifier {0}", filenameToLoad);
                    return;
                }
                Console.WriteLine("The classifier {0} is loaded.", filenameToLoad);
            }
            else
            {
                // create classifier by using <data> and <responses>
                Console.Write("Training the classifier ...");

                // 2. create sample_idx
                sampleIdx = new CvMat(1, nsamplesAll, MatrixType.U8C1);
                {
                    CvMat mat;
                    Cv.GetCols(sampleIdx, out mat, 0, ntrainSamples);
                    mat.Set(CvScalar.RealScalar(1));

                    Cv.GetCols(sampleIdx, out mat, ntrainSamples, nsamplesAll);
                    mat.SetZero();
                }

                // 3. train classifier
                // 方法、カーネルにより使わないパラメータは0で良く、
                // 重みについてもNULLで良い
                svm.Train(data, responses, null, sampleIdx, new CvSVMParams(CvSVM.C_SVC, CvSVM.RBF, 0, SvmGamma, 0, SvmC, 0, 0, null, criteria));
                Console.WriteLine();
            }

            
            // compute prediction error on train and test data            
            for (int i = 0; i < nsamplesAll; i++)
            {
                double r;
                CvMat sample;
                Cv.GetRow(data, out sample, i);

                r = svm.Predict(sample);
                // compare results
                Console.WriteLine(
                    "predict: {0}, responses: {1}, {2}",
                    (char)r,
                    (char)responses.DataArraySingle[i],
                    Math.Abs((double)r - responses.DataArraySingle[i]) <= float.Epsilon ? "Good!" : "Bad!"
                );
                r = Math.Abs((double)r - responses.DataArraySingle[i]) <= float.Epsilon ? 1 : 0;

                if (i < ntrainSamples)
                    trainHr += r;
                else
                    testHr += r;
            }

            testHr /= (double)(nsamplesAll - ntrainSamples);
            trainHr /= (double)ntrainSamples;
            Console.WriteLine("Gamma={0:F5}, C={1:F5}", SvmGamma, SvmC);
            if (filenameToLoad != null)
            {
                Console.WriteLine("Recognition rate: test = {0:F1}%", testHr * 100.0);
            }
            else
            {
                Console.WriteLine("Recognition rate: train = {0:F1}%, test = {1:F1}%", trainHr * 100.0, testHr * 100.0);
            }

            Console.WriteLine("Number of Support Vector: {0}", svm.GetSupportVectorCount());
            // Save SVM classifier to file if needed
            if (filenameToSave != null)
            {
                svm.Save(filenameToSave);
            }


            Console.Read();


            if (sampleIdx != null) sampleIdx.Dispose();
            data.Dispose();
            responses.Dispose();
            svm.Dispose();
        }