Новосибирский Государственный Университет
Опубликован: 20.08.2013 | Доступ: свободный | Студентов: 861 / 36 | Длительность: 14:11:00
Самостоятельная работа 3:

Машинное обучение

2.2. Машина опорных векторов

Пусть \mathbb{Y} = \{1,-1\}, т.е. рассматривается задача бинарной классификации. Идея алгоритма машины опорных векторов (Support Vector Machine, SVM) заключается в построении оптимальной поверхности \beta h(x) + \beta_{0} = 0, представляющей собой гиперплоскость в спрямляющем пространстве \mathbb{H}=h(\mathbb{X}) (см. лекционную часть курса), разделяющей точки x^{(i)} различных классов из обучающей выборки. Фактически, обучение алгоритмом опорных векторов заключается в решении оптимизационной задачи

\min_{\beta,\beta_{0},\zeta}\frac{1}{2}\parallel \beta\parallel + C \sum_{i=1}^{N} \zeta_{i},

при ограничениях

y^{(i)}\left(\beta h \left(x^{(i)}\right) + \beta_{0} \right) \geq 1-\zeta_{i}, \zeta_{i} \geq 0, \;\;\; i=\overline{1,N},

где отображение h:\mathbb{X} \rightarrow \mathbb{H} задает переход в спрямляющее пространство, C \geq 0 – параметр алгоритма обучения, регулирующий величину штрафа за то, что некоторые точки выходят за границу разделяющей полосы -1 \leq \betah(x) + \beta_{0} \leq 1. При этом отображение h может быть задано неявно с помощью, так называемого, ядра K(x,x')=h(x)h(x').Решающая функция запишется в виде f(x) = sign(h(x)\beta + \beta_{0}) = sign(\sum_{i=1}^{N}{\alpha_{i}y^{(i)}K(x^{(i)},x)+\beta_{0}}. Данная функция зависит от некоторых точек x^{(i)} из обучающей выборки, называемых опорными векторами.

Данный метод применим для решения задач классификации, но также может быть обобщен на случай регрессии [ 1 ], однако, подробное изложение регрессионного алгоритма выходит за рамки данной лабораторной работы. Также, несмотря на то, что выше описывался алгоритм бинарной классификации с использованием машины опорных векторов, данный метод легко обобщается на случай произвольного количества классов с помощью универсальных подходов "один против всех" или "каждый против каждого", тем самым сводясь к решению нескольких задач классификации с двумя классами. Машина опорных векторов как для классификации, так и для восстановления регрессии работает лишь с количественными признаками и не допускает наличия пропущенных значений.

Функционал, связанный с обучением машины опорных векторов, ее сохранением/загрузкой и использованием обученной модели для осуществления предсказаний реализован в классе CvSVM, как и все реализации алгоритмов обучения с учителем в библиотеке, унаследованном от класса CvStatModel. Остановимся подробнее на описании данного класса.

Для обучения машины опорных векторов служит метод train.

bool CvSVM::train(const Mat& trainData, 
      const Mat& responses, 
      const Mat& varIdx=Mat(), 
      const Mat& sampleIdx=Mat(), 
      CvSVMParams params=CvSVMParams()); 
    

Параметры:

  • trainData – матрица, содержащая векторы x^{(i)} из обучающей выборки. Матрица должна иметь тип CV_32F и размеры n \times d, таким образом, храня в i-й строке координаты вектора x^{(i)}.
  • responses – матрица-вектор, содержащая значения целевой переменной y^{(i)} для прецедентов обучающей выборки. Данная матрица должна иметь тип CV_32S или CV_32F и размеры 1 \times n или n \times 1.
  • varIdx – матрица-вектор, содержащая либо номера признаков (тип матрицы CV_32S), которые необходимо использовать при обучении, либо маску (тип матрицы CV_8U) размера 1 \times d, где единицами отмечены используемые признаки, нулями – игнорируемые. По умолчанию (varIdx=Mat()) используются все признаки.
  • sampleIdx – матрица-вектор, имеющая такой же формат, как и varIdx, но отвечающая за прецеденты выборки, которые необходимо использовать для обучения. По умолчанию используются все имеющиеся прецеденты.
  • params – параметры алгоритма обучения.

Для представления параметров SVM в OpenCV используется структура CvSVMParams.

struct CvSVMParams 
{ 
  CvSVMParams(); 
  CvSVMParams( int svm_type, 
      int kernel_type, 
      double degree, 
      double gamma, 
      double coef0, 
      double Cvalue, 
      double nu, 
      double p, 
      CvMat* class_weights, 
      CvTermCriteria term_crit ); 
 
  int   svm_type; 
  int   kernel_type; 
  double   degree; 
  double  gamma; 
  double  coef0; 
 
  double  C; 
  double  nu; 
  double  p; 
  CvMat*   class_weights; 
  CvTermCriteria term_crit; 
}; 
    

Рассмотрим поля данной структуры.

Поле svm_type отвечает за тип используемой машины опорных векторов. Возможные значения данной переменной описаны перечислением в классе CvSVM:

enum {C_SVC=100, NU_SVC=101, ONE_CLASS=102, EPS_SVR=103, 
NU_SVR=104}; 
    

C_SVC и NU_SVC обозначают различные модификации SVM для классификации, в то время как EPS_SVR и NU_SVR представляют собой формализации для регрессии. Машина опорных векторов типа ONE_CLASS строит границу области, в которой расположены точки одного единственного класса. Описанная выше задача оптимизации соответствует типу C_SVC (формализации с использованием параметра C). SVM типа NU_SVC решает схожую, но другую задачу с параметром v \in [0,1], являющимся нижней оценкой на долю опорных векторов в обучающей выборке и верхней границей доли неправильно классифицированных прецедентов обучающей выборки.

Поле kernel_type структуры CvSVMParams служит для обозначения используемого ядра. Возможные значения данной переменной также описаны в перечислении класса CvSVM:

enum { LINEAR=0, POLY=1, RBF=2, SIGMOID=3 }; 
    

В библиотеке OpenCV реализована непосредственная поддержка следующих ядер:

  • линейное ядро (LINEAR): K(x,x')=xx';
  • многочлен степени d (POLY): K(x,x')=(\gamma_{0} + \gamma xx')^{d}, \gamma >;
  • радиальная функция (RBF): K(x,x')=e^{-\gamma \parallel x-x' \parallel^2}, \gamma > 0 ;
  • сигмоидальная функция (SIGMOID): K(x,x')=tanh(\gamma_{0} + \gammaxx').

Далее в структуре CvSVMParams идут параметры ядер: degree соответствует степени многочлена, определяющего полиномиальное ядро, gamma – параметру \gamma в полиномиальном, радиальном и сигмоидальном ядрах, coef0 – параметру \gamma_{0} в полиномиальном и сигмоидальном ядрах. При использовании ядра, не имеющего того или иного параметра, значение, хранящееся в соответствующем поле структуры, игнорируется и может быть любым.

Поля C, nu и p соответствуют параметрам оптимизационных задач, решаемых алгоритмом обучения. Тип используемой машины опорных векторов указывает на то, какой из этих параметров "активен": C используется совместно с C_SVC, EPS_SVR и NU_SVR; nu – с NU_SVC, NU_SVR и ONE_CLASS; p – с EPS_SVR.

Поле class_weights предназначено для хранения матрицы-вектора, содержащей веса различных классов и может использоваться с машиной опорных векторов типа C_SVC, позволяя определить различные значения параметра C для точек разных классов. Как отмечалось выше, решение задачи классификации более чем на два класса сводится к серии задач бинарной классификации. В CvSVM реализован подход "каждый против каждого". Таким образом, при решении задачи разделения точек классов k_{1} и k_{2} решается задача

\min_{\beta,\beta_{0},\zeta}\frac{1}{2}\parallel \beta\parallel + class\_weights[k_{1}] \cdot C \sum_{i:y_{i}=k_{1}} \zeta_{i} + class\_weights[k_{2}] \cdot C \sum_{i:y_{i}=k_{2}} \zeta_{i}.

Данный параметр может быть полезен при несбалансированной обучающей выборке, содержащей малое количество прецедентов одного класса и большое количество другого. Чем больше вес, тем больший штраф назначается за неправильную классификацию обучающего прецедента этого класса. По умолчанию (class_weights = NULL) все веса равны.

Последним нерассмотренным полем структуры CvSVMParams является term_crit. Данная переменная содержит параметры итерационного метода, используемого для решения оптимизационной задачи на этапе обучения. Данные параметры указываются с помощью следующей структуры:

struct CvTermCriteria 
{ 
  int    type; 
  int    max_iter; 
  double  epsilon; 
}; 
    

Рассмотрим поля данной структуры:

  • type – вид критерия останова: по точности (CV_TERMCRIT_EPS) или по количеству итераций (CV_TERMCRIT_ITER). Значение type, равное CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, применяется в случае, когда используются оба критерия.
  • max_iter – максимальное количество итераций.
  • epsilon – пороговое значение точности.

Для использования обученной ранее модели в классе CvSVM используются методы

float predict( const Mat& sample, 
    bool returnDFVal=false ) const; 
void predict( InputArray samples, 
    OutputArray results ) const; 
    

Рассмотрим их параметры.

  • sample – матрица-вектор типа CV_32F и размера 1 \times d, содержащая координаты одной точки в пространстве признаков.
  • returnDFVal – флаг, позволяющий получать расстояние со знаком от разделяющей поверхности до указанной точки. Если returnDFVal=true и решается задача бинарной классификации, то возвращаемым значением будет величина h(x)\beta + \beta_{0}, иначе будет возвращено предсказанное значение целевого признака.
  • samples – матрица типа CV_32F и размера n_{1} \times d, построчно содержащая координаты точек в пространстве признаков, для которых необходимо сделать предсказания.
  • results – матрица-вектор, в которую будут сохранены предсказанные значения.

Для сохранения обученной модели используется метод

void save( const char* filename, 
    const char* name=0 ) const; 
    

Параметры данного метода:

  • filename – путь и имя файла, в который будет сохранена модель. В OpenCV поддерживается запись в XML- и YAML-файлы.
  • name – имя, под которым будет сохранена модель. Имя модели может состоять из строчных и заглавных букв латинского алфавита, цифр, символов "-" и "_". В случае сохранения в YAML-формате также допустимо использование пробелов.

Загрузка модели из файла осуществляется методом

void load( const char* filename, const char* name=0 ); 
    

Рассмотрим его параметры:

  • filename – XML- или YAML-файл, из которого будет выполнена загрузка.
  • name – имя модели, которую требуется загрузить.

Также в классе CvSVM реализован метод, позволяющий получить количество опорных векторов:

int get_support_vector_count() const; 
    

и метод для получения опорного вектора с номером i:

const float* get_support_vector(int i) const; 
    
Александра Максимова
Александра Максимова

При прохождении теста 1 в нем оказались вопросы, который во-первых в 1 лекции не рассматривались, во-вторых, оказалось, что вопрос был рассмаотрен в самостоятельно работе №2. Это значит, что их нужно выполнить перед прохождением теста? или это ошибка?
 

Алена Борисова
Алена Борисова

В лекции по обработке полутоновых изображений (http://www.intuit.ru/studies/courses/10621/1105/lecture/17979?page=2) увидела следующий фильтр:


    \begin{array}{|c|c|c|}
    \hline \\
    0 & 0 & 0 \\
    \hline \\
    0 & 2 & 0 \\
    \hline \\
    0 & 0 & 0 \\
    \hline 
    \end{array} - \frac{1}{9} \begin{array}{|c|c|c|}
    \hline \\
    0 & 0 & 0 \\
    \hline \\
    0 & 1 & 0 \\
    \hline \\
    0 & 0 & 0 \\
    \hline 
    \end{array}

В описании говорится, что он "делает изображение более чётким, потому что, как видно из конструкции фильтра, в однородных частях изображение не изменяется, а в местах изменения яркости это изменение усиливается".

Что вижу я в конструкции фильтра (скорее всего ошибочно): F(x, y) = 2 * I(x, y) - 1/9 I(x, y) = 17/9 * I(x, y), где F(x, y) - яркость отфильтрованного пикселя, а I(x, y) - яркость исходного пикселя с координатами (x, y). Что означает обычное повышение яркости изображения, при этом без учета соседних пикселей (так как их множители равны 0).

Объясните, пожалуйста, как данный фильтр может повышать четкость изображения?