ML тесты поправлены
Небольшие правки ML-модулей
This commit is contained in:
parent
b08e8b6c0a
commit
3938120846
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
|
||||
begin
|
||||
var ds := Datasets.TitanicRu;
|
||||
|
|
@ -11,8 +11,7 @@ begin
|
|||
df.StratifiedTrainTestSplit(ds.Target, testRatio := 0.2, seed := 42);
|
||||
|
||||
var prep :=
|
||||
DataPipeline.BuildPreprocessing(
|
||||
TaskKind.tkClassification,
|
||||
DataPipeline.BuildClassificationPreprocessing(
|
||||
target,
|
||||
features,
|
||||
new Imputer(['Возраст']),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
|
||||
function BuildPipe(features: array of string): DataPipeline;
|
||||
function BuildPipe(features: array of string): ClassificationDataPipeline;
|
||||
begin
|
||||
Result :=
|
||||
DataPipeline.BuildClassification(
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@ begin
|
|||
|
||||
var pred := pipe.Predict(testDf);
|
||||
var y := pipe.GetEncodedLabels(testDf);
|
||||
var predInt := pred.ToIntArray;
|
||||
var yInt := y.ToIntArray;
|
||||
var testPrepared := pipe.Transform(testDf);
|
||||
var cur := testFull.GetCursor;
|
||||
var curPrepared := testPrepared.GetCursor;
|
||||
|
||||
Println('TitanicRu: пассажиры, классифицированные неправильно');
|
||||
Println;
|
||||
|
|
@ -42,19 +42,22 @@ begin
|
|||
var shown := 0;
|
||||
while cur.MoveNext do
|
||||
begin
|
||||
if not curPrepared.MoveNext then
|
||||
break;
|
||||
|
||||
var i := cur.Position;
|
||||
if yInt[i] <> predInt[i] then
|
||||
if y[i] <> pred[i] then
|
||||
begin
|
||||
var id := cur.Int('Id');
|
||||
var name := cur.Str('Имя');
|
||||
var sex := cur.Str('Пол');
|
||||
var pclass := cur.Int('Класс');
|
||||
var age := cur.Float('Возраст');
|
||||
var age := curPrepared.Float('Возраст');
|
||||
var fare := cur.Float('ЦенаБилета');
|
||||
|
||||
Println($'Id={id}, {name}');
|
||||
Println($' Пол={sex}, класс={pclass}, возраст={age:F1}, билет={fare:F1}');
|
||||
Println($' Истина: {LabelText(yInt[i])}, прогноз: {LabelText(predInt[i])}');
|
||||
Println($' Истина: {LabelText(y[i])}, прогноз: {LabelText(pred[i])}');
|
||||
Println;
|
||||
|
||||
shown += 1;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
uses MLABC;
|
||||
|
||||
function BuildPipe(features: array of string): DataPipeline;
|
||||
function BuildPipe(features: array of string): ClassificationDataPipeline;
|
||||
begin
|
||||
Result :=
|
||||
DataPipeline.BuildClassification(
|
||||
|
|
|
|||
|
|
@ -19,8 +19,7 @@ begin
|
|||
var (trainDf, testDf) := df.TrainTestSplit(0.2, seed := 42);
|
||||
|
||||
var prep :=
|
||||
DataPipeline.BuildPreprocessing(
|
||||
TaskKind.tkRegression,
|
||||
DataPipeline.BuildRegressionPreprocessing(
|
||||
target,
|
||||
features,
|
||||
new OrdinalEncoder('model'),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
|
||||
begin
|
||||
var ds := Datasets.UsedCarsPrice;
|
||||
|
|
@ -19,8 +19,7 @@ begin
|
|||
var (trainDf, testDf) := df.TrainTestSplit(0.2, seed := 42);
|
||||
|
||||
var prep :=
|
||||
DataPipeline.BuildPreprocessing(
|
||||
TaskKind.tkRegression,
|
||||
DataPipeline.BuildRegressionPreprocessing(
|
||||
target,
|
||||
features,
|
||||
new OrdinalEncoder('model'),
|
||||
|
|
|
|||
|
|
@ -1,15 +1,21 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
var y := new Vector(Arr(0.0, 0.9999999999999, 2.0000000000001));
|
||||
var labels := LabelsToInts(y);
|
||||
var ds := new Dataset;
|
||||
ds.Task := TaskType.Classification;
|
||||
ds.Target := 'Target';
|
||||
ds.Data := new DataFrame;
|
||||
ds.Data.AddStrColumn('Target', Arr('cat', 'dog', 'cat'));
|
||||
|
||||
Check(labels.Length = 3, 'Length mismatch');
|
||||
Check(labels[0] = 0, 'First label mismatch');
|
||||
Check(labels[1] = 1, 'Second label mismatch');
|
||||
Check(labels[2] = 2, 'Third label mismatch');
|
||||
var enc := new LabelEncoder;
|
||||
var y := enc.FitTransform(ds);
|
||||
|
||||
var bad := new Vector(Arr(0.0, 1.2, 2.0));
|
||||
CheckRaises(procedure -> begin var tmp := LabelsToInts(bad); end, 'LabelsToInts must reject non-integer labels');
|
||||
Check(y.Length = 3, 'Length mismatch');
|
||||
Check(y[0] = 0, 'First label mismatch');
|
||||
Check(y[1] = 1, 'Second label mismatch');
|
||||
Check(y[2] = 0, 'Third label mismatch');
|
||||
Check(enc.Classes.Length = 2, 'Class count mismatch');
|
||||
Check(enc.Classes[0] = 'cat', 'First class mismatch');
|
||||
Check(enc.Classes[1] = 'dog', 'Second class mismatch');
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -6,6 +6,6 @@ begin
|
|||
var yPred := new Vector(Arr(0.51, 1.0));
|
||||
|
||||
CheckRaises(procedure -> begin
|
||||
var a := Metrics.Accuracy(yTrue, yPred);
|
||||
var a := Metrics.Accuracy(yTrue.ToIntArray, yPred.ToIntArray);
|
||||
end, 'Accuracy must reject non-integer class labels');
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -6,6 +6,6 @@ begin
|
|||
var yPred := new Vector(Arr(real.NaN, 1.0));
|
||||
|
||||
CheckRaises(procedure -> begin
|
||||
var a := Metrics.Accuracy(yTrue, yPred);
|
||||
var a := Metrics.Accuracy(yTrue.ToIntArray, yPred.ToIntArray);
|
||||
end, 'Accuracy must reject NaN and Infinity in class labels');
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
var df := new DataFrame;
|
||||
df.AddBoolColumn('Flag', Arr(true, false, true, false));
|
||||
df.AddBoolColumn('IsNew', Arr(false, false, true, true));
|
||||
df.AddFloatColumn('X', Arr(1.5, 2.5, 3.5, 4.5));
|
||||
df.AddIntColumn('Target', Arr(0, 1, 0, 1));
|
||||
df := df.SetCategorical(['Target']);
|
||||
|
||||
var X := df.ToMatrix(['Flag', 'IsNew', 'X']);
|
||||
var y := df.ToVector('Target').ToIntArray;
|
||||
|
||||
Check(X.RowCount = 4, 'ToMatrix row count mismatch');
|
||||
Check(X.ColCount = 3, 'ToMatrix col count mismatch');
|
||||
|
||||
Check(Abs(X[0,0] - 1.0) < 1e-12, 'Flag=true must encode as 1');
|
||||
Check(Abs(X[1,0] - 0.0) < 1e-12, 'Flag=false must encode as 0');
|
||||
Check(Abs(X[0,1] - 0.0) < 1e-12, 'IsNew=false must encode as 0');
|
||||
Check(Abs(X[2,1] - 1.0) < 1e-12, 'IsNew=true must encode as 1');
|
||||
Check(Abs(X[3,2] - 4.5) < 1e-12, 'Numeric column must stay unchanged');
|
||||
|
||||
var model := new DecisionTreeClassifier(maxDepth := 3);
|
||||
model.Fit(X, y);
|
||||
var pred := model.Predict(X);
|
||||
|
||||
Check(pred.Length = df.RowCount, 'Manual bool-feature model prediction length mismatch');
|
||||
end.
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -6,8 +6,7 @@ begin
|
|||
var df := ds.Data;
|
||||
|
||||
var pipe :=
|
||||
DataPipeline.Build(
|
||||
TaskKind.tkClassification,
|
||||
DataPipeline.BuildClassification(
|
||||
ds.Target,
|
||||
ds.Features,
|
||||
new StandardScaler,
|
||||
|
|
@ -25,3 +24,4 @@ begin
|
|||
Check(y.Length = testDf.RowCount, 'Encoded labels length mismatch');
|
||||
Check(Metrics.Accuracy(y, pred) > 0.8, 'Pipeline accuracy is unexpectedly low');
|
||||
end.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
var ds := Datasets.Iris;
|
||||
|
||||
var pipe :=
|
||||
UDataPipeline.Build(
|
||||
DataPipeline.BuildClustering(
|
||||
ds.Features,
|
||||
new StandardScaler,
|
||||
new KMeans(3, seed := 1)
|
||||
|
|
@ -15,3 +15,4 @@ begin
|
|||
|
||||
Check(labels.Length = ds.Data.RowCount, 'UDataPipeline labels length mismatch');
|
||||
end.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -7,8 +7,7 @@ begin
|
|||
var (trainDf, testDf) := df.TrainTestSplit(0.2, seed := 3);
|
||||
|
||||
var pipe :=
|
||||
DataPipeline.Build(
|
||||
TaskKind.tkClassification,
|
||||
DataPipeline.BuildClassification(
|
||||
ds.Target,
|
||||
ds.Features,
|
||||
new StandardScaler,
|
||||
|
|
@ -42,3 +41,4 @@ begin
|
|||
Check(classes[yi] = trueLabels[i], $'GetEncodedLabels[{i}] does not decode to true target');
|
||||
end;
|
||||
end.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -21,9 +21,8 @@ begin
|
|||
|
||||
for var i := 0 to X.RowCount - 1 do
|
||||
begin
|
||||
var pi := Round(pred[i]);
|
||||
Check(Abs(pred[i] - pi) < 1e-12, $'Predict[{i}] is not an original integer label');
|
||||
Check((labels[i] >= 0) and (labels[i] < modelClasses.Length), $'PredictLabels[{i}] out of range');
|
||||
Check(modelClasses[labels[i]] = pi.ToString, $'Predict[{i}] and PredictLabels[{i}] are inconsistent');
|
||||
var pi := pred[i];
|
||||
Check((pi >= 0) and (pi < modelClasses.Length), $'Predict[{i}] out of range');
|
||||
Check(labels[i] = pi.ToString, $'Predict[{i}] and PredictLabels[{i}] are inconsistent');
|
||||
end;
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -21,9 +21,8 @@ begin
|
|||
|
||||
for var i := 0 to X.RowCount - 1 do
|
||||
begin
|
||||
var pi := Round(pred[i]);
|
||||
Check(Abs(pred[i] - pi) < 1e-12, $'Predict[{i}] is not an original integer label');
|
||||
Check((labels[i] >= 0) and (labels[i] < modelClasses.Length), $'PredictLabels[{i}] out of range');
|
||||
Check(modelClasses[labels[i]] = pi.ToString, $'Predict[{i}] and PredictLabels[{i}] are inconsistent');
|
||||
var pi := pred[i];
|
||||
Check((pi >= 0) and (pi < modelClasses.Length), $'Predict[{i}] out of range');
|
||||
Check(labels[i] = pi.ToString, $'Predict[{i}] and PredictLabels[{i}] are inconsistent');
|
||||
end;
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -21,9 +21,8 @@ begin
|
|||
|
||||
for var i := 0 to X.RowCount - 1 do
|
||||
begin
|
||||
var pi := Round(pred[i]);
|
||||
Check(Abs(pred[i] - pi) < 1e-12, $'Predict[{i}] is not an original integer label');
|
||||
Check((labels[i] >= 0) and (labels[i] < modelClasses.Length), $'PredictLabels[{i}] out of range');
|
||||
Check(modelClasses[labels[i]] = pi.ToString, $'Predict[{i}] and PredictLabels[{i}] are inconsistent');
|
||||
var pi := pred[i];
|
||||
Check((pi >= 0) and (pi < modelClasses.Length), $'Predict[{i}] out of range');
|
||||
Check(labels[i] = pi.ToString, $'Predict[{i}] and PredictLabels[{i}] are inconsistent');
|
||||
end;
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -21,9 +21,8 @@ begin
|
|||
|
||||
for var i := 0 to X.RowCount - 1 do
|
||||
begin
|
||||
var pi := Round(pred[i]);
|
||||
Check(Abs(pred[i] - pi) < 1e-12, $'Predict[{i}] is not an original integer label');
|
||||
Check((labels[i] >= 0) and (labels[i] < modelClasses.Length), $'PredictLabels[{i}] out of range');
|
||||
Check(modelClasses[labels[i]] = pi.ToString, $'Predict[{i}] and PredictLabels[{i}] are inconsistent');
|
||||
var pi := pred[i];
|
||||
Check((pi >= 0) and (pi < modelClasses.Length), $'Predict[{i}] out of range');
|
||||
Check(labels[i] = pi.ToString, $'Predict[{i}] and PredictLabels[{i}] are inconsistent');
|
||||
end;
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC, PreprocessorABC;
|
||||
uses MLABC, PreprocessorABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
type
|
||||
|
|
@ -32,8 +32,7 @@ end;
|
|||
|
||||
begin
|
||||
var ds := Datasets.Iris;
|
||||
var pipe := DataPipeline.Build(
|
||||
TaskKind.tkClassification,
|
||||
var pipe := DataPipeline.BuildClassification(
|
||||
ds.Target,
|
||||
ds.Features,
|
||||
new BadDropper,
|
||||
|
|
@ -43,3 +42,4 @@ begin
|
|||
CheckRaises(procedure -> begin pipe.Fit(ds.Data); end,
|
||||
'Pipeline must reject DataFrame preprocessors that change RowCount');
|
||||
end.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -21,9 +21,8 @@ begin
|
|||
|
||||
for var i := 0 to X.RowCount - 1 do
|
||||
begin
|
||||
var pi := Round(pred[i]);
|
||||
Check(Abs(pred[i] - pi) < 1e-12, $'Predict[{i}] is not an original integer label');
|
||||
Check((labels[i] >= 0) and (labels[i] < modelClasses.Length), $'PredictLabels[{i}] out of range');
|
||||
Check(modelClasses[labels[i]] = pi.ToString, $'Predict[{i}] and PredictLabels[{i}] are inconsistent');
|
||||
var pi := pred[i];
|
||||
Check((pi >= 0) and (pi < modelClasses.Length), $'Predict[{i}] out of range');
|
||||
Check(labels[i] = pi.ToString, $'Predict[{i}] and PredictLabels[{i}] are inconsistent');
|
||||
end;
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -12,8 +12,7 @@ begin
|
|||
testDf.AddStrColumn('Target', Arr('cat', 'fox'));
|
||||
testDf := testDf.SetCategorical(['Target']);
|
||||
|
||||
var pipe := DataPipeline.Build(
|
||||
TaskKind.tkClassification,
|
||||
var pipe := DataPipeline.BuildClassification(
|
||||
'Target',
|
||||
Arr($'X'),
|
||||
new LogisticRegression
|
||||
|
|
@ -24,3 +23,4 @@ begin
|
|||
CheckRaises(procedure -> begin var y := pipe.GetEncodedLabels(testDf); end,
|
||||
'GetEncodedLabels must reject unseen target classes');
|
||||
end.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC, PreprocessorABC;
|
||||
uses MLABC, PreprocessorABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
type
|
||||
|
|
@ -32,7 +32,7 @@ end;
|
|||
|
||||
begin
|
||||
var ds := Datasets.Iris;
|
||||
var pipe := UDataPipeline.Build(
|
||||
var pipe := DataPipeline.BuildClustering(
|
||||
ds.Features,
|
||||
new BadDropper,
|
||||
new KMeans(3, seed := 1)
|
||||
|
|
@ -41,3 +41,4 @@ begin
|
|||
CheckRaises(procedure -> begin var labels := pipe.FitPredict(ds.Data); end,
|
||||
'UDataPipeline must reject DataFrame preprocessors that change RowCount');
|
||||
end.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -7,8 +7,7 @@ begin
|
|||
df.AddStrColumn('Target', Arr('low', 'mid', 'high'));
|
||||
df := df.SetCategorical(['Target']);
|
||||
|
||||
var pipe := DataPipeline.Build(
|
||||
TaskKind.tkRegression,
|
||||
var pipe := DataPipeline.BuildRegression(
|
||||
'Target',
|
||||
Arr($'X'),
|
||||
new LinearRegression
|
||||
|
|
@ -17,3 +16,4 @@ begin
|
|||
CheckRaises(procedure -> begin pipe.Fit(df); end,
|
||||
'Regression pipeline must reject non-numeric target');
|
||||
end.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -6,8 +6,7 @@ begin
|
|||
df.AddFloatColumn('X', Arr(1.0, 2.0, 3.0, 4.0));
|
||||
df.AddStrColumn('Target', Arr('cat', 'dog', 'cat', 'dog'));
|
||||
|
||||
var pipe := DataPipeline.Build(
|
||||
TaskKind.tkClassification,
|
||||
var pipe := DataPipeline.BuildClassification(
|
||||
'Target',
|
||||
Arr($'X'),
|
||||
new LogisticRegression
|
||||
|
|
@ -16,3 +15,4 @@ begin
|
|||
CheckRaises(procedure -> begin pipe.Fit(df); end,
|
||||
'Classification pipeline must require categorical target');
|
||||
end.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -6,8 +6,7 @@ begin
|
|||
var df := ds.Data;
|
||||
|
||||
var pipe :=
|
||||
DataPipeline.Build(
|
||||
TaskKind.tkClassification,
|
||||
DataPipeline.BuildClassification(
|
||||
ds.Target,
|
||||
ds.Features,
|
||||
new StandardScaler,
|
||||
|
|
@ -24,3 +23,4 @@ begin
|
|||
Check(proba.ColCount = classes.Length, 'Probability class count mismatch');
|
||||
CheckProbabilityRowsSumToOne(proba);
|
||||
end.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
CheckRaises(procedure -> begin
|
||||
var pipe := DataPipeline.Build(
|
||||
TaskKind.tkClassification,
|
||||
var pipe := DataPipeline.BuildClassification(
|
||||
'Target',
|
||||
Arr($'X', $'Target'),
|
||||
new LogisticRegression
|
||||
|
|
@ -12,3 +11,4 @@ begin
|
|||
end,
|
||||
'DataPipeline.Build must reject target inside features');
|
||||
end.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
CheckRaises(procedure -> begin
|
||||
var pipe := UDataPipeline.Build(
|
||||
var pipe := DataPipeline.BuildClustering(
|
||||
Arr($'X', $'X'),
|
||||
new KMeans(3, seed := 1)
|
||||
);
|
||||
end,
|
||||
'UDataPipeline.Build must reject duplicate features');
|
||||
end.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -7,8 +7,7 @@ begin
|
|||
var (trainDf, testDf) := df.TrainTestSplit(0.2, seed := 3);
|
||||
|
||||
var pipe :=
|
||||
DataPipeline.Build(
|
||||
TaskKind.tkClassification,
|
||||
DataPipeline.BuildClassification(
|
||||
ds.Target,
|
||||
ds.Features,
|
||||
new StandardScaler,
|
||||
|
|
@ -25,3 +24,4 @@ begin
|
|||
for var i := 0 to labels.Length - 1 do
|
||||
Check(labels[i] in classes, $'PredictLabels[{i}] must be one of pipeline class labels');
|
||||
end.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC, PreprocessorABC, MLCoreABC;
|
||||
uses MLABC, PreprocessorABC, MLCoreABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
type
|
||||
|
|
@ -41,8 +41,7 @@ end;
|
|||
|
||||
begin
|
||||
CheckRaises(procedure -> begin
|
||||
var pipe := DataPipeline.Build(
|
||||
TaskKind.tkClassification,
|
||||
var pipe := DataPipeline.BuildClassification(
|
||||
'Target',
|
||||
Arr($'X'),
|
||||
new BadTargetStep('Target'),
|
||||
|
|
@ -51,3 +50,4 @@ begin
|
|||
end,
|
||||
'DataPipeline must reject a bound preprocessor that targets the target column');
|
||||
end.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC, PreprocessorABC, MLCoreABC;
|
||||
uses MLABC, PreprocessorABC, MLCoreABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
type
|
||||
|
|
@ -41,8 +41,7 @@ end;
|
|||
|
||||
begin
|
||||
CheckRaises(procedure -> begin
|
||||
var pipe := DataPipeline.Build(
|
||||
TaskKind.tkClassification,
|
||||
var pipe := DataPipeline.BuildClassification(
|
||||
'Target',
|
||||
Arr($'X'),
|
||||
new BadTargetColumnsStep(Arr($'X', $'Target')),
|
||||
|
|
@ -51,3 +50,4 @@ begin
|
|||
end,
|
||||
'DataPipeline must reject a multi-column bound preprocessor that includes the target column');
|
||||
end.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -7,8 +7,7 @@ begin
|
|||
df.AddIntColumn('Target', Arr(10, 20, 10, 20));
|
||||
df := df.SetCategorical(['Target']);
|
||||
|
||||
var pipe := DataPipeline.Build(
|
||||
TaskKind.tkClassification,
|
||||
var pipe := DataPipeline.BuildClassification(
|
||||
'Target',
|
||||
Arr($'X'),
|
||||
new LogisticRegression
|
||||
|
|
@ -39,3 +38,4 @@ begin
|
|||
Check(predLabels[i] = classes[pi], $'PredictLabels[{i}] mismatch');
|
||||
end;
|
||||
end.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -7,7 +7,7 @@ begin
|
|||
X[2,0] := 1.0; X[3,0] := 1.1;
|
||||
X[4,0] := 2.0; X[5,0] := 2.1;
|
||||
|
||||
var y := new Vector(Arr(10.0, 10.0, 20.0, 20.0, 30.0, 30.0));
|
||||
var y := Arr(10, 10, 20, 20, 30, 30);
|
||||
|
||||
var model := new LogisticRegression;
|
||||
model.Fit(X, y);
|
||||
|
|
@ -30,9 +30,8 @@ begin
|
|||
|
||||
for var i := 0 to X.RowCount - 1 do
|
||||
begin
|
||||
var pi := Round(pred[i]);
|
||||
Check((labels[i] >= 0) and (labels[i] < classes.Length), $'PredictLabels[{i}] out of range');
|
||||
var pi := pred[i];
|
||||
Check((pi = 10) or (pi = 20) or (pi = 30), $'Predict[{i}] must return original sparse label');
|
||||
Check(classes[labels[i]] = pi.ToString, $'Predict and PredictLabels mismatch at {i}');
|
||||
Check(labels[i] = pi.ToString, $'Predict and PredictLabels mismatch at {i}');
|
||||
end;
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -7,7 +7,7 @@ begin
|
|||
X[2,0] := 1.0; X[3,0] := 1.1;
|
||||
X[4,0] := 2.0; X[5,0] := 2.1;
|
||||
|
||||
var y := new Vector(Arr(10.0, 10.0, 20.0, 20.0, 30.0, 30.0));
|
||||
var y := Arr(10, 10, 20, 20, 30, 30);
|
||||
|
||||
var model := new RandomForestClassifier(20, maxDepth := 6, seed := 1);
|
||||
model.Fit(X, y);
|
||||
|
|
@ -25,9 +25,8 @@ begin
|
|||
|
||||
for var i := 0 to X.RowCount - 1 do
|
||||
begin
|
||||
var pi := Round(pred[i]);
|
||||
Check((labels[i] >= 0) and (labels[i] < classes.Length), $'PredictLabels[{i}] out of range');
|
||||
var pi := pred[i];
|
||||
Check((pi = 10) or (pi = 20) or (pi = 30), $'Predict[{i}] must return original sparse label');
|
||||
Check(classes[labels[i]] = pi.ToString, $'Predict and PredictLabels mismatch at {i}');
|
||||
Check(labels[i] = pi.ToString, $'Predict and PredictLabels mismatch at {i}');
|
||||
end;
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -7,7 +7,7 @@ begin
|
|||
X[2,0] := 1.0; X[3,0] := 1.1;
|
||||
X[4,0] := 2.0; X[5,0] := 2.1;
|
||||
|
||||
var y := new Vector(Arr(10.0, 10.0, 20.0, 20.0, 30.0, 30.0));
|
||||
var y := Arr(10, 10, 20, 20, 30, 30);
|
||||
|
||||
var model := new GradientBoostingClassifier(20, learningRate := 0.1, maxDepth := 3, seed := 1);
|
||||
model.Fit(X, y);
|
||||
|
|
@ -25,9 +25,8 @@ begin
|
|||
|
||||
for var i := 0 to X.RowCount - 1 do
|
||||
begin
|
||||
var pi := Round(pred[i]);
|
||||
Check((labels[i] >= 0) and (labels[i] < classes.Length), $'PredictLabels[{i}] out of range');
|
||||
var pi := pred[i];
|
||||
Check((pi = 10) or (pi = 20) or (pi = 30), $'Predict[{i}] must return original sparse label');
|
||||
Check(classes[labels[i]] = pi.ToString, $'Predict and PredictLabels mismatch at {i}');
|
||||
Check(labels[i] = pi.ToString, $'Predict and PredictLabels mismatch at {i}');
|
||||
end;
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -7,7 +7,7 @@ begin
|
|||
X[2,0] := 1.0; X[3,0] := 1.1;
|
||||
X[4,0] := 2.0; X[5,0] := 2.1;
|
||||
|
||||
var y := new Vector(Arr(10.0, 10.0, 20.0, 20.0, 30.0, 30.0));
|
||||
var y := Arr(10, 10, 20, 20, 30, 30);
|
||||
|
||||
var model := new DecisionTreeClassifier(maxDepth := 6, seed := 1);
|
||||
model.Fit(X, y);
|
||||
|
|
@ -23,9 +23,8 @@ begin
|
|||
|
||||
for var i := 0 to X.RowCount - 1 do
|
||||
begin
|
||||
var pi := Round(pred[i]);
|
||||
Check((labels[i] >= 0) and (labels[i] < classes.Length), $'PredictLabels[{i}] out of range');
|
||||
var pi := pred[i];
|
||||
Check((pi = 10) or (pi = 20) or (pi = 30), $'Predict[{i}] must return original sparse label');
|
||||
Check(classes[labels[i]] = pi.ToString, $'Predict and PredictLabels mismatch at {i}');
|
||||
Check(labels[i] = pi.ToString, $'Predict and PredictLabels mismatch at {i}');
|
||||
end;
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -7,7 +7,7 @@ begin
|
|||
X[2,0] := 1.0; X[3,0] := 1.1;
|
||||
X[4,0] := 2.0; X[5,0] := 2.1;
|
||||
|
||||
var y := new Vector(Arr(10.0, 10.0, 20.0, 20.0, 30.0, 30.0));
|
||||
var y := Arr(10, 10, 20, 20, 30, 30);
|
||||
|
||||
var model := new KNNClassifier(3);
|
||||
model.Fit(X, y);
|
||||
|
|
@ -25,9 +25,8 @@ begin
|
|||
|
||||
for var i := 0 to X.RowCount - 1 do
|
||||
begin
|
||||
var pi := Round(pred[i]);
|
||||
Check((labels[i] >= 0) and (labels[i] < classes.Length), $'PredictLabels[{i}] out of range');
|
||||
var pi := pred[i];
|
||||
Check((pi = 10) or (pi = 20) or (pi = 30), $'Predict[{i}] must return original sparse label');
|
||||
Check(classes[labels[i]] = pi.ToString, $'Predict and PredictLabels mismatch at {i}');
|
||||
Check(labels[i] = pi.ToString, $'Predict and PredictLabels mismatch at {i}');
|
||||
end;
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -7,8 +7,7 @@ begin
|
|||
var (trainDf, testDf) := df.TrainTestSplit(0.2, seed := 3);
|
||||
|
||||
var pipe :=
|
||||
DataPipeline.Build(
|
||||
TaskKind.tkClassification,
|
||||
DataPipeline.BuildClassification(
|
||||
ds.Target,
|
||||
ds.Features,
|
||||
new StandardScaler,
|
||||
|
|
@ -30,3 +29,4 @@ begin
|
|||
Check((pi >= 0) and (pi < classes.Length), $'Predict[{i}] out of dense class range');
|
||||
end;
|
||||
end.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -7,8 +7,7 @@ begin
|
|||
var (trainDf, testDf) := df.TrainTestSplit(0.2, seed := 3);
|
||||
|
||||
var pipe :=
|
||||
DataPipeline.Build(
|
||||
TaskKind.tkClassification,
|
||||
DataPipeline.BuildClassification(
|
||||
ds.Target,
|
||||
ds.Features,
|
||||
new StandardScaler,
|
||||
|
|
@ -33,3 +32,4 @@ begin
|
|||
Check(predLabels[i] = classes[pi], $'PredictLabels[{i}] must decode Predict[{i}]');
|
||||
end;
|
||||
end.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
uses MLABC;
|
||||
uses MLABC;
|
||||
uses TestHelpers in '..\TestHelpers.pas';
|
||||
|
||||
begin
|
||||
|
|
@ -7,7 +7,7 @@ begin
|
|||
X[2,0] := 1.0; X[3,0] := 1.1;
|
||||
X[4,0] := 2.0; X[5,0] := 2.1;
|
||||
|
||||
var y := new Vector(Arr(10.0, 10.0, 20.0, 20.0, 30.0, 30.0));
|
||||
var y := Arr(10, 10, 20, 20, 30, 30);
|
||||
|
||||
var model := new LogisticRegression;
|
||||
model.Fit(X, y);
|
||||
|
|
@ -20,9 +20,8 @@ begin
|
|||
|
||||
for var i := 0 to X.RowCount - 1 do
|
||||
begin
|
||||
var pi := Round(pred[i]);
|
||||
var pi := pred[i];
|
||||
Check((pi = 10) or (pi = 20) or (pi = 30), $'Predict[{i}] must return original class label');
|
||||
Check((labels[i] >= 0) and (labels[i] < classes.Length), $'PredictLabels[{i}] out of range');
|
||||
Check(classes[labels[i]] = pi.ToString, $'PredictLabels[{i}] must point to Predict[{i}]');
|
||||
Check(labels[i] = pi.ToString, $'PredictLabels[{i}] must match Predict[{i}]');
|
||||
end;
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -22,12 +22,15 @@ unit MLABC;
|
|||
// =============================================================
|
||||
|
||||
// =============================================================
|
||||
// PIPELINES
|
||||
// КОНВЕЙЕРЫ
|
||||
//
|
||||
// DataFrame-based:
|
||||
// Табличные:
|
||||
// DataPipeline
|
||||
// ClassificationDataPipeline
|
||||
// RegressionDataPipeline
|
||||
// ClusteringDataPipeline
|
||||
//
|
||||
// Matrix/Vector-based:
|
||||
// Матричные:
|
||||
// MatrixPipeline
|
||||
// ClassificationMatrixPipeline
|
||||
// RegressionMatrixPipeline
|
||||
|
|
@ -37,6 +40,24 @@ unit MLABC;
|
|||
// для построения специализированных конвейеров.
|
||||
// =============================================================
|
||||
|
||||
// =============================================================
|
||||
// ПОЛИТИКА PREDICT
|
||||
//
|
||||
// 1. Классификация:
|
||||
// • Predict возвращает метки классов в том же виде,
|
||||
// в каком они были поданы модели при обучении.
|
||||
// • PredictLabels возвращает строковые метки классов.
|
||||
//
|
||||
// 2. Регрессия:
|
||||
// • Predict возвращает вектор числовых предсказаний.
|
||||
//
|
||||
// 3. Кластеризация:
|
||||
// • Predict и FitPredict возвращают номера кластеров.
|
||||
//
|
||||
// Внутреннее кодирование классов может использоваться внутри модели,
|
||||
// но наружу через Predict оно не выдаётся.
|
||||
// =============================================================
|
||||
|
||||
interface
|
||||
|
||||
uses LinearAlgebraML;
|
||||
|
|
@ -68,6 +89,9 @@ type
|
|||
ConfusionMatrix = MetricsABC.ConfusionMatrix;
|
||||
|
||||
DataPipeline = MLPipelineABC.DataPipeline;
|
||||
ClassificationDataPipeline = MLPipelineABC.ClassificationDataPipeline;
|
||||
RegressionDataPipeline = MLPipelineABC.RegressionDataPipeline;
|
||||
ClusteringDataPipeline = MLPipelineABC.ClusteringDataPipeline;
|
||||
|
||||
DataFrame = DataFrameABC.DataFrame;
|
||||
DataFrameCursor = DataFrameABCCore.DataFrameCursor;
|
||||
|
|
@ -134,6 +158,7 @@ type
|
|||
Datasets = MLDatasets.Datasets;
|
||||
Dataset = MLDatasets.Dataset;
|
||||
LabelEncoder = MLDatasets.LabelEncoder;
|
||||
TaskType = MLDatasets.TaskType;
|
||||
|
||||
IModel = MLCoreABC.IModel;
|
||||
IUnsupervisedModel = MLCoreABC.IUnsupervisedModel;
|
||||
|
|
|
|||
|
|
@ -54,35 +54,45 @@ type
|
|||
property IsFitted: boolean read;
|
||||
end;
|
||||
|
||||
/// Интерфейс модели без учителя (Unsupervised Model).
|
||||
/// Интерфейс модели без учителя.
|
||||
/// Наследуется от базового интерфейса IModel.
|
||||
/// Предназначен для алгоритмов, обучающихся только по признакам X
|
||||
/// без использования целевых значений (y)
|
||||
/// без использования целевых значений y.
|
||||
IUnsupervisedModel = interface(IModel)
|
||||
function Fit(X: Matrix): IUnsupervisedModel;
|
||||
end;
|
||||
|
||||
/// Интерфейс алгоритма кластеризации (unsupervised learning).
|
||||
/// Интерфейс алгоритма кластеризации.
|
||||
/// Предназначен для моделей, разбивающих объекты на кластеры
|
||||
/// без использования целевой переменной.
|
||||
/// Основной сценарий использования — FitPredict, возвращающий
|
||||
/// индекс кластера для каждого объекта обучающей выборки
|
||||
/// номер кластера для каждого объекта обучающей выборки.
|
||||
///
|
||||
/// Важно:
|
||||
/// • номер кластера — это внутренний идентификатор алгоритма;
|
||||
/// • он не связан с внешними метками классов, как в классификации;
|
||||
/// • одинаковые по смыслу кластеры в разных запусках могут получить
|
||||
/// разные номера.
|
||||
IClusterer = interface(IUnsupervisedModel)
|
||||
// function PredictLabels(X: Matrix): array of integer;
|
||||
|
||||
/// Выполняет кластеризацию данных и возвращает массив индексов кластеров
|
||||
/// Выполняет кластеризацию данных и возвращает массив номеров кластеров
|
||||
/// (0,1,2,...) для каждого объекта. Значение -1 может использоваться
|
||||
/// для обозначения шума (например, в DBSCAN).
|
||||
///
|
||||
/// Возвращаемые значения являются внутренними номерами кластеров,
|
||||
/// а не внешними метками, заданными пользователем.
|
||||
function FitPredict(X: Matrix): array of integer;
|
||||
end;
|
||||
|
||||
/// Интерфейс кластеризатора, поддерживающего предсказание для новых данных.
|
||||
/// Используется для алгоритмов, задающих явное отображение X → cluster
|
||||
/// (например, KMeans через ближайший центр кластера)
|
||||
/// Используется для алгоритмов, задающих явное отображение X → кластер
|
||||
/// (например, KMeans через ближайший центр кластера).
|
||||
IPredictiveClusterer = interface(IClusterer)
|
||||
/// Возвращает внутренний индекс кластера для каждого объекта из X
|
||||
/// Возвращает номер кластера для каждого объекта из X
|
||||
/// без повторного обучения модели.
|
||||
/// Требует предварительного вызова Fit или FitPredict.
|
||||
///
|
||||
/// Возвращаемые значения являются внутренними номерами кластеров,
|
||||
/// а не внешними метками классов.
|
||||
function Predict(X: Matrix): array of integer;
|
||||
end;
|
||||
|
||||
|
|
|
|||
|
|
@ -351,7 +351,7 @@ const
|
|||
ER_VALUECOUNTS_ONLY_CLASSIFICATION =
|
||||
'ValueCounts доступны только для задач классификации!!ValueCounts are only available for classification datasets';
|
||||
ER_DATASET_TARGET_MISSING =
|
||||
'Target обязателен для задач обучения с учителем!!Target is required for supervised learning datasets';
|
||||
'Target обязателен для задач с учителем!!Target is required for supervised learning datasets';
|
||||
ER_PARAM_LE =
|
||||
'Параметр {0} должен быть <= допустимого максимума!!Parameter {0} must be <= the allowed maximum value';
|
||||
ER_PARAM_RANGE_01 =
|
||||
|
|
|
|||
|
|
@ -1366,9 +1366,10 @@ type
|
|||
/// Используется для анализа обучения.
|
||||
function PredictStageProba(X: Matrix; m: integer): Matrix;
|
||||
|
||||
/// Предсказывает классы по первым m итерациям бустинга.
|
||||
/// Предсказывает метки классов по первым m итерациям бустинга.
|
||||
/// Возвращает их в том же виде, в каком они были поданы модели при обучении.
|
||||
/// Удобно для построения learning curve.
|
||||
function PredictStage(X: Matrix; m: integer): Vector;
|
||||
function PredictStage(X: Matrix; m: integer): array of integer;
|
||||
|
||||
/// Текущее количество деревьев в ансамбле.
|
||||
function TreeCount: integer := fEstimators.Count;
|
||||
|
|
@ -1458,7 +1459,6 @@ type
|
|||
private
|
||||
// ==== classification state ====
|
||||
fYEnc: array of integer;
|
||||
fClasses: array of double;
|
||||
fClassCount: integer;
|
||||
fLabels: ClassifierLabelHelper;
|
||||
|
||||
|
|
@ -1594,7 +1594,7 @@ type
|
|||
/// • обученное состояние модели (центры кластеров) НЕ копируется методом Clone
|
||||
function Fit(X: Matrix): IUnsupervisedModel;
|
||||
|
||||
/// Возвращает внутренний индекс кластера для каждого объекта из X.
|
||||
/// Возвращает номер кластера для каждого объекта из X.
|
||||
/// Требует предварительного вызова Fit.
|
||||
function Predict(X: Matrix): array of integer;
|
||||
|
||||
|
|
@ -1684,23 +1684,23 @@ type
|
|||
{$endregion Models}
|
||||
|
||||
{$region MatrixPipeline}
|
||||
/// Последовательный конвейер машинного обучения (supervised).
|
||||
/// Общая база для матричных конвейеров с учителем.
|
||||
/// Гарантирует строгий порядок выполнения шагов:
|
||||
/// [преобразователи] → [модель].
|
||||
///
|
||||
/// Поддерживает:
|
||||
/// • преобразователи без учёта целевой переменной (unsupervised);
|
||||
/// • преобразователи с учётом целевой переменной (supervised);
|
||||
/// • преобразователи без учёта целевой переменной;
|
||||
/// • преобразователи с учётом целевой переменной;
|
||||
/// • одну финальную модель с учителем.
|
||||
///
|
||||
/// Все преобразователи применяются последовательно к признакам X,
|
||||
/// после чего финальная модель обучается на (X, y).
|
||||
///
|
||||
/// Обеспечивает единый интерфейс Fit(X, y) / Predict(X)
|
||||
/// и воспроизводимость полного процесса обучения
|
||||
/// и воспроизводимость полного процесса обучения.
|
||||
///
|
||||
/// MatrixPipeline используется, когда данные уже представлены
|
||||
/// в виде Matrix X и Vector y
|
||||
/// в виде Matrix X и вектора y.
|
||||
MatrixPipeline = class(IModel)
|
||||
protected
|
||||
fTransformers: List<ITransformer>;
|
||||
|
|
@ -1775,8 +1775,8 @@ type
|
|||
|
||||
/// Строит матричный конвейер для задачи классификации.
|
||||
/// Шаги указываются в порядке выполнения:
|
||||
/// сначала преобразователи, затем модель.
|
||||
/// Последний шаг должен быть моделью.
|
||||
/// сначала преобразователи, затем модель.
|
||||
/// Последний шаг должен быть моделью.
|
||||
static function BuildClassification(params steps: array of IPipelineStep): ClassificationMatrixPipeline;
|
||||
|
||||
/// Строит матричный конвейер для задачи регрессии.
|
||||
|
|
@ -1801,7 +1801,7 @@ type
|
|||
/// X — матрица m × n (m объектов, n признаков).
|
||||
/// y — вектор длины m с целевыми значениями.
|
||||
/// Последовательно обучает все трансформеры и применяет их к данным,
|
||||
/// после чего обучает финальную supervised-модель.
|
||||
/// после чего обучает финальную модель с учителем.
|
||||
///
|
||||
/// Примечание:
|
||||
/// • обученное состояние пайплайна НЕ копируется методом Clone
|
||||
|
|
@ -1855,47 +1855,36 @@ type
|
|||
function Fit(X: Matrix; y: Vector): IRegressor; reintroduce;
|
||||
end;
|
||||
|
||||
/// Последовательный конвейер машинного обучения (unsupervised).
|
||||
/// Гарантирует строгий порядок выполнения шагов:
|
||||
/// [преобразователи].
|
||||
/// Общая база для матричных конвейеров без учителя.
|
||||
///
|
||||
/// Поддерживает:
|
||||
/// • преобразователи без учёта целевой переменной (unsupervised).
|
||||
///
|
||||
/// Все преобразователи применяются последовательно к признакам X.
|
||||
///
|
||||
/// Обеспечивает единый интерфейс Fit(X) / Transform(X)
|
||||
/// и воспроизводимость полного процесса преобразования данных.
|
||||
///
|
||||
/// Используется, когда данные уже представлены
|
||||
/// в виде Matrix X и отсутствует целевая переменная
|
||||
/// Поддерживает последовательность матричных преобразователей
|
||||
/// и одну финальную модель без учителя.
|
||||
/// Используется как базовый класс для специализированных
|
||||
/// матричных конвейеров, например ClusteringMatrixPipeline.
|
||||
UnsupervisedMatrixPipelineBase = class(IUnsupervisedModel)
|
||||
protected
|
||||
fTransformers: List<ITransformer>;
|
||||
fModel: IModel;
|
||||
fFitted: boolean;
|
||||
public
|
||||
/// Создаёт конвейер машинного обучения для заданной модели:
|
||||
/// • model — модель, которая будет применена
|
||||
/// после последовательного применения всех преобразователей.
|
||||
/// Модель должна реализовывать интерфейс IModel (без учёта целевой переменной)
|
||||
/// Создаёт конвейер машинного обучения для заданной модели.
|
||||
/// Модель применяется после последовательного выполнения всех преобразователей.
|
||||
constructor Create(model: IModel);
|
||||
|
||||
/// Создаёт пустой пайплайн (конвейер машинного обучения).
|
||||
/// Модель должна быть установлена через SetModel
|
||||
/// Создаёт пустой конвейер.
|
||||
/// Модель должна быть установлена позже через SetModel.
|
||||
constructor Create;
|
||||
|
||||
/// Строит конвейер машинного обучения из последовательности шагов.
|
||||
/// Шаги указываются в порядке выполнения:
|
||||
/// сначала преобразователи, затем модель.
|
||||
/// Последний шаг обязан быть моделью (IModel).
|
||||
/// Возвращает сконструированный конвейер.
|
||||
/// Строит матричный конвейер для задачи кластеризации.
|
||||
/// Шаги указываются в порядке выполнения:
|
||||
/// сначала преобразователи, затем модель.
|
||||
/// Последний шаг должен быть моделью.
|
||||
static function Build(params steps: array of IPipelineStep): ClusteringMatrixPipeline;
|
||||
|
||||
/// Устанавливает или заменяет модель.
|
||||
/// Устанавливает или заменяет модель.
|
||||
function SetModel(m: IModel): UnsupervisedMatrixPipelineBase;
|
||||
|
||||
/// Добавляет преобразование в конец пайплайна
|
||||
/// Добавляет преобразование в конец пайплайна.
|
||||
function Add(t: ITransformer): UnsupervisedMatrixPipelineBase;
|
||||
|
||||
/// Обучает пайплайн на данных.
|
||||
|
|
@ -1938,6 +1927,12 @@ type
|
|||
function Name: string := Self.GetType.Name;
|
||||
end;
|
||||
|
||||
/// Матричный конвейер для задачи кластеризации.
|
||||
/// FitPredict работает с любым кластеризатором.
|
||||
/// Predict для новых данных доступен только тогда,
|
||||
/// когда финальная модель реализует IPredictiveClusterer
|
||||
/// (например, KMeans).
|
||||
/// Для алгоритмов вроде DBSCAN используйте FitPredict.
|
||||
ClusteringMatrixPipeline = class(UnsupervisedMatrixPipelineBase)
|
||||
end;
|
||||
|
||||
|
|
@ -2093,7 +2088,7 @@ type
|
|||
|
||||
/// Трансформер, удаляющий признаки с малой дисперсией.
|
||||
/// Удаляет столбцы X_j, для которых Var(X_j) < threshold.
|
||||
/// Не использует целевую переменную (unsupervised)
|
||||
/// Не использует целевую переменную.
|
||||
VarianceThreshold = class(IUnsupervisedTransformer)
|
||||
private
|
||||
fThreshold: real;
|
||||
|
|
@ -2465,8 +2460,8 @@ const
|
|||
'Метки классов недоступны. Убедитесь, что модель обучена и метки установлены!!Class labels are not available. Ensure the model is fitted and class labels are set';
|
||||
ER_LABEL_INDEX_OUT_OF_RANGE =
|
||||
'Индекс метки {0} вне диапазона [0, {1})!!Label index {0} is out of range [0, {1})';
|
||||
ER_PIPELINE_LAST_NOT_SUPERVISED_MODEL =
|
||||
'Последний шаг Pipeline должен быть supervised-моделью!!' +
|
||||
ER_PIPELINE_LAST_NOT_SUPERVISED_MODEL =
|
||||
'Последний шаг Pipeline должен быть моделью с учителем!!' +
|
||||
'Last Pipeline step must be a supervised model';
|
||||
ER_INTERNAL_INVALID_MODEL_CLONE =
|
||||
'Внутренняя ошибка: Clone модели вернул несовместимый тип!!' +
|
||||
|
|
@ -2636,7 +2631,6 @@ begin
|
|||
if MLConfig.ValidateFiniteInputs then
|
||||
begin
|
||||
CheckXForFit(X);
|
||||
CheckYForFit(y);
|
||||
end;
|
||||
|
||||
var m := X.RowCount;
|
||||
|
|
@ -2761,7 +2755,6 @@ begin
|
|||
if MLConfig.ValidateFiniteInputs then
|
||||
begin
|
||||
CheckXForFit(X);
|
||||
CheckYForFit(y);
|
||||
end;
|
||||
|
||||
if X.RowCount = 0 then
|
||||
|
|
@ -3306,7 +3299,6 @@ begin
|
|||
if MLConfig.ValidateFiniteInputs then
|
||||
begin
|
||||
CheckXForFit(X);
|
||||
CheckYForFit(y);
|
||||
end;
|
||||
|
||||
if X.RowCount = 0 then
|
||||
|
|
@ -4758,7 +4750,6 @@ begin
|
|||
if MLConfig.ValidateFiniteInputs then
|
||||
begin
|
||||
CheckXForFit(X);
|
||||
CheckYForFit(y);
|
||||
end;
|
||||
|
||||
if X.RowCount = 0 then
|
||||
|
|
@ -5992,7 +5983,6 @@ begin
|
|||
if MLConfig.ValidateFiniteInputs then
|
||||
begin
|
||||
CheckXForFit(XTrain);
|
||||
CheckYForFit(yTrain);
|
||||
end;
|
||||
|
||||
// --- shape checks ---
|
||||
|
|
@ -6013,7 +6003,6 @@ begin
|
|||
if MLConfig.ValidateFiniteInputs then
|
||||
begin
|
||||
CheckXForPredict(XVal);
|
||||
CheckYForFit(yVal);
|
||||
end;
|
||||
|
||||
if XVal.RowCount <> yVal.Length then
|
||||
|
|
@ -7123,12 +7112,12 @@ begin
|
|||
Result := probs;
|
||||
end;
|
||||
|
||||
function GradientBoostingClassifier.PredictStage(X: Matrix; m: integer): Vector;
|
||||
function GradientBoostingClassifier.PredictStage(X: Matrix; m: integer): array of integer;
|
||||
begin
|
||||
var probs := PredictStageProba(X, m);
|
||||
|
||||
var n := probs.RowCount;
|
||||
var resultVec := new Vector(n);
|
||||
SetLength(Result, n);
|
||||
|
||||
for var i := 0 to n - 1 do
|
||||
begin
|
||||
|
|
@ -7142,10 +7131,8 @@ begin
|
|||
best := cls;
|
||||
end;
|
||||
|
||||
resultVec[i] := fClasses[best];
|
||||
Result[i] := fClasses[best];
|
||||
end;
|
||||
|
||||
Result := resultVec;
|
||||
end;
|
||||
|
||||
function GradientBoostingClassifier.FeatureImportances: Vector;
|
||||
|
|
@ -7506,11 +7493,6 @@ begin
|
|||
if fClassCount < 2 then
|
||||
ArgumentError(ER_NEED_AT_LEAST_TWO_CLASSES);
|
||||
|
||||
// сохранить оригинальные метки (double API)
|
||||
SetLength(fClasses, fClassCount);
|
||||
for var i := 0 to fClassCount - 1 do
|
||||
fClasses[i] := classesInt[i];
|
||||
|
||||
if fLabels = nil then
|
||||
fLabels := new ClassifierLabelHelper;
|
||||
fLabels.SetClassValues(classesInt);
|
||||
|
|
@ -7867,7 +7849,6 @@ begin
|
|||
if MLConfig.ValidateFiniteInputs then
|
||||
begin
|
||||
CheckXForFit(X);
|
||||
CheckYForFit(y);
|
||||
end;
|
||||
|
||||
fXTrain := X.Clone;
|
||||
|
|
@ -8701,6 +8682,7 @@ begin
|
|||
ArgumentError(ER_EMPTY_DATASET);
|
||||
|
||||
var Xt := X;
|
||||
var yVec: Vector := nil;
|
||||
|
||||
for var i := 0 to fTransformers.Count - 1 do
|
||||
begin
|
||||
|
|
@ -8709,8 +8691,12 @@ begin
|
|||
if t = nil then
|
||||
ArgumentError(ER_PIPELINE_STEP_NULL);
|
||||
|
||||
if t is ISupervisedTransformer then
|
||||
ArgumentError(ER_PIPELINE_INVALID_STEP_ORDER)
|
||||
if t is ISupervisedTransformer(var sup) then
|
||||
begin
|
||||
if yVec = nil then
|
||||
yVec := new Vector(y);
|
||||
fTransformers[i] := sup.Fit(Xt, yVec);
|
||||
end
|
||||
else if t is IUnsupervisedTransformer(var unsup) then
|
||||
fTransformers[i] := unsup.Fit(Xt)
|
||||
else
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ type
|
|||
/// Возвращает только те столбцы, которые реально присутствуют в current,
|
||||
/// без повторов и в итоговом порядке для построения матрицы признаков.
|
||||
///
|
||||
/// Если после preprocessing не осталось ни одного признака,
|
||||
/// Если после предобработки не осталось ни одного признака,
|
||||
/// выбрасывается исключение
|
||||
function ResolveFinalFeatures(current: DataFrame): array of string;
|
||||
|
||||
|
|
@ -116,8 +116,8 @@ type
|
|||
|
||||
/// Добавляет шаг в конец конвейера.
|
||||
/// Принимает:
|
||||
/// • IPreprocessor (DataFrame-уровень)
|
||||
/// • ITransformer (Matrix-уровень)
|
||||
/// • IPreprocessor (табличный шаг)
|
||||
/// • ITransformer (матричный шаг)
|
||||
/// • IModel (модель, должна быть последней)
|
||||
/// Запрещено добавлять шаги после вызова Fit.
|
||||
function Add(step: IPipelineStep): SupervisedDataPipelineBase;
|
||||
|
|
@ -126,7 +126,7 @@ type
|
|||
///
|
||||
/// Матричные шаги и модель при этом не используются.
|
||||
/// Метод предназначен в основном для просмотра и анализа промежуточного
|
||||
/// результата preprocessing.
|
||||
/// результата предобработки.
|
||||
///
|
||||
/// Полученный DataFrame обычно не следует повторно подавать в тот же pipeline,
|
||||
/// так как DataFrame-преобразования будут выполнены ещё раз.
|
||||
|
|
@ -169,22 +169,17 @@ type
|
|||
end;
|
||||
|
||||
/// Общая база для табличных конвейеров без учителя.
|
||||
///
|
||||
/// UnsupervisedDataPipelineBase — конвейер подготовки данных и обучения модели без учителя на DataFrame.
|
||||
///
|
||||
/// Поддерживает два уровня шагов:
|
||||
/// • DataFrame-уровень: IPreprocessor (Fit/Transform над DataFrame)
|
||||
/// • Matrix-уровень: IUnsupervisedTransformer и IUnsupervisedModel
|
||||
/// (после преобразования DataFrame → Matrix)
|
||||
///
|
||||
/// Правила порядка шагов:
|
||||
/// • Сначала идут только DataFrame-шаги (IPreprocessor).
|
||||
/// • Затем — матричные шаги (IUnsupervisedTransformer).
|
||||
/// • Модель (IUnsupervisedModel) добавляется последней и может быть только одна.
|
||||
/// Поддерживает два типа шагов:
|
||||
/// • табличные преобразователи;
|
||||
/// • матричные преобразователи и финальную модель без учителя.
|
||||
///
|
||||
/// В конвейере используются:
|
||||
/// • features — признаки (целевая переменная отсутствует).
|
||||
/// Порядок шагов строгий:
|
||||
/// • сначала идут табличные преобразователи;
|
||||
/// • затем матричные преобразователи;
|
||||
/// • модель без учителя добавляется последней и может быть только одна.
|
||||
///
|
||||
/// Конвейер работает только с признаками.
|
||||
UnsupervisedDataPipelineBase = class(PipelineBase, IModel)
|
||||
protected
|
||||
fModel: IUnsupervisedModel;
|
||||
|
|
@ -202,8 +197,8 @@ type
|
|||
|
||||
/// Добавляет шаг в конец конвейера.
|
||||
/// Принимает:
|
||||
/// • IPreprocessor (DataFrame-уровень)
|
||||
/// • ITransformer (Matrix-уровень)
|
||||
/// • IPreprocessor (табличный шаг)
|
||||
/// • ITransformer (матричный шаг)
|
||||
/// • IUnsupervisedModel (модель, должна быть последней)
|
||||
function Add(step: IPipelineStep): UnsupervisedDataPipelineBase;
|
||||
|
||||
|
|
@ -211,7 +206,7 @@ type
|
|||
///
|
||||
/// Матричные шаги и модель при этом не используются.
|
||||
/// Метод предназначен в основном для просмотра и анализа промежуточного
|
||||
/// результата preprocessing.
|
||||
/// результата предобработки.
|
||||
///
|
||||
/// Полученный DataFrame обычно не следует повторно подавать в тот же pipeline,
|
||||
/// так как DataFrame-преобразования будут выполнены ещё раз.
|
||||
|
|
@ -226,7 +221,7 @@ type
|
|||
end;
|
||||
|
||||
/// Табличный конвейер для задачи кластеризации.
|
||||
/// Predict возвращает внутренние индексы кластеров.
|
||||
/// Predict возвращает номера кластеров.
|
||||
ClusteringDataPipeline = class(UnsupervisedDataPipelineBase)
|
||||
public
|
||||
function WithModel(model: IUnsupervisedModel): ClusteringDataPipeline;
|
||||
|
|
@ -234,7 +229,7 @@ type
|
|||
/// Обучает конвейер и сразу возвращает метки кластеров.
|
||||
function FitPredict(df: DataFrame): array of integer;
|
||||
/// Делает предсказание кластеров для объектов из DataFrame.
|
||||
/// Возвращает внутренние индексы кластеров.
|
||||
/// Возвращает номера кластеров.
|
||||
function Predict(df: DataFrame): array of integer;
|
||||
end;
|
||||
|
||||
|
|
@ -280,9 +275,11 @@ const
|
|||
ER_PIPELINE_FINALFEATURES =
|
||||
'Внутренняя ошибка pipeline: итоговый набор признаков не определён. Возможно, Fit не был выполнен корректно!!Pipeline internal error: final feature set is not defined. Fit may not have been executed correctly';
|
||||
ER_PIPELINE_TARGET_REMOVED =
|
||||
'Целевая переменная "{0}" была удалена на этапе preprocessing pipeline!!Target column "{0}" was removed during pipeline preprocessing';
|
||||
'Целевая переменная "{0}" была удалена на этапе предобработки конвейера!!' +
|
||||
'Target column "{0}" was removed during pipeline preprocessing';
|
||||
ER_PIPELINE_NO_FEATURES =
|
||||
'После preprocessing pipeline не осталось признаков для обучения модели!!No features remain after pipeline preprocessing';
|
||||
'После предобработки конвейера не осталось признаков для обучения модели!!' +
|
||||
'No features remain after pipeline preprocessing';
|
||||
ER_MATRIXSTEP_NO_FIT =
|
||||
'Шаг матричного конвейера #{0} не поддерживает Fit!!Matrix step #{0} does not support Fit';
|
||||
ER_Model_NoFit =
|
||||
|
|
@ -307,7 +304,8 @@ const
|
|||
ER_LABEL_INDEX_OUT_OF_RANGE =
|
||||
'Индекс метки {0} вне диапазона [0, {1})!!Label index {0} is out of range [0, {1})';
|
||||
ER_ORDINALENCODER_TARGET_NOT_ALLOWED =
|
||||
'OrdinalEncoder нельзя применять к целевой переменной — кодирование выполняется внутри модели!!OrdinalEncoder cannot be applied to target — encoding is handled internally by the model';
|
||||
'OrdinalEncoder нельзя применять к целевой переменной: её кодирование выполняется внутри модели!!' +
|
||||
'OrdinalEncoder cannot be applied to the target because target encoding is handled inside the model';
|
||||
ER_ENCODELABELS_NOT_CATEGORICAL =
|
||||
'Целевой столбец должен быть категориальным для задач классификации!!Target column must be categorical for classification tasks';
|
||||
ER_CLASSIFICATION_TARGET_MUST_BE_CATEGORICAL_STR_OR_INT =
|
||||
|
|
@ -327,13 +325,13 @@ const
|
|||
'Pipeline не содержит шагов!!' +
|
||||
'Pipeline must contain at least one step';
|
||||
ER_PIPELINE_LAST_NOT_UNSUPERVISED_MODEL =
|
||||
'Последний шаг Pipeline должен быть unsupervised-моделью!!' +
|
||||
'Последний шаг Pipeline должен быть моделью без учителя!!' +
|
||||
'Last Pipeline step must be an unsupervised model';
|
||||
ER_PIPELINE_INVALID_STEP_ORDER =
|
||||
'Неверный порядок шагов в Pipeline: модель должна быть последней!!' +
|
||||
'Invalid pipeline step order: model must be the last step';
|
||||
ER_PIPELINE_LAST_NOT_SUPERVISED_MODEL =
|
||||
'Последний шаг Pipeline должен быть supervised-моделью!!' +
|
||||
'Последний шаг Pipeline должен быть моделью с учителем!!' +
|
||||
'Last Pipeline step must be a supervised model';
|
||||
ER_MODEL_NOT_CLASSIFIER =
|
||||
'Модель не является классификатором!!' +
|
||||
|
|
|
|||
Loading…
Reference in a new issue