示例#1
0
def run(_K, _recommended_artists):
    # Initialize variables to hold performance measures
    avg_prec = 0  # mean precision
    avg_rec = 0  # mean recall

    df_a_file = FileCache("DF_age", _K, _recommended_artists)
    df_c_file = FileCache("DF_country", _K, _recommended_artists)
    df_g_file = FileCache("DF_gender", _K, _recommended_artists)

    # For all users in our data (UAM)
    no_users = UAM.shape[0]
    no_artists = UAM.shape[1]
    for u in range(0, no_users):

        # Get seed user's artists listened to
        u_aidx = np.nonzero(UAM[u, :])[0]

        if NF >= len(u_aidx) or u == no_users - 1:
            continue

        # Split user's artists into train and test set for cross-fold (CV) validation
        fold = 0
        kf = cross_validation.KFold(
            len(u_aidx), n_folds=NF)  # create folds (splits) for 5-fold CV

        for train_aidx, test_aidx in kf:  # for all folds
            if VERBOSE:
                print "User: "******", Fold: " + str(fold) + ", Training items: " + str(
                        len(train_aidx)) + ", Test items: " + str(
                            len(test_aidx)
                        ),  # the comma at the end avoids line break
            # Call recommend function
            copy_UAM = UAM.copy(
            )  # we need to create a copy of the UAM, otherwise modifications within recommend function will effect the variable

            ###############################################
            ## Combine CB and CF together so we get a HF ##
            ###############################################

            dict_rec_aidx_DF_A = df_a_file.read_for_hybrid(u, fold)
            dict_rec_aidx_DF_C = df_c_file.read_for_hybrid(u, fold)
            dict_rec_aidx_DF_G = df_g_file.read_for_hybrid(u, fold)

            # @JPEER check in group if that solution is fair enough
            if len(dict_rec_aidx_DF_A) == 0 or len(
                    dict_rec_aidx_DF_C) == 0 or len(dict_rec_aidx_DF_G) == 0:
                continue

            # Fuse scores given by CF and by CB recommenders
            # First, create matrix to hold scores per recommendation method per artist
            scores = np.zeros(shape=(3, no_artists), dtype=np.float32)

            # Add scores from CB and CF recommenders to this matrix
            for aidx in dict_rec_aidx_DF_A.keys():
                scores[0, aidx] = dict_rec_aidx_DF_A[aidx]

            for aidx in dict_rec_aidx_DF_C.keys():
                scores[1, aidx] = dict_rec_aidx_DF_C[aidx]

            for aidx in dict_rec_aidx_DF_G.keys():
                scores[2, aidx] = dict_rec_aidx_DF_G[aidx]

            # Apply aggregation function (here, just take arithmetic mean of scores)
            scores_fused = np.mean(scores, axis=0)

            # Sort and select top K_HR artists to recommend
            sorted_idx = np.argsort(scores_fused)
            sorted_idx_top = sorted_idx[-_recommended_artists:]

            # Put (artist index, score) pairs of highest scoring artists in a dictionary
            dict_rec_aidx = {}

            for i in range(0, len(sorted_idx_top)):
                dict_rec_aidx[sorted_idx_top[i]] = scores_fused[
                    sorted_idx_top[i]]

            # Distill recommended artist indices from dictionary returned by the recommendation functions
            rec_aidx = dict_rec_aidx.keys()

            if VERBOSE:
                print "Recommended items: ", len(rec_aidx)

            # Compute performance measures
            correct_aidx = np.intersect1d(
                u_aidx[test_aidx], rec_aidx)  # correctly predicted artists

            # TP - True Positives is amount of overlap in recommended artists and test artists
            # FP - False Positives is recommended artists minus correctly predicted ones
            TP = len(correct_aidx)
            FP = len(np.setdiff1d(rec_aidx, correct_aidx))

            # Precision is percentage of correctly predicted among predicted
            # Handle special case that not a single artist could be recommended -> by definition, precision = 100%
            if len(rec_aidx) == 0:
                prec = 100.0

            else:
                prec = 100.0 * TP / len(rec_aidx)

            # Recall is percentage of correctly predicted among all listened to
            # Handle special case that there is no single artist in the test set -> by definition, recall = 100%
            if len(test_aidx) == 0:
                rec = 100.0

            else:
                rec = 100.0 * TP / len(test_aidx)

            # add precision and recall for current user and fold to aggregate variables
            avg_prec += prec / (NF * no_users)
            avg_rec += rec / (NF * no_users)

            # Output precision and recall of current fold
            if VERBOSE:
                print("\tPrecision: %.2f, Recall:  %.2f" % (prec, rec))

            # Increase fold counter
            fold += 1

    f1_score = 2 * ((avg_prec * avg_rec) / (avg_prec + avg_rec))

    # Output mean average precision and recall
    if VERBOSE:
        print("\nMAP: %.2f, MAR  %.2f, F1 Scrore: %.2f" %
              (avg_prec, avg_rec, f1_score))
        print("%.3f, %.3f" % (avg_prec, avg_rec))
        print("K neighbors " + str(K))
        print("Recommendation: " + str(_recommended_artists))

    data = {}
    data['f1_score'] = f1_score
    data['avg_prec'] = avg_prec
    data['avg_rec'] = avg_rec
    data['recommended'] = False

    return data
