Exemple #1
0
        public override void Setup()
        {
            base.Setup();

            if (!(MmlRecommenderInstance is BPRFM))
            {
                throw new WrapRecException("Expect ml-class 'BPRFM' for 'MmlBprfmRecommender'");
            }

            var wBprFm = MmlRecommenderInstance as WeightedBPRFM;

            if (wBprFm != null)
            {
                wBprFm.NumGroups = int.Parse(SetupParameters["numGroups"]);
            }

            if (SetupParameters.ContainsKey("Normalize"))
            {
                ((BPRFM)MmlRecommenderInstance).Normalize = bool.Parse(SetupParameters["Normalize"]);
            }

            if (SetupParameters.ContainsKey("ingoreFeatures"))
            {
                ((BPRFM)MmlRecommenderInstance).IgnoreFeaturesOnPrediction = bool.Parse(SetupParameters["ingoreFeatures"]);
            }
        }
Exemple #2
0
        public Task GetSetupParameters()
        {
            AssertOnlyInSetupMode();
            var setupParameters = SetupParameters.Get(ServerStore);

            using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context))
                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    writer.WriteStartObject();
                    writer.WritePropertyName(nameof(SetupParameters.FixedServerPortNumber));

                    if (setupParameters.FixedServerPortNumber.HasValue)
                    {
                        writer.WriteInteger(setupParameters.FixedServerPortNumber.Value);
                    }
                    else
                    {
                        writer.WriteNull();
                    }

                    writer.WriteComma();

                    writer.WritePropertyName(nameof(SetupParameters.IsDocker));
                    writer.WriteBool(setupParameters.IsDocker);

                    writer.WriteEndObject();
                }

            return(Task.CompletedTask);
        }
Exemple #3
0
        public override void Setup()
        {
            bool   hasHeader = (SetupParameters.ContainsKey("hasHeader") && SetupParameters["hasHeader"] == "false") ? false : true;
            string delimiter = SetupParameters.ContainsKey("delimiter") ? SetupParameters["delimiter"].Replace("\\t", "\t") : ",";

            CsvConfig = new CsvConfiguration()
            {
                Delimiter       = delimiter,
                HasHeaderRecord = hasHeader
            };

            if (SetupParameters.ContainsKey("header"))
            {
                Header = SetupParameters["header"].Split(',').Select(h =>
                {
                    var parts = h.Split(':');

                    if (parts.Length == 1)
                    {
                        return new { Header = parts[0], Type = "d" }
                    }
                    ;

                    return(new { Header = parts[0], Type = parts[1] });
                }).ToDictionary(h => h.Header, h => h.Type);

                int i = 0;
                FieldIndices = SetupParameters["header"].Split(',').ToDictionary(h => h.Split(':')[0], h => i++);
            }
        }
Exemple #4
0
        public override void Setup()
        {
            if (SetupParameters.ContainsKey("dim"))
            {
                SetupParameters["dim"] = SetupParameters["dim"].Replace('-', ',');
            }

            if (SetupParameters.ContainsKey("regular"))
            {
                SetupParameters["regular"] = SetupParameters["regular"].Replace('-', ',');
            }

            if (!SetupParameters.ContainsKey("libFmPath"))
            {
                SetupParameters["libFmPath"] = "libfm.net.exe";
            }

            LibFmArguments = SetupParameters.Where(kv => kv.Key.ToLower() != "libfmpath")
                             .ToDictionary(kv => "-" + kv.Key, kv => kv.Value)
                             .SelectMany(kv => new string[] { kv.Key, kv.Value }).ToList();

            if (!SetupParameters.ContainsKey("save_model"))
            {
                LibFmArguments.Add("-save_model train.model");
            }

            // default data type
            DataType = DataType.Ratings;

            FeatureBuilder = new FmFeatureBuilder();
        }
