Небольшой рефакторинг 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 Major = "3";
|
||||||
public const string Minor = "11";
|
public const string Minor = "11";
|
||||||
public const string Build = "1";
|
public const string Build = "1";
|
||||||
public const string Revision = "3804";
|
public const string Revision = "3805";
|
||||||
|
|
||||||
public const string MainVersion = Major + "." + Minor;
|
public const string MainVersion = Major + "." + Minor;
|
||||||
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
|
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
%COREVERSION%=1
|
|
||||||
%REVISION%=3804
|
|
||||||
%MINOR%=11
|
%MINOR%=11
|
||||||
|
%REVISION%=3805
|
||||||
|
%COREVERSION%=1
|
||||||
%MAJOR%=3
|
%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;
|
function DataFrame.RowCount: integer;
|
||||||
begin
|
begin
|
||||||
|
//if (columns[0] is StrColumn (var sc)) and (sc.Data = nil) then
|
||||||
|
// raise new Exception('Data = nil detected');
|
||||||
|
|
||||||
if columns.Count = 0 then
|
if columns.Count = 0 then
|
||||||
Result := 0
|
Result := 0
|
||||||
else Result := columns[0].RowCount;
|
else Result := columns[0].RowCount;
|
||||||
|
|
|
||||||
|
|
@ -109,8 +109,7 @@ type
|
||||||
public
|
public
|
||||||
constructor Create; begin end;
|
constructor Create; begin end;
|
||||||
constructor Create(name: string);
|
constructor Create(name: string);
|
||||||
constructor Create(name: string; data: array of integer;
|
constructor Create(name: string; values: array of integer; valid: array of boolean := nil);
|
||||||
valid: array of boolean := nil);
|
|
||||||
function TryGetNumericValue(i: integer; var value: real): boolean; override;
|
function TryGetNumericValue(i: integer; var value: real): boolean; override;
|
||||||
/// Возвращает количество строк в столбце
|
/// Возвращает количество строк в столбце
|
||||||
function RowCount: integer; override := Data.Length;
|
function RowCount: integer; override := Data.Length;
|
||||||
|
|
@ -123,7 +122,7 @@ type
|
||||||
public
|
public
|
||||||
constructor Create; begin end;
|
constructor Create; begin end;
|
||||||
constructor Create(name: string);
|
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);
|
valid: array of boolean := nil);
|
||||||
function TryGetNumericValue(i: integer; var value: real): boolean; override;
|
function TryGetNumericValue(i: integer; var value: real): boolean; override;
|
||||||
/// Возвращает количество строк в столбце
|
/// Возвращает количество строк в столбце
|
||||||
|
|
@ -137,7 +136,7 @@ type
|
||||||
public
|
public
|
||||||
constructor Create; begin end;
|
constructor Create; begin end;
|
||||||
constructor Create(name: string);
|
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);
|
valid: array of boolean := nil);
|
||||||
function TryGetNumericValue(i: integer; var value: real): boolean; override;
|
function TryGetNumericValue(i: integer; var value: real): boolean; override;
|
||||||
/// Возвращает количество строк в столбце
|
/// Возвращает количество строк в столбце
|
||||||
|
|
@ -155,7 +154,7 @@ type
|
||||||
public
|
public
|
||||||
constructor Create; begin end;
|
constructor Create; begin end;
|
||||||
constructor Create(name: string);
|
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);
|
valid: array of boolean := nil);
|
||||||
function TryGetNumericValue(i: integer; var value: real): boolean; override;
|
function TryGetNumericValue(i: integer; var value: real): boolean; override;
|
||||||
/// Возвращает количество строк в столбце
|
/// Возвращает количество строк в столбце
|
||||||
|
|
@ -564,13 +563,13 @@ end;
|
||||||
// Columns
|
// 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
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
Info := new ColumnInfo(name, ctInt);
|
Info := new ColumnInfo(name, ctInt);
|
||||||
|
|
||||||
var n := Length(data);
|
var n := Length(values);
|
||||||
Data := if n = 0 then [] else data;
|
Self.Data := if n = 0 then [] else values;
|
||||||
|
|
||||||
if valid = nil then
|
if valid = nil then
|
||||||
IsValid := [True] * n
|
IsValid := [True] * n
|
||||||
|
|
@ -588,8 +587,8 @@ begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
Info := new ColumnInfo(name, ctInt);
|
Info := new ColumnInfo(name, ctInt);
|
||||||
|
|
||||||
Data := [];
|
Data := new integer[0];
|
||||||
IsValid := [];
|
IsValid := new boolean[0];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function IntColumn.TryGetNumericValue(i: integer; var value: real): boolean;
|
function IntColumn.TryGetNumericValue(i: integer; var value: real): boolean;
|
||||||
|
|
@ -601,13 +600,13 @@ begin
|
||||||
exit(True);
|
exit(True);
|
||||||
end;
|
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
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
Info := new ColumnInfo(name, ctFloat);
|
Info := new ColumnInfo(name, ctFloat);
|
||||||
|
|
||||||
var n := Length(data);
|
var n := Length(values);
|
||||||
Data := if n = 0 then [] else data;
|
Self.Data := if n = 0 then [] else values;
|
||||||
|
|
||||||
if valid = nil then
|
if valid = nil then
|
||||||
IsValid := [True] * n
|
IsValid := [True] * n
|
||||||
|
|
@ -625,8 +624,8 @@ begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
Info := new ColumnInfo(name, ctFloat);
|
Info := new ColumnInfo(name, ctFloat);
|
||||||
|
|
||||||
Data := [];
|
Data := new real[0];
|
||||||
IsValid := [];
|
IsValid := new boolean[0];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function FloatColumn.TryGetNumericValue(i: integer; var value: real): boolean;
|
function FloatColumn.TryGetNumericValue(i: integer; var value: real): boolean;
|
||||||
|
|
@ -638,13 +637,13 @@ begin
|
||||||
exit(True);
|
exit(True);
|
||||||
end;
|
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
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
Info := new ColumnInfo(name, ctStr);
|
Info := new ColumnInfo(name, ctStr);
|
||||||
|
|
||||||
var n := Length(data);
|
var n := Length(values);
|
||||||
Data := if n = 0 then [] else data;
|
Self.Data := if n = 0 then [] else values;
|
||||||
|
|
||||||
if valid = nil then
|
if valid = nil then
|
||||||
IsValid := [True] * n
|
IsValid := [True] * n
|
||||||
|
|
@ -662,8 +661,8 @@ begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
Info := new ColumnInfo(name, ctStr);
|
Info := new ColumnInfo(name, ctStr);
|
||||||
|
|
||||||
Data := [];
|
Data := new string[0];
|
||||||
IsValid := [];
|
IsValid := new boolean[0];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function StrColumn.TryGetNumericValue(i: integer; var value: real): boolean;
|
function StrColumn.TryGetNumericValue(i: integer; var value: real): boolean;
|
||||||
|
|
@ -671,13 +670,13 @@ begin
|
||||||
exit(False);
|
exit(False);
|
||||||
end;
|
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
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
Info := new ColumnInfo(name, ctBool);
|
Info := new ColumnInfo(name, ctBool);
|
||||||
|
|
||||||
var n := Length(data);
|
var n := Length(values);
|
||||||
Data := if n = 0 then [] else data;
|
Self.Data := if n = 0 then [] else values;
|
||||||
|
|
||||||
if valid = nil then
|
if valid = nil then
|
||||||
IsValid := [True] * n
|
IsValid := [True] * n
|
||||||
|
|
@ -695,8 +694,8 @@ begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
Info := new ColumnInfo(name, ctBool);
|
Info := new ColumnInfo(name, ctBool);
|
||||||
|
|
||||||
Data := [];
|
Data := new boolean[0];
|
||||||
IsValid := [];
|
IsValid := new boolean[0];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function BoolColumn.TryGetNumericValue(i: integer; var value: real): boolean;
|
function BoolColumn.TryGetNumericValue(i: integer; var value: real): boolean;
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,10 @@ type
|
||||||
/// Вектор важностей признаков длины nFeatures.
|
/// Вектор важностей признаков длины nFeatures.
|
||||||
/// Чем больше значение, тем сильнее признак влияет на качество модели
|
/// Чем больше значение, тем сильнее признак влияет на качество модели
|
||||||
static function PermutationImportance(model: IPredictiveModel; X: Matrix; y: Vector;
|
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;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
@ -61,12 +64,11 @@ const
|
||||||
|
|
||||||
static function Inspection.PermutationImportance(
|
static function Inspection.PermutationImportance(
|
||||||
model: IPredictiveModel;
|
model: IPredictiveModel;
|
||||||
X: Matrix;
|
X: Matrix; y: Vector;
|
||||||
y: Vector;
|
|
||||||
scoreFunc: (Vector, Vector) -> real;
|
scoreFunc: (Vector, Vector) -> real;
|
||||||
nRepeats: integer;
|
nRepeats: integer;
|
||||||
seed: integer
|
higherIsBetter: boolean;
|
||||||
): Vector;
|
seed: integer): Vector;
|
||||||
begin
|
begin
|
||||||
if model = nil then
|
if model = nil then
|
||||||
ArgumentNullError(ER_MODEL_NULL);
|
ArgumentNullError(ER_MODEL_NULL);
|
||||||
|
|
@ -122,7 +124,10 @@ begin
|
||||||
var permPred := model.Predict(Xperm);
|
var permPred := model.Predict(Xperm);
|
||||||
var permScore := scoreFunc(y, permPred);
|
var permScore := scoreFunc(y, permPred);
|
||||||
|
|
||||||
acc += (baselineScore - permScore);
|
if higherIsBetter then
|
||||||
|
acc += (baselineScore - permScore)
|
||||||
|
else
|
||||||
|
acc += (permScore - baselineScore);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
resultVec[j] := acc / nRepeats;
|
resultVec[j] := acc / nRepeats;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ interface
|
||||||
|
|
||||||
const
|
const
|
||||||
ER_DIM_MISMATCH =
|
ER_DIM_MISMATCH =
|
||||||
'Несоответствие размерностей: {0} и {1}!!Dimension mismatch: {0} and {1}';
|
'Размерности не совпадают: {0} и {1}!!Dimension mismatch: {0} and {1}';
|
||||||
ER_PARAM_VALUES_EMPTY =
|
ER_PARAM_VALUES_EMPTY =
|
||||||
'Список paramValues пуст!!paramValues is empty';
|
'Список paramValues пуст!!paramValues is empty';
|
||||||
ER_EMPTY_DATASET =
|
ER_EMPTY_DATASET =
|
||||||
|
|
@ -25,6 +25,33 @@ const
|
||||||
'В DataFrame отсутствует столбец "{0}"!!DataFrame does not contain column "{0}"';
|
'В DataFrame отсутствует столбец "{0}"!!DataFrame does not contain column "{0}"';
|
||||||
ER_NOT_IMPLEMENTED =
|
ER_NOT_IMPLEMENTED =
|
||||||
'Метод {0} не реализован!!Method {0} is 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
|
type
|
||||||
/// Базовое исключение ML-библиотеки
|
/// Базовое исключение ML-библиотеки
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,4 @@
|
||||||
// =============================================================
|
/// Модуль моделей машинного обучения и матричных преобразований.
|
||||||
// СТАТИСТИЧЕСКОЕ СОГЛАШЕНИЕ (MLModelsABC)
|
|
||||||
//
|
|
||||||
// Модели и трансформеры используют статистические методы
|
|
||||||
// из LinearAlgebraML.
|
|
||||||
//
|
|
||||||
// В частности:
|
|
||||||
// • StandardScaler, VarianceThreshold и др. используют
|
|
||||||
// дисперсию с делением на n (population variance)
|
|
||||||
//
|
|
||||||
// См. статистическую политику в модуле MLABC.
|
|
||||||
// =============================================================
|
|
||||||
|
|
||||||
/// Модуль моделей машинного обучения и матричных преобразований.
|
|
||||||
///
|
///
|
||||||
/// Содержит:
|
/// Содержит:
|
||||||
/// • функции активации
|
/// • функции активации
|
||||||
|
|
@ -25,6 +12,19 @@
|
||||||
/// X — Matrix (объекты × признаки), y — Vector (целевая переменная).
|
/// X — Matrix (объекты × признаки), y — Vector (целевая переменная).
|
||||||
unit MLModelsABC;
|
unit MLModelsABC;
|
||||||
|
|
||||||
|
// =============================================================
|
||||||
|
// СТАТИСТИЧЕСКОЕ СОГЛАШЕНИЕ (MLModelsABC)
|
||||||
|
//
|
||||||
|
// Модели и трансформеры используют статистические методы
|
||||||
|
// из LinearAlgebraML.
|
||||||
|
//
|
||||||
|
// В частности:
|
||||||
|
// • StandardScaler, VarianceThreshold и др. используют
|
||||||
|
// дисперсию с делением на n (population variance)
|
||||||
|
//
|
||||||
|
// См. статистическую политику в модуле MLABC.
|
||||||
|
// =============================================================
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
uses MLCoreABC;
|
uses MLCoreABC;
|
||||||
|
|
@ -205,7 +205,7 @@ type
|
||||||
/// Обучение выполняется методом покоординатного спуска
|
/// Обучение выполняется методом покоординатного спуска
|
||||||
/// ВАЖНО: Модель чувствительна к масштабу признаков.
|
/// ВАЖНО: Модель чувствительна к масштабу признаков.
|
||||||
/// Всегда используйте StandardScaler в Pipeline перед ElasticNet.
|
/// Всегда используйте StandardScaler в Pipeline перед ElasticNet.
|
||||||
ElasticNet = class(IRegressor)
|
ElasticNet = class(IRegressor)
|
||||||
private
|
private
|
||||||
fLambda1: real; // L1
|
fLambda1: real; // L1
|
||||||
fLambda2: real; // L2
|
fLambda2: real; // L2
|
||||||
|
|
@ -549,6 +549,7 @@ type
|
||||||
minSamplesSplit: integer;
|
minSamplesSplit: integer;
|
||||||
minSamplesLeaf: integer;
|
minSamplesLeaf: integer;
|
||||||
criterion: ISplitCriterion;
|
criterion: ISplitCriterion;
|
||||||
|
classCount: integer;
|
||||||
maxFeatures: integer;
|
maxFeatures: integer;
|
||||||
seed: integer := -1
|
seed: integer := -1
|
||||||
);
|
);
|
||||||
|
|
@ -2023,7 +2024,11 @@ type
|
||||||
|
|
||||||
/// Стандартизирует признаки: вычитает среднее
|
/// Стандартизирует признаки: вычитает среднее
|
||||||
/// и делит на стандартное отклонение по каждому столбцу.
|
/// и делит на стандартное отклонение по каждому столбцу.
|
||||||
/// Используется для приведения признаков к сопоставимому масштабу
|
/// Используется для приведения признаков к сопоставимому масштабу.
|
||||||
|
///
|
||||||
|
/// Примечание:
|
||||||
|
/// • стандартное отклонение вычисляется с делением на n
|
||||||
|
/// (population variance, как в sklearn)
|
||||||
StandardScaler = class(IUnsupervisedTransformer)
|
StandardScaler = class(IUnsupervisedTransformer)
|
||||||
private
|
private
|
||||||
fMean: Vector;
|
fMean: Vector;
|
||||||
|
|
@ -2438,16 +2443,6 @@ const
|
||||||
'Неизвестный тип FeatureScore!!Unknown FeatureScore type';
|
'Неизвестный тип FeatureScore!!Unknown FeatureScore type';
|
||||||
ER_SELECTKBEST_FIT_INVALID =
|
ER_SELECTKBEST_FIT_INVALID =
|
||||||
'Для SelectKBest необходимо вызывать Fit(X, y)!!SelectKBest requires Fit(X, y)';
|
'Для 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 =
|
ER_N_ESTIMATORS_NOT_POSITIVE =
|
||||||
'Параметр nEstimators должен быть > 0!!nEstimators must be > 0';
|
'Параметр nEstimators должен быть > 0!!nEstimators must be > 0';
|
||||||
ER_LEARNING_RATE_NOT_POSITIVE =
|
ER_LEARNING_RATE_NOT_POSITIVE =
|
||||||
|
|
@ -2464,10 +2459,6 @@ const
|
||||||
'maxDepth должен быть > 0!!maxDepth must be > 0';
|
'maxDepth должен быть > 0!!maxDepth must be > 0';
|
||||||
ER_SUBSAMPLE_INVALID =
|
ER_SUBSAMPLE_INVALID =
|
||||||
'subsample должен быть > 0!!subsample must be > 0';
|
'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 =
|
ER_K_EXCEEDS_SAMPLES =
|
||||||
'k превышает число обучающих объектов!!k exceeds number of training samples';
|
'k превышает число обучающих объектов!!k exceeds number of training samples';
|
||||||
ER_MAX_DEPTH_TOO_LARGE =
|
ER_MAX_DEPTH_TOO_LARGE =
|
||||||
|
|
@ -2488,18 +2479,6 @@ const
|
||||||
ER_ELASTICNET_INVALID_LOSS =
|
ER_ELASTICNET_INVALID_LOSS =
|
||||||
'Функция потерь ElasticNet стала NaN или Infinity.' +
|
'Функция потерь ElasticNet стала NaN или Infinity.' +
|
||||||
'ElasticNet loss became NaN or 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 =
|
ER_MAXITER_INVALID =
|
||||||
'maxIter должен быть положительным. Получено {0}.!!' +
|
'maxIter должен быть положительным. Получено {0}.!!' +
|
||||||
'maxIter must be positive. Received {0}.';
|
'maxIter must be positive. Received {0}.';
|
||||||
|
|
@ -2598,8 +2577,6 @@ const
|
||||||
'Model (type: {0}) is not an unsupervised model';
|
'Model (type: {0}) is not an unsupervised model';
|
||||||
ER_DBSCAN_PREDICT_ONLY_TRAIN_DATA =
|
ER_DBSCAN_PREDICT_ONLY_TRAIN_DATA =
|
||||||
'DBSCAN: Predict поддерживается только для обучающей выборки!!DBSCAN: Predict is only supported for training 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 =
|
ER_DBSCAN_PREDICT_NEW_DATA =
|
||||||
'DBSCAN не поддерживает предсказание для новых данных!!DBSCAN does not support prediction for new data';
|
'DBSCAN не поддерживает предсказание для новых данных!!DBSCAN does not support prediction for new data';
|
||||||
ER_CLASSES_NOT_AVAILABLE =
|
ER_CLASSES_NOT_AVAILABLE =
|
||||||
|
|
@ -2618,7 +2595,9 @@ const
|
||||||
ER_UNKNOWN_CLASS_LABEL =
|
ER_UNKNOWN_CLASS_LABEL =
|
||||||
'Неизвестная метка класса: {0}!!Unknown class label: {0}';
|
'Неизвестная метка класса: {0}!!Unknown class label: {0}';
|
||||||
ER_MAX_FEATURES_INVALID =
|
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}
|
{$endregion ErrConstants}
|
||||||
|
|
||||||
|
|
@ -3526,7 +3505,6 @@ begin
|
||||||
Result := res;
|
Result := res;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function LeafClass(c: integer): DecisionTreeNode;
|
function LeafClass(c: integer): DecisionTreeNode;
|
||||||
begin
|
begin
|
||||||
var n := new DecisionTreeNode;
|
var n := new DecisionTreeNode;
|
||||||
|
|
@ -3582,6 +3560,7 @@ constructor DecisionTreeCore.Create(
|
||||||
minSamplesSplit: integer;
|
minSamplesSplit: integer;
|
||||||
minSamplesLeaf: integer;
|
minSamplesLeaf: integer;
|
||||||
criterion: ISplitCriterion;
|
criterion: ISplitCriterion;
|
||||||
|
classCount: integer;
|
||||||
maxFeatures: integer;
|
maxFeatures: integer;
|
||||||
seed: integer
|
seed: integer
|
||||||
);
|
);
|
||||||
|
|
@ -3591,6 +3570,7 @@ begin
|
||||||
fMinSamplesLeaf := minSamplesLeaf;
|
fMinSamplesLeaf := minSamplesLeaf;
|
||||||
fCriterion := criterion;
|
fCriterion := criterion;
|
||||||
fMaxFeatures := maxFeatures;
|
fMaxFeatures := maxFeatures;
|
||||||
|
fClassCount := classCount;
|
||||||
|
|
||||||
fRandomSeed := ResolveRandomSeed(seed, fUserProvidedSeed);
|
fRandomSeed := ResolveRandomSeed(seed, fUserProvidedSeed);
|
||||||
fRng := new System.Random(fRandomSeed);
|
fRng := new System.Random(fRandomSeed);
|
||||||
|
|
@ -3782,7 +3762,7 @@ begin
|
||||||
yr := y.SubvectorBy(rightArr);
|
yr := y.SubvectorBy(rightArr);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function DecisionTreeCore.FindBestSplit(
|
{function DecisionTreeCore.FindBestSplit(
|
||||||
X: Matrix;
|
X: Matrix;
|
||||||
y: Vector;
|
y: Vector;
|
||||||
indices: array of integer;
|
indices: array of integer;
|
||||||
|
|
@ -3888,6 +3868,160 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
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;
|
end;
|
||||||
|
|
||||||
function DecisionTreeCore.Clone: DecisionTreeCore;
|
function DecisionTreeCore.Clone: DecisionTreeCore;
|
||||||
|
|
@ -5575,6 +5709,10 @@ begin
|
||||||
if XVal.ColCount <> XTrain.ColCount then
|
if XVal.ColCount <> XTrain.ColCount then
|
||||||
DimensionError(ER_FEATURE_COUNT_MISMATCH);
|
DimensionError(ER_FEATURE_COUNT_MISMATCH);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// --- OOB checks ---
|
||||||
|
if fUseOOBEarlyStopping and (fSubsample >= 1.0) then
|
||||||
|
ArgumentError(ER_OOB_REQUIRES_SUBSAMPLE);
|
||||||
|
|
||||||
// --- init state ---
|
// --- init state ---
|
||||||
fOOBLossHistory.Clear;
|
fOOBLossHistory.Clear;
|
||||||
|
|
@ -6735,7 +6873,7 @@ begin
|
||||||
NotFittedError(ER_FIT_NOT_CALLED);
|
NotFittedError(ER_FIT_NOT_CALLED);
|
||||||
|
|
||||||
if fFeatureImportances <> nil then
|
if fFeatureImportances <> nil then
|
||||||
exit(fFeatureImportances);
|
exit(fFeatureImportances.Clone);
|
||||||
|
|
||||||
var importances := new Vector(fFeatureCount);
|
var importances := new Vector(fFeatureCount);
|
||||||
|
|
||||||
|
|
@ -6758,7 +6896,7 @@ begin
|
||||||
|
|
||||||
fFeatureImportances := importances;
|
fFeatureImportances := importances;
|
||||||
|
|
||||||
Result := fFeatureImportances;
|
Result := fFeatureImportances.Clone;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function GradientBoostingClassifier.ToString: string;
|
function GradientBoostingClassifier.ToString: string;
|
||||||
|
|
@ -7820,9 +7958,6 @@ begin
|
||||||
var n := X.RowCount;
|
var n := X.RowCount;
|
||||||
var p := X.ColCount;
|
var p := X.ColCount;
|
||||||
|
|
||||||
if n = 0 then
|
|
||||||
ArgumentError(ER_EMPTY_DATA, 'DBSCAN');
|
|
||||||
|
|
||||||
fFeatureCount := p;
|
fFeatureCount := p;
|
||||||
|
|
||||||
var labels := new integer[n];
|
var labels := new integer[n];
|
||||||
|
|
|
||||||
|
|
@ -285,7 +285,7 @@ const
|
||||||
ER_CLASSES_NOT_AVAILABLE =
|
ER_CLASSES_NOT_AVAILABLE =
|
||||||
'Метки классов недоступны. Убедитесь, что конвейер обучен и задача — классификация!!Class labels are not available. Ensure the pipeline is fitted and the task is classification';
|
'Метки классов недоступны. Убедитесь, что конвейер обучен и задача — классификация!!Class labels are not available. Ensure the pipeline is fitted and the task is classification';
|
||||||
ER_LABELENCODER_TARGET_NOT_ALLOWED =
|
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 =
|
ER_ENCODELABELS_NOT_CATEGORICAL =
|
||||||
'Целевой столбец должен быть категориальным для задач классификации!!Target column must be categorical for classification tasks';
|
'Целевой столбец должен быть категориальным для задач классификации!!Target column must be categorical for classification tasks';
|
||||||
ER_PIPELINE_TARGET_TRANSFORM_NOT_ALLOWED =
|
ER_PIPELINE_TARGET_TRANSFORM_NOT_ALLOWED =
|
||||||
|
|
|
||||||
|
|
@ -319,11 +319,12 @@ begin
|
||||||
var cls := pair.Key;
|
var cls := pair.Key;
|
||||||
var cnt := pair.Value.Count;
|
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;
|
end;
|
||||||
|
|
||||||
// --- 2. Контейнеры фолдов
|
// --- 2. Контейнеры фолдов
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue