Много добавок в ML
This commit is contained in:
parent
d4e56ead6c
commit
95a1e58952
|
|
@ -5,7 +5,6 @@ interface
|
||||||
type
|
type
|
||||||
Vector = class
|
Vector = class
|
||||||
private
|
private
|
||||||
|
|
||||||
static procedure CheckSameLength(const a, b: Vector);
|
static procedure CheckSameLength(const a, b: Vector);
|
||||||
static procedure CheckNonEmpty(const v: Vector);
|
static procedure CheckNonEmpty(const v: Vector);
|
||||||
procedure SetData(i: integer; value: real) := data[i] := value;
|
procedure SetData(i: integer; value: real) := data[i] := value;
|
||||||
|
|
@ -93,7 +92,25 @@ type
|
||||||
function ColumnMins: Vector;
|
function ColumnMins: Vector;
|
||||||
function ColumnMaxs: Vector;
|
function ColumnMaxs: Vector;
|
||||||
function RowMins: Vector;
|
function RowMins: Vector;
|
||||||
function RowMaxs: Vector;
|
function RowMaxs: Vector;
|
||||||
|
|
||||||
|
function RowSum(i: integer): real;
|
||||||
|
function RowMean(i: integer): real;
|
||||||
|
function RowVariance(i: integer): real;
|
||||||
|
function RowStd(i: integer): real;
|
||||||
|
function RowMin(i: integer): real;
|
||||||
|
function RowMax(i: integer): real;
|
||||||
|
function RowArgMin(i: integer): integer;
|
||||||
|
function RowArgMax(i: integer): integer;
|
||||||
|
|
||||||
|
function ColumnSum(j: integer): real;
|
||||||
|
function ColumnMean(j: integer): real;
|
||||||
|
function ColumnVariance(j: integer): real;
|
||||||
|
function ColumnStd(j: integer): real;
|
||||||
|
function ColumnMin(j: integer): real;
|
||||||
|
function ColumnMax(j: integer): real;
|
||||||
|
function ColumnArgMin(j: integer): integer;
|
||||||
|
function ColumnArgMax(j: integer): integer;
|
||||||
|
|
||||||
function FrobeniusNorm: real;
|
function FrobeniusNorm: real;
|
||||||
procedure AddScaledIdentity(lambda: real);
|
procedure AddScaledIdentity(lambda: real);
|
||||||
|
|
@ -561,6 +578,154 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function Matrix.RowArgMin(i: integer): integer;
|
||||||
|
begin
|
||||||
|
var minVal := data[i,0];
|
||||||
|
var arg := 0;
|
||||||
|
|
||||||
|
for var j := 1 to ColCount - 1 do
|
||||||
|
if data[i,j] < minVal then
|
||||||
|
begin
|
||||||
|
minVal := data[i,j];
|
||||||
|
arg := j;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := arg;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Matrix.RowMin(i: integer): real;
|
||||||
|
begin
|
||||||
|
Result := data[i, RowArgMin(i)];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Matrix.RowArgMax(i: integer): integer;
|
||||||
|
begin
|
||||||
|
var maxVal := data[i,0];
|
||||||
|
var arg := 0;
|
||||||
|
|
||||||
|
for var j := 1 to ColCount - 1 do
|
||||||
|
if data[i,j] > maxVal then
|
||||||
|
begin
|
||||||
|
maxVal := data[i,j];
|
||||||
|
arg := j;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := arg;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Matrix.RowMax(i: integer): real;
|
||||||
|
begin
|
||||||
|
Result := data[i, RowArgMax(i)];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Matrix.RowSum(i: integer): real;
|
||||||
|
begin
|
||||||
|
var sum := 0.0;
|
||||||
|
|
||||||
|
for var j := 0 to ColCount - 1 do
|
||||||
|
sum += data[i,j];
|
||||||
|
|
||||||
|
Result := sum;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Matrix.RowMean(i: integer): real;
|
||||||
|
begin
|
||||||
|
Result := RowSum(i) / ColCount;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Matrix.RowVariance(i: integer): real;
|
||||||
|
begin
|
||||||
|
var mean := RowMean(i);
|
||||||
|
var sum := 0.0;
|
||||||
|
|
||||||
|
for var j := 0 to ColCount - 1 do
|
||||||
|
begin
|
||||||
|
var d := data[i,j] - mean;
|
||||||
|
sum += d * d;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := sum / ColCount;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Matrix.RowStd(i: integer): real;
|
||||||
|
begin
|
||||||
|
Result := Sqrt(RowVariance(i));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Matrix.ColumnArgMin(j: integer): integer;
|
||||||
|
begin
|
||||||
|
var minVal := data[0,j];
|
||||||
|
var arg := 0;
|
||||||
|
|
||||||
|
for var i := 1 to RowCount - 1 do
|
||||||
|
if data[i,j] < minVal then
|
||||||
|
begin
|
||||||
|
minVal := data[i,j];
|
||||||
|
arg := i;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := arg;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Matrix.ColumnMin(j: integer): real;
|
||||||
|
begin
|
||||||
|
Result := data[ColumnArgMin(j), j];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Matrix.ColumnArgMax(j: integer): integer;
|
||||||
|
begin
|
||||||
|
var maxVal := data[0,j];
|
||||||
|
var arg := 0;
|
||||||
|
|
||||||
|
for var i := 1 to RowCount - 1 do
|
||||||
|
if data[i,j] > maxVal then
|
||||||
|
begin
|
||||||
|
maxVal := data[i,j];
|
||||||
|
arg := i;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := arg;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Matrix.ColumnMax(j: integer): real;
|
||||||
|
begin
|
||||||
|
Result := data[ColumnArgMax(j), j];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Matrix.ColumnSum(j: integer): real;
|
||||||
|
begin
|
||||||
|
var sum := 0.0;
|
||||||
|
|
||||||
|
for var i := 0 to RowCount - 1 do
|
||||||
|
sum += data[i,j];
|
||||||
|
|
||||||
|
Result := sum;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Matrix.ColumnMean(j: integer): real;
|
||||||
|
begin
|
||||||
|
Result := ColumnSum(j) / RowCount;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Matrix.ColumnVariance(j: integer): real;
|
||||||
|
begin
|
||||||
|
var mean := ColumnMean(j);
|
||||||
|
var sum := 0.0;
|
||||||
|
|
||||||
|
for var i := 0 to RowCount - 1 do
|
||||||
|
begin
|
||||||
|
var d := data[i,j] - mean;
|
||||||
|
sum += d * d;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := sum / RowCount;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Matrix.ColumnStd(j: integer): real;
|
||||||
|
begin
|
||||||
|
Result := Sqrt(ColumnVariance(j));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function Matrix.FrobeniusNorm: real;
|
function Matrix.FrobeniusNorm: real;
|
||||||
begin
|
begin
|
||||||
|
|
|
||||||
|
|
@ -24,13 +24,20 @@ type
|
||||||
CsvLoader = DataFrameABC.CsvLoader;
|
CsvLoader = DataFrameABC.CsvLoader;
|
||||||
|
|
||||||
StandardScaler = MLModelsABC.StandardScaler;
|
StandardScaler = MLModelsABC.StandardScaler;
|
||||||
|
PCATransformer = MLModelsABC.PCATransformer;
|
||||||
|
MinMaxScaler = MLModelsABC.MinMaxScaler;
|
||||||
|
VarianceThreshold = MLModelsABC.VarianceThreshold;
|
||||||
|
SelectKBest = MLModelsABC.SelectKBest;
|
||||||
|
FeatureScore = MLModelsABC.FeatureScore;
|
||||||
|
|
||||||
Activations = MLModelsABC.Activations;
|
Activations = MLModelsABC.Activations;
|
||||||
Pipeline = MLModelsABC.Pipeline;
|
Pipeline = MLModelsABC.Pipeline;
|
||||||
|
|
||||||
LinearRegression = MLModelsABC.LinearRegression;
|
LinearRegression = MLModelsABC.LinearRegression;
|
||||||
LogisticRegression = MLModelsABC.LogisticRegression;
|
LogisticRegression = MLModelsABC.LogisticRegression;
|
||||||
RidgeRegression = MLModelsABC.RidgeRegression;
|
RidgeRegression = MLModelsABC.RidgeRegression;
|
||||||
ElasticNet = ElasticNet;
|
ElasticNet = MLModelsABC.ElasticNet;
|
||||||
|
MulticlassLogisticRegression = MLModelsABC.MulticlassLogisticRegression;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,17 @@ type
|
||||||
function Transform(X: Matrix): Matrix;
|
function Transform(X: Matrix): Matrix;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
/// Интерфейс преобразования признаков с учётом целевой переменной.
|
||||||
|
/// Используется для методов отбора признаков и других процедур,
|
||||||
|
/// в которых при обучении требуется вектор целевых значений.
|
||||||
|
ISupervisedTransformer = interface(ITransformer)
|
||||||
|
/// Обучает преобразование на данных с использованием
|
||||||
|
/// как признаков X, так и целевой переменной y.
|
||||||
|
/// Запоминает необходимые параметры,
|
||||||
|
/// которые будут использоваться при Transform.
|
||||||
|
function Fit(X: Matrix; y: Vector): ISupervisedTransformer;
|
||||||
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
@ -234,34 +234,80 @@ type
|
||||||
/// Показывает, была ли модель обучена.
|
/// Показывает, была ли модель обучена.
|
||||||
/// После вызова Fit значение становится true.
|
/// После вызова Fit значение становится true.
|
||||||
property IsFitted: boolean read fFitted;
|
property IsFitted: boolean read fFitted;
|
||||||
|
end;
|
||||||
|
|
||||||
|
/// Многоклассовая логистическая регрессия (Softmax).
|
||||||
|
/// Предсказывает вероятности принадлежности к каждому классу
|
||||||
|
/// на основе линейной комбинации признаков и softmax-функции.
|
||||||
|
/// Использует кросс-энтропийную функцию потерь.
|
||||||
|
/// Поддерживает L2-регуляризацию.
|
||||||
|
MulticlassLogisticRegression = class(IProbabilisticClassifier)
|
||||||
|
private
|
||||||
|
fW: Matrix; // p x k
|
||||||
|
fIntercept: Vector; // k
|
||||||
|
fLambda: real;
|
||||||
|
fLearningRate: real;
|
||||||
|
fEpochs: integer;
|
||||||
|
fFitted: boolean;
|
||||||
|
fClassCount: integer;
|
||||||
|
public
|
||||||
|
/// lambda — коэффициент L2-регуляризации.
|
||||||
|
/// lr — шаг градиентного спуска.
|
||||||
|
/// epochs — число итераций обучения.
|
||||||
|
constructor Create(lambda: real := 0.0; lr: real := 0.1; epochs: integer := 1000);
|
||||||
|
|
||||||
|
function Fit(X: Matrix; y: Vector): IModel;
|
||||||
|
|
||||||
|
function PredictProba(X: Matrix): Vector;
|
||||||
|
|
||||||
|
/// Возвращает матрицу вероятностей (m x k).
|
||||||
|
function PredictProbaMatrix(X: Matrix): Matrix;
|
||||||
|
|
||||||
|
/// Возвращает вектор предсказанных классов.
|
||||||
|
function Predict(X: Matrix): Vector;
|
||||||
|
|
||||||
|
property IsFitted: boolean read fFitted;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
{$endregion Models}
|
{$endregion Models}
|
||||||
|
|
||||||
{$region Pipeline}
|
{$region Pipeline}
|
||||||
/// Конвейер машинного обучения (Pipeline).
|
/// Последовательный конвейер машинного обучения.
|
||||||
/// Объединяет несколько шагов подготовки данных и модель
|
/// Гарантирует строгий порядок выполнения шагов:
|
||||||
/// в единую последовательность обработки.
|
/// [преобразователи] → [модель].
|
||||||
/// Сначала данные проходят через все преобразования,
|
///
|
||||||
/// затем итоговые признаки передаются в модель.
|
/// Поддерживает:
|
||||||
/// Обеспечивает единый интерфейс Fit / Predict.
|
/// - преобразователи без учёта целевой переменной;
|
||||||
|
/// - преобразователи с учётом целевой переменной;
|
||||||
|
/// - одну финальную модель.
|
||||||
|
///
|
||||||
|
/// Обеспечивает единый интерфейс Fit / Predict
|
||||||
|
/// и воспроизводимость полного процесса обучения.
|
||||||
Pipeline = class(IModel)
|
Pipeline = class(IModel)
|
||||||
private
|
private
|
||||||
fTransformers: List<ITransformer>;
|
fTransformers: List<ITransformer>;
|
||||||
fModel: IModel;
|
fModel: IModel;
|
||||||
fFitted: boolean;
|
fFitted: boolean;
|
||||||
public
|
public
|
||||||
/// Создаёт пайплайн (конвейер машинного обучения) для заданной модели.
|
/// Создаёт конвейер машинного обучения для заданной модели.
|
||||||
/// model — финальная модель (регрессор или классификатор),
|
/// model — модель, которая будет обучена
|
||||||
/// которая будет обучаться после всех преобразований.
|
/// после последовательного применения всех преобразователей.
|
||||||
constructor Create(model: IModel);
|
constructor Create(model: IModel);
|
||||||
|
|
||||||
|
/// Создаёт пустой пайплайн (конвейер машинного обучения).
|
||||||
|
/// Модель должна быть установлена через SetModel.
|
||||||
|
constructor Create;
|
||||||
|
|
||||||
/// Строит пайплайн (конвейер машинного обучения).
|
/// Строит конвейер машинного обучения.
|
||||||
/// model — финальная модель, которая будет обучаться.
|
/// model — модель, обучаемая после применения всех преобразователей.
|
||||||
/// transformers — последовательность преобразований признаков,
|
/// transformers — последовательность преобразователей признаков,
|
||||||
/// применяемых к данным перед обучением модели.
|
/// применяемых к данным перед обучением модели.
|
||||||
/// Возвращает настроенный конвейер.
|
/// Возвращает сконструированный конвейер.
|
||||||
static function Build(model: IModel; params transformers: array of ITransformer): Pipeline;
|
static function Build(model: IModel; params transformers: array of ITransformer): Pipeline;
|
||||||
|
|
||||||
|
/// Устанавливает или заменяет модель.
|
||||||
|
function SetModel(m: IModel): Pipeline;
|
||||||
|
|
||||||
/// Добавляет преобразование в конец пайплайна
|
/// Добавляет преобразование в конец пайплайна
|
||||||
function Add(t: ITransformer): Pipeline;
|
function Add(t: ITransformer): Pipeline;
|
||||||
|
|
@ -342,6 +388,163 @@ type
|
||||||
/// Признак того, что преобразование обучено.
|
/// Признак того, что преобразование обучено.
|
||||||
property IsFitted: boolean read fFitted;
|
property IsFitted: boolean read fFitted;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
/// Трансформер главных компонент (PCA).
|
||||||
|
/// Выполняет уменьшение размерности путём проекции данных
|
||||||
|
/// на первые k главных компонент.
|
||||||
|
/// На этапе Fit вычисляет главные компоненты ковариационной матрицы.
|
||||||
|
/// На этапе Transform проецирует данные:
|
||||||
|
/// Z = (X - μ) · W
|
||||||
|
PCATransformer = class(ITransformer)
|
||||||
|
private
|
||||||
|
fK: integer;
|
||||||
|
fComponents: Matrix; // W
|
||||||
|
fMean: Vector; // μ
|
||||||
|
fFitted: boolean;
|
||||||
|
public
|
||||||
|
/// Создаёт PCA-трансформер.
|
||||||
|
/// k — число главных компонент (k > 0).
|
||||||
|
constructor Create(k: integer);
|
||||||
|
|
||||||
|
/// Обучает трансформер на матрице признаков X.
|
||||||
|
/// X — матрица m × n.
|
||||||
|
function Fit(X: Matrix): ITransformer;
|
||||||
|
|
||||||
|
/// Преобразует матрицу X в пространство главных компонент.
|
||||||
|
/// Возвращает матрицу m × k.
|
||||||
|
function Transform(X: Matrix): Matrix;
|
||||||
|
|
||||||
|
property Components: Matrix read fComponents;
|
||||||
|
property Mean: Vector read fMean;
|
||||||
|
property IsFitted: boolean read fFitted;
|
||||||
|
end;
|
||||||
|
|
||||||
|
/// Трансформер, удаляющий признаки с малой дисперсией.
|
||||||
|
/// Удаляет столбцы X_j, для которых Var(X_j) < threshold.
|
||||||
|
/// Не использует целевую переменную (unsupervised).
|
||||||
|
VarianceThreshold = class(ITransformer)
|
||||||
|
private
|
||||||
|
fThreshold: real;
|
||||||
|
fSelected: array of integer;
|
||||||
|
fFitted: boolean;
|
||||||
|
|
||||||
|
public
|
||||||
|
/// threshold — минимальная допустимая дисперсия (>= 0).
|
||||||
|
constructor Create(threshold: real := 0.0);
|
||||||
|
|
||||||
|
/// Вычисляет дисперсии признаков и запоминает индексы
|
||||||
|
/// признаков, удовлетворяющих порогу.
|
||||||
|
function Fit(X: Matrix): ITransformer;
|
||||||
|
|
||||||
|
/// Возвращает матрицу, содержащую только отобранные признаки.
|
||||||
|
function Transform(X: Matrix): Matrix;
|
||||||
|
|
||||||
|
/// Индексы выбранных признаков.
|
||||||
|
property SelectedFeatures: array of integer read fSelected;
|
||||||
|
|
||||||
|
/// Показывает, был ли выполнен Fit.
|
||||||
|
property IsFitted: boolean read fFitted;
|
||||||
|
end;
|
||||||
|
|
||||||
|
/// Тип критерия оценки признаков для SelectKBest.
|
||||||
|
/// Определяет способ вычисления значимости признака
|
||||||
|
/// относительно целевой переменной.
|
||||||
|
FeatureScore = (
|
||||||
|
/// Абсолютное значение коэффициента корреляции Пирсона
|
||||||
|
/// между признаком и целевой переменной.
|
||||||
|
/// Подходит для задач регрессии и бинарной классификации при линейной зависимости.
|
||||||
|
Correlation,
|
||||||
|
|
||||||
|
/// F-статистика линейной регрессии (FRegression).
|
||||||
|
/// Оценивает статистическую значимость линейной связи
|
||||||
|
/// между признаком и целевой переменной.
|
||||||
|
/// Основан на коэффициенте детерминации (R²) и F-статистике.
|
||||||
|
/// Более строгий критерий, чем простая корреляция.
|
||||||
|
FRegression,
|
||||||
|
|
||||||
|
/// ANOVA F-критерий.
|
||||||
|
/// Используется в задачах классификации.
|
||||||
|
/// Оценивает различие средних значений признака между различными классами.
|
||||||
|
AnovaF,
|
||||||
|
|
||||||
|
/// Хи-квадрат (Chi-Square) критерий независимости.
|
||||||
|
/// Используется в задачах классификации.
|
||||||
|
/// Оценивает зависимость между признаком и классом
|
||||||
|
/// на основе различия наблюдаемых и ожидаемых частот.
|
||||||
|
/// Предполагает, что значения признака неотрицательны.
|
||||||
|
/// Часто применяется для текстовых данных и частотных представлений (bag-of-words).
|
||||||
|
ChiSquare
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Преобразователь с учётом целевой переменной
|
||||||
|
/// Для каждого признака вычисляет score(X_j, y)
|
||||||
|
/// и оставляет k признаков с наибольшим значением score.
|
||||||
|
/// Может использовать встроенные критерии
|
||||||
|
/// или пользовательскую функцию оценки.
|
||||||
|
SelectKBest = class(ITransformer)
|
||||||
|
private
|
||||||
|
fK: integer;
|
||||||
|
fScoreType: FeatureScore;
|
||||||
|
fScoreFunc: (Vector, Vector) -> real;
|
||||||
|
fSelected: array of integer;
|
||||||
|
fFitted: boolean;
|
||||||
|
|
||||||
|
function ComputeScore(feature: Vector; y: Vector): real;
|
||||||
|
function ComputeCorrelation(x: Vector; y: Vector): real;
|
||||||
|
function ComputeFRegression(feature: Vector; y: Vector): real;
|
||||||
|
function ComputeAnovaF(feature: Vector; y: Vector): real;
|
||||||
|
function ComputeChiSquare(feature: Vector; y: Vector): real;
|
||||||
|
public
|
||||||
|
/// Создаёт трансформер с использованием встроенного критерия.
|
||||||
|
/// k — число отбираемых признаков.
|
||||||
|
/// score — тип критерия (например, Correlation).
|
||||||
|
constructor Create(k: integer; score: FeatureScore := FeatureScore.Correlation);
|
||||||
|
|
||||||
|
/// Создаёт трансформер с пользовательской функцией оценки.
|
||||||
|
/// scoreFunc — функция (feature, y) → real.
|
||||||
|
constructor Create(k: integer; scoreFunc: (Vector, Vector) -> real);
|
||||||
|
|
||||||
|
/// Выбрасывает исключение
|
||||||
|
/// Данный преобразователь требует целевую переменную.
|
||||||
|
/// Используйте перегруженный метод Fit(X, y).
|
||||||
|
function Fit(X: Matrix): ITransformer;
|
||||||
|
|
||||||
|
/// Вычисляет оценки признаков и выбирает k лучших.
|
||||||
|
function Fit(X: Matrix; y: Vector): ITransformer;
|
||||||
|
|
||||||
|
/// Возвращает матрицу, содержащую только выбранные признаки.
|
||||||
|
function Transform(X: Matrix): Matrix;
|
||||||
|
|
||||||
|
/// Индексы выбранных признаков.
|
||||||
|
property SelectedFeatures: array of integer read fSelected;
|
||||||
|
|
||||||
|
/// Показывает, был ли выполнен Fit.
|
||||||
|
property IsFitted: boolean read fFitted;
|
||||||
|
end;
|
||||||
|
|
||||||
|
/// Тип нормы для нормализации строк.
|
||||||
|
NormType = (L1, L2);
|
||||||
|
|
||||||
|
/// Преобразователь нормализации по строкам.
|
||||||
|
/// Для каждой строки X_i выполняет нормализацию:
|
||||||
|
/// L1: x := x / ||x||₁
|
||||||
|
/// L2: x := x / ||x||₂
|
||||||
|
/// Используется перед моделями, чувствительными к масштабу
|
||||||
|
/// (LogisticRegression, SVM, L1-регуляризация).
|
||||||
|
Normalizer = class(ITransformer)
|
||||||
|
private
|
||||||
|
fNormType: NormType;
|
||||||
|
fFitted: boolean;
|
||||||
|
public
|
||||||
|
constructor Create(norm: NormType := NormType.L2);
|
||||||
|
|
||||||
|
function Fit(X: Matrix): ITransformer;
|
||||||
|
function Transform(X: Matrix): Matrix;
|
||||||
|
|
||||||
|
property IsFitted: boolean read fFitted;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{$endregion Transformers}
|
{$endregion Transformers}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -650,54 +853,209 @@ begin
|
||||||
Result[i] += fIntercept;
|
Result[i] += fIntercept;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
constructor MulticlassLogisticRegression.Create(lambda: real; lr: real; epochs: integer);
|
||||||
|
begin
|
||||||
|
fLambda := lambda;
|
||||||
|
fLearningRate := lr;
|
||||||
|
fEpochs := epochs;
|
||||||
|
fFitted := false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function MulticlassLogisticRegression.Fit(X: Matrix; y: Vector): IModel;
|
||||||
|
begin
|
||||||
|
var m := X.RowCount;
|
||||||
|
var p := X.ColCount;
|
||||||
|
|
||||||
|
// число классов
|
||||||
|
fClassCount := Round(y.Max) + 1;
|
||||||
|
|
||||||
|
// инициализация параметров
|
||||||
|
fW := new Matrix(p, fClassCount);
|
||||||
|
fIntercept := new Vector(fClassCount);
|
||||||
|
|
||||||
|
// one-hot матрица
|
||||||
|
var YoneHot := new Matrix(m, fClassCount);
|
||||||
|
for var i := 0 to m - 1 do
|
||||||
|
YoneHot[i, Round(y[i])] := 1.0;
|
||||||
|
|
||||||
|
for var epoch := 1 to fEpochs do
|
||||||
|
begin
|
||||||
|
// Z = XW + b
|
||||||
|
var Z := X * fW;
|
||||||
|
|
||||||
|
for var i := 0 to m - 1 do
|
||||||
|
for var k := 0 to fClassCount - 1 do
|
||||||
|
Z[i,k] += fIntercept[k];
|
||||||
|
|
||||||
|
// softmax
|
||||||
|
for var i := 0 to m - 1 do
|
||||||
|
begin
|
||||||
|
var maxVal := Z.RowMax(i);
|
||||||
|
|
||||||
|
var sumExp := 0.0;
|
||||||
|
|
||||||
|
for var k := 0 to fClassCount - 1 do
|
||||||
|
begin
|
||||||
|
Z[i,k] := Exp(Z[i,k] - maxVal);
|
||||||
|
sumExp += Z[i,k];
|
||||||
|
end;
|
||||||
|
|
||||||
|
for var k := 0 to fClassCount - 1 do
|
||||||
|
Z[i,k] /= sumExp;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var PP := Z;
|
||||||
|
|
||||||
|
// градиенты
|
||||||
|
var diff := PP - YoneHot; // m x k
|
||||||
|
var gradW := X.Transpose * diff; // p x k
|
||||||
|
|
||||||
|
// L2 регуляризация (только веса)
|
||||||
|
if fLambda <> 0 then
|
||||||
|
gradW += fLambda * fW;
|
||||||
|
|
||||||
|
// обновление
|
||||||
|
fW -= fLearningRate * gradW;
|
||||||
|
|
||||||
|
// градиент по intercept
|
||||||
|
var gradB := diff.ColumnSums;
|
||||||
|
fIntercept -= fLearningRate * gradB;
|
||||||
|
end;
|
||||||
|
|
||||||
|
fFitted := true;
|
||||||
|
Result := Self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function MulticlassLogisticRegression.PredictProba(X: Matrix): Vector;
|
||||||
|
begin
|
||||||
|
var P := PredictProbaMatrix(X);
|
||||||
|
|
||||||
|
var m := P.RowCount;
|
||||||
|
Result := new Vector(m);
|
||||||
|
|
||||||
|
for var i := 0 to m - 1 do
|
||||||
|
begin
|
||||||
|
var k := P.RowArgMax(i);
|
||||||
|
Result[i] := P[i, k];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function MulticlassLogisticRegression.PredictProbaMatrix(X: Matrix): Matrix;
|
||||||
|
begin
|
||||||
|
if not fFitted then
|
||||||
|
raise new Exception('Model not fitted');
|
||||||
|
|
||||||
|
var m := X.RowCount;
|
||||||
|
|
||||||
|
var Z := X * fW;
|
||||||
|
|
||||||
|
for var i := 0 to m - 1 do
|
||||||
|
for var k := 0 to fClassCount - 1 do
|
||||||
|
Z[i,k] += fIntercept[k];
|
||||||
|
|
||||||
|
for var i := 0 to m - 1 do
|
||||||
|
begin
|
||||||
|
var maxVal := Z.RowMax(i);
|
||||||
|
|
||||||
|
var sumExp := 0.0;
|
||||||
|
|
||||||
|
for var k := 0 to fClassCount - 1 do
|
||||||
|
begin
|
||||||
|
Z[i,k] := Exp(Z[i,k] - maxVal);
|
||||||
|
sumExp += Z[i,k];
|
||||||
|
end;
|
||||||
|
|
||||||
|
for var k := 0 to fClassCount - 1 do
|
||||||
|
Z[i,k] /= sumExp;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := Z;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function MulticlassLogisticRegression.Predict(X: Matrix): Vector;
|
||||||
|
begin
|
||||||
|
var P := PredictProbaMatrix(X);
|
||||||
|
|
||||||
|
var m := P.RowCount;
|
||||||
|
Result := new Vector(m);
|
||||||
|
|
||||||
|
for var i := 0 to m - 1 do
|
||||||
|
Result[i] := P.RowArgMax(i);
|
||||||
|
end;
|
||||||
|
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
// Pipeline
|
// Pipeline
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
|
|
||||||
|
|
||||||
|
constructor Pipeline.Create;
|
||||||
|
begin
|
||||||
|
fTransformers := new List<ITransformer>;
|
||||||
|
fModel := nil;
|
||||||
|
fFitted := false;
|
||||||
|
end;
|
||||||
|
|
||||||
constructor Pipeline.Create(model: IModel);
|
constructor Pipeline.Create(model: IModel);
|
||||||
begin
|
begin
|
||||||
|
Create;
|
||||||
|
if model = nil then
|
||||||
|
raise new ArgumentException('Model cannot be nil');
|
||||||
fModel := model;
|
fModel := model;
|
||||||
fTransformers := new List<ITransformer>;
|
|
||||||
fFitted := false;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
static function Pipeline.Build(model: IModel; transformers: array of ITransformer): Pipeline;
|
static function Pipeline.Build(model: IModel; transformers: array of ITransformer): Pipeline;
|
||||||
begin
|
begin
|
||||||
var pipe := new Pipeline(model);
|
Result := new Pipeline(model);
|
||||||
|
|
||||||
foreach var t in transformers do
|
foreach var t in transformers do
|
||||||
pipe.Add(t);
|
Result.Add(t);
|
||||||
|
|
||||||
Result := pipe;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function Pipeline.Add(t: ITransformer): Pipeline;
|
function Pipeline.Add(t: ITransformer): Pipeline;
|
||||||
begin
|
begin
|
||||||
|
if t = nil then
|
||||||
|
raise new ArgumentException('Transformer cannot be nil');
|
||||||
|
|
||||||
fTransformers.Add(t);
|
fTransformers.Add(t);
|
||||||
Result := self;
|
Result := Self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Pipeline.SetModel(m: IModel): Pipeline;
|
||||||
|
begin
|
||||||
|
if m = nil then
|
||||||
|
raise new ArgumentException('Model cannot be nil');
|
||||||
|
|
||||||
|
fModel := m;
|
||||||
|
Result := Self;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function Pipeline.Fit(X: Matrix; y: Vector): IModel;
|
function Pipeline.Fit(X: Matrix; y: Vector): IModel;
|
||||||
begin
|
begin
|
||||||
var Xcur := X;
|
if fModel = nil then
|
||||||
|
raise new Exception('Model is not set');
|
||||||
|
|
||||||
|
var Xt := X;
|
||||||
|
|
||||||
foreach var t in fTransformers do
|
foreach var t in fTransformers do
|
||||||
begin
|
begin
|
||||||
t.Fit(Xcur);
|
if t is ISupervisedTransformer (var sup) then
|
||||||
Xcur := t.Transform(Xcur);
|
sup.Fit(Xt, y)
|
||||||
|
else t.Fit(Xt);
|
||||||
|
|
||||||
|
Xt := t.Transform(Xt);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
fModel.Fit(Xcur, y);
|
fModel.Fit(Xt, y);
|
||||||
fFitted := true;
|
|
||||||
|
|
||||||
Result := self;
|
fFitted := true;
|
||||||
|
Result := Self;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function Pipeline.Transform(X: Matrix): Matrix;
|
function Pipeline.Transform(X: Matrix): Matrix;
|
||||||
begin
|
begin
|
||||||
if not fFitted then
|
if not fFitted then
|
||||||
raise new Exception('Pipeline is not fitted');
|
raise new Exception('Pipeline not fitted');
|
||||||
|
|
||||||
var Xt := X;
|
var Xt := X;
|
||||||
|
|
||||||
|
|
@ -712,28 +1070,21 @@ begin
|
||||||
if not fFitted then
|
if not fFitted then
|
||||||
raise new Exception('Pipeline not fitted');
|
raise new Exception('Pipeline not fitted');
|
||||||
|
|
||||||
var Xcur := X;
|
var Xt := Transform(X);
|
||||||
|
Result := fModel.Predict(Xt);
|
||||||
foreach var t in fTransformers do
|
|
||||||
Xcur := t.Transform(Xcur);
|
|
||||||
|
|
||||||
Result := fModel.Predict(Xcur);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function Pipeline.PredictProba(X: Matrix): Vector;
|
function Pipeline.PredictProba(X: Matrix): Vector;
|
||||||
begin
|
begin
|
||||||
if not fFitted then
|
if not fFitted then
|
||||||
raise new Exception('Pipeline is not fitted');
|
raise new Exception('Pipeline not fitted');
|
||||||
|
|
||||||
var Xt := X;
|
if not (fModel is IProbabilisticClassifier) then
|
||||||
|
raise new Exception('Model does not support probability prediction');
|
||||||
|
|
||||||
foreach var t in fTransformers do
|
var Xt := Transform(X);
|
||||||
Xt := t.Transform(Xt);
|
|
||||||
|
|
||||||
if fModel is IProbabilisticClassifier then
|
Result := (fModel as IProbabilisticClassifier).PredictProba(Xt);
|
||||||
exit(IProbabilisticClassifier(fModel).PredictProba(Xt));
|
|
||||||
|
|
||||||
raise new Exception('Model does not support probability prediction');
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
|
|
@ -823,6 +1174,376 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
//-----------------------------
|
||||||
|
// PCATransformer
|
||||||
|
//-----------------------------
|
||||||
|
|
||||||
|
constructor PCATransformer.Create(k: integer);
|
||||||
|
begin
|
||||||
|
if k <= 0 then
|
||||||
|
raise new ArgumentException('k must be > 0');
|
||||||
|
|
||||||
|
fK := k;
|
||||||
|
fFitted := false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function PCATransformer.Fit(X: Matrix): ITransformer;
|
||||||
|
begin
|
||||||
|
if fK > X.ColCount then
|
||||||
|
raise new ArgumentException('k exceeds feature count');
|
||||||
|
|
||||||
|
fMean := X.ColumnMeans;
|
||||||
|
|
||||||
|
var Xc := X.Clone;
|
||||||
|
|
||||||
|
for var j := 0 to X.ColCount - 1 do
|
||||||
|
for var i := 0 to X.RowCount - 1 do
|
||||||
|
Xc[i,j] -= fMean[j];
|
||||||
|
|
||||||
|
var (W, xxx) := Xc.PCA(fK);
|
||||||
|
|
||||||
|
fComponents := W;
|
||||||
|
fFitted := true;
|
||||||
|
|
||||||
|
Result := Self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function PCATransformer.Transform(X: Matrix): Matrix;
|
||||||
|
begin
|
||||||
|
if not fFitted then
|
||||||
|
raise new InvalidOperationException('PCA not fitted');
|
||||||
|
|
||||||
|
var Xc := X.Clone;
|
||||||
|
|
||||||
|
for var j := 0 to X.ColCount - 1 do
|
||||||
|
for var i := 0 to X.RowCount - 1 do
|
||||||
|
Xc[i,j] -= fMean[j];
|
||||||
|
|
||||||
|
Result := Xc * fComponents;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//-----------------------------
|
||||||
|
// VarianceThreshold
|
||||||
|
//-----------------------------
|
||||||
|
|
||||||
|
constructor VarianceThreshold.Create(threshold: real);
|
||||||
|
begin
|
||||||
|
if threshold < 0 then
|
||||||
|
raise new ArgumentException('threshold must be >= 0');
|
||||||
|
|
||||||
|
fThreshold := threshold;
|
||||||
|
fFitted := false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function VarianceThreshold.Fit(X: Matrix): ITransformer;
|
||||||
|
begin
|
||||||
|
var vars := X.ColumnVariances;
|
||||||
|
|
||||||
|
var tmp := new List<integer>;
|
||||||
|
|
||||||
|
for var j := 0 to X.ColCount - 1 do
|
||||||
|
if vars[j] >= fThreshold then
|
||||||
|
tmp.Add(j);
|
||||||
|
|
||||||
|
fSelected := tmp.ToArray;
|
||||||
|
fFitted := true;
|
||||||
|
|
||||||
|
Result := Self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function VarianceThreshold.Transform(X: Matrix): Matrix;
|
||||||
|
begin
|
||||||
|
if not fFitted then
|
||||||
|
raise new InvalidOperationException('VarianceThreshold not fitted');
|
||||||
|
|
||||||
|
var n := X.RowCount;
|
||||||
|
var k := fSelected.Length;
|
||||||
|
|
||||||
|
var R := new Matrix(n, k);
|
||||||
|
|
||||||
|
for var i := 0 to n - 1 do
|
||||||
|
for var c := 0 to k - 1 do
|
||||||
|
R[i,c] := X[i, fSelected[c]];
|
||||||
|
|
||||||
|
Result := R;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//-----------------------------
|
||||||
|
// SelectKBest
|
||||||
|
//-----------------------------
|
||||||
|
|
||||||
|
constructor SelectKBest.Create(k: integer; score: FeatureScore);
|
||||||
|
begin
|
||||||
|
if k <= 0 then
|
||||||
|
raise new ArgumentException('k must be > 0');
|
||||||
|
|
||||||
|
fK := k;
|
||||||
|
fScoreType := score;
|
||||||
|
fScoreFunc := nil;
|
||||||
|
fFitted := false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor SelectKBest.Create(k: integer; scoreFunc: (Vector, Vector) -> real);
|
||||||
|
begin
|
||||||
|
if k <= 0 then
|
||||||
|
raise new ArgumentException('k must be > 0');
|
||||||
|
|
||||||
|
fK := k;
|
||||||
|
fScoreFunc := scoreFunc;
|
||||||
|
fFitted := false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function SelectKBest.ComputeCorrelation(x: Vector; y: Vector): real;
|
||||||
|
begin
|
||||||
|
var mx := x.Mean;
|
||||||
|
var my := y.Mean;
|
||||||
|
|
||||||
|
var num := 0.0;
|
||||||
|
var dx := 0.0;
|
||||||
|
var dy := 0.0;
|
||||||
|
|
||||||
|
for var i := 0 to x.Length - 1 do
|
||||||
|
begin
|
||||||
|
var vx := x[i] - mx;
|
||||||
|
var vy := y[i] - my;
|
||||||
|
|
||||||
|
num += vx * vy;
|
||||||
|
dx += vx * vx;
|
||||||
|
dy += vy * vy;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (dx = 0) or (dy = 0) then
|
||||||
|
exit(0.0);
|
||||||
|
|
||||||
|
Result := Abs(num / Sqrt(dx * dy));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function SelectKBest.ComputeFRegression(feature: Vector; y: Vector): real;
|
||||||
|
begin
|
||||||
|
var r := ComputeCorrelation(feature, y);
|
||||||
|
var n := feature.Length;
|
||||||
|
|
||||||
|
if Abs(r) >= 1 then
|
||||||
|
exit(1e308);
|
||||||
|
|
||||||
|
Result := (r*r / (1 - r*r)) * (n - 2);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function SelectKBest.ComputeAnovaF(feature: Vector; y: Vector): real;
|
||||||
|
begin
|
||||||
|
var mean0 := 0.0;
|
||||||
|
var mean1 := 0.0;
|
||||||
|
var n0 := 0;
|
||||||
|
var n1 := 0;
|
||||||
|
|
||||||
|
for var i := 0 to y.Length - 1 do
|
||||||
|
if y[i] = 0 then
|
||||||
|
begin
|
||||||
|
mean0 += feature[i];
|
||||||
|
n0 += 1;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
mean1 += feature[i];
|
||||||
|
n1 += 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (n0 = 0) or (n1 = 0) then
|
||||||
|
exit(0.0);
|
||||||
|
|
||||||
|
mean0 /= n0;
|
||||||
|
mean1 /= n1;
|
||||||
|
|
||||||
|
var grandMean := feature.Mean;
|
||||||
|
|
||||||
|
var ssBetween :=
|
||||||
|
n0 * Sqr(mean0 - grandMean) +
|
||||||
|
n1 * Sqr(mean1 - grandMean);
|
||||||
|
|
||||||
|
var ssWithin := 0.0;
|
||||||
|
|
||||||
|
for var i := 0 to y.Length - 1 do
|
||||||
|
if y[i] = 0 then
|
||||||
|
ssWithin += Sqr(feature[i] - mean0)
|
||||||
|
else
|
||||||
|
ssWithin += Sqr(feature[i] - mean1);
|
||||||
|
|
||||||
|
if ssWithin = 0 then
|
||||||
|
exit(1e308);
|
||||||
|
|
||||||
|
Result := (ssBetween) / (ssWithin / (y.Length - 2));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function SelectKBest.ComputeChiSquare(feature: Vector; y: Vector): real;
|
||||||
|
begin
|
||||||
|
var n := y.Length;
|
||||||
|
|
||||||
|
var sum0 := 0.0;
|
||||||
|
var sum1 := 0.0;
|
||||||
|
var total := 0.0;
|
||||||
|
var n0 := 0;
|
||||||
|
var n1 := 0;
|
||||||
|
|
||||||
|
for var i := 0 to n - 1 do
|
||||||
|
begin
|
||||||
|
var v := feature[i];
|
||||||
|
if v < 0 then
|
||||||
|
raise new ArgumentException('ChiSquare requires non-negative features');
|
||||||
|
|
||||||
|
total += v;
|
||||||
|
|
||||||
|
if y[i] = 0 then
|
||||||
|
begin
|
||||||
|
sum0 += v;
|
||||||
|
n0 += 1;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
sum1 += v;
|
||||||
|
n1 += 1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (n0 = 0) or (n1 = 0) or (total = 0) then
|
||||||
|
exit(0.0);
|
||||||
|
|
||||||
|
var expected0 := total * n0 / n;
|
||||||
|
var expected1 := total * n1 / n;
|
||||||
|
|
||||||
|
var chi := 0.0;
|
||||||
|
|
||||||
|
if expected0 > 0 then
|
||||||
|
chi += Sqr(sum0 - expected0) / expected0;
|
||||||
|
|
||||||
|
if expected1 > 0 then
|
||||||
|
chi += Sqr(sum1 - expected1) / expected1;
|
||||||
|
|
||||||
|
Result := chi;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function SelectKBest.ComputeScore(feature: Vector; y: Vector): real;
|
||||||
|
begin
|
||||||
|
case fScoreType of
|
||||||
|
FeatureScore.Correlation: Result := ComputeCorrelation(feature, y);
|
||||||
|
FeatureScore.FRegression: Result := ComputeFRegression(feature, y);
|
||||||
|
FeatureScore.AnovaF: Result := ComputeAnovaF(feature, y);
|
||||||
|
FeatureScore.ChiSquare: Result := ComputeChiSquare(feature, y);
|
||||||
|
else
|
||||||
|
raise new InvalidOperationException('Unknown FeatureScore type');
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function SelectKBest.Fit(X: Matrix; y: Vector): ITransformer;
|
||||||
|
begin
|
||||||
|
var p := X.ColCount;
|
||||||
|
|
||||||
|
var scores: array of (real, integer);
|
||||||
|
SetLength(scores, p);
|
||||||
|
|
||||||
|
for var j := 0 to p - 1 do
|
||||||
|
begin
|
||||||
|
var col := new Vector(X.RowCount);
|
||||||
|
for var i := 0 to X.RowCount - 1 do
|
||||||
|
col[i] := X[i,j];
|
||||||
|
|
||||||
|
var s :=
|
||||||
|
if fScoreFunc <> nil then
|
||||||
|
fScoreFunc(col, y)
|
||||||
|
else
|
||||||
|
ComputeCorrelation(col, y);
|
||||||
|
|
||||||
|
scores[j] := (s, j);
|
||||||
|
end;
|
||||||
|
|
||||||
|
scores := scores.OrderByDescending(t -> t.Item1).ToArray;
|
||||||
|
|
||||||
|
var k := Min(fK, p);
|
||||||
|
SetLength(fSelected, k);
|
||||||
|
|
||||||
|
for var i := 0 to k - 1 do
|
||||||
|
fSelected[i] := scores[i].Item2;
|
||||||
|
|
||||||
|
fFitted := true;
|
||||||
|
Result := Self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function SelectKBest.Fit(X: Matrix): ITransformer;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
raise new InvalidOperationException('Target variable is required');
|
||||||
|
end;
|
||||||
|
|
||||||
|
function SelectKBest.Transform(X: Matrix): Matrix;
|
||||||
|
begin
|
||||||
|
if not fFitted then
|
||||||
|
raise new InvalidOperationException('SelectKBest not fitted');
|
||||||
|
|
||||||
|
var n := X.RowCount;
|
||||||
|
var k := fSelected.Length;
|
||||||
|
|
||||||
|
var R := new Matrix(n, k);
|
||||||
|
|
||||||
|
for var i := 0 to n - 1 do
|
||||||
|
for var c := 0 to k - 1 do
|
||||||
|
R[i,c] := X[i, fSelected[c]];
|
||||||
|
|
||||||
|
Result := R;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//-----------------------------
|
||||||
|
// Normalizer
|
||||||
|
//-----------------------------
|
||||||
|
|
||||||
|
constructor Normalizer.Create(norm: NormType);
|
||||||
|
begin
|
||||||
|
fNormType := norm;
|
||||||
|
fFitted := false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Normalizer.Fit(X: Matrix): ITransformer;
|
||||||
|
begin
|
||||||
|
// Нормализация не требует обучения
|
||||||
|
fFitted := true;
|
||||||
|
Result := Self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Normalizer.Transform(X: Matrix): Matrix;
|
||||||
|
begin
|
||||||
|
if not fFitted then
|
||||||
|
raise new InvalidOperationException('Normalizer not fitted');
|
||||||
|
|
||||||
|
var n := X.RowCount;
|
||||||
|
var p := X.ColCount;
|
||||||
|
|
||||||
|
var R := new Matrix(n, p);
|
||||||
|
|
||||||
|
for var i := 0 to n - 1 do
|
||||||
|
begin
|
||||||
|
var norm := 0.0;
|
||||||
|
|
||||||
|
case fNormType of
|
||||||
|
NormType.L1:
|
||||||
|
for var j := 0 to p - 1 do
|
||||||
|
norm += Abs(X[i,j]);
|
||||||
|
|
||||||
|
NormType.L2:
|
||||||
|
for var j := 0 to p - 1 do
|
||||||
|
norm += Sqr(X[i,j]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if fNormType = NormType.L2 then
|
||||||
|
norm := Sqrt(norm);
|
||||||
|
|
||||||
|
if norm = 0 then
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for var j := 0 to p - 1 do
|
||||||
|
R[i,j] := X[i,j] / norm;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := R;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
Loading…
Reference in a new issue