示例#1
0
class Trainer():

    def __init__(self):

        et = EntityTracker()
        self.bow_enc = BoW_encoder()
        self.emb = UtteranceEmbed()
        at = ActionTracker(et)

        self.dataset, dialog_indices = Data(et, at).trainset
        self.dialog_indices_tr = dialog_indices[:200]
        self.dialog_indices_dev = dialog_indices[200:250]

        obs_size = self.emb.dim + self.bow_enc.vocab_size + et.num_features
        self.action_templates = at.get_action_templates()
        action_size = at.action_size
        nb_hidden = 128

        self.net = LSTM_net(obs_size=obs_size,
                            action_size=action_size,
                            nb_hidden=nb_hidden)


    def train(self):

        print('\n---training started---\n')
        epochs = 20
        for j in range(epochs):
            # iterate through dialogs
            num_tr_examples = len(self.dialog_indices_tr)
            loss = 0.
            for i,dialog_idx in enumerate(self.dialog_indices_tr):
                # get start and end index
                start, end = dialog_idx['start'], dialog_idx['end']
                # train on dialogue
                loss += self.dialog_train(self.dataset[start:end])
                # print #iteration
                sys.stdout.write('\r{}.[{}/{}]'.format(j+1, i+1, num_tr_examples))

            print('\n\n--- {}.tr loss {} ---'.format(j+1, loss/num_tr_examples))
            # evaluate every epoch
            accuracy = self.evaluate()
            print('--- {}.dev accuracy {} ---\n'.format(j+1, accuracy))

            if accuracy > 0.99:
                self.net.save()
                break

    def dialog_train(self, dialog):
        # create entity tracker
        et = EntityTracker()
        # create action tracker
        at = ActionTracker(et)
        # reset network
        self.net.reset_state()

        loss = 0.
        # iterate through dialog
        for (u, r) in dialog:
            u_ent = et.extract_entities(u)
            u_ent_features = et.context_features()
            u_emb = self.emb.encode(u)
            u_bow = self.bow_enc.encode(u)
            # concat features
            features = np.concatenate((u_ent_features, u_emb, u_bow), axis=0)
            # get action mask
            action_mask = at.action_mask()
            # forward propagation
            #  train step
            loss += self.net.train_step(features, r, action_mask)
        return loss/len(dialog)

    def evaluate(self):
        # create entity tracker
        et = EntityTracker()
        # create action tracker
        at = ActionTracker(et)
        # reset network
        self.net.reset_state()

        dialog_accuracy = 0.
        for dialog_idx in self.dialog_indices_dev:

            start, end = dialog_idx['start'], dialog_idx['end']
            dialog = self.dataset[start:end]
            num_dev_examples = len(self.dialog_indices_dev)

            # create entity tracker
            et = EntityTracker()
            # create action tracker
            at = ActionTracker(et)
            # reset network
            self.net.reset_state()

            # iterate through dialog
            correct_examples = 0
            for (u,r) in dialog:
                # encode utterance
                u_ent = et.extract_entities(u)
                u_ent_features = et.context_features()
                u_emb = self.emb.encode(u)
                u_bow = self.bow_enc.encode(u)
                # concat features
                features = np.concatenate((u_ent_features, u_emb, u_bow), axis=0)
                # get action mask
                action_mask = at.action_mask()
                # forward propagation
                #  train step
                prediction = self.net.forward(features, action_mask)
                correct_examples += int(prediction == r)
            # get dialog accuracy
            dialog_accuracy += correct_examples/len(dialog)

        return dialog_accuracy/num_dev_examples
示例#2
0
class Trainer():
    def __init__(self):
        import os
        #实体追踪
        et = EntityTracker()
        #词袋 word2vec
        self.bow_enc = BoW_encoder()
        #加载word2vec embedding
        self.emb = UtteranceEmbed()
        #将实体追踪器添加到动作追踪器中
        at = ActionTracker(et)
        #得到数据集和对话开始 结束行数
        self.dataset, dialog_indices = Data(et, at).trainset
        #划分数据集:200对做训练 50对做测试
        self.dialog_indices_tr = dialog_indices
        self.dialog_indices_dev = dialog_indices
        #obs_size 300维的词向量 + 85个袋中的词 + 4个槽位
        obs_size = self.emb.dim + self.bow_enc.vocab_size + et.num_features

        #话术模板
        self.action_templates = at.get_action_templates()
        #动作个数
        action_size = at.action_size
        #隐藏层神经元个数
        nb_hidden = 128

        self.net = LSTM_net(obs_size=obs_size,
                            action_size=action_size,
                            nb_hidden=nb_hidden)

    def train(self):

        print('\n:: training started\n')
        epochs = 25
        for j in range(epochs):
            # iterate through dialogs
            #训练集个数
            num_tr_examples = len(self.dialog_indices_tr)
            loss = 0.
            for i, dialog_idx in enumerate(self.dialog_indices_tr):
                # get start and end index
                start, end = dialog_idx['start'], dialog_idx['end']
                # train on dialogue
                loss += self.dialog_train(self.dataset[start:end])
                # print #iteration
                sys.stdout.write('\r{}.[{}/{}]'.format(j + 1, i + 1,
                                                       num_tr_examples))

            print('\n\n:: {}.tr loss {}'.format(j + 1, loss / num_tr_examples))
            # evaluate every epoch
            accuracy = self.evaluate()
            print(':: {}.dev accuracy {}\n'.format(j + 1, accuracy))

            if accuracy > 0.4:
                self.net.save()
                continue

    #训练过程
    def dialog_train(self, dialog):
        # create entity tracker
        et = EntityTracker()
        # create action tracker
        at = ActionTracker(et)
        # reset network
        self.net.reset_state()

        loss = 0.
        # iterate through dialog
        #u 用户输入 r 对应的动作索引
        for (u, r) in dialog:
            #u_ent 分词后的字符串
            u_ent = et.extract_entities(u)
            #槽位填充情况 【0 0 0 0】
            u_ent_features = et.context_features()
            #word2vec
            u_emb = self.emb.encode(u)
            #multi-hot
            u_bow = self.bow_enc.encode(u)
            # concat features
            #300 + 85 + 4 = 389
            features = np.concatenate((u_ent_features, u_emb, u_bow), axis=0)
            # get action mask
            action_mask = at.action_mask()
            # forward propagation
            #  train step
            loss += self.net.train_step(features, r, action_mask)
        return loss / len(dialog)

    #评估acc
    def evaluate(self):
        # create entity tracker
        et = EntityTracker()
        # create action tracker
        at = ActionTracker(et)
        # reset network
        self.net.reset_state()

        dialog_accuracy = 0.
        #加载测试集
        for dialog_idx in self.dialog_indices_dev:

            start, end = dialog_idx['start'], dialog_idx['end']
            dialog = self.dataset[start:end]
            num_dev_examples = len(self.dialog_indices_dev)

            # create entity tracker
            et = EntityTracker()
            # create action tracker
            at = ActionTracker(et)
            # reset network
            self.net.reset_state()

            # iterate through dialog
            correct_examples = 0
            #对于每个dialog 提取出utterance 和 response
            for (u, r) in dialog:
                # encode utterance
                #提取出user中带有的实体
                u_ent = et.extract_entities(u)
                #提取当前槽位填充情况
                u_ent_features = et.context_features()
                u_emb = self.emb.encode(u)
                u_bow = self.bow_enc.encode(u)
                # concat features
                features = np.concatenate((u_ent_features, u_emb, u_bow),
                                          axis=0)
                # get action mask 16维的multi-hot 向量
                action_mask = at.action_mask()
                # forward propagation
                #  train step
                prediction = self.net.forward(features, action_mask)
                correct_examples += int(prediction == r)
            # get dialog accuracy
            dialog_accuracy += correct_examples / len(dialog)

        return dialog_accuracy / num_dev_examples
