OpenCV k近傍法 - eiichiromomma/CVMLAB GitHub Wiki

(OpenCV) k近傍法

k近傍法(あるいはk最短近傍分類: k-nearest neighbour classifer)もletter_recog.cppに加えてみた

main

SupportVectorMachineを参照。 オプションをくっつけるだけ。

注意点

データによっては特徴量ごとに尺度が明らかに異なる場合もあるので要注意。

そこらへんはRのMASSパッケージの原本である"S-PLUS による統計解析"の第11章あたりに話が出ている。

build_knearest_classifier

RTreesのを元に作ってみた。 パラメータが少ない。というかチューニングのしようがない。

    static
    int build_knearest_classifier( char* data_filename,
        char* filename_to_save, char* filename_to_load )
    {
        CvMat* data = 0;
        CvMat* responses = 0;
        CvMat* sample_idx = 0;

        int ok = read_num_class_data( data_filename, 16, &data, &responses );
        int nsamples_all = 0, ntrain_samples = 0;
        int i = 0;
        double train_hr = 0, test_hr = 0;
        CvKNearest knn;
        CvMat* var_importance = 0;

        if( !ok )
        {
            printf( "Could not read the database %s\n", data_filename );
            return -1;
        }

        printf( "The database %s is loaded.\n", data_filename );
        nsamples_all = data->rows;
        //半分を学習に使用
        ntrain_samples = (int)(nsamples_all*0.5);

        // Create or load Random Trees classifier
        if( filename_to_load )
        {
            // load classifier from the specified file
            knn.load( filename_to_load );
            ntrain_samples = 0;
            //KNNかのチェック(未確認)
            if( knn.get_var_count() == 0 )
            {
                printf( "Could not read the classifier %s\n", filename_to_load );
                return -1;
            }
            printf( "The classifier %s is loaded.\n", data_filename );
        }
        else
        {
            // create classifier by using <data> and <responses>
            printf( "Training the classifier ...");

            // 2. create sample_idx
            sample_idx = cvCreateMat( 1, nsamples_all, CV_8UC1 );
            {
                CvMat mat;
                cvGetCols( sample_idx, &mat, 0, ntrain_samples );
                cvSet( &mat, cvRealScalar(1) );

                cvGetCols( sample_idx, &mat, ntrain_samples, nsamples_all );
                cvSetZero( &mat );
            }

            // 3. train classifier
            //32個までfind_nearest()の際に問合せ可能とする
            //パラメータは
            //http://opencv.jp/document/opencvref_ml.html#decl_CvKNearest_train
            //を参照
            //responsesはカテゴリ変数としている
            knn.train(data,responses,sample_idx,false, 32, false);
            printf( "\n");
        }

        // compute prediction error on train and test data
        for( i = 0; i < nsamples_all; i++ )
        {
            double r;
            CvMat sample;
            cvGetRow( data, &sample, i );
            //テストを行なう
            //返り値は近い10個(ここでは10:さっきの32より小さければ良い)で投票を行なった結果
            //近傍のベクトルの座標や距離が欲しい場合はCvMatサンプル数x個数のサイズで受け取る。詳細は
            //http://opencv.jp/document/opencvref_ml.html#decl_CvKNearest_find_nearest
            //を参照
            r = knn.find_nearest( &sample, 10);
              //結果の比較
            printf("predict: %c, responses: %c, %s\n", (unsigned char)r, (unsigned char)responses->data.fl[i],
              fabs((double)r - responses->data.fl[i]) <= FLT_EPSILON?"Good!":"Bad!");
            r = fabs((double)r - responses->data.fl[i]) <= FLT_EPSILON ? 1 : 0;
            if( i < ntrain_samples )
                train_hr += r;
            else
                test_hr += r;
        }

        test_hr /= (double)(nsamples_all-ntrain_samples);
        train_hr /= (double)ntrain_samples;
        printf( "Recognition rate: train = %.1f%%, test = %.1f%%\n",
                train_hr*100., test_hr*100. );

        // Save KNN classifier to file if needed
        if( filename_to_save )
           knn.save( filename_to_save );

        cvReleaseMat( &sample_idx );
        cvReleaseMat( &data );
        cvReleaseMat( &responses );

        return 0;
    }
⚠️ **GitHub.com Fallback** ⚠️