神经网络无法正常工作

时间:2015-05-06 10:06:09

标签: c# neural-network encog

我正在使用(ENCOG library)来创建和训练神经网络。它必须从建模字典中找到真实的故障向量(它有12个数字 - 如矢量=故障的特征)(它有70个故障,在12个频率上识别)。

在NN中,我有输入(12个神经元=一个输入故障矢量的len),隐藏(14个神经元= 2 *输出神经元)和输出(7个神经元 - 通过'0 \ 1'70个故障识别)层。

这是NN的代码(在C#上):

public static double[][] XORInput =
        {
            new double[] { 1, 1, 1, 1,1,1,1,2,2,2,2,2 },
            new double[] { 5, 5, 5, 5,5,5,5,6,6,7,7,7 }, 
            new double[] { 6, 6,6,6,6,6,5,5,5,1,2,3 }, 
            new double[] { 3, 3, 3, 3,3,3,3,3,2,2,1,1 } ,
            new double[] { 1, 1, 2, 2,2,3,3,3,3,3,3,3 },
            new double[] { 1, 4, 2, 7,2,5,6,7,8,8,8,8 },
            new double[] { 2, 3, 3, 3,3,3,3,3,3,3,2,2 },
            new double[] { 7,7, 7, 7,7,8,8,8,7,7,7,7 },
            new double[] { 6, 7, 7, 8,8,8,8,8,8,7,7,6 },
            new double[] { 3, 3, 3, 4 ,4,4,4,4,4,3,3,3 },
            new double[] { 1, 1, 1, 1,1,2,2,2,2,2,2,2 },
            new double[] { 5, 5, 5, 5,5,6,6,6,6,6,6,7 },
            new double[] { 1,2,3,4,5,6,7,8,1,2,3,1 },
            new double[] { 1, 1, 1, 1,1,1,1,1,1,2,4,1 },    
            new double[] { 1, 1, 1, 1,1,1,1,1,1,1,1,1 },
            new double[]  { 5, 5, 5,5,5,5,5,5,5,5,5,5 },
            new double[] {7, 8, 8, 8,8,7,6,4,1,2,2,2 },            
            new double[] { 2, 3, 3, 3,3,4,4,4,4,3,3,3 },
            new double[] { 8, 8,8, 8,8,5,6,7,8,8,8,8 },
            new double[] { 5, 5, 5, 5,5,6,8,6,1,1,1,1 },
            new double[] { 1, 1, 1, 1,1,1,1,4,4,6,3,5 },
            new double[] { 2, 2, 2, 2,2,2,2,2,3,3,3,3 },
           new double[]  { 6, 6, 6, 6,7,7,7,7,7,8,8,8 }, 
new double[] { 1, 16, 2, 6,71,72,73,27,74,81,81,58 },
new double[] { 2, 36, 3, 67,87,7,17,27,37,2,1,1 },
new double[] { 3, 46, 4, 8,4,5,6,7,22,8,18,2 },
new double[] { 4, 56, 12, 9,1,2,4,12,4,44,1,8 },
new double[] { 5, 66, 5, 6,17,4,5,11,5,7,8,9 },
new double[] { 6, 86, 6, 6, 10,2,5,8,1,3,5,1 },
new double[] { 66, 16, 14, 11,1,1,1,2,1,4,1,6 },
new double[] { 67, 6,11 , 16,2,2,2,7,21,2,1,9 },
new double[] { 7, 6, 10, 62,12,3,4,54,1,1,3,3 },
new double[] { 8, 16,9, 6,17,7,1,2,7,5,1,4 },
new double[] { 9, 26,11, 6,73,6,2,3,4,5,5,2 },
new double[] { 61, 21, 85, 61,5,2,5,1,6,3,4,5 }, 
new double[]             { 31, 1, 11, 1,1,1,1,2,2,2,2,2 },
            new double[] { 15, 5, 15, 5,5,5,5,6,6,7,7,7 }, 
            new double[] { 36, 6,16,6,6,6,5,5,5,1,2,3 }, 
            new double[] { 53, 3, 13, 3,3,3,3,3,2,2,1,1 } ,
            new double[] { 71, 1, 22, 2,2,3,3,3,3,3,3,3 },
            new double[] { 81, 4, 21, 7,2,5,6,7,8,8,8,8 },
            new double[] { 12, 3, 13, 3,3,3,3,3,3,3,2,2 },
            new double[] { 97,7, 71, 7,7,8,8,8,7,7,7,7 },
            new double[] { 5, 7, 17, 8,8,8,8,8,8,7,7,6 },
            new double[] { 13, 3, 13, 4,4,4,4,4,4,3,3,3 },
new double[]             { 11, 1, 11, 1,1,2,2,2,2,2,2,2 },
            new double[] { 55, 5, 51, 5,5,6,6,6,6,6,6,7 },
            new double[] { 16,2,19,4,5,6,7,8,1,2,3,1 },
            new double[] { 17, 1, 11, 1,1,1,1,1,1,2,4,1 },
            new double[] { 19, 1, 21, 1,1,1,1,1,1,1,1,1 },
            new double[] { 25, 5, 25,5,5,5,5,5,5,5,5,5 },           
                        new double[] {27, 8, 28, 8,8,7,6,4,1,2,2,2 },
            new double[] { 22, 3, 23, 3,3,3,3,3,3,2,1,7 },
            new double[] { 32, 3, 27, 3,3,4,4,4,4,3,3,3 },
            new double[] { 18, 8,2, 8,8,5,6,7,8,8,8,8 },
            new double[] { 31, 1, 4, 1,1,1,1,4,4,6,3,5 },
            new double[] { 23, 2, 6, 2,2,2,2,2,3,3,3,3 },
            new double[] { 36, 6, 16, 6,7,7,7,7,7,8,8,8 },
new double[] { 31, 16, 5, 6,71,72,73,27,74,81,81,58 },
new double[] { 12, 36, 14, 67,87,7,17,27,37,2,1,1 },
new double[] { 31, 46, 41, 8,4,5,6,7,22,8,18,2 },
new double[] { 14, 56, 1, 9,1,2,4,12,4,44,1,8 },
new double[] { 15, 66, 59, 6,17,4,5,11,5,7,8,9 },
new double[] { 16, 86, 16, 6, 10,2,5,8,1,3,5,1 },
new double[] { 16, 16, 10, 11,1,1,1,2,1,4,1,6 },
new double[] { 17, 6,114, 16,2,2,2,7,21,2,1,9 },
new double[] { 71, 6, 1, 62,12,3,4,54,1,1,3,3 },
new double[] { 18, 16,19, 6,17,7,1,2,7,5,1,4 },
new double[] { 19, 26,1, 6,73,6,2,3,4,5,5,2 },
new double[] { 6, 21, 5, 61,5,2,5,1,6,3,4,5 } //70
            };


        /// <summary>
        /// Array of numbers, which equal to squares of two
        /// </summary>
        static int[] powOfTwo = {2, 4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536 };    


private static void Main(string[] args)
            {
                double[][] XORIdeal = computeOutputVector(XORInput);
                // normalizing input data
                double[][] input = normalizeData(XORInput);

                // create a neural network, without using a factory
                var network = new BasicNetwork();
                network.AddLayer(new BasicLayer(null, true, 12));
                network.AddLayer(new BasicLayer(new ActivationSigmoid(), true, 14));
                network.AddLayer(new BasicLayer(new ActivationSigmoid(), false, 7));       
                network.Structure.FinalizeStructure();
                network.Reset();

                // create training data
                IMLDataSet trainingSet = new BasicMLDataSet(input, XORIdeal);
                //IMLDataSet trainingSet = new BasicMLDataSet(XORInput, XORIdeal);

            // train the neural network
            //IMLTrain train = new ResilientPropagation(network, trainingSet);
            //var train = new Backpropagation ( network , trainingSet , 0.3 , 0.7 ) ;
            var train = new Backpropagation(network, trainingSet, 0.2, 0.15); // speed and influence of backpropogation algorithm

            int epoch = 1;
            do
            {
                train.Iteration();
                Console.WriteLine(@"Epoch #" + epoch + @" Error:" + train.Error);
                epoch++;
            } while (train.Error > 0.05 && epoch < 2000);
            train.FinishTraining();

            // test the neural network
            Console.WriteLine(@"Neural Network Results:");

            double[] data = new double[] { 1, 1, 1, 1,1,1,1,2,2,2,2,2 }; //{ 5.1, 5.4, 5.5, 5.5, 5.8, 5.6, 5.6, 6.5, 6.6, 7.1, 7.1, 7.1 };  // 0000001
            double[] realSignature22 = new double[] { 6.21, 4.2, 6.6, 6.6, 6.6, 5.56, 6.5, 7, 7, 6.89, 6.8, 8 }; // 0010110
            double[] realSignature34 = new double[] { 58, 24, 90, 55, 4.5, 1.82, 5.4, 1.1, 6.4, 3.1, 3.4, 5.3 }; // 0100010

            IMLData example1 = new BasicMLData(normilizeRow(data));
            IMLData output1 = network.Compute(example1);
            Console.WriteLine("\nactual : 0 0 0 0 0 0 0 = #0 ");
            findNumber(output1);   

            IMLData example = new BasicMLData(normilizeRow(realSignature34));
            IMLData output = network.Compute(example);
            Console.WriteLine("\nactual : 0 1 0 0 0 1 0 = #34 ");
            findNumber(output);    

            IMLData example2 = new BasicMLData(normilizeRow(realSignature22));
            IMLData output2 = network.Compute(example2);
            Console.WriteLine("\nactual : 0 0 1 0 1 1 0 = #22 ");    
            findNumber(output2);    

            EncogFramework.Instance.Shutdown();
        }

        /// <summary>
        /// Returns degree of two which cowers number of mistakes in the input vector
        /// </summary>
        /// <param name="XORInput"></param>
        /// <returns></returns>
        static int calcSizeOfOutputVector(double[][] XORInput)
        {
            int size = 0;
            int len = XORInput.GetLength(0);
            foreach (int number in powOfTwo)
            {
                size++;
                if (len <= number) return size;
            }
            return -1;
        }

        static double[][] computeOutputVector(double[][] XORInput)
        {
            double[][] output;
            int sizeOfOut = calcSizeOfOutputVector(XORInput);
            int numOfFaults = XORInput.GetLength(0);
            output = new double[numOfFaults][];
            // convert decimal number into corresponding array from 0 and 1 (equal to decimal number) 
            for (int i = 0; i < numOfFaults; i++)
            {
                output[i] = new double[sizeOfOut];
                convertDecToByteAndSaveInDoubleArray(output[i], i);               
            }
            return output;
        }

        static double[] convertDecToByteAndSaveInDoubleArray(double[] outArray, int number ){
            // convert number into binary representation
            string binaryCode = Convert.ToString(number, 2);
            int size = outArray.GetLength(0);
            // Initially fill with zeros
            for (int i = 0; i < size; i++) outArray[i] = 0;
            // 
            for (int i = 0; i < binaryCode.Length; i++)
            {
                double d = Double.Parse(binaryCode.Substring(binaryCode.Length - i - 1, 1));
                outArray[size - 1 - i] = d;
            }
            return outArray;
        }      

        static void printOutputResults(IMLData output){
            Console.WriteLine("\nFrom NN  ");
            for (int i = 0; i < output.Count; i++ )
                Console.Write(" " + output[i] + " " );
        }

        static int[] findNumber(IMLData output)
        {
            int len = output.Count;
            // Round to 0 and 1 numbers, which is received from NN
            int[] outAr = new int[len];
            for (int i = 0; i < output.Count; i++)
            {
                outAr[i] = (int)Math.Round(output[i]);
            }
            // Display output vectors
            // Bug for number 1 and length 7 in the input vector looks like : 0[0] 0[1] 0[2] 0[3] 0[4] 0[5] 1[6] (in binary system) = 1 (in decimal system)
            Console.WriteLine("\nFrom NN ");
            for (int i = 0; i < len; i++)
                Console.Write(" " + outAr[i] + " ");
            // Convert binary vector into decimal
            Console.WriteLine("\nFrom NN (converted number)" + convertBinArrayToDecNumber(outAr));
            return outAr;
        }

        static int convertBinArrayToDecNumber(int[] binaryArray)
        {
            int n = 0;
            int maxIndex = binaryArray.Length - 1;
            for (int i = maxIndex; i >= 0; i--)
                n += (int)Math.Pow(2, maxIndex - i) * binaryArray[i];
            return n;
        }

        static double[][] normalizeData(double[][] data)
        {
            int numOfRows = data.Length;
            int lenOfRow = data[0].GetLength(0);
            double[][] result = new double[numOfRows][];
            for (int i = 0; i < numOfRows; i++)
                result[i] = normilizeRow(data[i]);
            return result;
        }

        static double[] normilizeRow(double[] row)
        {
            int lenOfRow = row.GetLength(0);
            double[] result = new double[lenOfRow];
            for (int i = 0; i < lenOfRow; i++) result[i] = 0;
            double N = 0;
            foreach (double num in row) N += num * num;           
            if (N != 0) {
                for (int j = 0; j < lenOfRow; j++)
                {
                    result[j] = (row[j] / Math.Sqrt(N));
                }
            }
            return result;
        }

我尝试通过backpropogation编辑训练参数,但几乎每次我都有很高的训练水平。

但此代码中最大的问题是结果。每次运行代码都有不同的(而不是正确的!!!)结果。例如:

actual : 0 0 0 0 0 0 0 = #0    
From NN
 0  0  0  0  0  0  1
From NN (converted number)1    
actual : 0 1 0 0 0 1 0 = #34    
From NN
 0  1  0  0  0  1  0
From NN (converted number)34    
actual : 0 0 1 0 1 1 0 = #22    
From NN
 0  0  0  0  0  1  0
From NN (converted number)2

或另一个:

Neural Network Results:    
actual : 0 0 0 0 0 0 0 = #0    
From NN
 0  0  0  0  1  0  1
From NN (converted number)5    
actual : 0 1 0 0 0 1 0 = #34    
From NN
 0  1  0  0  0  1  0
From NN (converted number)34    
actual : 0 0 1 0 1 1 0 = #22    
From NN
 0  0  0  1  1  1  1
From NN (converted number)15

任何人都可以告诉我:

1)如何更有效地培训网络