class Trainer():
        def __init__(self, train_ratio=15/20, \
                                                        epochs=100, \
                                                        train_whole=True, \
                                                        ):

                self.train_ratio = train_ratio
                self.epochs = epochs
                

                #flag für fehleranalyse
                self.startCountingErrors = False
                self.count_all_one_eval = 0 
                self.count_all_one_train = 0 
                self.count_all_train = 0
                self.count_all_eval = 0
                #data.trainset = [(u,da_indx), ...]
                
                #HIER acttemps und size
                self.at = ActionTracker()
                self.action_templates = self.at.action_templates
                self.at.dialog_acts = self.at.dialog_acts
                self.at.dialog_act_ids = self.at.dialog_act_ids
                self.dataset, self.dialog_indices, self.other_da, self.other_da_id = self.at.get_data()
                self.action_size = self.at.action_size
                self.accs = []
                self.loss = []
                self.dev_accs =[]
                self.dev_loss=[]
                self.countErrors = Counter()
                self.countPredicitions = 0
                self.errorLog = {}
                self.highest_accuracy = 0
                #pickle.load(open("data/errors/errorLog.p", "rb"))
                if train_whole:
                        self.bow_enc = BoW_encoder()
                        self.emb = UtteranceEmbed()
                        #HIER numfeats
                        obs_size = self.emb.dim + self.bow_enc.vocab_size + self.action_size# + self.et.size_context_features
                        nb_hidden = 128
                        self.net = LSTM_net(obs_size,
                                                                        self.action_size,
                                                                        nb_hidden=nb_hidden)

        def train(self):
                print(self.other_da)
                print('\n:: training started', \
                                '\ntrain len :\t', round(len(self.dialog_indices) * self.train_ratio), \
                                '\ndev len :\t', len(self.dialog_indices) - round(len(self.dialog_indices) * self.train_ratio))
                print(self.epochs)
                random.shuffle(self.dialog_indices)
                self.dialog_indices_tr = self.dialog_indices[:round(len(self.dialog_indices) * self.train_ratio)]
                self.dialog_indices_dev = self.dialog_indices[round(len(self.dialog_indices) * self.train_ratio):]
                num_tr_examples = len(self.dialog_indices_tr)
                for j in range(self.epochs):

                       
                        #if j < 250:
                        #       self.startCountingErrors == True
                        # iterate through dialogs
                        
                        loss = 0.
                        random.shuffle(self.dialog_indices_tr)
                        for i, dialog_idx in enumerate(self.dialog_indices_tr):
                                # get start and end index
                                start, end = dialog_idx['start'], dialog_idx['end']
                                # train on dialogue
                                loss += self.dialog_train(self.dataset[start:end])
                                # print #iteration
                                sys.stdout.write('\r{}.[{}/{}]'.format(j+1, i+1, num_tr_examples))
                        print('\n\n:: {}.tr loss {}'.format(j+1, loss/num_tr_examples))
                        # evaluate every epoch
                        accuracy = self.evaluate()
                        self.accs.append(accuracy)
                        print(':: {}.dev accuracy {}\n'.format(j+1, accuracy))
                        #if accuracy > 0.98: # original threshold was 0.99
                        #       self.net.save() 
                        #       plt.plot(self.accs)
                        #       plt.xlabel("epochs")
                        #       plt.ylabel('accuracy')
                        #       plt.show()
                        #       break
                        if j == self.epochs-1:
                                #print("ACC: {}".format(float(sum(self.accs[349:]))/float(len(self.accs[249:]))))
                                #self.countErrors["ACCURACY"]= float(sum(self.accs[349:]))/float(len(self.accs[249:]))
                                #self.errorLog[dt.datetime.now()] = self.countErrors
                                #if accuracy > 0.95:
                                self.net.save()  # save any result after j iterations
                                #for key in self.countErrors.keys():
                        #               print("ACC: {}".format(float(sum(self.accs[349:]))/float(len(self.accs[249:]))))
                                #       self.countErrors[key] = self.countErrors[key]/ self.countPredicitions
                                #print(json.dumps(self.countErrors, indent=4))
                                #pickle.dump(self.accs, open("data/accuracies_trunc_09.p", "wb"))
                                #pickle.dump(self.loss, open("data/losses_trunc_09.p", "wb"))
                                #pickle.dump(self.at.dialog_acts, open("data/acts.p", "wb"))
                                #pickle.dump(self.at.dialog_act_ids, open("data/ids.p", "wb"))
                                #pickle.dump(self.dev_accs, open("data/dev_accuracies_00.p", "wb"))
                                #pickle.dump(self.dev_loss, open("data/dev_losses_00.p", "wb"))
                                print("Mean Accuracy: ", float(sum(self.accs[149:]))/float(len(self.accs[149:])))
                                print("Predictions LSTM Training: ", self.count_all_one_train)
                                print("LSTM ratio Training {}".format(float(self.count_all_one_train)/float(self.count_all_train)))
                                print("Predictions LSTM Evaluation: ", self.count_all_one_eval)
                                print("LSTM ratio Evaluation {}".format(float(self.count_all_one_eval)/float(self.count_all_eval)))


                                
                                plt.plot(self.accs)
                                plt.xlabel("epochs")
                                plt.ylabel('loss')
                                plt.show()
                
                                break


        def dialog_train(self, dialog):
                self.at.reset_action_mask()
                self.net.reset_state()
                try:
                        self.at.set_exercise(self.at.get_dialog_act_id(dialog[0][1],action_template=True))
                except:
                        print(dialog[0][1])
                        exit()
                self.at.automaton.reset_current_state()
                self.at.memory.reset_memory(self.at.exercise)
                loss = 0.
                self.at.initialize_am()
                self.at.automaton.reset_current_state()
                #error_code = re.compile(r"\[01\]+S")
                
                for (u,r) in dialog:
                        if r.startswith("intro"):
                                r = "intro"
                        r = self.at.get_dialog_act_id(r)
                        #print(r)
                        
                        u_emb = self.emb.encode(u)#HIER
                        #print('\nEmbedded Utterance, W2V:\n\n', u_emb)
                        u_bow = self.bow_enc.encode(u)#HIER
                        self.count_all_one_train += 1
                        
                        action_mask = self.at.am
                        # forward propagation
                        # train step
                        
                        features = np.concatenate((u_emb, u_bow, action_mask), axis=0)
                        lossValue , prediction = self.net.train_step(features, r, action_mask)
                        #current_state = self.at.automaton.current_state
                        #list_of_interest = [self.other_da[i] for i in range(len(self.other_da)) if action_mask[i] == 1]
                        #print("action mask: ",list_of_interest,"\ncurrent_state:",current_state.name,"\nprediction: ", self.other_da[prediction])
                        self.at.automaton.current_state,_ = self.at.walk(u, prediction)
                        #print(prediction)
                        #print(self.at.automaton.current_state.name)
                        
                        self.count_all_train +=1
                        #print("predicted: ", self.at.dialog_acts[prediction])
                        loss += lossValue
                        #loss += self.net.train_step(features, r)
                self.loss.append(loss/len(dialog))
                return loss/len(dialog)
        def evaluate(self):
                self.net.reset_state()
                dialog_accuracy = 0
                dialog_loss = 0
                errors = []
                
                for dialog_idx in self.dialog_indices_dev:
                        start, end = dialog_idx['start'], dialog_idx['end']
                        dialog = self.dataset[start:end]
                        num_dev_examples = len(self.dialog_indices_dev)
                        # reset network
                        self.net.reset_state()
                        try:
                                self.at.set_exercise(self.at.get_dialog_act_id(dialog[0][1],action_template=True))
                        except:
                                print(dialog)
                                exit()
                        self.at.memory.reset_memory(self.at.exercise)
                        self.at.initialize_am()
                        # iterate through dialog
                        correct_examples = 0
                        #last_action = np.zeros([self.action_size], dtype=np.float32)
                        prev_prediction = -1
                        self.at.automaton.reset_current_state()
                        prev_state = ""
                        i = 0
                        loss = 0
                        for (u,r) in dialog:
                                if r.startswith("intro"):
                                        r = "intro"
                                r = self.at.get_dialog_act_id(r)
                                i +=1
                                u_emb = self.emb.encode(u)#HIER
                                #print('\nEmbedded Utterance, W2V:\n\n', u_emb)
                                u_bow = self.bow_enc.encode(u)#HIER
                                prev_state = self.at.automaton.current_state.name
                                action_mask = self.at.am
                                features = np.concatenate((u_emb, u_bow, action_mask), axis=0)
                                prediction= self.net.forward(features,  action_mask, r)
                                #current_state = self.at.automaton.current_state
                                #list_of_interest = [self.other_da[i] for i in range(len(self.other_da)) if action_mask[i] == 1]
                                #print("action mask: ",list_of_interest,"\ncurrent_state:",current_state.name,"\nprediction: ", self.other_da[prediction])
                                self.at.automaton.current_state,_ = self.at.walk(u,prediction)
                                #self.count_all_eval +=1
                                #if prediction != r:
                                #       print("FROM: {}, with: {}, TO: {}, predicted: {}".format(prev_state, self.at.automaton.get_utterance_type(u), self.at.automaton.current_state.name, self.at.dialog_acts[prediction]))
                                #if self.startCountingErrors and prediction != r:
                                #       self.countErrors[self.at.dialog_acts[prediction] + ":" + self.at.dialog_acts[r]] +=1
                                #if self.startCountingErrors:
                                #       self.countPredicitions +=1
                                if prediction != r:
                                        errors.append("EXERCISE: {}, step {}, Previous State: {}, Previous Act: {}, Prediction: {} Actual Da: {}, Utterance: {}, Symbol: {}".format(self.at.exercise, i, prev_state,  self.at.dialog_acts[prev_prediction], self.at.dialog_acts[prediction], self.at.dialog_acts[r], u, self.at.automaton.get_utterance_type(u)))
                                prev_prediction = r
                                #print("Prediction: {} Actual Da: {}".format(self.at.dialog_acts[prediction],self.at.dialog_acts[r]))
                                #self.at.memory.update(prediction)
                                #last_action= np.zeros([self.action_size], dtype=np.float32)
                                #last_action[prediction-1] = 1

                                #prediction = self.net.forward(features)
                                
                                #print("predicted: ", self.at.dialog_acts[prediction])
                                #if prediction == r:
                                #       print(self.at.dialog_acts[r])
                                correct_examples += int(prediction == r)
                                self.count_all_eval += 1
                                #loss += loss_value[0]
                        # get dialog accuracy
                        dialog_accuracy += correct_examples/len(dialog)
                        #dialog_loss += loss / len(dialog)
                        
                if self.highest_accuracy > 0 and self.highest_accuracy -(dialog_accuracy/num_dev_examples) > 0.2:
                        for e in errors:
                                print(e)
                print(self.highest_accuracy -(dialog_accuracy/num_dev_examples))
                if self.highest_accuracy < dialog_accuracy/num_dev_examples:
                        self.highest_accuracy = dialog_accuracy/num_dev_examples
                self.dev_loss.append(dialog_loss/num_dev_examples)
                self.dev_accs.append(dialog_accuracy/num_dev_examples)
                print("dev_loss: {}".format(dialog_loss/num_dev_examples))
                return dialog_accuracy/num_dev_examples
示例#4
0
class Trainer():

    def __init__(self):
    
        et = EntityTracker()
        self.bow_enc = BoW_encoder()
        self.emb = UtteranceEmbed()
        
        at = ActionTracker(et)
        
        self.train_dataset, train_dialog_indices = Data(et, at).train_set
        self.test_dataset, test_dialog_indices = Data(et, at).test_set
        
        print('=========================\n')
        print('length of Train dialog indices : ', len(train_dialog_indices))
        print('=========================\n')

        print('=========================\n')
        print('length of Test dialog indices : ', len(test_dialog_indices))
        print('=========================\n')
        
        # Shuffle Training Dataset
        random.shuffle(train_dialog_indices)
        
        self.dialog_indices_tr = train_dialog_indices
        self.dialog_indices_dev = test_dialog_indices

        obs_size = self.emb.dim + self.bow_enc.vocab_size + et.num_features
        self.action_templates = at.get_action_templates()
        action_size = at.action_size
        
        # nb_hidden = 128
        nb_hidden = 150
        
        print('=========================\n')
        print('Action_templates: ', action_size)
        print('=========================\n')

        self.net = LSTM_net(obs_size=obs_size,
                       action_size=action_size,
                       nb_hidden=nb_hidden)
        
        self.et = et
        self.at = at
        
        action_projection = []
        for action in self.action_templates:
            action_projection.append(self.emb.encode(action))
        self.action_projection = np.transpose(action_projection)
        self.action_size = action_size

    def train(self, exp_name, model_name):

        print('\n:: training started\n')
        epochs = 100
        
        import joblib
        
        per_response_list = []
        per_dialogue_list = []
        
        early_stop = False
        early_stop_count = 0
        for j in range(epochs):
            # iterate through dialogs
            num_tr_examples = len(self.dialog_indices_tr)
            loss = 0.
            for i,dialog_idx in enumerate(self.dialog_indices_tr):
                # get start and end index
                start, end = dialog_idx['start'], dialog_idx['end']
                # train on dialogue
                loss += self.dialog_train(self.train_dataset[start:end])
                
                # print #iteration
                sys.stdout.write('\r{}.[{}/{}]'.format(j+1, i+1, num_tr_examples))
            
            print('\n\n:: {}.tr loss {}'.format(j+1, loss/num_tr_examples))
            # evaluate every epoch
            accuracy = self.evaluate()
            per_response_list.append(accuracy[0])
            per_dialogue_list.append(accuracy[1])
            max_dialogue = max(per_dialogue_list)
            
            if len(per_dialogue_list) > 1:
                prev_max_dialogue = sorted(per_dialogue_list, reverse=True)[1]
            
            if max_dialogue > 2.0 and accuracy[1] > prev_max_dialogue:
                early_stop_count += 1
                self.net.save(model_name)
           
            print(':: {}.dev accuracy {}\n'.format(j+1, accuracy))
            print('current max dialogue accuracy : {}\n'.format(sorted(per_dialogue_list, reverse=True)[0]))
        
        print('Max Dialogue Accuracy : ', max(per_dialogue_list))
        joblib.dump(per_response_list, 'emnlp_performance/with_slot/per_response_list_' + exp_name)
        joblib.dump(per_dialogue_list, 'emnlp_performance/with_slot/per_dialogue_list_' + exp_name)
        
        # self.net.save()

    def dialog_train(self, dialog):
        # create entity tracker
        et = self.et
        et.init_entities()
        # create action tracker
        at = self.at
        # reset network
        self.net.reset_state()
        self.net.reset_attention()
        
        loss = 0.
        i = 0
        pred_list = []
        # iterate through dialog
        for (u,r) in dialog:
            i += 1
            
            if r == '<UNK>':
                continue
                
            u_ent = et.extract_entities(u)
            u_ent_features = et.context_features()
            u_emb = self.emb.encode(u)
            u_bow = self.bow_enc.encode(u)
            # concat features
            features = np.concatenate((u_ent_features, u_emb, u_bow), axis=0)
            
            if i ==1:
                loss += self.net.train_step(features, r, self.action_projection)
                pred_list.append(r)
            else:
                action_one_hot = np.zeros(self.action_size)
                action_one_hot[pred_list[-1]] = 1
                loss += self.net.train_step(features, r, self.action_projection, action_one_hot)
                pred_list.append(r)
        return loss / len(dialog)

    def evaluate(self):

        dialog_accuracy = 0.
        correct_dialogue_count = 0
        
        # for each dialog
        for dialog_idx in self.dialog_indices_dev:

            start, end = dialog_idx['start'], dialog_idx['end']
            dialog = self.test_dataset[start:end]
            num_dev_examples = len(self.dialog_indices_dev)

            # create entity tracker
            et = self.et
            et.init_entities()
            # create action tracker
            at = self.at
            # reset network
            self.net.reset_state()
            self.net.reset_attention()

            # iterate through dialog
            correct_examples = 0
            
            pred_list = []
            i = 0
            for (u,r) in dialog:
                i += 1
                
                if u == 'api_call no result':
                    correct_examples += 1
                    continue
                
                if r == '<UNK>':
                    # correct_examples += 1
                    continue
                
                # encode utterance
                u_ent = et.extract_entities(u)
                u_ent_features = et.context_features()
                u_emb = self.emb.encode(u)
                u_bow = self.bow_enc.encode(u)
                # concat features
                features = np.concatenate((u_ent_features, u_emb, u_bow), axis=0)
                
                if i == 1:
                    prediction, user_attention_weights, action_weights = self.net.forward(features, self.action_projection)
                    pred_list.append(prediction)
                else:
                    action_one_hot = np.zeros(self.action_size)
                    action_one_hot[pred_list[-1]] = 1
                    prediction, user_attention_weights, action_weights = self.net.forward(features, self.action_projection, action_one_hot)
                    pred_list.append(prediction)
                    
                correct_examples += int(prediction == r)

            if correct_examples == len(dialog):
                correct_dialogue_count += 1
                
            # get dialog accuracy
            dialog_accuracy += correct_examples / len(dialog)
        
        per_response_accuracy = dialog_accuracy / num_dev_examples * 100
        per_dialogue_accuracy = correct_dialogue_count / num_dev_examples * 100
        
        print('=============================')
        print('correct dialogue count')
        print(correct_dialogue_count)
        print('=============================\n')
        
        return per_response_accuracy, per_dialogue_accuracy
