2012-04-18 3 views
-1

y=e^(-(x-u)^2)/(2*o^2))의 신경망을 만들려고합니다. u = 50o = 15입니다.신경망, 출력이 적음 1

나는 각각의 y에 2 x를 찾을 수 있도록 신경 네트워크를 훈련해야합니다. 나는 folling code를 만들었다. 멋지게 배울 것 같다.하지만 출력을 테스트 한 후에는 0.99와 1 사이의 숫자를 얻고 25와 75를 얻어야한다. 이유는 알 수 없다. 내 최선의 추측은 내 오류 수정이 잘못되었지만 오류를 찾을 수 없다는 것입니다. 신경망은 역 전파를 사용합니다.

테스트 코드 및 교육 네트워크 뒤에

class Program 
    { 
     static void Main(string[] args) 
     { 
      args = new string[] { 
       "c:\\testTrain.csv", 
       "c:\\testValues.csv" 
      }; 

      // Output File 
      string fileTrainPath = null; 
      string fileValuesPath = null; 
      if (args.Length > 0) 
      { 
       fileTrainPath = args[0]; 
       if (File.Exists(fileTrainPath)) 
        File.Delete(fileTrainPath); 
       fileValuesPath = args[1]; 
       if (File.Exists(fileValuesPath)) 
        File.Delete(fileValuesPath); 
      } 

      double learningRate = 0.1; 
      double u = 50; 
      double o = 15; 

      Random rand = new Random(); 

      Network net = new Network(1, 8, 4, 2); 
      NetworkTrainer netTrainer = new NetworkTrainer(learningRate, net); 

      List<TrainerSet> TrainerSets = new List<TrainerSet>(); 
      for(int i = 0; i <= 20; i++) 
      { 
       double random = rand.NextDouble(); 

       TrainerSets.Add(new TrainerSet(){ 
        Inputs = new double[] { random }, 
        Outputs = getX(random, u, o) 
       }); 
      } 

      // Train Network 
      string fileTrainValue = String.Empty; 
      for (int i = 0; i <= 10000; i++) 
      { 
       if (i == 5000) 
       { } 
       double error = netTrainer.RunEpoch(TrainerSets); 
       Console.WriteLine("Epoch " + i + ": Error = " + error); 
       if(fileTrainPath != null) 
        fileTrainValue += i + "," + learningRate + "," + error + "\n"; 
      } 
      if (fileTrainPath != null) 
       File.WriteAllText(fileTrainPath, fileTrainValue); 

      // Test Network 
      string fileValuesValue = String.Empty; 
      for (int i = 0; i <= 100; i++) 
      { 
       double y = rand.NextDouble(); 
       double[] dOutput = getX(y, u, o); 
       double[] Output = net.Compute(new double[] { y }); 

       if (fileValuesPath != null) 
        fileValuesValue += i + "," + y + "," + dOutput[0] + "," + dOutput[1] + "," + Output[0] + "," + Output[1] + "\n"; 
      } 
      if (fileValuesPath != null) 
       File.WriteAllText(fileValuesPath, fileValuesValue); 
     } 

     public static double getResult(int x, double u, double o) 
     { 
      return Math.Exp(-Math.Pow(x-u,2)/(2*Math.Pow(o,2))); 
     } 

     public static double[] getX(double y, double u, double o) 
     { 
      return new double[] { 
       u + Math.Sqrt(2 * Math.Pow(o, 2) * Math.Log(1/y)), 
       u - Math.Sqrt(2 * Math.Pow(o, 2) * Math.Log(1/y)), 
      }; 
     } 
    } 

에게 코드를 설정

public class Network 
{ 
    protected int inputsCount; 
    protected int layersCount; 
    protected NetworkLayer[] layers; 
    protected double[] output; 

    public int Count 
    { 
     get 
     { 
      return layers.Count(); 
     } 
    } 
    public NetworkLayer this[int index] 
    { 
     get { return layers[index]; } 
    } 

    public Network(int inputsCount, params int[] neuronsCount) 
    { 
     this.inputsCount = Math.Max(1, inputsCount); 
     this.layersCount = Math.Max(1, neuronsCount.Length); 

     layers = new NetworkLayer[neuronsCount.Length]; 
     for (int i = 0; i < layersCount; i++) 
      layers[i] = new NetworkLayer(neuronsCount[i], 
       (i == 0) ? inputsCount : neuronsCount[i - 1]); 
    } 

    public virtual double[] Compute(double[] input) 
    { 
     output = input; 

     foreach (NetworkLayer layer in layers) 
      output = layer.Compute(output); 

     return output; 
    } 
} 
public class NetworkLayer 
{ 
    protected int inputsCount = 0; 
    protected int neuronsCount = 0; 
    protected Neuron[] neurons; 
    protected double[] output; 

    public Neuron this[int index] 
    { 
     get { return neurons[index]; } 
    } 
    public int Count 
    { 
     get { return neurons.Length; } 
    } 
    public int Inputs 
    { 
     get { return inputsCount; } 
    } 
    public double[] Output 
    { 
     get { return output; } 
    } 

