Delphi-列表索引超出范围(4) [英] Delphi - List Index Out Of Bounds(4)
问题描述
我知道这个问题已经提出了一百万次了,但是,我不明白为什么这段代码会引发错误,我已经找到了导致该错误的元凶FOR循环,但是,我没有发现任何错误
I know this question has been brought up a million times, however, I cant understand why this code is throwing the error, I have tracked down the culprit FOR loop causing the error, however, I don't see anything wrong with it.
我遇到了错误-列表索引超出范围(4)
I'm getting the error - "List Index Out Of Bounds(4)"
function TNetwork.FeedForward(InputVals : array of Real) : Real;
var
I : Integer;
begin
for I := 0 to Length(InputVals)-1 do
begin
Input[I].Input(InputVals[I]);
end;
for I := 0 to Length(Hidden)-1 do
begin
Hidden[I].CalcOutput;
end;
Output.CalcOutput;
Result := Output.GetOutput;
end;
该错误发生在第二个For循环中,在这里设置隐藏数组的大小。
The error occurs on the second For Loop, here is where I set the size of the hidden array.
constructor TNetwork.Create(Inputs, HiddenTotal : Integer);
var
C : TConnection;
I, J : Integer;
begin
LEARNING_CONSTANT := 0.5;
SetLength(Input,Inputs+1);
SetLength(Hidden,HiddenTotal+1);
所以,正如我所看到的,循环只执行三次,所以为什么要尝试索引第四空间?没关系,为什么,更重要的是,为什么?
So, as I see it, the loop executes only three times, so why is it trying to index the 4th space? never mind why, more importantly, HOW?
如果有人可以阐明原因,并找到可能的解决办法,我将不胜感激
If someone could shed some light on the cause, and a possible fix, I would be ever grateful
为完成起见,这里是完整的单位。
For completion's sake, here is the complete unit..
unit NeuralNetwork_u;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, Math;
type
TConnection = Class;
TNeuron = class(TObject)
protected
Output : Real;
Connections : TList;
isBias : Boolean;
public
Constructor Create; overload;
Constructor Create(BiasValue : Integer); overload;
procedure CalcOutput;
procedure AddConnection( Con : TConnection );
function GetOutput : Real;
Function F( X : Real ) : Real;
end;
TConnection = class
private
nFrom, nTo : TNeuron;
Weight : Real;
public
constructor Create(a , b : TNeuron) ; overload;
constructor Create(a, b : TNeuron ; W : Real) ; overload;
function GetFrom : TNeuron;
function GetTo : TNeuron;
function GetWeight : Real;
procedure AdjustWeight(DeltaWeight : Real);
end;
type TInputNeuron = class(TNeuron)
public
procedure Input (D : Real);
end;
type THiddenNeuron = class(TNeuron)
private
public
end;
type TOutputNeuron = Class(TNeuron)
private
public
end;
type TNetwork = class(TObject)
private
LEARNING_CONSTANT : Real;
public
Input : array of TInputNeuron;
Hidden : array of THiddenNeuron;
Output : TOutputNeuron;
constructor Create(Inputs,HiddenTotal : Integer);
function FeedForward(InputVals : array of Real) : Real;
function Train(Inputs : array of Real ; Answer : Real) : Real;
function TrainOnFile(Epochs : Integer ; TrainingFile : String) : Real;
end;
implementation
constructor TNeuron.Create;
begin
Output := 0;
Connections := TList.Create;
isBias := False;
end;
Constructor TNeuron.Create(BiasValue : Integer);
begin
Output := BiasValue;
Connections := TList.Create;
isBias := True;
end;
procedure TNeuron.CalcOutput;
var
Sum : Real;
Bias : Real;
C : TConnection ;
NeuronFrom, NeuronTo : TNeuron;
I : Integer;
begin
if isBias then
else
begin
Sum := 0;
Bias := 0;
for I := 0 to Connections.Count do
begin
C := Connections[I];
NeuronFrom := C.GetFrom;
NeuronTo := C.GetTo;
if NeuronTo = self then
begin
if NeuronFrom.isBias then
begin
Bias := NeuronFrom.GetOutput * C.GetWeight;
end
else
begin
Sum := Sum + NeuronFrom.GetOutput * C.GetWeight;
end;
end;
end;
Output := F(Bias + Sum);
end;
end;
procedure TNeuron.AddConnection(Con : TConnection);
begin
Connections.Add(Con) ;
end;
function TNeuron.GetOutput : Real;
begin
Result := Output;
end;
function TNeuron.F( X : Real ) : Real;
begin
Result := 1.0 /(1.0 + Exp(-X));
end;
procedure TInputNeuron.Input ( D : Real);
begin
Output := D;
end;
constructor TConnection.Create(a, b : TNeuron);
begin
nFrom := a;
nTo := b;
Weight := Random * 2 - 1;
end;
constructor TConnection.Create(a, b : TNeuron ; w : Real);
begin
nFrom := a;
nTo := b;
Weight := w;
end;
function TConnection.GetFrom : TNeuron;
begin
Result := nFrom;
end;
function TConnection.GetTo : TNeuron;
begin
Result := nTo;
end;
function TConnection.GetWeight;
begin
Result := Weight;
end;
procedure Tconnection.AdjustWeight(DeltaWeight : Real);
begin
Weight := Weight + DeltaWeight;
end;
constructor TNetwork.Create(Inputs, HiddenTotal : Integer);
var
C : TConnection;
I, J : Integer;
begin
LEARNING_CONSTANT := 0.5;
SetLength(Input,Inputs+1);
SetLength(Hidden,HiddenTotal+1);
for I := 0 to Length(Input)-1 do
begin
Input[I] := TInputNeuron.Create;
end;
for I := 0 to Length(Hidden)-1 do
begin
Hidden[I] := THiddenNeuron.Create;
end;
Input[Length(Input)-1] := TInputNeuron.Create(1);
Hidden[Length(Hidden)-1] := THiddenNeuron.Create(1);
Output := TOutputNeuron.Create;
for I := 0 to Length(Input)-1 do
begin
for J := 0 to Length(Hidden)-1 do
begin
C := TConnection.Create(Input[I],Hidden[J]);
Input[I].AddConnection(C);
Hidden[J].AddConnection(C);
end;
end;
for I := 0 to Length(Hidden)-1 do
begin
C := TConnection.Create(Hidden[I],Output);
Hidden[I].AddConnection(C);
Output.AddConnection(C);
end;
end;
function TNetwork.FeedForward(InputVals : array of Real) : Real;
var
I : Integer;
begin
for I := 0 to Length(InputVals)-1 do
begin
Input[I].Input(InputVals[I]);
end;
for I := 0 to Length(Hidden)-1 do
begin
Hidden[I].CalcOutput;
end;
Output.CalcOutput;
Result := Output.GetOutput;
end;
function TNetwork.Train(Inputs : array of Real ; Answer : Real) : Real;
var
rResult : Real;
deltaOutput, rOutput, deltaWeight, Sum, deltaHidden : Real;
Connections : TList;
C : TConnection;
Neuron : TNeuron;
I, J : Integer;
begin
rResult := FeedForward(Inputs);
deltaOutput := rResult * (1 - rResult) * (Answer - rResult);
Connections := Output.Connections;
for I := 0 to Connections.Count do
begin
C := Connections[I];
Neuron := C.GetFrom;
rOutput := Neuron.Output;
deltaWeight := rOutput * deltaOutput;
C.AdjustWeight(LEARNING_CONSTANT * deltaWeight);
end;
for I := 0 to Length(Hidden) do
begin
Connections := Hidden[I].Connections;
Sum := 0;
for J := 0 to Connections.Count do
begin
C := Connections[J];
if c.GetFrom = Hidden[I] then
begin
Sum := Sum + (C.GetWeight * deltaOutput);
end;
end;
for J := 0 to Connections.Count do
begin
C := Connections[I];
if C.GetTo = Hidden[I] then
begin
rOutput := Hidden[I].GetOutput;
deltaHidden := rOutput * ( 1 - rOutput);
deltaHidden := deltaHidden * Sum;
Neuron := C.GetFrom;
deltaWeight := Neuron.GetOutput * deltaHidden;
C.AdjustWeight(LEARNING_CONSTANT * deltaWeight);
end;
end;
end;
Result := rResult;
end;
function TNetwork.TrainOnFile(Epochs : Integer ; TrainingFile : string) : Real;
var
FileT : TStringList;
Inputss : array of Real;
Outputss : Real;
I, C : Integer;
sTemp : String;
NumInputs, NumOutputs : Integer;
begin
// Load File
FileT := TStringList.Create;
try
FileT.LoadFromFile(TrainingFile);
except
raise Exception.Create('Training File Does Not Exist');
end;
for I := 0 to FileT.Count-1 do
begin
sTemp := FileT[I];
if I = 0 then
begin
// get Configurators
Delete(sTemp,1,Pos(' ',stemp)); // no Longer need training Set count
NumInputs := StrToInt(Copy(sTemp,1,Pos(' ',sTemp)-1));
Delete(sTemp,1,Pos(' ',sTemp));
NumOutputs := StrToInt(Copy(sTemp,1,Length(sTemp)));
SetLength(Inputss,NumInputs+1);
end
else
begin
for C := 0 to NumInputs-1 do
begin
Inputss[C] := StrToFloat(Copy(sTemp,1,Pos(' ',sTemp)-1));
Delete(sTemp,1,Pos(' ',sTemp));
end;
Outputss := StrToFloat(Copy(sTemp,1,Length(sTemp)));
Train(Inputss,Outputss);
end;
end;
end;
end.
推荐答案
for I := 0 to Connections.Count do
您在这里结束了列表的结尾。有效索引是 0
到 Connections.Count-1
的索引。你走得太远了。
You run off the end of the list here. Valid indices are 0
to Connections.Count-1
inclusive. You go one too far.
您反复犯此错误。当然,您需要在任何地方修复它。
You make this mistake repeatedly. You need to fix it everywhere, of course.
对列表索引越界错误> TList
或 TStringList
。
The list index out of bounds error is generally seen when you perform an out of bounds access of a collection class like TList
or TStringList
.
另一方面,除非启用了范围检查,否则数组边界错误是无法预测的。如果这样做并且应该这样做,那么您会收到此类事件的运行时错误。您需要启用范围检查。
On the other hand, array bounds errors are unpredictable unless you have enabled range checking. If you do that, and you should, then you get a runtime error for such events. You'll want to enable range checking.
这篇关于Delphi-列表索引超出范围(4)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!