KOBERT 및 라이브러리 불러오기

pip install 'git+https://github.com/SKTBrain/KoBERT.git#egg=kobert_tokenizer&subdirectory=kobert_hf'
!pip install git+https://git@github.com/SKTBrain/KoBERT.git@master
!pip install sentencepiece==0.1.91
import transformers
transformers.__version__
import pandas as pd
import numpy as np
import urllib.request
import os
from tqdm import tqdm
import tensorflow as tf
from transformers import BertTokenizer, TFBertModel

from torch.utils.data import TensorDataset,DataLoader

from kobert_tokenizer import KoBERTTokenizer
import torch
import torch.nn as nn
import torch.optim as optim
from transformers import BertModel
from transformers import BertForSequenceClassification
import gluonnlp as nlp

데이터 불러오기

urllib.request.urlretrieve("https://raw.githubusercontent.com/e9t/nsmc/master/ratings_train.txt", filename="ratings_train.txt")
urllib.request.urlretrieve("https://raw.githubusercontent.com/e9t/nsmc/master/ratings_test.txt", filename="ratings_test.txt")

train_data = pd.read_table('ratings_train.txt')
test_data = pd.read_table('ratings_test.txt')

train_data = train_data.dropna(how = 'any')
train_data = train_data.reset_index(drop=True)
print(train_data.isnull().values.any())

test_data = test_data.dropna(how = 'any')
test_data = test_data.reset_index(drop=True)
print(test_data.isnull().values.any())

데이터 전처리

tokenizer = KoBERTTokenizer.from_pretrained("skt/kobert-base-v1")

max_seq_len = 128
def Preprocessing(examples,labels,max_seq_len,tokenizer):

  input_ids = []
  attention_masks = []
  token_type_ids = []
  data_labels = []

  for example, label in tqdm(zip(examples,labels),total=len(examples)):

    encode = tokenizer(example,max_length=max_seq_len,pad_to_max_length=True)
    input_id = encode["input_ids"]
    attention_mask = encode["attention_mask"]
    token_type_id = encode["token_type_ids"]

    assert len(input_id) == max_seq_len
    assert len(attention_mask) == max_seq_len
    assert len(token_type_id) == max_seq_len

    input_ids.append(input_id)
    attention_masks.append(attention_mask)
    token_type_ids.append(token_type_id)
    data_labels.append(label)

  input_ids = torch.tensor(input_ids)
  attention_masks = torch.tensor(attention_masks)
  token_type_ids = torch.tensor(token_type_ids)
  data_labels = torch.tensor(data_labels)

  return (input_ids,attention_masks,token_type_ids),data_labels

train_X,train_y = Preprocessing(train_data["document"],train_data["label"],max_seq_len,tokenizer)
test_X, test_y = Preprocessing(test_data["document"],test_data["label"],max_seq_len,tokenizer)

모델 생성 및 학습

device = xm.xla_device()
bert = BertModel.from_pretrained("skt/kobert-base-v1").to(device)
input_ids_train = train_X[0]
attention_masks_train = train_X[1]
token_type_ids_train = train_X[2]

input_ids_test = test_X[0]
attention_masks_test = test_X[1]
token_type_ids_test = test_X[2]

train_tensor = TensorDataset(input_ids_train,attention_masks_train,token_type_ids_train,train_y)
test_tensor = TensorDataset(input_ids_test,attention_masks_test,token_type_ids_test,test_y)

train_loader = DataLoader(train_tensor,batch_size=128,shuffle=True,drop_last=True)
test_loader = DataLoader(test_tensor,batch_size=128,shuffle=False)

class BERTClassifier(nn.Module):
  def __init__(self,bert,hidden_size = 768,num_classes=1,dropout=None):
    super().__init__()
    self.bert = bert
    self.classifier = nn.Linear(hidden_size,num_classes)
    self.sigmoid = nn.Sigmoid()

    if dropout :
      self.dropout = nn.Dropout(dropout)
    
  def forward(self,input_ids,attention_masks,token_type_ids):
    _,pooler = self.bert(input_ids,attention_masks,token_type_ids,return_dict=False)

    if self.dropout :
      out = self.dropout(pooler)
      out = self.classifier(out)
      out = self.sigmoid(out)
    else :
      out = self.classifier(pooler)
      out = self.sigmoid(out)

    return out

hidden_size = 768
num_classes = 1
model = BERTClassifier(bert,hidden_size,num_classes,dropout = 0.1).to(device)
optimizer = optim.Adam(model.parameters(),lr=5e-5)
criterion = nn.BCELoss()

for epoch in range(2):
  avg_loss = 0

  model.train()

  for batch in train_loader:

    input_id = batch[0].to(device)
    attention_mask = batch[1].to(device)
    token_type_id = batch[2].to(device)
    target = batch[3].to(device)
    target = target.type(torch.FloatTensor)

    logits = model(input_id,attention_mask,token_type_id)

    loss = criterion(logits.cpu().view(-1),target.cpu())

    avg_loss += loss / len(train_loader)
    
    optimizer.zero_grad()
    loss.backward()
    xm.optimizer_step(optimizer,barrier=True)

  print("epoch : {} 일때 loss : {}".format(epoch+1,avg_loss))

평가

def test():
  model.eval()
  corrected = 0

  for batch in test_loader:
    input_id = batch[0].to(device)
    attention_mask = batch[1].to(device)
    token_type_id = batch[2].to(device)
    target = batch[3].to(device)

    logits = model(input_id,attention_mask,token_type_id)
    corrected += ((logits.cpu().view(-1) > 0.5) == target.cpu()).sum()

  print("테스트 정확도 : {:.2f}%".format(corrected / len(test_loader.dataset) * 100))

test()

def sentiment_predict(new_sentence):
  encode = tokenizer(new_sentence,max_length=max_seq_len,pad_to_max_length=True)
  input_id = encode["input_ids"]
  attention_mask = encode["attention_mask"]
  token_type_id = encode["token_type_ids"]

  input_id = torch.tensor(input_id).unsqueeze(0)
  attention_mask = torch.tensor(attention_mask).unsqueeze(0)
  token_type_id = torch.tensor(token_type_id).unsqueeze(0)

  input_id = input_id.to(device)
  attention_mask = attention_mask.to(device)
  token_type_id = token_type_id.to(device)

  logits = model(input_id,attention_mask,token_type_id)
  score = logits.cpu().item()

  if score > 0.5:
    print("{:.2f}% 확률로 긍정 리뷰입니다.\n".format(score * 100))
  else :
    print("{:.2f}% 확률로 부정 리뷰입니다.\n".format((1-score) * 100))

sentiment_predict("이 영화 존잼입니다 대박")

Tags:

Categories:

Updated: