Nano Hash - криптовалюты, майнинг, программирование

Образец ядра OpenCV SVM

Документы OpenCV приводят следующий пример типа ядра SVM:

Сравнение различных ядер в следующем двухмерном тестовом примере с четырьмя классами. Четыре SVM::C_SVC SVM были обучены (одна против покоя) с помощью auto_train. Оценка на трех разных ядрах (SVM::CHI2, SVM::INTER, SVM::RBF). Цвет изображает класс с максимальным баллом. Яркое означает максимальное количество баллов › 0, темное означает максимальное количество баллов ‹ 0.

Где я могу найти пример кода, который создает этот пример?

В частности, метод SVM predict() предположительно возвращает значение метки, а не максимальный балл. Как он может вернуть max-score?

введите здесь описание изображения

Обратите внимание, что в цитате указано, что используется SVM::C_SVC, который является типом классификации, а не регрессии.

22.10.2015

Ответы:


1

Вы можете получить оценку с помощью 2-классового SVM, и если вы передадите RAW_OUTPUT для прогнозирования:

// svm.cpp, SVMImpl::predict(...) , line 1917 
bool returnDFVal = (flags & RAW_OUTPUT) != 0;

// svm.cpp, PredictBody::operator(), line 1896,
float result = returnDFVal && class_count == 2 ?
                    (float)sum : (float)(svm->class_labels.at<int>(k));

Затем вам нужно тренировать 4 разных SVM 2 класса, один против остальных.

Вот результат, который я получаю на этих образцах:

введите здесь описание изображения

ИНТЕР с trainAuto

введите здесь описание изображения

CHI2 с trainAuto

введите здесь описание изображения

RBF с train (C = 0.1, gamma = 0.001) (в данном случае trainAuto накладывается)

введите здесь описание изображения

Вот код. Вы можете включить trainAuto с логической переменной AUTO_TRAIN_ENABLED, и вы можете установить KERNEL, а также размеры изображений и т. д.

#include <opencv2/opencv.hpp>
#include <vector>
#include <algorithm>
using namespace std;
using namespace cv;
using namespace cv::ml;

int main()
{
    const int WIDTH = 512;
    const int HEIGHT = 512;
    const int N_SAMPLES_PER_CLASS = 10;
    const float NON_LINEAR_SAMPLES_RATIO = 0.1;
    const int KERNEL = SVM::CHI2;
    const bool AUTO_TRAIN_ENABLED = false;


    int N_NON_LINEAR_SAMPLES = N_SAMPLES_PER_CLASS * NON_LINEAR_SAMPLES_RATIO;
    int N_LINEAR_SAMPLES = N_SAMPLES_PER_CLASS - N_NON_LINEAR_SAMPLES;



    vector<Scalar> colors{Scalar(255,0,0), Scalar(0,255,0), Scalar(0,0,255), Scalar(0,255,255)};
    vector<Vec3b> colorsv{ Vec3b(255, 0, 0), Vec3b(0, 255, 0), Vec3b(0, 0, 255), Vec3b(0, 255, 255) };
    vector<Vec3b> colorsv_shaded{ Vec3b(200, 0, 0), Vec3b(0, 200, 0), Vec3b(0, 0, 200), Vec3b(0, 200, 200) };

    Mat1f data(4 * N_SAMPLES_PER_CLASS, 2);
    Mat1i labels(4 * N_SAMPLES_PER_CLASS, 1);

    RNG rng(0);

    ////////////////////////
    // Set training data
    ////////////////////////

    // Class 1
    Mat1f class1 = data.rowRange(0, 0.5 * N_LINEAR_SAMPLES);
    Mat1f x1 = class1.colRange(0, 1);
    Mat1f y1 = class1.colRange(1, 2);
    rng.fill(x1, RNG::UNIFORM, Scalar(1), Scalar(WIDTH));
    rng.fill(y1, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT / 8));

    class1 = data.rowRange(0.5 * N_LINEAR_SAMPLES, 1 * N_LINEAR_SAMPLES);
    x1 = class1.colRange(0, 1);
    y1 = class1.colRange(1, 2);
    rng.fill(x1, RNG::UNIFORM, Scalar(1), Scalar(WIDTH));
    rng.fill(y1, RNG::UNIFORM, Scalar(7*HEIGHT / 8), Scalar(HEIGHT));

    class1 = data.rowRange(N_LINEAR_SAMPLES, 1 * N_SAMPLES_PER_CLASS);
    x1 = class1.colRange(0, 1);
    y1 = class1.colRange(1, 2);
    rng.fill(x1, RNG::UNIFORM, Scalar(1), Scalar(WIDTH));
    rng.fill(y1, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT));



    // Class 2
    Mat1f class2 = data.rowRange(N_SAMPLES_PER_CLASS, N_SAMPLES_PER_CLASS + N_LINEAR_SAMPLES);
    Mat1f x2 = class2.colRange(0, 1);
    Mat1f y2 = class2.colRange(1, 2);
    rng.fill(x2, RNG::NORMAL, Scalar(3 * WIDTH / 4), Scalar(WIDTH/16));
    rng.fill(y2, RNG::NORMAL, Scalar(HEIGHT / 2), Scalar(HEIGHT/4));

    class2 = data.rowRange(N_SAMPLES_PER_CLASS + N_LINEAR_SAMPLES, 2 * N_SAMPLES_PER_CLASS);
    x2 = class2.colRange(0, 1);
    y2 = class2.colRange(1, 2);
    rng.fill(x2, RNG::UNIFORM, Scalar(1), Scalar(WIDTH));
    rng.fill(y2, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT));



    // Class 3
    Mat1f class3 = data.rowRange(2 * N_SAMPLES_PER_CLASS, 2 * N_SAMPLES_PER_CLASS + N_LINEAR_SAMPLES);
    Mat1f x3 = class3.colRange(0, 1);
    Mat1f y3 = class3.colRange(1, 2);
    rng.fill(x3, RNG::NORMAL, Scalar(WIDTH / 4), Scalar(WIDTH/8));
    rng.fill(y3, RNG::NORMAL, Scalar(HEIGHT / 2), Scalar(HEIGHT/8));

    class3 = data.rowRange(2*N_SAMPLES_PER_CLASS + N_LINEAR_SAMPLES, 3 * N_SAMPLES_PER_CLASS);
    x3 = class3.colRange(0, 1);
    y3 = class3.colRange(1, 2);
    rng.fill(x3, RNG::UNIFORM, Scalar(1), Scalar(WIDTH));
    rng.fill(y3, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT));



    // Class 4
    Mat1f class4 = data.rowRange(3 * N_SAMPLES_PER_CLASS, 3 * N_SAMPLES_PER_CLASS + 0.5 * N_LINEAR_SAMPLES);
    Mat1f x4 = class4.colRange(0, 1);
    Mat1f y4 = class4.colRange(1, 2);
    rng.fill(x4, RNG::NORMAL, Scalar(WIDTH / 2), Scalar(WIDTH / 16));
    rng.fill(y4, RNG::NORMAL, Scalar(HEIGHT / 4), Scalar(HEIGHT / 16));

    class4 = data.rowRange(3 * N_SAMPLES_PER_CLASS + 0.5 * N_LINEAR_SAMPLES, 3 * N_SAMPLES_PER_CLASS + N_LINEAR_SAMPLES);
    x4 = class4.colRange(0, 1);
    y4 = class4.colRange(1, 2);
    rng.fill(x4, RNG::NORMAL, Scalar(WIDTH / 2), Scalar(WIDTH / 16));
    rng.fill(y4, RNG::NORMAL, Scalar(3 * HEIGHT / 4), Scalar(HEIGHT / 16));

    class4 = data.rowRange(3 * N_SAMPLES_PER_CLASS + N_LINEAR_SAMPLES, 4 * N_SAMPLES_PER_CLASS);
    x4 = class4.colRange(0, 1);
    y4 = class4.colRange(1, 2);
    rng.fill(x4, RNG::UNIFORM, Scalar(1), Scalar(WIDTH));
    rng.fill(y4, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT));



    // Labels
    labels.rowRange(0*N_SAMPLES_PER_CLASS, 1*N_SAMPLES_PER_CLASS).setTo(1);
    labels.rowRange(1*N_SAMPLES_PER_CLASS, 2*N_SAMPLES_PER_CLASS).setTo(2);
    labels.rowRange(2*N_SAMPLES_PER_CLASS, 3*N_SAMPLES_PER_CLASS).setTo(3);
    labels.rowRange(3*N_SAMPLES_PER_CLASS, 4*N_SAMPLES_PER_CLASS).setTo(4);



    // Draw training data
    Mat3b samples(HEIGHT, WIDTH, Vec3b(0,0,0));
    for (int i = 0; i < labels.rows; ++i)
    {
        circle(samples, Point(data(i, 0), data(i, 1)), 3, colors[labels(i,0) - 1], CV_FILLED);
    }



    //////////////////////////
    // SVM
    //////////////////////////

    // SVM label 1
    Ptr<SVM> svm1 = SVM::create();
    svm1->setType(SVM::C_SVC);
    svm1->setKernel(KERNEL);

    Mat1i labels1 = (labels != 1) / 255;

    if (AUTO_TRAIN_ENABLED)
    {
        Ptr<TrainData> td1 = TrainData::create(data, ROW_SAMPLE, labels1);
        svm1->trainAuto(td1);
    }
    else
    {
        svm1->setC(0.1);
        svm1->setGamma(0.001);
        svm1->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, (int)1e7, 1e-6));
        svm1->train(data, ROW_SAMPLE, labels1);
    }

    // SVM label 2
    Ptr<SVM> svm2 = SVM::create();
    svm2->setType(SVM::C_SVC);
    svm2->setKernel(KERNEL);

    Mat1i labels2 = (labels != 2) / 255;

    if (AUTO_TRAIN_ENABLED)
    {
        Ptr<TrainData> td2 = TrainData::create(data, ROW_SAMPLE, labels2);
        svm2->trainAuto(td2);
    }
    else
    {
        svm2->setC(0.1);
        svm2->setGamma(0.001);
        svm2->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, (int)1e7, 1e-6));
        svm2->train(data, ROW_SAMPLE, labels2);
    }

    // SVM label 3
    Ptr<SVM> svm3 = SVM::create();
    svm3->setType(SVM::C_SVC);
    svm3->setKernel(KERNEL);

    Mat1i labels3 = (labels != 3) / 255;

    if (AUTO_TRAIN_ENABLED)
    {
        Ptr<TrainData> td3 = TrainData::create(data, ROW_SAMPLE, labels3);
        svm3->trainAuto(td3);
    }
    else
    {
        svm3->setC(0.1);
        svm3->setGamma(0.001);
        svm3->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, (int)1e7, 1e-6));
        svm3->train(data, ROW_SAMPLE, labels3);
    }


    // SVM label 4
    Ptr<SVM> svm4 = SVM::create();
    svm4->setType(SVM::C_SVC);
    svm4->setKernel(KERNEL);

    Mat1i labels4 = (labels != 4) / 255;

    if (AUTO_TRAIN_ENABLED)
    {
        Ptr<TrainData> td4 = TrainData::create(data, ROW_SAMPLE, labels4);
        svm4->trainAuto(td4);
    }
    else
    {
        svm4->setC(0.1);
        svm4->setGamma(0.001);
        svm4->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, (int)1e7, 1e-6));
        svm4->train(data, ROW_SAMPLE, labels4);
    }



    //////////////////////////
    // Show regions
    //////////////////////////

    Mat3b regions(HEIGHT, WIDTH);
    Mat1f R(HEIGHT, WIDTH);

    Mat1f R1(HEIGHT, WIDTH);
    Mat1f R2(HEIGHT, WIDTH);
    Mat1f R3(HEIGHT, WIDTH);
    Mat1f R4(HEIGHT, WIDTH);


    for (int r = 0; r < HEIGHT; ++r)
    {
        for (int c = 0; c < WIDTH; ++c)
        {
            Mat1f sample = (Mat1f(1,2) << c, r);

            vector<float> responses(4);

            responses[0] = svm1->predict(sample, noArray(), StatModel::RAW_OUTPUT);
            responses[1] = svm2->predict(sample, noArray(), StatModel::RAW_OUTPUT);
            responses[2] = svm3->predict(sample, noArray(), StatModel::RAW_OUTPUT);
            responses[3] = svm4->predict(sample, noArray(), StatModel::RAW_OUTPUT);

            int best_class = distance(responses.begin(), max_element(responses.begin(), responses.end()));
            float best_response = responses[best_class];

            // View responses for each SVM, and the best responses
            R(r,c) = best_response;
            R1(r, c) = responses[0];
            R2(r, c) = responses[1];
            R3(r, c) = responses[2];
            R4(r, c) = responses[3];

            if (best_response >= 0) {
                regions(r, c) = colorsv[best_class];
            }
            else {
                regions(r, c) = colorsv_shaded[best_class];
            }


        }
    }


    imwrite("svm_samples.png", samples);
    imwrite("svm_x.png", regions);

    imshow("Samples", samples);
    imshow("Regions", regions);
    waitKey();

    return 0;
}
24.10.2015
  • Престижность за БОЛЬШОЙ ответ! Судя по фрагменту кода, он работает только для двухклассовых классификаторов. Интересный. 24.10.2015
  • @AdiShavit рад, что это помогло. Меня тоже это интересовало :D 24.10.2015
  • @Miki @Miki На самом деле требуется более 4 парных SVM, не так ли? Имеется N*(N-1)/2 = 6 для 4 классов: (1,2), (1,3), (1,4), (2,4), (3,4), (2, 3). Разве вам не пришлось бы классифицировать точку с помощью мультиклассового классификатора, а затем получить 4 парных SVM между этим классом и каждым другим классом, прежде чем выполнять процедуру, которую вы продемонстрировали? Кроме того, правильно ли я понимаю, что вы установили пороговое значение best_response равным 0, что указывает на уверенность в результате, если он больше 0? Является ли это значение расстоянием со знаком от гиперплоскости, разделяющей два класса? 14.01.2017
  • @David, это 4 svm 1 против всех. Почти ... это означает, что это не (скажем) класс 1, а один из трех других классов вместе, но ни один из других классов по отдельности не имеет лучшего ответа, чем класс 1. Вероятно, да, я на самом деле не помню. 14.01.2017
  • @Miki А, точно, теперь я слежу, спасибо. Я сделал этот пример более общим: gist.github.com/daviddoria/1725d6dfe1bf6ee2f951eb6ae9b6a973 14.01.2017
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..