def run_main(): args = parse_arg() if args.IMDb: ds = ds_imdb else: ds = ds_jptxt print("1. preparing datasets ... ", end="", flush=True) dataset_generator = ds.DataSetGenerator(args.vocab_file[0], args.text_length, mecab_dict=args.mecab_dict) test_ds = dataset_generator.loadTSV(args.tsv_file[0]) test_dl = ds.get_data_loader(test_ds, args.batch_size, for_train=False) dataset_generator.build_vocab(test_ds) print("done.", flush=True) print("2. loading network ... ", end="", flush=True) conf = get_config(file_path=args.conf[0]) bert_base = BertModel(conf) net = BertClassifier(bert_base, out_features=2) net.load_state_dict(torch.load(args.load_path[0])) net.eval() device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") net.to(device) print("done.", flush=True) criterion = torch.nn.CrossEntropyLoss() # クラス分けの場合 # criterion = torch.nn.MSELoss() # 数値予測の場合 print("3. run tests. ", flush=True) epoch_acc = test_model(net, test_dl, criterion, device) print("# of test data: {} || Acc. {:.4f}".format(len(test_dl.dataset), epoch_acc))
def bert_model(): config = get_config(file_path=BERT_CONFIG) net_bert = BertModel(config) net_trained = BertForEmoji(net_bert) net_trained.load_state_dict( torch.load(MODEL_FILE, map_location=torch.device('cpu'))) device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") net_trained.eval() net_trained.to(device) return net_trained
def build_bert_model(): config = get_config(file_path=BERT_CONFIG) net_bert = BertModel(config) # BERTモデルを作成します net_trained = BertForchABSA(net_bert) net_trained.load_state_dict(torch.load(MODEL_FILE, map_location='cpu')) device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") net_trained.eval() # モデルを検証モードに net_trained.to(device) return net_trained
def __init__(self, data_dir=r'./', bert_dir=r'./pytorch_advanced/nlp_sentiment_bert/'): self.data_dir = data_dir self.bert_dir = bert_dir self.tokenizer_bert = BertTokenizer( vocab_file=self.bert_dir + "vocab/bert-base-uncased-vocab.txt", do_lower_case=True) self.vocab_bert, self.ids_to_tokens_bert = load_vocab( vocab_file=self.bert_dir + "vocab/bert-base-uncased-vocab.txt") config = get_config(file_path=self.bert_dir + "weights/bert_config.json") self.net_bert = BertModel(config) self.net_bert = set_learned_params(self.net_bert, weights_path=self.bert_dir + "weights/pytorch_model.bin")
def run_main(): args = parse_arg() if args.random_seed is not None: init_random_seed(args.random_seed) if args.IMDb: ds = ds_imdb else: ds = ds_jptxt print("1. preparing datasets ... ", end="", flush=True) dataset_generator = ds.DataSetGenerator( args.vocab_file[0], args.text_length, do_normalize_text=args.normalize_text, mecab_dict=args.mecab_dict) data_set = dataset_generator.loadTSV(args.train_tsv[0]) train_ds, validation_ds = data_set.split(split_ratio=0.8, random_state=random.seed(1234)) dataset_generator.build_vocab(train_ds) train_dl = ds.get_data_loader(train_ds, args.batch_size, for_train=True) validation_dl = ds.get_data_loader(validation_ds, args.batch_size, for_train=False) print("done.", flush=True) print("2. preparing network ... ", end="", flush=True) conf = get_config(file_path=args.conf[0]) bert_base = BertModel(conf) bert_base = set_learned_params(bert_base, weights_path=args.bert_model[0]) net = BertClassifier(bert_base, out_features=2) # out_features = クラス数 net.train() optimizer = get_optimizer(net) criterion = torch.nn.CrossEntropyLoss() # クラス分けの場合 # criterion = torch.nn.MSELoss() # 数値予測の場合 print("done.", flush=True) print("3. start to train.", flush=True) data_loader_set = {"train": train_dl, "validation": validation_dl} net_trained = train_model(net, data_loader_set, criterion, optimizer, args.epoch) if args.save_path is not None: torch.save(net_trained.to("cpu").state_dict(), args.save_path)
def run_main(): args = parse_arg() if args.IMDb: ds = ds_imdb else: ds = ds_jptxt print("1. preparing datasets ... ", end="", flush=True) dataset_generator = ds.DataSetGenerator(args.vocab_file[0], args.text_length, args.mecab_dict) dataset = dataset_generator.loadTSV_at_index(args.tsv_file[0], args.index) dataset_generator.build_vocab(dataset) dataloader = ds.get_data_loader(dataset, args.batch_size, for_train=False) print("done.", flush=True) print("2. loading network ... ", end="", flush=True) conf = get_config(file_path=args.conf[0]) bert_base = BertModel(conf) net = BertClassifier(bert_base, out_features=2) net.load_state_dict(torch.load(args.load_path[0])) net.eval() device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") net.to(device) print("done.", flush=True) example = next(iter(dataloader)) inputs = example.Text[0].to(device) # 文章 preds, attention_probs = predict(net, inputs) if args.save_html is not None: print("3. generating HTML file.", flush=True) html = mk_html(example.Text[0][0], example.Label[0], preds[0], attention_probs, dataset_generator.tokenizer) with open(args.save_html, "w") as f: f.write(html) elif args.save_raw_attn is not None: print("3. generating raw attention tsv file.", flush=True) mk_high_attention_words_list(example.Text[0][0], example.Label[0], preds[0], attention_probs, dataset_generator.tokenizer, args.save_raw_attn) else: print("no flag for saving file")
# IDを単語に戻す text = tokenizer_bert.convert_ids_to_tokens(text_minibatch_1) print(text) # # 2.BERTによるネガポジ分類モデル実装 # In[16]: from utils.bert import get_config, BertModel,BertForchABSA, set_learned_params # モデル設定のJOSNファイルをオブジェクト変数として読み込みます config = get_config(file_path="./weights/bert_config.json") # BERTモデルを作成します net_bert = BertModel(config) # BERTモデルに学習済みパラメータセットします net_bert = set_learned_params( net_bert, weights_path="./weights/pytorch_model.bin") # In[17]: # モデル構築 net = BertForchABSA(net_bert)
encoded_layers, _ = self.bert( input_ids, token_type_ids, attention_mask, output_all_encoded_layers, attention_show_flg) # 入力文章の1単語目[CLS]の特徴量を使用して、ポジ・ネガを分類します vec_0 = encoded_layers[:, 0, :] vec_0 = vec_0.view(-1, self.cls.in_features) # sizeを[batch_size, hidden_sizeに変換 out = self.cls(vec_0) # attention_showのときは、attention_probs(1番最後の)もリターンする if attention_show_flg == True: return out, attention_probs elif attention_show_flg == False: return out if __name__ == "__main__": import argparse from utils.bert import BertModel, get_config, set_learned_params def parse_arg(): parser = argparse.ArgumentParser(description="Test for BERT for Japanese Texts.") parser.add_argument("conf", type=str, nargs=1, help="a configuration file.") parser.add_argument("model", type=str, nargs=1, help="a trained model file.") return parser.parse_args() args = parse_arg() conf = get_config(file_path=args.conf[0]) bert_base = BertModel(conf) bert_base = set_learned_params(bert_base, weights_path=args.model[0]) net = BertClassifier(bert_base, out_features=2) print(net)
def main(): # define output dataframe sample = pd.read_csv("./data/sample_submission.csv") # データを読み込んだときに、読み込んだ内容に対して行う処理を定義します max_length = 256 TEXT = torchtext.data.Field(sequential=True, tokenize=tokenizer_with_preprocessing, use_vocab=True, lower=True, include_lengths=True, batch_first=True, fix_length=max_length, init_token="[CLS]", eos_token="[SEP]", pad_token='[PAD]', unk_token='[UNK]') LABEL1 = torchtext.data.Field(sequential=False, use_vocab=False) LABEL2 = torchtext.data.Field(sequential=False, use_vocab=False) LABEL3 = torchtext.data.Field(sequential=False, use_vocab=False) LABEL4 = torchtext.data.Field(sequential=False, use_vocab=False) LABEL5 = torchtext.data.Field(sequential=False, use_vocab=False) LABEL6 = torchtext.data.Field(sequential=False, use_vocab=False) # (注釈):各引数を再確認 # sequential: データの長さが可変か?文章は長さがいろいろなのでTrue.ラベルはFalse # tokenize: 文章を読み込んだときに、前処理や単語分割をするための関数を定義 # use_vocab:単語をボキャブラリーに追加するかどうか # lower:アルファベットがあったときに小文字に変換するかどうか # include_length: 文章の単語数のデータを保持するか # batch_first:ミニバッチの次元を先頭に用意するかどうか # fix_length:全部の文章を指定した長さと同じになるように、paddingします # init_token, eos_token, pad_token, unk_token:文頭、文末、padding、未知語に対して、どんな単語を与えるかを指定 # フォルダ「data」から各tsvファイルを読み込みます # BERT用で処理するので、10分弱時間がかかります temp_path = preprocessing.reformat_csv_header(path="./data", train_file="train.csv", test_file="test.csv") print("temp path {}".format(temp_path)) print("text {}".format(vars(TEXT))) train_val_ds, test_ds = torchtext.data.TabularDataset.splits( path=temp_path, train='train.csv', test='test.csv', format='csv', fields=[('Text', TEXT), ('toxic', LABEL1), ('severe_toxic', LABEL2), ('obscene', LABEL3), ('threat', LABEL4), ('insult', LABEL5), ('identity_hate', LABEL6)]) # torchtext.data.Datasetのsplit関数で訓練データとvalidationデータを分ける train_ds, val_ds = train_val_ds.split(split_ratio=0.8, random_state=random.seed(2395)) # BERTはBERTが持つ全単語でBertEmbeddingモジュールを作成しているので、ボキャブラリーとしては全単語を使用します # そのため訓練データからボキャブラリーは作成しません vocab_bert, ids_to_tokens_bert = load_vocab( vocab_file="./weights/bert-base-uncased-vocab.txt") # このまま、TEXT.vocab.stoi= vocab_bert (stoiはstring_to_IDで、単語からIDへの辞書)としたいですが、 # 一度bulild_vocabを実行しないとTEXTオブジェクトがvocabのメンバ変数をもってくれないです。 # ('Field' object has no attribute 'vocab' というエラーをはきます) # 1度適当にbuild_vocabでボキャブラリーを作成してから、BERTのボキャブラリーを上書きします TEXT.build_vocab(train_ds, min_freq=1) TEXT.vocab.stoi = vocab_bert # DataLoaderを作成します(torchtextの文脈では単純にiteraterと呼ばれています) batch_size = 16 # BERTでは16、32あたりを使用する train_dl = torchtext.data.Iterator(train_ds, batch_size=batch_size, train=True) val_dl = torchtext.data.Iterator(val_ds, batch_size=batch_size, train=False, sort=False) test_dl = torchtext.data.Iterator(test_ds, batch_size=batch_size, train=False, sort=False) # 辞書オブジェクトにまとめる dataloaders_dict = {"train": train_dl, "val": val_dl} print(vars(train_ds[0])) print(vars(test_ds[0])) # モデル設定のJOSNファイルをオブジェクト変数として読み込みます config = get_config(file_path="./weights/bert_config.json") # BERTモデルを作成します net_bert = BertModel(config) # BERTモデルに学習済みパラメータセットします net_bert = set_learned_params(net_bert, weights_path="./weights/pytorch_model.bin") for label in [ 'toxic', 'severe_toxic', 'obscene', 'threat', 'insult', 'identity_hate' ]: # モデル構築 net = BertTraining(net_bert) # 訓練モードに設定 net.train() print('done setup network') # 勾配計算を最後のBertLayerモジュールと追加した分類アダプターのみ実行 # 1. まず全部を、勾配計算Falseにしてしまう for name, param in net.named_parameters(): param.requires_grad = False # 2. 最後のBertLayerモジュールを勾配計算ありに変更 for name, param in net.bert.encoder.layer[-1].named_parameters(): param.requires_grad = True # 3. 識別器を勾配計算ありに変更 for name, param in net.cls.named_parameters(): param.requires_grad = True # 最適化手法の設定 # BERTの元の部分はファインチューニング optimizer = optim.Adam( [{ 'params': net.bert.encoder.layer[-1].parameters(), 'lr': 5e-5 }, { 'params': net.cls.parameters(), 'lr': 5e-5 }], betas=(0.9, 0.999)) # 損失関数の設定 criterion = nn.CrossEntropyLoss() # nn.LogSoftmax()を計算してからnn.NLLLoss(negative log likelihood loss)を計算 device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") # 学習・検証を実行する。1epochに20分ほどかかります num_epochs = 2 net_trained = train_model(net, dataloaders_dict, criterion, optimizer, num_epochs=num_epochs, label=label, device=device) # 学習したネットワークパラメータを保存します save_path = './weights/bert_fine_tuning_weights.pth' torch.save(net_trained.state_dict(), save_path) # テストデータ net_trained.eval() # モデルを検証モードに net_trained.to(device) # GPUが使えるならGPUへ送る predicts = [] for batch in tqdm(test_dl): # testデータのDataLoader # batchはTextとLableの辞書オブジェクト # GPUが使えるならGPUにデータを送る inputs = batch.Text[0].to(device) # 文章 # 順伝搬(forward)計算 with torch.set_grad_enabled(False): # BertForIMDbに入力 outputs = net_trained(inputs, token_type_ids=None, attention_mask=None, output_all_encoded_layers=False, attention_show_flg=False) _, preds = torch.max(outputs, 1) # ラベルを予測 preds = preds.cpu() preds = preds.numpy().tolist() predicts += preds sample[label] = predicts # save predictions if not os.path.exists("./submission"): os.mkdir("./submission") sample.to_csv("./submission/submission_Bert_{}_{}ep.csv".format( datetime.datetime.now().date(), num_epochs), index=False)