Exemple #1
0
        public static void Run(ResnetModel modelType)
        {
            OpenFileDialog ofd = new OpenFileDialog {
                Filter = "Image files(*.jpg;*.png;*.gif;*.bmp)|*.jpg;*.png;*.gif;*.bmp|All files(*.*)|*.*"
            };

            if (ofd.ShowDialog() == DialogResult.OK)
            {
                int resnetId = (int)modelType;

                RILogManager.Default?.SendDebug("Mean Loading.");
                string  meanFilePath = InternetFileDownloader.Download(DOWNLOAD_URL_MEAN, MODEL_FILE_MEAN);
                NdArray mean         = CaffemodelDataLoader.ReadBinary(meanFilePath);

                RILogManager.Default?.SendDebug("Model Loading.");
                string             modelFilePath = InternetFileDownloader.Download(Urls[resnetId], FileNames[resnetId]);
                FunctionDictionary nn            = CaffemodelDataLoader.LoadNetWork(true, modelFilePath);
                string[]           classList     = File.ReadAllLines(CLASS_LIST_PATH);

                // Initialize the GPU
                foreach (FunctionStack resNetFunctionBlock in nn.FunctionBlocks)
                {
                    SwitchGPU(resNetFunctionBlock);
                }

                RILogManager.Default?.SendDebug("Model Loading done.");

                do
                {
                    // Set the resolution to 224px x 224px x 3ch before entering the network
                    Bitmap   baseImage   = new Bitmap(ofd.FileName);
                    Bitmap   resultImage = new Bitmap(224, 224, PixelFormat.Format24bppRgb);
                    Graphics g           = Graphics.FromImage(resultImage);
                    g.InterpolationMode = InterpolationMode.Bilinear;
                    g.DrawImage(baseImage, 0, 0, 224, 224);
                    g.Dispose();

                    NdArray imageArray = NdArrayConverter.Image2NdArray(resultImage, false, true);
                    imageArray           -= mean;
                    imageArray.ParentFunc = null;

                    RILogManager.Default?.SendDebug("Start predict.");
                    Stopwatch sw     = Stopwatch.StartNew();
                    NdArray   result = nn.Predict(true, imageArray)[0];
                    sw.Stop();

                    RILogManager.Default?.SendDebug("Result Time : " +
                                                    (sw.ElapsedTicks / (Stopwatch.Frequency / (1000L * 1000L))).ToString("n0") +
                                                    "μs");

                    int maxIndex = Array.IndexOf(result.Data, result.Data.Max());
                    RILogManager.Default?.SendDebug("[" + result.Data[maxIndex] + "] : " + classList[maxIndex]);
                }while (ofd.ShowDialog() == DialogResult.OK);
            }
        }