Exemple #5
0
        public override void Setup()
        {
            if (!Split.Container.IsLoaded)
            {
                Logger.Current.Info("Loading DataContainer '{0}'...", Split.Container.Id);
                Split.Container.Load();
            }

            OutputPath = Path.Combine(ExperimentManager.ResultsFolder, SetupParameters["outputPath"]);

            if (SetupParameters.ContainsKey("contextNames"))
            {
                ContextNames = SetupParameters["contextNames"].Split(',').ToList();
            }
            else
            {
                ContextNames = new List <string>();
            }

            UserMapper    = new Mapping();
            ContextMapper = new Mapping();

            // burn id 0
            UserMapper.ToInternalID("burn");
            ContextMapper.ToInternalID("burn");

            UserItems = Split.Container.Users.Values.ToDictionary(u => u.Id,
                                                                  u => u.Feedbacks.Select(f => f.Item.Id).ToList());

            AllItems = Split.Container.Items.Values.Select(i => i.Id).ToList();
        }
        public override void Setup()
        {
            base.Setup();

            if (SetupParameters.ContainsKey("predictionFile"))
            {
                _predictionWriter = new MultiKeyDictionary <int, int, StreamWriter>();
            }
        }
Exemple #7
0
        public override void Setup()
        {
            try
            {
                // build recommender object
                Type mmlRecommenderType = Helpers.ResolveType(SetupParameters["ml-class"]);
                MmlRecommenderInstance = (IRecommender)mmlRecommenderType.GetConstructor(Type.EmptyTypes).Invoke(null);

                if (typeof(ITimeAwareRatingPredictor).IsAssignableFrom(mmlRecommenderType))
                {
                    DataType = DataType.TimeAwareRating;
                }
                else if (typeof(IRatingPredictor).IsAssignableFrom(mmlRecommenderType))
                {
                    DataType = DataType.Ratings;
                }
                else if (typeof(ItemRecommender).IsAssignableFrom(mmlRecommenderType))
                {
                    DataType = DataType.PosFeedback;
                }
                else
                {
                    throw new WrapRecException(string.Format("Unknown MmlRecommender class: {0}", SetupParameters["ml-class"]));
                }

                // Set properties
                foreach (var param in SetupParameters.Where(kv => kv.Key != "ml-class" && kv.Key != "numGroups" && kv.Key != "ingoreFeatures"))
                {
                    PropertyInfo pi = MmlRecommenderInstance.GetType().GetProperty(param.Key);

                    // in case the value of attribute is empty ignore
                    // empty attributes are only used for logging purposes
                    if (string.IsNullOrEmpty(param.Value))
                    {
                        continue;
                    }

                    object paramVal;
                    if (pi.PropertyType.IsEnum)
                    {
                        paramVal = Enum.Parse(pi.PropertyType, param.Value);
                    }
                    else
                    {
                        paramVal = param.Value;
                    }

                    pi.SetValue(MmlRecommenderInstance, Convert.ChangeType(paramVal, pi.PropertyType));
                }
            }
            catch (Exception ex)
            {
                throw new WrapRecException(string.Format("Cannot resolve MmlRecommender: {0}\n{1}", ex.Message, ex.StackTrace));
            }
        }
        public string WriteFile(string text, SetupParameters setupParameters)
        {
            createDirectory(setupParameters.WorkingDirectory);
            createDirectory(setupParameters.ScriptDirectory);

             var fileName = setupParameters.ScriptDirectory + "\\" + DateTime.UtcNow.ToString("yyyyMMddTHHmmss") + ".sql";

            File.WriteAllText(fileName,text);

            return fileName;
        }
Exemple #9
0
        public override void Setup()
        {
            if (SetupParameters.ContainsKey("delimiter"))
            {
                Delimiter = SetupParameters["delimiter"].Replace("\\t", "\t");
            }
            else
            {
                Delimiter = "\t";
            }

            ResultFiles = SetupParameters["sourceFiles"].Split(',')
                          .Select(eId => Path.Combine(ExperimentManager.ResultsFolder, eId)).ToArray();

            OutputFile = Path.Combine(ExperimentManager.ResultsFolder, SetupParameters["outputFile"]);
        }
