예제 #1
0
        public override float Predict(int user_id, int item_id)
        {
            string userIdOrg = UsersMap.ToOriginalID(user_id);
            string itemIdOrg = ItemsMap.ToOriginalID(item_id);
            List <Tuple <int, float> > features = new List <Tuple <int, float> >();

            if (!IgnoreFeaturesOnPrediction && Split.Container.FeedbacksDic.ContainsKey(userIdOrg, itemIdOrg))
            {
                var feedback = Split.Container.FeedbacksDic[userIdOrg, itemIdOrg];
                features = feedback.GetAllAttributes().Select(a => FeatureBuilder.TranslateAttribute(a)).NormalizeSumToOne(Normalize).ToList();
            }

            bool newUser = (user_id > MaxUserID);
            bool newItem = (item_id > MaxItemID);

            float userAttrsTerm = 0, itemAttrsTerm = 0;

            foreach (var feat in features)
            {
                // if feat_index is greater than MaxFeatureId it means that the feature is new in test set so its factors has not been learnt
                if (feat.Item1 < NumTrainFeaturs)
                {
                    float x_z = feat.Item2;

                    userAttrsTerm += newUser ? 0 : x_z *MatrixExtensions.RowScalarProduct(feature_factors, feat.Item1, user_factors, user_id);

                    itemAttrsTerm += newItem ? 0 : x_z *MatrixExtensions.RowScalarProduct(feature_factors, feat.Item1, item_factors, item_id);
                }
            }

            float itemBias     = newItem ? 0 : item_bias[item_id];
            float userItemTerm = (newUser || newItem) ? 0 : MatrixExtensions.RowScalarProduct(user_factors, user_id, item_factors, item_id);

            return(itemBias + userItemTerm + userAttrsTerm + itemAttrsTerm);
        }