Exemple #2
0
        public static void Run()
        {
            OpenFileDialog ofd = new OpenFileDialog {
                Filter = "Image Files(*.jpg;*.png;*.gif;*.bmp)|*.jpg;*.png;*.gif;*.bmp|All Files(*.*)|*.*"
            };

            if (ofd.ShowDialog() == DialogResult.OK)
            {
                RILogManager.Default?.SendDebug("Model Loading.");
                string          modelFilePath = InternetFileDownloader.Download(DOWNLOAD_URL, MODEL_FILE);
                List <Function> vgg16Net      = CaffemodelDataLoader.ModelLoad(true, modelFilePath);
                string[]        classList     = File.ReadAllLines(CLASS_LIST_PATH);

                // Initialize the GPU
                for (int i = 0; i < vgg16Net.Count - 1; i++)
                {
                    if (vgg16Net[i] is Convolution2D || vgg16Net[i] is Linear || vgg16Net[i] is MaxPooling)
                    {
                        ((IParallelizable)vgg16Net[i]).SetGpuEnable(true);
                    }
                }

                FunctionStack nn = new FunctionStack(vgg16Net.ToArray());

                // compress layer
                nn.Compress();

                RILogManager.Default?.SendDebug("Model Loading done.");

                do
                {
                    // Set the resolution to 224px x 224px x 3ch before entering the network
                    Bitmap   baseImage   = new Bitmap(ofd.FileName);
                    Bitmap   resultImage = new Bitmap(224, 224, PixelFormat.Format24bppRgb);
                    Graphics g           = Graphics.FromImage(resultImage);
                    g.DrawImage(baseImage, 0, 0, 224, 224);
                    g.Dispose();

                    Real[]  bias       = { -123.68, -116.779, -103.939 }; // The channel order of the correction value follows the input image
                    NdArray imageArray = NdArrayConverter.Image2NdArray(resultImage, false, true, bias);

                    RILogManager.Default?.SendDebug("Start predict.");
                    Stopwatch sw     = Stopwatch.StartNew();
                    NdArray   result = nn.Predict(true, imageArray)[0];
                    sw.Stop();

                    RILogManager.Default?.SendDebug("Result Time : " +
                                                    (sw.ElapsedTicks / (Stopwatch.Frequency / (1000L * 1000L))).ToString("n0") + "μs");

                    int maxIndex = Array.IndexOf(result.Data, result.Data.Max());
                    RILogManager.Default?.SendDebug("[" + result.Data[maxIndex] + "] : " + classList[maxIndex]);
                }while (ofd.ShowDialog() == DialogResult.OK);
            }
        }
        /// <summary>   Initializes a new instance of the MNISTLoader.MnistDataLoader class. </summary>
        public MnistDataLoader()
        {
            string           trainlabelPath   = InternetFileDownloader.Download(DOWNLOAD_URL + TRAIN_LABEL, TRAIN_LABEL);
            MnistLabelLoader trainLabelLoader = MnistLabelLoader.Load(trainlabelPath);

            TrainLabel = trainLabelLoader.labelList;

            string           trainimagePath   = InternetFileDownloader.Download(DOWNLOAD_URL + TRAIN_IMAGE, TRAIN_IMAGE);
            MnistImageLoader trainImageLoader = MnistImageLoader.Load(trainimagePath);

            TrainData = trainImageLoader.bitmapList.ToArray();


            string           teachlabelPath   = InternetFileDownloader.Download(DOWNLOAD_URL + TEACH_LABEL, TEACH_LABEL);
            MnistLabelLoader teachLabelLoader = MnistLabelLoader.Load(teachlabelPath);

            TeachLabel = teachLabelLoader.labelList;

            string           teachimagePath   = InternetFileDownloader.Download(DOWNLOAD_URL + TEACH_IMAGE, TEACH_IMAGE);
            MnistImageLoader teachImageLoader = MnistImageLoader.Load(teachimagePath);

            TeachData = teachImageLoader.bitmapList.ToArray();
        }
Exemple #4
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   Initializes a new instance of the CIFARLoader.CIFARDataLoader class. </summary>
        ///
        /// <param name="isCifar100">   (Optional) True if this object is cifar 100. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        public CIFARDataLoader(bool isCifar100 = false)
        {
            if (!isCifar100)
            {
                string cifar10Path = InternetFileDownloader.Download(DOWNLOAD_URL + CIFAR10, CIFAR10);
                Dictionary <string, byte[]> data = Tar.GetExtractedStreams(cifar10Path);

                LabelNames = Encoding.ASCII.GetString(data["cifar-10-batches-bin/batches.meta.txt"]).Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);

                List <byte>   trainLabel = new List <byte>();
                List <byte[]> trainData  = new List <byte[]>();

                foreach (var t in CIFAR10TrainNames)
                {
                    for (int j = 0; j < CIFAR10_DATA_COUNT; j++)
                    {
                        trainLabel.Add(data[t][j * (DATA_SIZE + LABEL_SIZE)]);
                        byte[] tmpArray = new byte[DATA_SIZE];
                        Array.Copy(data[t], j * (DATA_SIZE + LABEL_SIZE) + LABEL_SIZE, tmpArray, 0, tmpArray.Length);
                        trainData.Add(tmpArray);
                    }
                }

                TrainLabel = trainLabel.ToArray();
                TrainData  = trainData.ToArray();

                List <byte>   testLabel = new List <byte>();
                List <byte[]> testData  = new List <byte[]>();

                for (int j = 0; j < CIFAR10_DATA_COUNT; j++)
                {
                    testLabel.Add(data[CIFAR10TestName][j * (DATA_SIZE + LABEL_SIZE)]);
                    byte[] tmpArray = new byte[DATA_SIZE];
                    Array.Copy(data[CIFAR10TestName], j * (DATA_SIZE + LABEL_SIZE) + LABEL_SIZE, tmpArray, 0, tmpArray.Length);
                    testData.Add(tmpArray);
                }

                TestLabel = testLabel.ToArray();
                TestData  = testData.ToArray();
            }
            else
            {
                string cifar100Path = InternetFileDownloader.Download(DOWNLOAD_URL + CIFAR100, CIFAR100);
                Dictionary <string, byte[]> data = Tar.GetExtractedStreams(cifar100Path);

                LabelNames     = Encoding.ASCII.GetString(data["cifar-100-binary/coarse_label_names.txt"]).Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
                FineLabelNames = Encoding.ASCII.GetString(data["cifar-100-binary/fine_label_names.txt"]).Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);

                List <byte>   trainLabel     = new List <byte>();
                List <byte>   trainFineLabel = new List <byte>();
                List <byte[]> trainData      = new List <byte[]>();

                for (int j = 0; j < CIFAR100_DATA_COUNT; j++)
                {
                    trainLabel.Add(data[CIFAR100TrainName][j * (DATA_SIZE + LABEL_SIZE + LABEL_SIZE)]);
                    trainFineLabel.Add(data[CIFAR100TrainName][j * (DATA_SIZE + LABEL_SIZE + LABEL_SIZE) + LABEL_SIZE]);
                    byte[] tmpArray = new byte[DATA_SIZE];
                    Array.Copy(data[CIFAR100TrainName], j * (DATA_SIZE + LABEL_SIZE + LABEL_SIZE) + LABEL_SIZE + LABEL_SIZE, tmpArray, 0,
                               tmpArray.Length);
                    trainData.Add(tmpArray);
                }

                TrainLabel     = trainLabel.ToArray();
                TrainFineLabel = trainFineLabel.ToArray();
                TrainData      = trainData.ToArray();

                List <byte>   testLabel     = new List <byte>();
                List <byte>   testFineLabel = new List <byte>();
                List <byte[]> testData      = new List <byte[]>();

                for (int j = 0; j < CIFAR100_TEST_DATA_COUNT; j++)
                {
                    testLabel.Add(data[CIFAR100TestName][j * (DATA_SIZE + LABEL_SIZE + LABEL_SIZE)]);
                    testFineLabel.Add(data[CIFAR100TestName][j * (DATA_SIZE + LABEL_SIZE + LABEL_SIZE) + LABEL_SIZE]);
                    byte[] tmpArray = new byte[DATA_SIZE];
                    Array.Copy(data[CIFAR100TestName], j * (DATA_SIZE + LABEL_SIZE + LABEL_SIZE) + LABEL_SIZE + LABEL_SIZE, tmpArray, 0, tmpArray.Length);
                    testData.Add(tmpArray);
                }

                TestLabel     = testLabel.ToArray();
                TestFineLabel = testFineLabel.ToArray();
                TestData      = testData.ToArray();
            }
        }
Exemple #5
0
        public static void Run()
        {
            RILogManager.Default?.SendDebug("Building Vocabulary.");

            Vocabulary vocabulary = new Vocabulary();
            string     trainPath  = InternetFileDownloader.Download(DOWNLOAD_URL + TRAIN_FILE, TRAIN_FILE);
            string     testPath   = InternetFileDownloader.Download(DOWNLOAD_URL + TEST_FILE, TEST_FILE);

            int[] trainData = vocabulary.LoadData(trainPath);
            int[] testData  = vocabulary.LoadData(testPath);
            int   nVocab    = vocabulary.Length;

            RILogManager.Default?.SendDebug("Network Initializing.");
            FunctionStack model = new FunctionStack("Test9",
                                                    new EmbedID(nVocab, N_UNITS, name: "l1 EmbedID"),
                                                    new Linear(true, N_UNITS, N_UNITS, name: "l2 Linear"),
                                                    new Tanh("l2 Tanh"),
                                                    new Linear(true, N_UNITS, nVocab, name: "l3 Linear"),
                                                    new Softmax("l3 Softmax")
                                                    );

            model.SetOptimizer(new Adam());

            List <int> s = new List <int>();

            RILogManager.Default?.SendDebug("Train Start.");
            SoftmaxCrossEntropy softmaxCrossEntropy = new SoftmaxCrossEntropy();

            for (int epoch = 0; epoch < TRAINING_EPOCHS; epoch++)
            {
                for (int pos = 0; pos < trainData.Length; pos++)
                {
                    NdArray h  = new NdArray(new Real[N_UNITS]);
                    int     id = trainData[pos];
                    s.Add(id);

                    if (id == vocabulary.EosID)
                    {
                        Real            accumloss = 0;
                        Stack <NdArray> tmp       = new Stack <NdArray>();

                        for (int i = 0; i < s.Count; i++)
                        {
                            int tx = i == s.Count - 1 ? vocabulary.EosID : s[i + 1];

                            //l1 EmbedID
                            NdArray l1 = model.Functions[0].Forward(true, s[i])[0];

                            //l2 Linear
                            NdArray l2 = model.Functions[1].Forward(true, h)[0];

                            //Add
                            NdArray xK = l1 + l2;

                            //l2 Tanh
                            h = model.Functions[2].Forward(true, xK)[0];

                            //l3 Linear
                            NdArray h2 = model.Functions[3].Forward(true, h)[0];

                            Real loss = softmaxCrossEntropy.Evaluate(h2, tx);
                            tmp.Push(h2);
                            accumloss += loss;
                        }

                        RILogManager.Default?.SendDebug(accumloss.ToString());

                        for (int i = 0; i < s.Count; i++)
                        {
                            model.Backward(true, tmp.Pop());
                        }

                        model.Update();
                        s.Clear();
                    }

                    if (pos % 100 == 0)
                    {
                        RILogManager.Default?.SendDebug(pos + "/" + trainData.Length + " finished");
                    }
                }
            }

            RILogManager.Default?.SendDebug("Test Start.");

            Real       sum     = 0;
            int        wnum    = 0;
            List <int> ts      = new List <int>();
            bool       unkWord = false;

            for (int pos = 0; pos < 1000; pos++)
            {
                int id = testData[pos];
                ts.Add(id);

                if (id > trainData.Length)
                {
                    unkWord = true;
                }

                if (id == vocabulary.EosID)
                {
                    if (!unkWord)
                    {
                        RILogManager.Default?.SendDebug("pos: " + pos);
                        RILogManager.Default?.SendDebug("tsLen: " + ts.Count);
                        RILogManager.Default?.SendDebug("sum: " + sum);
                        RILogManager.Default?.SendDebug("wnum: " + wnum);
                        RILogManager.Default?.ViewerSendWatch("pos", pos);
                        RILogManager.Default?.ViewerSendWatch("tsLen", ts.Count);
                        RILogManager.Default?.ViewerSendWatch("sum", sum);
                        RILogManager.Default?.ViewerSendWatch("wnum", wnum);


                        sum  += CalPs(model, ts);
                        wnum += ts.Count - 1;
                    }
                    else
                    {
                        unkWord = false;
                    }

                    ts.Clear();
                }
            }

            RILogManager.Default?.SendDebug(Math.Pow(2.0, sum / wnum).ToString());
        }
