Подготовка к рефакторингу MLCore

This commit is contained in:
Mikhalkovich Stanislav 2026-05-26 21:39:12 +03:00
parent 84a039e631
commit 1eb7f69f7b
7 changed files with 176 additions and 35 deletions

View file

@ -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;

View file

@ -1,4 +1,4 @@
%COREVERSION%=1
%REVISION%=3826
%MINOR%=11
%REVISION%=3827
%COREVERSION%=1
%MAJOR%=3

View file

@ -1 +1 @@
3.11.1.3826
3.11.1.3827

View file

@ -1 +1 @@
!define VERSION '3.11.1.3826'
!define VERSION '3.11.1.3827'

View file

@ -718,7 +718,7 @@ namespace VisualPascalABC
private NamedValue GetNullBasedArray(Value val)
{
IList<FieldInfo> 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;

View file

@ -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

View file

@ -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<IPreprocessor>;
@ -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;