Exemple #10
0
        private void LoadFmModel()
        {
            string modelFile = SetupParameters.ContainsKey("save_model") ?
                               SetupParameters["save_model"] : "train.model";

            modelFile = modelFile.Replace("\"", "");

            var lines = File.ReadAllLines(modelFile);

            // TODO: if dim is 0,0,x w0 and w would be 0 and the format of the file would be different
            float w0 = float.Parse(lines.Skip(1).First());

            _w = new float[] { w0 }.Concat(
                lines.Skip(3).TakeWhile(l => !l.StartsWith("#")).Select(l => float.Parse(l))).ToList();

            _v = lines.Skip(_w.Count + 3)
                 .Select(l => l.Split(' ').Select(v => float.Parse(v)).ToArray()).ToList();
        }
Exemple #11
0
        public async Task GetSetupParameters()
        {
            AssertOnlyInSetupMode();
            var setupParameters = await SetupParameters.Get(ServerStore);

            using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context))
                await using (var writer = new AsyncBlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    writer.WriteStartObject();
                    writer.WritePropertyName(nameof(SetupParameters.FixedServerPortNumber));

                    if (setupParameters.FixedServerPortNumber.HasValue)
                    {
                        writer.WriteInteger(setupParameters.FixedServerPortNumber.Value);
                    }
                    else
                    {
                        writer.WriteNull();
                    }

                    writer.WriteComma();

                    writer.WritePropertyName(nameof(SetupParameters.IsDocker));
                    writer.WriteBool(setupParameters.IsDocker);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(SetupParameters.IsAzure));
                    writer.WriteBool(setupParameters.IsAzure);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(SetupParameters.IsAws));
                    writer.WriteBool(setupParameters.IsAws);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(SetupParameters.RunningOnPosix));
                    writer.WriteBool(setupParameters.RunningOnPosix);
                    writer.WriteComma();

                    writer.WritePropertyName(nameof(SetupParameters.RunningOnMacOsx));
                    writer.WriteBool(setupParameters.RunningOnMacOsx);

                    writer.WriteEndObject();
                }
        }
Exemple #12
0
        public override void Setup()
        {
            var readerPaths = ExperimentManager.ConfigRoot.Descendants("reader")
                              .ToDictionary(el => el.Attribute("id").Value.Inject(ExperimentManager.Parameters), el => el.Attribute("path").Value.Inject(ExperimentManager.Parameters));

            Part1Path  = readerPaths[SetupParameters["part1Reader"]];
            Part2Path  = readerPaths[SetupParameters["part2Reader"]];
            SourcePath = readerPaths[SetupParameters["sourceReader"]];

            Part1Ratio = float.Parse(SetupParameters["part1Ratio"]);

            var hasHeaderAttr = ExperimentManager.ConfigRoot.Descendants("reader")
                                .Where(el => el.Attribute("id").Value.Inject(ExperimentManager.Parameters) == SetupParameters["sourceReader"]).Single()
                                .Attribute("hasHeader");

            HasHeader = hasHeaderAttr != null && hasHeaderAttr.Value == "false" ? false : true;

            Shuffle = SetupParameters.ContainsKey("shuffle") && SetupParameters["shuffle"] == "false" ? false : true;
        }
Exemple #13
0
        public override Dictionary <string, string> GetModelParameters()
        {
            string mlClass = SetupParameters["ml-class"].Split('.').Last();

            return(SetupParameters.Select(kv =>
            {
                if (kv.Key == "ml-class")
                {
                    return new KeyValuePair <string, string>("ml-class", mlClass);
                }

                if (string.IsNullOrEmpty(kv.Value))
                {
                    return new KeyValuePair <string, string>(kv.Key,
                                                             MmlRecommenderInstance.GetType().GetProperty(kv.Key).GetValue(MmlRecommenderInstance).ToString());
                }

                return kv;
            }).ToDictionary(kv => kv.Key, kv => kv.Value));
        }
        public override void Setup()
        {
            base.Setup();

            if (!(MmlRecommenderInstance is FM))
            {
                throw new WrapRecException("Expect ml-class 'FM' for 'MmlFmRecommender'");
            }

            var wFm = MmlRecommenderInstance as WFM;

            if (wFm != null)
            {
                wFm.NumGroups = int.Parse(SetupParameters["numGroups"]);
            }

            if (SetupParameters.ContainsKey("Normalize"))
            {
                ((FM)MmlRecommenderInstance).Normalize = bool.Parse(SetupParameters["Normalize"]);
            }
        }