Exemple #6
0
        public static void Run()
        {
            _outputStream = File.Create(LogPath);

            _logWriter = new HistogramLogWriter(_outputStream);
            _logWriter.Write(DateTime.Now);

            var recorder = HistogramFactory
                           .With64BitBucketSize()
                           ?.WithValuesFrom(1)
                           ?.WithValuesUpTo(2345678912345)
                           ?.WithPrecisionOf(3)
                           ?.WithThreadSafeWrites()
                           ?.WithThreadSafeReads()
                           ?.Create();

            var accumulatingHistogram = new LongHistogram(2345678912345, 3);

            var size = accumulatingHistogram.GetEstimatedFootprintInBytes();

            RILogManager.Default?.SendDebug("Histogram size = {0} bytes ({1:F2} MB)", size, size / 1024.0 / 1024.0);


            RILogManager.Default?.SendDebug("Recorded latencies [in system clock ticks]");
            accumulatingHistogram.OutputPercentileDistribution(Console.Out, outputValueUnitScalingRatio: OutputScalingFactor.None, useCsvFormat: true);
            Console.WriteLine();

            RILogManager.Default?.SendDebug("Recorded latencies [in usec]");
            accumulatingHistogram.OutputPercentileDistribution(Console.Out, outputValueUnitScalingRatio: OutputScalingFactor.TimeStampToMicroseconds, useCsvFormat: true);
            Console.WriteLine();

            RILogManager.Default?.SendDebug("Recorded latencies [in msec]");
            accumulatingHistogram.OutputPercentileDistribution(Console.Out, outputValueUnitScalingRatio: OutputScalingFactor.TimeStampToMilliseconds, useCsvFormat: true);
            Console.WriteLine();

            RILogManager.Default?.SendDebug("Recorded latencies [in sec]");
            accumulatingHistogram.OutputPercentileDistribution(Console.Out, outputValueUnitScalingRatio: OutputScalingFactor.TimeStampToSeconds, useCsvFormat: true);

            DocumentResults(accumulatingHistogram, recorder);

            RILogManager.Default?.SendDebug("Build Vocabulary.");

            DocumentResults(accumulatingHistogram, recorder);

            Vocabulary vocabulary = new Vocabulary();

            DocumentResults(accumulatingHistogram, recorder);

            string trainPath = InternetFileDownloader.Download(DOWNLOAD_URL + TRAIN_FILE, TRAIN_FILE);

            DocumentResults(accumulatingHistogram, recorder);

            string validPath = InternetFileDownloader.Download(DOWNLOAD_URL + VALID_FILE, VALID_FILE);

            DocumentResults(accumulatingHistogram, recorder);

            string testPath = InternetFileDownloader.Download(DOWNLOAD_URL + TEST_FILE, TEST_FILE);

            DocumentResults(accumulatingHistogram, recorder);


            int[] trainData = vocabulary.LoadData(trainPath);
            DocumentResults(accumulatingHistogram, recorder);

            int[] validData = vocabulary.LoadData(validPath);
            DocumentResults(accumulatingHistogram, recorder);

            int[] testData = vocabulary.LoadData(testPath);
            DocumentResults(accumulatingHistogram, recorder);

            int nVocab = vocabulary.Length;

            RILogManager.Default?.SendDebug("Network Initializing.");
            FunctionStack model = new FunctionStack("Test10",
                                                    new EmbedID(nVocab, N_UNITS, name: "l1 EmbedID"),
                                                    new Dropout(),
                                                    new LSTM(true, N_UNITS, N_UNITS, name: "l2 LSTM"),
                                                    new Dropout(),
                                                    new LSTM(true, N_UNITS, N_UNITS, name: "l3 LSTM"),
                                                    new Dropout(),
                                                    new Linear(true, N_UNITS, nVocab, name: "l4 Linear")
                                                    );

            DocumentResults(accumulatingHistogram, recorder);

            // Do not cease at the given threshold, correct the rate by taking the rate from L2Norm of all parameters
            GradientClipping gradientClipping = new GradientClipping(threshold: GRAD_CLIP);
            SGD sgd = new SGD(learningRate: 1);

            model.SetOptimizer(gradientClipping, sgd);
            DocumentResults(accumulatingHistogram, recorder);

            Real wholeLen = trainData.Length;
            int  jump     = (int)Math.Floor(wholeLen / BATCH_SIZE);
            int  epoch    = 0;

            Stack <NdArray[]> backNdArrays = new Stack <NdArray[]>();

            RILogManager.Default?.SendDebug("Train Start.");
            double  dVal;
            NdArray x = new NdArray(new[] { 1 }, BATCH_SIZE, (Function)null);
            NdArray t = new NdArray(new[] { 1 }, BATCH_SIZE, (Function)null);

            for (int i = 0; i < jump * N_EPOCH; i++)
            {
                for (int j = 0; j < BATCH_SIZE; j++)
                {
                    x.Data[j] = trainData[(int)((jump * j + i) % wholeLen)];
                    t.Data[j] = trainData[(int)((jump * j + i + 1) % wholeLen)];
                }

                NdArray[] result  = model.Forward(true, x);
                Real      sumLoss = new SoftmaxCrossEntropy().Evaluate(result, t);
                backNdArrays.Push(result);
                RILogManager.Default?.SendDebug("[{0}/{1}] Loss: {2}", i + 1, jump, sumLoss);

                //Run truncated BPTT
                if ((i + 1) % BPROP_LEN == 0)
                {
                    for (int j = 0; backNdArrays.Count > 0; j++)
                    {
                        RILogManager.Default?.SendDebug("backward" + backNdArrays.Count);
                        model.Backward(true, backNdArrays.Pop());
                    }

                    model.Update();
                    model.ResetState();
                }

                if ((i + 1) % jump == 0)
                {
                    epoch++;
                    RILogManager.Default?.SendDebug("evaluate");
                    dVal = Evaluate(model, validData);
                    RILogManager.Default?.SendDebug($"validation perplexity: {dVal}");

                    if (epoch >= 6)
                    {
                        sgd.LearningRate /= 1.2;
                        RILogManager.Default?.SendDebug("learning rate =" + sgd.LearningRate);
                    }
                }
                DocumentResults(accumulatingHistogram, recorder);
            }

            RILogManager.Default?.SendDebug("test start");
            dVal = Evaluate(model, testData);
            RILogManager.Default?.SendDebug("test perplexity:" + dVal);
            DocumentResults(accumulatingHistogram, recorder);

            _logWriter.Dispose();
            _outputStream.Dispose();


            RILogManager.Default?.SendDebug("Log contents");
            RILogManager.Default?.SendDebug(File.ReadAllText(LogPath));
            Console.WriteLine();
            RILogManager.Default?.SendDebug("Percentile distribution (values reported in milliseconds)");
            accumulatingHistogram.OutputPercentileDistribution(Console.Out, outputValueUnitScalingRatio: OutputScalingFactor.TimeStampToMilliseconds, useCsvFormat: true);

            RILogManager.Default?.SendDebug("Mean: " + BytesToString(accumulatingHistogram.GetMean()) + ", StdDev: " +
                                            BytesToString(accumulatingHistogram.GetStdDeviation()));
        }