    public NetworkLayer(int neuronsCount, int inputsCount) 
    { 
     this.inputsCount = Math.Max(1, inputsCount); 
     this.neuronsCount = Math.Max(1, neuronsCount); 

     neurons = new Neuron[this.neuronsCount]; 
     output = new double[this.neuronsCount]; 

     // create each neuron 
     for (int i = 0; i < neuronsCount; i++) 
      neurons[i] = new Neuron(inputsCount); 
    } 

    public virtual double[] Compute(double[] input) 
    { 
     // compute each neuron 
     for (int i = 0; i < neuronsCount; i++) 
      output[i] = neurons[i].Compute(input); 

     return output; 
    } 
} 
public class Neuron 
{ 
    protected static Random rand = new Random((int)DateTime.Now.Ticks); 

    public int Inputs; 
    public double[] Input; 
    public double[] Weights; 
    public double Output = 0; 
    public double Threshold; 
    public double Error; 

    public Neuron(int inputs) 
    { 
     this.Inputs = inputs; 
     Weights = new double[inputs]; 

     for (int i = 0; i < inputs; i++) 
      Weights[i] = rand.NextDouble() * 0.5; 
    } 

    public double Compute(double[] inputs) 
    { 
     Input = inputs; 

     double e = 0.0; 
     for (int i = 0; i < inputs.Length; i++) 
      e += Weights[i] * inputs[i]; 

     e -= Threshold; 
     return (Output = sigmoid(e)); 
    } 

    private double sigmoid(double value) 
    { 
     return (1/(1 + Math.Exp(-1 * value))); 
     //return 1/(1 + Math.Exp(-value)); 
    } 
} 

내 트레이너

당신의 출력 층이 정체성을 가지고 있어야 회귀 문제에 대한
public class NetworkTrainer 
{ 
    private Network network; 
    private double learningRate = 0.1; 

    public NetworkTrainer(double a, Network network) 
    { 
     this.network = network; 
     this.learningRate = a; 
    } 

    public double Run(double[] input, double[] output) 
    { 
     network.Compute(input); 

     return CorrectErrors(output); 
    } 

    public double RunEpoch(List<TrainerSet> sets) 
    { 
     double error = 0.0; 
     for (int i = 0, n = sets.Count; i < n; i++) 
      error += Run(sets[i].Inputs, sets[i].Outputs); 

     // return summary error 
     return error; 
    } 

    private double CorrectErrors(double[] desiredOutput) 
    { 
     double[] errorLast = new double[desiredOutput.Length]; 

     NetworkLayer lastLayer = network[network.Count - 1]; 
     for (int i = 0; i < desiredOutput.Length; i++) 
     { 
      // S(p)=y(p)*[1-y(p)]*(yd(p)-y(p)) 
      lastLayer[i].Error = lastLayer[i].Output * (1-lastLayer[i].Output)*(desiredOutput[i] - lastLayer[i].Output); 
      errorLast[i] = lastLayer[i].Error; 
     } 

     // Calculate errors 
     for (int l = network.Count - 2; l >= 0; l--) 
     { 
      for (int n = 0; n < network[l].Count; n++) 
      { 
       double newError = 0; 
       for (int np = 0; np < network[l + 1].Count; np++) 
       { 
        newError += network[l + 1][np].Weights[n] * network[l + 1][np].Error; 
       } 
       network[l][n].Error = newError; 
      } 
     } 

     // Update Weights 
     // w = w + (a * input * error) 
     for (int l = network.Count - 1; l >= 0; l--) 
     { 
      for (int n = 0; n < network[l].Count; n++) 
      { 
       for (int i = 0; i < network[l][n].Inputs; i++) 
       { 
        // deltaW = a * y(p) * s(p) 
        double deltaW = learningRate * network[l][n].Output * network[l][n].Error; 
        network[l][n].Weights[i] += deltaW; 
       } 

      } 
     } 

     double returnError = 0; 
     foreach (double e in errorLast) 
      returnError += e; 
     return returnError; 
    } 
} 
+3

무슨 문제가 있습니까? 이것은 꽤 긴 코드입니다. http://sscce.org/ – Coffee

+0

제가 말했듯이, 나는 eks가되어야하는 곳에서만 0.99에서 1의 출력을 얻습니다. 75 또는 25, 나는 무엇을해야할지 모르지만 나는 틀린 것을 구현해야만한다. – Androme

+0

나는 내 활성화 함수가 0에서 1 사이의 값을 제공하고 크기를 조정해야하기 때문이라고 들었습니다. 그러나 나는 이것에 관해 무엇이라도 발견 할 수 없다. – Androme

답변

1

(또는 적어도 선형) 활성화 함수. 이렇게하면 출력을 확장 할 필요가 없습니다. 아이덴티티 함수의 미분은 1이므로 출력 레이어의 미분 dE/da_i는 y-t (lastLayer[i].Output - desiredOutput[i])입니다.