示例#1
0
        static void Main(string[] args)
        {
            //不使用預設的激發函數組,預設激發函數為LogisticSigmoid
            Perceptron.Default_Activation = ActivationFunction.HyperbolicTangent;
            Perceptron.Default_DiffActivation = ActivationFunction.Diff_HyperbolicTangent;

            //建構一個輸入層數值數量為2 感知器權重亂數範圍為-1~1
            //隱藏層節點數量為4 輸出層數量為1的神經網路
            PerceptronNetwork network = new PerceptronNetwork(2, -1, 1, new int[] { 4,1 });
            LearnData[] data = new LearnData[] {//學習用資料
                new LearnData() { Input = new double[] {0,0 },Output = new double[] { 0 }},
                new LearnData() { Input = new double[] {1,1 },Output = new double[] { 0 }},
                new LearnData() { Input = new double[] {1,0 },Output = new double[] { 1 }},
                new LearnData() { Input = new double[] {0,1 },Output = new double[] { 1 }},
            };
            LearnData.Standardize(data, -1, 1, -1, 1);//將資料轉換為符合Tanh激發函數的資料

            //呼叫學習函數,速率0.8,慣性0.6,目標誤差值0.05
            network.Train(data,0.8,0.6, 0.05);

            //測試
            foreach (var item in data) {
                Console.WriteLine($"測試({string.Join(",", item.Input)}) => {string.Join(",", network.Compute(item.Input))}");
            }

            //儲存神經網路結果
            StreamWriter writer = new StreamWriter("output.json");
            writer.Write(network.ToJObject());//匯出JSON,也可使用Load方法反序列化
            writer.Close();

            Console.ReadKey();
        }
示例#2
0
        static void Main(string[] args)
        {
            //不使用預設的激發函數組,預設激發函數為LogisticSigmoid
            Perceptron.Default_Activation     = ActivationFunction.HyperbolicTangent;
            Perceptron.Default_DiffActivation = ActivationFunction.Diff_HyperbolicTangent;

            //建構一個輸入層數值數量為2 感知器權重亂數範圍為-1~1
            //隱藏層節點數量為4 輸出層數量為1的神經網路
            PerceptronNetwork network = new PerceptronNetwork(2, -1, 1, new int[] { 4, 1 });

            LearnData[] data = new LearnData[] {//學習用資料
                new LearnData()
                {
                    Input = new double[] { 0, 0 }, Output = new double[] { 0 }
                },
                new LearnData()
                {
                    Input = new double[] { 1, 1 }, Output = new double[] { 0 }
                },
                new LearnData()
                {
                    Input = new double[] { 1, 0 }, Output = new double[] { 1 }
                },
                new LearnData()
                {
                    Input = new double[] { 0, 1 }, Output = new double[] { 1 }
                },
            };
            LearnData.Standardize(data, -1, 1, -1, 1);//將資料轉換為符合Tanh激發函數的資料

            //呼叫學習函數,速率0.8,慣性0.6,目標誤差值0.05
            network.Train(data, 0.8, 0.6, 0.05);

            //測試
            foreach (var item in data)
            {
                Console.WriteLine($"測試({string.Join(",", item.Input)}) => {string.Join(",", network.Compute(item.Input))}");
            }

            //儲存神經網路結果
            StreamWriter writer = new StreamWriter("output.json");

            writer.Write(network.ToJObject());//匯出JSON,也可使用Load方法反序列化
            writer.Close();

            Console.ReadKey();
        }
