Классификация

Этот пример показывает, как выполнить классификацию с помощью дискриминантного анализа, наивных классификаторов Байеса и деревьев решений. Предположим, что у вас есть набор данных, содержащий наблюдения с измерениями на различных переменных (названный предикторами) и их известные метки класса. Если вы получаете значения предиктора для новых наблюдений, вы могли бы определить, которым классам, вероятно, принадлежат те наблюдения? Это - проблема классификации.

Ирисовые данные Фишера

Ирисовые данные Фишера состоят из измерений на длине чашелистика, ширине чашелистика, лепестковой длине и лепестковой ширине для 150 ирисовых экземпляров. Существует 50 экземпляров от каждой из трех разновидностей. Загрузите данные и смотрите, как измерения чашелистика отличаются между разновидностями. Можно использовать эти два столбца, содержащие измерения чашелистика.

load fisheriris
f = figure;
gscatter(meas(:,1), meas(:,2), species,'rgb','osd');
xlabel('Sepal length');
ylabel('Sepal width');
N = size(meas,1);

Предположим, что вы измеряете чашелистик и лепесток от ирисовой диафрагмы, и необходимо определить ее разновидности на основе тех измерений. Один подход к решению этой проблемы известен как дискриминантный анализ.

Линейный и квадратичный дискриминантный анализ

Функция fitcdiscr может выполнить классификацию с помощью различных типов дискриминантного анализа. Сначала классифицируйте данные с помощью линейного дискриминантного анализа (LDA) по умолчанию.

lda = fitcdiscr(meas(:,1:2),species);
ldaClass = resubPredict(lda);

Наблюдения с известными метками класса обычно называются данными тренировки. Теперь вычислите ошибку перезамены, которая является misclassification ошибкой (пропорция неправильно классифицированных наблюдений) на наборе обучающих данных.

ldaResubErr = resubLoss(lda)
ldaResubErr =

    0.2000

Можно также вычислить матрицу беспорядка на наборе обучающих данных. Матрица беспорядка содержит информацию об известных метках класса и предсказанных метках класса. Вообще говоря, (i, j) элемент в матрице беспорядка является количеством выборок, известная метка класса которых является классом i и чей предсказанный класс является j. Диагональные элементы представляют правильно классифицированные наблюдения.

figure
ldaResubCM = confusionchart(species,ldaClass);

Из 150 учебных наблюдений 20% или 30 наблюдений неправильно классифицируются линейной дискриминантной функцией. Вы видите, которые они рисунком X через неправильно классифицированные точки.

figure(f)
bad = ~strcmp(ldaClass,species);
hold on;
plot(meas(bad,1), meas(bad,2), 'kx');
hold off;

Функция разделила плоскость на области, разделенные на строки, и присвоила различные области различным разновидностям. Один способ визуализировать эти области состоит в том, чтобы создать сетку (x, y) значения и применить функцию классификации к той сетке.

[x,y] = meshgrid(4:.1:8,2:.1:4.5);
x = x(:);
y = y(:);
j = classify([x y],meas(:,1:2),species);
gscatter(x,y,j,'grb','sod')

Для некоторых наборов данных области для различных классов не хорошо разделяются строками. Когда это имеет место, линейный дискриминантный анализ не является соответствующим. Вместо этого можно попробовать квадратичный дискриминантный анализ (QDA) за наши данные.

Вычислите ошибку перезамены для квадратичного дискриминантного анализа.

qda = fitcdiscr(meas(:,1:2),species,'DiscrimType','quadratic');
qdaResubErr = resubLoss(qda)
qdaResubErr =

    0.2000

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

В этом случае у вас нет другого маркированного набора данных, но можно моделировать один путем выполнения перекрестной проверки. Стратифицированная 10-кратная перекрестная проверка является популярным выбором для оценки тестовой ошибки на алгоритмах классификации. Это случайным образом делит набор обучающих данных на 10 непересекающихся подмножеств. Каждое подмножество имеет примерно равный размер и примерно те же пропорции класса как в наборе обучающих данных. Удалите одно подмножество, обучите модель классификации использование других девяти подмножеств и используйте обученную модель, чтобы классифицировать удаленное подмножество. Вы могли повторить это путем удаления каждого из этих десяти подмножеств по одному.

Поскольку перекрестная проверка случайным образом делит данные, его результат зависит от начального случайного seed. Чтобы воспроизвести точные результаты в этом примере, выполните следующую команду:

