1

我有以下关于神经网络类的草稿。这个神经网络应该用 TD-lambda 学习。它通过调用 getRating() 函数启动。

但不幸的是,在以下几行中大约 1000 次迭代后,出现了 EInvalidOp(无效的加载点操作)错误:

neuronsHidden[j] := neuronsHidden[j]+neuronsInput[t][i]*weightsInput[i][j]; // input -> hidden

weightsHidden[j][k] := weightsHidden[j][k]+LEARNING_RATE_HIDDEN*tdError[k]*eligibilityTraceOutput[j][k]; // adjust hidden->output weights according to TD-lambda

为什么会出现这个错误?我在我的代码中找不到错误:(你能帮我吗?非常感谢你提前!

learningMode: Boolean; // does the network learn and change its weights?
neuronsInput: Array[1..MAX_TIMESTEPS] of Array[1..NEURONS_INPUT] of Extended;
neuronsHidden: Array[1..NEURONS_HIDDEN] of Extended;
neuronsOutput: Array[1..NEURONS_OUTPUT] of Extended;
weightsInput: Array[1..NEURONS_INPUT] of Array[1..NEURONS_HIDDEN] of Extended;
weightsHidden: Array[1..NEURONS_HIDDEN] of Array[1..NEURONS_OUTPUT] of Extended;

[...]

function HyperbolicTangent;
begin
  if x > 5500 then // prevent overflow
    result := 1
  else
    result := (Exp(2*x)-1)/(Exp(2*x)+1);
end;
[...]
4

3 回答 3

2

不是答案,只是建议;您显示的两行代码仅包括乘法和加法,非常简单的操作。记录失败的值怎么样,也许看到你可以弄清楚的值。

停止异常最烦人的问题是您无法检查该异常中涉及的变量。为了解决这个限制,我有时将麻烦的操作包装在一个try-except块中,并在处理程序中放置一个断点except;Delphi 将首先在异常处停止,我点击运行,然后它在我的断点处停止。在断点处,我可以自由地检查错误生成语句中使用的所有变量,以便找出问题所在。

// In place of:
neuronsHidden[j] := neuronsHidden[j]+neuronsInput[t][i]*weightsInput[i][j];

var saveNerusonsHidden: Double;
try
  saveNeuronsHidden := neuronsHidden[j]; // saved, to be sure I can inspect the original value
  neuronsHidden[j] := neuronsHidden[j]+neuronsInput[t][i]*weightsInput[i][j];
except on E:EInvalidOp do
  begin
    // Breakpoint here, so you can inspect the values of neuronsInput[t][i], wightsInput[i][j] and saveNeuronsHidden
    raise;
  end;
end;
于 2011-02-17T07:10:42.517 回答
1

您出错的最可能原因是您溢出了累加器neuronsHiddenweightsHidden. 我对神经网络一无所知,所以我无法解释为什么会这样。

作为一个附带问题,我质疑Extended浮点变量的使用。通常这只会导致性能极慢,比使用Double. 您可能认为它为大量数字提供了更多空间,但实际上,如果这是我怀疑的本性失控溢出,那么使用Extended将永远无法拯救您。

UPDATE OP 指出溢出会导致不同的异常类。所以EInvalidOp我怀疑一些平方根或三角失败或类似的东西。或者可能是一个信号 NaN,但由于您显然没有使用未初始化的数据,我不会相信这一点。

我现在可以看到,您已受到 Embarcadero 打破其实施的奇怪决定的影响Tanh。这曾经在旧版本的 Delphi(例如 D6)上完美运行,但最近被破坏了。您使用的版本不太适合大的负输入,并且Exp在一个就足够时使用两个调用。我使用这个版本:

const
  MaxTanhDomain = 5678.22249441322; // Ln(MaxExtended)/2

function Tanh(const X: Extended): Extended;
begin
  if X>MaxTanhDomain then begin
    Result := 1.0
  end else if X<-MaxTanhDomain then begin
    Result := -1.0
  end else begin
    Result := Exp(X);
    Result := Result*Result;
    Result := (Result-1.0)/(Result+1.0);
  end;
end;
于 2011-02-16T06:48:50.597 回答
0

当计算非常大或非常小的数字时,您可以获得 EInvalidOp。

收到此错误时,也许您可​​以调试/查看数组中的值并在监视列表中进行部分计算?

于 2011-02-16T07:21:32.227 回答