2)为什么NN无法正确识别像'{1,1,1,1,1,1,2,2,2,2,2}'这样的行(在列车数据中)?

// --------------------------------------------- ----------------------

我尝试用Encog函数来规范化数据。代码:

public static void  readCSVFileToNN(){
            int numOfCol = 12;
            // Define the format of the data file.
            // This area will change, depending on the columns and 
            // format of the file that you are trying to model.
            IVersatileDataSource source = new CSVDataSource("c:\\test.txt", false,
                CSVFormat.DecimalPoint);
            var data = new VersatileMLDataSet(source);
            for (int i = 0; i < numOfCol; i++ )
                data.DefineSourceColumn("freq#" +i , i, ColumnType.Nominal);

            // Define the column that we are trying to predict.
            ColumnDefinition outputColumn = data.DefineSourceColumn("faultNumbers", 12,
                ColumnType.Nominal);

            // Analyze the data, determine the min/max/mean/sd of every column.
            data.Analyze();

            // Map the prediction column to the output of the model, and all
            // other columns to the input.
            data.DefineSingleOutputOthersInput(outputColumn);

            // Create feedforward neural network as the model type. MLMethodFactory.TYPE_FEEDFORWARD.
            // You could also other model types, such as:
            // MLMethodFactory.SVM:  Support Vector Machine (SVM)
            // MLMethodFactory.TYPE_RBFNETWORK: RBF Neural Network
            // MLMethodFactor.TYPE_NEAT: NEAT Neural Network
            // MLMethodFactor.TYPE_PNN: Probabilistic Neural Network
            var model = new EncogModel(data);
            model.SelectMethod(data, MLMethodFactory.TypeFeedforward);

            // Send any output to the console.
            model.Report = new ConsoleStatusReportable();

            // Now normalize the data.  Encog will automatically determine the correct normalization
            // type based on the model you chose in the last step.
            data.Normalize();

            // Hold back some data for a final validation.
            // Shuffle the data into a random ordering.
            // Use a seed of 1001 so that we always use the same holdback and will get more consistent results.
            model.HoldBackValidation(0.3, true, 1001);

            // Choose whatever is the default training type for this model.
            model.SelectTrainingType(data);
            // Use a 5-fold cross-validated train.  Return the best method found.
            var bestMethod = (IMLRegression)model.Crossvalidate(2, true);

            // Display the training and validation errors.
            Console.WriteLine(@"Training error: " + model.CalculateError(bestMethod, model.TrainingDataset));
            Console.WriteLine(@"Validation error: " + model.CalculateError(bestMethod, model.ValidationDataset));

            // Display our normalization parameters.
            NormalizationHelper helper = data.NormHelper;
            Console.WriteLine(helper.ToString());

            // Display the final model.
            Console.WriteLine(@"Final model: " + bestMethod);
            source.Close();

            // test work of model on the example:
            IMLData input = helper.AllocateInputVector();
            var line = new String[numOfCol];
            var result = new StringBuilder();
            // в качестве примера возьмем сигнатуру [5,5,..,5] под номером 15
            for (int i = 0; i < numOfCol; i++)
                line[i] = 5.ToString();
            String correct = 15.ToString();
            // нормализуем входной вектор
            helper.NormalizeInputVector(line, ((BasicMLData) input).Data, false);
            // производим поиск по НС
            IMLData output = bestMethod.Compute(input);
            // выводим результат
            String faultChosen = helper.DenormalizeOutputVectorToString(output)[0];
                result.Append(line);
                result.Append(" -> predicted: ");
                result.Append(faultChosen);
                result.Append("(correct: ");
                result.Append(correct);
                result.Append(")");

                Console.WriteLine(result.ToString());

        }

但结果仍然很糟糕。我做这个功能~10次,没有一个结果不正确

1 个答案:

答案 0 :(得分:1)

您的问题是每行标准化与其他行无关。例如,第一行将是27处的每个值的除法,第二行将是394处的每个数字的除法。问题的另一个来源可能是您需要将每行独立规范化,但是所有行应根据某些规则进行归一化。然后,您应该为输入应用相同的规范化规则。我建议你看看Encog中的函数normalize