rng(0,'twister');

Сначала используйте cvpartition, чтобы сгенерировать 10 непересекающихся стратифицированных подмножеств.

cp = cvpartition(species,'KFold',10)
cp = 

K-fold cross validation partition
   NumObservations: 150
       NumTestSets: 10
         TrainSize: 135  135  135  135  135  135  135  135  135  135
          TestSize: 15  15  15  15  15  15  15  15  15  15

crossval и методы kfoldLoss могут оценить misclassification ошибку и для LDA и для QDA использование раздела определенных данных cp.

Оцените истинную тестовую ошибку для LDA использование 10-кратной стратифицированной перекрестной проверки.

cvlda = crossval(lda,'CVPartition',cp);
ldaCVErr = kfoldLoss(cvlda)
ldaCVErr =

    0.2000

Ошибка перекрестной проверки LDA имеет то же значение как ошибка перезамены LDA на этих данных.

Оцените истинную тестовую ошибку для QDA использование 10-кратной стратифицированной перекрестной проверки.

cvqda = crossval(qda,'CVPartition',cp);
qdaCVErr = kfoldLoss(cvqda)
qdaCVErr =

    0.2200

QDA имеет немного большую ошибку перекрестной проверки, чем LDA. Это показывает, что более простая модель может получить сопоставимую, или лучшую производительность, чем более сложная модель.

Наивные классификаторы Байеса

Функция fitcdiscr имеет другие два других типа, 'DiagLinear' и 'DiagQuadratic'. Они подобны 'линейному' и 'квадратичному', но с диагональными оценками ковариационной матрицы. Этим диагональным выбором являются определенные примеры наивного классификатора Байеса, потому что они принимают, что переменные условно независимы, учитывая метку класса. Наивные классификаторы Байеса среди самых популярных классификаторов. В то время как предположение об условной согласно классу независимости между переменными не верно в целом, наивные классификаторы Байеса, как находили, работали хорошо на практике над многими наборами данных.

Функция fitcnb может использоваться, чтобы создать более общий тип наивного классификатора Байеса.

Первая модель каждая переменная в каждом классе с помощью Распределения Гаусса. Можно вычислить ошибку перезамены и ошибку перекрестной проверки.

nbGau = fitcnb(meas(:,1:2), species);
nbGauResubErr = resubLoss(nbGau)
nbGauCV = crossval(nbGau, 'CVPartition',cp);
nbGauCVErr = kfoldLoss(nbGauCV)

labels = predict(nbGau, [x y]);
gscatter(x,y,labels,'grb','sod')
nbGauResubErr =

    0.2200


nbGauCVErr =

    0.2200

До сих пор вы приняли, что переменные из каждого класса имеют многомерное нормальное распределение. Часто это - разумное предположение, но иногда вы не можете быть готовы сделать то предположение, или можно видеть ясно, что это не допустимо. Теперь попытайтесь смоделировать каждую переменную в каждом классе с помощью оценки плотности ядра, которая является более гибким непараметрическим методом. Здесь мы устанавливаем ядро на box.

nbKD = fitcnb(meas(:,1:2), species, 'DistributionNames','kernel', 'Kernel','box');
nbKDResubErr = resubLoss(nbKD)
nbKDCV = crossval(nbKD, 'CVPartition',cp);
nbKDCVErr = kfoldLoss(nbKDCV)

labels = predict(nbKD, [x y]);
gscatter(x,y,labels,'rgb','osd')
nbKDResubErr =

    0.2067


nbKDCVErr =

    0.2133

Для этого набора данных наивный классификатор Байеса с оценкой плотности ядра получает меньшую ошибку перезамены и ошибку перекрестной проверки, чем наивный классификатор Байеса с Распределением Гаусса.

Дерево решений

Другой алгоритм классификации основан на дереве решений. Дерево решений является набором простых правил, такой как, "если длина чашелистика - меньше чем 5,45, классифицируйте экземпляр как setosa". Деревья решений являются также непараметрическими, потому что они не требуют никаких предположений о распределении переменных в каждом классе.

Функция fitctree создает дерево решений. Создайте дерево решений для ирисовых данных и смотрите, как хорошо они классифицируют ирисовые диафрагмы в разновидности.

t = fitctree(meas(:,1:2), species,'PredictorNames',{'SL' 'SW' });