Exemple #15
0
        public virtual void Setup()
        {
            if (!Split.Container.IsLoaded)
            {
                Logger.Current.Info("Loading DataContainer '{0}'...", Split.Container.Id);
                Split.Container.Load();
            }
            if (!EvaluationContext.IsSetuped)
            {
                Logger.Current.Info("Setuping evaluation context '{0}'...", EvaluationContext.Id);
                EvaluationContext.Setup();
            }

            Logger.Current.Info("Setuping model '{0}'...", Model.Id);
            Model.Setup();

            if (SetupParameters.ContainsKey("multiEval"))
            {
                MultiEval       = int.Parse(SetupParameters["multiEval"]);
                Model.Iterated += ModelIterated;
            }
        }
Exemple #16
0
        public override void Setup()
        {
            base.Setup();

            // the CrossValidationSplit is already setuped by its parent split
            if (IsSetup || Type == SplitType.CROSSVALIDATION_SUBSPLIT || Type == SplitType.DYNAMIC_SUBSPLIT)
            {
                IsSetup = true;
                return;
            }

            // Setuping splits
            float[] trainRatios = { 1f };
            int     numFolds    = 5;

            if (SetupParameters.ContainsKey("trainRatios"))
            {
                trainRatios = SetupParameters["trainRatios"].Split(',').Select(tr => float.Parse(tr)).ToArray();
            }

            if (SetupParameters.ContainsKey("numFolds"))
            {
                numFolds = int.Parse(SetupParameters["numFolds"]);
            }

            if (Type == SplitType.STATIC)
            {
                _train = Container.Feedbacks.Where(f => f.SliceType == FeedbackSlice.TRAIN);
                _test  = Container.Feedbacks.Where(f => f.SliceType == FeedbackSlice.TEST);
            }
            else if (Type == SplitType.DYNAMIC)
            {
                var feedbacks = Container.Feedbacks.Shuffle();

                SubSplits = trainRatios.Select(tr =>
                {
                    // the trainCount wont be calculated until the enumerator is being used
                    // So container is not required to be loaded in advanced
                    var trainCount = new Lazy <int>(() => Convert.ToInt32(Container.Feedbacks.Count * tr));

                    var train = feedbacks.Take(trainCount);
                    var test  = feedbacks.Skip(trainCount);

                    var ss = new FeedbackSimpleSplit(train, test)
                    {
                        Id              = Id + "-" + tr.ToString(),
                        Type            = SplitType.DYNAMIC_SUBSPLIT,
                        Container       = this.Container,
                        SetupParameters = this.SetupParameters
                    };
                    ss.Setup();
                    return(ss);
                });
            }
            else if (Type == SplitType.CROSSVALIDATION)
            {
                var feedbacks = Container.Feedbacks.Shuffle();
                // here all parameters of Take and Skip functions are calculated with lazyLoading
                // The SubSplits are formed when the enumeration is being started
                var foldCount = new Lazy <int>(() => (int)((1f / numFolds) * Container.Feedbacks.Count));

                SubSplits = Enumerable.Range(0, numFolds)
                            .Select(i =>
                {
                    var train = feedbacks.Take(() => (numFolds - i - 1) * foldCount.Value)
                                .Concat(feedbacks.Skip(() => (numFolds - i) * foldCount.Value)
                                        .Take(() => i * foldCount.Value));
                    var test = feedbacks.Skip(() => (numFolds - i - 1) * foldCount.Value)
                               .Take(foldCount);
                    var ss = new FeedbackSimpleSplit(train, test)
                    {
                        Id              = this.Id + "-fold" + (i + 1),
                        Type            = SplitType.CROSSVALIDATION_SUBSPLIT,
                        Container       = this.Container,
                        SetupParameters = this.SetupParameters
                    };
                    ss.Setup();
                    return(ss);
                });
            }
            IsSetup = true;
        }
Exemple #17
0
 public override Dictionary <string, string> GetModelParameters()
 {
     return(SetupParameters.Where(kv => kv.Key.ToLower() != "libfmpath").ToDictionary(kv => kv.Key, kv => kv.Value));
 }
Exemple #18
0
        public Task GetIps()
        {
            AssertOnlyInSetupMode();

            using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context))
                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    writer.WriteStartObject();
                    writer.WritePropertyName("MachineName");
                    writer.WriteString(Environment.MachineName);
                    writer.WriteComma();
                    writer.WritePropertyName("NetworkInterfaces");
                    writer.WriteStartArray();
                    var first = true;
                    foreach (var netInterface in NetworkInterface.GetAllNetworkInterfaces())
                    {
                        var ips = netInterface.GetIPProperties().UnicastAddresses
                                  .Where(x =>
                        {
                            // filter 169.254.xxx.xxx out, they are not meaningful for binding
                            if (x.Address.AddressFamily != AddressFamily.InterNetwork)
                            {
                                return(false);
                            }
                            var addressBytes = x.Address.GetAddressBytes();

                            // filter 127.xxx.xxx.xxx out, in docker only
                            if (SetupParameters.Get(ServerStore).IsDocker&& addressBytes[0] == 127)
                            {
                                return(false);
                            }

                            return(addressBytes[0] != 169 || addressBytes[1] != 254);
                        })
                                  .Select(addr => addr.Address.ToString())
                                  .ToList();

                        // If there's a hostname in the server url, add it to the list
                        if (SetupParameters.Get(ServerStore).DockerHostname != null && ips.Contains(SetupParameters.Get(ServerStore).DockerHostname) == false)
                        {
                            ips.Add(SetupParameters.Get(ServerStore).DockerHostname);
                        }

                        if (first == false)
                        {
                            writer.WriteComma();
                        }
                        first = false;

                        writer.WriteStartObject();
                        writer.WritePropertyName("Name");
                        writer.WriteString(netInterface.Name);
                        writer.WriteComma();
                        writer.WritePropertyName("Description");
                        writer.WriteString(netInterface.Description);
                        writer.WriteComma();
                        writer.WriteArray("Addresses", ips);
                        writer.WriteEndObject();
                    }

                    writer.WriteEndArray();
                    writer.WriteEndObject();
                }

            return(Task.CompletedTask);
        }
Exemple #19
0
        public override void Setup()
        {
            // candidate items
            if (!SetupParameters.ContainsKey("candidateItemsMode"))
            {
                CandidateItemsMode = CandidateItems.TRAINING;
            }
            else
            {
                CandidateItemsMode = (CandidateItems)Enum.Parse(typeof(CandidateItems), SetupParameters["candidateItemsMode"], true);
            }

            if (SetupParameters.ContainsKey("candidateItemsFile"))
            {
                CandidateItemsFile = SetupParameters["candidateItemsFile"];
            }
            else if (CandidateItemsMode == CandidateItems.EXPLICIT)
            {
                throw new WrapRecException("Expect a 'candidateItemsFile' for the mode 'explicit'!");
            }

            // candidate users
            if (!SetupParameters.ContainsKey("candidateUsersMode"))
            {
                CandidateUsersMode = CandidateItems.TEST;
            }
            else
            {
                CandidateUsersMode = (CandidateItems)Enum.Parse(typeof(CandidateItems), SetupParameters["candidateUsersMode"], true);
            }

            if (SetupParameters.ContainsKey("candidateUsersFile"))
            {
                CandidateUsersFile = SetupParameters["candidateUsersFile"];
            }
            else if (CandidateUsersMode == CandidateItems.EXPLICIT)
            {
                throw new WrapRecException("Expect a 'candidateUsersFile' for the mode 'explicit!'");
            }

            CutOffs = SetupParameters["cutOffs"].Split(',').Select(c => int.Parse(c)).ToArray();

            if (!SetupParameters.ContainsKey("numCandidates"))
            {
                NumCandidates = new int[] { int.MaxValue }
            }
            ;
            else
            {
                NumCandidates = SetupParameters["numCandidates"].Split(',').Select(n =>
                {
                    return((n == "max") ? int.MaxValue : int.Parse(n));
                }).ToArray();
            }

            _maxNumCandidates = NumCandidates.Max();

            if (SetupParameters.ContainsKey("relevantItems") && SetupParameters["relevantItems"].ToLower() == "all")
            {
                _isSliceRelevant = f => f.SliceType == FeedbackSlice.TRAIN || f.SliceType == FeedbackSlice.TEST;
            }
            else
            {
                _isSliceRelevant = f => f.SliceType == FeedbackSlice.TEST;
            }

            if (SetupParameters.ContainsKey("userMetricsFile"))
            {
                _perUserMetrics = new MultiKeyDictionary <int, int, StreamWriter>();
            }
        }
