/// 出力層の重み計算 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); } } }