예제 #1
0
    def set_model(self, inference=False):
        self.model_type = 'linear' if 'phone' in self.task else 'rnn'
        input_dim = int(self.config['downstream'][self.model_type]['input_dim']) if \
                    self.config['downstream'][self.model_type]['input_dim'] != 'None' else None
        if 'mockingjay' in self.task:
            self.mockingjay = Tester(self.mock_config, self.mock_paras)
            if self.fine_tune and inference:
                self.mockingjay.load = False  # Do not load twice when testing the fine-tuned model, load only for fine-tune training
            self.mockingjay.set_model(inference=True,
                                      with_head=self.paras.with_head)
            self.dr = self.mockingjay.dr
            if input_dim is None:
                input_dim = self.mock_config['mockingjay']['hidden_size']
        elif 'apc' in self.task:
            self.apc = get_apc_model(path=self.paras.apc_path)
            if input_dim is None:
                input_dim = self.mock_config['mockingjay'][
                    'hidden_size']  # use identical dim size for fair comparison
        elif 'baseline' in self.task:
            if input_dim is None:
                input_dim = mel_dim
        else:
            raise NotImplementedError('Invalid Task!')

        if self.model_type == 'linear':
            self.classifier = LinearClassifier(
                input_dim=input_dim,
                class_num=self.dataloader.dataset.class_num,
                task=self.task,
                dconfig=self.config['downstream']['linear'],
                sequencial=False).to(self.device)
        elif self.model_type == 'rnn':
            self.classifier = RnnClassifier(
                input_dim=input_dim,
                class_num=self.dataloader.dataset.class_num,
                task=self.task,
                dconfig=self.config['downstream']['rnn']).to(self.device)

        if not inference and self.fine_tune:
            # Setup Fine tune optimizer
            self.mockingjay.mockingjay.train()
            param_optimizer = list(
                self.mockingjay.mockingjay.named_parameters()) + list(
                    self.classifier.named_parameters())
            self.optimizer = get_mockingjay_optimizer(
                params=param_optimizer,
                lr=self.learning_rate,
                warmup_proportion=self.config['optimizer']
                ['warmup_proportion'],
                training_steps=self.total_steps)
        elif not inference:
            self.optimizer = Adam(self.classifier.parameters(),
                                  lr=self.learning_rate,
                                  betas=(0.9, 0.999))
            self.classifier.train()
        else:
            self.classifier.eval()

        if self.load:  # This will be set to True by default when Tester is running set_model()
            self.load_model(inference=inference)
예제 #2
0
def get_downstream_model(args, input_dim, class_num, config):
    
    model_name = args.run.split('_')[-1].replace('frame', 'linear') # support names: ['linear', '1hidden', 'concat', 'utterance']
    model_config = config['model'][model_name]

    if args.task == 'speaker' and 'utterance' in args.run:
        downstream_model = RnnClassifier(input_dim, class_num, model_config)
    else:
        downstream_model = LinearClassifier(input_dim, class_num, model_config)
    
    return downstream_model