Exemple #20
0
        public Task GetIps()
        {
            AssertOnlyInSetupMode();

            NetworkInterface[] netInterfaces = null;
            try
            {
                netInterfaces = NetworkInterface.GetAllNetworkInterfaces();
            }
            catch (Exception)
            {
                // https://github.com/dotnet/corefx/issues/26476
                // If GetAllNetworkInterfaces is not supported, we'll just return the default: 127.0.0.1
            }


            using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context))
                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    writer.WriteStartObject();
                    writer.WritePropertyName("MachineName");
                    writer.WriteString(Environment.MachineName);
                    writer.WriteComma();
                    writer.WritePropertyName("NetworkInterfaces");
                    writer.WriteStartArray();
                    var first = true;

                    List <string> ips;
                    if (netInterfaces != null)
                    {
                        foreach (var netInterface in netInterfaces)
                        {
                            ips = netInterface.GetIPProperties().UnicastAddresses
                                  .Where(x =>
                            {
                                // filter 169.254.xxx.xxx out, they are not meaningful for binding
                                if (x.Address.AddressFamily != AddressFamily.InterNetwork)
                                {
                                    return(false);
                                }
                                var addressBytes = x.Address.GetAddressBytes();

                                // filter 127.xxx.xxx.xxx out, in docker only
                                if (SetupParameters.Get(ServerStore).IsDocker&& addressBytes[0] == 127)
                                {
                                    return(false);
                                }

                                return(addressBytes[0] != 169 || addressBytes[1] != 254);
                            })
                                  .Select(addr => addr.Address.ToString())
                                  .ToList();

                            // If there's a hostname in the server url, add it to the list
                            if (SetupParameters.Get(ServerStore).DockerHostname != null && ips.Contains(SetupParameters.Get(ServerStore).DockerHostname) == false)
                            {
                                ips.Add(SetupParameters.Get(ServerStore).DockerHostname);
                            }

                            if (first == false)
                            {
                                writer.WriteComma();
                            }
                            first = false;

                            writer.WriteStartObject();
                            writer.WritePropertyName("Name");
                            writer.WriteString(netInterface.Name);
                            writer.WriteComma();
                            writer.WritePropertyName("Description");
                            writer.WriteString(netInterface.Description);
                            writer.WriteComma();
                            writer.WriteArray("Addresses", ips);
                            writer.WriteEndObject();
                        }
                    }
                    else
                    {
                        // https://github.com/dotnet/corefx/issues/26476
                        // If GetAllNetworkInterfaces is not supported, we'll just return the default: 127.0.0.1
                        ips = new List <string>
                        {
                            "127.0.0.1"
                        };
                        writer.WriteStartObject();
                        writer.WritePropertyName("Name");
                        writer.WriteString("Loopback Interface");
                        writer.WriteComma();
                        writer.WritePropertyName("Description");
                        writer.WriteString("Loopback Interface");
                        writer.WriteComma();
                        writer.WriteArray("Addresses", ips);
                        writer.WriteEndObject();
                    }


                    writer.WriteEndArray();
                    writer.WriteEndObject();
                }

            return(Task.CompletedTask);
        }