示例#3
0
        /// <summary>
        /// 資料集標準化
        /// </summary>
        /// <param name="Data">原始資料集</param>
        /// <param name="InputMin">輸入標準最小值</param>
        /// <param name="InputMax">輸入標準最大值</param>
        /// <param name="OutputMin">輸出標準最小值</param>
        /// <param name="OutputMax">輸出標準最大值</param>
        public static void Standardize(LearnData[] Data,int InputMin = 0,int InputMax = 1,int OutputMin = 0,int OutputMax = 1) {
            var DataInputMax = Enumerable.Range(0, Data.First().Input.Length).Select(
                i => Data.Select(x=>x.Input).Select(x=>x[i]).Max()
            ).ToArray();
            var DataInputMin = Enumerable.Range(0, Data.First().Input.Length).Select(
                i => Data.Select(x => x.Input).Select(x => x[i]).Min()
            ).ToArray();
            var DataOutputMax = Enumerable.Range(0, Data.First().Output.Length).Select(
                i => Data.Select(x => x.Output).Select(x => x[i]).Max()
            ).ToArray();
            var DataOutputMin = Enumerable.Range(0, Data.First().Output.Length).Select(
                i => Data.Select(x => x.Output).Select(x => x[i]).Min()
            ).ToArray();

            for(int i = 0; i < Data.Length; i++) {
                Data[i].Input = Data[i].Input.Select((x, i2) =>
                    ConvertValue((x - DataInputMin[i2]) / (DataInputMax[i2] - DataInputMin[i2]), InputMin, InputMax)
                ).ToArray();
                Data[i].Output = Data[i].Output.Select((x, i2) =>
                    ConvertValue((x - DataOutputMin[i2]) / (DataOutputMax[i2] - DataOutputMin[i2]), OutputMin, OutputMax)
                ).ToArray();
            }
        }
 /// <summary>
 /// 計算輸入值產生的結果
 /// </summary>
 /// <param name="Input">學習資料</param>
 /// <returns>運算結果</returns>
 public double[] Compute(LearnData Input) {
     return Compute(Input.Input);
 }
        /// <summary>
        /// 反傳導學習子方法
        /// </summary>
        /// <param name="Data">學習資料</param>
        /// <param name="Rate">學習速率</param>
        /// <returns></returns>
        private double BackPropagate(LearnPerceptron[][] LearnNodes, LearnData Data, double Rate) {
            LearnPerceptron[][] ComputeResult = LearnCompute(Data.Input);

            double Error = 0;

            #region 感知器節點運算結果誤差
            for (int layer = Length - 1; layer > -1; layer--) {
                for (int instance = 0; instance < this[layer].Length; instance++) {
                    if (layer == Length - 1) {//輸出層
                        LearnNodes[layer][instance].ResultDelta =
                            (Data.Output[instance] - ComputeResult[layer][instance].Result) *
                            this[layer][instance].DiffActivation(ComputeResult[layer][instance].Result);
                        Error += Math.Abs(Data.Output[instance] - ComputeResult[layer][instance].Result);
                    } else {//隱藏層
                        //下層偏差值加權總合
                        double sumDelta = 0;// ComputeResult[layer][instance].Result
                        for (int nextInstance = 0; nextInstance < Layers[layer + 1].Length; nextInstance++) {
                            sumDelta += //下一層的節點的誤差加權
                                LearnNodes[layer + 1][nextInstance].ResultDelta *
                                this[layer + 1][nextInstance][instance];
                        }
                        LearnNodes[layer][instance].ResultDelta = sumDelta *
                            this[layer][instance].DiffActivation(ComputeResult[layer][instance].Result);
                    }
                }
            }
            #endregion

            #region 計算感知器節點的權重與閥值修正值
            for (int layer = Length - 1; layer > -1; layer--) {
                for (int instance = 0; instance < this[layer].Length; instance++) {
                    //修正閥值
                    LearnNodes[layer][instance].ThresholdDelta += -Rate * LearnNodes[layer][instance].ResultDelta;
                    for (int weight = 0; weight < this[layer][instance].Length; weight++) {
                        if (layer == 0) {//輸入層
                                         //本節點偏差與輸入值
                            for (int upInstance = 0; upInstance < Data.Input.Length; upInstance++) {
                                LearnNodes[layer][instance].WeightsDelta[upInstance] += Rate * LearnNodes[layer][instance].ResultDelta * Data.Input[upInstance];
                            }
                        } else {
                            //本節點偏差與上層節點給的輸入
                            for (int upInstance = 0; upInstance < this[layer - 1].Length; upInstance++) {
                                LearnNodes[layer][instance].WeightsDelta[upInstance] += Rate * LearnNodes[layer][instance].ResultDelta * ComputeResult[layer - 1][upInstance].Result;
                            }
                        }
                    }
                }
            }
            #endregion

            return Error;
        }
        /// <summary>
        /// 反傳導學習方法
        /// </summary>
        /// <param name="Data">學習資料集和</param>
        /// <param name="Rate">學習速率</param>
        /// <param name="Momentum">慣性動量</param>
        /// <param name="Difference">目標誤差值</param>
        /// <param name="Iterations">迭代次數限制</param>
        public void Train(LearnData[] Data, double Rate, double Momentum = 0, double Difference = 0, int Iterations = -1) {
            double Min = double.MaxValue;
            for (int i = 0; Iterations == -1 || i < Iterations; i++) {
                //學習用暫存資料
                LearnPerceptron[][] LearnNodes = GetLearnPerceptrons();

                double Error = 0;
                foreach (LearnData Item in Data) {
                    Error += BackPropagate(LearnNodes,Item, Rate);
                }
                
                #region 修正
                for (int layer = Length - 1; layer > -1; layer--) {
                    for (int instance = 0; instance < this[layer].Length; instance++) {
                        //修正閥值
                        this[layer][instance].Threshold += LearnNodes[layer][instance].ThresholdDelta + LearnNodes[layer][instance].Last_ThresholdDelta * Momentum;// / Math.Sqrt(Data.Length);
                        for (int weight = 0; weight < this[layer][instance].Length; weight++) {
                            this[layer][instance][weight] += LearnNodes[layer][instance].WeightsDelta[weight] + LearnNodes[layer][instance].Last_WeightsDelta[weight] * Momentum;// / Math.Sqrt(Data.Length);
                        }
                    }
                }
                #endregion

                #region 備份修正值
                for(int layer = Length - 1;layer > -1;layer--) {
                    for(int instance = 0; instance < this[layer].Length; instance++) {
                        LearnNodes[layer][instance].Last_ThresholdDelta = LearnNodes[layer][instance].ThresholdDelta;
                        LearnNodes[layer][instance].Last_WeightsDelta = LearnNodes[layer][instance].WeightsDelta;
                    }
                }
                #endregion
                Min = Math.Min(Min, Error);
                Console.WriteLine($"迭代:{i}\t{Error}\t{Min}");
                if (Error <= Difference) {
                    break;
                }
            }
        }