Интересно, чтобы видеть, как метод дерева решений делит плоскость. Используйте тот же метод как выше, чтобы визуализировать области, присвоенные каждой разновидности.

[grpname,node] = predict(t,[x y]);
gscatter(x,y,grpname,'grb','sod')

Другой способ визуализировать дерево решений состоит в том, чтобы чертить схему правила решения и присвоений класса.

view(t,'Mode','graph');

Это выглядящее словно нарушенное дерево использует ряд правил формы "SL <5.45", чтобы классифицировать каждый экземпляр в один из 19 терминальных узлов. Чтобы определить присвоение разновидностей для наблюдения, запустите в главном узле и примените правило. Если точка удовлетворяет правило, вы выбираете левое путь, и если не вы выбираете право путь. В конечном счете вы достигаете терминального узла, который присваивает наблюдение одной из трех разновидностей.

Вычислите ошибку перезамены и ошибку перекрестной проверки для дерева решений.

dtResubErr = resubLoss(t)

cvt = crossval(t,'CVPartition',cp);
dtCVErr = kfoldLoss(cvt)
dtResubErr =

    0.1333


dtCVErr =

    0.3067

Для алгоритма дерева решений ошибочная оценка перекрестной проверки значительно больше, чем ошибка перезамены. Это показывает, что сгенерированное дерево сверхсоответствует набору обучающих данных. Другими словами, это - дерево, которое классифицирует исходный набор обучающих данных хорошо, но структура дерева чувствительна к этому конкретному набору обучающих данных так, чтобы его производительность на новых данных, вероятно, ухудшилась. Часто возможно найти более простое дерево, которое выполняет лучше, чем более комплексное дерево на новых данных.

Попытайтесь сократить дерево. Сначала вычислите ошибку перезамены для различных подмножеств исходного дерева. Затем вычислите ошибку перекрестной проверки для этих поддеревьев. График показывает, что ошибка перезамены чрезмерно оптимистична. Это всегда уменьшается, когда древовидный размер растет, но после определенного предела, увеличивание древовидного размера увеличивает коэффициент ошибок перекрестной проверки.

resubcost = resubLoss(t,'Subtrees','all');
[cost,secost,ntermnodes,bestlevel] = cvloss(t,'Subtrees','all');
plot(ntermnodes,cost,'b-', ntermnodes,resubcost,'r--')
figure(gcf);
xlabel('Number of terminal nodes');
ylabel('Cost (misclassification error)')
legend('Cross-validation','Resubstitution')

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

Можно показать это на графике путем вычисления значения сокращения, которое равно минимальным издержкам плюс одна стандартная погрешность. "Лучший" уровень, вычисленный методом cvloss, является самым маленьким деревом при этом сокращении. (Обратите внимание на то, что bestlevel=0 соответствует несокращенному дереву, таким образом, необходимо добавить 1, чтобы использовать его в качестве индекса в векторные выходные параметры от cvloss.)

[mincost,minloc] = min(cost);
cutoff = mincost + secost(minloc);
hold on
plot([0 20], [cutoff cutoff], 'k:')
plot(ntermnodes(bestlevel+1), cost(bestlevel+1), 'mo')
legend('Cross-validation','Resubstitution','Min + 1 std. err.','Best choice')
hold off

Наконец, можно посмотреть на сокращенное дерево и вычислить предполагаемую misclassification ошибку для него.

pt = prune(t,'Level',bestlevel);
view(pt,'Mode','graph')

cost(bestlevel+1)
ans =

    0.2467

Заключения

Этот пример показывает, как выполнить классификацию в MATLAB® с помощью функций Statistics and Machine Learning Toolbox™.

Этот пример не предназначен, чтобы быть идеальным анализом ирисовых данных Фишера, На самом деле, с помощью лепестковых измерений вместо, или в дополнение к, измерения чашелистика могут привести к лучшей классификации. Кроме того, этот пример не предназначен, чтобы сравнить достоинства и недостатки различных алгоритмов классификации. Можно найти его поучительным, чтобы выполнить анализ других наборов данных и сравнить различные алгоритмы. Существуют также функции Тулбокса, которые реализуют другие алгоритмы классификации. Например, можно использовать TreeBagger, чтобы выполнить агрегацию начальной загрузки для ансамбля деревьев решений, как описано в Агрегации Начальной загрузки в качестве примера (Укладывание в мешки) Деревьев Классификации Используя TreeBagger.