2026-03-24 14:26:08 +03:00
|
|
|
|
// Задача с концентрическими окружностями (MakeCircles).
|
|
|
|
|
|
// Классы вложены друг в друга, поэтому линейная разделяющая
|
|
|
|
|
|
// граница в принципе невозможна.
|
|
|
|
|
|
//
|
|
|
|
|
|
// LogisticRegression строит только линейную границу,
|
|
|
|
|
|
// поэтому полностью проваливается (сильное недообучение).
|
|
|
|
|
|
//
|
|
|
|
|
|
// DecisionTree способен моделировать нелинейную структуру,
|
|
|
|
|
|
// но делает это через разбиения по осям, из-за чего граница
|
|
|
|
|
|
// получается рваной и переобученной.
|
|
|
|
|
|
//
|
|
|
|
|
|
// RandomForest усредняет множество деревьев,
|
|
|
|
|
|
// сглаживает границу и даёт более устойчивый результат.
|
|
|
|
|
|
//
|
|
|
|
|
|
// KNNClassifier показывает лучший результат,
|
|
|
|
|
|
// так как является локальной моделью и хорошо восстанавливает
|
|
|
|
|
|
// форму вложенных областей.
|
|
|
|
|
|
//
|
|
|
|
|
|
// Визуализация наглядно показывает различия:
|
|
|
|
|
|
// • Logistic — почти прямая граница (не подходит)
|
|
|
|
|
|
// • Tree — "ступенчатая" структура (переобучение)
|
|
|
|
|
|
// • Forest — сглаженная версия дерева
|
|
|
|
|
|
// • KNN — наиболее близкая к истинной геометрии граница
|
|
|
|
|
|
uses MLABC, PlotML;
|
|
|
|
|
|
|
|
|
|
|
|
begin
|
|
|
|
|
|
// --- данные
|
|
|
|
|
|
var (X, y) := Datasets.MakeCircles(
|
|
|
|
|
|
n := 400,
|
|
|
|
|
|
noise := 0.2,
|
|
|
|
|
|
factor := 0.5,
|
|
|
|
|
|
classBalance := 0.5,
|
|
|
|
|
|
flipProb := 0.05,
|
|
|
|
|
|
scale := 3.0,
|
|
|
|
|
|
shuffle := True,
|
|
|
|
|
|
seed := 1
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
var (XTrain, XTest, yTrain, yTest) :=
|
|
|
|
|
|
Validation.TrainTestSplit(X, y, testRatio := 0.3, seed := 1);
|
|
|
|
|
|
|
|
|
|
|
|
// --- модели
|
|
|
|
|
|
var logreg := new LogisticRegression;
|
|
|
|
|
|
logreg.Fit(XTrain, yTrain);
|
|
|
|
|
|
|
|
|
|
|
|
var tree := new DecisionTreeClassifier(seed := 1);
|
|
|
|
|
|
tree.Fit(XTrain, yTrain);
|
|
|
|
|
|
|
|
|
|
|
|
var rf := new RandomForestClassifier(100, seed := 1);
|
|
|
|
|
|
rf.Fit(XTrain, yTrain);
|
|
|
|
|
|
|
|
|
|
|
|
var knn := new KNNClassifier(5);
|
|
|
|
|
|
knn.Fit(XTrain, yTrain);
|
|
|
|
|
|
|
|
|
|
|
|
// --- метрики
|
2026-05-28 10:23:22 +03:00
|
|
|
|
var accLR := Metrics.Accuracy(yTest, logreg.Predict(XTest));
|
|
|
|
|
|
var accTree := Metrics.Accuracy(yTest, tree.Predict(XTest));
|
|
|
|
|
|
var accRF := Metrics.Accuracy(yTest, rf.Predict(XTest));
|
|
|
|
|
|
var accKNN := Metrics.Accuracy(yTest, knn.Predict(XTest));
|
2026-03-24 14:26:08 +03:00
|
|
|
|
|
|
|
|
|
|
Println('--- Circles ---');
|
|
|
|
|
|
Println($'Logistic Acc: {accLR,0:F4}');
|
|
|
|
|
|
Println($'Tree Acc: {accTree,0:F4}');
|
|
|
|
|
|
Println($'Forest Acc: {accRF,0:F4}');
|
|
|
|
|
|
Println($'KNN Acc: {accKNN,0:F4}');
|
|
|
|
|
|
|
|
|
|
|
|
// --- данные для визуализации
|
|
|
|
|
|
var x1 := X.Col(0);
|
|
|
|
|
|
var x2 := X.Col(1);
|
2026-05-28 10:23:22 +03:00
|
|
|
|
var yArr := y;
|
2026-03-24 14:26:08 +03:00
|
|
|
|
|
|
|
|
|
|
var nx := 80;
|
|
|
|
|
|
var ny := 80;
|
|
|
|
|
|
|
|
|
|
|
|
// --- визуализация
|
|
|
|
|
|
var fig := Plot.Grid(2, 2);
|
|
|
|
|
|
|
|
|
|
|
|
// Logistic
|
2026-05-28 10:23:22 +03:00
|
|
|
|
fig[0,0].Surface(x1, x2, nx, ny, G -> logreg.Predict(G),Palettes.Pastel);
|
2026-03-24 14:26:08 +03:00
|
|
|
|
fig[0,0].Points(x1, x2, yArr, size := 6);
|
|
|
|
|
|
fig[0,0].Title := $'Logistic (acc={accLR,0:F3})';
|
|
|
|
|
|
|
|
|
|
|
|
// Tree
|
2026-05-28 10:23:22 +03:00
|
|
|
|
fig[0,1].Surface(x1, x2, nx, ny, G -> tree.Predict(G), Palettes.Pastel);
|
2026-03-24 14:26:08 +03:00
|
|
|
|
fig[0,1].Points(x1, x2, yArr, size := 6);
|
|
|
|
|
|
fig[0,1].Title := $'Tree (acc={accTree,0:F3})';
|
|
|
|
|
|
|
|
|
|
|
|
// Forest
|
2026-05-28 10:23:22 +03:00
|
|
|
|
fig[1,0].Surface(x1, x2, nx, ny, G -> rf.Predict(G), Palettes.Pastel);
|
2026-03-24 14:26:08 +03:00
|
|
|
|
fig[1,0].Points(x1, x2, yArr, size := 6);
|
|
|
|
|
|
fig[1,0].Title := $'Forest (acc={accRF,0:F3})';
|
|
|
|
|
|
|
|
|
|
|
|
// KNN
|
2026-05-28 10:23:22 +03:00
|
|
|
|
fig[1,1].Surface(x1, x2, nx, ny, G -> knn.Predict(G), Palettes.Pastel);
|
2026-03-24 14:26:08 +03:00
|
|
|
|
fig[1,1].Points(x1, x2, yArr, size := 6);
|
|
|
|
|
|
fig[1,1].Title := $'KNN (acc={accKNN,0:F3})';
|
|
|
|
|
|
end.
|