Небольшой рефакторинг ML
исправление ошибк data Data
This commit is contained in:
parent
94927c73e1
commit
4b02fb9c94
|
|
@ -15,7 +15,7 @@ internal static class RevisionClass
|
|||
public const string Major = "3";
|
||||
public const string Minor = "11";
|
||||
public const string Build = "1";
|
||||
public const string Revision = "3804";
|
||||
public const string Revision = "3805";
|
||||
|
||||
public const string MainVersion = Major + "." + Minor;
|
||||
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
%COREVERSION%=1
|
||||
%REVISION%=3804
|
||||
%MINOR%=11
|
||||
%REVISION%=3805
|
||||
%COREVERSION%=1
|
||||
%MAJOR%=3
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3.11.1.3804
|
||||
3.11.1.3805
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
!define VERSION '3.11.1.3804'
|
||||
!define VERSION '3.11.1.3805'
|
||||
|
|
|
|||
|
|
@ -2119,6 +2119,9 @@ end;
|
|||
|
||||
function DataFrame.RowCount: integer;
|
||||
begin
|
||||
//if (columns[0] is StrColumn (var sc)) and (sc.Data = nil) then
|
||||
// raise new Exception('Data = nil detected');
|
||||
|
||||
if columns.Count = 0 then
|
||||
Result := 0
|
||||
else Result := columns[0].RowCount;
|
||||
|
|
|
|||
|
|
@ -109,8 +109,7 @@ type
|
|||
public
|
||||
constructor Create; begin end;
|
||||
constructor Create(name: string);
|
||||
constructor Create(name: string; data: array of integer;
|
||||
valid: array of boolean := nil);
|
||||
constructor Create(name: string; values: array of integer; valid: array of boolean := nil);
|
||||
function TryGetNumericValue(i: integer; var value: real): boolean; override;
|
||||
/// Возвращает количество строк в столбце
|
||||
function RowCount: integer; override := Data.Length;
|
||||
|
|
@ -123,7 +122,7 @@ type
|
|||
public
|
||||
constructor Create; begin end;
|
||||
constructor Create(name: string);
|
||||
constructor Create(name: string; data: array of real;
|
||||
constructor Create(name: string; values: array of real;
|
||||
valid: array of boolean := nil);
|
||||
function TryGetNumericValue(i: integer; var value: real): boolean; override;
|
||||
/// Возвращает количество строк в столбце
|
||||
|
|
@ -137,7 +136,7 @@ type
|
|||
public
|
||||
constructor Create; begin end;
|
||||
constructor Create(name: string);
|
||||
constructor Create(name: string; data: array of string;
|
||||
constructor Create(name: string; values: array of string;
|
||||
valid: array of boolean := nil);
|
||||
function TryGetNumericValue(i: integer; var value: real): boolean; override;
|
||||
/// Возвращает количество строк в столбце
|
||||
|
|
@ -155,7 +154,7 @@ type
|
|||
public
|
||||
constructor Create; begin end;
|
||||
constructor Create(name: string);
|
||||
constructor Create(name: string; data: array of boolean;
|
||||
constructor Create(name: string; values: array of boolean;
|
||||
valid: array of boolean := nil);
|
||||
function TryGetNumericValue(i: integer; var value: real): boolean; override;
|
||||
/// Возвращает количество строк в столбце
|
||||
|
|
@ -564,13 +563,13 @@ end;
|
|||
// Columns
|
||||
//-----------------------------
|
||||
|
||||
constructor IntColumn.Create(name: string; data: array of integer; valid: array of boolean);
|
||||
constructor IntColumn.Create(name: string; values: array of integer; valid: array of boolean);
|
||||
begin
|
||||
inherited Create;
|
||||
Info := new ColumnInfo(name, ctInt);
|
||||
|
||||
var n := Length(data);
|
||||
Data := if n = 0 then [] else data;
|
||||
var n := Length(values);
|
||||
Self.Data := if n = 0 then [] else values;
|
||||
|
||||
if valid = nil then
|
||||
IsValid := [True] * n
|
||||
|
|
@ -588,8 +587,8 @@ begin
|
|||
inherited Create;
|
||||
Info := new ColumnInfo(name, ctInt);
|
||||
|
||||
Data := [];
|
||||
IsValid := [];
|
||||
Data := new integer[0];
|
||||
IsValid := new boolean[0];
|
||||
end;
|
||||
|
||||
function IntColumn.TryGetNumericValue(i: integer; var value: real): boolean;
|
||||
|
|
@ -601,13 +600,13 @@ begin
|
|||
exit(True);
|
||||
end;
|
||||
|
||||
constructor FloatColumn.Create(name: string; data: array of real; valid: array of boolean);
|
||||
constructor FloatColumn.Create(name: string; values: array of real; valid: array of boolean);
|
||||
begin
|
||||
inherited Create;
|
||||
Info := new ColumnInfo(name, ctFloat);
|
||||
|
||||
var n := Length(data);
|
||||
Data := if n = 0 then [] else data;
|
||||
var n := Length(values);
|
||||
Self.Data := if n = 0 then [] else values;
|
||||
|
||||
if valid = nil then
|
||||
IsValid := [True] * n
|
||||
|
|
@ -625,8 +624,8 @@ begin
|
|||
inherited Create;
|
||||
Info := new ColumnInfo(name, ctFloat);
|
||||
|
||||
Data := [];
|
||||
IsValid := [];
|
||||
Data := new real[0];
|
||||
IsValid := new boolean[0];
|
||||
end;
|
||||
|
||||
function FloatColumn.TryGetNumericValue(i: integer; var value: real): boolean;
|
||||
|
|
@ -638,13 +637,13 @@ begin
|
|||
exit(True);
|
||||
end;
|
||||
|
||||
constructor StrColumn.Create(name: string; data: array of string; valid: array of boolean);
|
||||
constructor StrColumn.Create(name: string; values: array of string; valid: array of boolean);
|
||||
begin
|
||||
inherited Create;
|
||||
Info := new ColumnInfo(name, ctStr);
|
||||
|
||||
var n := Length(data);
|
||||
Data := if n = 0 then [] else data;
|
||||
var n := Length(values);
|
||||
Self.Data := if n = 0 then [] else values;
|
||||
|
||||
if valid = nil then
|
||||
IsValid := [True] * n
|
||||
|
|
@ -662,8 +661,8 @@ begin
|
|||
inherited Create;
|
||||
Info := new ColumnInfo(name, ctStr);
|
||||
|
||||
Data := [];
|
||||
IsValid := [];
|
||||
Data := new string[0];
|
||||
IsValid := new boolean[0];
|
||||
end;
|
||||
|
||||
function StrColumn.TryGetNumericValue(i: integer; var value: real): boolean;
|
||||
|
|
@ -671,13 +670,13 @@ begin
|
|||
exit(False);
|
||||
end;
|
||||
|
||||
constructor BoolColumn.Create(name: string; data: array of boolean; valid: array of boolean);
|
||||
constructor BoolColumn.Create(name: string; values: array of boolean; valid: array of boolean);
|
||||
begin
|
||||
inherited Create;
|
||||
Info := new ColumnInfo(name, ctBool);
|
||||
|
||||
var n := Length(data);
|
||||
Data := if n = 0 then [] else data;
|
||||
var n := Length(values);
|
||||
Self.Data := if n = 0 then [] else values;
|
||||
|
||||
if valid = nil then
|
||||
IsValid := [True] * n
|
||||
|
|
@ -695,8 +694,8 @@ begin
|
|||
inherited Create;
|
||||
Info := new ColumnInfo(name, ctBool);
|
||||
|
||||
Data := [];
|
||||
IsValid := [];
|
||||
Data := new boolean[0];
|
||||
IsValid := new boolean[0];
|
||||
end;
|
||||
|
||||
function BoolColumn.TryGetNumericValue(i: integer; var value: real): boolean;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,10 @@ type
|
|||
/// Вектор важностей признаков длины nFeatures.
|
||||
/// Чем больше значение, тем сильнее признак влияет на качество модели
|
||||
static function PermutationImportance(model: IPredictiveModel; X: Matrix; y: Vector;
|
||||
scoreFunc: (Vector, Vector) -> real; nRepeats: integer := 5; seed: integer := -1): Vector;
|
||||
scoreFunc: (Vector, Vector) -> real;
|
||||
nRepeats: integer := 5;
|
||||
higherIsBetter: boolean := True;
|
||||
seed: integer := -1): Vector;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
|
@ -61,12 +64,11 @@ const
|
|||
|
||||
static function Inspection.PermutationImportance(
|
||||
model: IPredictiveModel;
|
||||
X: Matrix;
|
||||
y: Vector;
|
||||
X: Matrix; y: Vector;
|
||||
scoreFunc: (Vector, Vector) -> real;
|
||||
nRepeats: integer;
|
||||
seed: integer
|
||||
): Vector;
|
||||
higherIsBetter: boolean;
|
||||
seed: integer): Vector;
|
||||
begin
|
||||
if model = nil then
|
||||
ArgumentNullError(ER_MODEL_NULL);
|
||||
|
|
@ -122,7 +124,10 @@ begin
|
|||
var permPred := model.Predict(Xperm);
|
||||
var permScore := scoreFunc(y, permPred);
|
||||
|
||||
acc += (baselineScore - permScore);
|
||||
if higherIsBetter then
|
||||
acc += (baselineScore - permScore)
|
||||
else
|
||||
acc += (permScore - baselineScore);
|
||||
end;
|
||||
|
||||
resultVec[j] := acc / nRepeats;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ interface
|
|||
|
||||
const
|
||||
ER_DIM_MISMATCH =
|
||||
'Несоответствие размерностей: {0} и {1}!!Dimension mismatch: {0} and {1}';
|
||||
'Размерности не совпадают: {0} и {1}!!Dimension mismatch: {0} and {1}';
|
||||
ER_PARAM_VALUES_EMPTY =
|
||||
'Список paramValues пуст!!paramValues is empty';
|
||||
ER_EMPTY_DATASET =
|
||||
|
|
@ -25,6 +25,33 @@ const
|
|||
'В DataFrame отсутствует столбец "{0}"!!DataFrame does not contain column "{0}"';
|
||||
ER_NOT_IMPLEMENTED =
|
||||
'Метод {0} не реализован!!Method {0} is not implemented';
|
||||
ER_X_NULL =
|
||||
'X не может быть nil!!X cannot be nil';
|
||||
ER_Y_NULL =
|
||||
'y не может быть nil!!y cannot be nil';
|
||||
ER_XY_SIZE_MISMATCH =
|
||||
'Размерности X и y не согласованы!!X and y size mismatch';
|
||||
ER_FEATURE_COUNT_MISMATCH =
|
||||
'Число признаков не совпадает!!Feature count mismatch';
|
||||
ER_NAN_IN_X =
|
||||
'X содержит NaN (пропуски)!!X contains NaN';
|
||||
ER_NAN_IN_Y =
|
||||
'y содержит NaN (пропуски)!!y contains NaN';
|
||||
ER_TRAINING_DATA_CONTAINS_NAN =
|
||||
'Обучающие данные содержат NaN. Обработайте пропуски до вызова Fit.!!' +
|
||||
'Training data contains NaN. Please handle missing values before calling Fit.';
|
||||
ER_TRAINING_DATA_CONTAINS_INF =
|
||||
'Обучающие данные содержат Infinity. Проверьте данные на выбросы.!!' +
|
||||
'Training data contains Infinity. Please check for extreme values.';
|
||||
ER_PREDICTION_DATA_CONTAINS_NAN =
|
||||
'Данные для предсказания содержат NaN. Обработайте пропуски до вызова Predict.!!' +
|
||||
'Prediction data contains NaN. Please handle missing values before calling Predict.';
|
||||
ER_PREDICTION_DATA_CONTAINS_INF =
|
||||
'Данные для предсказания содержат Infinity. Проверьте данные на выбросы.!!' +
|
||||
'Prediction data contains Infinity. Please check for extreme values.';
|
||||
ER_MODEL_NOT_FITTED =
|
||||
'Модель "{0}" не обучена. Сначала вызовите Fit()|Model "{0}" is not fitted. Call Fit() first';
|
||||
|
||||
|
||||
type
|
||||
/// Базовое исключение ML-библиотеки
|
||||
|
|
|
|||
|
|
@ -1,17 +1,4 @@
|
|||
// =============================================================
|
||||
// СТАТИСТИЧЕСКОЕ СОГЛАШЕНИЕ (MLModelsABC)
|
||||
//
|
||||
// Модели и трансформеры используют статистические методы
|
||||
// из LinearAlgebraML.
|
||||
//
|
||||
// В частности:
|
||||
// • StandardScaler, VarianceThreshold и др. используют
|
||||
// дисперсию с делением на n (population variance)
|
||||
//
|
||||
// См. статистическую политику в модуле MLABC.
|
||||
// =============================================================
|
||||
|
||||
/// Модуль моделей машинного обучения и матричных преобразований.
|
||||
/// Модуль моделей машинного обучения и матричных преобразований.
|
||||
///
|
||||
/// Содержит:
|
||||
/// • функции активации
|
||||
|
|
@ -25,6 +12,19 @@
|
|||
/// X — Matrix (объекты × признаки), y — Vector (целевая переменная).
|
||||
unit MLModelsABC;
|
||||
|
||||
// =============================================================
|
||||
// СТАТИСТИЧЕСКОЕ СОГЛАШЕНИЕ (MLModelsABC)
|
||||
//
|
||||
// Модели и трансформеры используют статистические методы
|
||||
// из LinearAlgebraML.
|
||||
//
|
||||
// В частности:
|
||||
// • StandardScaler, VarianceThreshold и др. используют
|
||||
// дисперсию с делением на n (population variance)
|
||||
//
|
||||
// См. статистическую политику в модуле MLABC.
|
||||
// =============================================================
|
||||
|
||||
interface
|
||||
|
||||
uses MLCoreABC;
|
||||
|
|
@ -205,7 +205,7 @@ type
|
|||
/// Обучение выполняется методом покоординатного спуска
|
||||
/// ВАЖНО: Модель чувствительна к масштабу признаков.
|
||||
/// Всегда используйте StandardScaler в Pipeline перед ElasticNet.
|
||||
ElasticNet = class(IRegressor)
|
||||
ElasticNet = class(IRegressor)
|
||||
private
|
||||
fLambda1: real; // L1
|
||||
fLambda2: real; // L2
|
||||
|
|
@ -549,6 +549,7 @@ type
|
|||
minSamplesSplit: integer;
|
||||
minSamplesLeaf: integer;
|
||||
criterion: ISplitCriterion;
|
||||
classCount: integer;
|
||||
maxFeatures: integer;
|
||||
seed: integer := -1
|
||||
);
|
||||
|
|
@ -2023,7 +2024,11 @@ type
|
|||
|
||||
/// Стандартизирует признаки: вычитает среднее
|
||||
/// и делит на стандартное отклонение по каждому столбцу.
|
||||
/// Используется для приведения признаков к сопоставимому масштабу
|
||||
/// Используется для приведения признаков к сопоставимому масштабу.
|
||||
///
|
||||
/// Примечание:
|
||||
/// • стандартное отклонение вычисляется с делением на n
|
||||
/// (population variance, как в sklearn)
|
||||
StandardScaler = class(IUnsupervisedTransformer)
|
||||
private
|
||||
fMean: Vector;
|
||||
|
|
@ -2438,16 +2443,6 @@ const
|
|||
'Неизвестный тип FeatureScore!!Unknown FeatureScore type';
|
||||
ER_SELECTKBEST_FIT_INVALID =
|
||||
'Для SelectKBest необходимо вызывать Fit(X, y)!!SelectKBest requires Fit(X, y)';
|
||||
ER_FIT_NOT_CALLED =
|
||||
'Необходимо вызвать Fit перед Predict!!Fit must be called before Predict';
|
||||
ER_X_NULL =
|
||||
'X не может быть nil!!X cannot be nil';
|
||||
ER_Y_NULL =
|
||||
'y не может быть nil!!y cannot be nil';
|
||||
ER_XY_SIZE_MISMATCH =
|
||||
'Размерности X и y не согласованы!!X and y size mismatch';
|
||||
ER_FEATURE_COUNT_MISMATCH =
|
||||
'Число признаков не совпадает!!Feature count mismatch';
|
||||
ER_N_ESTIMATORS_NOT_POSITIVE =
|
||||
'Параметр nEstimators должен быть > 0!!nEstimators must be > 0';
|
||||
ER_LEARNING_RATE_NOT_POSITIVE =
|
||||
|
|
@ -2464,10 +2459,6 @@ const
|
|||
'maxDepth должен быть > 0!!maxDepth must be > 0';
|
||||
ER_SUBSAMPLE_INVALID =
|
||||
'subsample должен быть > 0!!subsample must be > 0';
|
||||
ER_NAN_IN_Y =
|
||||
'y содержит NaN!!y contains NaN';
|
||||
ER_NAN_IN_X =
|
||||
'x содержит NaN!!x contains NaN';
|
||||
ER_K_EXCEEDS_SAMPLES =
|
||||
'k превышает число обучающих объектов!!k exceeds number of training samples';
|
||||
ER_MAX_DEPTH_TOO_LARGE =
|
||||
|
|
@ -2488,18 +2479,6 @@ const
|
|||
ER_ELASTICNET_INVALID_LOSS =
|
||||
'Функция потерь ElasticNet стала NaN или Infinity.' +
|
||||
'ElasticNet loss became NaN or Infinity.';
|
||||
ER_TRAINING_DATA_CONTAINS_NAN =
|
||||
'Обучающие данные содержат NaN. Обработайте пропуски до вызова Fit.!!' +
|
||||
'Training data contains NaN. Please handle missing values before calling Fit.';
|
||||
ER_TRAINING_DATA_CONTAINS_INF =
|
||||
'Обучающие данные содержат Infinity. Проверьте данные на выбросы.!!' +
|
||||
'Training data contains Infinity. Please check for extreme values.';
|
||||
ER_PREDICTION_DATA_CONTAINS_NAN =
|
||||
'Данные для предсказания содержат NaN. Обработайте пропуски до вызова Predict.!!' +
|
||||
'Prediction data contains NaN. Please handle missing values before calling Predict.';
|
||||
ER_PREDICTION_DATA_CONTAINS_INF =
|
||||
'Данные для предсказания содержат Infinity. Проверьте данные на выбросы.!!' +
|
||||
'Prediction data contains Infinity. Please check for extreme values.';
|
||||
ER_MAXITER_INVALID =
|
||||
'maxIter должен быть положительным. Получено {0}.!!' +
|
||||
'maxIter must be positive. Received {0}.';
|
||||
|
|
@ -2598,8 +2577,6 @@ const
|
|||
'Model (type: {0}) is not an unsupervised model';
|
||||
ER_DBSCAN_PREDICT_ONLY_TRAIN_DATA =
|
||||
'DBSCAN: Predict поддерживается только для обучающей выборки!!DBSCAN: Predict is only supported for training data';
|
||||
ER_MODEL_NOT_FITTED =
|
||||
'Модель "{0}" не обучена. Сначала вызовите Fit()|Model "{0}" is not fitted. Call Fit() first';
|
||||
ER_DBSCAN_PREDICT_NEW_DATA =
|
||||
'DBSCAN не поддерживает предсказание для новых данных!!DBSCAN does not support prediction for new data';
|
||||
ER_CLASSES_NOT_AVAILABLE =
|
||||
|
|
@ -2618,7 +2595,9 @@ const
|
|||
ER_UNKNOWN_CLASS_LABEL =
|
||||
'Неизвестная метка класса: {0}!!Unknown class label: {0}';
|
||||
ER_MAX_FEATURES_INVALID =
|
||||
'maxFeatures должен быть >= 0!!maxFeatures must be >= 0';
|
||||
'maxFeatures должен быть >= 0!!maxFeatures must be >= 0';
|
||||
ER_OOB_REQUIRES_SUBSAMPLE =
|
||||
'Для OOB early stopping требуется subsample < 1.0!!OOB early stopping requires subsample < 1.0';
|
||||
|
||||
{$endregion ErrConstants}
|
||||
|
||||
|
|
@ -3526,7 +3505,6 @@ begin
|
|||
Result := res;
|
||||
end;
|
||||
|
||||
|
||||
function LeafClass(c: integer): DecisionTreeNode;
|
||||
begin
|
||||
var n := new DecisionTreeNode;
|
||||
|
|
@ -3582,6 +3560,7 @@ constructor DecisionTreeCore.Create(
|
|||
minSamplesSplit: integer;
|
||||
minSamplesLeaf: integer;
|
||||
criterion: ISplitCriterion;
|
||||
classCount: integer;
|
||||
maxFeatures: integer;
|
||||
seed: integer
|
||||
);
|
||||
|
|
@ -3591,6 +3570,7 @@ begin
|
|||
fMinSamplesLeaf := minSamplesLeaf;
|
||||
fCriterion := criterion;
|
||||
fMaxFeatures := maxFeatures;
|
||||
fClassCount := classCount;
|
||||
|
||||
fRandomSeed := ResolveRandomSeed(seed, fUserProvidedSeed);
|
||||
fRng := new System.Random(fRandomSeed);
|
||||
|
|
@ -3782,7 +3762,7 @@ begin
|
|||
yr := y.SubvectorBy(rightArr);
|
||||
end;
|
||||
|
||||
function DecisionTreeCore.FindBestSplit(
|
||||
{function DecisionTreeCore.FindBestSplit(
|
||||
X: Matrix;
|
||||
y: Vector;
|
||||
indices: array of integer;
|
||||
|
|
@ -3888,6 +3868,160 @@ begin
|
|||
end;
|
||||
end;
|
||||
end;
|
||||
end;}
|
||||
|
||||
// Новая реализация (O(n log n · p))
|
||||
function DecisionTreeCore.FindBestSplit(
|
||||
X: Matrix;
|
||||
y: Vector;
|
||||
indices: array of integer;
|
||||
var bestF: integer;
|
||||
var bestT: real
|
||||
): boolean;
|
||||
begin
|
||||
Result := false;
|
||||
|
||||
var n := indices.Length;
|
||||
if n < 2 then exit;
|
||||
|
||||
var parentImp := fCriterion.Impurity(y, indices);
|
||||
var bestScore := parentImp;
|
||||
|
||||
var featureCount := X.ColCount;
|
||||
|
||||
// --- выбор признаков (как было)
|
||||
var features: array of integer;
|
||||
|
||||
if (fMaxFeatures > 0) and (fMaxFeatures < featureCount) then
|
||||
begin
|
||||
var perm := new integer[featureCount];
|
||||
for var i := 0 to featureCount - 1 do
|
||||
perm[i] := i;
|
||||
|
||||
for var i := 0 to fMaxFeatures - 1 do
|
||||
begin
|
||||
var j := i + fRng.Next(featureCount - i);
|
||||
var tmp := perm[i];
|
||||
perm[i] := perm[j];
|
||||
perm[j] := tmp;
|
||||
end;
|
||||
|
||||
SetLength(features, fMaxFeatures);
|
||||
for var i := 0 to fMaxFeatures - 1 do
|
||||
features[i] := perm[i];
|
||||
end
|
||||
else
|
||||
begin
|
||||
SetLength(features, featureCount);
|
||||
for var i := 0 to featureCount - 1 do
|
||||
features[i] := i;
|
||||
end;
|
||||
|
||||
// --- перебор признаков
|
||||
for var fi := 0 to features.Length - 1 do
|
||||
begin
|
||||
var f := features[fi];
|
||||
|
||||
// пары (value, index)
|
||||
var pairs: array of (real, integer);
|
||||
SetLength(pairs, n);
|
||||
|
||||
for var i := 0 to n - 1 do
|
||||
begin
|
||||
var idx := indices[i];
|
||||
pairs[i] := (X[idx, f], idx);
|
||||
end;
|
||||
|
||||
pairs.Sort(p -> p.Item1);
|
||||
|
||||
// --- counts
|
||||
var leftCounts := new integer[fClassCount];
|
||||
var rightCounts := new integer[fClassCount];
|
||||
|
||||
for var i := 0 to n - 1 do
|
||||
rightCounts[Round(y[pairs[i].Item2])] += 1;
|
||||
|
||||
var leftCount := 0;
|
||||
|
||||
// --- проход
|
||||
for var i := 1 to n - 1 do
|
||||
begin
|
||||
var idx := pairs[i-1].Item2;
|
||||
var cls := Round(y[idx]);
|
||||
|
||||
leftCounts[cls] += 1;
|
||||
rightCounts[cls] -= 1;
|
||||
leftCount += 1;
|
||||
|
||||
var rightCount := n - leftCount;
|
||||
|
||||
if (leftCount < fMinSamplesLeaf) or (rightCount < fMinSamplesLeaf) then
|
||||
continue;
|
||||
|
||||
var x1 := pairs[i-1].Item1;
|
||||
var x2 := pairs[i].Item1;
|
||||
|
||||
if x1 = x2 then
|
||||
continue;
|
||||
|
||||
// --- impurity left
|
||||
var leftImp := 0.0;
|
||||
var rightImp := 0.0;
|
||||
|
||||
if fCriterion is GiniCriterion then
|
||||
begin
|
||||
var sumsqL := 0.0;
|
||||
var sumsqR := 0.0;
|
||||
|
||||
for var c := 0 to fClassCount - 1 do
|
||||
begin
|
||||
if leftCounts[c] > 0 then
|
||||
begin
|
||||
var p := leftCounts[c] / leftCount;
|
||||
sumsqL += p * p;
|
||||
end;
|
||||
|
||||
if rightCounts[c] > 0 then
|
||||
begin
|
||||
var p := rightCounts[c] / rightCount;
|
||||
sumsqR += p * p;
|
||||
end;
|
||||
end;
|
||||
|
||||
leftImp := 1.0 - sumsqL;
|
||||
rightImp := 1.0 - sumsqR;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// entropy
|
||||
for var c := 0 to fClassCount - 1 do
|
||||
begin
|
||||
if leftCounts[c] > 0 then
|
||||
begin
|
||||
var p := leftCounts[c] / leftCount;
|
||||
leftImp -= p * Ln(p);
|
||||
end;
|
||||
|
||||
if rightCounts[c] > 0 then
|
||||
begin
|
||||
var p := rightCounts[c] / rightCount;
|
||||
rightImp -= p * Ln(p);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
var score :=
|
||||
(leftCount * leftImp + rightCount * rightImp) / n;
|
||||
|
||||
if score < bestScore then
|
||||
begin
|
||||
bestScore := score;
|
||||
bestF := f;
|
||||
bestT := (x1 + x2) * 0.5;
|
||||
Result := true;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function DecisionTreeCore.Clone: DecisionTreeCore;
|
||||
|
|
@ -5575,6 +5709,10 @@ begin
|
|||
if XVal.ColCount <> XTrain.ColCount then
|
||||
DimensionError(ER_FEATURE_COUNT_MISMATCH);
|
||||
end;
|
||||
|
||||
// --- OOB checks ---
|
||||
if fUseOOBEarlyStopping and (fSubsample >= 1.0) then
|
||||
ArgumentError(ER_OOB_REQUIRES_SUBSAMPLE);
|
||||
|
||||
// --- init state ---
|
||||
fOOBLossHistory.Clear;
|
||||
|
|
@ -6735,7 +6873,7 @@ begin
|
|||
NotFittedError(ER_FIT_NOT_CALLED);
|
||||
|
||||
if fFeatureImportances <> nil then
|
||||
exit(fFeatureImportances);
|
||||
exit(fFeatureImportances.Clone);
|
||||
|
||||
var importances := new Vector(fFeatureCount);
|
||||
|
||||
|
|
@ -6758,7 +6896,7 @@ begin
|
|||
|
||||
fFeatureImportances := importances;
|
||||
|
||||
Result := fFeatureImportances;
|
||||
Result := fFeatureImportances.Clone;
|
||||
end;
|
||||
|
||||
function GradientBoostingClassifier.ToString: string;
|
||||
|
|
@ -7820,9 +7958,6 @@ begin
|
|||
var n := X.RowCount;
|
||||
var p := X.ColCount;
|
||||
|
||||
if n = 0 then
|
||||
ArgumentError(ER_EMPTY_DATA, 'DBSCAN');
|
||||
|
||||
fFeatureCount := p;
|
||||
|
||||
var labels := new integer[n];
|
||||
|
|
|
|||
|
|
@ -285,7 +285,7 @@ const
|
|||
ER_CLASSES_NOT_AVAILABLE =
|
||||
'Метки классов недоступны. Убедитесь, что конвейер обучен и задача — классификация!!Class labels are not available. Ensure the pipeline is fitted and the task is classification';
|
||||
ER_LABELENCODER_TARGET_NOT_ALLOWED =
|
||||
'LabelEncoder нельзя применять к целевому столбцу. Используйте EncodeLabels!!LabelEncoder cannot be applied to the target column. Use EncodeLabels instead';
|
||||
'LabelEncoder нельзя применять к целевой переменной — кодирование выполняется внутри модели!!LabelEncoder cannot be applied to target — encoding is handled internally by the model';
|
||||
ER_ENCODELABELS_NOT_CATEGORICAL =
|
||||
'Целевой столбец должен быть категориальным для задач классификации!!Target column must be categorical for classification tasks';
|
||||
ER_PIPELINE_TARGET_TRANSFORM_NOT_ALLOWED =
|
||||
|
|
|
|||
|
|
@ -319,11 +319,12 @@ begin
|
|||
var cls := pair.Key;
|
||||
var cnt := pair.Value.Count;
|
||||
|
||||
if cnt < k then
|
||||
ArgumentError(
|
||||
ER_STRATIFIED_CLASS_TOO_SMALL,
|
||||
cls, cnt, k
|
||||
);
|
||||
// Класс может иметь меньше объектов, чем число фолдов.
|
||||
// В этом случае он не будет представлен во всех фолдах.
|
||||
// Это допустимо, но может привести к ошибкам при обучении модели.
|
||||
|
||||
//if cnt < k then
|
||||
// ArgumentError(ER_STRATIFIED_CLASS_TOO_SMALL, cls, cnt, k);
|
||||
end;
|
||||
|
||||
// --- 2. Контейнеры фолдов
|
||||
|
|
|
|||
Loading…
Reference in a new issue