`
sogotobj
  • 浏览: 615851 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Delphi版的线性回归分析

阅读更多

文章《C语言版的线性回归分析函数》发布后,不少朋友留言或给我来信,询问能否提供Delphi版的线性回归分析代码,因C语言版是我以前DOS下的老代码稍作整理后发布的,所以没有现成的Delphi代码,今天比较闲,于是将C代码改写为Delphi代码贴在下面,有关的回归公式说明及例子图示可参见《C语言版的线性回归分析函数》,这里不再累叙,由于改写时间仓促,可能有错误,请不吝指出,亦可来信建议:maozefa@hotmail.com

线性回归分析代码:

unitRegression;

interface

usesSysUtils;

type
PEquationsData
=^TEquationsData;
TEquationsData
=array[0..0]ofDouble;
//线性回归
TLinearRegression=class(TObject)
private
FData:PEquationsData;
FAnswer:PEquationsData;
FSquareSum:Double;
FSurplusSum:Double;
FRowCount:Integer;
FColCount:Integer;
FModify:Boolean;
functionGetAnswer(Index:Integer):Double;
functionGetItem(ARow,ACol:Integer):Double;
procedureSetItem(ARow,ACol:Integer;
constValue:Double);
procedureSetColCount(
constValue:Integer);
procedureSetRowCount(
constValue:Integer);
procedureSetSize(
constARowCount,AColCount:Integer);
procedureSetModify(
constValue:Boolean);
functionGetCorrelation:Double;
functionGetDeviatSum:Double;
functionGetFTest:Double;
functionGetSurplus:Double;
functionGetVariance:Double;
functionGetStandardDiffer:Double;
functionGetEstimate(ARow:Integer):Double;
public
constructorCreate(
constAData;constARowCount,AColCount:Integer);overload;
destructorDestroy;
override;
//计算回归方程
procedureCalculation;
//设置回归数据
//AData[ARowCount*AColCount]二维数组;X1i,X2i,...Xni,Yi(i=0toARowCount-1)
//ARowCount:数据行数;AColCount数据列数
procedureSetData(constAData;constARowCount,AColCount:Integer);
//数据列数(自变量个数+Y)
propertyColCount:IntegerreadFColCountwriteSetColCount;
//数据行数
propertyRowCount:IntegerreadFRowCountwriteSetRowCount;
//原始数据
propertyData[ARow,ACol:Integer]:DoublereadGetItemwriteSetItem;default;
propertyModify:BooleanreadFModify;
//回归系数数组(B0,B1...Bn)
propertyAnswer[Index:Integer]:DoublereadGetAnswer;
//Y估计值
propertyEstimate[ARow:Integer]:DoublereadGetEstimate;
//回归平方和
propertyRegresSquareSum:DoublereadFSquareSum;
//剩余平方和
propertySurplusSquareSum:DoublereadFSurplusSum;
//离差平方和
propertyDeviatSquareSum:DoublereadGetDeviatSum;
//回归方差
propertyRegresVariance:DoublereadGetVariance;
//剩余方差
propertySurplusVariance:DoublereadGetSurplus;
//标准误差
propertyStandardDiffer:DoublereadGetStandardDiffer;
//相关系数
propertyCorrelation:DoublereadGetCorrelation;
//F检验
propertyF_Test:DoublereadGetFTest;
end;

//解线性方程。AData[count*(count+1)]矩阵数组;count:方程元数;
//Answer[count]:求解数组。返回:True求解成功,否则无解或者无穷解
functionLinearEquations(constAData;Count:Integer;varAnswer:arrayofDouble):Boolean;

implementation

const
SMatrixSizeError
='Regressiondatamatrixcannotbelessthan2*2';
SIndexOutOfRange
='indexoutofrange';
SEquationNoSolution
='EquationnosolutionorInfiniteSolutions';

functionLinearEquations(
constAData;Count:Integer;varAnswer:arrayofDouble):Boolean;
var
j,m,n,ColCount:Integer;
tmp:Double;
Data,d:PEquationsData;
begin
Result:
=False;
ifCount<2thenExit;

ColCount:
=Count+1;
GetMem(Data,Count
*ColCount*Sizeof(Double));
GetMem(d,ColCount
*Sizeof(Double));
try
Move(AData,Data
^,Count*ColCount*Sizeof(Double));
form:=0toCount-2do
begin
n:
=m+1;
//如果主对角线元素为0,行交换
while(n<Count)and(Data^[m*ColCount+m]=0.0)do
begin
ifData^[n*ColCount+m]<>0.0then
begin
Move(Data
^[m*ColCount+m],d^,ColCount*Sizeof(Double));
Move(Data
^[n*ColCount+m],Data^[m*ColCount+m],ColCount*Sizeof(Double));
Move(d
^,Data^[n*ColCount+m],ColCount*Sizeof(Double));
end;
Inc(n);
end;
//行交换后,主对角线元素仍然为0,无解
ifData^[m*ColCount+m]=0.0thenExit;
//消元
forn:=m+1toCount-1do
begin
tmp:
=Data^[n*ColCount+m]/Data^[m*ColCount+m];
forj:=mtoCountdo
Data
^[n*ColCount+j]:=Data^[n*ColCount+j]-tmp*Data^[m*ColCount+j];
end;
end;
FillChar(d
^,Count*Sizeof(Double),0);
//求得count-1的元
Answer[Count-1]:=Data^[(Count-1)*ColCount+Count]/
Data
^[(Count-1)*ColCount+Count-1];
//逐行代入求各元
form:=Count-2downto0do
begin
forj:=Count-1downtom+1do
d
^[m]:=d^[m]+Answer[j]*Data^[m*ColCount+j];
Answer[m]:
=(Data^[m*ColCount+Count]-d^[m])/Data^[m*ColCount+m];
end;
Result:
=True;
finally
FreeMem(d);
FreeMem(Data);
end;
end;

{TLinearRegression}

procedureTLinearRegression.Calculation;
var
m,n,i,count:Integer;
dat:PEquationsData;
a,b,d:Double;
begin
if(FRowCount<2)or(FColCount<2)then
raiseException.Create(SMatrixSizeError);
ifnotFModifythenExit;
GetMem(dat,FColCount
*(FColCount+1)*Sizeof(Double));
try
count:
=FColCount-1;
dat
^[0]:=FRowCount;
forn:=0tocount-1do
begin
a:
=0.0;
b:
=0.0;
form:=0toFRowCount-1do
begin
d:
=FData^[m*FColCount+n];
a:
=a+d;
b:
=b+d*d;
end;
dat
^[n+1]:=a;
dat
^[(n+1)*(FColCount+1)]:=a;
dat
^[(n+1)*(FColCount+1)+n+1]:=b;
fori:=n+1tocount-1do
begin
a:
=0.0;
form:=0toFRowCount-1do
a:
=a+FData^[m*FColCount+n]*FData^[m*FColCount+i];
dat
^[(n+1)*(FColCount+1)+i+1]:=a;
dat
^[(i+1)*(FColCount+1)+n+1]:=a;
end;
end;
b:
=0.0;
form:=0toFRowCount-1do
b:
=b+FData^[m*FColCount+count];
dat
^[FColCount]:=b;
forn:=0tocount-1do
begin
a:
=0.0;
form:=0toFRowCount-1do
a:
=a+FData^[m*FColCount+n]*FData^[m*FColCount+count];
dat
^[(n+1)*(FColCount+1)+FColCount]:=a;
end;
ifnotLinearEquations(dat^,FColCount,FAnswer^)then
raiseException.Create(SEquationNoSolution);
FSquareSum:
=0.0;
FSurplusSum:
=0.0;
b:
=b/FRowCount;
form:=0toFRowCount-1do
begin
a:
=FAnswer^[0];
fori:=1tocountdo
a:
=a+FData^[m*FColCount+i-1]*FAnswer[i];
FSquareSum:
=FSquareSum+(a-b)*(a-b);
d:
=FData^[m*FColCount+count];
FSurplusSum:
=FSurplusSum+(d-a)*(d-a);
end;
SetModify(False);
finally
FreeMem(dat);
end;
end;

constructorTLinearRegression.Create(
constAData;constARowCount,
AColCount:Integer);
begin
SetData(AData,ARowCount,AColCount);
end;

destructorTLinearRegression.Destroy;
begin
SetSize(
0,0);
end;

functionTLinearRegression.GetAnswer(Index:Integer):Double;
begin
if(Index<0)or(Index>=FColCount)then
raiseException.Create(SIndexOutOfRange);
ifnotAssigned(FAnswer)then
Result:
=0.0
else
Result:
=FAnswer^[Index];
end;

functionTLinearRegression.GetCorrelation:Double;
begin
Result:
=DeviatSquareSum;
ifResult<>0.0then
Result:
=Sqrt(FSquareSum/Result);
end;

functionTLinearRegression.GetDeviatSum:Double;
begin
Result:
=FSquareSum+FSurplusSum;
end;

functionTLinearRegression.GetEstimate(ARow:Integer):Double;
var
I:Integer;
begin
if(ARow<0)or(ARow>=FRowCount)then
raiseException.Create(SIndexOutOfRange);
Result:
=Answer[0];
forI:=1toColCount-1do
Result:
=Result+FData^[ARow*FColCount+I-1]*Answer[I];
end;

functionTLinearRegression.GetFTest:Double;
begin
Result:
=SurplusVariance;
ifResult<>0.0then
Result:
=RegresVariance/Result;
end;

functionTLinearRegression.GetItem(ARow,ACol:Integer):Double;
begin
if(ARow<0)or(ARow>=FRowCount)or(ACol<0)or(ACol>=FColCount)then
raiseException.Create(SIndexOutOfRange);
Result:
=FData^[ARow*FColCount+ACol];
end;

functionTLinearRegression.GetStandardDiffer:Double;
begin
Result:
=Sqrt(SurplusVariance);
end;

functionTLinearRegression.GetSurplus:Double;
begin
ifFRowCount-FColCount<1then
Result:
=0.0
else
Result:
=FSurplusSum/(FRowCount-FColCount);
end;

functionTLinearRegression.GetVariance:Double;
begin
ifFColCount<2then
Result:
=0.0
else
Result:
=FSquareSum/(FColCount-1);
end;

procedureTLinearRegression.SetColCount(
constValue:Integer);
begin
ifValue<2then
raiseException.Create(SMatrixSizeError);
SetSize(FRowCount,Value);
end;

procedureTLinearRegression.SetData(
constAData;constARowCount,AColCount:Integer);
begin
if(ARowCount<2)or(AColCount<2)then
raiseException.Create(SMatrixSizeError);
SetSize(ARowCount,AColCount);
Move(AData,FData
^,FRowCount*FColCount*Sizeof(Double));
end;

procedureTLinearRegression.SetItem(ARow,ACol:Integer;
constValue:Double);
begin
if(ARow<0)or(ARow>=FRowCount)or(ACol<0)or(ACol>=FColCount)then
raiseException.Create(SIndexOutOfRange);
ifFData^[ARow*(FColCount)+ACol]<>Valuethen
begin
FData
^[ARow*(FColCount)+ACol]:=Value;
SetModify(True);
end;
end;

procedureTLinearRegression.SetModify(
constValue:Boolean);
begin
ifFModify<>Valuethen
begin
FModify:
=Value;
ifFModifythen
begin
FillChar(FAnswer
^,FColCount*Sizeof(Double),0);
FSquareSum:
=0.0;
FSurplusSum:
=0.0;
end;
end;
end;

procedureTLinearRegression.SetRowCount(
constValue:Integer);
begin
ifValue<2then
raiseException.Create(SMatrixSizeError);
SetSize(Value,FColCount);
end;

procedureTLinearRegression.SetSize(
constARowCount,AColCount:Integer);
begin
if(FRowCount=ARowCount)and(FColCount=AColCount)then
Exit;
ifAssigned(FData)then
begin
FreeMem(FData);
FData:
=nil;
FreeMem(FAnswer);
FAnswer:
=nil;
FModify:
=False;
end;

FRowCount:
=ARowCount;
FColCount:
=AColCount;

if(FRowCount=0)or(FColCount=0)thenExit;

GetMem(FData,FRowCount
*FColCount*Sizeof(Double));
FillChar(FData
^,FRowCount*FColCount*Sizeof(Double),0);
GetMem(FAnswer,FColCount
*Sizeof(Double));
SetModify(True);
end;

end.

因为一元线性回归分析本是多元线性回归分析的一个特例,因此原C代码中的一元线性回归函数取消,一元线性回归和多元线性回归都使用TLinearRegression类。下面是Pascal控制台应用程序例子:

programLinearRegression;

{$APPTYPECONSOLE}

uses
SysUtils,
Regression
in'....pasRegression.pas';

const
data1:array[
1..12,1..2]ofDouble=(
//XY
(187.1,25.4),
(
179.5,22.8),
(
157.0,20.6),
(
197.0,21.8),
(
239.4,32.4),
(
217.8,24.4),
(
227.1,29.3),
(
233.4,27.9),
(
242.0,27.8),
(
251.9,34.2),
(
230.0,29.2),
(
271.8,30.0)
);

data:array[
1..15,1..5]ofDouble=(
//X1X2X3X4Y
(316,1536,874,981,3894),
(
385,1771,777,1386,4628),
(
299,1565,678,1672,4569),
(
326,1970,785,1864,5340),
(
441,1890,785,2143,5449),
(
460,2050,709,2176,5599),
(
470,1873,673,1769,5010),
(
504,1955,793,2207,5694),
(
348,2016,968,2251,5792),
(
400,2199,944,2390,6126),
(
496,1328,749,2287,5025),
(
497,1920,952,2388,5924),
(
533,1400,1452,2093,5657),
(
506,1612,1587,2083,6019),
(
458,1613,1485,2390,6141)
);

procedureDisplay(s:
string;R:TLinearRegression);
var
i:Integer;
v,o:Double;
begin
Writeln(s);
Writeln(
'回归方程式:');
Write(
'Y=',R.Answer[0]:1:5);
fori:=1toR.ColCount-1do
Write(
'+',R.Answer[i]:1:5,'*X',i);
Writeln;
Writeln(
'回归显著性检验:');
Writeln(
'回归平方和:',R.RegresSquareSum:12:4,'回归方差:',R.RegresVariance:12:4);
Writeln(
'剩余平方和:'<span
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics