Exemplo n.º 1
0
        public void ComputeGraduateInThread(object input)
        {
            ThreadInputDatum inputDatum = (ThreadInputDatum) input;

            int lastLayerId = this.LayerCount - 1;

            foreach (double[] t in inputDatum.trainDatum)
            {
                // no need to visit in random order because all rows processed before any updates ('batch')
                Array.Copy(t, inputDatum.xValues, this.Sizes[0]); // get the inputs
                // get the target values
                Array.Copy(t, this.Sizes[0], inputDatum.tValues, 0, this.Sizes[lastLayerId]);
                // copy xValues in, compute outputs using curr weights (and store outputs internally)
                double[] yValues = this.ComputeOutputs(inputDatum.xValues, inputDatum.field);

                double[][] gradTerms = this.CalculateGradTerms(inputDatum.field, inputDatum.tValues);

                for (int layer = lastLayerId; layer > 0; layer--)
                {
                    // add input to h-o component to make h-o weight gradients, and accumulate
                    for (int j = 0; j < this.Sizes[layer]; ++j)
                    {
                        double grad = gradTerms[layer][j];
                        inputDatum.allGradsAcc[layer].Biases[j] += grad;

                        for (int i = 0; i < this.Sizes[layer - 1]; ++i)
                        {
                            grad = gradTerms[layer][j] * inputDatum.field[layer - 1][i];
                            inputDatum.allGradsAcc[layer].Weights[j][i] += grad;
                        }
                    }
                }

                for (int j = 0; j < this.Sizes[lastLayerId]; ++j)
                {
                    double err = Math.Pow(yValues[j] - inputDatum.tValues[j], 2);
                    inputDatum.sumSquaredErrors[0] += err * inputDatum.delim1;
                    inputDatum.sumSquaredErrors[1] += err * inputDatum.delim2;
                }
            }
        }
Exemplo n.º 2
0
        /**
         * Подсчитываем градиент в несколько потоков
         */
        protected double[] ComputeGraduateMultiThread(double[][] trainData, WeightComposite[] allGradsAcc)
        {
            TaskFactory taskFactory = new TaskFactory();
            Task[] tasks = new Task[this.threadCount];
            ThreadInputDatum[] threadInputData = new ThreadInputDatum[this.threadCount];
            for (int i = 0; i < this.threadCount; i++)
            {
                threadInputData[i].field = new double[this.LayerCount][];
                threadInputData[i].allGradsAcc = new WeightComposite[this.LayerCount];
                threadInputData[i].xValues = new double[this.Sizes[0]]; // inputs
                threadInputData[i].tValues = new double[this.Sizes[this.LayerCount - 1]]; // targets

                threadInputData[i].delim1 = 1.0 / trainData.Length;
                threadInputData[i].delim2 = 1.0 / trainData.Length / this.Sizes[this.LayerCount - 1];
                threadInputData[i].sumSquaredErrors = new double[] {0, 0};
                for (int j = 0; j < this.LayerCount; j++)
                {
                    threadInputData[i].field[j] = new double[this.Sizes[j]];

                    if (j <= 0) continue;
                    threadInputData[i].allGradsAcc[j].Biases = new double[this.Sizes[j]];
                    threadInputData[i].allGradsAcc[j].Weights = MakeMatrix(this.Sizes[j], this.Sizes[j - 1], 0.0);
                }
            }

            List<double[]> innerTrainData = new List<double[]>(trainData);
            List<double[]> innerTrainDataChunk = new List<double[]>();
            int chunk_size = (int) (innerTrainData.Count * 0.8 / this.threadCount);
            while (innerTrainData.Count > 0)
            {
                int currentThread = -1;

                for (int i = 0; i < this.threadCount; i++)
                {
                    // ReSharper disable once InvertIf
                    if ((tasks[i] == null) || tasks[i].IsCompleted)
                    {
                        currentThread = i;
                        break;
                    }
                }

                if (currentThread == -1)
                {
                    Thread.Sleep(20);
                    continue;
                }

                innerTrainDataChunk.Clear();
                while ((innerTrainDataChunk.Count < chunk_size) && (innerTrainData.Count > 0))
                {
                    innerTrainDataChunk.Add(innerTrainData[0]);
                    innerTrainData.RemoveAt(0);
                }
                threadInputData[currentThread].trainDatum = innerTrainDataChunk.ToArray();

                for (int layer = 1; layer < this.LayerCount; layer++)
                {
                    // zero-out values from prev iteration
                    ZeroOut(threadInputData[currentThread].allGradsAcc[layer].Weights);
                    ZeroOut(threadInputData[currentThread].allGradsAcc[layer].Biases);
                }

                tasks[currentThread] =
                    taskFactory.StartNew(this.ComputeGraduateInThread, threadInputData[currentThread]);
            }

            for (int i = 0; i < this.threadCount; i++)
            {
                if (tasks[i] != null)
                {
                    tasks[i].Wait();
                }
            }

            // Всё в allGradsAcc
            for (int i = 0; i < this.threadCount; i++)
            {
                for (int layer = 1; layer < this.LayerCount; layer++)
                {
                    for (int size = 0; size < this.Sizes[layer]; size++)
                    {
                        allGradsAcc[layer].Biases[size] += threadInputData[i].allGradsAcc[layer].Biases[size];
                        for (int prev_size = 0; prev_size < this.Sizes[layer - 1]; prev_size++)
                        {
                            allGradsAcc[layer].Weights[size][prev_size]
                                += threadInputData[i].allGradsAcc[layer].Weights[size][prev_size];
                        }
                    }
                }
            }

            double sumSquaredErrorItem = 0;
            double sumSquaredError = 0;
            for (int i = 0; i < this.threadCount; i++)
            {
                sumSquaredError += threadInputData[i].sumSquaredErrors[0];
                sumSquaredErrorItem += threadInputData[i].sumSquaredErrors[1];
            }

            double[] d = {Math.Sqrt(sumSquaredErrorItem), Math.Sqrt(sumSquaredError)};
            return d;
        }