예제 #3
0
class Downstream_Solver(Solver):
    ''' Handler for complete training progress'''
    def __init__(self, config, paras, task):
        super(Downstream_Solver, self).__init__(config, paras)
        # Downstream task the solver is solving
        self.task = task
        self.mock_paras = copy.deepcopy(paras)
        self.mock_config = copy.deepcopy(config)

        # path and directories
        self.exp_name = self.exp_name.replace('mockingjay', task)
        self.paras.ckpdir = paras.ckpdir.replace('mockingjay', task)
        self.ckpdir = self.ckpdir.replace('mockingjay', task)
        self.ckpt = os.path.join(paras.ckpdir, paras.dckpt)

        # modify log directory
        paras.logdir = paras.logdir.replace('mockingjay', task)

        # model
        self.model_type = config['downstream']['model_type']
        self.load_model_list = config['downstream']['load_model_list']
        self.fine_tune = paras.fine_tune
        self.run_mockingjay = paras.run_mockingjay
        self.run_apc = paras.run_apc
        if self.fine_tune:
            assert (
                self.run_mockingjay
            ), 'Use `--run_mockingjay` to fine-tune the mockingjay model.'
            assert (not self.run_apc
                    ), 'Fine tuning only supports the mockingjay model.'
            assert (
                not self.paras.with_head
            ), 'Fine tuning only supports the mockingjay model, not with head.'
        assert (not (self.run_mockingjay and self.run_apc)
                ), 'Mockingjay and Apc can not run at the same time!'
        if self.run_mockingjay and self.paras.with_head:
            self.verbose('Using Mockingjay representations from head.')
        elif self.run_mockingjay and self.fine_tune:
            self.verbose('Fine-tuning on Mockingjay representations.')
        elif self.run_mockingjay:
            self.verbose('Using Mockingjay representations.')

    def load_data(self, split='train', load='phone'):
        ''' Load date for training / testing'''
        assert (load in [
            'phone', 'cpc_phone', 'sentiment', 'speaker', 'speaker_large'
        ]), 'Unsupported dataloader!'
        if load == 'phone' or load == 'cpc_phone' or load == 'speaker_large':
            if split == 'train':
                self.verbose('Loading source data from ' +
                             str(self.config['dataloader']['train_set']) +
                             ' from ' + self.config['dataloader']['data_path'])
                if load == 'phone' or load == 'cpc_phone':
                    self.verbose('Loading phone data from ' +
                                 str(self.config['dataloader']['train_set']) +
                                 ' from ' +
                                 self.config['dataloader']['phone_path'])
            elif split == 'test':
                if load != 'cpc_phone':
                    self.verbose('Loading testing data ' +
                                 str(self.config['dataloader']['test_set']) +
                                 ' from ' +
                                 self.config['dataloader']['data_path'])
                if load == 'phone':
                    self.verbose('Loading label data ' +
                                 str(self.config['dataloader']['test_set']) +
                                 ' from ' +
                                 self.config['dataloader']['phone_path'])
                elif load == 'cpc_phone':
                    self.verbose('Loading label data from ' +
                                 self.config['dataloader']['phone_path'])
            else:
                raise NotImplementedError('Invalid `split` argument!')
        elif load == 'speaker':
            if split == 'train':
                self.verbose('Loading source data from ' +
                             str(self.config['dataloader']
                                 ['train_set']).replace('360', '100') +
                             ' from ' + self.config['dataloader']['data_path'])
            elif split == 'test':
                self.verbose('Loading testing data ' +
                             str(self.config['dataloader']
                                 ['test_set']).replace('360', '100') +
                             ' from ' + self.config['dataloader']['data_path'])
            else:
                raise NotImplementedError('Invalid `split` argument!')
        elif load == 'sentiment':
            target = self.config['dataloader']['sentiment_config']['dataset']
            sentiment_path = self.config['dataloader']['sentiment_config'][
                target]['path']
            self.verbose(f'Loading {split} data from {sentiment_path}')
        else:
            raise NotImplementedError('Unsupported downstream tasks.')

        setattr(self, 'dataloader', get_Dataloader(split, load=load, use_gpu=self.paras.gpu, \
                run_mockingjay=self.run_mockingjay, mock_config=self.config['mockingjay'], \
                **self.config['dataloader']))

    def set_model(self, inference=False):
        input_dim = int(self.config['downstream'][self.model_type]['input_dim']) if \
                    self.config['downstream'][self.model_type]['input_dim'] != 'None' else None
        if 'mockingjay' in self.task:
            self.mockingjay = Tester(self.mock_config, self.mock_paras)
            if self.fine_tune and inference:
                self.mockingjay.load = False  # Do not load twice when testing the fine-tuned model, load only for fine-tune training
            self.mockingjay.set_model(inference=True,
                                      with_head=self.paras.with_head)
            self.dr = self.mockingjay.dr
            if input_dim is None:
                input_dim = self.mock_config['mockingjay']['hidden_size']
        elif 'apc' in self.task:
            self.apc = get_apc_model(path=self.paras.apc_path)
            if input_dim is None:
                input_dim = self.mock_config['mockingjay'][
                    'hidden_size']  # use identical dim size for fair comparison
        elif 'baseline' in self.task:
            if input_dim is None:
                if 'input_dim' in self.mock_config['mockingjay']:
                    input_dim = self.mock_config['mockingjay']['input_dim']
                    self.verbose(
                        'Using `input_dim` setting from config for downstream model.'
                    )
                else:
                    input_dim = fmllr_dim if 'fmllr' in self.config[
                        'dataloader'][
                            'data_path'] else mfcc_dim if 'mfcc' in self.config[
                                'dataloader']['data_path'] else mel_dim
        else:
            raise NotImplementedError('Invalid Task!')

        if self.model_type == 'linear':
            self.classifier = LinearClassifier(
                input_dim=input_dim,
                class_num=self.dataloader.dataset.class_num,
                task=self.task,
                dconfig=self.config['downstream']['linear']).to(self.device)
        elif self.model_type == 'rnn':
            self.classifier = RnnClassifier(
                input_dim=input_dim,
                class_num=self.dataloader.dataset.class_num,
                task=self.task,
                dconfig=self.config['downstream']['rnn']).to(self.device)

        if not inference and self.fine_tune:
            # Setup Fine tune optimizer
            self.mockingjay.mockingjay.train()
            param_optimizer = list(
                self.mockingjay.mockingjay.named_parameters()) + list(
                    self.classifier.named_parameters())
            self.optimizer = get_mockingjay_optimizer(
                params=param_optimizer,
                lr=self.learning_rate,
                warmup_proportion=self.config['optimizer']
                ['warmup_proportion'],
                training_steps=self.total_steps)
        elif not inference:
            self.optimizer = Adam(self.classifier.parameters(),
                                  lr=self.learning_rate,
                                  betas=(0.9, 0.999))
            self.classifier.train()
        else:
            self.classifier.eval()

        if self.load:  # This will be set to True by default when Tester is running set_model()
            self.load_model(inference=inference)

    def save_model(self, name, model_all=True, assign_name=None):
        if model_all:
            all_states = {
                'Classifier':
                self.classifier.state_dict(),
                'Mockingjay':
                self.mockingjay.mockingjay.state_dict()
                if self.fine_tune else None,
                'Optimizer':
                self.optimizer.state_dict(),
                'Global_step':
                self.global_step,
                'Settings': {
                    'Config': self.config,
                    'Paras': self.paras,
                },
            }
        else:
            all_states = {
                'Classifier': self.classifier.state_dict(),
                'Settings': {
                    'Config': self.config,
                    'Paras': self.paras,
                },
            }

        if assign_name is not None:
            model_path = f'{self.ckpdir}/{assign_name}.ckpt'
            torch.save(all_states, model_path)
            return

        new_model_path = '{}/{}-{}.ckpt'.format(self.ckpdir, name,
                                                self.global_step)
        torch.save(all_states, new_model_path)
        self.model_kept.append(new_model_path)

        if len(self.model_kept) >= self.max_keep:
            os.remove(self.model_kept[0])
            self.model_kept.pop(0)

    def load_model(self, inference=False):
        self.verbose('Load model from {}'.format(self.ckpt))
        all_states = torch.load(self.ckpt, map_location='cpu')

        if 'Classifier' in self.load_model_list:
            try:
                self.classifier.load_state_dict(all_states['Classifier'])
                self.verbose('[Classifier] - Loaded')
            except:
                self.verbose('[Classifier - X]')

        if 'Optimizer' in self.load_model_list and not inference:
            try:
                self.optimizer.load_state_dict(all_states['Optimizer'])
                for state in self.optimizer.state.values():
                    for k, v in state.items():
                        if torch.is_tensor(v):
                            state[k] = v.cuda()
                self.verbose('[Optimizer] - Loaded')
            except:
                self.verbose('[Optimizer - X]')

        if 'Global_step' in self.load_model_list:
            try:
                self.global_step = all_states['Global_step']
                self.verbose('[Global_step] - Loaded')
            except:
                self.verbose('[Global_step - X]')

        if self.fine_tune:
            try:
                self.verbose(
                    '@ Downstream, [Fine-Tuned Mockingjay] - Loading from Upstream Tester...'
                )
                self.mockingjay.load_model(inference=inference,
                                           from_path=self.ckpt)
                self.verbose('@ Downstream, [Fine-Tuned Mockingjay] - Loaded')
            except:
                self.verbose('[Fine-Tuned Mockingjay] - X')

        self.verbose('Model loading complete!')
    def set_model(self, inference=False):
        input_dim = int(self.config['downstream'][self.model_type]['input_dim']) if \
                    self.config['downstream'][self.model_type]['input_dim'] != 'None' else None
        if 'transformer' in self.task:
            self.upstream_tester = Tester(self.upstream_config,
                                          self.upstream_paras)
            if self.fine_tune and inference:
                self.upstream_tester.load = False  # During inference on fine-tuned model, load with `load_downstream_model()`
            self.upstream_tester.set_model(
                inference=True, with_head=self.paras.with_head
            )  # inference should be set True so upstream solver won't create optimizer
            self.dr = self.upstream_tester.dr
            if input_dim is None:
                input_dim = self.transformer_config['hidden_size']
        elif 'apc' in self.task:
            self.apc = get_apc_model(path=self.paras.apc_path)
            if input_dim is None:
                input_dim = self.transformer_config[
                    'hidden_size']  # use identical dim size for fair comparison
        elif 'baseline' in self.task:
            if input_dim is None:
                if 'input_dim' in self.transformer_config:
                    input_dim = self.transformer_config['input_dim']
                else:
                    raise ValueError(
                        'Please update your config file to include the attribute `input_dim`.'
                    )
        else:
            raise NotImplementedError('Invalid Task!')

        if self.model_type == 'linear':
            self.classifier = LinearClassifier(
                input_dim=input_dim,
                class_num=self.dataloader.dataset.class_num,
                dconfig=self.config['downstream']['linear']).to(self.device)
        elif self.model_type == 'rnn':
            self.classifier = RnnClassifier(
                input_dim=input_dim,
                class_num=self.dataloader.dataset.class_num,
                dconfig=self.config['downstream']['rnn']).to(self.device)

        if not inference and self.fine_tune:
            # Setup Fine tune optimizer
            self.upstream_tester.transformer.train()
            param_optimizer = list(
                self.upstream_tester.transformer.named_parameters()) + list(
                    self.classifier.named_parameters())
            self.optimizer = get_optimizer(
                params=param_optimizer,
                lr=self.learning_rate,
                warmup_proportion=self.config['optimizer']
                ['warmup_proportion'],
                training_steps=self.total_steps)
        elif not inference:
            self.optimizer = Adam(self.classifier.parameters(),
                                  lr=self.learning_rate,
                                  betas=(0.9, 0.999))
            self.classifier.train()
        else:
            self.classifier.eval()

        if self.load:  # This will be set to True by default when Tester is running set_model()
            self.load_downstream_model(inference=inference)