Документация Engee
Notebook

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

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

Для запуска этой демонстрации требуется подключение к интернету

Ирисы Фишера

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

Загрузка библиотек для статистического анализа

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

In [ ]:
Pkg.add("DecisionTree")#загрузка библиотеки решающих деревьев
Pkg.add("NaiveBayes")#загрузка библиотеки с Баесовскими классификаторами
Pkg.add("StatsBase")#для использования predict в баесовском классификаторе
Pkg.add("StatsPlots")#для построения точечных графиков

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

In [ ]:
using NaiveBayes
using RDatasets
using StatsBase
using Random
using StatsPlots
using Plots, RDatasets
using DecisionTree
using ScikitLearn: fit!, predict
using ScikitLearn.CrossValidation: cross_val_score

Формирование матриц предикторов и набора меток классов.

In [ ]:
features, labels = load_data("iris")
features = float.(features);
labels   = string.(labels);

Подключение метода библиотеки Plots для отображения графиков, а также определение датасета для отображения распределения наблюдений по ширине и длине чашелистика (SepalWidth, SepalLength).

In [ ]:
plotlyjs();
iris = dataset("datasets", "iris");

Набор данных с предикторами и классами.

In [ ]:
first(iris[:,1:5],5)
Out[0]:

5 rows × 5 columns

SepalLengthSepalWidthPetalLengthPetalWidthSpecies
Float64Float64Float64Float64Cat…
15.13.51.40.2setosa
24.93.01.40.2setosa
34.73.21.30.2setosa
44.63.11.50.2setosa
55.03.61.40.2setosa

График распределения наблюдений по ширине и длине чашелистика.

In [ ]:
@df iris scatter(:SepalLength, :SepalWidth, group = :Species)
Out[0]:

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

In [ ]:
h = 10000;
x1 = rand(4:0.1:8, h)
x1t = x1'
x2 = rand(2:0.1:4.5, h)
x2t = x2'
x12 = vcat(x1t,x2t);

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

Наивный Баесовский классификатор - простой вероятностный классификатор, основанный на применении теоремы Байеса со строгими (наивными) предположениями о независимости.

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

Предобработка данных для использования в обучении модели Баесовского классификатора.

In [ ]:
Xx = Matrix(iris[:,1:2])';#features';#
Yy = [species for species in iris[:, 5]];#labels;
p, n = size(Xx)
train_frac = 0.8
k = floor(Int, train_frac * n)
idxs = randperm(n)
train_idxs = idxs[1:k];
test_idxs = idxs[k+1:end];

Определение структуры модели методом GaussianNB и её обучение методом fit. Вычисление точности.

In [ ]:
modelNB = GaussianNB(unique(Yy), p)
fit(modelNB, Xx[:, train_idxs], Yy[train_idxs])
accuracyNB = count(!iszero, StatsBase.predict(modelNB, Xx[:,test_idxs]) .== Yy[test_idxs]) / count(!iszero, test_idxs)
println("Accuracy: $accuracyNB")
Accuracy: 0.7333333333333333

Формирование матрицы прогнозов для новых наблюдений.

In [ ]:
predNB = fill("", 0);#Определение пустого массива
predNB = (NaiveBayes.predict(modelNB, x12[:,1:h]));#наполнение массива значениями предсказаний

Формирование матрицы предиктор-прогноз для новых наблюдений.

In [ ]:
x_pred_NB = hcat(x12',predNB);
pred_df_NB = DataFrame(x_pred_NB,:auto);

Отображение разделения классификатором поля предикторов на классы, соответствующие видам ирисов.

In [ ]:
gr()
@df pred_df_NB scatter(:x1, :x2, group = :x3, markersize = 7)
Out[0]:

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

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

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

Определение структуры модели методом DecisionTreeClassifier и её обучение методом fit!. Вычисление точности с помощью кросс-валидации.

Отображение дерева решений.

In [ ]:
modelDT = DecisionTreeClassifier(max_depth=10)#определение структуры модели
fit!(modelDT, features[:,1:2], labels)#обучение модели
print_tree(modelDT, 5)#отображение дерева решений
accuracy = cross_val_score(modelDT, features[:,1:2], labels, cv=8)#вычисление точности
Feature 1 < 5.55 ?
├─ Feature 2 < 2.8 ?
    ├─ Feature 1 < 4.95 ?
        ├─ Feature 2 < 2.35 ?
            ├─ Iris-setosa : 1/1
            └─ Feature 2 < 2.45 ?
                ├─ Iris-versicolor : 1/1
                └─ Iris-virginica : 1/1
        └─ Iris-versicolor : 9/9
    └─ Feature 1 < 5.35 ?
        ├─ Iris-setosa : 39/39
        └─ Feature 2 < 3.2 ?
            ├─ Iris-versicolor : 1/1
            └─ Iris-setosa : 7/7
└─ Feature 2 < 3.7 ?
    ├─ Feature 1 < 6.25 ?
        ├─ Feature 1 < 5.75 ?
            ├─ Feature 2 < 2.85 ?
                ├─ 
                └─ Iris-versicolor : 5/5
            └─ Feature 2 < 2.95 ?
                ├─ 
                └─ 
        └─ Feature 1 < 7.05 ?
            ├─ Feature 2 < 2.4 ?
                ├─ Iris-versicolor : 1/1
                └─ 
            └─ Iris-virginica : 10/10
    └─ Feature 1 < 6.75 ?
        ├─ Iris-setosa : 3/3
        └─ Iris-virginica : 2/2
Out[0]:
8-element Vector{Float64}:
 0.6190476190476191
 0.7619047619047619
 0.5
 0.7222222222222222
 0.7222222222222222
 0.7222222222222222
 0.7777777777777778
 0.7222222222222222

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

Формирование матрицы прогнозов для новых наблюдений.

In [ ]:
predDT = fill("", 0);#определение массива 
#формирование матрицы значение-прогноз для решающего дерева
for i in 1:h
    predDT = vcat(predDT, predict(modelDT, x12[:,i]))
end

Формирование матрицы предиктор-прогноз для новых наблюдений.

In [ ]:
x_pred_DT = hcat(x12',predDT);
pred_df_DT = DataFrame(x_pred_DT,:auto);

Отображение разделения классификатором поля предикторов на классы, соответствующие видам ирисов.

In [ ]:
@df pred_df_DT scatter(:x1, :x2, group = :x3, markersize = 7)
Out[0]:

Вывод

В данном примере была решена задача классификации с использованием наивного байесовского классификатора и дерева решений. Было продемонстрировано использование библиотек DecisionTree и NaiveBayes. С их помощью осуществлялось обучение классификаторов.

Классификаторы, в свою очередь, при достаточно малом наборе данных, показали хорошую точность и разделили поле предикторов на классы.