您好,我一直在将Karpathy's ReinforceJs移植到C#,并且在遇到此问题之前一直做得很好。

    backward: function() {
      for(var i=this.backprop.length-1;i>=0;i--) {
      this.backprop[i](); // tick!
    }


backprop是Graph中的一个数组,从上面可以看出,该数组包含函数的存储方式:

    if(this.needs_backprop) {
    var backward = function() {
    for(var i=0,n=d;i<n;i++){ m.dw[d * ix + i] += out.dw[i]; }
    }
    this.backprop.push(backward);
    }


我刚刚将this(backward)转换为一个当needs_backprop为true时运行的函数,但是在测试我的功能之后,每次C# code in repo摘要时都会产生相同的动作:

    if (NeedsBackPropagation)
    {
        Backward(m, outt, n);
    }


和向后:

    public void Backward(Matrix m, Matrix outt,int n)
    {
        for (var i = 0; i < n; i++)
        {
            // grad for z = tanh(x) is (1 - z^2)
            var mwi = outt.Weights[i];
            m.BackPropWeights[i] += (1.0 - mwi * mwi)* outt.BackPropWeights[i];
       }
    }


我想知道A.像他那样直接将函数存储在数组中,然后稍后再调用它们,或者B.在C#中等效,我不介意对存储库本身的贡献

最佳答案

您也可以在c#中存储函数,这是使用代码的示例:

public class Graph
{

    public bool NeedsBackPropagation { get; }
    public List<Action> BackProp { get; }


    public Graph(bool backProp)
    {
        NeedsBackPropagation = backProp;
        BackProp = new List<>();
    }


    public Matrix RowPluck(Matrix m, int ix)
    {
        Util.Assert(ix >= 0 && ix < m.NumberOfRows);
        var d = m.NumberOfColumns;
        var outt = new Matrix(d, 1);
        for (int i = 0, n = d; i < n; i++)
        {
            outt.Weights[i] = m.Weights[d * ix + i];
        }

        if (NeedsBackPropagation)
        {
            BackProp.Add(new Action(() => {
                for (int i = 0, n = d; i < n; i++)
                {
                    m.BackPropWeights[d * ix + i] += outt.BackPropWeights[i];
                }
            }));
        }

        return outt;
    }

}


然后,您只需要给他们打电话就可以了

foreach (Action action in BackProp)
{
    action();
}

10-05 20:59
查看更多