。
自然言語処理モデル(BERT)を利用した日本語の文章分類 〜GoogleColab & Pytorchによるファインチューニングしています。
--> 138 from transformers import BertForSequenceClassification, AdamW, BertConfig
139
140
3 frames
/usr/lib/python3.7/importlib/init.py in import_module(name, package)
125 break
126 level += 1
--> 127 return _bootstrap._gcd_import(name[level:], package, level)
128
129
ModuleNotFoundError: No module named 'transformers.models'
#BERTで二値分類するプログラム(Google Colab用)
##■tensorflowのバージョンを2に指定
%tensorflow_version 2.x
##■transformerをインストール
!pip install transformers
##■pytorchをimportし、GPUが使えれば、実行環境をGPUに変更
import torch
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
##■pandasをimportし、データを読み込むボールドテキスト
import pandas as pd
df = pd.read_csv("sinaq001.csv", delimiter=',', header=None, names=['label', 'sentence'])
print(f'データサイズ: {df.shape}')
df.sample(10)
##■必要なデータを、リスト(sentences, labels, labels2)に格納
sentences = df.sentence.values
labels = df.label.values
sentences = sentences[1:]
labels = labels[1:]
labels2 = []
for l in labels:
l2 = int(l)
labels2.append(l2)
##■形態素解析器(MeCab), 辞書(IPADIC), pythonバインディング(fugashi)のインストール
!apt install aptitude swig
!aptitude install mecab libmecab-dev mecab-ipadic-utf8 git make curl xz-utils file -y
!pip install mecab-python3
!pip install ipadic
!pip install fugashi
##■ 日本語BERT Tokenizerの準備。(モデルは既にライブラリ内に準備されている)
from transformers.tokenization_bert_japanese import BertJapaneseTokenizer
tokenizer = BertJapaneseTokenizer.from_pretrained('cl-tohoku/bert-base-japanese-whole-word-masking')
##■
##■ データを処理する。
##■
input_ids = []
attention_masks = []
inds = []
1文づつ処理
for sent in sentences:
token_words = tokenizer.tokenize(sent)
encoded_dict = tokenizer.encode_plus(
sent,
add_special_tokens = True, # Special Tokenの追加
truncation=True,
max_length = 200, # 文章の長さを固定(Padding/Trancatinating)
pad_to_max_length = True,# PADDINGで埋める
return_attention_mask = True, # Attention maksの作成
return_tensors = 'pt', # Pytorch tensorsで返す
)
# 単語IDを取得 input_ids.append(encoded_dict['input_ids']) # Attention maskの取得 attention_masks.append(encoded_dict['attention_mask'])
リストに入ったtensorを縦方向(dim=0)へ結合
input_ids = torch.cat(input_ids, dim=0)
attention_masks = torch.cat(attention_masks, dim=0)
for i in range(0,len(labels2)):
inds.append(i)
inds = torch.tensor(inds)
tenosor型に変換
print(labels2)
labels = torch.tensor(labels2)
確認
print('Original: ', sentences[0])
print('Token IDs:', input_ids[0])
##■
##■ 学習データ・テストデータ準備。
##■
from torch.utils.data import TensorDataset, random_split
from torch.utils.data import DataLoader, RandomSampler, SequentialSampler
データセットクラスの作成
dataset = TensorDataset(input_ids, attention_masks, labels, inds)
90%地点のIDを取得
train_size = int(0.9 * len(dataset))
val_size = len(dataset) - train_size
データセットを分割
train_dataset, val_dataset = random_split(dataset, [train_size, val_size])
print('訓練データ数:{}'.format(train_size))
print('検証データ数: {} '.format(val_size))
データローダーの作成
batch_size = 32
訓練データローダー
train_dataloader = DataLoader(
train_dataset,
sampler = RandomSampler(train_dataset), # ランダムにデータを取得してバッチ化
batch_size = batch_size
)
検証データローダー
validation_dataloader = DataLoader(
val_dataset,
sampler = SequentialSampler(val_dataset), # 順番にデータを取得してバッチ化
batch_size = batch_size
)
##■
##■ BERT転移学習(学習済みデータを利用し、分類モデルを構築)
##■
##■ 準備
#!pip install transformers==3.5.1
from transformers import BertForSequenceClassification, AdamW, BertConfig
BertForSequenceClassification 学習済みモデルのロード
model = BertForSequenceClassification.from_pretrained(
'cl-tohoku/bert-base-japanese-whole-word-masking', # 日本語Pre trainedモデルの指定
num_labels = 2, # ラベル数(今回はBinayなので2、数値を増やせばマルチラベルも対応可)
output_attentions = False, # アテンションベクトルを出力するか
output_hidden_states = False, # 隠れ層を出力するか
)
モデルをGPUへ転送
model.cuda()
最適化手法の設定
optimizer = AdamW(model.parameters(), lr=2e-5)
訓練パートの定義
def train(model):
model.train() # 訓練モードで実行
train_loss = 0
for batch in train_dataloader:# train_dataloaderはword_id, mask, labelを出力する点に注意
b_input_ids = batch[0].to(device)
b_input_mask = batch[1].to(device)
b_labels = batch[2].to(device)
optimizer.zero_grad()
loss, logits = model(b_input_ids,
token_type_ids=None,
attention_mask=b_input_mask,
labels=b_labels)
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
optimizer.step()
train_loss += loss.item()
return train_loss
テストパートの定義
def validation(model):
model.eval()# 訓練モードをオフ
val_loss = 0
with torch.no_grad(): # 勾配を計算しない
for batch in validation_dataloader:
b_input_ids = batch[0].to(device)
b_input_mask = batch[1].to(device)
b_labels = batch[2].to(device)
with torch.no_grad():
(loss, logits) = model(b_input_ids,
token_type_ids=None,
attention_mask=b_input_mask,
labels=b_labels)
val_loss += loss.item()
return val_loss
##■ 学習の実行
max_epoch = 4
train_loss_ = []
test_loss_ = []
for epoch in range(max_epoch):
train_ = train(model)
test_ = train(model)
train_loss_.append(train_)
test_loss_.append(test_)
##■ テストデータを分類して結果を表示
import numpy as np
model.eval()# 訓練モードをオフ
for batch in validation_dataloader:
print("one batch")
b_input_ids = batch[0].to(device)
b_input_mask = batch[1].to(device)
b_labels = batch[2].to(device)
b_inds = batch[3].to(device)
a=[]
for id in batch[3]:
sent = sentences[id]
if len(sent)>20:
sent = sent[:20]
a.append(sent)#sentences[id])
#a2 = torch.tensor(a)
#b_sents = a.to(device)
with torch.no_grad():
# 学習済みモデルによる予測結果をpredsで取得
preds = model(b_input_ids,
token_type_ids=None,
attention_mask=b_input_mask)
logits_df = pd.DataFrame(preds[0].cpu().numpy(), columns=['logit_0', 'logit_1']) ## np.argmaxで大き方の値を取得 pred_df = pd.DataFrame(np.argmax(preds[0].cpu().numpy(), axis=1), columns=['pred_label']) label_df = pd.DataFrame(b_labels.cpu().numpy(), columns=['true_label']) source_df = pd.DataFrame(b_inds.cpu().numpy(), columns=['source_id']) sents_df = pd.DataFrame(a, columns=['source_sent']) accuracy_df = pd.concat([logits_df, pred_df, label_df, source_df, sents_df], axis=1) print(accuracy_df)