def run(_K, _recommended_artists):
    avg_prec = 0
    avg_rec = 0
    no_users = UAM.shape[0]
    no_artists = UAM.shape[1]

    cf_file = FileCache("CF", _K, _recommended_artists)
    cb_file = FileCache("CB_Wiki", _K, _recommended_artists)
    pb_file = FileCache("PB", 1, _recommended_artists)

    recommended_artists = {}

    for u in range(0, no_users):
        # Get seed user's artists listened to
        u_aidx = np.nonzero(UAM[u, :])[0]

        if NF >= len(u_aidx) or u == no_users - 1:
            continue

        # Split user's artists into train and test set for cross-fold (CV) validation
        fold = 0
        kf = cross_validation.KFold(
            len(u_aidx), n_folds=NF)  # create folds (splits) for 5-fold CV
        for train_aidx, test_aidx in kf:  # for all folds
            # Show progress
            if VERBOSE:
                print "User: "******", Fold: " + str(fold) + ", Training items: " + str(
                        len(train_aidx)) + ", Test items: " + str(
                            len(test_aidx)
                        ),  # the comma at the end avoids line break

            # Call recommend function
            copy_UAM = UAM.copy(
            )  # we need to create a copy of the UAM, otherwise modifications within recommend function will effect the variable

            dict_rec_aidx_CB = cb_file.read_for_hybrid(
                u, fold)  #recommend_CB(AAM, u_aidx[train_aidx], _K)
            dict_rec_aidx_PB = pb_file.read_for_hybrid(
                u, fold
            )  #recommend_PB(copy_UAM, u_aidx[train_aidx], _recommended_artists)
            dict_rec_aidx_CF = cf_file.read_for_hybrid(
                u, fold
            )  #recommend_CF(copy_UAM, u_aidx[train_aidx], _recommended_artists)

            # @JPEER check in group if that solution is fair enough
            if len(dict_rec_aidx_CB) == 0 or len(dict_rec_aidx_PB) == 0 or len(
                    dict_rec_aidx_CF) == 0:
                continue

            # Fuse scores given by CB and by PB recommenders
            # First, create matrix to hold scores per recommendation method per artist
            scores = np.zeros(shape=(3, no_artists), dtype=np.float32)

            # Add scores from CB and CF recommenders to this matrix
            for aidx in dict_rec_aidx_CB.keys():
                scores[0, aidx] = dict_rec_aidx_CB[aidx]

            for aidx in dict_rec_aidx_PB.keys():
                scores[1, aidx] = dict_rec_aidx_PB[aidx]

            for aidx in dict_rec_aidx_CF.keys():
                scores[2, aidx] = dict_rec_aidx_CF[aidx]

            # Convert scores to ranks
            ranks = np.zeros(shape=(3, no_artists),
                             dtype=np.int16)  # init rank matrix

            for m in range(0, scores.shape[0]):  # for all methods to fuse
                aidx_nz = np.nonzero(
                    scores[m])[0]  # identify artists with positive scores
                scores_sorted_idx = np.argsort(
                    scores[m, aidx_nz]
                )  # sort artists with positive scores according to their score
                # Insert votes (i.e., inverse ranks) for each artist and current method

                for a in range(0, len(scores_sorted_idx)):
                    ranks[m, aidx_nz[scores_sorted_idx[a]]] = a + 1

            # Sum ranks over different approaches
            ranks_fused = np.sum(ranks, axis=0)
            # Sort and select top K_HR artists to recommend
            sorted_idx = np.argsort(ranks_fused)
            sorted_idx_top = sorted_idx[-_recommended_artists:]
            # Put (artist index, score) pairs of highest scoring artists in a dictionary
            dict_rec_aidx = {}

            for i in range(0, len(sorted_idx_top)):
                dict_rec_aidx[sorted_idx_top[i]] = ranks_fused[
                    sorted_idx_top[i]]

            # Distill recommended artist indices from dictionary returned by the recommendation functions
            rec_aidx = dict_rec_aidx.keys()

            if VERBOSE:
                print "Recommended items: ", len(rec_aidx)

            # Compute performance measures
            correct_aidx = np.intersect1d(
                u_aidx[test_aidx], rec_aidx)  # correctly predicted artists
            # True Positives is amount of overlap in recommended artists and test artists
            TP = len(correct_aidx)
            # False Positives is recommended artists minus correctly predicted ones
            FP = len(np.setdiff1d(rec_aidx, correct_aidx))

            # Precision is percentage of correctly predicted among predicted
            # Handle special case that not a single artist could be recommended -> by definition, precision = 100%
            if len(rec_aidx) == 0:
                prec = 100.0
            else:
                prec = 100.0 * TP / len(rec_aidx)

            # Recall is percentage of correctly predicted among all listened to
            # Handle special case that there is no single artist in the test set -> by definition, recall = 100%
            if len(test_aidx) == 0:
                rec = 100.0
            else:
                rec = 100.0 * TP / len(test_aidx)

            # add precision and recall for current user and fold to aggregate variables
            avg_prec += prec / (NF * no_users)
            avg_rec += rec / (NF * no_users)

            # Output precision and recall of current fold
            if VERBOSE:
                print("\tPrecision: %.2f, Recall:  %.2f" % (prec, rec))

            # Increase fold counter
            fold += 1

    # Output mean average precision and recall
    if VERBOSE:
        print("\nMAP: %.2f, MAR  %.2f" % (avg_prec, avg_rec))
        print("%.3f, %.3f" % (avg_prec, avg_rec))

    f1_score = 2 * ((avg_prec * avg_rec) / (avg_prec + avg_rec))

    data = {}
    data['avg_prec'] = avg_prec
    data['avg_rec'] = avg_rec
    data['f1_score'] = f1_score
    data['recommended'] = False

    return data