Exemple #7
0
        public static void Run()
        {
            Console.WriteLine("Build Vocabulary.");

            Vocabulary vocabulary = new Vocabulary();

            string trainPath = InternetFileDownloader.Download(DOWNLOAD_URL + TRAIN_FILE, TRAIN_FILE);
            string validPath = InternetFileDownloader.Download(DOWNLOAD_URL + VALID_FILE, VALID_FILE);
            string testPath  = InternetFileDownloader.Download(DOWNLOAD_URL + TEST_FILE, TEST_FILE);

            int[] trainData = vocabulary.LoadData(trainPath);
            int[] validData = vocabulary.LoadData(validPath);
            int[] testData  = vocabulary.LoadData(testPath);

            int nVocab = vocabulary.Length;

            Console.WriteLine("Network Initilizing.");
            FunctionStack model = new FunctionStack(
                new EmbedID(nVocab, N_UNITS, name: "l1 EmbedID"),
                new Dropout(),
                new LSTM(N_UNITS, N_UNITS, name: "l2 LSTM"),
                new Dropout(),
                new LSTM(N_UNITS, N_UNITS, name: "l3 LSTM"),
                new Dropout(),
                new Linear(N_UNITS, nVocab, name: "l4 Linear")
                );

            //与えられたthresholdで頭打ちではなく、全パラメータのL2Normからレートを取り補正を行う
            GradientClipping gradientClipping = new GradientClipping(threshold: GRAD_CLIP);
            SGD sgd = new SGD(learningRate: 1);

            model.SetOptimizer(gradientClipping, sgd);

            Real wholeLen = trainData.Length;
            int  jump     = (int)Math.Floor(wholeLen / BATCH_SIZE);
            int  epoch    = 0;

            Stack <NdArray[]> backNdArrays = new Stack <NdArray[]>();

            Console.WriteLine("Train Start.");

            for (int i = 0; i < jump * N_EPOCH; i++)
            {
                NdArray x = new NdArray(new[] { 1 }, BATCH_SIZE);
                NdArray t = new NdArray(new[] { 1 }, BATCH_SIZE);

                for (int j = 0; j < BATCH_SIZE; j++)
                {
                    x.Data[j] = trainData[(int)((jump * j + i) % wholeLen)];
                    t.Data[j] = trainData[(int)((jump * j + i + 1) % wholeLen)];
                }

                NdArray[] result  = model.Forward(x);
                Real      sumLoss = new SoftmaxCrossEntropy().Evaluate(result, t);
                backNdArrays.Push(result);
                Console.WriteLine("[{0}/{1}] Loss: {2}", i + 1, jump, sumLoss);

                //Run truncated BPTT
                if ((i + 1) % BPROP_LEN == 0)
                {
                    for (int j = 0; backNdArrays.Count > 0; j++)
                    {
                        Console.WriteLine("backward" + backNdArrays.Count);
                        model.Backward(backNdArrays.Pop());
                    }

                    model.Update();
                    model.ResetState();
                }

                if ((i + 1) % jump == 0)
                {
                    epoch++;
                    Console.WriteLine("evaluate");
                    Console.WriteLine("validation perplexity: {0}", Evaluate(model, validData));

                    if (epoch >= 6)
                    {
                        sgd.LearningRate /= 1.2;
                        Console.WriteLine("learning rate =" + sgd.LearningRate);
                    }
                }
            }

            Console.WriteLine("test start");
            Console.WriteLine("test perplexity:" + Evaluate(model, testData));
        }