예제 #2
0
        protected void _Iterate(IList <int> rating_indices, bool update_user, bool update_item)
        {
            foreach (int index in rating_indices)
            {
                int u = ratings.Users[index];
                int i = ratings.Items[index];

                int   g_u     = 0; //FeatureGroups[user_id];
                int   g_i     = 1; //FeatureGroups[item_id];
                float alpha_u = weights[g_u];
                float alpha_i = weights[g_i];

                // used by WrapRec-based logic
                string userIdOrg = UsersMap.ToOriginalID(u);
                string itemIdOrg = ItemsMap.ToOriginalID(i);

                List <Tuple <int, float> > features = new List <Tuple <int, float> >();
                if (Split.SetupParameters.ContainsKey("feedbackAttributes"))
                {
                    features = Split.Container.FeedbacksDic[userIdOrg, itemIdOrg].GetAllAttributes().Select(a => a.Translation)
                               .NormalizeSumToOne(Normalize).ToList();
                }

                var p = Predict(u, i);

                float err = (p - ratings[index]) * 2;

                float sum_u = 0, sum_i = 0;
                foreach (var feature in features)
                {
                    int   j       = feature.Item1;
                    float x_j     = feature.Item2;
                    int   g_z     = 2; // FeatureGroups[feature.Item1];
                    float alpha_z = weights[g_z];

                    sum_u += x_j * alpha_z * MatrixExtensions.RowScalarProduct(user_factors, u, feature_factors, j);
                    sum_i += x_j * alpha_z * MatrixExtensions.RowScalarProduct(item_factors, i, feature_factors, j);
                }
                float ui = MatrixExtensions.RowScalarProduct(item_factors, i, user_factors, u);
                sum_u += alpha_i * ui;
                sum_i += alpha_u * ui;

                float sum_z      = 0;
                float sum_z_bias = 0;
                for (int z = 0; z < features.Count; z++)
                {
                    int   z_ix    = features[z].Item1;
                    float x_z     = features[z].Item2;
                    float sum_j   = 0;
                    int   g_z     = 2; // FeatureGroups[z_ix];
                    float alpha_z = weights[g_z];
                    for (int j = z + 1; j < features.Count; j++)
                    {
                        int   j_ix = features[j].Item1;
                        float x_j  = features[j].Item2;
                        sum_j += x_j * MatrixExtensions.RowScalarProduct(feature_factors, z_ix, feature_factors, j_ix);
                    }
                    sum_z      += 2 * alpha_z * x_z * sum_j;
                    sum_z      += x_z * alpha_u * MatrixExtensions.RowScalarProduct(feature_factors, z_ix, user_factors, u);
                    sum_z      += x_z * alpha_i * MatrixExtensions.RowScalarProduct(feature_factors, z_ix, item_factors, i);
                    sum_z_bias += x_z * feature_biases[z_ix];
                }


                float[] sum = new float[NumFactors];
                foreach (var feature in features)
                {
                    int   j       = feature.Item1;
                    float x_j     = feature.Item2;
                    int   g_z     = 2; //FeatureGroups[feature.Item1];
                    float alpha_z = weights[g_z];

                    for (int f = 0; f < NumFactors; f++)
                    {
                        sum[f] += feature_factors[j, f] * x_j * alpha_z;
                    }
                }

                for (int f = 0; f < NumFactors; f++)
                {
                    sum[f] += user_factors[u, f] * alpha_u + item_factors[i, f] * alpha_i;
                }

                // adjust biases
                global_bias -= current_learnrate * (err + RegB * global_bias);

                if (update_user)
                {
                    user_bias[u] -= current_learnrate * (err * alpha_u + RegU * user_bias[u]);
                }
                if (update_item)
                {
                    item_bias[i] -= current_learnrate * (err * alpha_i + RegI * item_bias[i]);
                }

                foreach (var feature in features)
                {
                    int   j       = feature.Item1;
                    float x_j     = feature.Item2;
                    float w_j     = feature_biases[j];
                    int   g_z     = 2; // FeatureGroups[feature.Item1];
                    float alpha_z = weights[g_z];

                    feature_biases[j] -= current_learnrate * (x_j * alpha_z * err + RegC * w_j);
                }

                // adjust latent factors
                for (int f = 0; f < NumFactors; f++)
                {
                    double v_uf = user_factors[u, f];
                    double v_if = item_factors[i, f];

                    if (update_user)
                    {
                        double delta_u = alpha_u * (sum[f] - v_uf * alpha_u) * err + RegU * v_uf;
                        user_factors.Inc(u, f, -current_learnrate * delta_u);
                    }
                    if (update_item)
                    {
                        double delta_i = alpha_i * (sum[f] - v_if * alpha_i) * err + RegI * v_if;
                        item_factors.Inc(i, f, -current_learnrate * delta_i);
                    }

                    foreach (var feature in features)
                    {
                        int   j       = feature.Item1;
                        float x_j     = feature.Item2;
                        float v_jf    = feature_factors[j, f];
                        int   g_z     = 2; // FeatureGroups[feature.Item1];
                        float alpha_z = weights[g_z];

                        double delta_j = x_j * alpha_z * (sum[f] - v_jf * x_j * alpha_z) * err + RegC * v_jf;
                        feature_factors.Inc(j, f, -current_learnrate * delta_j);
                    }
                }

                // update alphas
                float update_alpha_u = (user_bias[u] + sum_u) * err + reg_w * weights[g_u];
                weights[g_u] -= current_learnrate * update_alpha_u;

                float update_alpha_i = (item_bias[i] + sum_i) * err + reg_w * weights[g_i];
                weights[g_i] -= current_learnrate * update_alpha_i;

                for (int g = 0; g < NumGroups - 2; g++)
                {
                    float alpha_z_g      = weights[g + 2];
                    float update_alpha_z = (sum_z + sum_z_bias) * err + reg_w * alpha_z_g;
                    weights[g + 2] -= current_learnrate * update_alpha_z;
                }


                NormalizeWeights();
            }

            Console.WriteLine($"alpha_u: {weights[0]}, alpha_i: {weights[1]}" + (weights.Length > 2 ? $", alpha_z: {weights[2]}" : ""));
            //_alphaWriter.WriteLine(++_iter + "," + weights[0] + "," + weights[1] + (weights.Length > 2 ? "," + weights[2] : ""));
        }