Exemple #21
0
        public Dictionary <string, string> GetStatistics()
        {
            // TODO: when test is empty ther is error
            if (_statistics != null)
            {
                return(_statistics);
            }

            Logger.Current.Info("Calculating split '{0}' statistics...", Id);

            var trainUsers = new Dictionary <string, int>();
            var trainItems = new Dictionary <string, int>();

            var testUsers = new Dictionary <string, int>();
            var testItems = new Dictionary <string, int>();

            int trainCount = 0, testCount = 0;

            foreach (Feedback f in Train)
            {
                trainCount++;
                string userId = f.User.Id;
                string itemId = f.Item.Id;

                if (!trainUsers.ContainsKey(userId))
                {
                    trainUsers[userId] = 1;
                }
                else
                {
                    trainUsers[userId]++;
                }

                if (!trainItems.ContainsKey(itemId))
                {
                    trainItems[itemId] = 1;
                }
                else
                {
                    trainItems[itemId]++;
                }
            }

            foreach (Feedback f in Test)
            {
                testCount++;
                string userId = f.User.Id;
                string itemId = f.Item.Id;

                if (!testUsers.ContainsKey(userId))
                {
                    testUsers[userId] = 1;
                }
                else
                {
                    testUsers[userId]++;
                }

                if (!testItems.ContainsKey(itemId))
                {
                    testItems[itemId] = 1;
                }
                else
                {
                    testItems[itemId]++;
                }
            }

            _statistics = new Dictionary <string, string>();

            int   totalCount = trainCount + testCount;
            float percTrain  = 100f * ((float)trainCount / totalCount);
            float percTest   = 100f * ((float)testCount / totalCount);

            long   trainMatrixCount = (long)trainUsers.Count * trainItems.Count;
            double sparsityTrain    = (double)100L * (trainMatrixCount - trainCount) / trainMatrixCount;

            long   testMatrixCount = (long)testUsers.Count * testItems.Count;
            double sparsityTest    = (double)100L * (testMatrixCount - testCount) / testMatrixCount;

            _statistics.Add("splitId", Id);

            _statistics.Add("train", trainCount.ToString());
            _statistics.Add("test", testCount.ToString());
            _statistics.Add("%train", string.Format("{0:0.00}", percTrain));
            _statistics.Add("%test", string.Format("{0:0.00}", percTest));

            _statistics.Add("trainUsers", trainUsers.Count.ToString());
            _statistics.Add("trainItems", trainItems.Count.ToString());
            _statistics.Add("sparsityTrain", string.Format("{0:0.00}", sparsityTrain));

            _statistics.Add("testUsers", testUsers.Count.ToString());
            _statistics.Add("testItems", testItems.Count.ToString());
            _statistics.Add("sparsityTest", string.Format("{0:0.00}", sparsityTest));

            _statistics.Add("newTestUsers", testUsers.Keys.Except(trainUsers.Keys).Count().ToString());
            _statistics.Add("newTestItems", testItems.Keys.Except(trainItems.Keys).Count().ToString());

            _statistics.Add("trUsrMinFb", trainUsers.Values.Min().ToString());
            _statistics.Add("trUsrMaxFb", trainUsers.Values.Max().ToString());
            _statistics.Add("trUsrAvgFb", string.Format("{0:0.00}", trainUsers.Values.Average()));

            _statistics.Add("teUsrMinFb", testUsers.Values.Min().ToString());
            _statistics.Add("teUsrMaxFb", testUsers.Values.Max().ToString());
            _statistics.Add("teUsrAvgFb", string.Format("{0:0.00}", testUsers.Values.Average()));

            _statistics.Add("trItmMinFb", trainItems.Values.Min().ToString());
            _statistics.Add("trItmMaxFb", trainItems.Values.Max().ToString());
            _statistics.Add("trItmAvgFb", string.Format("{0:0.00}", trainItems.Values.Average()));

            _statistics.Add("teItmMinFb", testItems.Values.Min().ToString());
            _statistics.Add("teItmMaxFb", testItems.Values.Max().ToString());
            _statistics.Add("teItmAvgFb", string.Format("{0:0.00}", testItems.Values.Average()));

            _statistics.Add("feedbackAttrs", SetupParameters.ContainsKey("feedbackAttributes") ? SetupParameters["feedbackAttributes"] : "NA");
            _statistics.Add("userAttrs", SetupParameters.ContainsKey("userAttributes") ? SetupParameters["userAttributes"] : "NA");
            _statistics.Add("itemAttrs", SetupParameters.ContainsKey("itemAttributes") ? SetupParameters["itemAttributes"] : "NA");

            return(_statistics);
        }