def initialize_user_preference_value_based_on_preferred_item( user_preference_data, item_info_dict, categorical_attributes, numerical_attributes): user_preference_value_dict = {} user_preferred_item = user_preference_data['phones'] user_preferred_item_dict = {} for item_id in user_preferred_item: user_preferred_item_dict[len(user_preferred_item_dict) + 1] = item_info_dict[item_id] user_preferred_item_df = pd.DataFrame.from_dict(user_preferred_item_dict, orient='index') # pp.pprint(user_preferred_item_df) for attr in categorical_attributes: user_preferred_item_attr_df = user_preferred_item_df[attr] user_preference_value_dict[ attr] = user_preferred_item_attr_df.value_counts().to_dict() for attr in numerical_attributes: user_preferred_item_attr_df = user_preferred_item_df[attr].astype(str) user_preferred_item_attr_value_dict = user_preferred_item_attr_df.value_counts( ).to_dict() attr_rank_label_list = helper.get_numerical_attribute_rank_label(attr) for rank in attr_rank_label_list: if rank not in user_preferred_item_attr_value_dict.keys(): user_preferred_item_attr_value_dict[rank] = 0 user_preference_value_dict[attr] = user_preferred_item_attr_value_dict # pp.pprint(user_preference_value_dict) time_helper.print_current_time() print( "Initialize User Model ---- Initialize preference value based on the user's selected preferred items." ) return user_preference_value_dict
def post(self): start = time.process_time() time_helper.print_current_time() print("Update User Model ---- start") json_data = request.get_json(force=True) user_profile = json_data['user_profile'] user_interaction_dialog = user_profile['logger']['latest_dialog'] user_browsed_items = user_profile['logger']['browsedItems'] user_model = user_profile['user'] current_recommended_item = user_profile['topRecommendedItem'] key = 'id' # update the user model (three parts) updated_user_preference_model, updated_user_constraints, updated_user_critique_preference = user_modeling.update_user_model(user_model, \ user_interaction_dialog, user_browsed_items, current_recommended_item, categorical_attributes, numerical_attributes, key, item_info_dict) user_profile['user']['user_preference_model'] = updated_user_preference_model user_profile['user']['user_constraints'] = updated_user_constraints user_profile['user']['user_critique_preference'] = updated_user_critique_preference # update the user interaction log # for log in user_interaction_dialog: # user_profile['logger']['dialog'].append(copy.deepcopy(log)) # user_profile['logger']['latest_dialog'] = [] end = time.process_time() time_helper.print_current_time() print ('Update User Model ---- run time : %ss ' % str(end-start)) return json.dumps(user_profile)
def initialize_user_preference_model(user_preference_data, item_info_dict, categorical_attributes, numerical_attributes): # ---- 2020/05 # version 1: initialize_user_preference_value --- based on specified preference value (e.g. specific brand, or range of price...) # user_initial_preference_value = initialize_user_preference_value(user_preference_data, categorical_attributes, numerical_attributes) # ---- 2020/09 # version 2: initialize_user_preference_value --- based on selected preferred mobile phone (user_preference_data contains N preferred mobile phone id) user_initial_preference_value = initialize_user_preference_value_based_on_preferred_item( user_preference_data, item_info_dict, categorical_attributes, numerical_attributes) user_preference_attribute_frequency = initialize_user_preference_attribute_frequency( categorical_attributes, numerical_attributes) user_preference_model = { 'preference_value': user_initial_preference_value, 'attribute_frequency': user_preference_attribute_frequency } # pp.pprint(user_preference_model) time_helper.print_current_time() print( "Initialize User Model ---- Preference Model about %d categorical attributes." % len(categorical_attributes)) time_helper.print_current_time() print( "Initialize User Model ---- Preference Model about %d numerical attributes." % len(numerical_attributes)) return user_preference_model
def initialize_user_preference_attribute_frequency(categorical_attributes, numerical_attributes): user_preference_attribute_frequency_dict = {} for attr in categorical_attributes: user_preference_attribute_frequency_dict[attr] = 1 for attr in numerical_attributes: user_preference_attribute_frequency_dict[attr] = 1 time_helper.print_current_time() print( "Initialize User Model ---- Initialize attribute frequency as 1 for all attributes." ) return user_preference_attribute_frequency_dict
def initialize_user_preference_value(user_preference_data, categorical_attributes, numerical_attributes): user_preference_value_dict = {} for attr in categorical_attributes: if attr not in user_preference_data.keys(): user_preference_data[attr] = [] user_preference_value_dict[attr] = categorical_attribute_preference( user_preference_data[attr]) for attr in numerical_attributes: if attr not in user_preference_data.keys(): user_preference_data[attr] = [] user_preference_value_dict[attr] = numerical_attribute_preference( user_preference_data[attr], attr) pp.pprint(user_preference_value_dict) time_helper.print_current_time() print( "Initialize User Model ---- Initialize preference value based on the user's specified preference data." ) return user_preference_value_dict
def update_user_model(user_model, user_interaction_dialog, user_browsed_items, current_recommended_item, categorical_attributes, numerical_attributes, key, item_info_dict): updated_user_preference_value = user_model['user_preference_model'][ 'preference_value'] updated_user_attribute_frequency = user_model['user_preference_model'][ 'attribute_frequency'] updated_user_constraints = user_model['user_constraints'] updated_user_critique_preference = user_model['user_critique_preference'] numerical_crit_direction_limit = ['higher', 'lower', 'normal', 'similar'] updated_user_preference_model = user_model['user_preference_model'] for utterance_info in user_interaction_dialog: current_action = utterance_info['action'].lower() # Condition 1: user critiquing / system suggest critiquing - Yes # -> update (1) user critique preference, (2) preference model: attribute frequency, (3) user constraints, time_helper.print_current_time() print("Update User Model ---- User Action: %s." % (current_action)) if current_action == "user_critique" or current_action == "accept_suggestion": critique_list = [] if 'critique' in utterance_info.keys(): critique_list = utterance_info['critique'] critique_item_info = item_info_dict[current_recommended_item] time_helper.print_current_time() print("Update User Model (%s) ---- Number of Critiques: %d." % (current_action, len(critique_list))) for crit in critique_list: for attr, criti_value in crit.items(): if attr not in numerical_attributes and attr not in categorical_attributes: time_helper.print_current_time() print("Unrecognized attributes: %s." % attr) continue if attr in numerical_attributes and criti_value not in numerical_crit_direction_limit: time_helper.print_current_time() print("Unrecognized critique direction: %s." % criti_value) continue # preference model: attribute frequency updated_user_attribute_frequency[ attr] = updated_user_attribute_frequency[attr] * 2 time_helper.print_current_time() print("update attribute frequence: attribute (%s) - %f. " % (attr, updated_user_attribute_frequency[attr])) # user critique preference updated_user_critique_preference = update_user_critique_preference(updated_user_critique_preference, attr,\ criti_value, critique_item_info, numerical_attributes, 'pos') # pp.pprint(updated_user_critique_preference) # user constraint constraint_number = 5 updated_user_constraints = update_user_constraints( updated_user_critique_preference, constraint_number) # pp.pprint(updated_user_constraints) time_helper.print_current_time() print( "Update User Model ---- Number of Current User Constraints: %d." % len(updated_user_constraints)) # Condition 2: system suggest critiquing - No # -> update (1) user critique negative if current_action == 'reject_suggestion': critique_list = [] if 'critique' in utterance_info.keys(): critique_list = utterance_info['critique'] critique_song_info = current_recommended_item time_helper.print_current_time() print("Update User Model (%s) ---- Number of Critiques: %d." % (current_action, len(critique_list))) for crit in critique_list: for attr, criti_value in crit.items(): check_consective_reject_SC = False # check if there are consective rejected critiques within the same attribute (decrease the attribute frequency) if len(updated_user_critique_preference) > 0: latest_user_critique_preference = updated_user_critique_preference[ -1] # time_helper.print_current_time() # print("latest_critique: ", latest_user_critique_preference) if attr in numerical_attributes and latest_user_critique_preference[ 'pos_or_neg'] == 'neg' and latest_user_critique_preference[ 'attribute'] == attr: check_consective_reject_SC = True updated_user_attribute_frequency[ attr] = updated_user_attribute_frequency[ attr] / 2 time_helper.print_current_time() print( "update attribute frequence: attribute (%s) - %f. " % (attr, updated_user_attribute_frequency[attr])) if check_consective_reject_SC == False: updated_user_attribute_frequency[ attr] = updated_user_attribute_frequency[ attr] * 0.75 time_helper.print_current_time() print( "update attribute frequence: attribute (%s) - %f. " % (attr, updated_user_attribute_frequency[attr])) # user critique preferencef updated_user_critique_preference = update_user_critique_preference( updated_user_critique_preference, attr, criti_value, critique_song_info, numerical_attributes, 'neg') # Condition 3: accept the recommendation if current_action == "accept_item" or current_action == "request_rate": # --- Revise ---- system critique - accept -> update critique preference, attribute frequency, user constraints # # if the recommended item is based on system critiques # # -> update (1) user critique preference (if "sys_critique"), (2) preference model: attribute frequency, (3) user constraints, # if len(sys_critique_list) > 0: # critique_list = sys_critique_list # critique_item_id = utterance_info['critiqued_item'] # critique_item_info = {} # for item in user_listened_longs: # if item['id'] == critique_item_id: # critique_item_info = item # for crit in critique_list: # for attr, criti_value in crit.items(): # # preference model: attribute frequency # updated_user_attribute_frequency[attr] = updated_user_attribute_frequency[attr] + 1 # # user critique preference # updated_user_critique_preference = update_user_critique_preference(updated_user_critique_preference, attr, criti_value, critique_item_info, numerical_attributes) # # user constraint # constraint_number = 3 # updated_user_constraints = update_user_constraints(updated_user_critique_preference, constraint_number) # ------------------------------------------------ # Update preference value based on the liked items # ------------------------------------------------ liked_item_info = item_info_dict[current_recommended_item] updated_user_preference_value = update_user_preference_value( updated_user_preference_value, liked_item_info, categorical_attributes, numerical_attributes) time_helper.print_current_time() print( "Update User Model ---- Update preference value based on the accepted item." ) updated_user_preference_model = { 'preference_value': updated_user_preference_value, 'attribute_frequency': updated_user_attribute_frequency } return updated_user_preference_model, updated_user_constraints, updated_user_critique_preference
def generate_system_critiques_preference_oriented( user_info, user_critique_preference, estimated_score_dict, item_pool, cur_rec, top_K, unit_or_compound, categorical_attributes, numerical_attributes, key): # Step 1: Generate a critique array for each item item_critique_arrays, item_critique_arrays_dict = generate_critique_array( item_pool, cur_rec, categorical_attributes, numerical_attributes, key) # Step 2: Find frequent critiques set (Compound & Unit) num_critique_sets_dict, rules = apriori(item_critique_arrays, min_support=min_support, min_confidence=min_confidence) # Step 3: Filter frequent critiques that have conflict with user past critiques. categorical_critique_dict, numerical_critique_dict = helper.convert_to_critique_preference_dict( user_critique_preference) # pp.pprint(categorical_critique_dict) # pp.pprint(numerical_critique_dict) all_critiques_freq_dict = {} frequent_critiques_freq_dict = {} for num in unit_or_compound: for crit, freq in num_critique_sets_dict[num].items(): all_critiques_freq_dict[crit] = freq if not check_critique_conflict_with_user_preference( crit, cur_rec, categorical_critique_dict, numerical_critique_dict): frequent_critiques_freq_dict[crit] = freq # pp.pprint(frequent_critiques_freq_dict) time_helper.print_current_time() print('Frequent critiques (support value: %f): %d (%s).' % (min_support, len(frequent_critiques_freq_dict), str(unit_or_compound))) # ------------------------------------------------------- # -------------------- Apropri ----------------------- # ------------------------------------------------------- # # pp.pprint(rules) # # Print out every rule with 2 items on the left hand side, # # 1 item on the right hand side, sorted by lift # rules_rhs = filter(lambda rule: len(rule.lhs) == 1 and len(rule.rhs) == 1, rules) # for rule in sorted(rules_rhs, key=lambda rule: rule.lift, reverse=True): # pass # # print(rule) # Prints the rule and its confidence, support, lift, ... # ------------------------------------------------------- if len(frequent_critiques_freq_dict) == 0: frequent_critiques_freq_dict = all_critiques_freq_dict time_helper.print_current_time() print("Generate critiques that may conflict with users' preferences.") else: time_helper.print_current_time() print("Find some critiques that suit users' taste.") # Step 3: Obtain the set of items that satisfy the critique frequent_critiques_satisfied_items_dict = obtain_critique_items_dict( frequent_critiques_freq_dict, item_critique_arrays_dict) # pp.pprint(frequent_critiques_satisfied_items_dict) # Step 4: Compute critique utility for frequent critiques # compatibility_score_dict = recommendation.compute_recommendation_by_MAUT(user_info, item_pool, len(item_pool), categorical_attributes, numerical_attributes) user_attribute_frequency = user_info['attribute_frequency'] sorted_critique_utility_list = compute_critique_utility_preference_oriented( user_attribute_frequency, frequent_critiques_freq_dict, min_support, frequent_critiques_satisfied_items_dict, estimated_score_dict) # time_helper.print_current_time() # print('compute critique utility - preference-oriented - Done.') # version 1: re-sort SC (put the critiques with same attribute but different directions together) top_K = min([top_K, len(sorted_critique_utility_list)]) sorted_critique_list = resort_critique_list(sorted_critique_utility_list, top_K, numerical_attributes) # top_K = min([top_K, len(sorted_critique_utility_list)]) # sorted_critique_diveristy_utility_list = compute_critique_diversity_utility(sorted_critique_utility_list, top_K) # time_helper.print_current_time() # print('obtain critique diversified - Done.') # pp.pprint(sorted_critique_diveristy_utility_list) topK_critique_item_list = obtain_top_k_critique_with_recommendation_list( top_K, sorted_critique_list, frequent_critiques_satisfied_items_dict, estimated_score_dict) return topK_critique_item_list
def post(self): start = time.process_time() time_helper.print_current_time() print("Initialize User Model ---- start") json_data = request.get_json(force=True) user_profile = json_data['user_profile'] user_preference_data = user_profile['user']['preferenceData'] # initial preference data: a list of ids of phones that user preferred # initialize the user preference model ** using user preference data # preference model consists of two parts: attribute frequency and preference value for each attribute user_preference_model = user_modeling.initialize_user_preference_model(user_preference_data, item_info_dict, categorical_attributes, numerical_attributes) user_profile['user']['user_preference_model'] = user_preference_model time_helper.print_current_time() print("Initialize User Model ---- Part 1: User Preference Model --- Done!") # initialize the user critique preference (empty) user_critique_preference = [] user_profile['user']['user_critique_preference'] = user_critique_preference time_helper.print_current_time() print("Initialize User Model ---- Part 2: User Critique Preference (empty) --- Done!") # initialize the user constraints (empty) user_constraint = [] user_profile['user']['user_constraints'] = user_constraint time_helper.print_current_time() print("Initialize User Model ---- Part 3: User Constraints (empty) --- Done!") ### -------------------------------------------------------------- ### obtain initial recommendations (top 150 based on MAUT) initial_recommendations_list = [] top_K = 150 method = 'MAUT' alpha = 0.5 topK_recommendations_score_dict = recommendation.compute_recommendation(user_preference_model, user_critique_preference, item_pool, top_K, \ categorical_attributes, numerical_attributes, method, key, alpha) if len(topK_recommendations_score_dict) > 0: for rec in topK_recommendations_score_dict: initial_recommendations_list.append(rec[0]) user_profile['pool'] = initial_recommendations_list time_helper.print_current_time() print("Obtain initial recommendation (top 150) based on MAUT --- Done!") end = time.process_time() time_helper.print_current_time() print ('Initialize User Model ---- run time : %ss ' % str(end-start)) return json.dumps(user_profile)
def post(self): start = time.process_time() time_helper.print_current_time() print("Get System Critiques ---- start") json_data = request.get_json(force=True) user_profile = json_data['user_profile'] user_preference_model = user_profile['user']['user_preference_model'] user_critique_preference = user_profile['user']['user_critique_preference'] user_constraints = user_profile['user']['user_constraints'] item_pool_name_list = user_profile['pool'] new_item_pool_name_list = user_profile['new_pool'] user_interaction_log = user_profile['logger'] cur_rec = user_profile['topRecommendedItem'] cur_rec = copy.deepcopy(item_info_dict[cur_rec]) item_pool = [] user_pool_item_info_dict = {} for item in item_pool_name_list: item_pool.append(item_info_dict[item]) user_pool_item_info_dict[item] = item_info_dict[item] time_helper.print_current_time() new_item_pool = [] new_pool_item_info_dict = {} for item in new_item_pool_name_list: new_item_pool.append(item_info_dict[item]) new_pool_item_info_dict[item] = item_info_dict[item] top_K = 3 unit_or_compound = [1,2] item_pool_for_SC = item_pool new_item_pool_state = False if len(new_item_pool) > 0: new_item_pool_state = True item_pool_for_SC = new_item_pool time_helper.print_current_time() print("Get System Critiques ---- Item Pool: %d songs" % len(item_pool_for_SC)) # whether or not to filter recommendation using hard constraints # minimal_threshold = 150 # filtered_item_pool = recommendation.filter_items_by_user_constraints(user_constraints, item_pool, minimal_threshold,\ # categorical_attributes, numerical_attributes, key) # time_helper.print_current_time() # print("Filter By User Constraints --- after filtering, %d phones left." % len(filtered_item_pool)) # filtered_item_pool = item_pool method = 'MAUT_COMPAT' alpha = 0.5 top_k_candidates = 150 # top_k_candidates = min([top_k_candidates, len(filtered_item_pool)]) estimated_score_dict = recommendation.compute_recommendation(user_preference_model, user_critique_preference, item_pool_for_SC, len(item_pool_for_SC), categorical_attributes, numerical_attributes, method, key, alpha, sort=True) time_helper.print_current_time() print("Get System Critiques ---- Obtain item utility score by %s method (alpha:%f) --- Done." %(method, alpha)) sorted_candidated_list = [] for rec in estimated_score_dict: sorted_candidated_list.append(rec[0]) estimated_score_dict = dict(estimated_score_dict) selected_item_pool = [] for item in item_pool: if item[key] in sorted_candidated_list: selected_item_pool.append(item) time_helper.print_current_time() print('select %d recommendation for generating critiques.' % len(selected_item_pool)) sys_crit_version = 'preference_oriented' # preference_oriented / diversity_oriented / personality_adjusted time_helper.print_current_time() print("Get System Critiques ---- system critique generation version: %s" % sys_crit_version) state = 'SC_and_Recommendation' sys_crit = None sys_crit = system_critiquing.generate_system_critiques_preference_oriented(user_preference_model, user_critique_preference, estimated_score_dict, selected_item_pool, cur_rec, top_K, unit_or_compound, categorical_attributes , numerical_attributes, key) time_helper.print_current_time() print(state) # time_helper.print_current_time() # pp.pprint(sys_crit) sys_crit_with_rec_list = {'state': state, 'result': sys_crit} end = time.process_time() time_helper.print_current_time() print ('Get System Critiques ---- run time : %ss ' % str(end-start)) return json.dumps(sys_crit_with_rec_list), 201 return json.dumps(sys_crit_with_rec_list), 201
def post(self): start = time.process_time() time_helper.print_current_time() print("Get Recommendation ---- start") json_data = request.get_json(force=True) user_profile = json_data['user_profile'] user_preference_model = user_profile['user']['user_preference_model'] user_critique_preference = user_profile['user']['user_critique_preference'] user_constraints = user_profile['user']['user_constraints'] item_pool_name_list = user_profile['pool'] new_item_pool_name_list = user_profile['new_pool'] item_pool = [] user_pool_item_info_dict = {} for item in item_pool_name_list: item_pool.append(item_info_dict[item]) user_pool_item_info_dict[item] = item_info_dict[item] new_item_pool = [] new_pool_item_info_dict = {} for item in new_item_pool_name_list: new_item_pool.append(item_info_dict[item]) new_pool_item_info_dict[item] = item_info_dict[item] # Filter the items that the user has browsed # user_interaction_log = user_profile['logger'] # user_browsed_items = user_interaction_log['browsedItems'] # for item_key in user_browsed_items: # item_info = item_info_dict[item_key] # item_pool.remove(item_info) # time_helper.print_current_time() # print("Filter Phone Data ---- Filter %d items that the user has browsed, %d items left. -- Done!" % (len(user_browsed_items), len(item_pool))) top_K = 20 method = 'MAUT_COMPAT' # (1) MAUT (2) COMPAT (3) MAUT_COMPAT alpha = 0.5 # Linear combination weight: alpha-> weight for MAUT score; 1-alpha -> weight for COMPAT score minimal_threshold = 20 time_helper.print_current_time() print("Get Recommendation ---- Method: %s (alpha:%f)." % (method,alpha)) topK_recommendations_score_dict = {} if len(new_item_pool) > 0: topK_recommendations_score_dict = recommendation.compute_recommendation(user_preference_model, user_critique_preference, new_item_pool, top_K, \ categorical_attributes, numerical_attributes, method, key, alpha) else: filtered_item_pool = recommendation.filter_items_by_user_constraints(user_constraints, item_pool, minimal_threshold,\ categorical_attributes, numerical_attributes, key) time_helper.print_current_time() print("Filter by User Constraints --- after filtering, %d items left." % len(filtered_item_pool)) if len(filtered_item_pool) > 0: topK_recommendations_score_dict = recommendation.compute_recommendation(user_preference_model, user_critique_preference, filtered_item_pool, top_K, \ categorical_attributes, numerical_attributes, method, key, alpha) topK_recommendation_list = [] if len(topK_recommendations_score_dict) > 0: for rec in topK_recommendations_score_dict: topK_recommendation_list.append(rec[0]) time_helper.print_current_time() print("Get Recommendation ---- Obtained top %d recommended items. "% len(topK_recommendation_list)) updated_item_pool = [] if len(new_item_pool) > 0: time_helper.print_current_time() print("Get Recommendation ---- New Pool: %d songs." % (len(new_item_pool))) time_helper.print_current_time() print("Get Recommendation ---- Original Item Pool: %d songs." % (len(item_pool))) integrated_item_pool = new_item_pool + item_pool assert(len(integrated_item_pool) == len(item_pool) + len(new_item_pool)) max_item_pool_number = min([150, len(integrated_item_pool)]) updated_item_pool = recommendation.update_recommendation_pool(user_preference_model, user_critique_preference, new_item_pool, integrated_item_pool, max_item_pool_number, categorical_attributes, numerical_attributes, method, alpha) print("Get Recommendation ---- Updated Item Pool: %d songs." % (len(updated_item_pool))) user_profile['pool'] = updated_item_pool user_profile['new_pool'] = [] recommendation_and_user_profile = {'recommendation_list': topK_recommendation_list, 'user_profile': user_profile} end = time.process_time() time_helper.print_current_time() print ('Get Recommendation ---- run time : %ss ' % str(end-start)) return json.dumps(recommendation_and_user_profile), 201
categorical_attributes = ['brand','nettech','os1', 'nfc', 'year', 'fullscreen'] numerical_attributes = ['phone_size', 'phone_weight', 'camera', 'storage', 'ram', 'price'] # Load Phone Data phone_data_file = 'data/new_phone_data.json' phone_data = load_data.load_json_data(phone_data_file) # 'id' in music domain and 'id' in phone domain # Load Phone Data key = 'id' item_pool = copy.deepcopy(phone_data['pool']) item_info_dict = {} for item in item_pool: item_info_dict[item[key]] = item time_helper.print_current_time() print("Load Phone Data (%d)---- Done!" % len(item_pool)) # 操作(post / get)资源列表 class InitializeUserModel(Resource): def post(self): start = time.process_time() time_helper.print_current_time() print("Initialize User Model ---- start") json_data = request.get_json(force=True) user_profile = json_data['user_profile'] user_preference_data = user_profile['user']['preferenceData'] # initial preference data: a list of ids of phones that user preferred
def filter_items_by_user_constraints(user_constraints, item_pool, minimal_threshold, categorical_attributes, numerical_attributes, key): # revise filtered_item_pool = copy.deepcopy(item_pool) filter_by_top_critique = False for critique_unit_dict in user_constraints: filtered_id_list = [] attr = critique_unit_dict['attribute'] crit_direction = critique_unit_dict['crit_direction'] crit_value = '' if attr in numerical_attributes: crit_value = critique_unit_dict['value'] time_helper.print_current_time() print(critique_unit_dict) if attr in categorical_attributes: if type(crit_direction) == str: if attr == 'nettech' and '/' not in crit_direction: for item in filtered_item_pool: if crit_direction not in item[attr]: filtered_id_list.append(item[key]) else: for item in filtered_item_pool: if item[attr].lower() != crit_direction.lower(): # print(item[attr]) filtered_id_list.append(item[key]) if type(crit_direction) == list: if attr == 'nettech': for item in filtered_item_pool: for crit_v in crit_direction: if crit_v not in item[attr]: filtered_id_list.append(item[key]) break else: for item in filtered_item_pool: if item[attr] not in crit_direction: filtered_id_list.append(item[key]) if attr in numerical_attributes: cur_index = crit_value _index, rank_total = helper.get_numerical_attribute_rank(attr, -1) for item in filtered_item_pool: item_index = item[attr] satisfied_flag = False if item_index == cur_index and crit_direction == 'similar': satisfied_flag = True # case 1: current critiqued item value has been already the lowest range - allows to return items within same range if cur_index == 1: if item_index <= cur_index and crit_direction == 'lower': satisfied_flag = True # case 2: current critiqued item value has been already the highest range - allows to return items within same range elif cur_index == rank_total: if item_index >= cur_index and crit_direction == 'higher': satisfied_flag = True else: if item_index < cur_index and crit_direction == 'lower': satisfied_flag = True if item_index > cur_index and crit_direction == 'higher': satisfied_flag = True if satisfied_flag == False: filtered_id_list.append(item[key]) updated_filtered_item_pool = [] for item in filtered_item_pool: if item[key] not in filtered_id_list: updated_filtered_item_pool.append(item) time_helper.print_current_time() print("number of filtered items: %d" % len(filtered_item_pool)) time_helper.print_current_time() print("number of items after filtering: %d" % len(updated_filtered_item_pool)) if filter_by_top_critique and len( updated_filtered_item_pool) < minimal_threshold: return filtered_item_pool else: filtered_item_pool = copy.deepcopy(updated_filtered_item_pool) filter_by_top_critique = True return filtered_item_pool
def compute_recommendation_compatibility_score(user_critique_preference, item_pool, top_K, categorical_attributes, numerical_attributes, key, sort=True): # based on user critique preference and item value # calculate the compatibility score for each item # item compatibility score item_compatibility_score_dict = {} categorical_critique_dict, numerical_critique_dict = helper.convert_to_critique_preference_dict( user_critique_preference) for each_item in item_pool: item_id = each_item[key] item_compatibility_score = 0 satisfied_critique_attribute_list = [] unsatisfied_critique_attribute_list = [] # 1. Categorical Attributes for attr in categorical_critique_dict.keys(): critique_on_attribute = categorical_critique_dict[attr]['pos'] if each_item[attr] in critique_on_attribute: satisfied_critique_attribute_list.append(attr) else: unsatisfied_critique_attribute_list.append(attr) # 2. Numerical Attributes for attr in numerical_critique_dict.keys(): critique_on_attribute = numerical_critique_dict[attr] if each_item[attr] > critique_on_attribute[0] and each_item[ attr] < critique_on_attribute[1]: satisfied_critique_attribute_list.append(attr) else: unsatisfied_critique_attribute_list.append(attr) if len(satisfied_critique_attribute_list) > 0: item_compatibility_score = len( satisfied_critique_attribute_list) / ( len(satisfied_critique_attribute_list) + len(unsatisfied_critique_attribute_list)) item_compatibility_score_dict[item_id] = item_compatibility_score # pp.pprint(item_compatibility_score_dict) time_helper.print_current_time() print( "Get Recommendation ---- Compute recommendation compatibility score (COMPAT) ---- Done." ) if sort: sorted_item_compatibility_score_list = helper.sort_dict( item_compatibility_score_dict) top_K_recommmendation_list = sorted_item_compatibility_score_list[ 0:top_K] return top_K_recommmendation_list else: return item_compatibility_score_dict
def compute_recommendation_by_MAUT(user_preference_model, item_pool, top_K, categorical_attributes, numerical_attributes, key, sort=True): # based on user preference model and item value # use MAUT to estimate the user's preference for each item user_pref_attribute_frequency = user_preference_model[ 'attribute_frequency'] user_pref_preference_value = user_preference_model['preference_value'] # item utility item_utility_dict = {} # compute the attribute weight (normalization)-> the user's attribute preference user_pref_attribute_weight_dict = obtain_attribute_weight( user_pref_attribute_frequency) # user preference to item w.r.t. each attribute user_item_preference_value_dict = {} for each_item in item_pool: item_id = each_item[key] item_utility = 0 # Step 1: Obtain the value for each attributes # 1. Categorical Attributes for attr in categorical_attributes: user_item_preference_value_dict[ attr] = categorical_attributes_value_function( user_pref_preference_value[attr], each_item[attr], attr) # 2. Numerical Attributes for attr in numerical_attributes: user_item_preference_value_dict[ attr] = numerical_attributes_value_function( user_pref_preference_value[attr], each_item[attr], attr) # Step 2: Calculate the utility # 1. Categorical Attributes for attr in categorical_attributes: item_utility = item_utility + user_pref_attribute_weight_dict[ attr] * user_item_preference_value_dict[attr] # 2. Numerical Attributes for attr in numerical_attributes: item_utility = item_utility + user_pref_attribute_weight_dict[ attr] * user_item_preference_value_dict[attr] item_utility_dict[item_id] = item_utility # print(item_utility) time_helper.print_current_time() print( "Get Recommendation ---- Compute recommendation Multi-attribute Utility score (MAUT) ---- Done." ) if sort: sorted_item_utility_list = helper.sort_dict(item_utility_dict) # pp.pprint(sorted_item_utility_list) top_K_recommmendation_list = sorted_item_utility_list[0:top_K] print("Get Recommendation ---- MAUT Sort ---- Done.") return top_K_recommmendation_list else: return item_utility_dict