예제 #3
0
        public override float Predict(int user_id, int item_id)
        {
            int u = user_id;
            int i = item_id;

            // used by WrapRec-based logic
            string userIdOrg = UsersMap.ToOriginalID(user_id);
            string itemIdOrg = ItemsMap.ToOriginalID(item_id);

            List <Tuple <int, float> > features = new List <Tuple <int, float> >();

            if (Split.SetupParameters.ContainsKey("feedbackAttributes"))
            {
                features = Split.Container.FeedbacksDic[userIdOrg, itemIdOrg].GetAllAttributes().Select(a => a.Translation)
                           .NormalizeSumToOne(Normalize).ToList();
            }

            float alpha_u = weights[0];
            float alpha_i = weights[1];
            float alpha_z = weights.Length > 2 ? weights[2] : 0;

            float score = global_bias;

            if (u < user_bias.Length)
            {
                score += user_bias[u] * alpha_u;
            }

            if (i < item_bias.Length)
            {
                score += item_bias[i] * alpha_i;
            }

            foreach (var feat in features)
            {
                float x_z = feat.Item2;
                score += feature_biases[feat.Item1] * x_z * alpha_z;
            }

            for (int f = 0; f < NumFactors; f++)
            {
                float sum = 0, sum_sq = 0;

                float v_uf = 0, v_if = 0;
                if (u < user_bias.Length)
                {
                    v_uf = user_factors[u, f];
                }
                if (i < item_bias.Length)
                {
                    v_if = item_factors[i, f];
                }

                sum    += v_uf * alpha_u + v_if * alpha_i;
                sum_sq += v_uf * v_uf * alpha_u * alpha_u + v_if * v_if * alpha_i * alpha_i;

                foreach (var feat in features)
                {
                    int   j    = feat.Item1;
                    float x_j  = feat.Item2;
                    float v_jf = feature_factors[j, f];

                    sum    += x_j * v_jf * alpha_z;
                    sum_sq += x_j * x_j * v_jf * v_jf * alpha_z * alpha_z;
                }

                score += 0.5f * (sum * sum - sum_sq);
            }

            if (score > MaxRating)
            {
                return(MaxRating);
            }
            if (score < MinRating)
            {
                return(MinRating);
            }

            return(score);
        }
예제 #4
0
        protected override void UpdateFactors(int user_id, int item_id, int other_item_id, bool update_u, bool update_i, bool update_j)
        {
            // used by WrapRec-based logic
            string userIdOrg = UsersMap.ToOriginalID(user_id);
            string itemIdOrg = ItemsMap.ToOriginalID(item_id);

            List <Tuple <int, float> > features = new List <Tuple <int, float> >();

            if (Split.SetupParameters.ContainsKey("feedbackAttributes"))
            {
                features = Split.Container.FeedbacksDic[userIdOrg, itemIdOrg].GetAllAttributes().Select(a => a.Translation).NormalizeSumToOne(Normalize).ToList();
            }

            double item_bias_diff = item_bias[item_id] - item_bias[other_item_id];

            int   g_u     = 0; //FeatureGroups[user_id];
            int   g_i     = 1; //FeatureGroups[item_id];
            float alpha_u = weights[g_u];
            float alpha_i = weights[g_i];

            double u_i_term = MatrixExtensions.RowScalarProductWithRowDifference(
                user_factors, user_id, item_factors, item_id, item_factors, other_item_id);

            double y_uij = item_bias_diff + alpha_u * alpha_i * u_i_term;

            double items_z_term_sum = 0;

            double[] items_z_terms = new double[features.Count];
            double[] group_z_terms = new double[NumGroups - 2];
            int      z             = 0;

            foreach (var feat in features)
            {
                int   g_z     = FeatureGroups[feat.Item1];
                float alpha_z = weights[g_z];
                items_z_terms[z] = feat.Item2 * MatrixExtensions.RowScalarProductWithRowDifference(
                    feature_factors, feat.Item1, item_factors, item_id, item_factors, other_item_id);
                group_z_terms[g_z - 2] += items_z_terms[z];
                items_z_term_sum       += alpha_z * items_z_terms[z];
                z++;
            }
            y_uij += alpha_i * items_z_term_sum;

            double exp     = Math.Exp(y_uij);
            double sigmoid = 1 / (1 + exp);

            // adjust bias terms
            if (update_i)
            {
                double update = sigmoid - BiasReg * item_bias[item_id];
                item_bias[item_id] += (float)(learn_rate * update);
            }

            if (update_j)
            {
                double update = -sigmoid - BiasReg * item_bias[other_item_id];
                item_bias[other_item_id] += (float)(learn_rate * update);
            }

            // adjust factors
            for (int f = 0; f < num_factors; f++)
            {
                float v_uf = user_factors[user_id, f];
                float v_if = item_factors[item_id, f];
                float v_jf = item_factors[other_item_id, f];

                if (update_u)
                {
                    double update = alpha_u * alpha_i * (v_if - v_jf) * sigmoid - reg_u * v_uf;
                    user_factors[user_id, f] = (float)(v_uf + learn_rate * update);
                }

                // update features latent factors and make a sum term to use later for updating item factors
                // sum = Sum_{l=1}{num_features} c_l * v_{c_l,f}
                float sum = 0f;

                foreach (var feat in features)
                {
                    float v_zf    = feature_factors[feat.Item1, f];
                    float x_z     = feat.Item2;
                    int   g_z     = FeatureGroups[feat.Item1];
                    float alpha_z = weights[g_z];

                    sum += x_z * v_zf * alpha_z;

                    double update = alpha_i * alpha_z * x_z * (v_if - v_jf) * sigmoid - reg_c * v_zf;
                    feature_factors[feat.Item1, f] = (float)(v_zf + learn_rate * update);
                }

                if (update_i)
                {
                    double update = (alpha_u * alpha_i * v_uf + alpha_i * sum) * sigmoid - reg_i * v_if;
                    item_factors[item_id, f] = (float)(v_if + learn_rate * update);
                }

                if (update_j)
                {
                    double update = (alpha_u * alpha_i * -v_uf - alpha_i * sum) * sigmoid - reg_j * v_jf;
                    item_factors[other_item_id, f] = (float)(v_jf + learn_rate * update);
                }
            }

            // update alphas
            double update_alpha_u = alpha_i * u_i_term * sigmoid - reg_w * alpha_u;

            weights[g_u] = (float)(alpha_u + learn_rate * update_alpha_u);

            //NormalizeWeights();

            double update_alpha_i = (alpha_u * u_i_term + items_z_term_sum) * sigmoid - reg_w * alpha_i;

            weights[g_i] = (float)(alpha_i + learn_rate * update_alpha_i);

            for (int g = 0; g < NumGroups - 2; g++)
            {
                double alpha_z_g        = weights[g + 2];
                double update_alpha_z_g = alpha_i * group_z_terms[g] * sigmoid - reg_w * alpha_z_g;
                weights[g + 2] = (float)(alpha_z_g + learn_rate * update_alpha_z_g);
            }

            // normalize weights
            NormalizeWeights();
        }
예제 #5
0
        protected void _Iterate(IList <int> rating_indices, bool update_user, bool update_item)
        {
            foreach (int index in rating_indices)
            {
                int u = ratings.Users[index];
                int i = ratings.Items[index];

                // used by WrapRec-based logic
                string userIdOrg = UsersMap.ToOriginalID(u);
                string itemIdOrg = ItemsMap.ToOriginalID(i);

                List <Tuple <int, float> > features = new List <Tuple <int, float> >();
                if (Split.SetupParameters.ContainsKey("feedbackAttributes"))
                {
                    features = Split.Container.FeedbacksDic[userIdOrg, itemIdOrg].GetAllAttributes()
                               .Select(a => a.Translation).NormalizeSumToOne(Normalize).ToList();
                }

                var   p   = Predict(u, i);
                float err = (p - ratings[index]) * 2;

                float[] sum = new float[NumFactors];
                foreach (var feature in features)
                {
                    int   j   = feature.Item1;
                    float x_j = feature.Item2;

                    for (int f = 0; f < NumFactors; f++)
                    {
                        sum[f] += feature_factors[j, f] * x_j;
                    }
                }

                for (int f = 0; f < NumFactors; f++)
                {
                    sum[f] += user_factors[u, f] + item_factors[i, f];
                }

                // adjust biases
                //global_bias -= current_learnrate*(err + RegB*global_bias);

                if (update_user)
                {
                    user_bias[u] -= current_learnrate * (err + RegU * user_bias[u]);
                }
                if (update_item)
                {
                    item_bias[i] -= current_learnrate * (err + RegI * item_bias[i]);
                }

                foreach (var feature in features)
                {
                    int   j   = feature.Item1;
                    float x_j = feature.Item2;
                    float w_j = feature_biases[j];

                    feature_biases[j] -= BiasLearnRate * current_learnrate * (x_j * err + BiasReg * RegC * w_j);
                }

                // adjust latent factors
                for (int f = 0; f < NumFactors; f++)
                {
                    double v_uf = user_factors[u, f];
                    double v_if = item_factors[i, f];

                    if (update_user)
                    {
                        double delta_u = (sum[f] - v_uf) * err + RegU * v_uf;
                        user_factors.Inc(u, f, -current_learnrate * delta_u);
                    }
                    if (update_item)
                    {
                        double delta_i = (sum[f] - v_if) * err + RegI * v_if;
                        item_factors.Inc(i, f, -current_learnrate * delta_i);
                    }

                    foreach (var feature in features)
                    {
                        int   j    = feature.Item1;
                        float x_j  = feature.Item2;
                        float v_jf = feature_factors[j, f];

                        double delta_j = (sum[f] * x_j - v_jf * x_j * x_j) * err + RegC * v_jf;
                        feature_factors.Inc(j, f, -current_learnrate * delta_j);
                    }
                }
            }
        }
