mlpIPELINEabc - НОВЫЙ МОДУЛЬ
DataPipeline - закончен
This commit is contained in:
parent
f834ed4ea9
commit
398ea2440f
|
|
@ -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 = "3764";
|
||||
public const string Revision = "3765";
|
||||
|
||||
public const string MainVersion = Major + "." + Minor;
|
||||
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
%COREVERSION%=1
|
||||
%REVISION%=3764
|
||||
%MINOR%=11
|
||||
%REVISION%=3765
|
||||
%COREVERSION%=1
|
||||
%MAJOR%=3
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3.11.1.3764
|
||||
3.11.1.3765
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
!define VERSION '3.11.1.3764'
|
||||
!define VERSION '3.11.1.3765'
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ uses
|
|||
TasksArr, TasksMatr, TasksStr, Tasks1Begin, Tasks1BoolIfCase, Tasks1Loops, Tasks1Arr,
|
||||
WPF,
|
||||
DataFrameABC, DataFrameABCCore, LinearAlgebraML, PreprocessorABC,
|
||||
MetricsABC, MLABC, MLCoreABC, MLModelsABC, ValidationML, MLExceptions, InspectionML
|
||||
MetricsABC, MLABC, MLCoreABC, MLModelsABC, ValidationML, MLExceptions, InspectionML, MLPipelineABC
|
||||
;
|
||||
|
||||
begin
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
ABCDatabases,
|
||||
School, SF, TurtleABC,
|
||||
DataFrameABC, DataFrameABCCore, LinearAlgebraML, PreprocessorABC,
|
||||
MetricsABC, MLABC, MLCoreABC, MLModelsABC, ValidationML, MLExceptions, InspectionML
|
||||
MetricsABC, MLABC, MLCoreABC, MLModelsABC, ValidationML, MLExceptions, InspectionML, MLPipelineABC
|
||||
;
|
||||
|
||||
begin
|
||||
|
|
|
|||
|
|
@ -190,6 +190,7 @@
|
|||
File ..\bin\Lib\ValidationML.pcu
|
||||
File ..\bin\Lib\MLExceptions.pcu
|
||||
File ..\bin\Lib\InspectionML.pcu
|
||||
File ..\bin\Lib\MLPipelineABC.pcu
|
||||
|
||||
File ..\bin\Lib\PABCRtl.dll
|
||||
File ..\bin\Lib\HelixToolkit.Wpf.dll
|
||||
|
|
@ -294,6 +295,7 @@
|
|||
${AddFile} "ValidationML.pcu"
|
||||
${AddFile} "MLExceptions.pcu"
|
||||
${AddFile} "InspectionML.pcu"
|
||||
${AddFile} "MLPipelineABC.pcu"
|
||||
|
||||
|
||||
${AddFile} "turtle.png"
|
||||
|
|
@ -435,6 +437,7 @@
|
|||
File ..\bin\Lib\ValidationML.pas
|
||||
File ..\bin\Lib\MLExceptions.pas
|
||||
File ..\bin\Lib\InspectionML.pas
|
||||
File ..\bin\Lib\MLPipelineABC.pas
|
||||
|
||||
File ..\bin\Lib\__RedirectIOMode.vb
|
||||
File ..\bin\Lib\VBSystem.vb
|
||||
|
|
@ -526,6 +529,8 @@
|
|||
${AddFile} "ValidationML.pas"
|
||||
${AddFile} "MLExceptions.pas"
|
||||
${AddFile} "InspectionML.pas"
|
||||
${AddFile} "MLPipelineABC.pas"
|
||||
|
||||
|
||||
${AddFile} "__RedirectIOMode.vb"
|
||||
${AddFile} "VBSystem.vb"
|
||||
|
|
|
|||
|
|
@ -119,6 +119,9 @@ copy bin\Lib\MLABC.pcu Release\PascalABCNETLinux\Lib\MLABC.pcu
|
|||
copy bin\Lib\MLCoreABC.pcu Release\PascalABCNETLinux\Lib\MLCoreABC.pcu
|
||||
copy bin\Lib\MLModelsABC.pcu Release\PascalABCNETLinux\Lib\MLModelsABC.pcu
|
||||
copy bin\Lib\ValidationML.pcu Release\PascalABCNETLinux\Lib\ValidationML.pcu
|
||||
copy bin\Lib\MLExceptions.pcu Release\PascalABCNETLinux\Lib\MLExceptions.pcu
|
||||
copy bin\Lib\InspectionML.pcu Release\PascalABCNETLinux\Lib\InspectionML.pcu
|
||||
copy bin\Lib\MLPipelineABC.pcu Release\PascalABCNETLinux\Lib\MLPipelineABC.pcu
|
||||
|
||||
copy bin\Lib\ABCDatabases.pas Release\PascalABCNETLinux\LibSource\ABCDatabases.pas
|
||||
copy bin\Lib\BBCMicrobit.pas Release\PascalABCNETLinux\LibSource\BBCMicrobit.pas
|
||||
|
|
@ -169,6 +172,10 @@ copy bin\Lib\MLABC.pas Release\PascalABCNETLinux\LibSource\MLABC.pas
|
|||
copy bin\Lib\MLCoreABC.pas Release\PascalABCNETLinux\LibSource\MLCoreABC.pas
|
||||
copy bin\Lib\MLModelsABC.pas Release\PascalABCNETLinux\LibSource\MLModelsABC.pas
|
||||
copy bin\Lib\ValidationML.pas Release\PascalABCNETLinux\LibSource\ValidationML.pas
|
||||
copy bin\Lib\MLExceptions.pas Release\PascalABCNETLinux\LibSource\MLExceptions.pas
|
||||
copy bin\Lib\InspectionML.pas Release\PascalABCNETLinux\LibSource\InspectionML.pas
|
||||
copy bin\Lib\MLPipelineABC.pas Release\PascalABCNETLinux\LibSource\MLPipelineABC.pas
|
||||
|
||||
|
||||
copy bin\Lng\Eng\.LanguageName Release\PascalABCNETLinux\Lng\Eng\.LanguageName
|
||||
copy bin\Lng\Eng\AspectsTree.dat Release\PascalABCNETLinux\Lng\Eng\AspectsTree.dat
|
||||
|
|
|
|||
|
|
@ -6,24 +6,31 @@ interface
|
|||
|
||||
uses LinearAlgebraML;
|
||||
uses ValidationML;
|
||||
uses MLCoreABC;
|
||||
uses MLModelsABC;
|
||||
uses MetricsABC;
|
||||
uses PreprocessorABC;
|
||||
uses DataFrameABC;
|
||||
uses MLExceptions;
|
||||
uses InspectionML;
|
||||
uses MLPipelineABC;
|
||||
|
||||
type
|
||||
Vector = LinearAlgebraML.Vector;
|
||||
Matrix = LinearAlgebraML.Matrix;
|
||||
|
||||
Validation = ValidationML.Validation;
|
||||
|
||||
ConfusionMatrix = MetricsABC.ConfusionMatrix;
|
||||
Metrics = MetricsABC.Metrics;
|
||||
DataPipeline = PreprocessorABC.DataPipeline;
|
||||
DataStandardScaler = PreprocessorABC.DataStandardScaler;
|
||||
|
||||
DataPipeline = MLPipelineABC.DataPipeline;
|
||||
|
||||
DataFrame = DataFrameABC.DataFrame;
|
||||
Statistics = DataFrameABC.Statistics;
|
||||
CsvLoader = DataFrameABC.CsvLoader;
|
||||
|
||||
IProbabilisticClassifier = MLCoreABC.IProbabilisticClassifier;
|
||||
|
||||
StandardScaler = MLModelsABC.StandardScaler;
|
||||
PCATransformer = MLModelsABC.PCATransformer;
|
||||
|
|
@ -63,60 +70,5 @@ type
|
|||
|
||||
implementation
|
||||
|
||||
const
|
||||
ER_TO_MATRIX_NO_COLUMNS =
|
||||
'ToMatrix: не указаны столбцы!!ToMatrix: no columns specified';
|
||||
ER_TO_VECTOR_NON_NUMERIC =
|
||||
'ToVector: столбец "{0}" содержит нечисловые или NA значения!!' +
|
||||
'ToVector: column "{0}" contains non-numeric or NA values';
|
||||
|
||||
function ToMatrix(Self: DataFrame; colNames: array of string): Matrix; extensionmethod;
|
||||
begin
|
||||
var df := Self;
|
||||
var n := df.RowCount;
|
||||
var p := colNames.Length;
|
||||
|
||||
if p = 0 then
|
||||
ArgumentError(ER_TO_MATRIX_NO_COLUMNS);
|
||||
|
||||
Result := new Matrix(n, p);
|
||||
|
||||
for var j := 0 to p - 1 do
|
||||
begin
|
||||
var col := df[colNames[j]];
|
||||
|
||||
for var i := 0 to n - 1 do
|
||||
begin
|
||||
var value: real;
|
||||
|
||||
if not col.TryGetNumericValue(i, value) then
|
||||
raise new Exception(
|
||||
'ToMatrix: column "' + colNames[j] +
|
||||
'" contains non-numeric or NA values');
|
||||
|
||||
Result[i,j] := value;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ToVector(Self: DataFrame; colName: string): Vector; extensionmethod;
|
||||
begin
|
||||
var df := Self;
|
||||
var n := df.RowCount;
|
||||
Result := new Vector(n);
|
||||
|
||||
var col := df[colName];
|
||||
|
||||
for var i := 0 to n - 1 do
|
||||
begin
|
||||
var value: real;
|
||||
|
||||
if not col.TryGetNumericValue(i, value) then
|
||||
ArgumentError(ER_TO_VECTOR_NON_NUMERIC, colName);
|
||||
|
||||
Result[i] := value;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
|
@ -5,13 +5,24 @@ interface
|
|||
uses LinearAlgebraML;
|
||||
|
||||
type
|
||||
/// Базовый интерфейс шага конвейера машинного обучения.
|
||||
/// Используется для объединения преобразователей и моделей
|
||||
/// в единую последовательность выполнения внутри Pipeline.
|
||||
IPipeStep = interface end;
|
||||
/// Базовый интерфейс шага конвейера машинного обучения.
|
||||
/// Используется для объединения всех типов шагов
|
||||
/// (DataFrame-преобразователей, матричных трансформеров и моделей)
|
||||
/// в единую последовательность выполнения внутри различных Pipeline
|
||||
IPipelineStep = interface end;
|
||||
|
||||
/// Интерфейс шага конвейера, работающего в числовом (матричном) пространстве.
|
||||
/// Реализуется трансформерами и моделями, которые принимают на вход Matrix и Vector
|
||||
/// и используются в Matrix-уровне Pipeline
|
||||
IMatrixStep = interface(IPipelineStep) end;
|
||||
|
||||
/// Интерфейс шага конвейера, работающего на уровне DataFrame.
|
||||
/// Реализуется препроцессорами, которые выполняют преобразования табличных данных
|
||||
/// до перехода в числовое (Matrix) представление
|
||||
IDataStep = interface(IPipelineStep) end;
|
||||
|
||||
/// Базовый интерфейс модели машинного обучения
|
||||
IModel = interface(IPipeStep)
|
||||
IModel = interface(IMatrixStep)
|
||||
function Fit(X: Matrix; y: Vector): IModel;
|
||||
function Predict(X: Matrix): Vector;
|
||||
function Clone: IModel;
|
||||
|
|
@ -36,8 +47,12 @@ type
|
|||
/// Позволяет получать значения в диапазоне (0, 1)
|
||||
/// вместо только итогового решения.
|
||||
IProbabilisticClassifier = interface(IClassifier)
|
||||
/// Возвращает вероятность принадлежности к положительному классу для каждого объекта.
|
||||
/// Возвращает матрицу вероятностей размера (nSamples × nClasses).
|
||||
/// Столбцы соответствуют классам в порядке внутреннего кодирования модели
|
||||
function PredictProba(X: Matrix): Matrix;
|
||||
|
||||
/// Возвращает массив меток классов в порядке столбцов PredictProba.
|
||||
function GetClasses: array of real;
|
||||
end;
|
||||
|
||||
/// Интерфейс регрессионной модели.
|
||||
|
|
@ -49,7 +64,7 @@ type
|
|||
/// Базовый интерфейс преобразования признаков.
|
||||
/// Используется для масштабирования, отбора,
|
||||
/// уменьшения размерности и других преобразований данных.
|
||||
ITransformer = interface(IPipeStep)
|
||||
ITransformer = interface(IMatrixStep)
|
||||
/// Обучает преобразование на данных.
|
||||
/// Запоминает необходимые параметры,
|
||||
/// которые будут использоваться при Transform.
|
||||
|
|
|
|||
|
|
@ -223,6 +223,9 @@ type
|
|||
/// Возвращает матрицу вероятностей (m x k).
|
||||
function PredictProba(X: Matrix): Matrix;
|
||||
|
||||
/// Возвращает массив меток классов в порядке столбцов PredictProba.
|
||||
function GetClasses: array of real;
|
||||
|
||||
/// Возвращает вектор предсказанных классов.
|
||||
function Predict(X: Matrix): Vector;
|
||||
|
||||
|
|
@ -905,6 +908,8 @@ type
|
|||
/// Вероятности получаются через softmax.
|
||||
function PredictProba(X: Matrix): Matrix;
|
||||
|
||||
function GetClasses: array of real;
|
||||
|
||||
/// Создает глубокую копию классификатора.
|
||||
/// Копируются все деревья и внутреннее состояние.
|
||||
function Clone: IModel;
|
||||
|
|
@ -949,8 +954,14 @@ type
|
|||
idx: integer;
|
||||
end;
|
||||
|
||||
/// Режим взвешивания в алгоритме k ближайших соседей.
|
||||
/// Uniform — равномерное голосование/усреднение.
|
||||
/// Distance — веса обратно пропорциональны расстоянию (1 / dist)
|
||||
KNNWeighting = (Uniform, Distance);
|
||||
|
||||
/// Базовый абстрактный класс для алгоритма k ближайших соседей (kNN).
|
||||
/// Реализует общий механизм поиска k ближайших объектов,
|
||||
/// но не определяет способ агрегации (классификация или регрессия)
|
||||
KNNBase = abstract class(IModel)
|
||||
protected
|
||||
// ==== train state ====
|
||||
|
|
@ -973,14 +984,26 @@ type
|
|||
function Partition(left, right: integer): integer;
|
||||
|
||||
public
|
||||
/// Создаёт модель kNN.
|
||||
/// k — число ближайших соседей (k > 0).
|
||||
/// weighting — режим взвешивания соседей
|
||||
constructor Create(k: integer; weighting: KNNWeighting := KNNWeighting.Uniform);
|
||||
|
||||
|
||||
/// Обучает модель на матрице признаков X и целевом векторе y.
|
||||
/// Возвращает текущий экземпляр модели
|
||||
function Fit(X: Matrix; y: Vector): IModel; virtual; abstract;
|
||||
|
||||
/// Выполняет предсказание для матрицы признаков X.
|
||||
/// Возвращает вектор предсказанных значений или меток
|
||||
function Predict(X: Matrix): Vector; virtual; abstract;
|
||||
|
||||
|
||||
/// Создаёт глубокую копию модели
|
||||
function Clone: IModel; virtual; abstract;
|
||||
end;
|
||||
|
||||
/// Классификатор на основе алгоритма k ближайших соседей (kNN).
|
||||
/// Поддерживает равномерное (Uniform) и взвешенное по расстоянию (Distance) голосование.
|
||||
/// Реализует вероятностные предсказания через PredictProba
|
||||
KNNClassifier = class(KNNBase, IProbabilisticClassifier)
|
||||
private
|
||||
// ==== classification state ====
|
||||
|
|
@ -997,27 +1020,57 @@ type
|
|||
procedure EncodeClasses(y: Vector);
|
||||
|
||||
public
|
||||
/// Создаёт классификатор kNN.
|
||||
/// k — число ближайших соседей (k > 0).
|
||||
/// weighting — режим взвешивания голосов соседей
|
||||
constructor Create(k: integer; weighting: KNNWeighting := KNNWeighting.Uniform);
|
||||
|
||||
|
||||
/// Обучает модель на матрице признаков X и векторе меток y.
|
||||
/// Метки классов могут быть произвольными числами.
|
||||
/// Возвращает текущий экземпляр модели
|
||||
function Fit(X: Matrix; y: Vector): IModel; override;
|
||||
|
||||
/// Выполняет предсказание меток классов для объектов X.
|
||||
/// Возвращает вектор предсказанных меток
|
||||
function Predict(X: Matrix): Vector; override;
|
||||
|
||||
/// Возвращает матрицу вероятностей размера (nSamples × nClasses).
|
||||
/// Столбцы соответствуют классам в порядке, возвращаемом GetClasses()
|
||||
function PredictProba(X: Matrix): Matrix;
|
||||
function GetClasses: array of double;
|
||||
|
||||
|
||||
/// Возвращает массив меток классов в порядке столбцов PredictProba
|
||||
function GetClasses: array of real;
|
||||
|
||||
/// Создаёт глубокую копию классификатора
|
||||
function Clone: IModel; override;
|
||||
end;
|
||||
|
||||
/// Регрессор на основе алгоритма k ближайших соседей (kNN).
|
||||
/// Поддерживает равномерное (Uniform) усреднение и взвешенное по расстоянию (Distance) усреднение.
|
||||
/// Предсказание вычисляется как среднее (или взвешенное среднее) значений целевой переменной
|
||||
/// по k ближайшим обучающим объектам
|
||||
KNNRegressor = class(KNNBase, IRegressor)
|
||||
private
|
||||
fYTrain: Vector;
|
||||
|
||||
public
|
||||
/// Создаёт регрессор kNN.
|
||||
/// k — число ближайших соседей (k > 0).
|
||||
/// weighting — режим взвешивания вкладов соседей
|
||||
constructor Create(k: integer; weighting: KNNWeighting := KNNWeighting.Uniform);
|
||||
|
||||
|
||||
/// Обучает модель на матрице признаков X и целевом векторе y.
|
||||
/// Возвращает текущий экземпляр модели
|
||||
function Fit(X: Matrix; y: Vector): IModel; override;
|
||||
|
||||
/// Выполняет предсказание числовых значений для объектов X.
|
||||
/// Возвращает вектор предсказанных значений
|
||||
function Predict(X: Matrix): Vector; override;
|
||||
|
||||
/// Создаёт глубокую копию регрессора
|
||||
function Clone: IModel; override;
|
||||
end;
|
||||
|
||||
{$endregion Models}
|
||||
|
||||
{$region Pipeline}
|
||||
|
|
@ -1032,7 +1085,7 @@ type
|
|||
///
|
||||
/// Обеспечивает единый интерфейс Fit / Predict
|
||||
/// и воспроизводимость полного процесса обучения
|
||||
Pipeline = class(IModel)
|
||||
Pipeline = class(IModel, IProbabilisticClassifier)
|
||||
private
|
||||
fTransformers: List<ITransformer>;
|
||||
fModel: IModel;
|
||||
|
|
@ -1052,7 +1105,7 @@ type
|
|||
/// сначала преобразователи, затем модель.
|
||||
/// Последний шаг обязан быть моделью (IModel).
|
||||
/// Возвращает сконструированный конвейер.
|
||||
static function Build(params steps: array of IPipeStep): Pipeline;
|
||||
static function Build(params steps: array of IPipelineStep): Pipeline;
|
||||
|
||||
/// Устанавливает или заменяет модель.
|
||||
function SetModel(m: IModel): Pipeline;
|
||||
|
|
@ -1072,6 +1125,8 @@ type
|
|||
/// Возвращает матрицу вероятностей (m x k)
|
||||
/// для вероятностной модели в конце пайплайна.
|
||||
function PredictProba(X: Matrix): Matrix;
|
||||
|
||||
function GetClasses: array of real;
|
||||
|
||||
/// Показывает, был ли пайплайн обучен (вызван метод Fit).
|
||||
property IsFitted: boolean read fFitted;
|
||||
|
|
@ -1080,6 +1135,7 @@ type
|
|||
|
||||
function Clone: IModel;
|
||||
end;
|
||||
|
||||
{$endregion Pipeline}
|
||||
|
||||
{$region Transformers}
|
||||
|
|
@ -1922,6 +1978,13 @@ begin
|
|||
Result := Z;
|
||||
end;
|
||||
|
||||
function LogisticRegression.GetClasses: array of real;
|
||||
begin
|
||||
SetLength(Result, fClassCount);
|
||||
for var i := 0 to fClassCount - 1 do
|
||||
Result[i] := fIndexToClass[i];
|
||||
end;
|
||||
|
||||
function LogisticRegression.Predict(X: Matrix): Vector;
|
||||
begin
|
||||
if not fFitted then
|
||||
|
|
@ -4328,6 +4391,13 @@ begin
|
|||
Result := probs;
|
||||
end;
|
||||
|
||||
function GradientBoostingClassifier.GetClasses: array of real;
|
||||
begin
|
||||
SetLength(Result, fClassCount);
|
||||
for var i := 0 to fClassCount - 1 do
|
||||
Result[i] := fClasses[i];
|
||||
end;
|
||||
|
||||
function GradientBoostingClassifier.PredictStageProba(
|
||||
X: Matrix; m: integer): Matrix;
|
||||
begin
|
||||
|
|
@ -4724,7 +4794,7 @@ begin
|
|||
exit(self);
|
||||
end;
|
||||
|
||||
function KNNClassifier.GetClasses: array of double;
|
||||
function KNNClassifier.GetClasses: array of real;
|
||||
begin
|
||||
Result := fClasses;
|
||||
end;
|
||||
|
|
@ -5117,7 +5187,7 @@ begin
|
|||
fModel := model;
|
||||
end;
|
||||
|
||||
class function Pipeline.Build(params steps: array of IPipeStep): Pipeline;
|
||||
class function Pipeline.Build(params steps: array of IPipelineStep): Pipeline;
|
||||
begin
|
||||
if (steps = nil) or (Length(steps) = 0) then
|
||||
ArgumentError(ER_PIPELINE_NO_STEPS);
|
||||
|
|
@ -5220,6 +5290,14 @@ begin
|
|||
.PredictProba(Xt);
|
||||
end;
|
||||
|
||||
function Pipeline.GetClasses: array of real;
|
||||
begin
|
||||
if not (fModel is IProbabilisticClassifier) then
|
||||
ArgumentError(ER_PROBA_NOT_SUPPORTED);
|
||||
|
||||
Result := (fModel as IProbabilisticClassifier).GetClasses;
|
||||
end;
|
||||
|
||||
function Pipeline.ToString: string;
|
||||
begin
|
||||
var sb := 'Pipeline (' +
|
||||
|
|
@ -5250,6 +5328,8 @@ begin
|
|||
p.Add(t.Clone);
|
||||
|
||||
p.SetModel(fModel.Clone);
|
||||
|
||||
p.fFitted := fFitted;
|
||||
|
||||
Result := p;
|
||||
end;
|
||||
|
|
|
|||
372
bin/Lib/MLPipelineABC.pas
Normal file
372
bin/Lib/MLPipelineABC.pas
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
unit MLPipelineABC;
|
||||
|
||||
interface
|
||||
|
||||
uses MLCoreABC;
|
||||
uses PreprocessorABC;
|
||||
uses DataFrameABC;
|
||||
uses LinearAlgebraML;
|
||||
|
||||
type
|
||||
/// DataPipeline — конвейер подготовки данных и обучения модели на DataFrame.
|
||||
/// Поддерживает два уровня шагов:
|
||||
/// • DataFrame-уровень: IPreprocessor (Fit/Transform над DataFrame)
|
||||
/// • Matrix-уровень: ITransformer + IModel (после преобразования DataFrame → Matrix/Vector)
|
||||
///
|
||||
/// Правила порядка шагов:
|
||||
/// • Сначала идут только DataFrame-шаги (IPreprocessor).
|
||||
/// • Затем — матричные шаги (ITransformer).
|
||||
/// • Модель (IModel) добавляется последней и может быть только одна.
|
||||
///
|
||||
/// Если модель не добавлена, DataPipeline работает как чистый DF-конвейер (Fit/Transform/FitTransform)
|
||||
DataPipeline = class
|
||||
private
|
||||
fDataSteps: List<IPreprocessor>;
|
||||
fMatrixSteps: List<ITransformer>;
|
||||
fModel: IModel;
|
||||
|
||||
fTarget: string;
|
||||
fFeatures: array of string;
|
||||
|
||||
fFitted: boolean;
|
||||
|
||||
procedure ValidateSchema(df: DataFrame);
|
||||
public
|
||||
/// Создаёт пустой конвейер
|
||||
constructor Create;
|
||||
|
||||
/// Добавляет шаг в конец конвейера.
|
||||
/// Принимает:
|
||||
/// • IPreprocessor (DataFrame-уровень)
|
||||
/// • ITransformer (Matrix-уровень)
|
||||
/// • IModel (модель, должна быть последней)
|
||||
/// Запрещено добавлять шаги после вызова Fit/FitTransform.
|
||||
function Add(step: IPipelineStep): DataPipeline;
|
||||
|
||||
/// Строит конвейер из последовательности шагов.
|
||||
/// target и features используются только в режиме с моделью (когда в шагах присутствует IModel).
|
||||
/// Шаги должны удовлетворять порядку: DataFrame* → Matrix* → Model.
|
||||
class function Build(target: string; features: array of string;
|
||||
params steps: array of IPipelineStep): DataPipeline;
|
||||
|
||||
/// Обучает конвейер на DataFrame.
|
||||
/// Семантика:
|
||||
/// • выполняет Fit/Transform для всех DataFrame-шагов;
|
||||
/// • если присутствует модель — преобразует DataFrame в (X, y) по features/target,
|
||||
/// затем обучает матричные трансформеры и модель.
|
||||
function Fit(df: DataFrame): DataPipeline;
|
||||
|
||||
/// Применяет обученные DataFrame-шаги к DataFrame и возвращает новый DataFrame.
|
||||
/// В ML-режиме Transform не выполняет матричные шаги и не вызывает модель.
|
||||
function Transform(df: DataFrame): DataFrame;
|
||||
|
||||
/// Выполняет Fit и Transform за один проход для DataFrame-режима.
|
||||
/// Недоступен, если конвейер содержит модель (IModel).
|
||||
function FitTransform(df: DataFrame): DataFrame;
|
||||
|
||||
/// Делает предсказание модели для объектов из DataFrame.
|
||||
/// Доступен только если конвейер содержит модель (IModel) и был обучен (Fit).
|
||||
function Predict(df: DataFrame): Vector;
|
||||
|
||||
/// Возвращает матрицу вероятностей (nSamples × nClasses).
|
||||
/// Доступен только если конечная модель поддерживает IProbabilisticClassifier.
|
||||
function PredictProba(df: DataFrame): Matrix;
|
||||
|
||||
/// Возвращает список классов в порядке столбцов PredictProba.
|
||||
/// Доступен только если конечная модель поддерживает IProbabilisticClassifier.
|
||||
function GetClasses: array of real;
|
||||
|
||||
/// Признак того, что был вызван Fit или FitTransform.
|
||||
property IsFitted: boolean read fFitted;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses MLExceptions;
|
||||
|
||||
const
|
||||
ER_PIPELINE_MODIFY_AFTER_FIT =
|
||||
'Нельзя добавлять шаг после вызова Fit()!!Cannot add step after Fit';
|
||||
ER_PIPELINE_STEP_NULL =
|
||||
'Шаг конвейера не может быть nil!!Pipeline step cannot be nil';
|
||||
ER_DATAPIPE_DF_AFTER_MATRIX =
|
||||
'Шаг DataFrame не может идти после матричных шагов!!DataFrame step cannot appear after matrix steps';
|
||||
ER_PIPELINE_MULTIPLE_MODELS =
|
||||
'В конвейере разрешена только одна модель!!Only one model is allowed in the pipeline';
|
||||
ER_DATAPIPE_MATRIX_AFTER_MODEL =
|
||||
'Матричный шаг не может идти после модели!!Matrix step cannot appear after the model';
|
||||
ER_DATAPIPE_UNKNOWN_STEP =
|
||||
'Неизвестный тип шага конвейера!!Unknown pipeline step type';
|
||||
ER_TO_MATRIX_NO_COLUMNS =
|
||||
'ToMatrix: не указаны столбцы!!ToMatrix: no columns specified';
|
||||
ER_TO_VECTOR_NON_NUMERIC =
|
||||
'ToVector: столбец "{0}" содержит нечисловые или NA значения!!' +
|
||||
'ToVector: column "{0}" contains non-numeric or NA values';
|
||||
ER_FITTRANSFORM_WITH_MODEL =
|
||||
'FitTransform недоступен, если конвейер содержит модель!!FitTransform is not available when the pipeline contains a model';
|
||||
ER_PROBA_NOT_SUPPORTED =
|
||||
'Модель не поддерживает предсказание вероятностей!!Model does not support probability prediction';
|
||||
ER_TARGET_EMPTY =
|
||||
'Имя целевой переменной не задано!!Target column name is not specified';
|
||||
ER_FEATURES_EMPTY =
|
||||
'Список признаков пуст!!Feature list must not be empty';
|
||||
ER_DATAPIPE_TARGET_IN_FEATURES =
|
||||
'Целевая переменная не должна входить в список признаков!!Target column must not be included in feature list';
|
||||
ER_TO_MATRIX_NON_NUMERIC =
|
||||
'Столбец "{0}" содержит нечисловые или NA значения!!Column "{0}" contains non-numeric or NA values';
|
||||
ER_DATAPIPE_TARGET_NOT_FOUND =
|
||||
'Целевой столбец "{0}" не найден!!Target column "{0}" not found';
|
||||
ER_DATAPIPE_FEATURE_NOT_FOUND =
|
||||
'Столбец признака "{0}" не найден!!Feature column "{0}" not found';
|
||||
|
||||
function ToMatrix(Self: DataFrame; colNames: array of string): Matrix; extensionmethod;
|
||||
begin
|
||||
var df := Self;
|
||||
var n := df.RowCount;
|
||||
var p := colNames.Length;
|
||||
|
||||
if p = 0 then
|
||||
ArgumentError(ER_TO_MATRIX_NO_COLUMNS);
|
||||
|
||||
Result := new Matrix(n, p);
|
||||
|
||||
for var j := 0 to p - 1 do
|
||||
begin
|
||||
var col := df[colNames[j]];
|
||||
|
||||
for var i := 0 to n - 1 do
|
||||
begin
|
||||
var value: real;
|
||||
|
||||
if not col.TryGetNumericValue(i, value) then
|
||||
ArgumentError(ER_TO_MATRIX_NON_NUMERIC, colNames[j]);
|
||||
|
||||
Result[i,j] := value;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ToVector(Self: DataFrame; colName: string): Vector; extensionmethod;
|
||||
begin
|
||||
var df := Self;
|
||||
var n := df.RowCount;
|
||||
Result := new Vector(n);
|
||||
|
||||
var col := df[colName];
|
||||
|
||||
for var i := 0 to n - 1 do
|
||||
begin
|
||||
var value: real;
|
||||
|
||||
if not col.TryGetNumericValue(i, value) then
|
||||
ArgumentError(ER_TO_VECTOR_NON_NUMERIC, colName);
|
||||
|
||||
Result[i] := value;
|
||||
end;
|
||||
end;
|
||||
|
||||
//-----------------------------
|
||||
// DataPipeline
|
||||
//-----------------------------
|
||||
|
||||
constructor DataPipeline.Create;
|
||||
begin
|
||||
fDataSteps := new List<IPreprocessor>;
|
||||
fMatrixSteps := new List<ITransformer>;
|
||||
fModel := nil;
|
||||
fTarget := '';
|
||||
fFeatures := nil;
|
||||
fFitted := false;
|
||||
end;
|
||||
|
||||
function DataPipeline.Add(step: IPipelineStep): DataPipeline;
|
||||
begin
|
||||
if step = nil then
|
||||
ArgumentError(ER_PIPELINE_STEP_NULL);
|
||||
|
||||
if fFitted then
|
||||
Error(ER_PIPELINE_MODIFY_AFTER_FIT);
|
||||
|
||||
if step is IDataStep then
|
||||
begin
|
||||
if (fMatrixSteps.Count > 0) or (fModel <> nil) then
|
||||
ArgumentError(ER_DATAPIPE_DF_AFTER_MATRIX);
|
||||
|
||||
fDataSteps.Add(step as IPreprocessor);
|
||||
exit(Self);
|
||||
end;
|
||||
|
||||
if step is IMatrixStep then
|
||||
begin
|
||||
if step is IModel then
|
||||
begin
|
||||
if fModel <> nil then
|
||||
ArgumentError(ER_PIPELINE_MULTIPLE_MODELS);
|
||||
|
||||
fModel := step as IModel;
|
||||
exit(Self);
|
||||
end;
|
||||
|
||||
if fModel <> nil then
|
||||
ArgumentError(ER_DATAPIPE_MATRIX_AFTER_MODEL);
|
||||
|
||||
fMatrixSteps.Add(step as ITransformer);
|
||||
exit(Self);
|
||||
end;
|
||||
|
||||
ArgumentError(ER_DATAPIPE_UNKNOWN_STEP);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
class function DataPipeline.Build(target: string;
|
||||
features: array of string; params steps: array of IPipelineStep): DataPipeline;
|
||||
begin
|
||||
var p := new DataPipeline;
|
||||
p.fTarget := target;
|
||||
p.fFeatures := features;
|
||||
|
||||
for var i := 0 to High(steps) do
|
||||
p.Add(steps[i]);
|
||||
|
||||
Result := p;
|
||||
end;
|
||||
|
||||
function DataPipeline.Fit(df: DataFrame): DataPipeline;
|
||||
begin
|
||||
var current := df;
|
||||
|
||||
// 1) DataFrame слой (с сохранением fitted-объектов)
|
||||
for var i := 0 to fDataSteps.Count - 1 do
|
||||
begin
|
||||
fDataSteps[i] := fDataSteps[i].Fit(current);
|
||||
current := fDataSteps[i].Transform(current);
|
||||
end;
|
||||
|
||||
// DF-only режим
|
||||
if fModel = nil then
|
||||
begin
|
||||
fFitted := true;
|
||||
exit(Self);
|
||||
end;
|
||||
|
||||
// 2) Проверка схемы
|
||||
ValidateSchema(current);
|
||||
|
||||
// 3) Split
|
||||
var X := current.ToMatrix(fFeatures);
|
||||
var y := current.ToVector(fTarget);
|
||||
|
||||
// 4) Matrix слой (с сохранением fitted-объектов)
|
||||
for var i := 0 to fMatrixSteps.Count - 1 do
|
||||
begin
|
||||
var t := fMatrixSteps[i];
|
||||
|
||||
if t is ISupervisedTransformer (var sup) then
|
||||
fMatrixSteps[i] := sup.Fit(X, y)
|
||||
else
|
||||
fMatrixSteps[i] := t.Fit(X);
|
||||
|
||||
X := fMatrixSteps[i].Transform(X);
|
||||
end;
|
||||
|
||||
// 5) Модель
|
||||
fModel.Fit(X, y);
|
||||
|
||||
fFitted := true;
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
function DataPipeline.Transform(df: DataFrame): DataFrame;
|
||||
begin
|
||||
if not fFitted then
|
||||
NotFittedError(ER_FIT_NOT_CALLED);
|
||||
|
||||
var current := df;
|
||||
foreach var s in fDataSteps do
|
||||
current := s.Transform(current);
|
||||
|
||||
Result := current;
|
||||
end;
|
||||
|
||||
function DataPipeline.FitTransform(df: DataFrame): DataFrame;
|
||||
begin
|
||||
if fModel <> nil then
|
||||
ArgumentError(ER_FITTRANSFORM_WITH_MODEL);
|
||||
|
||||
var current := df;
|
||||
|
||||
for var i := 0 to fDataSteps.Count - 1 do
|
||||
begin
|
||||
fDataSteps[i] := fDataSteps[i].Fit(current);
|
||||
current := fDataSteps[i].Transform(current);
|
||||
end;
|
||||
|
||||
fFitted := true;
|
||||
Result := current;
|
||||
end;
|
||||
|
||||
function DataPipeline.Predict(df: DataFrame): Vector;
|
||||
begin
|
||||
if not fFitted then
|
||||
NotFittedError(ER_FIT_NOT_CALLED);
|
||||
|
||||
if fModel = nil then
|
||||
ArgumentError(ER_MODEL_NULL);
|
||||
|
||||
var current := Transform(df);
|
||||
var X := current.ToMatrix(fFeatures);
|
||||
|
||||
foreach var t in fMatrixSteps do
|
||||
X := t.Transform(X);
|
||||
|
||||
Result := fModel.Predict(X);
|
||||
end;
|
||||
|
||||
function DataPipeline.PredictProba(df: DataFrame): Matrix;
|
||||
begin
|
||||
if not fFitted then
|
||||
NotFittedError(ER_FIT_NOT_CALLED);
|
||||
|
||||
if not (fModel is IProbabilisticClassifier) then
|
||||
Error(ER_PROBA_NOT_SUPPORTED);
|
||||
|
||||
var current := Transform(df);
|
||||
var X := current.ToMatrix(fFeatures);
|
||||
|
||||
foreach var t in fMatrixSteps do
|
||||
X := t.Transform(X);
|
||||
|
||||
Result := (fModel as IProbabilisticClassifier).PredictProba(X);
|
||||
end;
|
||||
|
||||
function DataPipeline.GetClasses: array of real;
|
||||
begin
|
||||
if not (fModel is IProbabilisticClassifier) then
|
||||
ArgumentError(ER_PROBA_NOT_SUPPORTED);
|
||||
|
||||
Result := (fModel as IProbabilisticClassifier).GetClasses;
|
||||
end;
|
||||
|
||||
procedure DataPipeline.ValidateSchema(df: DataFrame);
|
||||
begin
|
||||
if fTarget = '' then
|
||||
ArgumentError(ER_TARGET_EMPTY);
|
||||
|
||||
if (fFeatures = nil) or (Length(fFeatures) = 0) then
|
||||
ArgumentError(ER_FEATURES_EMPTY);
|
||||
|
||||
for var i := 0 to High(fFeatures) do
|
||||
if fFeatures[i] = fTarget then
|
||||
ArgumentError(ER_DATAPIPE_TARGET_IN_FEATURES);
|
||||
|
||||
if not df.Schema.HasColumn(fTarget) then
|
||||
ArgumentError(ER_DATAPIPE_TARGET_NOT_FOUND, fTarget);
|
||||
|
||||
for var i := 0 to High(fFeatures) do
|
||||
if not df.Schema.HasColumn(fFeatures[i]) then
|
||||
ArgumentError(ER_DATAPIPE_FEATURE_NOT_FOUND, fFeatures[i]);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
end.
|
||||
|
|
@ -22,11 +22,12 @@ interface
|
|||
|
||||
uses DataFrameABC;
|
||||
uses System;
|
||||
uses MLCoreABC;
|
||||
|
||||
type
|
||||
/// Базовый интерфейс шагов подготовки данных.
|
||||
/// Определяет семантику операций Fit и Transform
|
||||
IPreprocessor = interface
|
||||
IPreprocessor = interface(IDataStep)
|
||||
/// Анализирует DataFrame и и сохраняет параметры шага
|
||||
function Fit(df: DataFrame): IPreprocessor;
|
||||
/// Применяет сохранённые параметры к DataFrame.
|
||||
|
|
@ -36,50 +37,6 @@ type
|
|||
function FitTransform(df: DataFrame): DataFrame;
|
||||
end;
|
||||
|
||||
/// Приводит числовые столбцы к нулевому среднему и единичному стандартному отклонению.
|
||||
/// При Fit вычисляет среднее значение и стандартное отклонение столбцов.
|
||||
/// Применяет преобразование: x' = (x - mean) / std.
|
||||
/// Пропущенные значения (NA) сохраняются.
|
||||
DataStandardScaler = class(IPreprocessor)
|
||||
private
|
||||
cols: array of string;
|
||||
means: array of real;
|
||||
stds: array of real;
|
||||
fitted: boolean;
|
||||
public
|
||||
/// Создаёт StandardScaler для указанных числовых столбцов.
|
||||
constructor Create(params columns: array of string);
|
||||
/// Вычисляет среднее значение и стандартное отклонение для каждого столбца.
|
||||
function Fit(df: DataFrame): IPreprocessor;
|
||||
/// Возвращает DataFrame со стандартизованными числовыми столбцами.
|
||||
function Transform(df: DataFrame): DataFrame;
|
||||
/// Последовательно выполняет Fit и Transform.
|
||||
function FitTransform(df: DataFrame): DataFrame;
|
||||
end;
|
||||
|
||||
/// Приводит числовые столбцы к заданному диапазону значений
|
||||
/// При Fit вычисляет минимальное и максимальное значения столбцов
|
||||
/// Применяет преобразование: x' = (x - min) / (max - min)
|
||||
/// Пропущенные значения (NA) сохраняются
|
||||
DataMinMaxScaler = class(IPreprocessor)
|
||||
private
|
||||
cols: array of string;
|
||||
mins: array of real;
|
||||
maxs: array of real;
|
||||
fitted: boolean;
|
||||
public
|
||||
/// Создаёт MinMaxScaler для указанных столбцов
|
||||
constructor Create(params columns: array of string);
|
||||
|
||||
/// Вычисляет минимальные и максимальные значения столбцов
|
||||
function Fit(df: DataFrame): IPreprocessor;
|
||||
/// Применяет масштабирование к DataFrame
|
||||
/// Возвращает новый DataFrame
|
||||
function Transform(df: DataFrame): DataFrame;
|
||||
/// Последовательно выполняет Fit и Transform.
|
||||
function FitTransform(df: DataFrame): DataFrame;
|
||||
end;
|
||||
|
||||
/// Кодирует строковый категориальный столбец в числовые значения
|
||||
/// Категории фиксируются при Fit
|
||||
/// Работает только со строковыми столбцами
|
||||
|
|
@ -150,26 +107,51 @@ type
|
|||
/// Выполняет Fit и Transform последовательно
|
||||
function FitTransform(df: DataFrame): DataFrame;
|
||||
end;
|
||||
|
||||
|
||||
type
|
||||
/// DataPipeline (конвейер) шагов подготовки данных.
|
||||
/// Выполняет шаги последовательно с семантикой Fit / Transform.
|
||||
DataPipeline = class
|
||||
{/// Приводит числовые столбцы к нулевому среднему и единичному стандартному отклонению.
|
||||
/// При Fit вычисляет среднее значение и стандартное отклонение столбцов.
|
||||
/// Применяет преобразование: x' = (x - mean) / std.
|
||||
/// Пропущенные значения (NA) сохраняются.
|
||||
DataStandardScaler = class(IPreprocessor)
|
||||
private
|
||||
steps: List<IPreprocessor>;
|
||||
cols: array of string;
|
||||
means: array of real;
|
||||
stds: array of real;
|
||||
fitted: boolean;
|
||||
public
|
||||
constructor;
|
||||
/// Добавляет шаг в конец pipeline
|
||||
function Add(p: IPreprocessor): DataPipeline;
|
||||
/// Обучает все шаги pipeline на DataFrame
|
||||
function Fit(df: DataFrame): DataPipeline;
|
||||
/// Применяет обученный pipeline к DataFrame
|
||||
/// Создаёт StandardScaler для указанных числовых столбцов.
|
||||
constructor Create(params columns: array of string);
|
||||
/// Вычисляет среднее значение и стандартное отклонение для каждого столбца.
|
||||
function Fit(df: DataFrame): IPreprocessor;
|
||||
/// Возвращает DataFrame со стандартизованными числовыми столбцами.
|
||||
function Transform(df: DataFrame): DataFrame;
|
||||
/// Выполняет Fit и Transform последовательно
|
||||
/// Последовательно выполняет Fit и Transform.
|
||||
function FitTransform(df: DataFrame): DataFrame;
|
||||
end;
|
||||
|
||||
/// Приводит числовые столбцы к заданному диапазону значений
|
||||
/// При Fit вычисляет минимальное и максимальное значения столбцов
|
||||
/// Применяет преобразование: x' = (x - min) / (max - min)
|
||||
/// Пропущенные значения (NA) сохраняются
|
||||
DataMinMaxScaler = class(IPreprocessor)
|
||||
private
|
||||
cols: array of string;
|
||||
mins: array of real;
|
||||
maxs: array of real;
|
||||
fitted: boolean;
|
||||
public
|
||||
/// Создаёт MinMaxScaler для указанных столбцов
|
||||
constructor Create(params columns: array of string);
|
||||
|
||||
/// Вычисляет минимальные и максимальные значения столбцов
|
||||
function Fit(df: DataFrame): IPreprocessor;
|
||||
/// Применяет масштабирование к DataFrame
|
||||
/// Возвращает новый DataFrame
|
||||
function Transform(df: DataFrame): DataFrame;
|
||||
/// Последовательно выполняет Fit и Transform.
|
||||
function FitTransform(df: DataFrame): DataFrame;
|
||||
end;}
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
|
|
@ -233,14 +215,12 @@ const
|
|||
ER_IMPUTER_CONSTANT_TYPE_MISMATCH =
|
||||
'Imputer(constant): несоответствие типа значения для столбца "{0}"!!' +
|
||||
'Imputer(constant): value type mismatch for column "{0}"';
|
||||
ER_PIPELINE_MODIFY_AFTER_FIT =
|
||||
'Нельзя добавлять шаг после вызова Fit()!!Cannot add step after Fit';
|
||||
|
||||
|
||||
//-----------------------------
|
||||
// StandardScaler
|
||||
//-----------------------------
|
||||
|
||||
constructor DataStandardScaler.Create(params columns: array of string);
|
||||
{constructor DataStandardScaler.Create(params columns: array of string);
|
||||
begin
|
||||
if (columns = nil) or (columns.Length = 0) then
|
||||
ArgumentError(ER_SCALER_NO_COLUMNS);
|
||||
|
|
@ -420,7 +400,7 @@ function DataMinMaxScaler.FitTransform(df: DataFrame): DataFrame;
|
|||
begin
|
||||
Fit(df);
|
||||
Result := Transform(df);
|
||||
end;
|
||||
end;}
|
||||
|
||||
//-----------------------------
|
||||
// LabelEncoder
|
||||
|
|
@ -733,56 +713,5 @@ begin
|
|||
Result := Transform(df);
|
||||
end;
|
||||
|
||||
//-----------------------------
|
||||
// Pipeline
|
||||
//-----------------------------
|
||||
|
||||
constructor DataPipeline.Create;
|
||||
begin
|
||||
steps := new List<IPreprocessor>;
|
||||
fitted := false;
|
||||
end;
|
||||
|
||||
function DataPipeline.Add(p: IPreprocessor): DataPipeline;
|
||||
begin
|
||||
if fitted then
|
||||
Error(ER_PIPELINE_MODIFY_AFTER_FIT);
|
||||
|
||||
steps.Add(p);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
function DataPipeline.Fit(df: DataFrame): DataPipeline;
|
||||
begin
|
||||
var current := df;
|
||||
|
||||
for var i := 0 to steps.Count - 1 do
|
||||
begin
|
||||
steps[i] := steps[i].Fit(current);
|
||||
current := steps[i].Transform(current);
|
||||
end;
|
||||
|
||||
fitted := true;
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
function DataPipeline.Transform(df: DataFrame): DataFrame;
|
||||
begin
|
||||
if not fitted then
|
||||
NotFittedError(ER_FIT_NOT_CALLED);
|
||||
|
||||
var current := df;
|
||||
foreach var step in steps do
|
||||
current := step.Transform(current);
|
||||
|
||||
Result := current;
|
||||
end;
|
||||
|
||||
function DataPipeline.FitTransform(df: DataFrame): DataFrame;
|
||||
begin
|
||||
Fit(df);
|
||||
Result := Transform(df);
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
Loading…
Reference in a new issue