Delphi-列表索引超出范围(4) [英] Delphi - List Index Out Of Bounds(4)

查看:111
本文介绍了Delphi-列表索引超出范围(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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