예제 #6
0
        protected override void UpdateFactors(int user_id, int item_id, int other_item_id, bool update_u, bool update_i, bool update_j)
        {
            // used by WrapRec-based logic
            string userIdOrg = UsersMap.ToOriginalID(user_id);
            string itemIdOrg = ItemsMap.ToOriginalID(item_id);

            List <Tuple <int, float> > features = new List <Tuple <int, float> >();

            if (Split.SetupParameters.ContainsKey("feedbackAttributes"))
            {
                features = Split.Container.FeedbacksDic[userIdOrg, itemIdOrg].GetAllAttributes().Select(a => a.Translation).NormalizeSumToOne(Normalize).ToList();
            }

            double item_bias_diff = item_bias[item_id] - item_bias[other_item_id];

            double y_uij = item_bias_diff + MatrixExtensions.RowScalarProductWithRowDifference(
                user_factors, user_id, item_factors, item_id, item_factors, other_item_id);

            foreach (var feat in features)
            {
                y_uij += feat.Item2 * MatrixExtensions.RowScalarProductWithRowDifference(
                    feature_factors, feat.Item1, item_factors, item_id, item_factors, other_item_id);
            }

            double exp     = Math.Exp(y_uij);
            double sigmoid = 1 / (1 + exp);

            // adjust bias terms
            if (update_i)
            {
                // TODO: check why -Bias
                double update = sigmoid - BiasReg * item_bias[item_id];
                item_bias[item_id] += (float)(learn_rate * update);
            }

            if (update_j)
            {
                double update = -sigmoid - BiasReg * item_bias[other_item_id];
                item_bias[other_item_id] += (float)(learn_rate * update);
            }

            // adjust factors
            for (int f = 0; f < num_factors; f++)
            {
                float v_uf = user_factors[user_id, f];
                float v_if = item_factors[item_id, f];
                float v_jf = item_factors[other_item_id, f];

                if (update_u)
                {
                    double update = (v_if - v_jf) * sigmoid - reg_u * v_uf;
                    user_factors[user_id, f] = (float)(v_uf + learn_rate * update);
                }

                // update features latent factors and make a sum term to use later for updating item factors
                // sum = Sum_{l=1}{num_features} c_l * v_{c_l,f}
                float sum = 0f;

                foreach (var feat in features)
                {
                    float v_zf = feature_factors[feat.Item1, f];
                    float x_z  = feat.Item2;

                    sum += x_z * v_zf;

                    double update = x_z * (v_if - v_jf) * sigmoid - reg_c * v_zf;
                    feature_factors[feat.Item1, f] = (float)(v_zf + learn_rate * update);
                }

                if (update_i)
                {
                    double update = (v_uf + sum) * sigmoid - reg_i * v_if;
                    item_factors[item_id, f] = (float)(v_if + learn_rate * update);
                }

                if (update_j)
                {
                    double update = (-v_uf - sum) * sigmoid - reg_j * v_jf;
                    item_factors[other_item_id, f] = (float)(v_jf + learn_rate * update);
                }
            }
        }