示例#7
0
        /// <summary>
        /// 反傳導學習子方法
        /// </summary>
        /// <param name="Data">學習資料</param>
        /// <param name="Rate">學習速率</param>
        /// <returns></returns>
        private double BackPropagate(LearnPerceptron[][] LearnNodes, LearnData Data, double Rate)
        {
            LearnPerceptron[][] ComputeResult = LearnCompute(Data.Input);

            double Error = 0;

            #region 感知器節點運算結果誤差
            for (int layer = Length - 1; layer > -1; layer--)
            {
                for (int instance = 0; instance < this[layer].Length; instance++)
                {
                    if (layer == Length - 1)  //輸出層
                    {
                        LearnNodes[layer][instance].ResultDelta =
                            (Data.Output[instance] - ComputeResult[layer][instance].Result) *
                            this[layer][instance].DiffActivation(ComputeResult[layer][instance].Result);
                        Error += Math.Abs(Data.Output[instance] - ComputeResult[layer][instance].Result);
                    }
                    else    //隱藏層
                    //下層偏差值加權總合
                    {
                        double sumDelta = 0;// ComputeResult[layer][instance].Result
                        for (int nextInstance = 0; nextInstance < Layers[layer + 1].Length; nextInstance++)
                        {
                            sumDelta += //下一層的節點的誤差加權
                                        LearnNodes[layer + 1][nextInstance].ResultDelta *
                                        this[layer + 1][nextInstance][instance];
                        }
                        LearnNodes[layer][instance].ResultDelta = sumDelta *
                                                                  this[layer][instance].DiffActivation(ComputeResult[layer][instance].Result);
                    }
                }
            }
            #endregion

            #region 計算感知器節點的權重與閥值修正值
            for (int layer = Length - 1; layer > -1; layer--)
            {
                for (int instance = 0; instance < this[layer].Length; instance++)
                {
                    //修正閥值
                    LearnNodes[layer][instance].ThresholdDelta += -Rate * LearnNodes[layer][instance].ResultDelta;
                    for (int weight = 0; weight < this[layer][instance].Length; weight++)
                    {
                        if (layer == 0)  //輸入層
                                         //本節點偏差與輸入值
                        {
                            for (int upInstance = 0; upInstance < Data.Input.Length; upInstance++)
                            {
                                LearnNodes[layer][instance].WeightsDelta[upInstance] += Rate * LearnNodes[layer][instance].ResultDelta * Data.Input[upInstance];
                            }
                        }
                        else
                        {
                            //本節點偏差與上層節點給的輸入
                            for (int upInstance = 0; upInstance < this[layer - 1].Length; upInstance++)
                            {
                                LearnNodes[layer][instance].WeightsDelta[upInstance] += Rate * LearnNodes[layer][instance].ResultDelta * ComputeResult[layer - 1][upInstance].Result;
                            }
                        }
                    }
                }
            }
            #endregion

            return(Error);
        }
示例#8
0
 /// <summary>
 /// 計算輸入值產生的結果
 /// </summary>
 /// <param name="Input">學習資料</param>
 /// <returns>運算結果</returns>
 public double[] Compute(LearnData Input)
 {
     return(Compute(Input.Input));
 }