ML - исправления очередного аудита
This commit is contained in:
parent
e338acb18b
commit
5c8f2b0caa
|
|
@ -15,7 +15,7 @@ internal static class RevisionClass
|
||||||
public const string Major = "3";
|
public const string Major = "3";
|
||||||
public const string Minor = "11";
|
public const string Minor = "11";
|
||||||
public const string Build = "1";
|
public const string Build = "1";
|
||||||
public const string Revision = "3790";
|
public const string Revision = "3793";
|
||||||
|
|
||||||
public const string MainVersion = Major + "." + Minor;
|
public const string MainVersion = Major + "." + Minor;
|
||||||
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
|
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
%COREVERSION%=1
|
|
||||||
%REVISION%=3790
|
|
||||||
%MINOR%=11
|
%MINOR%=11
|
||||||
|
%REVISION%=3793
|
||||||
|
%COREVERSION%=1
|
||||||
%MAJOR%=3
|
%MAJOR%=3
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
3.11.1.3790
|
3.11.1.3793
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
!define VERSION '3.11.1.3790'
|
!define VERSION '3.11.1.3793'
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ interface
|
||||||
|
|
||||||
uses DataFrameABCCore;
|
uses DataFrameABCCore;
|
||||||
|
|
||||||
const DataFrameVersion = '1.0';
|
const DataFrameVersion = '1.1';
|
||||||
|
|
||||||
// Реэкспортируем публичные типы для удобства
|
// Реэкспортируем публичные типы для удобства
|
||||||
type
|
type
|
||||||
|
|
@ -93,6 +93,9 @@ type
|
||||||
|
|
||||||
function GetColumnIndex(name: string): integer;
|
function GetColumnIndex(name: string): integer;
|
||||||
function GetColumn(name: string): Column;
|
function GetColumn(name: string): Column;
|
||||||
|
|
||||||
|
function CloneWithCopiedColumns: DataFrame;
|
||||||
|
static procedure EnsureValidArray(var valid: array of boolean; rowCount, filledCount: integer);
|
||||||
public
|
public
|
||||||
/// Создает пустой DataFrame
|
/// Создает пустой DataFrame
|
||||||
constructor Create;
|
constructor Create;
|
||||||
|
|
@ -2475,7 +2478,7 @@ begin
|
||||||
cnt += 1;
|
cnt += 1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if cnt = 0 then
|
if cnt <= 1 then
|
||||||
exit(0.0);
|
exit(0.0);
|
||||||
|
|
||||||
var mean := sum / cnt;
|
var mean := sum / cnt;
|
||||||
|
|
@ -2491,7 +2494,7 @@ begin
|
||||||
acc += d * d;
|
acc += d * d;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Result := acc / cnt;
|
Result := acc / (cnt - 1);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function DataFrame.Variance(colName: string): real
|
function DataFrame.Variance(colName: string): real
|
||||||
|
|
@ -3182,14 +3185,10 @@ begin
|
||||||
Result := columns[idx];
|
Result := columns[idx];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function DataFrame.WithColumnInt(name: string; f: DataFrameCursor -> integer): DataFrame;
|
function DataFrame.CloneWithCopiedColumns: DataFrame;
|
||||||
begin
|
begin
|
||||||
if fSchema.HasColumn(name) then
|
Result := new DataFrame;
|
||||||
ArgumentError(ER_COLUMN_ALREADY_EXISTS, name);
|
|
||||||
|
|
||||||
var res := new DataFrame;
|
|
||||||
|
|
||||||
// 1. копируем столбцы (без categorical!)
|
|
||||||
for var i := 0 to columns.Count - 1 do
|
for var i := 0 to columns.Count - 1 do
|
||||||
begin
|
begin
|
||||||
var col := columns[i];
|
var col := columns[i];
|
||||||
|
|
@ -3198,30 +3197,47 @@ begin
|
||||||
ctInt:
|
ctInt:
|
||||||
begin
|
begin
|
||||||
var c := IntColumn(col);
|
var c := IntColumn(col);
|
||||||
res.AddIntColumn(c.Info.Name, c.Data, c.IsValid);
|
Result.AddIntColumn(c.Info.Name, c.Data, c.IsValid);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
ctStr:
|
ctStr:
|
||||||
begin
|
begin
|
||||||
var c := StrColumn(col);
|
var c := StrColumn(col);
|
||||||
res.AddStrColumn(c.Info.Name, c.Data, c.IsValid);
|
Result.AddStrColumn(c.Info.Name, c.Data, c.IsValid);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
ctFloat:
|
ctFloat:
|
||||||
begin
|
begin
|
||||||
var c := FloatColumn(col);
|
var c := FloatColumn(col);
|
||||||
res.AddFloatColumn(c.Info.Name, c.Data, c.IsValid);
|
Result.AddFloatColumn(c.Info.Name, c.Data, c.IsValid);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
ctBool:
|
ctBool:
|
||||||
begin
|
begin
|
||||||
var c := BoolColumn(col);
|
var c := BoolColumn(col);
|
||||||
res.AddBoolColumn(c.Info.Name, c.Data, c.IsValid);
|
Result.AddBoolColumn(c.Info.Name, c.Data, c.IsValid);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
static procedure DataFrame.EnsureValidArray(var valid: array of boolean; rowCount, filledCount: integer);
|
||||||
|
begin
|
||||||
|
if valid = nil then
|
||||||
|
begin
|
||||||
|
valid := new boolean[rowCount];
|
||||||
|
for var j := 0 to filledCount - 1 do
|
||||||
|
valid[j] := true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DataFrame.WithColumnInt(name: string; f: DataFrameCursor -> integer): DataFrame;
|
||||||
|
begin
|
||||||
|
if fSchema.HasColumn(name) then
|
||||||
|
ArgumentError(ER_COLUMN_ALREADY_EXISTS, name);
|
||||||
|
|
||||||
|
var res := CloneWithCopiedColumns;
|
||||||
|
|
||||||
// 2. вычисляем новый столбец
|
|
||||||
var data := new integer[RowCount];
|
var data := new integer[RowCount];
|
||||||
var valid: array of boolean := nil;
|
var valid: array of boolean := nil;
|
||||||
|
|
||||||
|
|
@ -3236,14 +3252,7 @@ begin
|
||||||
on e: Exception do
|
on e: Exception do
|
||||||
begin
|
begin
|
||||||
data[i] := 0;
|
data[i] := 0;
|
||||||
|
EnsureValidArray(valid, RowCount, i);
|
||||||
if valid = nil then
|
|
||||||
begin
|
|
||||||
valid := new boolean[RowCount];
|
|
||||||
for var j := 0 to i - 1 do
|
|
||||||
valid[j] := true;
|
|
||||||
end;
|
|
||||||
|
|
||||||
valid[i] := false;
|
valid[i] := false;
|
||||||
i += 1;
|
i += 1;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -3256,13 +3265,10 @@ begin
|
||||||
i += 1;
|
i += 1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// 3. добавляем новый столбец
|
|
||||||
res.AddIntColumn(name, data, valid);
|
res.AddIntColumn(name, data, valid);
|
||||||
|
|
||||||
res.SetSchema(ExtendSchema(name, ctInt, false));
|
res.SetSchema(ExtendSchema(name, ctInt, false));
|
||||||
|
|
||||||
Result := res;
|
Result := res;
|
||||||
|
|
||||||
AssertSchemaConsistent;
|
AssertSchemaConsistent;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -3270,41 +3276,9 @@ function DataFrame.WithColumnFloat(name: string; f: DataFrameCursor -> real): Da
|
||||||
begin
|
begin
|
||||||
if fSchema.HasColumn(name) then
|
if fSchema.HasColumn(name) then
|
||||||
ArgumentError(ER_COLUMN_ALREADY_EXISTS, name);
|
ArgumentError(ER_COLUMN_ALREADY_EXISTS, name);
|
||||||
|
|
||||||
var res := new DataFrame;
|
|
||||||
|
|
||||||
// 1. копируем существующие колонки
|
var res := CloneWithCopiedColumns;
|
||||||
for var i := 0 to columns.Count - 1 do
|
|
||||||
begin
|
|
||||||
var col := columns[i];
|
|
||||||
case col.Info.ColType of
|
|
||||||
ctInt:
|
|
||||||
begin
|
|
||||||
var c := IntColumn(col);
|
|
||||||
res.AddIntColumn(c.Info.Name, c.Data, c.IsValid);
|
|
||||||
end;
|
|
||||||
|
|
||||||
ctStr:
|
|
||||||
begin
|
|
||||||
var c := StrColumn(col);
|
|
||||||
res.AddStrColumn(c.Info.Name, c.Data, c.IsValid);
|
|
||||||
end;
|
|
||||||
|
|
||||||
ctFloat:
|
|
||||||
begin
|
|
||||||
var c := FloatColumn(col);
|
|
||||||
res.AddFloatColumn(c.Info.Name, c.Data, c.IsValid);
|
|
||||||
end;
|
|
||||||
|
|
||||||
ctBool:
|
|
||||||
begin
|
|
||||||
var c := BoolColumn(col);
|
|
||||||
res.AddBoolColumn(c.Info.Name, c.Data, c.IsValid);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// 2. вычисляем новый столбец
|
|
||||||
var data := new real[RowCount];
|
var data := new real[RowCount];
|
||||||
var valid: array of boolean := nil;
|
var valid: array of boolean := nil;
|
||||||
|
|
||||||
|
|
@ -3316,16 +3290,10 @@ begin
|
||||||
try
|
try
|
||||||
data[i] := f(cur);
|
data[i] := f(cur);
|
||||||
except
|
except
|
||||||
|
on e: Exception do
|
||||||
begin
|
begin
|
||||||
data[i] := 0.0;
|
data[i] := 0.0;
|
||||||
|
EnsureValidArray(valid, RowCount, i);
|
||||||
if valid = nil then
|
|
||||||
begin
|
|
||||||
valid := new boolean[RowCount];
|
|
||||||
for var j := 0 to i - 1 do
|
|
||||||
valid[j] := true;
|
|
||||||
end;
|
|
||||||
|
|
||||||
valid[i] := false;
|
valid[i] := false;
|
||||||
i += 1;
|
i += 1;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -3338,13 +3306,10 @@ begin
|
||||||
i += 1;
|
i += 1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// 3. добавляем новый столбец
|
|
||||||
res.AddFloatColumn(name, data, valid);
|
res.AddFloatColumn(name, data, valid);
|
||||||
|
|
||||||
res.SetSchema(ExtendSchema(name, ctFloat, false));
|
res.SetSchema(ExtendSchema(name, ctFloat, false));
|
||||||
|
|
||||||
Result := res;
|
Result := res;
|
||||||
|
|
||||||
AssertSchemaConsistent;
|
AssertSchemaConsistent;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -3352,41 +3317,9 @@ function DataFrame.WithColumnStr(name: string; f: DataFrameCursor -> string): Da
|
||||||
begin
|
begin
|
||||||
if fSchema.HasColumn(name) then
|
if fSchema.HasColumn(name) then
|
||||||
ArgumentError(ER_COLUMN_ALREADY_EXISTS, name);
|
ArgumentError(ER_COLUMN_ALREADY_EXISTS, name);
|
||||||
|
|
||||||
var res := new DataFrame;
|
|
||||||
|
|
||||||
// 1. копируем существующие колонки
|
var res := CloneWithCopiedColumns;
|
||||||
for var i := 0 to columns.Count - 1 do
|
|
||||||
begin
|
|
||||||
var col := columns[i];
|
|
||||||
case col.Info.ColType of
|
|
||||||
ctInt:
|
|
||||||
begin
|
|
||||||
var c := IntColumn(col);
|
|
||||||
res.AddIntColumn(c.Info.Name, c.Data, c.IsValid);
|
|
||||||
end;
|
|
||||||
|
|
||||||
ctStr:
|
|
||||||
begin
|
|
||||||
var c := StrColumn(col);
|
|
||||||
res.AddStrColumn(c.Info.Name, c.Data, c.IsValid);
|
|
||||||
end;
|
|
||||||
|
|
||||||
ctFloat:
|
|
||||||
begin
|
|
||||||
var c := FloatColumn(col);
|
|
||||||
res.AddFloatColumn(c.Info.Name, c.Data, c.IsValid);
|
|
||||||
end;
|
|
||||||
|
|
||||||
ctBool:
|
|
||||||
begin
|
|
||||||
var c := BoolColumn(col);
|
|
||||||
res.AddBoolColumn(c.Info.Name, c.Data, c.IsValid);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// 2. вычисляем новый столбец
|
|
||||||
var data := new string[RowCount];
|
var data := new string[RowCount];
|
||||||
var valid: array of boolean := nil;
|
var valid: array of boolean := nil;
|
||||||
|
|
||||||
|
|
@ -3398,16 +3331,10 @@ begin
|
||||||
try
|
try
|
||||||
data[i] := f(cur);
|
data[i] := f(cur);
|
||||||
except
|
except
|
||||||
|
on e: Exception do
|
||||||
begin
|
begin
|
||||||
data[i] := '';
|
data[i] := nil;
|
||||||
|
EnsureValidArray(valid, RowCount, i);
|
||||||
if valid = nil then
|
|
||||||
begin
|
|
||||||
valid := new boolean[RowCount];
|
|
||||||
for var j := 0 to i - 1 do
|
|
||||||
valid[j] := true;
|
|
||||||
end;
|
|
||||||
|
|
||||||
valid[i] := false;
|
valid[i] := false;
|
||||||
i += 1;
|
i += 1;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -3420,13 +3347,10 @@ begin
|
||||||
i += 1;
|
i += 1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// 3. добавляем новый столбец
|
|
||||||
res.AddStrColumn(name, data, valid);
|
res.AddStrColumn(name, data, valid);
|
||||||
|
|
||||||
res.SetSchema(ExtendSchema(name, ctStr, false));
|
res.SetSchema(ExtendSchema(name, ctStr, false));
|
||||||
|
|
||||||
Result := res;
|
Result := res;
|
||||||
|
|
||||||
AssertSchemaConsistent;
|
AssertSchemaConsistent;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -3434,41 +3358,9 @@ function DataFrame.WithColumnBool(name: string; f: DataFrameCursor -> boolean):
|
||||||
begin
|
begin
|
||||||
if fSchema.HasColumn(name) then
|
if fSchema.HasColumn(name) then
|
||||||
ArgumentError(ER_COLUMN_ALREADY_EXISTS, name);
|
ArgumentError(ER_COLUMN_ALREADY_EXISTS, name);
|
||||||
|
|
||||||
var res := new DataFrame;
|
|
||||||
|
|
||||||
// 1. копируем существующие колонки
|
var res := CloneWithCopiedColumns;
|
||||||
for var i := 0 to columns.Count - 1 do
|
|
||||||
begin
|
|
||||||
var col := columns[i];
|
|
||||||
case col.Info.ColType of
|
|
||||||
ctInt:
|
|
||||||
begin
|
|
||||||
var c := IntColumn(col);
|
|
||||||
res.AddIntColumn(c.Info.Name, c.Data, c.IsValid);
|
|
||||||
end;
|
|
||||||
|
|
||||||
ctStr:
|
|
||||||
begin
|
|
||||||
var c := StrColumn(col);
|
|
||||||
res.AddStrColumn(c.Info.Name, c.Data, c.IsValid);
|
|
||||||
end;
|
|
||||||
|
|
||||||
ctFloat:
|
|
||||||
begin
|
|
||||||
var c := FloatColumn(col);
|
|
||||||
res.AddFloatColumn(c.Info.Name, c.Data, c.IsValid);
|
|
||||||
end;
|
|
||||||
|
|
||||||
ctBool:
|
|
||||||
begin
|
|
||||||
var c := BoolColumn(col);
|
|
||||||
res.AddBoolColumn(c.Info.Name, c.Data, c.IsValid);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// 2. вычисляем новый столбец
|
|
||||||
var data := new boolean[RowCount];
|
var data := new boolean[RowCount];
|
||||||
var valid: array of boolean := nil;
|
var valid: array of boolean := nil;
|
||||||
|
|
||||||
|
|
@ -3480,16 +3372,10 @@ begin
|
||||||
try
|
try
|
||||||
data[i] := f(cur);
|
data[i] := f(cur);
|
||||||
except
|
except
|
||||||
|
on e: Exception do
|
||||||
begin
|
begin
|
||||||
data[i] := false;
|
data[i] := false;
|
||||||
|
EnsureValidArray(valid, RowCount, i);
|
||||||
if valid = nil then
|
|
||||||
begin
|
|
||||||
valid := new boolean[RowCount];
|
|
||||||
for var j := 0 to i - 1 do
|
|
||||||
valid[j] := true;
|
|
||||||
end;
|
|
||||||
|
|
||||||
valid[i] := false;
|
valid[i] := false;
|
||||||
i += 1;
|
i += 1;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -3502,13 +3388,10 @@ begin
|
||||||
i += 1;
|
i += 1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// 3. добавляем новый столбец
|
|
||||||
res.AddBoolColumn(name, data, valid);
|
res.AddBoolColumn(name, data, valid);
|
||||||
|
|
||||||
res.SetSchema(ExtendSchema(name, ctBool, false));
|
res.SetSchema(ExtendSchema(name, ctBool, false));
|
||||||
|
|
||||||
Result := res;
|
Result := res;
|
||||||
|
|
||||||
AssertSchemaConsistent;
|
AssertSchemaConsistent;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -3549,27 +3432,56 @@ begin
|
||||||
|
|
||||||
var cur := GetCursor;
|
var cur := GetCursor;
|
||||||
var row := 0;
|
var row := 0;
|
||||||
|
|
||||||
while cur.MoveNext do
|
while cur.MoveNext do
|
||||||
begin
|
begin
|
||||||
|
// --- NA: обрабатываем явно, без исключений
|
||||||
|
if not cur.IsValid(colIndex) then
|
||||||
|
begin
|
||||||
|
data[row] := 0.0;
|
||||||
|
|
||||||
|
if valid = nil then
|
||||||
|
begin
|
||||||
|
valid := new boolean[rowCount];
|
||||||
|
for var j := 0 to row - 1 do
|
||||||
|
valid[j] := true;
|
||||||
|
end;
|
||||||
|
|
||||||
|
valid[row] := false;
|
||||||
|
row += 1;
|
||||||
|
continue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// --- вычисление
|
||||||
try
|
try
|
||||||
data[row] := f(cur);
|
data[row] := f(cur);
|
||||||
if valid <> nil then valid[row] := true;
|
|
||||||
except
|
except
|
||||||
on e: Exception do
|
on e: Exception do
|
||||||
begin
|
begin
|
||||||
data[row] := 0.0;
|
data[row] := 0.0;
|
||||||
|
|
||||||
if valid = nil then
|
if valid = nil then
|
||||||
begin
|
begin
|
||||||
valid := new boolean[rowCount];
|
valid := new boolean[rowCount];
|
||||||
for var j := 0 to row - 1 do valid[j] := true;
|
for var j := 0 to row - 1 do
|
||||||
|
valid[j] := true;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
valid[row] := false;
|
valid[row] := false;
|
||||||
|
row += 1;
|
||||||
|
continue;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
if valid <> nil then
|
||||||
|
valid[row] := true;
|
||||||
|
|
||||||
row += 1;
|
row += 1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// --- сборка результата
|
||||||
var res := new DataFrame;
|
var res := new DataFrame;
|
||||||
|
|
||||||
for var i := 0 to columns.Count - 1 do
|
for var i := 0 to columns.Count - 1 do
|
||||||
if i <> colIndex then
|
if i <> colIndex then
|
||||||
res.AddColumnView(columns[i])
|
res.AddColumnView(columns[i])
|
||||||
|
|
@ -5452,11 +5364,8 @@ begin
|
||||||
Error(ER_ZERO_STD_STANDARDIZE);
|
Error(ER_ZERO_STD_STANDARDIZE);
|
||||||
|
|
||||||
Result := df.ReplaceColumnFloat(colName, cur ->
|
Result := df.ReplaceColumnFloat(colName, cur ->
|
||||||
begin
|
(cur.Float(idx) - mean) / std
|
||||||
if not cur.IsValid(idx) then
|
);
|
||||||
Error(ER_INVALID_VALUE_IN_COLUMN, colName);
|
|
||||||
Result := (cur.Float(idx) - mean) / std;
|
|
||||||
end);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
static function Statistics.StandardizeAll(df: DataFrame): DataFrame;
|
static function Statistics.StandardizeAll(df: DataFrame): DataFrame;
|
||||||
|
|
@ -5653,37 +5562,6 @@ end;
|
||||||
// CSVLoader
|
// CSVLoader
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
|
|
||||||
{procedure ScanFields(line: string; delimiter: char;
|
|
||||||
starts, lens: array of integer; var actualCount: integer);
|
|
||||||
begin
|
|
||||||
var j := 1;
|
|
||||||
var col := 0;
|
|
||||||
var n := line.Length;
|
|
||||||
|
|
||||||
starts[0] := 1;
|
|
||||||
|
|
||||||
while j <= n do
|
|
||||||
begin
|
|
||||||
if line[j] = delimiter then
|
|
||||||
begin
|
|
||||||
if col < starts.Length then
|
|
||||||
lens[col] := j - starts[col];
|
|
||||||
col += 1;
|
|
||||||
if col < starts.Length then
|
|
||||||
starts[col] := j + 1;
|
|
||||||
end;
|
|
||||||
j += 1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if col < starts.Length then
|
|
||||||
lens[col] := n - starts[col] + 1;
|
|
||||||
|
|
||||||
for var k := col + 1 to starts.Length - 1 do
|
|
||||||
lens[k] := 0;
|
|
||||||
|
|
||||||
actualCount := col + 1;
|
|
||||||
end;}
|
|
||||||
|
|
||||||
procedure ScanFieldsQuoted(
|
procedure ScanFieldsQuoted(
|
||||||
line: string; delimiter: char;
|
line: string; delimiter: char;
|
||||||
starts, lens: array of integer;
|
starts, lens: array of integer;
|
||||||
|
|
@ -6466,13 +6344,34 @@ begin
|
||||||
System.IO.FileShare.ReadWrite
|
System.IO.FileShare.ReadWrite
|
||||||
);
|
);
|
||||||
try
|
try
|
||||||
|
// --- BOM check
|
||||||
var bom := new byte[3];
|
var bom := new byte[3];
|
||||||
var n := fs.Read(bom, 0, 3);
|
var n := fs.Read(bom, 0, 3);
|
||||||
|
|
||||||
|
// UTF-8 BOM
|
||||||
if (n >= 3) and (bom[0] = $EF) and (bom[1] = $BB) and (bom[2] = $BF) then
|
if (n >= 3) and (bom[0] = $EF) and (bom[1] = $BB) and (bom[2] = $BF) then
|
||||||
Result := Encoding.UTF8
|
exit(Encoding.UTF8);
|
||||||
else
|
|
||||||
Result := Encoding.UTF8;
|
// --- reset position
|
||||||
|
fs.Position := 0;
|
||||||
|
|
||||||
|
// --- read small chunk
|
||||||
|
var bufferSize := 4096;
|
||||||
|
var buffer := new byte[bufferSize];
|
||||||
|
var readBytes := fs.Read(buffer, 0, bufferSize);
|
||||||
|
|
||||||
|
// --- strict UTF-8 check
|
||||||
|
try
|
||||||
|
var utf8 := new System.Text.UTF8Encoding(false, true); // strict
|
||||||
|
utf8.GetString(buffer, 0, readBytes);
|
||||||
|
exit(Encoding.UTF8);
|
||||||
|
except
|
||||||
|
// not UTF-8
|
||||||
|
end;
|
||||||
|
|
||||||
|
// --- fallback
|
||||||
|
Result := Encoding.Default;
|
||||||
|
|
||||||
finally
|
finally
|
||||||
fs.Close;
|
fs.Close;
|
||||||
end;
|
end;
|
||||||
|
|
|
||||||
|
|
@ -789,7 +789,14 @@ end;}
|
||||||
|
|
||||||
function JoinKey.Equals(oth: object): boolean;
|
function JoinKey.Equals(oth: object): boolean;
|
||||||
begin
|
begin
|
||||||
var other: JoinKey := JoinKey(oth);
|
if oth = nil then
|
||||||
|
exit(false);
|
||||||
|
|
||||||
|
if not (oth is JoinKey) then
|
||||||
|
exit(false);
|
||||||
|
|
||||||
|
var other := JoinKey(oth);
|
||||||
|
|
||||||
if Ints.Length <> other.Ints.Length then exit(false);
|
if Ints.Length <> other.Ints.Length then exit(false);
|
||||||
if Floats.Length <> other.Floats.Length then exit(false);
|
if Floats.Length <> other.Floats.Length then exit(false);
|
||||||
if Strs.Length <> other.Strs.Length then exit(false);
|
if Strs.Length <> other.Strs.Length then exit(false);
|
||||||
|
|
|
||||||
|
|
@ -327,6 +327,9 @@ const
|
||||||
ER_SINGULAR_MATRIX =
|
ER_SINGULAR_MATRIX =
|
||||||
'Матрица вырождена или плохо обусловлена!!Matrix is singular or ill-conditioned';
|
'Матрица вырождена или плохо обусловлена!!Matrix is singular or ill-conditioned';
|
||||||
|
|
||||||
|
type
|
||||||
|
MLNotSPDException = class(MLException);
|
||||||
|
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
// Vector
|
// Vector
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
|
|
@ -1254,7 +1257,6 @@ begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Helper
|
// Helper
|
||||||
function Cholesky(A: Matrix): Matrix;
|
function Cholesky(A: Matrix): Matrix;
|
||||||
begin
|
begin
|
||||||
|
|
@ -1274,7 +1276,7 @@ begin
|
||||||
if i = j then
|
if i = j then
|
||||||
begin
|
begin
|
||||||
if s <= 0.0 then
|
if s <= 0.0 then
|
||||||
Error(ER_MATRIX_NOT_SPD);
|
raise new MLNotSPDException('Матрица не является положительно определённой (SPD)');
|
||||||
L[i, i] := Sqrt(s);
|
L[i, i] := Sqrt(s);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
|
@ -1423,6 +1425,7 @@ begin
|
||||||
DimensionError(ER_VECTOR_SIZE_MISMATCH, b.Length, A.RowCount);
|
DimensionError(ER_VECTOR_SIZE_MISMATCH, b.Length, A.RowCount);
|
||||||
|
|
||||||
var L := Cholesky(A);
|
var L := Cholesky(A);
|
||||||
|
|
||||||
var y := SolveLowerTriangular(L, b);
|
var y := SolveLowerTriangular(L, b);
|
||||||
Result := SolveUpperTriangular(L.Transpose, y);
|
Result := SolveUpperTriangular(L.Transpose, y);
|
||||||
end;
|
end;
|
||||||
|
|
@ -1432,7 +1435,8 @@ begin
|
||||||
try
|
try
|
||||||
Result := SolveSPD(A, b);
|
Result := SolveSPD(A, b);
|
||||||
except
|
except
|
||||||
Result := Solve(A, b);
|
on e: MLNotSPDException do
|
||||||
|
Result := Solve(A, b);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ type
|
||||||
|
|
||||||
IModel = MLCoreABC.IModel;
|
IModel = MLCoreABC.IModel;
|
||||||
ISupervisedModel = MLCoreABC.ISupervisedModel;
|
ISupervisedModel = MLCoreABC.ISupervisedModel;
|
||||||
IUnSupervisedModel = MLCoreABC.IUnSupervisedModel;
|
IUnsupervisedModel = MLCoreABC.IUnsupervisedModel;
|
||||||
UPipeline = MLModelsABC.UPipeline;
|
UPipeline = MLModelsABC.UPipeline;
|
||||||
UDataPipeline = MLPipelineABC.UDataPipeline;
|
UDataPipeline = MLPipelineABC.UDataPipeline;
|
||||||
TaskKind = MLPipelineABC.TaskKind;
|
TaskKind = MLPipelineABC.TaskKind;
|
||||||
|
|
|
||||||
|
|
@ -1303,26 +1303,31 @@ end;
|
||||||
|
|
||||||
static function Datasets.StudentExam: Dataset;
|
static function Datasets.StudentExam: Dataset;
|
||||||
begin
|
begin
|
||||||
|
NotImplementedError(ER_NOT_IMPLEMENTED, 'Datasets.StudentExam');
|
||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
static function Datasets.BankClients: Dataset;
|
static function Datasets.BankClients: Dataset;
|
||||||
begin
|
begin
|
||||||
|
NotImplementedError(ER_NOT_IMPLEMENTED, 'Datasets.BankClients');
|
||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
static function Datasets.TaxiTrips: Dataset;
|
static function Datasets.TaxiTrips: Dataset;
|
||||||
begin
|
begin
|
||||||
|
NotImplementedError(ER_NOT_IMPLEMENTED, 'Datasets.TaxiTrips');
|
||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
static function Datasets.MoscowTransport: Dataset;
|
static function Datasets.MoscowTransport: Dataset;
|
||||||
begin
|
begin
|
||||||
|
NotImplementedError(ER_NOT_IMPLEMENTED, 'Datasets.MoscowTransport');
|
||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
static function Datasets.OnlineShopping: Dataset;
|
static function Datasets.OnlineShopping: Dataset;
|
||||||
begin
|
begin
|
||||||
|
NotImplementedError(ER_NOT_IMPLEMENTED, 'Datasets.OnlineShopping');
|
||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@ const
|
||||||
'Пустой набор данных для {0}!!Empty dataset for {0}';
|
'Пустой набор данных для {0}!!Empty dataset for {0}';
|
||||||
ER_COLUMN_NOT_FOUND =
|
ER_COLUMN_NOT_FOUND =
|
||||||
'В DataFrame отсутствует столбец "{0}"!!DataFrame does not contain column "{0}"';
|
'В DataFrame отсутствует столбец "{0}"!!DataFrame does not contain column "{0}"';
|
||||||
|
ER_NOT_IMPLEMENTED =
|
||||||
|
'Метод {0} не реализован!!Method {0} is not implemented';
|
||||||
|
|
||||||
type
|
type
|
||||||
/// Базовое исключение ML-библиотеки
|
/// Базовое исключение ML-библиотеки
|
||||||
MLException = class(Exception);
|
MLException = class(Exception);
|
||||||
|
|
@ -33,6 +35,8 @@ type
|
||||||
|
|
||||||
/// Несоответствие размерностей
|
/// Несоответствие размерностей
|
||||||
MLDimensionException = class(MLException);
|
MLDimensionException = class(MLException);
|
||||||
|
|
||||||
|
MLNotImplementedException = class(MLException);
|
||||||
|
|
||||||
procedure Error(msg: string; params args: array of object);
|
procedure Error(msg: string; params args: array of object);
|
||||||
procedure ArgumentError(msg: string; params args: array of object);
|
procedure ArgumentError(msg: string; params args: array of object);
|
||||||
|
|
@ -40,6 +44,7 @@ procedure NotFittedError(msg: string; params args: array of object);
|
||||||
procedure DimensionError(msg: string; params args: array of object);
|
procedure DimensionError(msg: string; params args: array of object);
|
||||||
procedure ArgumentNullError(msg: string; params args: array of object);
|
procedure ArgumentNullError(msg: string; params args: array of object);
|
||||||
procedure ArgumentOutOfRangeError(msg: string; params args: array of object);
|
procedure ArgumentOutOfRangeError(msg: string; params args: array of object);
|
||||||
|
procedure NotImplementedError(msg: string; params args: array of object);
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
|
@ -83,4 +88,10 @@ begin
|
||||||
raise new System.ArgumentOutOfRangeException(FormatSafe(msg, args));
|
raise new System.ArgumentOutOfRangeException(FormatSafe(msg, args));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure NotImplementedError(msg: string; params args: array of object);
|
||||||
|
begin
|
||||||
|
raise new MLNotImplementedException(FormatSafe(msg, args));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
|
||||||
|
|
@ -1013,7 +1013,7 @@ type
|
||||||
: ISupervisedModel;
|
: ISupervisedModel;
|
||||||
|
|
||||||
procedure BuildClassMapping(y: Vector);
|
procedure BuildClassMapping(y: Vector);
|
||||||
function EncodeLabels(y: Vector): array of integer;
|
function ApplyLabelEncoding(y: Vector): array of integer;
|
||||||
|
|
||||||
procedure SoftmaxRow(var logits: array of real; var probs: array of real);
|
procedure SoftmaxRow(var logits: array of real; var probs: array of real);
|
||||||
procedure SoftmaxMatrix(logits: Matrix; probs: Matrix);
|
procedure SoftmaxMatrix(logits: Matrix; probs: Matrix);
|
||||||
|
|
@ -1339,7 +1339,6 @@ type
|
||||||
private
|
private
|
||||||
fEps: real;
|
fEps: real;
|
||||||
fMinSamples: integer;
|
fMinSamples: integer;
|
||||||
fSeed: integer;
|
|
||||||
|
|
||||||
fFitted: boolean;
|
fFitted: boolean;
|
||||||
fFeatureCount: integer;
|
fFeatureCount: integer;
|
||||||
|
|
@ -1356,8 +1355,7 @@ type
|
||||||
/// seed — параметр для совместимости API.
|
/// seed — параметр для совместимости API.
|
||||||
constructor Create(
|
constructor Create(
|
||||||
eps: real;
|
eps: real;
|
||||||
minSamples: integer := 5;
|
minSamples: integer := 5
|
||||||
seed: integer := -1
|
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Обучает модель на матрице признаков.
|
/// Обучает модель на матрице признаков.
|
||||||
|
|
@ -3506,18 +3504,6 @@ begin
|
||||||
if X.RowCount <> y.Length then
|
if X.RowCount <> y.Length then
|
||||||
DimensionError(ER_DIM_MISMATCH, X.RowCount, y.Length);
|
DimensionError(ER_DIM_MISMATCH, X.RowCount, y.Length);
|
||||||
|
|
||||||
if fMinSamplesSplit < 2 then
|
|
||||||
ArgumentOutOfRangeError(ER_MINSAMPLESSPLIT_INVALID, fMinSamplesSplit);
|
|
||||||
|
|
||||||
if fMinSamplesLeaf < 1 then
|
|
||||||
ArgumentOutOfRangeError(ER_MINSAMPLESLEAF_INVALID, fMinSamplesLeaf);
|
|
||||||
|
|
||||||
if fMaxDepth < -1 then
|
|
||||||
ArgumentOutOfRangeError(ER_MAX_DEPTH_INVALID, fMaxDepth);
|
|
||||||
|
|
||||||
if fMaxDepth > 10000 then
|
|
||||||
ArgumentError(ER_MAX_DEPTH_TOO_LARGE, fMaxDepth);
|
|
||||||
|
|
||||||
|
|
||||||
fFeatureImportances := new Vector(X.ColCount);
|
fFeatureImportances := new Vector(X.ColCount);
|
||||||
|
|
||||||
|
|
@ -3758,21 +3744,9 @@ begin
|
||||||
if X.RowCount <> y.Length then
|
if X.RowCount <> y.Length then
|
||||||
DimensionError(ER_DIM_MISMATCH, X.RowCount, y.Length);
|
DimensionError(ER_DIM_MISMATCH, X.RowCount, y.Length);
|
||||||
|
|
||||||
if fMinSamplesSplit < 2 then
|
|
||||||
ArgumentOutOfRangeError(ER_MINSAMPLESSPLIT_INVALID, fMinSamplesSplit);
|
|
||||||
|
|
||||||
if fMinSamplesLeaf < 1 then
|
|
||||||
ArgumentOutOfRangeError(ER_MINSAMPLESLEAF_INVALID, fMinSamplesLeaf);
|
|
||||||
|
|
||||||
if fLeafL2 < 0 then
|
if fLeafL2 < 0 then
|
||||||
ArgumentOutOfRangeError(ER_L2_NEGATIVE, fLeafL2);
|
ArgumentOutOfRangeError(ER_L2_NEGATIVE, fLeafL2);
|
||||||
|
|
||||||
if fMaxDepth < -1 then
|
|
||||||
ArgumentOutOfRangeError(ER_MAX_DEPTH_INVALID, fMaxDepth);
|
|
||||||
|
|
||||||
if fMaxDepth > 10000 then
|
|
||||||
ArgumentError(ER_MAX_DEPTH_TOO_LARGE, fMaxDepth);
|
|
||||||
|
|
||||||
fFeatureImportances := new Vector(X.ColCount);
|
fFeatureImportances := new Vector(X.ColCount);
|
||||||
|
|
||||||
var indices: array of integer;
|
var indices: array of integer;
|
||||||
|
|
@ -3986,24 +3960,6 @@ begin
|
||||||
if X.RowCount <> y.Length then
|
if X.RowCount <> y.Length then
|
||||||
DimensionError(ER_DIM_MISMATCH, X.RowCount, y.Length);
|
DimensionError(ER_DIM_MISMATCH, X.RowCount, y.Length);
|
||||||
|
|
||||||
if fNTrees <= 0 then
|
|
||||||
ArgumentOutOfRangeError(ER_NTREES_INVALID, fNTrees);
|
|
||||||
|
|
||||||
if fMinSamplesSplit < 2 then
|
|
||||||
ArgumentOutOfRangeError(ER_MINSAMPLESSPLIT_INVALID, fMinSamplesSplit);
|
|
||||||
|
|
||||||
if fMinSamplesLeaf < 1 then
|
|
||||||
ArgumentOutOfRangeError(ER_MINSAMPLESLEAF_INVALID, fMinSamplesLeaf);
|
|
||||||
|
|
||||||
if fMinSamplesLeaf >= fMinSamplesSplit then
|
|
||||||
ArgumentError(ER_MIN_LEAF_GE_SPLIT, fMinSamplesLeaf, fMinSamplesSplit);
|
|
||||||
|
|
||||||
if fMaxDepth < -1 then
|
|
||||||
ArgumentOutOfRangeError(ER_MAX_DEPTH_INVALID, fMaxDepth);
|
|
||||||
|
|
||||||
if fMaxDepth > MAX_ALLOWED_TREE_DEPTH then
|
|
||||||
ArgumentError(ER_MAX_DEPTH_TOO_LARGE, fMaxDepth);
|
|
||||||
|
|
||||||
var n := X.RowCount;
|
var n := X.RowCount;
|
||||||
var p := X.ColCount;
|
var p := X.ColCount;
|
||||||
|
|
||||||
|
|
@ -4231,24 +4187,6 @@ begin
|
||||||
if X.RowCount <> y.Length then
|
if X.RowCount <> y.Length then
|
||||||
DimensionError(ER_DIM_MISMATCH, X.RowCount, y.Length);
|
DimensionError(ER_DIM_MISMATCH, X.RowCount, y.Length);
|
||||||
|
|
||||||
if fNTrees <= 0 then
|
|
||||||
ArgumentOutOfRangeError(ER_NTREES_INVALID, fNTrees);
|
|
||||||
|
|
||||||
if fMinSamplesSplit < 2 then
|
|
||||||
ArgumentOutOfRangeError(ER_MINSAMPLESSPLIT_INVALID, fMinSamplesSplit);
|
|
||||||
|
|
||||||
if fMinSamplesLeaf < 1 then
|
|
||||||
ArgumentOutOfRangeError(ER_MINSAMPLESLEAF_INVALID, fMinSamplesLeaf);
|
|
||||||
|
|
||||||
if fMinSamplesLeaf >= fMinSamplesSplit then
|
|
||||||
ArgumentError(ER_MIN_LEAF_GE_SPLIT, fMinSamplesLeaf, fMinSamplesSplit);
|
|
||||||
|
|
||||||
if fMaxDepth < -1 then
|
|
||||||
ArgumentOutOfRangeError(ER_MAX_DEPTH_INVALID, fMaxDepth);
|
|
||||||
|
|
||||||
if fMaxDepth > MAX_ALLOWED_TREE_DEPTH then
|
|
||||||
ArgumentError(ER_MAX_DEPTH_TOO_LARGE, fMaxDepth);
|
|
||||||
|
|
||||||
var n := X.RowCount;
|
var n := X.RowCount;
|
||||||
var p := X.ColCount;
|
var p := X.ColCount;
|
||||||
|
|
||||||
|
|
@ -4594,6 +4532,51 @@ begin
|
||||||
Result := fClassLabels;
|
Result := fClassLabels;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
//-----------------------------
|
||||||
|
// Helper GBC GBR
|
||||||
|
//-----------------------------
|
||||||
|
|
||||||
|
function BuildSubsampleIndices(nTrain: integer; subsample: real; rng: System.Random): array of integer;
|
||||||
|
begin
|
||||||
|
if nTrain <= 0 then
|
||||||
|
ArgumentOutOfRangeError(ER_EMPTY_DATASET);
|
||||||
|
|
||||||
|
if (subsample <= 0.0) or (subsample > 1.0) then
|
||||||
|
ArgumentOutOfRangeError(ER_SUBSAMPLE_INVALID, subsample);
|
||||||
|
|
||||||
|
var k := Floor(nTrain * subsample);
|
||||||
|
if k < 1 then
|
||||||
|
k := 1;
|
||||||
|
if k > nTrain then
|
||||||
|
k := nTrain;
|
||||||
|
|
||||||
|
// если берём всё — можно быстро вернуть [0..nTrain-1]
|
||||||
|
if k = nTrain then
|
||||||
|
begin
|
||||||
|
Result := new integer[nTrain];
|
||||||
|
for var i := 0 to nTrain - 1 do
|
||||||
|
Result[i] := i;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var all := new integer[nTrain];
|
||||||
|
for var i := 0 to nTrain - 1 do
|
||||||
|
all[i] := i;
|
||||||
|
|
||||||
|
// partial Fisher–Yates (без повторений)
|
||||||
|
for var i := 0 to k - 1 do
|
||||||
|
begin
|
||||||
|
var j := i + rng.Next(nTrain - i);
|
||||||
|
var tmp := all[i];
|
||||||
|
all[i] := all[j];
|
||||||
|
all[j] := tmp;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := new integer[k];
|
||||||
|
for var i := 0 to k - 1 do
|
||||||
|
Result[i] := all[i];
|
||||||
|
end;
|
||||||
|
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
// GradientBoostingRegressor
|
// GradientBoostingRegressor
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
|
|
@ -4629,6 +4612,9 @@ begin
|
||||||
|
|
||||||
if minSamplesLeaf < 1 then
|
if minSamplesLeaf < 1 then
|
||||||
ArgumentOutOfRangeError(ER_MIN_SAMPLES_LEAF_INVALID, minSamplesLeaf);
|
ArgumentOutOfRangeError(ER_MIN_SAMPLES_LEAF_INVALID, minSamplesLeaf);
|
||||||
|
|
||||||
|
if maxDepth > MAX_ALLOWED_TREE_DEPTH then
|
||||||
|
ArgumentOutOfRangeError(ER_MAX_DEPTH_TOO_LARGE, maxDepth);
|
||||||
|
|
||||||
fNEstimators := nEstimators;
|
fNEstimators := nEstimators;
|
||||||
fLearningRate := learningRate;
|
fLearningRate := learningRate;
|
||||||
|
|
@ -4905,28 +4891,6 @@ begin
|
||||||
DimensionError(ER_FEATURE_COUNT_MISMATCH);
|
DimensionError(ER_FEATURE_COUNT_MISMATCH);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- hyperparameter checks ---
|
|
||||||
if fNEstimators <= 0 then
|
|
||||||
ArgumentOutOfRangeError(ER_NESTIMATORS_INVALID, fNEstimators);
|
|
||||||
|
|
||||||
if fLearningRate <= 0 then
|
|
||||||
ArgumentOutOfRangeError(ER_LEARNING_RATE_INVALID, fLearningRate);
|
|
||||||
|
|
||||||
if (fSubsample <= 0.0) or (fSubsample > 1.0) then
|
|
||||||
ArgumentOutOfRangeError(ER_SUBSAMPLE_INVALID, fSubsample);
|
|
||||||
|
|
||||||
if fMinSamplesSplit < 2 then
|
|
||||||
ArgumentOutOfRangeError(ER_MINSAMPLESSPLIT_INVALID, fMinSamplesSplit);
|
|
||||||
|
|
||||||
if fMinSamplesLeaf < 1 then
|
|
||||||
ArgumentOutOfRangeError(ER_MINSAMPLESLEAF_INVALID, fMinSamplesLeaf);
|
|
||||||
|
|
||||||
if fMaxDepth < 0 then
|
|
||||||
ArgumentOutOfRangeError(ER_MAX_DEPTH_INVALID, fMaxDepth);
|
|
||||||
|
|
||||||
if fMaxDepth > MAX_ALLOWED_TREE_DEPTH then
|
|
||||||
ArgumentError(ER_MAX_DEPTH_TOO_LARGE, fMaxDepth);
|
|
||||||
|
|
||||||
// --- init state ---
|
// --- init state ---
|
||||||
fOOBLossHistory.Clear;
|
fOOBLossHistory.Clear;
|
||||||
fEstimators.Clear;
|
fEstimators.Clear;
|
||||||
|
|
@ -4994,40 +4958,20 @@ begin
|
||||||
// --- subsample ---
|
// --- subsample ---
|
||||||
var rows: array of integer := nil;
|
var rows: array of integer := nil;
|
||||||
var used: array of boolean := nil;
|
var used: array of boolean := nil;
|
||||||
|
|
||||||
if useSubsample then
|
if useSubsample then
|
||||||
begin
|
begin
|
||||||
var k := Floor(nTrain * fSubsample);
|
rows := BuildSubsampleIndices(nTrain, fSubsample, fRng);
|
||||||
if k < 1 then k := 1;
|
|
||||||
if k > nTrain then k := nTrain;
|
|
||||||
|
|
||||||
var all := new integer[nTrain];
|
|
||||||
for var i := 0 to nTrain - 1 do
|
|
||||||
all[i] := i;
|
|
||||||
|
|
||||||
// partial Fisher–Yates
|
|
||||||
for var i := 0 to k - 1 do
|
|
||||||
begin
|
|
||||||
var j := i + fRng.Next(nTrain - i);
|
|
||||||
var tmp := all[i];
|
|
||||||
all[i] := all[j];
|
|
||||||
all[j] := tmp;
|
|
||||||
end;
|
|
||||||
|
|
||||||
rows := new integer[k];
|
|
||||||
for var i := 0 to k - 1 do
|
|
||||||
rows[i] := all[i];
|
|
||||||
|
|
||||||
tree.SetRowIndices(rows);
|
tree.SetRowIndices(rows);
|
||||||
|
|
||||||
if useOOB then
|
if useOOB then
|
||||||
begin
|
begin
|
||||||
used := new boolean[nTrain];
|
used := new boolean[nTrain];
|
||||||
for var i := 0 to k - 1 do
|
for var i := 0 to rows.Length - 1 do
|
||||||
used[rows[i]] := true;
|
used[rows[i]] := true;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
tree.Fit(XTrain, r);
|
tree.Fit(XTrain, r);
|
||||||
fEstimators.Add(tree);
|
fEstimators.Add(tree);
|
||||||
|
|
||||||
|
|
@ -5399,6 +5343,7 @@ begin
|
||||||
Result := copy;
|
Result := copy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
// GradientBoostingClassifier
|
// GradientBoostingClassifier
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
|
|
@ -5450,28 +5395,6 @@ begin
|
||||||
DimensionError(ER_FEATURE_COUNT_MISMATCH);
|
DimensionError(ER_FEATURE_COUNT_MISMATCH);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- hyperparameter checks ---
|
|
||||||
if fNEstimators <= 0 then
|
|
||||||
ArgumentOutOfRangeError(ER_NESTIMATORS_INVALID, fNEstimators);
|
|
||||||
|
|
||||||
if fLearningRate <= 0 then
|
|
||||||
ArgumentOutOfRangeError(ER_LEARNING_RATE_INVALID, fLearningRate);
|
|
||||||
|
|
||||||
if (fSubsample <= 0.0) or (fSubsample > 1.0) then
|
|
||||||
ArgumentOutOfRangeError(ER_SUBSAMPLE_INVALID, fSubsample);
|
|
||||||
|
|
||||||
if fMinSamplesSplit < 2 then
|
|
||||||
ArgumentOutOfRangeError(ER_MINSAMPLESSPLIT_INVALID, fMinSamplesSplit);
|
|
||||||
|
|
||||||
if fMinSamplesLeaf < 1 then
|
|
||||||
ArgumentOutOfRangeError(ER_MINSAMPLESLEAF_INVALID, fMinSamplesLeaf);
|
|
||||||
|
|
||||||
if fMaxDepth < 0 then
|
|
||||||
ArgumentOutOfRangeError(ER_MAX_DEPTH_INVALID, fMaxDepth);
|
|
||||||
|
|
||||||
if fMaxDepth > MAX_ALLOWED_TREE_DEPTH then
|
|
||||||
ArgumentError(ER_MAX_DEPTH_TOO_LARGE, fMaxDepth);
|
|
||||||
|
|
||||||
// --- reset state
|
// --- reset state
|
||||||
fOOBLossHistory.Clear;
|
fOOBLossHistory.Clear;
|
||||||
fEstimators.Clear;
|
fEstimators.Clear;
|
||||||
|
|
@ -5485,7 +5408,7 @@ begin
|
||||||
|
|
||||||
// --- mapping
|
// --- mapping
|
||||||
BuildClassMapping(yTrain);
|
BuildClassMapping(yTrain);
|
||||||
var yEncoded := EncodeLabels(yTrain);
|
var yEncoded := ApplyLabelEncoding(yTrain);
|
||||||
|
|
||||||
var nTrain := XTrain.RowCount;
|
var nTrain := XTrain.RowCount;
|
||||||
var classCount := fClassCount;
|
var classCount := fClassCount;
|
||||||
|
|
@ -5540,7 +5463,7 @@ begin
|
||||||
if useValidation then
|
if useValidation then
|
||||||
begin
|
begin
|
||||||
logitsVal := new Matrix(XVal.RowCount, classCount);
|
logitsVal := new Matrix(XVal.RowCount, classCount);
|
||||||
yValEncoded := EncodeLabels(yVal);
|
yValEncoded := ApplyLabelEncoding(yVal);
|
||||||
|
|
||||||
// --- инициализация log-prior
|
// --- инициализация log-prior
|
||||||
for var i := 0 to XVal.RowCount - 1 do
|
for var i := 0 to XVal.RowCount - 1 do
|
||||||
|
|
@ -5578,6 +5501,11 @@ begin
|
||||||
// inBag
|
// inBag
|
||||||
var inBag: array of boolean := nil;
|
var inBag: array of boolean := nil;
|
||||||
|
|
||||||
|
if useSubsample then
|
||||||
|
begin
|
||||||
|
subIndices := BuildSubsampleIndices(nTrain, fSubsample, fRng);
|
||||||
|
end;
|
||||||
|
|
||||||
if useOOB then
|
if useOOB then
|
||||||
begin
|
begin
|
||||||
SetLength(inBag, nTrain);
|
SetLength(inBag, nTrain);
|
||||||
|
|
@ -5741,7 +5669,7 @@ begin
|
||||||
fClassIndex[fClasses[cls]] := cls;
|
fClassIndex[fClasses[cls]] := cls;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function GradientBoostingClassifier.EncodeLabels(y: Vector): array of integer;
|
function GradientBoostingClassifier.ApplyLabelEncoding(y: Vector): array of integer;
|
||||||
begin
|
begin
|
||||||
var n := y.Length;
|
var n := y.Length;
|
||||||
Result := new integer[n];
|
Result := new integer[n];
|
||||||
|
|
@ -7297,8 +7225,7 @@ end;
|
||||||
|
|
||||||
constructor DBSCAN.Create(
|
constructor DBSCAN.Create(
|
||||||
eps: real;
|
eps: real;
|
||||||
minSamples: integer;
|
minSamples: integer
|
||||||
seed: integer
|
|
||||||
);
|
);
|
||||||
begin
|
begin
|
||||||
if eps <= 0 then
|
if eps <= 0 then
|
||||||
|
|
@ -7309,7 +7236,6 @@ begin
|
||||||
|
|
||||||
fEps := eps;
|
fEps := eps;
|
||||||
fMinSamples := minSamples;
|
fMinSamples := minSamples;
|
||||||
fSeed := seed;
|
|
||||||
|
|
||||||
fFitted := False;
|
fFitted := False;
|
||||||
end;
|
end;
|
||||||
|
|
@ -7454,7 +7380,7 @@ end;
|
||||||
|
|
||||||
function DBSCAN.Clone: IModel;
|
function DBSCAN.Clone: IModel;
|
||||||
begin
|
begin
|
||||||
var m := new DBSCAN(fEps, fMinSamples, fSeed);
|
var m := new DBSCAN(fEps, fMinSamples);
|
||||||
|
|
||||||
m.fFitted := fFitted;
|
m.fFitted := fFitted;
|
||||||
m.fFeatureCount := fFeatureCount;
|
m.fFeatureCount := fFeatureCount;
|
||||||
|
|
|
||||||
|
|
@ -101,8 +101,6 @@ type
|
||||||
procedure Hist(x: Vector; bins: integer := 0;
|
procedure Hist(x: Vector; bins: integer := 0;
|
||||||
color: ColorWPF := DefaultColor; alpha: real := 0.7; legend: string := nil);
|
color: ColorWPF := DefaultColor; alpha: real := 0.7; legend: string := nil);
|
||||||
|
|
||||||
//procedure Surface(labels: array of integer; nx, ny: integer; xmin, xmax, ymin, ymax: real; pal: PlotML.Palette := nil);
|
|
||||||
|
|
||||||
procedure Surface(x1, x2: array of real; nx, ny: integer; f: Matrix -> array of integer; pal: PlotML.Palette := nil);
|
procedure Surface(x1, x2: array of real; nx, ny: integer; f: Matrix -> array of integer; pal: PlotML.Palette := nil);
|
||||||
|
|
||||||
procedure Heatmap(m: Matrix);
|
procedure Heatmap(m: Matrix);
|
||||||
|
|
@ -1319,16 +1317,6 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{procedure Cell.Surface(labels: array of integer; nx, ny: integer; xmin, xmax, ymin, ymax: real; pal: PlotML.Palette);
|
|
||||||
begin
|
|
||||||
Plot.RunUI(() ->
|
|
||||||
begin
|
|
||||||
EnsureChart;
|
|
||||||
var usePal := if pal <> nil then pal else palette;
|
|
||||||
Plot.DrawSurface(chart, labels, nx, ny, xmin, xmax, ymin, ymax, usePal);
|
|
||||||
end);
|
|
||||||
end;}
|
|
||||||
|
|
||||||
procedure Cell.Surface(x1, x2: array of real; nx, ny: integer; f: Matrix -> array of integer; pal: PlotML.Palette);
|
procedure Cell.Surface(x1, x2: array of real; nx, ny: integer; f: Matrix -> array of integer; pal: PlotML.Palette);
|
||||||
begin
|
begin
|
||||||
Plot.RunUI(() ->
|
Plot.RunUI(() ->
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,8 @@ type
|
||||||
X: Matrix; y: Vector;
|
X: Matrix; y: Vector;
|
||||||
k: integer;
|
k: integer;
|
||||||
metric: (Vector, Vector) -> real;
|
metric: (Vector, Vector) -> real;
|
||||||
maximize: boolean := True
|
maximize: boolean := True;
|
||||||
|
seed: integer := -1
|
||||||
): (real, real, T); where T: class,ISupervisedModel;
|
): (real, real, T); where T: class,ISupervisedModel;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -447,7 +448,8 @@ class function GridSearch.Search<T>(
|
||||||
y: Vector;
|
y: Vector;
|
||||||
k: integer;
|
k: integer;
|
||||||
metric: (Vector, Vector) -> real;
|
metric: (Vector, Vector) -> real;
|
||||||
maximize: boolean
|
maximize: boolean;
|
||||||
|
seed: integer
|
||||||
): (real, real, T); where T: class,ISupervisedModel;
|
): (real, real, T); where T: class,ISupervisedModel;
|
||||||
begin
|
begin
|
||||||
if modelFactory = nil then
|
if modelFactory = nil then
|
||||||
|
|
@ -480,7 +482,7 @@ begin
|
||||||
var model := modelFactory(param);
|
var model := modelFactory(param);
|
||||||
if model = nil then
|
if model = nil then
|
||||||
ArgumentError(ER_MODEL_NULL);
|
ArgumentError(ER_MODEL_NULL);
|
||||||
var avgScore := Validation.CrossValidate(model, X, y, k, metric);
|
var avgScore := Validation.CrossValidate(model, X, y, k, metric, seed);
|
||||||
|
|
||||||
if double.IsNaN(avgScore) or double.IsInfinity(avgScore) then
|
if double.IsNaN(avgScore) or double.IsInfinity(avgScore) then
|
||||||
ArgumentError(ER_INVALID_VALUE, 'avgScore');
|
ArgumentError(ER_INVALID_VALUE, 'avgScore');
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue