Skip to content

Commit

Permalink
First test for a multithreaded svm learner
Browse files Browse the repository at this point in the history
  • Loading branch information
mikerabat committed Jan 26, 2022
1 parent 1cfc94e commit 9f2dff5
Showing 1 changed file with 35 additions and 9 deletions.
44 changes: 35 additions & 9 deletions SimpleClassifier/SVM.pas
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ TSVMLearner = class(TCustomWeightedLearner)

faStar : IMatrix;
fBias : IMatrix;
fMtxClass : TMatrixClass;

fVectIdx : TIntegerDynArray;

Expand All @@ -117,18 +118,23 @@ TSVMLearner = class(TCustomWeightedLearner)
// todo: add support for weighted learning
function DoLearn(const weights : Array of double) : TCustomClassifier; override;
public
class var Threaded : boolean;

property Margin : double read GetMargin; // just a property

procedure AfterConstruction; override;

procedure SetProps(const Props : TSVMProps);

class function CanLearnClassifier(Classifier : TCustomClassifierClass) : boolean; override;

constructor Create;
destructor Destroy; override;
end;

implementation

uses BaseMatrixExamples, MatrixConst, MathUtilFunc, math;
uses BaseMatrixExamples, MatrixConst, MathUtilFunc, math, ThreadedMatrix;

procedure TanhFunc(var value : double);
begin
Expand Down Expand Up @@ -162,15 +168,14 @@ function TSVMLearner.TrainSet(doAugment : boolean): IMatrix;
if doAugment then
augsize := 1;

Result := TDoubleMatrix.Create(DataSet.Count, DataSet.Example[0].FeatureVec.FeatureVecLen + augsize, 1);
Result := fMtxClass.MatrixClass.Create(DataSet.Count, DataSet.Example[0].FeatureVec.FeatureVecLen + augsize, 1);

if DataSet is TMatrixLearnerExampleList
then
Result.AssignSubMatrix(TMatrixLearnerExampleList(DataSet).Matrix, 0, 0)
else
begin
// Create a matrix of the feature vectors -> this classifier only understands matrices
Result := TDoubleMatrix.Create(DataSet.Count, DataSet[0].FeatureVec.FeatureVecLen);
for y := 0 to DataSet[0].FeatureVec.FeatureVecLen - 1 do
for x := 0 to DataSet.Count - 1 do
Result[x, y] := DataSet[x].FeatureVec[y];
Expand All @@ -183,6 +188,20 @@ class function TSVMLearner.CanLearnClassifier(
Result := Classifier = TSVMClassifier;
end;

constructor TSVMLearner.Create;
begin
inherited;

fMtxClass := TMatrixClass.Create;
end;

destructor TSVMLearner.Destroy;
begin
fMtxClass.Free;

inherited;
end;

function TSVMLearner.DoLearn(const weights : Array of double): TCustomClassifier;
var augExmpl : IMatrix;
y : IMatrix;
Expand All @@ -198,6 +217,12 @@ function TSVMLearner.DoLearn(const weights : Array of double): TCustomClassifier

//fDists : TDoubleDynArray;
begin
if Threaded
then
fMtxClass.MatrixClass := TThreadedMatrix
else
fMtxClass.MatrixClass := TDoubleMatrix;

numCl := IndexOfClasses(idx, cl);
if numCl <> 2 then
raise ESVMClassException.Create('Error only 2 class problems are supported');
Expand Down Expand Up @@ -230,7 +255,7 @@ function TSVMLearner.DoLearn(const weights : Array of double): TCustomClassifier
scaleFact[0, counter] := 1;
end;

ones := TDoubleMatrix.Create(scaleFact.Width, scaleFact.Height, 1);
ones := fMtxClass.MatrixClass.Create(scaleFact.Width, scaleFact.Height, 1);
scaleFact := ones.ElementWiseDiv(scaleFact);

// now scale the examples!
Expand Down Expand Up @@ -269,7 +294,7 @@ function TSVMLearner.DoLearn(const weights : Array of double): TCustomClassifier
end;

faStar.UseFullMatrix;
if Length(fVectIdx) < faStar.Height then
if (Length(fVectIdx) < faStar.Height) or Threaded then
begin
faStar.SetSubMatrix(0, 0, 1, Length(fVectIdx));
tmp := TDoubleMatrix.Create;
Expand Down Expand Up @@ -437,7 +462,7 @@ procedure TSVMLearner.LearnLeastSquares(y: IMatrix);
gIdx := nil;

// create augmented matrix A
A := TDoubleMatrix.Create(DataSet.Count + 1, DataSet.Count + 1);
A := fMtxClass.MatrixClass.Create(DataSet.Count + 1, DataSet.Count + 1);
A.SetSubMatrix(1, 0, Length(grIndex), 1);
A.SetRow(0, grIndex);
A.SetSubMatrix(0, 1, 1, Length(grIndex));
Expand Down Expand Up @@ -479,7 +504,7 @@ function TSVMLearner.PolyKernelData(augTrainSet : IMatrix): IMatrix;
if fProps.kernelType = svmPolyInhomogen then
dotproduct.AddInplace(1);

Result := TDoubleMatrix.Create;
Result := fMtxClass.MatrixClass.Create;
Result.Assign(dotproduct);

for x := 1 to fProps.order - 1 do
Expand All @@ -491,7 +516,7 @@ function TSVMLearner.SigmoidKernelData(augTrainSet: IMatrix): IMatrix;
tTrainSet : IMatrix;
col : IMatrix;
begin
Result := TDoubleMatrix.Create(augTrainSet.Width, augTrainSet.Width);
Result := fMtxClass.MatrixClass.Create(augTrainSet.Width, augTrainSet.Width);
tTrainSet := augTrainSet.Transpose;

for x := 0 to Result.Height - 1 do
Expand All @@ -514,7 +539,7 @@ function TSVMLearner.GaussKernelData(augTrainSet: IMatrix): IMatrix;
xi, sum : IMatrix;
val : double;
begin
Result := TDoubleMatrix.Create(augTrainSet.Width, augTrainSet.Width);
Result := fMtxClass.MatrixClass.Create(augTrainSet.Width, augTrainSet.Width);

// y(:,i) = exp(-sum((train_patterns-train_patterns(:,i)*ones(1,Nf)).^2)'/(2*ker_param^2));
// according to wikipedia k(xi, xj) = exp(-s * ||xi - xj]]^2) s = 1/(2*sigma^2);
Expand Down Expand Up @@ -1008,5 +1033,6 @@ procedure TSVMLearner.SigmoidTraining(cl: TSVMClassifier; var confA, confB: doub

initialization
RegisterMathIO(TSVMClassifier);
TSVMLearner.Threaded := False;

end.

0 comments on commit 9f2dff5

Please sign in to comment.