void UpdateWeight(ILearningData data) { // 各Nodeの入力重みを更新 ILayer forwardLayer = outputLayer; foreach (var layer in this.Layers.Skip(1).Reverse()) { layer.UpdateWeightFunction(layer, forwardLayer, errorFunction, data); forwardLayer = layer; } }
/// 出力層の重み計算 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); } } }
public static void UpdateWeightOfSoftMax(ILayer layer , ILayer _ , Func <IEnumerable <Tuple <double, double> >, double> errorFunction , ILearningData data) { var ys = layer.Nodes.Select(x => x.GetValue()).ToArray(); var ts = data.Expected.ToArray(); var deltas = ys.Zip(ts, (y, t) => (y - t)).ToArray(); foreach (var item in layer.Nodes.Zip(deltas, Tuple.Create)) { var node = item.Item1; var delta = item.Item2; // 入力Nodeごとに重みを更新 foreach (var link in node.Links) { Update(node, link, delta); } } }