ML - док комменты и Clone - в порядке
This commit is contained in:
parent
3e88b53848
commit
e5c9344b74
|
|
@ -216,6 +216,11 @@ type
|
||||||
/// epochs — число итераций обучения.
|
/// epochs — число итераций обучения.
|
||||||
constructor Create(lambda: real := 0.0; lr: real := 0.1; epochs: integer := 1000);
|
constructor Create(lambda: real := 0.0; lr: real := 0.1; epochs: integer := 1000);
|
||||||
|
|
||||||
|
/// Обучает модель логистической регрессии.
|
||||||
|
/// X — матрица признаков.
|
||||||
|
/// y — вектор меток классов (целочисленные значения).
|
||||||
|
/// Возвращает обученную модель.
|
||||||
|
/// После вызова IsFitted становится true.
|
||||||
function Fit(X: Matrix; y: Vector): IModel;
|
function Fit(X: Matrix; y: Vector): IModel;
|
||||||
|
|
||||||
/// Возвращает матрицу вероятностей (m x k).
|
/// Возвращает матрицу вероятностей (m x k).
|
||||||
|
|
@ -224,10 +229,14 @@ type
|
||||||
/// Возвращает вектор предсказанных классов.
|
/// Возвращает вектор предсказанных классов.
|
||||||
function Predict(X: Matrix): Vector;
|
function Predict(X: Matrix): Vector;
|
||||||
|
|
||||||
|
/// Показывает, была ли модель обучена.
|
||||||
|
/// Если false — вызов Predict или PredictProba приведет к ошибке.
|
||||||
property IsFitted: boolean read fFitted;
|
property IsFitted: boolean read fFitted;
|
||||||
|
|
||||||
|
/// Возвращает строковое представление модели.
|
||||||
function ToString: string; override;
|
function ToString: string; override;
|
||||||
|
|
||||||
|
/// Создает глубокую копию модели.
|
||||||
function Clone: IModel;
|
function Clone: IModel;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -240,32 +249,56 @@ type
|
||||||
Right: DecisionTreeNode;
|
Right: DecisionTreeNode;
|
||||||
LeafValue: real;
|
LeafValue: real;
|
||||||
|
|
||||||
|
/// Создает глубокую копию узла вместе со всеми подузлами
|
||||||
function Clone: DecisionTreeNode;
|
function Clone: DecisionTreeNode;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
/// Результат поиска лучшего разбиения узла дерева.
|
||||||
SplitResult = record
|
SplitResult = record
|
||||||
|
/// Found = true, если допустимое разбиение найдено.
|
||||||
Found: boolean;
|
Found: boolean;
|
||||||
|
/// Feature — индекс признака, по которому делается split.
|
||||||
Feature: integer;
|
Feature: integer;
|
||||||
|
/// Threshold — пороговое значение признака.
|
||||||
Threshold: real;
|
Threshold: real;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
/// Интерфейс критерия разбиения узла дерева.
|
||||||
|
/// Определяет функцию нечистоты (impurity), которая используется для оценки качества разбиения.
|
||||||
ISplitCriterion = interface
|
ISplitCriterion = interface
|
||||||
|
/// Вычисляет нечистоту для вектора целевых значений y.
|
||||||
|
/// Чем меньше значение — тем "чище" узел.
|
||||||
function Impurity(y: Vector): real;
|
function Impurity(y: Vector): real;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
/// Критерий Джини.
|
||||||
|
/// Используется в классификации.
|
||||||
|
/// Минимизирует Gini-нечистоту, что приводит к более однородным по классам листьям.
|
||||||
GiniCriterion = class(ISplitCriterion)
|
GiniCriterion = class(ISplitCriterion)
|
||||||
public
|
public
|
||||||
|
/// Вычисляет Gini impurity для текущего набора y.
|
||||||
function Impurity(y: Vector): real;
|
function Impurity(y: Vector): real;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
/// Критерий дисперсии.
|
||||||
|
/// Используется в регрессии.
|
||||||
|
/// Минимизирует внутригрупповую дисперсию значений целевой переменной.
|
||||||
VarianceCriterion = class(ISplitCriterion)
|
VarianceCriterion = class(ISplitCriterion)
|
||||||
public
|
public
|
||||||
|
/// Вычисляет дисперсию значений y.
|
||||||
|
/// Чем меньше дисперсия — тем лучше узел.
|
||||||
function Impurity(y: Vector): real;
|
function Impurity(y: Vector): real;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
//============================
|
//============================
|
||||||
// DecisionTreeBase
|
// DecisionTreeBase
|
||||||
//============================
|
//============================
|
||||||
|
/// Базовый абстрактный класс дерева решений.
|
||||||
|
/// Реализует общую логику построения структуры дерева:
|
||||||
|
/// рекурсивное разбиение, контроль глубины,
|
||||||
|
/// минимального числа объектов и расчет важности признаков.
|
||||||
|
/// Конкретная логика вычисления значения листа
|
||||||
|
/// и критерия разбиения задается в наследниках.
|
||||||
DecisionTreeBase = abstract class(ITreeModel)
|
DecisionTreeBase = abstract class(ITreeModel)
|
||||||
protected
|
protected
|
||||||
fRoot: DecisionTreeNode;
|
fRoot: DecisionTreeNode;
|
||||||
|
|
@ -296,20 +329,45 @@ type
|
||||||
|
|
||||||
procedure SetRowIndices(rows: array of integer);
|
procedure SetRowIndices(rows: array of integer);
|
||||||
public
|
public
|
||||||
|
/// Создает дерево решений.
|
||||||
|
/// maxDepth — максимальная глубина дерева.
|
||||||
|
/// minSamplesSplit — минимальное число объектов для разбиения узла.
|
||||||
|
/// minSamplesLeaf — минимальное число объектов в листе.
|
||||||
constructor Create(maxDepth: integer := 10; minSamplesSplit: integer := 2; minSamplesLeaf: integer := 1);
|
constructor Create(maxDepth: integer := 10; minSamplesSplit: integer := 2; minSamplesLeaf: integer := 1);
|
||||||
|
|
||||||
|
/// Возвращает вектор важности признаков.
|
||||||
|
/// Важность вычисляется как суммарное уменьшение
|
||||||
|
/// нечистоты (impurity reduction) по всем разбиениям.
|
||||||
|
/// Значения нормированы так, что сумма равна 1.
|
||||||
function FeatureImportances: Vector;
|
function FeatureImportances: Vector;
|
||||||
|
|
||||||
|
/// Обучает дерево решений.
|
||||||
|
/// X — матрица признаков.
|
||||||
|
/// y — целевая переменная.
|
||||||
|
/// Реализация зависит от типа дерева (регрессия или классификация).
|
||||||
function Fit(X: Matrix; y: Vector): IModel; virtual; abstract;
|
function Fit(X: Matrix; y: Vector): IModel; virtual; abstract;
|
||||||
|
|
||||||
|
/// Выполняет предсказание для матрицы X.
|
||||||
|
/// Возвращает вектор прогнозов.
|
||||||
|
/// Для регрессии — вещественные значения.
|
||||||
|
/// Для классификации — метки классов.
|
||||||
function Predict(X: Matrix): Vector; virtual; abstract;
|
function Predict(X: Matrix): Vector; virtual; abstract;
|
||||||
|
|
||||||
|
/// Создает глубокую копию дерева.
|
||||||
|
/// Копируется структура узлов, параметры и обученное состояние.
|
||||||
function Clone: IModel; virtual; abstract;
|
function Clone: IModel; virtual; abstract;
|
||||||
|
|
||||||
|
/// Возвращает true, если дерево обучено.
|
||||||
|
/// Если false — Predict вызовет ошибку.
|
||||||
function IsFitted: boolean;
|
function IsFitted: boolean;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
//============================
|
//============================
|
||||||
// DecisionTreeClassifier
|
// DecisionTreeClassifier
|
||||||
//============================
|
//============================
|
||||||
|
/// Дерево решений для задачи классификации.
|
||||||
|
/// Использует критерий нечистоты (обычно Gini) для выбора оптимальных разбиений.
|
||||||
|
/// В листьях хранится наиболее частый класс.
|
||||||
DecisionTreeClassifier = class(DecisionTreeBase, IClassifier)
|
DecisionTreeClassifier = class(DecisionTreeBase, IClassifier)
|
||||||
private
|
private
|
||||||
fClassToIndex: Dictionary<integer, integer>;
|
fClassToIndex: Dictionary<integer, integer>;
|
||||||
|
|
@ -328,16 +386,38 @@ type
|
||||||
end;
|
end;
|
||||||
|
|
||||||
public
|
public
|
||||||
|
/// Создает классификационное дерево.
|
||||||
|
/// maxDepth — максимальная глубина дерева.
|
||||||
|
/// minSamplesSplit — минимальное число объектов для разбиения узла.
|
||||||
|
/// minSamplesLeaf — минимальное число объектов в листе.
|
||||||
constructor Create(maxDepth: integer := 10; minSamplesSplit: integer := 2; minSamplesLeaf: integer := 1);
|
constructor Create(maxDepth: integer := 10; minSamplesSplit: integer := 2; minSamplesLeaf: integer := 1);
|
||||||
|
|
||||||
|
/// Обучает классификационное дерево.
|
||||||
|
/// X — матрица признаков.
|
||||||
|
/// y — вектор целевых меток (целые значения).
|
||||||
|
/// Строит структуру дерева путем минимизации нечистоты в узлах.
|
||||||
function Fit(X: Matrix; y: Vector): IModel; override;
|
function Fit(X: Matrix; y: Vector): IModel; override;
|
||||||
|
|
||||||
|
/// Выполняет предсказание меток классов для X.
|
||||||
|
/// Для каждого объекта возвращается класс, соответствующий листу дерева.
|
||||||
function Predict(X: Matrix): Vector; override;
|
function Predict(X: Matrix): Vector; override;
|
||||||
|
|
||||||
|
/// Создает глубокую копию дерева классификации.
|
||||||
|
/// Копируется структура узлов, параметры и обученное состояние.
|
||||||
function Clone: IModel; override;
|
function Clone: IModel; override;
|
||||||
|
|
||||||
|
/// Возвращает строковое представление модели.
|
||||||
|
function ToString: string; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
//============================
|
//============================
|
||||||
// DecisionTreeRegressor
|
// DecisionTreeRegressor
|
||||||
//============================
|
//============================
|
||||||
|
/// Дерево решений для задачи регрессии.
|
||||||
|
/// Наследуется от DecisionTreeBase.
|
||||||
|
/// Использует критерий дисперсии для выбора разбиений.
|
||||||
|
/// В листьях хранится среднее значение целевой переменной.
|
||||||
|
/// Поддерживает L2-регуляризацию значения листа (leafL2).
|
||||||
DecisionTreeRegressor = class(DecisionTreeBase, IRegressor)
|
DecisionTreeRegressor = class(DecisionTreeBase, IRegressor)
|
||||||
private
|
private
|
||||||
fLeafL2: real;
|
fLeafL2: real;
|
||||||
|
|
@ -345,28 +425,60 @@ type
|
||||||
function PredictOne(x: Vector): real;
|
function PredictOne(x: Vector): real;
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
/// Вычисляет значение листа для набора индексов.
|
||||||
|
/// В регрессии это среднее целевой переменной
|
||||||
|
/// с учетом L2-регуляризации (если leafL2 > 0).
|
||||||
function LeafValue(y: Vector; indices: array of integer): real; override;
|
function LeafValue(y: Vector; indices: array of integer): real; override;
|
||||||
|
/// Ищет лучшее разбиение узла по всем признакам и возможным порогам.
|
||||||
|
/// Критерий — максимальное уменьшение дисперсии.
|
||||||
function FindBestSplit(X: Matrix; y: Vector; indices: array of integer): SplitResult; override;
|
function FindBestSplit(X: Matrix; y: Vector; indices: array of integer): SplitResult; override;
|
||||||
|
/// Проверяет, является ли узел "чистым".
|
||||||
|
/// Для регрессии это означает, что все значения y одинаковы
|
||||||
|
/// или разбиение больше не имеет смысла.
|
||||||
function IsPure(y: Vector; indices: array of integer): boolean; override;
|
function IsPure(y: Vector; indices: array of integer): boolean; override;
|
||||||
|
|
||||||
public
|
public
|
||||||
|
/// Создает регрессионное дерево.
|
||||||
|
/// maxDepth — максимальная глубина.
|
||||||
|
/// minSamplesSplit — минимальное число объектов для разбиения.
|
||||||
|
/// minSamplesLeaf — минимальное число объектов в листе.
|
||||||
|
/// leafL2 — коэффициент L2-регуляризации значения листа.
|
||||||
constructor Create(maxDepth: integer := 10; minSamplesSplit: integer := 2; minSamplesLeaf: integer := 1;
|
constructor Create(maxDepth: integer := 10; minSamplesSplit: integer := 2; minSamplesLeaf: integer := 1;
|
||||||
leafL2: real := 0.0);
|
leafL2: real := 0.0);
|
||||||
|
|
||||||
|
/// Обучает регрессионное дерево.
|
||||||
|
/// X — матрица признаков.
|
||||||
|
/// y — вещественная целевая переменная.
|
||||||
function Fit(X: Matrix; y: Vector): IModel; override;
|
function Fit(X: Matrix; y: Vector): IModel; override;
|
||||||
|
|
||||||
|
/// Выполняет предсказание для всех объектов X.
|
||||||
|
/// Возвращает вектор вещественных значений.
|
||||||
function Predict(X: Matrix): Vector; override;
|
function Predict(X: Matrix): Vector; override;
|
||||||
|
|
||||||
|
/// Создает глубокую копию дерева регрессии.
|
||||||
|
/// Копируется структура узлов, параметры и обученное состояние.
|
||||||
function Clone: IModel; override;
|
function Clone: IModel; override;
|
||||||
|
|
||||||
|
/// Возвращает строковое представление модели.
|
||||||
|
function ToString: string; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
/// Режим выбора числа признаков при поиске разбиения.
|
||||||
|
/// Определяет, сколько признаков m из общего числа p
|
||||||
|
/// будет случайно выбрано для рассмотрения в узле.
|
||||||
|
/// Используется в Random Forest и других ансамблях
|
||||||
|
/// для увеличения разнообразия деревьев.
|
||||||
TMaxFeaturesMode = (
|
TMaxFeaturesMode = (
|
||||||
/// m = p
|
/// Использовать все признаки: m = p
|
||||||
AllFeatures,
|
AllFeatures,
|
||||||
/// m = sqrt(p)
|
/// Использовать квадратный корень от числа признаков: m = sqrt(p)
|
||||||
SqrtFeatures,
|
/// Типичный выбор для классификации.
|
||||||
/// m = log2(p)
|
SqrtFeatures,
|
||||||
|
/// Использовать log2 от числа признаков: m = log2(p)
|
||||||
|
/// Более агрессивное ограничение признаков.
|
||||||
Log2Features,
|
Log2Features,
|
||||||
/// m = p/2
|
/// Использовать половину признаков: m = p / 2
|
||||||
|
/// Компромисс между скоростью и разнообразием.
|
||||||
HalfFeatures
|
HalfFeatures
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -378,6 +490,12 @@ type
|
||||||
// feature-subset = в каждом дереве - случайные признаки
|
// feature-subset = в каждом дереве - случайные признаки
|
||||||
// RandomForest снижает корреляцию между деревьями, что хорошо
|
// RandomForest снижает корреляцию между деревьями, что хорошо
|
||||||
|
|
||||||
|
/// Базовый абстрактный класс случайного леса.
|
||||||
|
/// Реализует ансамбль из множества независимых деревьев,
|
||||||
|
/// обученных на случайных подвыборках данных
|
||||||
|
/// и случайных подмножествах признаков.
|
||||||
|
/// Конкретная логика агрегирования предсказаний
|
||||||
|
/// определяется в наследниках (регрессия или классификация).
|
||||||
RandomForestBase = abstract class(IModel)
|
RandomForestBase = abstract class(IModel)
|
||||||
protected
|
protected
|
||||||
fNTrees: integer;
|
fNTrees: integer;
|
||||||
|
|
@ -390,56 +508,125 @@ type
|
||||||
function ComputeMaxFeatures(p: integer): integer;
|
function ComputeMaxFeatures(p: integer): integer;
|
||||||
procedure BootstrapSample(X: Matrix; y: Vector; var Xb: Matrix; var yb: Vector);
|
procedure BootstrapSample(X: Matrix; y: Vector; var Xb: Matrix; var yb: Vector);
|
||||||
public
|
public
|
||||||
|
/// Создает случайный лес.
|
||||||
|
/// nTrees — число деревьев в ансамбле.
|
||||||
|
/// maxDepth — максимальная глубина каждого дерева.
|
||||||
|
/// minSamplesSplit — минимальное число объектов для разбиения узла.
|
||||||
|
/// minSamplesLeaf — минимальное число объектов в листе.
|
||||||
|
/// maxFeatures — режим выбора числа признаков, рассматриваемых при поиске разбиения.
|
||||||
constructor Create(
|
constructor Create(
|
||||||
nTrees: integer;
|
nTrees: integer;
|
||||||
maxDepth: integer;
|
maxDepth: integer;
|
||||||
minSamplesSplit: integer;
|
minSamplesSplit: integer;
|
||||||
minSamplesLeaf: integer;
|
minSamplesLeaf: integer;
|
||||||
maxFeatures: TMaxFeaturesMode);
|
maxFeatures: TMaxFeaturesMode);
|
||||||
|
|
||||||
|
/// Обучает ансамбль деревьев на данных X и y.
|
||||||
|
/// Для каждого дерева используется bootstrap-подвыборка
|
||||||
|
/// и случайное подмножество признаков.
|
||||||
function Fit(X: Matrix; y: Vector): IModel; virtual; abstract;
|
function Fit(X: Matrix; y: Vector): IModel; virtual; abstract;
|
||||||
|
|
||||||
|
/// Выполняет предсказание для матрицы X.
|
||||||
|
/// В регрессии — усреднение предсказаний деревьев.
|
||||||
|
/// В классификации — голосование (majority vote) или усреднение вероятностей.
|
||||||
function Predict(X: Matrix): Vector; virtual; abstract;
|
function Predict(X: Matrix): Vector; virtual; abstract;
|
||||||
|
|
||||||
|
/// Создает глубокую копию случайного леса.
|
||||||
|
/// Копируются все деревья и параметры ансамбля.
|
||||||
function Clone: IModel; virtual; abstract;
|
function Clone: IModel; virtual; abstract;
|
||||||
|
|
||||||
|
/// Возвращает вектор важности признаков.
|
||||||
|
/// Обычно вычисляется как средняя важность по всем деревьям ансамбля.
|
||||||
function FeatureImportances: Vector; virtual; abstract;
|
function FeatureImportances: Vector; virtual; abstract;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
/// Случайный лес для задачи регрессии.
|
||||||
|
/// Строит ансамбль регрессионных деревьев,
|
||||||
|
/// обученных на bootstrap-подвыборках данных и случайных подмножествах признаков.
|
||||||
|
/// Итоговое предсказание — среднее значение по всем деревьям ансамбля.
|
||||||
RandomForestRegressor = class(RandomForestBase, IModel)
|
RandomForestRegressor = class(RandomForestBase, IModel)
|
||||||
private
|
private
|
||||||
fTrees: array of DecisionTreeRegressor;
|
fTrees: array of DecisionTreeRegressor;
|
||||||
public
|
public
|
||||||
|
/// Создает регрессионный случайный лес.
|
||||||
|
/// nTrees — число деревьев в ансамбле.
|
||||||
|
/// maxDepth — максимальная глубина деревьев.
|
||||||
|
/// minSamplesSplit — минимальное число объектов для разбиения узла.
|
||||||
|
/// minSamplesLeaf — минимальное число объектов в листе.
|
||||||
|
/// maxFeaturesMode — режим выбора числа признаков, рассматриваемых при поиске разбиения.
|
||||||
constructor Create(nTrees: integer := 100;
|
constructor Create(nTrees: integer := 100;
|
||||||
maxDepth: integer := integer.MaxValue;
|
maxDepth: integer := integer.MaxValue;
|
||||||
minSamplesSplit: integer := 2;
|
minSamplesSplit: integer := 2;
|
||||||
minSamplesLeaf: integer := 1;
|
minSamplesLeaf: integer := 1;
|
||||||
maxFeaturesMode: TMaxFeaturesMode := TMaxFeaturesMode.HalfFeatures);
|
maxFeaturesMode: TMaxFeaturesMode := TMaxFeaturesMode.HalfFeatures);
|
||||||
|
|
||||||
|
/// Обучает случайный лес на данных X и y.
|
||||||
|
/// Для каждого дерева используется bootstrap-выборка.
|
||||||
|
/// Возвращает обученную модель.
|
||||||
function Fit(X: Matrix; y: Vector): IModel; override;
|
function Fit(X: Matrix; y: Vector): IModel; override;
|
||||||
|
|
||||||
|
/// Выполняет предсказание для X.
|
||||||
|
/// Итоговое значение — среднее предсказаний всех деревьев ансамбля.
|
||||||
function Predict(X: Matrix): Vector; override;
|
function Predict(X: Matrix): Vector; override;
|
||||||
|
|
||||||
|
/// Создает глубокую копию случайного леса.
|
||||||
|
/// Копируются все деревья и параметры модели.
|
||||||
function Clone: IModel; override;
|
function Clone: IModel; override;
|
||||||
|
|
||||||
|
/// Возвращает усредненную важность признаков по всем деревьям ансамбля.
|
||||||
|
/// Значения нормированы так, что сумма равна 1.
|
||||||
function FeatureImportances: Vector; override;
|
function FeatureImportances: Vector; override;
|
||||||
|
|
||||||
|
/// Возвращает строковое представление модели.
|
||||||
|
function ToString: string; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
/// Случайный лес для задачи классификации.
|
||||||
|
/// Наследуется от RandomForestBase и реализует интерфейс IClassifier.
|
||||||
|
/// Строит ансамбль классификационных деревьев, обученных на bootstrap-подвыборках
|
||||||
|
/// объектов и случайных подмножествах признаков.
|
||||||
|
/// Итоговое предсказание формируется голосованием деревьев или агрегацией вероятностей классов.
|
||||||
RandomForestClassifier = class(RandomForestBase, IClassifier)
|
RandomForestClassifier = class(RandomForestBase, IClassifier)
|
||||||
private
|
private
|
||||||
fTrees: array of DecisionTreeClassifier;
|
fTrees: array of DecisionTreeClassifier;
|
||||||
public
|
public
|
||||||
|
/// Создает классификационный случайный лес.
|
||||||
|
/// nTrees — число деревьев в ансамбле.
|
||||||
|
/// maxDepth — максимальная глубина каждого дерева.
|
||||||
|
/// minSamplesSplit — минимальное число объектов для разбиения узла.
|
||||||
|
/// minSamplesLeaf — минимальное число объектов в листе.
|
||||||
|
/// maxFeaturesMode — режим выбора числа признаков при поиске разбиения, по умолчанию используется sqrt(p),
|
||||||
|
/// что является стандартом для классификации.
|
||||||
constructor Create(nTrees: integer := 100;
|
constructor Create(nTrees: integer := 100;
|
||||||
maxDepth: integer := integer.MaxValue;
|
maxDepth: integer := integer.MaxValue;
|
||||||
minSamplesSplit: integer := 2;
|
minSamplesSplit: integer := 2;
|
||||||
minSamplesLeaf: integer := 1;
|
minSamplesLeaf: integer := 1;
|
||||||
maxFeaturesMode: TMaxFeaturesMode := TMaxFeaturesMode.SqrtFeatures);
|
maxFeaturesMode: TMaxFeaturesMode := TMaxFeaturesMode.SqrtFeatures);
|
||||||
|
|
||||||
|
/// Обучает случайный лес на данных X и y.
|
||||||
|
/// Для каждого дерева используется bootstrap-выборка обучающих объектов.
|
||||||
|
/// В каждом узле рассматривается случайное подмножество признаков согласно maxFeaturesMode.
|
||||||
|
/// Возвращает обученную модель.
|
||||||
function Fit(X: Matrix; y: Vector): IModel; override;
|
function Fit(X: Matrix; y: Vector): IModel; override;
|
||||||
|
|
||||||
|
/// Выполняет предсказание меток классов для матрицы X.
|
||||||
|
/// Для каждого объекта агрегируются предсказания всех деревьев.
|
||||||
|
/// Итоговый класс определяется большинством голосов или максимальной суммарной вероятностью.
|
||||||
function Predict(X: Matrix): Vector; override;
|
function Predict(X: Matrix): Vector; override;
|
||||||
|
|
||||||
|
/// Создает глубокую копию случайного леса классификации.
|
||||||
|
/// Копируются все деревья, параметры ансамбля и обученное состояние модели.
|
||||||
function Clone: IModel; override;
|
function Clone: IModel; override;
|
||||||
|
|
||||||
|
/// Возвращает усредненную важность признаков по всем деревьям ансамбля.
|
||||||
|
/// Важность рассчитывается как суммарное уменьшение нечистоты, нормированное так, что сумма равна 1.
|
||||||
function FeatureImportances: Vector; override;
|
function FeatureImportances: Vector; override;
|
||||||
|
|
||||||
|
/// Возвращает строковое представление модели.
|
||||||
|
function ToString: string; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Gradient Boosting v1.0 — Freeze Checklist
|
{ Gradient Boosting v1.0 — Freeze Checklist
|
||||||
|
|
||||||
GradientBoostingRegressor
|
GradientBoostingRegressor
|
||||||
✔ SquaredError
|
✔ SquaredError
|
||||||
✔ Huber
|
✔ Huber
|
||||||
|
|
@ -465,9 +652,19 @@ type
|
||||||
✔ Feature importance
|
✔ Feature importance
|
||||||
✔ Clone
|
✔ Clone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Тип функции потерь для GradientBoostingRegressor.
|
||||||
|
/// SquaredError — классическая L2 (MSE).
|
||||||
|
/// Huber — робастная loss: квадратичная около нуля и линейная на хвостах.
|
||||||
|
/// Quantile — квантильная регрессия (асимметричная L1).
|
||||||
TGBLoss = (SquaredError, Huber, Quantile);
|
TGBLoss = (SquaredError, Huber, Quantile);
|
||||||
|
|
||||||
|
/// Gradient Boosting Regressor.
|
||||||
|
/// Реализует градиентный бустинг над деревьями решений.
|
||||||
|
/// Каждая новая модель обучается на псевдо-остатках предыдущей.
|
||||||
|
/// Поддерживает разные loss-функции, subsample (stochastic boosting),
|
||||||
|
/// early stopping (validation или OOB),
|
||||||
|
/// L2-регуляризацию в листьях и staged prediction.
|
||||||
GradientBoostingRegressor = class(IRegressor)
|
GradientBoostingRegressor = class(IRegressor)
|
||||||
private
|
private
|
||||||
fNEstimators: integer;
|
fNEstimators: integer;
|
||||||
|
|
@ -515,6 +712,20 @@ type
|
||||||
function ComputeTrainLossMasked(yTrue, yPred: Vector; mask: array of boolean): real;
|
function ComputeTrainLossMasked(yTrue, yPred: Vector; mask: array of boolean): real;
|
||||||
|
|
||||||
public
|
public
|
||||||
|
/// Создает новый GradientBoostingRegressor.
|
||||||
|
/// nEstimators — число деревьев (итераций бустинга).
|
||||||
|
/// learningRate — коэффициент shrinkage.
|
||||||
|
/// maxDepth — максимальная глубина дерева.
|
||||||
|
/// minSamplesSplit — минимальное число объектов для split.
|
||||||
|
/// minSamplesLeaf — минимальное число объектов в листе.
|
||||||
|
/// subsample — доля выборки на каждой итерации (0..1].
|
||||||
|
/// randomSeed — зерно генератора случайных чисел.
|
||||||
|
/// loss — функция потерь.
|
||||||
|
/// huberDelta — параметр Huber loss.
|
||||||
|
/// earlyStoppingPatience — число итераций без улучшения до остановки.
|
||||||
|
/// quantileAlpha — уровень квантили для Quantile loss.
|
||||||
|
/// leafL2 — L2-регуляризация значения листа.
|
||||||
|
/// useOOBEarlyStopping — использовать OOB loss для ранней остановки.
|
||||||
constructor Create(
|
constructor Create(
|
||||||
nEstimators: integer := 100;
|
nEstimators: integer := 100;
|
||||||
learningRate: real := 0.1;
|
learningRate: real := 0.1;
|
||||||
|
|
@ -531,28 +742,65 @@ type
|
||||||
useOOBEarlyStopping: boolean := false
|
useOOBEarlyStopping: boolean := false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Обучает модель на всей обучающей выборке.
|
||||||
|
/// Если включен early stopping и subsample < 1,
|
||||||
|
/// может использоваться OOB loss.
|
||||||
|
/// Возвращает обученную модель.
|
||||||
function Fit(X: Matrix; y: Vector): IModel;
|
function Fit(X: Matrix; y: Vector): IModel;
|
||||||
|
/// Предсказывает значения целевой переменной.
|
||||||
|
/// Используются все обученные деревья.
|
||||||
function Predict(X: Matrix): Vector;
|
function Predict(X: Matrix): Vector;
|
||||||
|
/// Создает глубокую копию модели.
|
||||||
|
/// Копируются все деревья и внутреннее состояние.
|
||||||
function Clone: IModel;
|
function Clone: IModel;
|
||||||
|
|
||||||
|
/// Обучает модель с использованием отдельной validation-выборки.
|
||||||
|
/// Early stopping (если включен) происходит по validation loss.
|
||||||
function FitWithValidation(XTrain: Matrix; yTrain: Vector;
|
function FitWithValidation(XTrain: Matrix; yTrain: Vector;
|
||||||
XVal: Matrix; yVal: Vector): IModel;
|
XVal: Matrix; yVal: Vector): IModel;
|
||||||
|
|
||||||
|
/// История значения функции потерь на обучающей выборке.
|
||||||
|
/// Один элемент на итерацию бустинга.
|
||||||
property TrainLossHistory: List<real> read fTrainLossHistory;
|
property TrainLossHistory: List<real> read fTrainLossHistory;
|
||||||
|
/// История значения функции потерь на validation-выборке.
|
||||||
property ValLossHistory: List<real> read fValLossHistory;
|
property ValLossHistory: List<real> read fValLossHistory;
|
||||||
|
/// Индекс итерации с лучшим значением функции потерь
|
||||||
|
/// (validation или OOB в зависимости от режима).
|
||||||
property BestIteration: integer read fBestIteration;
|
property BestIteration: integer read fBestIteration;
|
||||||
|
/// История OOB loss (если включен OOB early stopping).
|
||||||
property OOBLossHistory: List<real> read fOOBLossHistory;
|
property OOBLossHistory: List<real> read fOOBLossHistory;
|
||||||
|
|
||||||
|
/// Предсказание по первым m итерациям бустинга.
|
||||||
|
/// m может быть от 0 до TreeCount.
|
||||||
|
/// Используется для анализа обучения и переобучения.
|
||||||
function PredictStage(X: Matrix; m: integer): Vector;
|
function PredictStage(X: Matrix; m: integer): Vector;
|
||||||
|
/// Возвращает последовательность предсказаний
|
||||||
|
/// после каждой итерации бустинга.
|
||||||
|
/// Удобно для построения learning curve.
|
||||||
function StagedPredict(X: Matrix): sequence of Vector;
|
function StagedPredict(X: Matrix): sequence of Vector;
|
||||||
|
|
||||||
|
/// Возвращает текущее количество деревьев в ансамбле.
|
||||||
function TreeCount: integer := fEstimators.Count;
|
function TreeCount: integer := fEstimators.Count;
|
||||||
|
|
||||||
|
/// Возвращает нормированные importance признаков.
|
||||||
|
/// Значения суммируются по всем деревьям и нормируются к 1.
|
||||||
function FeatureImportances: Vector;
|
function FeatureImportances: Vector;
|
||||||
|
|
||||||
|
/// Возвращает строковое представление модели.
|
||||||
|
function ToString: string; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
/// Тип функции потерь для классификатора.
|
||||||
|
/// В текущей версии используется только LogLoss
|
||||||
|
/// (многоклассовая кросс-энтропия).
|
||||||
TGBCLoss = (LogLoss);
|
TGBCLoss = (LogLoss);
|
||||||
|
|
||||||
|
/// Gradient Boosting Classifier.
|
||||||
|
/// Реализует многоклассовый градиентный бустинг с использованием softmax и LogLoss.
|
||||||
|
/// На каждой итерации обучается по одному дереву
|
||||||
|
/// для каждого класса (one-vs-all в логит-пространстве).
|
||||||
|
/// Поддерживает subsample, validation early stopping,
|
||||||
|
/// OOB early stopping и staged prediction.
|
||||||
GradientBoostingClassifier = class(IProbabilisticClassifier)
|
GradientBoostingClassifier = class(IProbabilisticClassifier)
|
||||||
private
|
private
|
||||||
// hyperparams
|
// hyperparams
|
||||||
|
|
@ -604,6 +852,15 @@ type
|
||||||
mask: array of boolean): real;
|
mask: array of boolean): real;
|
||||||
|
|
||||||
public
|
public
|
||||||
|
/// Создает новый GradientBoostingClassifier.
|
||||||
|
/// nEstimators — число итераций бустинга.
|
||||||
|
/// learningRate — коэффициент shrinkage.
|
||||||
|
/// maxDepth — максимальная глубина деревьев.
|
||||||
|
/// minSamplesSplit — минимальное число объектов для split.
|
||||||
|
/// minSamplesLeaf — минимальное число объектов в листе.
|
||||||
|
/// subsample — доля обучающей выборки на каждой итерации.
|
||||||
|
/// randomSeed — зерно генератора случайных чисел.
|
||||||
|
/// earlyStoppingPatience — число итераций без улучшения до ранней остановки.
|
||||||
constructor Create(
|
constructor Create(
|
||||||
nEstimators: integer := 200;
|
nEstimators: integer := 200;
|
||||||
learningRate: real := 0.05;
|
learningRate: real := 0.05;
|
||||||
|
|
@ -614,25 +871,58 @@ type
|
||||||
randomSeed: integer := 42;
|
randomSeed: integer := 42;
|
||||||
earlyStoppingPatience: integer := 20);
|
earlyStoppingPatience: integer := 20);
|
||||||
|
|
||||||
|
/// Обучает классификатор на всей обучающей выборке.
|
||||||
|
/// Если включен early stopping и subsample < 1,
|
||||||
|
/// может использоваться OOB loss.
|
||||||
|
/// Возвращает обученную модель.
|
||||||
function Fit(X: Matrix; y: Vector): IModel;
|
function Fit(X: Matrix; y: Vector): IModel;
|
||||||
|
|
||||||
|
/// Обучает классификатор с использованием validation-набора.
|
||||||
|
/// Если включен early stopping, он основан на validation loss.
|
||||||
function FitWithValidation(XTrain: Matrix; yTrain: Vector; XVal: Matrix; yVal: Vector): IModel;
|
function FitWithValidation(XTrain: Matrix; yTrain: Vector; XVal: Matrix; yVal: Vector): IModel;
|
||||||
|
|
||||||
|
/// Предсказывает метки классов.
|
||||||
|
/// Возвращает исходные значения классов, а не внутренние индексы.
|
||||||
function Predict(X: Matrix): Vector;
|
function Predict(X: Matrix): Vector;
|
||||||
|
|
||||||
|
/// Возвращает вероятности принадлежности к каждому классу.
|
||||||
|
/// Размер результата: [nSamples x nClasses].
|
||||||
|
/// Вероятности получаются через softmax.
|
||||||
function PredictProba(X: Matrix): Matrix;
|
function PredictProba(X: Matrix): Matrix;
|
||||||
|
|
||||||
|
/// Создает глубокую копию классификатора.
|
||||||
|
/// Копируются все деревья и внутреннее состояние.
|
||||||
function Clone: IModel;
|
function Clone: IModel;
|
||||||
|
|
||||||
|
/// История значения LogLoss на обучающей выборке.
|
||||||
|
/// Один элемент на итерацию бустинга.
|
||||||
property TrainLossHistory: List<real> read fTrainLossHistory;
|
property TrainLossHistory: List<real> read fTrainLossHistory;
|
||||||
|
/// История LogLoss на validation-наборе.
|
||||||
property ValLossHistory: List<real> read fValLossHistory;
|
property ValLossHistory: List<real> read fValLossHistory;
|
||||||
|
/// Индекс итерации с лучшим значением функции потерь (validation или OOB).
|
||||||
property BestIteration: integer read fBestIteration;
|
property BestIteration: integer read fBestIteration;
|
||||||
|
/// История OOB LogLoss (если включен OOB early stopping).
|
||||||
property OOBLossHistory: List<real> read fOOBLossHistory;
|
property OOBLossHistory: List<real> read fOOBLossHistory;
|
||||||
|
|
||||||
|
/// Возвращает вероятности после первых m итераций бустинга.
|
||||||
|
/// m может быть от 0 до TreeCount.
|
||||||
|
/// Используется для анализа обучения.
|
||||||
function PredictStageProba(X: Matrix; m: integer): Matrix;
|
function PredictStageProba(X: Matrix; m: integer): Matrix;
|
||||||
|
|
||||||
|
/// Предсказывает классы по первым m итерациям бустинга.
|
||||||
|
/// Удобно для построения learning curve.
|
||||||
function PredictStage(X: Matrix; m: integer): Vector;
|
function PredictStage(X: Matrix; m: integer): Vector;
|
||||||
|
|
||||||
|
/// Текущее количество деревьев в ансамбле.
|
||||||
function TreeCount: integer := fEstimators.Count;
|
function TreeCount: integer := fEstimators.Count;
|
||||||
|
|
||||||
|
/// Нормированные importance признаков.
|
||||||
|
/// Рассчитываются как суммарное уменьшение impurity
|
||||||
|
/// по всем деревьям и нормируются к 1.
|
||||||
function FeatureImportances: Vector;
|
function FeatureImportances: Vector;
|
||||||
|
|
||||||
|
/// Возвращает строковое представление модели.
|
||||||
|
function ToString: string; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{$endregion Models}
|
{$endregion Models}
|
||||||
|
|
@ -905,7 +1195,11 @@ type
|
||||||
/// Показывает, был ли выполнен Fit.
|
/// Показывает, был ли выполнен Fit.
|
||||||
property IsFitted: boolean read fFitted;
|
property IsFitted: boolean read fFitted;
|
||||||
|
|
||||||
|
/// Возвращает строковое представление трансформера
|
||||||
function ToString: string; override;
|
function ToString: string; override;
|
||||||
|
|
||||||
|
/// Создает глубокую копию.
|
||||||
|
/// Копируются параметры и внутреннее состояние.
|
||||||
function Clone: ITransformer;
|
function Clone: ITransformer;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -923,14 +1217,29 @@ type
|
||||||
fNormType: NormType;
|
fNormType: NormType;
|
||||||
fFitted: boolean;
|
fFitted: boolean;
|
||||||
public
|
public
|
||||||
|
/// Создает нормализатор.
|
||||||
|
/// norm — тип нормы, используемой для масштабирования строки признаков.
|
||||||
|
/// По умолчанию используется L2-норма.
|
||||||
constructor Create(norm: NormType := NormType.L2);
|
constructor Create(norm: NormType := NormType.L2);
|
||||||
|
|
||||||
|
/// Подготавливает трансформер к работе.
|
||||||
|
/// Для Normalizer этап обучения может быть формальным, так как параметры не накапливаются.
|
||||||
function Fit(X: Matrix): ITransformer;
|
function Fit(X: Matrix): ITransformer;
|
||||||
|
|
||||||
|
/// Применяет нормализацию к матрице X.
|
||||||
|
/// Каждая строка масштабируется так, чтобы ее норма соответствовала выбранному типу.
|
||||||
|
/// Возвращает новую матрицу с нормализованными объектами.
|
||||||
function Transform(X: Matrix): Matrix;
|
function Transform(X: Matrix): Matrix;
|
||||||
|
|
||||||
|
/// Показывает, был ли вызван метод Fit.
|
||||||
|
/// Если False, вызов Transform может привести к ошибке.
|
||||||
property IsFitted: boolean read fFitted;
|
property IsFitted: boolean read fFitted;
|
||||||
|
|
||||||
|
/// Возвращает строковое представление трансформера
|
||||||
function ToString: string; override;
|
function ToString: string; override;
|
||||||
|
|
||||||
|
/// Создает глубокую копию нормализатора.
|
||||||
|
/// Копируются параметры и внутреннее состояние.
|
||||||
function Clone: ITransformer;
|
function Clone: ITransformer;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -1678,6 +1987,14 @@ begin
|
||||||
dest.fMinSamplesSplit := fMinSamplesSplit;
|
dest.fMinSamplesSplit := fMinSamplesSplit;
|
||||||
dest.fMinSamplesLeaf := fMinSamplesLeaf;
|
dest.fMinSamplesLeaf := fMinSamplesLeaf;
|
||||||
dest.fFitted := fFitted;
|
dest.fFitted := fFitted;
|
||||||
|
dest.fRandomSeed := fRandomSeed;
|
||||||
|
dest.fMaxFeatures := fMaxFeatures;
|
||||||
|
|
||||||
|
if fCriterion <> nil then
|
||||||
|
dest.fCriterion := fCriterion; // можно так, если критерий stateless
|
||||||
|
|
||||||
|
if fFeatureImportances <> nil then
|
||||||
|
dest.fFeatureImportances := fFeatureImportances.Clone;
|
||||||
|
|
||||||
if fRoot <> nil then
|
if fRoot <> nil then
|
||||||
dest.fRoot := fRoot.Clone;
|
dest.fRoot := fRoot.Clone;
|
||||||
|
|
@ -2231,6 +2548,16 @@ begin
|
||||||
Result := MajorityClass(y, indices);
|
Result := MajorityClass(y, indices);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function DecisionTreeClassifier.ToString: string;
|
||||||
|
begin
|
||||||
|
Result :=
|
||||||
|
$'DecisionTreeClassifier(' +
|
||||||
|
$'maxDepth={fMaxDepth}, ' +
|
||||||
|
$'minSamplesSplit={fMinSamplesSplit}, ' +
|
||||||
|
$'minSamplesLeaf={fMinSamplesLeaf}' +
|
||||||
|
')';
|
||||||
|
end;
|
||||||
|
|
||||||
// DecisionTreeRegressor
|
// DecisionTreeRegressor
|
||||||
|
|
||||||
constructor DecisionTreeRegressor.Create(maxDepth: integer; minSamplesSplit: integer;
|
constructor DecisionTreeRegressor.Create(maxDepth: integer; minSamplesSplit: integer;
|
||||||
|
|
@ -2340,7 +2667,8 @@ begin
|
||||||
var m := new DecisionTreeRegressor(
|
var m := new DecisionTreeRegressor(
|
||||||
fMaxDepth,
|
fMaxDepth,
|
||||||
fMinSamplesSplit,
|
fMinSamplesSplit,
|
||||||
fMinSamplesLeaf
|
fMinSamplesLeaf,
|
||||||
|
fLeafL2
|
||||||
);
|
);
|
||||||
|
|
||||||
CopyBaseState(m);
|
CopyBaseState(m);
|
||||||
|
|
@ -2348,6 +2676,21 @@ begin
|
||||||
Result := m;
|
Result := m;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function DecisionTreeRegressor.ToString: string;
|
||||||
|
begin
|
||||||
|
var s :=
|
||||||
|
$'DecisionTreeRegressor(maxDepth={fMaxDepth}, ' +
|
||||||
|
$'minSamplesSplit={fMinSamplesSplit}, ' +
|
||||||
|
$'minSamplesLeaf={fMinSamplesLeaf}';
|
||||||
|
|
||||||
|
if fLeafL2 <> 0.0 then
|
||||||
|
s += $', leafL2={fLeafL2}';
|
||||||
|
|
||||||
|
s += ')';
|
||||||
|
|
||||||
|
Result := s;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
// RandomForestBase
|
// RandomForestBase
|
||||||
|
|
@ -2499,9 +2842,26 @@ begin
|
||||||
Result := resultVec;
|
Result := resultVec;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function RandomForestRegressor.ToString: string;
|
||||||
|
begin
|
||||||
|
var depthStr :=
|
||||||
|
if fMaxDepth = integer.MaxValue then '∞'
|
||||||
|
else fMaxDepth.ToString;
|
||||||
|
|
||||||
|
Result :=
|
||||||
|
$'RandomForestRegressor(' +
|
||||||
|
$'nTrees={fNTrees}, ' +
|
||||||
|
$'maxDepth={depthStr}, ' +
|
||||||
|
$'minSamplesSplit={fMinSamplesSplit}, ' +
|
||||||
|
$'minSamplesLeaf={fMinSamplesLeaf}, ' +
|
||||||
|
$'maxFeatures={fMaxFeaturesMode}' +
|
||||||
|
')';
|
||||||
|
end;
|
||||||
|
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
// RandomForestClassifier
|
// RandomForestClassifier
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
|
|
||||||
constructor RandomForestClassifier.Create(nTrees: integer;
|
constructor RandomForestClassifier.Create(nTrees: integer;
|
||||||
maxDepth: integer; minSamplesSplit: integer; minSamplesLeaf: integer;
|
maxDepth: integer; minSamplesSplit: integer; minSamplesLeaf: integer;
|
||||||
maxFeaturesMode: TMaxFeaturesMode);
|
maxFeaturesMode: TMaxFeaturesMode);
|
||||||
|
|
@ -2626,6 +2986,22 @@ begin
|
||||||
Result := resultVec;
|
Result := resultVec;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function RandomForestClassifier.ToString: string;
|
||||||
|
begin
|
||||||
|
var depthStr :=
|
||||||
|
if fMaxDepth = integer.MaxValue then '∞'
|
||||||
|
else fMaxDepth.ToString;
|
||||||
|
|
||||||
|
Result :=
|
||||||
|
$'RandomForestClassifier(' +
|
||||||
|
$'nTrees={fNTrees}, ' +
|
||||||
|
$'maxDepth={depthStr}, ' +
|
||||||
|
$'minSamplesSplit={fMinSamplesSplit}, ' +
|
||||||
|
$'minSamplesLeaf={fMinSamplesLeaf}, ' +
|
||||||
|
$'maxFeatures={fMaxFeaturesMode}' +
|
||||||
|
')';
|
||||||
|
end;
|
||||||
|
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
// GradientBoostingRegressor
|
// GradientBoostingRegressor
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
|
|
@ -3185,63 +3561,57 @@ begin
|
||||||
Result := fFeatureImportances;
|
Result := fFeatureImportances;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function GradientBoostingRegressor.ToString: string;
|
||||||
|
begin
|
||||||
|
var s :=
|
||||||
|
$'GradientBoostingRegressor(' +
|
||||||
|
$'n={fNEstimators}, ' +
|
||||||
|
$'lr={fLearningRate}, ' +
|
||||||
|
$'maxDepth={fMaxDepth}, ' +
|
||||||
|
$'loss={fLoss}';
|
||||||
|
|
||||||
|
if fSubsample <> 1.0 then
|
||||||
|
s += $', subs={fSubsample}';
|
||||||
|
|
||||||
|
if fEarlyStoppingPatience > 0 then
|
||||||
|
s += $', earlyStop={fEarlyStoppingPatience}';
|
||||||
|
|
||||||
|
if fLoss = TGBLoss.Huber then
|
||||||
|
s += $', delta={fHuberDelta}';
|
||||||
|
|
||||||
|
if fLoss = TGBLoss.Quantile then
|
||||||
|
s += $', alpha={fQuantileAlpha}';
|
||||||
|
|
||||||
|
if fLeafL2 <> 0.0 then
|
||||||
|
s += $', leafL2={fLeafL2}';
|
||||||
|
|
||||||
|
if fUseOOBEarlyStopping then
|
||||||
|
s += ', OOB=true';
|
||||||
|
|
||||||
|
s += ')';
|
||||||
|
|
||||||
|
Result := s;
|
||||||
|
end;
|
||||||
|
|
||||||
function GradientBoostingRegressor.Clone: IModel;
|
function GradientBoostingRegressor.Clone: IModel;
|
||||||
begin
|
begin
|
||||||
var c := new GradientBoostingRegressor(
|
var copy := new GradientBoostingRegressor(
|
||||||
fNEstimators,
|
fNEstimators,
|
||||||
fLearningRate,
|
fLearningRate,
|
||||||
fMaxDepth,
|
fMaxDepth,
|
||||||
fMinSamplesSplit,
|
fMinSamplesSplit,
|
||||||
fMinSamplesLeaf,
|
fMinSamplesLeaf,
|
||||||
fSubsample,
|
fSubsample,
|
||||||
fRandomSeed,
|
fRandomSeed);
|
||||||
fLoss,
|
|
||||||
fHuberDelta,
|
|
||||||
fEarlyStoppingPatience,
|
|
||||||
fQuantileAlpha,
|
|
||||||
fLeafL2,
|
|
||||||
fUseOOBEarlyStopping
|
|
||||||
);
|
|
||||||
|
|
||||||
// --- fitted state
|
copy.fInitValue := fInitValue;
|
||||||
c.fFitted := fFitted;
|
copy.fFeatureCount := fFeatureCount;
|
||||||
c.fFeatureCount := fFeatureCount;
|
copy.fFitted := fFitted;
|
||||||
c.fInitValue := fInitValue;
|
|
||||||
|
|
||||||
// --- best/iters
|
foreach var tree in fEstimators do
|
||||||
c.fBestIteration := fBestIteration;
|
copy.fEstimators.Add(tree.Clone as DecisionTreeRegressor);
|
||||||
c.fBestTrainLoss := fBestTrainLoss;
|
|
||||||
c.fBestValLoss := fBestValLoss;
|
|
||||||
|
|
||||||
// --- estimators (deep)
|
Result := copy;
|
||||||
c.fEstimators.Clear;
|
|
||||||
foreach var t in fEstimators do
|
|
||||||
c.fEstimators.Add(DecisionTreeRegressor(t.Clone));
|
|
||||||
|
|
||||||
// --- histories (deep copy values)
|
|
||||||
c.fTrainLossHistory.Clear;
|
|
||||||
foreach var v in fTrainLossHistory do
|
|
||||||
c.fTrainLossHistory.Add(v);
|
|
||||||
|
|
||||||
c.fValLossHistory.Clear;
|
|
||||||
foreach var v in fValLossHistory do
|
|
||||||
c.fValLossHistory.Add(v);
|
|
||||||
|
|
||||||
c.fOOBLossHistory.Clear;
|
|
||||||
foreach var v in fOOBLossHistory do
|
|
||||||
c.fOOBLossHistory.Add(v);
|
|
||||||
|
|
||||||
// --- feature importances (deep)
|
|
||||||
if fFeatureImportances <> nil then
|
|
||||||
begin
|
|
||||||
c.fFeatureImportances := new Vector(fFeatureImportances.Length);
|
|
||||||
for var i := 0 to fFeatureImportances.Length - 1 do
|
|
||||||
c.fFeatureImportances[i] := fFeatureImportances[i];
|
|
||||||
end
|
|
||||||
else
|
|
||||||
c.fFeatureImportances := nil;
|
|
||||||
|
|
||||||
Result := c;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
|
|
@ -3880,9 +4250,28 @@ begin
|
||||||
Result := fFeatureImportances;
|
Result := fFeatureImportances;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function GradientBoostingClassifier.ToString: string;
|
||||||
|
begin
|
||||||
|
var s :=
|
||||||
|
$'GradientBoostingClassifier(' +
|
||||||
|
$'n={fNEstimators}, ' +
|
||||||
|
$'lr={fLearningRate}, ' +
|
||||||
|
$'maxDepth={fMaxDepth}';
|
||||||
|
|
||||||
|
if fSubsample <> 1.0 then
|
||||||
|
s += $', subs={fSubsample}';
|
||||||
|
|
||||||
|
if fEarlyStoppingPatience > 0 then
|
||||||
|
s += $', earlyStop={fEarlyStoppingPatience}';
|
||||||
|
|
||||||
|
s += ')';
|
||||||
|
|
||||||
|
Result := s;
|
||||||
|
end;
|
||||||
|
|
||||||
function GradientBoostingClassifier.Clone: IModel;
|
function GradientBoostingClassifier.Clone: IModel;
|
||||||
begin
|
begin
|
||||||
var c := new GradientBoostingClassifier(
|
var model := new GradientBoostingClassifier(
|
||||||
fNEstimators,
|
fNEstimators,
|
||||||
fLearningRate,
|
fLearningRate,
|
||||||
fMaxDepth,
|
fMaxDepth,
|
||||||
|
|
@ -3894,77 +4283,47 @@ begin
|
||||||
);
|
);
|
||||||
|
|
||||||
// --- fitted state
|
// --- fitted state
|
||||||
c.fFitted := fFitted;
|
model.fFitted := fFitted;
|
||||||
c.fFeatureCount := fFeatureCount;
|
model.fFeatureCount := fFeatureCount;
|
||||||
|
model.fClassCount := fClassCount;
|
||||||
// --- class mapping (deep)
|
|
||||||
c.fClassCount := fClassCount;
|
|
||||||
|
|
||||||
|
// --- classes
|
||||||
if fClasses <> nil then
|
if fClasses <> nil then
|
||||||
begin
|
begin
|
||||||
SetLength(c.fClasses, Length(fClasses));
|
SetLength(model.fClasses, Length(fClasses));
|
||||||
for var i := 0 to Length(fClasses) - 1 do
|
for var i := 0 to Length(fClasses) - 1 do
|
||||||
c.fClasses[i] := fClasses[i];
|
model.fClasses[i] := fClasses[i];
|
||||||
end
|
|
||||||
else
|
|
||||||
c.fClasses := nil;
|
|
||||||
|
|
||||||
c.fClassIndex := new Dictionary<integer, integer>;
|
|
||||||
if fClassIndex <> nil then
|
|
||||||
foreach var kv in fClassIndex do
|
|
||||||
c.fClassIndex[kv.Key] := kv.Value;
|
|
||||||
|
|
||||||
// --- init logits (deep)
|
|
||||||
if fInitLogits <> nil then
|
|
||||||
begin
|
|
||||||
SetLength(c.fInitLogits, Length(fInitLogits));
|
|
||||||
for var i := 0 to Length(fInitLogits) - 1 do
|
|
||||||
c.fInitLogits[i] := fInitLogits[i];
|
|
||||||
end
|
|
||||||
else
|
|
||||||
c.fInitLogits := nil;
|
|
||||||
|
|
||||||
// --- best/iters
|
|
||||||
c.fBestIteration := fBestIteration;
|
|
||||||
c.fBestValLoss := fBestValLoss;
|
|
||||||
|
|
||||||
// --- estimators (deep): List<array of DecisionTreeRegressor>
|
|
||||||
c.fEstimators.Clear;
|
|
||||||
foreach var arr in fEstimators do
|
|
||||||
begin
|
|
||||||
var k := Length(arr);
|
|
||||||
var arr2 := new DecisionTreeRegressor[k];
|
|
||||||
|
|
||||||
for var cls := 0 to k - 1 do
|
|
||||||
arr2[cls] := DecisionTreeRegressor(arr[cls].Clone);
|
|
||||||
|
|
||||||
c.fEstimators.Add(arr2);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- histories
|
if fClassIndex <> nil then
|
||||||
c.fTrainLossHistory.Clear;
|
|
||||||
foreach var v in fTrainLossHistory do
|
|
||||||
c.fTrainLossHistory.Add(v);
|
|
||||||
|
|
||||||
c.fValLossHistory.Clear;
|
|
||||||
foreach var v in fValLossHistory do
|
|
||||||
c.fValLossHistory.Add(v);
|
|
||||||
|
|
||||||
c.fOOBLossHistory.Clear;
|
|
||||||
foreach var v in fOOBLossHistory do
|
|
||||||
c.fOOBLossHistory.Add(v);
|
|
||||||
|
|
||||||
// --- feature importances (deep)
|
|
||||||
if fFeatureImportances <> nil then
|
|
||||||
begin
|
begin
|
||||||
c.fFeatureImportances := new Vector(fFeatureImportances.Length);
|
model.fClassIndex := new Dictionary<integer, integer>;
|
||||||
for var i := 0 to fFeatureImportances.Length - 1 do
|
foreach var kv in fClassIndex do
|
||||||
c.fFeatureImportances[i] := fFeatureImportances[i];
|
model.fClassIndex.Add(kv.Key, kv.Value);
|
||||||
end
|
end;
|
||||||
else
|
|
||||||
c.fFeatureImportances := nil;
|
|
||||||
|
|
||||||
Result := c;
|
// --- estimators (deep copy)
|
||||||
|
foreach var trees in fEstimators do
|
||||||
|
begin
|
||||||
|
var newTrees := new DecisionTreeRegressor[Length(trees)];
|
||||||
|
|
||||||
|
for var cls := 0 to Length(trees) - 1 do
|
||||||
|
newTrees[cls] := trees[cls].Clone as DecisionTreeRegressor;
|
||||||
|
|
||||||
|
model.fEstimators.Add(newTrees);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// --- history
|
||||||
|
foreach var v in fTrainLossHistory do
|
||||||
|
model.fTrainLossHistory.Add(v);
|
||||||
|
|
||||||
|
foreach var v in fValLossHistory do
|
||||||
|
model.fValLossHistory.Add(v);
|
||||||
|
|
||||||
|
model.fBestIteration := fBestIteration;
|
||||||
|
model.fBestValLoss := fBestValLoss;
|
||||||
|
|
||||||
|
Result := model;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function GradientBoostingClassifier.Fit(X: Matrix; y: Vector): IModel;
|
function GradientBoostingClassifier.Fit(X: Matrix; y: Vector): IModel;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue