Ejemplo n.º 1
0
        /// 出力層の重み計算
        public static void UpdateWeightOfOutputLayer(ILayer layer
                                                     , ILayer _
                                                     , Func <IEnumerable <Tuple <double, double> >, double> errorFunction
                                                     , ILearningData data)
        {
            var ox = layer.Nodes.Select(x => x.GetValue()).ToArray();
            var ux = layer.Nodes.Select(layer.CalcFunction).ToArray();

            foreach (var item in layer.Nodes.Select((x, index) => new { x, index }))
            {
                var node  = item.x;
                var index = item.index;
                // 誤差関数の偏微分
                Func <double, double> ef = (double x) =>
                {
                    var rx = ox.ToArray();
                    rx[index] = x;
                    return(errorFunction(rx.Zip(data.Expected, Tuple.Create)));
                };
                // 活性化関数の偏微分
                Func <double, double> of = (double x) =>
                {
                    var rx = ux.ToArray();
                    rx[index] = x;
                    var result = layer.ActivationFunction(rx).ToArray();
                    return(result[index]);
                };

                // 活性化前の値
                var u = ux[index];   // todo cache
                // 出力
                var o = ox[index];
                // 前の層の重み計算で使える部分
                var delta = ef.Derivative()(o) * of.Derivative()(u);

                // 入力Nodeごとに重みを更新
                foreach (var link in node.Links)
                {
                    Update(node, link, delta);
                }
            }
        }