1. Regresja liniowa
W niniejszym rozdziale przedstawiono implementację prostej i wielorakiej regresji liniowej w Delphi Object Pascalu.
Prosta regresja liniowa
Pełny kod znajduje się na GitHub.
program SimpleLinearRegression;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows;
const
{ 1. Set the hyperparameters for the model }
LearningRate: Single = 0.0005;
Iterations: Integer = 35000;
PrintEvery: Integer = 1000;
type
TSample = array[0..1] of Single;
TDataset = array[0..4] of TSample;
var
a, b: Single;
i, j, n: Integer;
error, squaredError, sumErrorValue, sumError, meanSquaredError: Single;
x, y, prediction: Single;
deltaA, deltaB: Single;
const
{ 2. Create dataset }
{ y = -2*x + 120 }
data: TDataset = (
(10, 100),
(20, 80),
(30, 60),
(40, 40),
(50, 20)
);
begin
SetConsoleOutputCP(CP_UTF8);
{ 3. Initialize model parameters }
a := 0;
b := 0;
{ Number of samples }
n := Length(data);
{ 3. Training loop }
for i := 0 to Iterations - 1 do
begin
{ Initialize accumulators for errors }
sumErrorValue := 0;
sumError := 0;
squaredError := 0;
for j := 0 to n - 1 do
begin
x := data[j][0];
y := data[j][1];
{ Prediction and error calculation }
prediction := a * x + b;
error := y - prediction;
{ Accumulate squared error and gradients }
squaredError := squaredError + error * error;
sumErrorValue := sumErrorValue + error * x;
sumError := sumError + error;
end;
deltaA := -2.0 / n * sumErrorValue;
deltaB := -2.0 / n * sumError;
{ Update regression parameters }
a := a - LearningRate * deltaA;
b := b - LearningRate * deltaB;
if (i mod PrintEvery = 0) then
begin
meanSquaredError := squaredError / n;
Writeln(Format('Iteration: %5d | MSE: %10.5f | ∂MSE/∂a: %10.4f | ∂MSE/∂b: %10.4f | a: %9.4f | b: %9.4f',
[i, meanSquaredError, deltaA, deltaB, a, b]));
end;
end;
{ 5. Output learned parameters }
Writeln;
Writeln(Format('%-20s a = %9.4f | b = %9.4f', ['Learned parameters:', a, b]));
Writeln(Format('%-20s a = %9.4f | b = %9.4f', ['Expected parameters:', -2.0, 120.0]));
Readln;
end.
Wieloraka regresja liniowa z macierzami
Program główny
Poniższy kod jest portem z C# kodu umieszczonego w rozdziale nt. wielorakiej regresji liniowej. Program oblicza model wielorakiej regresji liniowej z wykorzystaniem rachunku macierzowego.
Pełny kod znajduje się na GitHub.
program MultiLinearRegression;
{$APPTYPE CONSOLE}
uses
SysUtils,
Windows,
Math,
MatrixUtility in 'MatrixUtility.pas';
const
{ 1. Set the hyperparameters for the model }
LearningRate: Single = 0.0005;
Iterations: Integer = 35000;
PrintEvery: Integer = 1000;
type
TSample = array[0..3] of Single; // [x1, x2, x3, y]
TDataset = array[0..4] of TSample;
var
XAnd1, Y, AB, Predictions, Errors, DeltaAB: TMatrix;
i, j, k, n, numCoefficients: Integer;
meanSquaredError, tempSum: Single;
const
{ 2. Create dataset }
{ y = 2*x1 + 3*x2 - 1*x3 + 5 }
data: TDataset = (
(1, 2, 1, 12),
(2, 1, 2, 10),
(3, 3, 1, 19),
(4, 2, 3, 16),
(1, 4, 2, 17)
);
begin
SetConsoleOutputCP(CP_UTF8);
{ Number of samples and coefficients }
n := Length(data);
numCoefficients := Length(data[0]) - 1;
{ Feature matrix XAnd1 with bias term, and target vector Y }
XAnd1 := CreateMatrix(n, numCoefficients + 1);
Y := CreateMatrix(n, 1);
for i := 0 to n - 1 do
begin
for j := 0 to numCoefficients - 1 do
XAnd1[i][j] := data[i][j];
XAnd1[i][numCoefficients] := 1; // Bias term
Y[i][0] := data[i][numCoefficients];
end;
{ 3. Initialize model parameters (a1, a2, a3, b) }
AB := CreateMatrix(numCoefficients + 1, 1);
{ 4. Training loop }
for i := 1 to Iterations do
begin
{ Predictions and errors }
Predictions := MultiplyDot(XAnd1, AB);
Errors := Subtract(Y, Predictions);
{ Gradient calculation: ∂MSE/∂AB = -2/n * X^T * Errors }
DeltaAB := MultiplyScalar(MultiplyDot(Transpose(XAnd1), Errors), -2.0 / n);
{ Update parameters }
AB := Subtract(AB, MultiplyScalar(DeltaAB, LearningRate));
if (i mod PrintEvery = 0) then
begin
{ Mean Squared Error }
meanSquaredError := Mean(PowerMatrix(Errors, 2));
Writeln(Format('Iteration: %6d | MSE: %8.5f | a1: %8.4f | a2: %8.4f | a3: %8.4f | b: %8.4f',
[i, meanSquaredError, AB[0][0], AB[1][0], AB[2][0], AB[3][0]]));
end;
end;
{ 5. Output learned parameters }
Writeln;
Writeln('--- Training Complete (Matrices with Bias) ---');
Writeln(Format('%-20s a1 = %9.4f | a2 = %9.4f | a3 = %9.4f | b = %9.4f',
['Learned parameters:', AB[0][0], AB[1][0], AB[2][0], AB[3][0]]));
Writeln(Format('%-20s a1 = %9.4f | a2 = %9.4f | a3 = %9.4f | b = %9.4f',
['Expected parameters:', 2.0, 3.0, -1.0, 5.0]));
Readln;
end.
Moduł pomocniczy do operacji macierzowych
Kod znajduje się na GitHub.
unit MatrixUtility;
interface
uses
Math;
type
TMatrix = array of array of Single;
{ --- Matrix utility functions --- }
function CreateMatrix(rows, cols: Integer): TMatrix;
function MultiplyDot(const A, B: TMatrix): TMatrix;
function Subtract(const A, B: TMatrix): TMatrix;
function Transpose(const A: TMatrix): TMatrix;
function MultiplyScalar(const A: TMatrix; s: Single): TMatrix;
function PowerMatrix(const A: TMatrix; p: Integer): TMatrix;
function Mean(const A: TMatrix): Single;
implementation
{ --- Matrix utility functions --- }
function CreateMatrix(rows, cols: Integer): TMatrix;
var
rowIndex, rowSize: Integer;
begin
SetLength(Result, rows, cols);
rowSize := cols * SizeOf(Single);
for rowIndex := 0 to rows - 1 do
FillChar(Result[rowIndex][0], rowSize, 0);
end;
function MultiplyDot(const A, B: TMatrix): TMatrix;
var
i, j, k, aRows, aCols, bCols: Integer;
sum: Single;
begin
aRows := Length(A);
aCols := Length(A[0]);
bCols := Length(B[0]);
Result := CreateMatrix(aRows, bCols);
for i := 0 to aRows - 1 do
for j := 0 to bCols - 1 do
begin
sum := 0;
for k := 0 to aCols - 1 do
sum := sum + A[i][k] * B[k][j];
Result[i][j] := sum;
end;
end;
function Subtract(const A, B: TMatrix): TMatrix;
var
i, j, aRows, aCols: Integer;
begin
aRows := Length(A);
aCols := Length(A[0]);
Result := CreateMatrix(aRows, aCols);
for i := 0 to aRows - 1 do
for j := 0 to aCols - 1 do
Result[i][j] := A[i][j] - B[i][j];
end;
function Transpose(const A: TMatrix): TMatrix;
var
i, j, aRows, aCols: Integer;
begin
aRows := Length(A);
aCols := Length(A[0]);
Result := CreateMatrix(aCols, aRows);
for i := 0 to aRows - 1 do
for j := 0 to aCols - 1 do
Result[j][i] := A[i][j];
end;
function MultiplyScalar(const A: TMatrix; s: Single): TMatrix;
var
i, j, aRows, aCols: Integer;
begin
aRows := Length(A);
aCols := Length(A[0]);
Result := CreateMatrix(aRows, aCols);
for i := 0 to aRows - 1 do
for j := 0 to aCols - 1 do
Result[i][j] := A[i][j] * s;
end;
function PowerMatrix(const A: TMatrix; p: Integer): TMatrix;
var
i, j, aRows, aCols: Integer;
begin
aRows := Length(A);
aCols := Length(A[0]);
Result := CreateMatrix(aRows, aCols);
for i := 0 to aRows - 1 do
for j := 0 to aCols - 1 do
Result[i][j] := Power(A[i][j], p);
end;
function Mean(const A: TMatrix): Single;
var
i, j, aRows, aCols: Integer;
sum: Single;
begin
aRows := Length(A);
aCols := Length(A[0]);
sum := 0;
for i := 0 to aRows - 1 do
for j := 0 to aCols - 1 do
sum := sum + A[i][j];
Result := sum / (aRows * aCols);
end;
end.
Created: 2025-06-23
Last modified: 2025-10-31
Title: 1. Regresja liniowa
Tags: [Delphi] [Pascal] [Object Pascal] [Sieci neuronowe] [Regresja liniowa]