public void ReMappingFromWeightVector(WeightVector weightVector, bool normalize = true)
        {
            var newDictKtoF = new Dictionary<int, string>();
            var newDictFtoK = new Dictionary<string, int>();
            //var weightDict = new Dictionary<int, double>();
            //int k = 0;

            //var elements = from element in weightVector.WeightArray
            //               orderby element descending
            //               where element > 1
            //               select element;

            //var sortedDictionary = from pair in weightVector.WDictionary
            //                       where Math.Abs(pair.Value) > 1
            //                        orderby Math.Abs(pair.Value) descending
            //                        select pair;
            const double limit = 0;
            var newWeights = new double[weightVector.FeatureCount];
            int featureCount = 0;
            Array.Clear(newWeights, 0, newWeights.Length);
            double max = 0;

            for (int i = 0; i < weightVector.FeatureCount; i++)
            {
                if (max < Math.Abs(weightVector.WeightArray[i]))
                {
                    max = Math.Abs(weightVector.WeightArray[i]);
                }
                if (Math.Abs(weightVector.WeightArray[i]) > limit)
                {
                    newWeights[featureCount] = weightVector.WeightArray[i];
                    var feature = DictKToFeatures[i];
                    newDictFtoK[feature] = featureCount;
                    newDictKtoF[featureCount] = feature;
                    featureCount++;
                }
            }

            //if (normalize)
            //{
            //    for (int i = 0; i < featureCount; i++)
            //    {
            //        newWeights[i] /= max;
            //    }
            //}
            weightVector.WeightArray = newWeights;
            weightVector.FeatureCount = featureCount;
            DictFeaturesToK = weightVector.FeatureKDictionary = newDictFtoK;
            DictKToFeatures = newDictKtoF;
            if (normalize)
            {
                weightVector.AvgNormalize();
            }
        }
        public WeightVector RunIterations(WeightVector weightVector, int iterationCount, int threadCount = 1)
        {
            _weightVector = weightVector;

            for (var iter = 0; iter < iterationCount; iter++)
            {
                Console.WriteLine(DateTime.Now + " running iteration " + iter);

                var newWeightVector = _weightVector.DeepCopy();
                SetForwardBackwordAlgo(newWeightVector);
                if (threadCount > 1)
                {
                    var doneEvents = new ManualResetEvent[threadCount];
                    var partition = newWeightVector.FeatureCount / threadCount;

                    for (int threadIndex = 0; threadIndex < threadCount; threadIndex++)
                    {
                        var start = threadIndex*partition;
                        var end = start + partition;
                        end = end > newWeightVector.FeatureCount ? newWeightVector.FeatureCount : end;
                        doneEvents[threadIndex] = new ManualResetEvent(false);

                        var info = new ThreadInfoObject(this, start, end, newWeightVector,
                            doneEvents[threadIndex], null);
                        ThreadPool.QueueUserWorkItem(info.StartGradientComputing, threadIndex);
                    }

                    WaitHandle.WaitAll(doneEvents);
                }
                else
                {
                    ComputeRange(0, _weightVector.FeatureCount, newWeightVector);
                }
                _weightVector = newWeightVector;
                if (iter + 1 < iterationCount)
                {
                    _weightVector.AvgNormalize();
                }
            }
            _weightVector.AvgNormalize();
            return _weightVector;
        }