From 1eb7f69f7b6f3353889f8f18e68cc24fb6c3221b Mon Sep 17 00:00:00 2001 From: Mikhalkovich Stanislav Date: Tue, 26 May 2026 21:39:12 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=B4=D0=B3=D0=BE=D1=82=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D0=BA=20=D1=80=D0=B5=D1=84=D0=B0=D0=BA?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=D1=83=20MLCore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Configuration/GlobalAssemblyInfo.cs | 2 +- Configuration/Version.defs | 4 +- Release/pabcversion.txt | 2 +- ReleaseGenerators/PascalABCNET_version.nsh | 2 +- VisualPascalABCNET/IB/Debugger/Debugger.cs | 2 +- bin/Lib/MLModelsABC.pas | 30 ++++ bin/Lib/MLPipelineABC.pas | 169 +++++++++++++++++---- 7 files changed, 176 insertions(+), 35 deletions(-) diff --git a/Configuration/GlobalAssemblyInfo.cs b/Configuration/GlobalAssemblyInfo.cs index 887c1b2c9..7a1e19b0e 100644 --- a/Configuration/GlobalAssemblyInfo.cs +++ b/Configuration/GlobalAssemblyInfo.cs @@ -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 = "3826"; + public const string Revision = "3827"; public const string MainVersion = Major + "." + Minor; public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision; diff --git a/Configuration/Version.defs b/Configuration/Version.defs index 036bd09e2..c0fed99e6 100644 --- a/Configuration/Version.defs +++ b/Configuration/Version.defs @@ -1,4 +1,4 @@ -%COREVERSION%=1 -%REVISION%=3826 %MINOR%=11 +%REVISION%=3827 +%COREVERSION%=1 %MAJOR%=3 diff --git a/Release/pabcversion.txt b/Release/pabcversion.txt index 49cd70e01..8ce6d24db 100644 --- a/Release/pabcversion.txt +++ b/Release/pabcversion.txt @@ -1 +1 @@ -3.11.1.3826 +3.11.1.3827 diff --git a/ReleaseGenerators/PascalABCNET_version.nsh b/ReleaseGenerators/PascalABCNET_version.nsh index c5b5936e7..5086d9cae 100644 --- a/ReleaseGenerators/PascalABCNET_version.nsh +++ b/ReleaseGenerators/PascalABCNET_version.nsh @@ -1 +1 @@ -!define VERSION '3.11.1.3826' +!define VERSION '3.11.1.3827' diff --git a/VisualPascalABCNET/IB/Debugger/Debugger.cs b/VisualPascalABCNET/IB/Debugger/Debugger.cs index 57effe020..fdfd03537 100644 --- a/VisualPascalABCNET/IB/Debugger/Debugger.cs +++ b/VisualPascalABCNET/IB/Debugger/Debugger.cs @@ -718,7 +718,7 @@ namespace VisualPascalABC private NamedValue GetNullBasedArray(Value val) { IList flds = val.Type.GetFields(); - if (flds.Count != 3) return null; + //if (flds.Count != 3) return null; foreach (FieldInfo fi in flds) if (fi.Name == "NullBasedArray") return fi.GetValue(val); return null; diff --git a/bin/Lib/MLModelsABC.pas b/bin/Lib/MLModelsABC.pas index f62b127b3..0187088e5 100644 --- a/bin/Lib/MLModelsABC.pas +++ b/bin/Lib/MLModelsABC.pas @@ -39,6 +39,9 @@ uses MLCoreABC; uses LinearAlgebraML; type + MatrixPipeline = class; + UMatrixPipeline = class; + {$region Activations} /// Активационные функции для моделей Activations = static class @@ -1789,6 +1792,15 @@ type /// Последний шаг обязан быть моделью (IModel). /// Возвращает сконструированный конвейер. static function Build(params steps: array of IPipelineStep): MatrixPipeline; + + /// Строит supervised-конвейер для задачи классификации. + static function BuildClassification(params steps: array of IPipelineStep): MatrixPipeline; + + /// Строит supervised-конвейер для задачи регрессии. + static function BuildRegression(params steps: array of IPipelineStep): MatrixPipeline; + + /// Строит unsupervised-конвейер для задачи кластеризации. + static function BuildClustering(params steps: array of IPipelineStep): UMatrixPipeline; /// Устанавливает или заменяет модель. function SetModel(m: ISupervisedModel): MatrixPipeline; @@ -8479,6 +8491,24 @@ begin Result := pipe; end; +class function MatrixPipeline.BuildClassification(params steps: array of IPipelineStep): MatrixPipeline; +begin + var stepsCopy := Copy(steps); + Result := Build(stepsCopy); +end; + +class function MatrixPipeline.BuildRegression(params steps: array of IPipelineStep): MatrixPipeline; +begin + var stepsCopy := Copy(steps); + Result := Build(stepsCopy); +end; + +class function MatrixPipeline.BuildClustering(params steps: array of IPipelineStep): UMatrixPipeline; +begin + var stepsCopy := Copy(steps); + Result := UMatrixPipeline.Build(stepsCopy); +end; + function MatrixPipeline.Add(t: ITransformer): MatrixPipeline; begin if t = nil then diff --git a/bin/Lib/MLPipelineABC.pas b/bin/Lib/MLPipelineABC.pas index a01201591..bcddbb59a 100644 --- a/bin/Lib/MLPipelineABC.pas +++ b/bin/Lib/MLPipelineABC.pas @@ -11,6 +11,12 @@ type TaskKind = (tkRegression, tkClassification); type + DataPipeline = class; + UDataPipeline = class; + ClassificationDataPipeline = class; + RegressionDataPipeline = class; + ClusteringDataPipeline = class; + PipelineBase = abstract class protected fDataSteps: List; @@ -47,7 +53,7 @@ type /// Признак того, что был вызван Fit. property IsFitted: boolean read fFitted; end; - + /// DataPipeline — конвейер подготовки данных и обучения модели с учителем на DataFrame. /// /// Поддерживает два уровня шагов: @@ -65,12 +71,11 @@ type /// • target — целевая переменная. /// DataPipeline = class(PipelineBase, IModel) - private + protected fModel: ISupervisedModel; fTask: TaskKind; fTarget: string; - protected procedure ValidateSchema(df: DataFrame); override; public /// Создаёт пустой конвейер @@ -97,6 +102,26 @@ type params steps: array of IPipelineStep ): DataPipeline; + /// Строит supervised-конвейер для задачи классификации. + static function BuildClassification( + target: string; + features: array of string; + params steps: array of IPipelineStep + ): ClassificationDataPipeline; + + /// Строит supervised-конвейер для задачи регрессии. + static function BuildRegression( + target: string; + features: array of string; + params steps: array of IPipelineStep + ): RegressionDataPipeline; + + /// Строит unsupervised-конвейер для задачи кластеризации. + static function BuildClustering( + features: array of string; + params steps: array of IPipelineStep + ): ClusteringDataPipeline; + /// Строит только preprocessing-часть supervised-конвейера без модели. /// Модель затем можно присоединить методом WithModel static function BuildPreprocessing( @@ -159,6 +184,18 @@ type function Clone: IModel; end; + + /// Конвейер DataFrame-предобработки и классификации. + /// Специализированный тип будет постепенно получать + /// собственный контракт Predict/PredictLabels. + ClassificationDataPipeline = class(DataPipeline) + end; + + /// Конвейер DataFrame-предобработки и регрессии. + /// Специализированный тип будет постепенно получать + /// собственный контракт Predict. + RegressionDataPipeline = class(DataPipeline) + end; /// UDataPipeline — конвейер подготовки данных и обучения модели без учителя на DataFrame. /// @@ -176,12 +213,11 @@ type /// • features — признаки (целевая переменная отсутствует). /// UDataPipeline = class(PipelineBase, IModel) - private + protected fModel: IUnsupervisedModel; procedure ValidateNumericFeatures(df: DataFrame); function TransformToMatrix(df: DataFrame): Matrix; - protected procedure ValidateSchema(df: DataFrame); override; public /// Создаёт пустой конвейер @@ -248,7 +284,14 @@ type function Clone: IModel; function Name: string := Self.GetType.Name; + end; + + /// Конвейер DataFrame-предобработки и кластеризации. + /// Специализированный тип будет постепенно получать + /// собственный контракт Predict. + ClusteringDataPipeline = class(UDataPipeline) + end; implementation @@ -598,19 +641,17 @@ begin if f = target then ArgumentError(ER_DATAPIPE_TARGET_IN_FEATURES, target); - if (steps = nil) or (Length(steps) = 0) then - ArgumentError(ER_PIPELINE_NO_STEPS); + if steps <> nil then + for var i := 0 to High(steps) do + begin + var step := steps[i]; - for var i := 0 to High(steps) do - begin - var step := steps[i]; + if step = nil then + ArgumentError(ER_PIPELINE_STEP_NULL, i); - if step = nil then - ArgumentError(ER_PIPELINE_STEP_NULL, i); - - if step is ISupervisedModel then - ArgumentError(ER_PIPELINE_INVALID_STEP_ORDER); - end; + if step is ISupervisedModel then + ArgumentError(ER_PIPELINE_INVALID_STEP_ORDER); + end; var p := new DataPipeline; p.fTarget := target; @@ -674,6 +715,77 @@ begin .WithModel(last as ISupervisedModel); end; +class function DataPipeline.BuildClassification( + target: string; + features: array of string; + params steps: array of IPipelineStep +): ClassificationDataPipeline; +begin + ValidateFeatureList(features); + + if (target = nil) or (target = '') then + ArgumentError(ER_TARGET_EMPTY); + + foreach var f in features do + if f = target then + ArgumentError(ER_DATAPIPE_TARGET_IN_FEATURES, target); + + var p := new ClassificationDataPipeline; + p.fTarget := target; + p.fFeatures := Copy(features); + p.fTask := TaskKind.tkClassification; + + if steps <> nil then + for var i := 0 to High(steps) do + p.Add(steps[i]); + + Result := p; +end; + +class function DataPipeline.BuildRegression( + target: string; + features: array of string; + params steps: array of IPipelineStep +): RegressionDataPipeline; +begin + ValidateFeatureList(features); + + if (target = nil) or (target = '') then + ArgumentError(ER_TARGET_EMPTY); + + foreach var f in features do + if f = target then + ArgumentError(ER_DATAPIPE_TARGET_IN_FEATURES, target); + + var p := new RegressionDataPipeline; + p.fTarget := target; + p.fFeatures := Copy(features); + p.fTask := TaskKind.tkRegression; + + if steps <> nil then + for var i := 0 to High(steps) do + p.Add(steps[i]); + + Result := p; +end; + +class function DataPipeline.BuildClustering( + features: array of string; + params steps: array of IPipelineStep +): ClusteringDataPipeline; +begin + ValidateFeatureList(features); + + var p := new ClusteringDataPipeline; + p.fFeatures := Copy(features); + + if steps <> nil then + for var i := 0 to High(steps) do + p.Add(steps[i]); + + Result := p; +end; + function DataPipeline.WithModel(model: ISupervisedModel): DataPipeline; begin if model = nil then @@ -1005,25 +1117,24 @@ class function UDataPipeline.BuildPreprocessing(features: array of string; begin ValidateFeatureList(features); - if (steps = nil) or (Length(steps) = 0) then - ArgumentError(ER_PIPELINE_NO_STEPS); + if steps <> nil then + for var i := 0 to High(steps) do + begin + var step := steps[i]; - for var i := 0 to High(steps) do - begin - var step := steps[i]; + if step = nil then + ArgumentError(ER_PIPELINE_STEP_NULL, i); - if step = nil then - ArgumentError(ER_PIPELINE_STEP_NULL, i); - - if step is IUnsupervisedModel then - ArgumentError(ER_PIPELINE_INVALID_STEP_ORDER); - end; + if step is IUnsupervisedModel then + ArgumentError(ER_PIPELINE_INVALID_STEP_ORDER); + end; var p := new UDataPipeline; p.fFeatures := Copy(features); - for var i := 0 to High(steps) do - p.Add(steps[i]); + if steps <> nil then + for var i := 0 to High(steps) do + p.Add(steps[i]); Result := p; end;