示例#3
0
def run(_K, _recommended_artists):
    """
    Function to run an evaluation experiment
    """
    # Initialize variables to hold performance measures
    avg_prec = 0  # mean precision
    avg_rec = 0  # mean recall

    cb_file = FileCache("CB_Wiki", _K, _recommended_artists)
    cf_file = FileCache("CF", _K, _recommended_artists)

    # For all users in our data (UAM)
    no_users = UAM.shape[0]

    for u in range(0, no_users):

        # Get seed user's artists listened to
        # u_aidx = np.nonzero(UAM[u, :])[0]
        u_aidx = np.nonzero(UAM[u, :])[0]

        if NF >= len(u_aidx) or u == no_users - 1:
            continue

        # Split user's artists into train and test set for cross-fold (CV) validation
        fold = 0

        # create folds (splits) for 10-fold CV
        kf = cross_validation.KFold(len(u_aidx), n_folds=NF)

        # For all folds
        for train_aidx, test_aidx in kf:
            if VERBOSE:
                print "User: "******", Fold: " + str(fold) + ", Training items: " + str(
                        len(train_aidx)) + ", Test items: " + str(
                            len(test_aidx)),

            # Create a copy of the UAM, otherwise modifications within recommend function will effect the variable
            copy_UAM = UAM.copy()

            # Call recommend function
            rec_aidx_CF = cf_file.read_for_hybrid(
                u, fold)  # recommend_CF(copy_UAM, u, u_aidx[train_aidx])
            rec_aidx_CB = cb_file.read_for_hybrid(
                u, fold)  # recommend_CB(AAM, u_aidx[train_aidx], _K)

            # @JPEER check in group if that solution is fair enough
            if len(rec_aidx_CF) == 0 or len(rec_aidx_CB) == 0:
                continue

            # Return the sorted, unique values that are in both of the input arrays.
            rec_aidx = np.intersect1d(rec_aidx_CB, rec_aidx_CF)

            if VERBOSE:
                print "Items CB: " + str(len(rec_aidx_CB))
                print "Items CF: " + str(len(rec_aidx_CF))
                print "Recommended items: " + str(len(rec_aidx))
                print "Predicted to be: " + str(_recommended_artists)

            ################################
            # Compute performance measures #
            ################################

            # Correctly predicted artists
            correct_aidx = np.intersect1d(u_aidx[test_aidx], rec_aidx)

            # TP - True Positives is amount of overlap in recommended artists and test artists
            # FP - False Positives is recommended artists minus correctly predicted ones
            TP = len(correct_aidx)
            FP = len(np.setdiff1d(rec_aidx, correct_aidx))

            # Precision is percentage of correctly predicted among predicted
            # Handle special case that not a single artist could be recommended -> by definition, precision = 100%
            if len(rec_aidx) == 0:
                prec = 100.0

            else:
                prec = 100.0 * TP / len(rec_aidx)

            # Recall is percentage of correctly predicted among all listened to
            # Handle special case that there is no single artist in the test set -> by definition, recall = 100%
            if len(test_aidx) == 0:
                rec = 100.0

            else:
                rec = 100.0 * TP / len(test_aidx)

            # add precision and recall for current user and fold to aggregate variables
            avg_prec += prec / (NF * no_users)
            avg_rec += rec / (NF * no_users)

            # Output precision and recall of current fold
            if VERBOSE:
                print("\tPrecision: %.2f, Recall:  %.2f" % (prec, rec))

            # Increase fold counter
            fold += 1

    f1_score = 2 * ((avg_prec * avg_rec) / (avg_prec + avg_rec))

    # Output mean average precision and recall
    if VERBOSE:
        print("MAP: %.3f, MAR: %.3f, F1 Score: %.3f" %
              (avg_prec, avg_rec, f1_score))
        print("K neighbors: " + str(_K))
        print("Recommendations: " + str(_recommended_artists))

    data = {}
    data['avg_prec'] = avg_prec
    data['avg_rec'] = avg_rec
    data['f1_score'] = f1_score
    data['recommended'] = False

    return data