예제 #1
0
파일: agent.py 프로젝트: SuBoYu/CRS_Chatbot
    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
예제 #2
0
파일: agent.py 프로젝트: SuBoYu/CRS_Chatbot
    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
예제 #3
0
    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
예제 #4
0
    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))
예제 #5
0
파일: agent.py 프로젝트: CART2020/CART
    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
예제 #6
0
파일: agent.py 프로젝트: CART2020/CART
    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))