Доброго времени суток! Речь пойдет о задаче классификации. А если быть точнее, то о способе оценить эффективность построенной модели, в частности, о методе перекрестной проверки. Что подразумевается под эффективностью? Конечно же, раз речь идет о классифицирующей модели, то оценивать нужно количество верных ответов.
Чем выше процент правильных ответов, тем больше вероятность, что модель адекватно себя поведет в «полевых условиях» — на реальных данных. Хорошо, когда размер обучающей выборки достаточно велик для того, чтобы выбрать оттуда процентов 30 элементов для тестирования. Но как быть, если данных для обучения очень мало?
На помощь приходит метод перекрестной проверки, в оригинале — Cross-validation.
Суть метода перекрестной проверки
Исходя из названия можно догадаться, что мы будем оперировать доступными ресурсами максимально эффективно, пытаясь их «перекрестить». То есть будем обучать модель на одних и тех же данных, но выкидывая каждый раз по кусочку, который будет использоваться для тестирования полученной модели. Перебрав все «кусочки» и посчитав средний процент отгадывания, мы получим наиболее достоверную оценку модели классификатора.
Всего существует два подхода к выбору размера «кусочка», остановимся на каждом подробнее.
Перекрестная проверка с проходом по одному
Самый простой и действенный метод, выкидываем каждый раз один объект, обучаем модель на остальных и тестируем. Преимущество в том, что используется максимально возможное количество как тестовых, так и обучающих данных, следовательно оценка максимально приближена к реальности.
Но есть существенный недостаток — метод требует больших вычислительных расходов, все таки приходится переобучать модель сколько раз, сколько элементов в обучающей выборке.
X-проходная перекрестная проверка
Этот подход был призван уменьшить вычислительные расходы. Суть в том, что обучающая выборка делится на X сбалансированных частей. Сбалансированность в том смысле, что не должно быть части, в которой какой-то класс сильно доминирует. Затем модель обучается X раз на выборке за исключением одной части. Далее по аналогии с первым методом, считается процент правильных ответов.
Как правило, на практике X = 5, деление на пять частей наиболее подходящий выбор в плане производительности и точности оценки.
Реализация метода перекрестной проверки на PHP
Чтобы не быть голословным, решил в качестве примера привести реализацию метода перекрестной проверки с проходом по одному. Это код из моего недавнего проекта, в нем используется метод опорных векторов из библиотеки PHP-ML. Можно примерно прикинуть, как осуществляется обход элементов обучающей выборки.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
function croosValidation($model) { //1) Вытащить из базы тренировочную выборку для обучения и для тестирования модели $mysqli = new mysqli('localhost', 'root', '', 'qiwi'); if($mysqli->connect_errno) { echo "Connection error: ".$mysqli->connect_error; } $mysqli->set_charset('utf8'); $in_res = $mysqli->query( 'select * from train_set order by class' ); if(!$in_res) { echo "Error in query: ".$mysqli->error; } //Формирование вектора признаков для метода опорных векторов $samples = array(); $labels = array(); while ($row = $in_res->fetch_assoc()) { $vector = array(); array_push($vector, $row['in_sum_val']); array_push($vector, $row['in_sum_rnd']); array_push($vector, $row['out_sum_val']); array_push($vector, $row['out_sum_rnd']); array_push($vector, $row['in_source']); array_push($vector, $row['out_dest']); array_push($vector, $row['in_freq']); array_push($vector, $row['out_freq']); array_push($vector, $row['in_com_type']); array_push($vector, $row['out_com_type']); array_push($samples, $vector); array_push($labels, $row['class']); } $mysqli->close(); //2) Обучить классификатор с помощью кросс валидации, так как данных слишком мало $count = count($samples); $correct = 0; //Количество отгаданных for ($i = 0; $i < $count; $i++) { //Обучающая выборка - все кроме i-го элемента $trainSet = array( 'samples' => array(), 'labels' => array()); $testElem = array('samples', 'labels'); for ($j = 0; $j < $count; $j++) { if ($j == $i) { $testElem['samples'] = $samples[$j]; $testElem['labels'] = $labels[$j]; } else { array_push($trainSet['samples'], $samples[$j]); array_push($trainSet['labels'], $labels[$j]); } } //Обучить классификатор $model->train($trainSet['samples'], $trainSet['labels']); //Предсказать $predict = $model->predict($testElem['samples']); //записать результат if ($predict == $testElem['labels']) { $correct++; } } //Посчитать процент правильных ответов $acc = round($correct / floatval($count), 2) * 100; return $acc; } |
Заключение
В заключении можно сказать, что метод перекрестной проверки здорово спасает в том случае, когда нельзя выделить достаточное количество элементов из обучающей выборки для теста. Как раз в моем проекте был такой случай. На этом у меня все, спасибо за внимание!