示例#5
0
class Trainer():
    def __init__(self):

        et = EntityTracker()
        self.bow_enc = BoW_encoder()
        self.emb = UtteranceEmbed()
        at = ActionTracker(et)
        '''
        ['any preference on a type of cuisine', 'api_call <cuisine> <location> <party_size> <rest_type>', 'great let me do the reservation', 'hello what can i help you with today', 'here it is <info_address>', 'here it is <info_phone>', 'how many people would be in your party', "i'm on it", 'is there anything i can help you with', 'ok let me look into some options for you', 'sure is there anything else to update', 'sure let me find an other option for you', 'what do you think of this option: <restaurant>', 'where should it be', 'which price range are looking for', "you're welcome"]

        '''
        self.dataset, dialog_indices = Data(et, at).trainset
        self.dialog_indices_tr = dialog_indices[:200]
        self.dialog_indices_dev = dialog_indices[200:250]

        obs_size = self.emb.dim + self.bow_enc.vocab_size + et.num_features
        self.action_templates = at.get_action_templates()
        action_size = at.action_size
        nb_hidden = 128

        self.net = LSTM_net(obs_size=obs_size,
                            action_size=action_size,
                            nb_hidden=nb_hidden)

    def train(self):

        print('\n:: training started\n')
        epochs = 20
        for j in range(epochs):
            # iterate through dialogs
            num_tr_examples = len(self.dialog_indices_tr)
            loss = 0.
            for i, dialog_idx in enumerate(self.dialog_indices_tr):
                # get start and end index
                start, end = dialog_idx['start'], dialog_idx['end']
                # train on dialogue
                loss += self.dialog_train(self.dataset[start:end])
                # print #iteration
                sys.stdout.write('\r{}.[{}/{}]'.format(j + 1, i + 1,
                                                       num_tr_examples))

            print('\n\n:: {}.tr loss {}'.format(j + 1, loss / num_tr_examples))
            # evaluate every epoch
            accuracy = self.evaluate()
            print(':: {}.dev accuracy {}\n'.format(j + 1, accuracy))

            if accuracy > 0.99:
                self.net.save()
                break

    def dialog_train(self, dialog):
        # create entity tracker
        et = EntityTracker()
        # create action tracker
        at = ActionTracker(et)
        # reset network
        self.net.reset_state()

        loss = 0.
        # iterate through dialog
        for (u, r) in dialog:
            u_ent = et.extract_entities(u)
            u_ent_features = et.context_features()
            u_emb = self.emb.encode(u)
            u_bow = self.bow_enc.encode(u)
            # concat features
            features = np.concatenate((u_ent_features, u_emb, u_bow), axis=0)
            # get action mask
            action_mask = at.action_mask()
            # forward propagation
            #  train step
            loss += self.net.train_step(features, r, action_mask)
        return loss / len(dialog)

    def evaluate(self):
        # create entity tracker
        et = EntityTracker()
        # create action tracker
        at = ActionTracker(et)
        # reset network
        self.net.reset_state()

        dialog_accuracy = 0.
        for dialog_idx in self.dialog_indices_dev:

            start, end = dialog_idx['start'], dialog_idx['end']
            dialog = self.dataset[start:end]
            num_dev_examples = len(self.dialog_indices_dev)

            # create entity tracker
            et = EntityTracker()
            # create action tracker
            at = ActionTracker(et)
            # reset network
            self.net.reset_state()

            # iterate through dialog
            correct_examples = 0
            for (u, r) in dialog:
                # encode utterance
                u_ent = et.extract_entities(u)
                u_ent_features = et.context_features()
                u_emb = self.emb.encode(u)
                u_bow = self.bow_enc.encode(u)
                # concat features
                features = np.concatenate((u_ent_features, u_emb, u_bow),
                                          axis=0)
                # get action mask
                action_mask = at.action_mask()
                # forward propagation
                #  train step
                prediction = self.net.forward(features, action_mask)
                correct_examples += int(prediction == r)
            # get dialog accuracy
            dialog_accuracy += correct_examples / len(dialog)

        return dialog_accuracy / num_dev_examples
示例#6
0
class InteractiveSession():
    def __init__(self):
        self.bow_enc = BoW_encoder()
        self.emb = UtteranceEmbed()
        self.at = ActionTracker(interact=True)
        print(self.at.dialog_acts)
        _, _, self.other_da, self.other_da_id = self.at.get_data()
        self.action_templates = self.at.action_templates
        self.action_size = self.at.action_size
        #self.responses = [r[0] for r in self.at.responses]
        #print(self.emb.dim , self.bow_enc.vocab_size , self.action_size)
        self.obs_size = self.emb.dim + self.bow_enc.vocab_size + self.action_size
        nb_hidden = 128
        self.exercises = list(self.at.action_templates.keys())
        self.net = LSTM_net(obs_size=self.obs_size,
                            action_size=self.action_size,
                            nb_hidden=nb_hidden)
        # restore checkpoint
        self.net.restore()

        # setup remote interaction via zeromq
        context = zmq.Context.instance()
        # PUB socket for sending system-output
        self.pubSocket: zmq.Socket = context.socket(zmq.PUB)
        self.pubSocket.bind(Config.SYSTEM_OUTPUT_ADDR)
        # SUB socket for receiving user-input
        self.subSocket: zmq.Socket = context.socket(zmq.SUB)
        self.subSocket.connect(Config.USER_INPUT_ADDR)
        self.subSocket.setsockopt_string(zmq.SUBSCRIBE,
                                         Config.USER_INPUT_SUBJECT)
        self.lastOutputMessage: str = None
        self.requestHandler: threading.Thread = None
        self.requestInterrupted: threading.Lock = None

    def has_exercise(self, exercise_name: str) -> bool:
        return exercise_name in self.at.action_templates

    def get_current_exercise(self) -> str:
        return self.at.exercise

    def send(self, message, utteranceType, state, dialogAct):
        print(">>", message)
        data = SystemOutputData(text=message,
                                utterance_type=utteranceType,
                                state=state,
                                dialogue_act=dialogAct)
        msg = SystemOutputMessage(type=MessageType.OUTPUT,
                                  timestamp=int(time.time() * 1000),
                                  data=data)
        jsonMsg = json.dumps(msg.to_dict())
        self.lastOutputMessage = jsonMsg
        rawMsg = "%s %s" % (to_enum(MessageType, msg.type), jsonMsg)
        # print("  ", rawMsg)#DEBUG
        self.pubSocket.send_string(rawMsg)

    def receive(self) -> 'UserInputMessage':
        rawMsg = self.subSocket.recv_string()
        # print("  ", rawMsg)#DEBUG
        # FIXME detect & handle when message has other type than "input"
        # TODO handle message types other than "input"
        msgTypeStr = to_enum(MessageType, MessageType.INPUT)
        # extract JSON message by removing subject/subscription string from beginning of message:
        msgStr = rawMsg.replace(msgTypeStr, "", 1).strip()
        return user_input_message_from_dict(json.loads(msgStr))

    def start_processing_requests(self, verbose: bool = False):
        self.stop_processing_requests()
        self.requestInterrupted = threading.Lock()
        self.requestInterrupted.acquire()
        self.requestHandler = threading.Thread(
            target=request_worker,
            args=(Config.QUERY_SYSTEM_OUTPUT_ADDR, self,
                  self.requestInterrupted, verbose))
        self.requestHandler.start()

    def stop_processing_requests(self):
        if self.requestInterrupted is not None and self.requestHandler is not None and self.requestHandler.isAlive(
        ):
            self.requestInterrupted.release()
            # print("should stop request_worker thread now!")
            self.requestHandler.join()
            print("stopped request_worker thread.")

    def interact_anew(self,
                      verbose,
                      update,
                      out_file,
                      new_state_name: str = None):
        prev_prediction = -1
        self.net.reset_state()
        if new_state_name is None:
            new_state_name = random.choice(self.exercises)
        self.at.set_exercise_string(new_state_name)
        self.at.memory.reset_memory(self.at.exercise)
        self.at.initialize_am()

        u = "start"
        if verbose == True:
            print("\n*******************\nÄUßERUNGSTYP: ",
                  self.at.automaton.get_utterance_type(u))

        action_mask = self.at.am
        u_emb = self.emb.encode(u)  # HIER
        u_bow = self.bow_enc.encode(u)  # HIER
        features = np.concatenate((u_emb, u_bow, action_mask), axis=0)
        # forward
        prediction = self.net.forward(features,
                                      action_mask,
                                      self.other_da,
                                      print_top=True)
        self.at.automaton.current_state, response = self.at.walk(u, prediction)
        prev_prediction = prediction

        if verbose == True:
            print("AKTUELLER ZUSTAND: ", self.at.automaton.current_state.name,
                  "\nDIALOGAKT: ", self.other_da[prediction],
                  "\n*******************\n"
                  )  # print("CURRENT Exercise: ", self.at.exercise)

        # self.net.train_step(features, prediction, action_mask)
        # response = self.at.get_text(prediction)
        self.send(response, self.at.automaton.get_utterance_type(u),
                  self.at.automaton.current_state.name,
                  self.at.dialog_acts[prediction])  # print('>>', response)
        if out_file:
            out_file.write(u + '\t' + response + '\t' +
                           self.other_da[prediction] + '\n')
        return prev_prediction

    def interact(self, verbose, update, write_to_file):
        print(
            "How do you do? I'm glad you're here. Let's do some exercises together."
        )
        # open file to write around here
        # only if write_to_file !
        with open('data/dialogs_from_interaction', 'a') as out:
            with open("data/utterances_from_interaction", "a") as uttout:
                self.start_processing_requests(verbose)
                out_file = None
                if write_to_file:
                    out_file = out
                prev_prediction = self.interact_anew(verbose, update, out_file)
                # begin interaction loop
                while True:
                    if verbose == True:
                        print([
                            self.other_da[i] for i in range(len(self.at.am))
                            if self.at.am[i] == 1
                        ])
                    #print("prediction: ",self.at.dialog_acts[prediction])
                    #print("response: ",response)

                    # get input from user; utterance isn't saved!
                    message = self.receive()  # u = input(':: ')
                    u = message.data.strip()
                    print(":: %s" % (u))

                    # check if user wants to begin new session
                    if u == 'clear' or u == 'reset' or u == 'restart' or u == 'von vorne' or u == 'neustart':
                        if write_to_file:
                            out.write("WARNING: Interaction was reset.\n\n")
                        prev_prediction = self.interact_anew(
                            verbose, update, out_file)
                        if write_to_file:
                            uttout.write(
                                u + "\t" +
                                self.at.automaton.get_utterance_type(u) + "\n")

                    elif self.other_da[prev_prediction] in [
                            "closing", "finish"
                    ]:
                        if write_to_file:
                            out.write('\n')
                        prev_prediction = self.interact_anew(
                            verbose, update, out_file)

                    # check for exit command
                    elif u == 'exit' or u == 'quit':

                        if update == True:
                            self.net.save()
                        self.send(
                            'Ok, wir brechen ab. Bis zum nächsten Mal!',
                            'EXIT COMMAND',
                            self.at.automaton.current_state.name, "UNKNOWN"
                        )  # print('>> Ok, wir brechen ab. Bis zum nächsten Mal!')
                        if write_to_file:
                            out.write("WARNING: Dialog may not be finished.\n")
                        break

                    else:
                        if u == "\n" or u == "":
                            u = '<SILENCE>'
                        #self.at.reset_action_mask()

                        if self.at.automaton.current_state.name == "all_one":
                            if verbose == True:
                                print("\n*******************\nÄUßERUNGSTYP: ",
                                      self.at.automaton.get_utterance_type(u))
                            ##print(self.at.automaton.current_state.name, self.at.dialog_acts[prev_prediction])
                        else:
                            if verbose == True:
                                print("\n*******************\nÄUßERUNGSTYP: ",
                                      self.at.automaton.get_utterance_type(u))
                        action_mask = self.at.am
                        u_emb = self.emb.encode(u)  #HIER
                        u_bow = self.bow_enc.encode(u)  #HIER
                        features = np.concatenate((u_emb, u_bow, action_mask),
                                                  axis=0)
                        # forward

                        prediction = self.net.forward(features,
                                                      action_mask,
                                                      self.other_da,
                                                      print_top=True)
                        self.at.automaton.current_state, response = self.at.walk(
                            u, prediction)
                        if prediction != "all_one":
                            prev_prediction = prediction

                        #self.at.memory.update(prediction)
                        if verbose == True:
                            print(
                                "AKTUELLER ZUSTAND: ",
                                self.at.automaton.current_state.name,
                                "\nDIALOGAKT: ", self.other_da[prediction],
                                "\n*******************\n"
                            )  #print("CURRENT Exercise: ", self.at.exercise)

                        self.net.train_step(features, prediction, action_mask)
                        self.send(response,
                                  self.at.automaton.get_utterance_type(u),
                                  self.at.automaton.current_state.name,
                                  self.at.dialog_acts[prediction]
                                  )  # print('>>', response)
                        if write_to_file:
                            out.write(u + '\t' + response + '\t' +
                                      self.other_da[prediction] + '\n')
                            uttout.write(
                                u + "\t" +
                                self.at.automaton.get_utterance_type(u) + "\n")
                if write_to_file:
                    out.write('\n')
                self.stop_processing_requests()