def response(self, input_message): ''' The agent moves a step forward, upon receiving a message from the user. ''' assert input_message.sender == cfg.USER assert input_message.receiver == cfg.AGENT self.update_this_turn = False #_______ update the agent self_______ if input_message.message_type == cfg.INFORM_FACET: self.update_upon_feature_inform(input_message) if input_message.message_type == cfg.REJECT_REC: self.rejected_item_list_ += input_message.data[ 'rejected_item_list'] if self.mini == 1: if self.alwaysupdate == 1 or self.mini_update_already is False: for i in range(cfg.update_count): self.mini_update_FM() self.mini_update_already = True self.recent_candidate_list = list( set(self.recent_candidate_list) - set(self.rejected_item_list_)) self.recent_candidate_list = list( set(self.recent_candidate_list) - set([self.busi_id])) + [self.busi_id] self.recent_candidate_list_ranked = rank_items( self.known_feature, self.user_id, self.busi_id, self.skip_big_feature, self.FM_model, self.recent_candidate_list, self.write_fp, 1) #_______ Adding into history _______ if input_message.message_type == cfg.INFORM_FACET: if self.turn_count > 0: # means first doesn't count if input_message.data['value'] is None: self.history_list.append(0) # ask attribute, fail else: self.history_list.append(1) # ask attribute, successful if input_message.message_type == cfg.REJECT_REC: self.history_list.append( -1) # try recommendation, user doesn't want. self.recent_candidate_list = list( set(self.recent_candidate_list) - set(self.rejected_item_list_)) # don't consider if cfg.play_by != 'AOO' and cfg.play_by != 'AOO_valid': # Add control point here if cfg.mod == 'ear': state_vector = self.vectorize() else: state_vector = self.vectorize_crm() action = None SoftMax = nn.Softmax(dim=-1) if cfg.play_by == 'AOO' or cfg.play_by == 'AOO_valid': new_message = self.prepare_next_question() if cfg.play_by == 'AO': # means Ask, the recommendation is made by a probability new_message = self.prepare_next_question() x = len(self.recent_candidate_list) p = 10.0 / x a = random.uniform(0, 1) if a < p: new_message = self.prepare_rec_message() if cfg.play_by == 'RO': # means RecOnly, only make recommendation at each turn. # For Abs-Greedy Evaluation new_message = self.prepare_rec_message() if cfg.play_by == 'policy': s = torch.from_numpy(state_vector).float() s = Variable(s, requires_grad=False) self.PN_model.eval() # print(torch.min(s)) pred = self.PN_model(s) # print(pred.detach().numpy()) for feat in self.asked_feature: pred[cfg.tag_map[feat]] = -math.inf prob = SoftMax(pred) # print(prob.detach().numpy()) # print(torch.min(prob)) c = Categorical(prob) # use max prob if cfg.eval == 1 or cfg.eval == 0: pred_data = pred.data.tolist() sorted_index = sorted(range(len(pred_data)), key=lambda k: pred_data[k], reverse=True) print('Top 5 action: {}'.format(sorted_index[:5])) print('Value of top 5 actions: {}'.format( [pred_data[v] for v in sorted_index[:5]])) print('Ranking of recommendation action: {}'.format( sorted_index.index(len(cfg.tag_map)))) print('Value of recommendation action: {}'.format( pred_data[len(cfg.tag_map)])) unasked_max = None # for item in sorted_index: # if item <= 7: # unasked_max = item # break if self.turn_count < 5 - 2: unasked_max = sorted_index[0] else: unasked_max = pred.shape[0] - 1 action = Variable(torch.tensor( [unasked_max], dtype=torch.long)) # make it compatible with torch else: # for training of Action stage i = 0 action_ = pred.shape[0] ap = np.random.random() if ap >= cfg.actionProb: # if ap > 1: print('sample action') # while i < 10000: # action_ = c.sample() # i += 1 # if action_ <= 7: # break # action = action_ action = c.sample() action = Variable(torch.tensor([action], dtype=torch.long)) else: print('max prob action') pred_data = pred.data.tolist() sorted_index = sorted(range(len(pred_data)), key=lambda k: pred_data[k], reverse=True) unasked_max = sorted_index[0] action = Variable( torch.tensor([unasked_max], dtype=torch.long)) # action = Variable(torch.IntTensor([unasked_max])) # make it compatible with torch print('action is: {}'.format(action.numpy()[0])) log_prob = c.log_prob(action) if self.turn_count != 0: self.log_prob_list = torch.cat( [self.log_prob_list, log_prob.reshape(1)]) else: self.log_prob_list = log_prob.reshape(1) if action < pred.shape[0] - 1: # self.ask_rel.append(action) data = dict() # data['facet'] = int(cfg.FACET_POOL[action]) data['facet'] = cfg.FACET_POOL[action] new_message = message(cfg.AGENT, cfg.USER, cfg.ASK_FACET, data) else: new_message = self.prepare_rec_message() # end if policy if cfg.play_by == 'policy': self.action_tracker.append(action.data.numpy().tolist()) self.candidate_length_tracker.append( len(self.recent_candidate_list)) # following are for writing to numpy array # action = None # if new_message.message_type == cfg.ASK_FACET: # action = cfg.FACET_POOL.index(str(new_message.data['facet'])) # if new_message.message_type == cfg.MAKE_REC: # action = len(cfg.FACET_POOL) # # if cfg.purpose != 'fmdata': # self.numpy_list.append((action, state_vector)) # # end following # # inverted_known_feature = [int(cfg.tag_map_inverted[item]) for item in self.known_feature] # self.residual_feature_big = list(set(cfg.item_dict[str(self.busi_id)]['categories']) - set(inverted_known_feature)) # # with open(self.write_fp, 'a') as f: # f.write('Turn count: {}, candidate length: {}\n'.format(self.turn_count, len(self.recent_candidate_list))) return new_message
def update_upon_feature_inform(self, input_message): assert input_message.message_type == cfg.INFORM_FACET #_______ update F_dict________ facet = input_message.data['facet'] self.asked_feature.append(str(facet)) value = input_message.data['value'] if value is not None: self.update_this_turn = True rcl = [] for k in self.recent_candidate_list: if set(value).issubset(set( cfg.item_dict[str(k)]['categories'])): rcl.append(k) # self.recent_candidate_list = [k for k in self.recent_candidate_list if set(value).issubset(set(cfg.item_dict[str(k)]['categories']))] self.recent_candidate_list = rcl self.recent_candidate_list = list( set(self.recent_candidate_list) - set([self.busi_id])) + [self.busi_id] self.known_feature.append(cfg.tag_map[str(value[0])]) self.known_feature = list(set(self.known_feature)) # following dict l = list(set(self.recent_candidate_list) - set([self.busi_id])) random.shuffle(l) if cfg.play_by == 'AOO': self.sample_dict[self.busi_id].append( (self.known_feature, l[:10])) if cfg.play_by == 'AOO_valid': self.sample_dict[self.busi_id].append( (self.known_feature, l[:300])) # end dictionary if cfg.play_by != 'AOO' and cfg.play_by != 'AOO_valid': self.sim_dict = feature_similarity(self.known_feature, self.user_id, self.TopKTaxo) self.sim_dict2 = self.sim_dict.copy() self.recent_candidate_list = list( set(self.recent_candidate_list) - set([self.busi_id])) + [self.busi_id] self.recent_candidate_list_ranked = rank_items( self.known_feature, self.user_id, self.busi_id, self.skip_big_feature, self.FM_model, self.recent_candidate_list, self.write_fp, 0) if value is not None and value[0] is not None: c = cal_ent(self.recent_candidate_list) d = c.do_job() self.entropy_dict = d c = cal_ent(self.recent_candidate_list[:10]) d = c.do_job() self.entropy_dict_10 = d c = cal_ent(self.recent_candidate_list[:50]) d = c.do_job() self.entropy_dict_50 = d for f in self.asked_feature: # self.entropy_dict[int(f)] = 0 self.entropy_dict[f] = 0 if cfg.play_by == 'AOO' or cfg.play_by == 'AOO_valid': return for f in self.asked_feature: if self.sim_dict is not None and str(f) in self.sim_dict: self.sim_dict[str(f)] = -1 for f in self.asked_feature: if self.sim_dict2 is not None and str(f) in self.sim_dict: self.sim_dict2[str(f)] = -1 residual_feature = cfg.item_dict[str(self.busi_id)]['categories'] # known_ = [int(cfg.tag_map_inverted[item]) for item in self.known_feature] known_ = [cfg.tag_map_inverted[item] for item in self.known_feature] residual_feature = list(set(residual_feature) - set(known_)) self.residual_feature_big = residual_feature
def response(self, input_message): ''' The agent moves a step forward, upon receiving a message from the user. ''' assert input_message.sender == cfg.USER assert input_message.receiver == cfg.AGENT #_______ update the agent self_______ if input_message.message_type == cfg.INFORM_FACET: self.update_upon_feature_inform(input_message) if input_message.message_type == cfg.REJECT_REC: self.rejected_item_list_ += input_message.data[ 'rejected_item_list'] self.rejected_time += 1 if self.mini == 1: if self.alwaysupdate == 1: for i in range(cfg.update_count): self.mini_update_FM() self.mini_update_already = True self.recent_candidate_list = list( set(self.recent_candidate_list) - set(self.rejected_item_list_)) self.recent_candidate_list = list( set(self.recent_candidate_list) - set([self.busi_id])) + [self.busi_id] self.recent_candidate_list_ranked, self.previous_dict = rank_items( self.known_feature, self.user_id, self.busi_id, self.skip_big_feature, self.FM_model, self.recent_candidate_list, self.write_fp, 1, self.rejected_item_list_, self.previous_dict) #_______ Adding into history _______ if input_message.message_type == cfg.INFORM_FACET: if self.turn_count > 0: # means first doesn't# count if input_message.data['value'] is None: self.history_list.append(0) # ask attribute, fail else: self.history_list.append(1) # ask attribute, successful if input_message.message_type == cfg.REJECT_REC: self.history_list.append( -1) # try recommendation, user doesn't want. self.recent_candidate_list = list( set(self.recent_candidate_list) - set(self.rejected_item_list_)) # don't consider if cfg.play_by != 'AOO' and cfg.play_by != 'AOO_valid': # Add control point here if cfg.mod == 'ear': state_vector = self.vectorize() else: state_vector = self.vectorize_crm() action = None SoftMax = nn.Softmax(dim=-1) if cfg.play_by == 'AOO' or cfg.play_by == 'AOO_valid': new_message = self.prepare_next_question() # if cfg.play_by == 'AO': # means Ask, the recommendation is made by a probability new_message = self.prepare_next_question() x = len(self.recent_candidate_list) p = 10.0 / x a = random.uniform(0, 1) if a < p: new_message = self.prepare_rec_message() if cfg.play_by == 'RO': # means RecOnly, only make recommendation at each turn. # For Abs-Greedy Evaluation new_message = self.prepare_rec_message() if cfg.play_by == 'policy': # means using Policy Network to determine action s = torch.from_numpy(state_vector).float() s = Variable(s, requires_grad=True) self.PN_model.eval() pred = self.PN_model(s) prob = SoftMax(pred) c = Categorical(prob) # different way to choose action if cfg.eval == 1: # for evaluation of Action stage pred_data = pred.data.tolist() sorted_index = sorted(range(len(pred_data)), key=lambda k: pred_data[k], reverse=True) # The following line are for avoid asking same question # It is a fair evaluation, because all models have such operation. unasked_max = None for item in sorted_index: if item < self.big_feature_length: if cfg.FACET_POOL[item] not in self.asked_feature: unasked_max = item break else: unasked_max = self.big_feature_length break action = Variable(torch.IntTensor( [unasked_max])) # make it compatible with torch print('action is: {}'.format(action)) else: # for training of Action stage i = 0 action_ = self.big_feature_length while (i < 10000): action_ = c.sample() i += 1 if action_ <= self.big_feature_length: if action_ == self.big_feature_length: break elif cfg.FACET_POOL[action_] not in self.asked_feature: break action = action_ print('action is: {}'.format(action)) log_prob = c.log_prob(action) if self.turn_count != 0: self.log_prob_list = torch.cat( [self.log_prob_list, log_prob.reshape(1)]) else: self.log_prob_list = log_prob.reshape(1) # translate into message if action < len(cfg.FACET_POOL): data = dict() data['facet'] = cfg.FACET_POOL[action] new_message = message(cfg.AGENT, cfg.USER, cfg.ASK_FACET, data) else: new_message = self.prepare_rec_message() self.action_tracker.append(action.data.numpy().tolist()) self.candidate_length_tracker.append( len(self.recent_candidate_list)) else: new_message = self.prepare_rec_message() # following are for writing to numpy array action = None if new_message.message_type == cfg.ASK_FACET: action = cfg.FACET_POOL.index(new_message.data['facet']) if new_message.message_type == cfg.MAKE_REC: action = len(cfg.FACET_POOL) if cfg.purpose == 'pretrain': self.numpy_list.append((action, state_vector)) # end following with open(self.write_fp, 'a') as f: f.write('Turn count: {}, candidate length: {}\n'.format( self.turn_count, len(self.recent_candidate_list))) return new_message
def update_upon_feature_inform(self, input_message): assert input_message.message_type == cfg.INFORM_FACET #_______ update F_dict________ facet = input_message.data['facet'] if facet is None: print('?') self.asked_feature.append(facet) value = input_message.data['value'] if facet in ['stars', 'RestaurantsPriceRange2', 'city']: ''' value is a list for stars: [3.0] for Prices: [3.0] for city: as we integerized, [31] be cautious for city, they must be integer ''' if value is not None and value[0] is not None: self.recent_candidate_list = [ k for k in self.recent_candidate_list if cfg.item_dict[str(k)][facet] in value ] self.recent_candidate_list = list( set(self.recent_candidate_list) - set([self.busi_id])) + [self.busi_id] self.known_facet.append(facet) fresh = True if facet == 'city': if int(value[0]) not in self.known_feature: self.known_feature.append(int(value[0])) else: fresh = False if facet == 'stars': if int(value[0] + cfg.city_count) not in self.known_feature: self.known_feature.append( int(value[0] + cfg.city_count - 1)) else: fresh = False if facet == 'RestaurantsPriceRange2': if int(value[0] + cfg.star_count + cfg.city_count) not in self.known_feature: self.known_feature.append( int(value[0] + cfg.star_count + cfg.city_count - 1)) else: fresh = False self.known_feature = list(set(self.known_feature)) if fresh is True: # dictionary l = list( set(self.recent_candidate_list) - set([self.busi_id])) random.shuffle(l) if cfg.play_by == 'AOO': self.sample_dict[self.busi_id].append( (self.known_feature, l[:10])) if cfg.play_by == 'AOO_valid': self.sample_dict[self.busi_id].append( (self.known_feature, l[:300])) # end dictionary #end if if cfg.play_by != 'AOO' and cfg.play_by != 'AOO_valid': self.sim_dict = feature_similarity(self.known_feature, self.user_id, self.TopKTaxo) self.sim_dict2 = self.sim_dict.copy() #print('Similarity ranking dict: {}'.format(self.sim_dict)) self.recent_candidate_list_ranked, self.previous_dict = rank_items( self.known_feature, self.user_id, self.busi_id, self.skip_big_feature, self.FM_model, self.recent_candidate_list, self.write_fp, 0, self.rejected_item_list_, self.previous_dict) # end if else: # means the feature is in the small tags if value is not None: self.recent_candidate_list = [ k for k in self.recent_candidate_list if set(value).issubset( set(cfg.item_dict[str(k)]['categories'])) ] self.recent_candidate_list = list( set(self.recent_candidate_list) - set([self.busi_id])) + [self.busi_id] base = cfg.star_count + cfg.price_count + cfg.city_count self.known_feature += [int(i + base) for i in value] self.known_feature = list(set(self.known_feature)) self.known_facet.append(facet) # dictionary l = list(set(self.recent_candidate_list) - set([self.busi_id])) random.shuffle(l) if cfg.play_by == 'AOO': self.sample_dict[self.busi_id].append( (self.known_feature, l[:10])) if cfg.play_by == 'AOO_valid': self.sample_dict[self.busi_id].append( (self.known_feature, l[:300])) # end dictionary if cfg.play_by != 'AOO' and cfg.play_by != 'AOO_valid': self.sim_dict = feature_similarity(self.known_feature, self.user_id, self.TopKTaxo) self.sim_dict2 = self.sim_dict.copy() self.recent_candidate_list_ranked, self.previous_dict = rank_items( self.known_feature, self.user_id, self.busi_id, self.skip_big_feature, self.FM_model, self.recent_candidate_list, self.write_fp, 0, self.rejected_item_list_, self.previous_dict) # end else start = time.time() if value is not None and value[0] is not None: c = cal_ent(self.recent_candidate_list[:10]) d = c.do_job() self.entropy_dict_10 = d c = cal_ent(self.recent_candidate_list[:50]) d = c.do_job() self.entropy_dict_50 = d c = cal_ent(self.recent_candidate_list) d = c.do_job() self.entropy_dict = d # _______ set those asked feature's entropy to 0 _______ for f in self.asked_feature: self.entropy_dict[f] = 0 for f in self.asked_feature: if self.sim_dict is not None and f in self.sim_dict: self.sim_dict[f] = -1 if self.entropy_dict[f] == 0: self.sim_dict[f] = -1 for f in self.asked_feature: if self.sim_dict2 is not None and f in self.sim_dict: self.sim_dict2[f] = -1 if self.entropy_dict[f] == 0: self.sim_dict[f] = -1 self.residual_feature_big = list( set(self.choose_pool) - set(self.known_facet)) ent_position, sim_position = None, None if self.entropy_dict is not None: ent_value = sorted([v for k, v in self.entropy_dict.items()], reverse=True) ent_position = [ ent_value.index(self.entropy_dict[big_f]) for big_f in self.residual_feature_big ] if self.sim_dict is not None: sim_value = sorted([v for k, v in self.sim_dict.items()], reverse=True) sim_position = [ sim_value.index(self.sim_dict[str(big_f)]) for big_f in self.residual_feature_big ] if len(self.residual_feature_big) > 0: with open(self.write_fp, 'a') as f: f.write( 'Turn Count: {} residual feature: {}***ent position: {}*** sim position: {}***\n' .format(self.turn_count, self.residual_feature_big, ent_position, sim_position))
def response(self, input_message): assert input_message.sender == cfg.USER assert input_message.receiver == cfg.AGENT if input_message.message_type == cfg.INFORM_FACET: self.update_upon_feature_inform(input_message) if input_message.message_type == cfg.REJECT_REC: self.rejected_item_list_ += input_message.data[ 'rejected_item_list'] self.rejected_time += 1 if self.mini == 1: if self.alwaysupdate == 1: for i in range(cfg.update_count): self.mini_update_transE() self.mini_update_already = True self.recent_candidate_list = list( set(self.recent_candidate_list) - set(self.rejected_item_list_)) self.recent_candidate_list = list( set(self.recent_candidate_list) - set([self.busi_id])) + [self.busi_id] self.recent_candidate_list_ranked = rank_items( self.known_feature_total, self.items, self.features, self.transE_model, self.recent_candidate_list, self.rejected_item_list_) if input_message.message_type == cfg.INFORM_FACET: if self.turn_count > 0: if input_message.data['value'] is None: self.history_list.append(0) else: self.history_list.append(1) if input_message.message_type == cfg.REJECT_REC: self.history_list.append(-1) self.recent_candidate_list = list( set(self.recent_candidate_list) - set(self.rejected_item_list_)) if cfg.play_by != 'AOO' and cfg.play_by != 'AOO_valid': if cfg.mod == 'ours': state_vector = self.vectorize() action = None SoftMax = nn.Softmax(dim=-1) if cfg.play_by == 'policy': s = torch.from_numpy(state_vector).float() s = Variable(s, requires_grad=True) self.PN_model.eval() pred = self.PN_model(s) prob = SoftMax(pred) c = Categorical(prob) if cfg.eval == 1: pred_data = pred.data.tolist() sorted_index = sorted(range(len(pred_data)), key=lambda k: pred_data[k], reverse=True) unasked_max = None for item in sorted_index: if item < self.big_feature_length: if cfg.FACET_POOL[item] not in self.asked_feature: unasked_max = item break else: unasked_max = self.big_feature_length break action = Variable(torch.IntTensor([unasked_max])) print('action is: {}'.format(action)) else: # for RL i = 0 action_ = self.big_feature_length while (i < 10000): action_ = c.sample() i += 1 if action_ <= self.big_feature_length: if action_ == self.big_feature_length: break elif cfg.FACET_POOL[action_] not in self.asked_feature: break action = action_ print('action is: {}'.format(action)) log_prob = c.log_prob(action) if self.turn_count != 0: self.log_prob_list = torch.cat( [self.log_prob_list, log_prob.reshape(1)]) else: self.log_prob_list = log_prob.reshape(1) if action < len(cfg.FACET_POOL): data = dict() data['facet'] = cfg.FACET_POOL[action] new_message = message(cfg.AGENT, cfg.USER, cfg.ASK_FACET, data) else: new_message = self.prepare_rec_message() self.action_tracker.append(action.data.numpy().tolist()) self.candidate_length_tracker.append( len(self.recent_candidate_list)) action = None if new_message.message_type == cfg.ASK_FACET: action = cfg.FACET_POOL.index(new_message.data['facet']) if new_message.message_type == cfg.MAKE_REC: action = len(cfg.FACET_POOL) if cfg.purpose == 'pretrain': self.numpy_list.append((action, state_vector)) with open(self.write_fp, 'a') as f: f.write('Turn count: {}, candidate length: {}\n'.format( self.turn_count, len(self.recent_candidate_list))) return new_message
def update_upon_feature_inform(self, input_message): assert input_message.message_type == cfg.INFORM_FACET facet = input_message.data['facet'] if facet is None: print('?') self.asked_feature.append(facet) value = input_message.data['value'] if facet in ['clusters', 'POI_Type']: if value is not None and value[0] is not None: # value is in list. self.recent_candidate_list = [ k for k in self.recent_candidate_list if cfg.item_dict[str(k)][facet] in value ] self.recent_candidate_list = list( set(self.recent_candidate_list) - set([self.busi_id])) + [self.busi_id] self.known_facet.append(facet) fresh = True if facet == 'clusters': if int(value[0]) not in self.known_feature_cluster: self.known_feature_cluster.append(int(value[0])) else: fresh = False if facet == 'POI_Type': if int(value[0]) not in self.known_feature_type: self.known_feature_type.append(int(value[0])) else: fresh = False self.known_feature = list(set( self.known_feature)) # feature = values if cfg.play_by != 'AOO' and cfg.play_by != 'AOO_valid': self.known_feature_total.clear() self.known_feature_total.append(self.known_feature_cluster) self.known_feature_total.append(self.known_feature_type) self.known_feature_total.append( self.known_feature_category) self.distance_dict = feature_distance( self.known_feature_total, self.user_id, self.TopKTaxo, self.features) self.distance_dict2 = self.distance_dict.copy() self.recent_candidate_list_ranked = rank_items( self.known_feature_total, self.items, self.features, self.transE_model, self.recent_candidate_list, self.rejected_item_list_) else: if value is not None: self.recent_candidate_list = [ k for k in self.recent_candidate_list if set(value).issubset( set(cfg.item_dict[str(k)]['L2_Category_name'])) ] self.recent_candidate_list = list( set(self.recent_candidate_list) - set([self.busi_id])) + [self.busi_id] self.known_feature_category += [int(i) for i in value] self.known_feature_category = list( set(self.known_feature_category)) self.known_facet.append(facet) l = list(set(self.recent_candidate_list) - set([self.busi_id])) random.shuffle(l) if cfg.play_by != 'AOO' and cfg.play_by != 'AOO_valid': self.known_feature_total.clear() self.known_feature_total.append(self.known_feature_cluster) self.known_feature_total.append(self.known_feature_type) self.known_feature_total.append( self.known_feature_category) self.distance_dict = feature_distance( self.known_feature_total, self.user_id, self.TopKTaxo, self.features) self.distance_dict2 = self.distance_dict.copy() self.recent_candidate_list_ranked = rank_items( self.known_feature_total, self.items, self.features, self.transE_model, self.recent_candidate_list, self.rejected_item_list_) start = time.time() if value is not None and value[0] is not None: c = cal_ent(self.recent_candidate_list) d = c.do_job() self.entropy_dict = d for f in self.asked_feature: self.entropy_dict[f] = 0 for f in self.asked_feature: if self.distance_dict is not None and f in self.distance_dict: self.distance_dict[f] = 10000 if self.entropy_dict[f] == 0: self.distance_dict[f] = 10000 for f in self.asked_feature: if self.distance_dict2 is not None and f in self.distance_dict: self.distance_dict2[f] = 10000 if self.entropy_dict[f] == 0: self.distance_dict[f] = 10000 self.residual_feature_big = list( set(self.choose_pool) - set(self.known_facet)) ent_position, sim_position = None, None if self.entropy_dict is not None: ent_value = sorted([v for k, v in self.entropy_dict.items()], reverse=True) ent_position = [ ent_value.index(self.entropy_dict[big_f]) for big_f in self.residual_feature_big ] if self.distance_dict is not None: sim_value = sorted([v for k, v in self.distance_dict.items()], reverse=True) sim_position = [ sim_value.index(self.distance_dict[str(big_f)]) for big_f in self.residual_feature_big ] if len(self.residual_feature_big) > 0: with open(self.write_fp, 'a') as f: f.write( 'Turn Count: {} residual feature: {}***ent position: {}*** sim position: {}***\n' .format(self.turn_count, self.residual_feature_big, ent_position, sim_position))