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

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

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

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

Ирисы Фишера

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

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

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

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

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

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

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

features, labels = load_data("iris")
features = float.(features);
labels   = string.(labels);

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

plotlyjs();
iris = dataset("datasets", "iris");

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

first(iris[:,1:5],5)
5×5 DataFrame
 Row │ SepalLength  SepalWidth  PetalLength  PetalWidth  Species
     │ Float64      Float64     Float64      Float64     Cat…
─────┼───────────────────────────────────────────────────────────
   1 │         5.1         3.5          1.4         0.2  setosa
   2 │         4.9         3.0          1.4         0.2  setosa
   3 │         4.7         3.2          1.3         0.2  setosa
   4 │         4.6         3.1          1.5         0.2  setosa
   5 │         5.0         3.6          1.4         0.2  setosa

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

@df iris scatter(:SepalLength, :SepalWidth, group = :Species)

interactive-scripts/images/data_analysis_Classification_Algorithms/fe42df781facaaa9ff646a46adfeb78595d9e6a1

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

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);

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

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

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

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

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. Вычисление точности.

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

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

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

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

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

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

gr()
@df pred_df_NB scatter(:x1, :x2, group = :x3, markersize = 7)

interactive-scripts/images/data_analysis_Classification_Algorithms/326ed08f5d9aecdd218849decd4846e6d3f56459

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

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

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

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

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

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
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 конечных узлов. Чтобы определить вид наблюдаемого ириса, начните с верхнего условия и применяйте правила. Если наблюдение удовлетворяет правилу, вы выбираете верхнюю ветвь, а если нет, то выбираете нижнюю. В итоге вы достигнете конечного узла, который присвоит наблюдаемому экземпляру значение одного из трех видов.

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

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

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

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

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

@df pred_df_DT scatter(:x1, :x2, group = :x3, markersize = 7)

interactive-scripts/images/data_analysis_Classification_Algorithms/352533c83cdf9daf50025f17ed27c06b49a70afd

Вывод

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

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