Natural Language Processing with Disaster Tweets
Predict which Tweets are about real disasters and which ones are not
https://www.kaggle.com/c/nlp-getting-started
Natural Language Processing with Disaster Tweets | Kaggle
www.kaggle.com
NLP ๊ณต๋ถ๋ฅผ ํ๋ฉด์ ์ด๊ธฐ ๋ ผ๋ฌธ๋ถํฐ ํ๋์ฉ ๋ณด๋ฉด์ ์์ฑํด๋ณด๊ณ , ์ต์ ํธ๋ ๋๋ฅผ ๊ณต๋ถํด๊ฐ๋ฉด์,
์ง์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ถํฐ ๋ชจ๋ธ์ ๋๋ ค๋ณด๊ณ , ์์ฐ์ด๋ฅผ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ๋์ง ๊ณผ์ ์ ์ง์ ๊ฒฝํํด ๋ณด๊ณ ์ถ์๋ค.
์ฆ, NLP ๋ชจ๋ธ์ ๋๋ฆฌ๊ธฐ ์ํ ์ง์ ์ฝ๋ฉ์ ํ๊ณ ์ถ์๋ค.
๊ธฐ์กด์ BERT Model์ ๊ณต๋ถํ๋ฉด์ ์ธํฐ๋ท์ ์๋ ์์ ๋ก ๋ค์ด๋ฒ ๋ฆฌ๋ทฐ ๊ฐ์ฑ๋ถ๋ฅ๋ฅผ ํด๋ณด์์๋๋ฐ,
๋ค๋ฅธ ๋ฌธ์ ๋ฅผ ์ง์ ํ์ด๋ณด๊ณ ์ถ์ด์ Kaggle์ ๋ค์ ๊ฑฐ๋ฆฌ๋ค๊ฐ ์์ฐ์ด์ฒ๋ฆฌ์ ํ์ดํ๋ ๊ฐ์ NLP ๊ณต๋ถ ๋ํ๊ฐ ์์๋ค.

์ด๋ฅผ ๊ธฐ์กด์ ์์ฑํ๋ ์ฝ๋๋ค์ ์์ฉํด์ ์ง์ ๋ํ์ ์ฐธ๊ฐํ์ฌ ์ฝ๋ฉ์ ํด๋ณด์๋ค.
์ด ๋ํ๋ ํธ์ํฐ์ ์ฌ๋ ํธ์์ ๋ถ๋ฅํ๋ ๋ํ์ธ๋ฐ, ํธ์์ ๋ณด๊ณ ์ค์ ๋ก ์ฌ๋์ํฉ์ธ์ง, ๊ฑฐ์ง ์ฌ๋์ํฉ์ธ์ง ๊ตฌ๋ถํ์ฌ ๋ผ๋ฒจ๋งํ๋ Getting Started competitions์ด๋ค.

Train ๋ฐ์ดํฐ์ ์ ์ด๋ฌํ ํ์์ CSV ํ์ผ์ด๋ค.
import pandas as pd
import torch
from torch.utils.data import Dataset, DataLoader
from pytorch_transformers import BertTokenizer, BertForSequenceClassification
from torch.optim import Adam
import torch.nn.functional as F
train_data = pd.read_csv('train.csv')
test_data = pd.read_csv('test.csv')
train_data.head() # 7,613 Rows 5 Columns
train_df = train_data.dropna()
test_df = test_data.dropna()
train_df.shape #5,080 Rows 5 Columns
ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ถ๋ฌ์ค๊ณ ๋ฐ์ดํฐ์ ํ์ผ์ ๋ถ์ํด๋ณด๋ 7,613๊ฐ์ Rows๊ฐ ์์๋ค.
๊ทธ๋ฆฌ ๋ง์ง์์ ๋ฐ์ดํฐ์ด๊ธฐ์ NLP ๊ณต๋ถ๋ฅผ ํ๋ฉด์ ๋ชจ๋ธ์ ๋๋ ค๋ณด๊ธฐ์ ์ข์ ๋ฐ์ดํฐ ๊ฐ์๋ค.
๊ทธ๋ฌ๋ ๋ค๋ฅธ ํ ์ผ๋ค๋ ์๊ณ ์ด ๋ํ์ ๋ง์ ์๊ฐ์ ํฌ์ํ ์ ์๋ ์ํฉ์ด๋ฉฐ, ๊ทธ๋ ๊ธฐ์ ์งง์ ์๊ฐ์ ํ๊ธฐ ์ํด ๊ฐ๋จํ ์ ์ฒ๋ฆฌ๋ฅผ ์งํํด ์ฃผ์๋ค.
์ผ๋จ, ๊ฒฐ์ธก์น๋ฅผ ์ ๋ถ ์ ๊ฑฐํ์๋ค.
๊ฒฐ์ธก์น๋ฅผ ๋์ฒดํ๊ณ ์ด ๋ฐ์ดํฐ๋ฅผ ๋ถ์ํ๊ธฐ์๋ ์๊ฐ์ด ์์๋ฐ..
๊ทธ๋ฌ๋๋ 7,613 -> 5,080์ผ๋ก ๋ฐ์ดํฐ๊ฐ ์ค์๋ค. 5000๊ฐ์ ๋ฐ์ดํฐ๋ก ์ ๋ ๋ ค๋ ๊ฑฑ์ ํ์๋ค.
class load_dataset(Dataset) :
def __init__(self, df):
self.df = df
def __len__(self):
return len(self.df)
def __getitem__(self, item):
text = self.df.iloc[item, 3]
label = self.df.iloc[item,4]
return text, label
๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ๊ฐ๋จํ๊ฒ classํ๋๋ฅผ ์ ์ํ์ฌ text์ label์ด return ๋๋๋ก ๋ง๋ค์๋ค.
train_dataset = load_dataset(train_df)
train_loader = DataLoader(train_dataset, shuffle=True)
๊ทธ๋ฌ๊ณ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด์ keywords, location, Id Column ๊ฐ๋ค์ ์ ๋ถ ์ ๊ฑฐํ๊ณ ๊ฐ๋จํ๊ฒ Text, Label ๊ฐ๋ง ๋ฝ์๋ค.
device = torch.device("cuda")
tokenizer = BertTokenizer.from_pretrained('bert-base-multilingual-cased')
model = BertForSequenceClassification.from_pretrained('bert-base-multilingual-cased')
model.to(device)
optimizer = Adam(model.parameters(), lr=1e-6)
""" ๋ชจ๋ธ ํ์ต """
model.train()
๊ทธ๋ฌ๊ณ ๋ชจ๋ธ์ ๋๋ฆฌ๊ธฐ ์ํด pretrained ๋ Bert์ Classification ๋ชจ๋ธ์ ๋ถ๋ฌ์์ ์ด๋ฅผ CUDA์ ์ฌ๋ฆฌ๊ณ ์ค๋น๋ฅผ ํ์๋ค.
total_corrct = 0
total_len = 0
total_loss = 0
count = 0
for epoch in range(1) :
for text, label in train_loader:
optimizer.zero_grad()
#ํ ๋ฌธ์ฅ์์ ๋จ์ด์ฉ
#<CLS>, <SEP> ๋ฑ์ special token์ ์ถ๊ฐ
encoding_list = [tokenizer.encode(x, add_special_tokens=True) for x in text]
padding_list = [x + [0]*(256-len(x)) for x in encoding_list]
sample = torch.tensor(padding_list)
sample = sample.to(device)
#label = torch.tensor(label)
label = label.to(device)
outputs = model(sample, labels=label)
loss, logits = outputs
print(logits)
predict = torch.argmax(F.softmax(logits), dim=1)
print(predict)
corrct = predict.eq(label)
total_corrct += corrct.sum()
total_len += len(label)
total_loss += loss
loss.backward()
optimizer.step()
break
if count % 1000 ==0 :
print(f'Epoch : {epoch+1}, Iteration : {count}')
print(f'Train Loss : {total_loss/1000}')
print(f'Accuracy : {total_corrct/total_len}\n')
count +=1
model.eval()
๊ทธ๋ฌ๊ณ ์ด๋ ๊ฒ ๋๋ ค์ ๋ํ๋ฅผ ์ํ BERT ๋ชจ๋ธ์ ๋ง๋ค๊ณ , ์ฑ๋ฅ์ ํ๊ฐํ๊ณ ์ด ๋ชจ๋ธ์ ์ ์ฅํ์ฌ ์ฌ์ฉํ์๋ค.
์ํฌํฌ๋ฅผ ์ฌ๋ฌ๋ฒ ๋๋ฆด๊ฑธ ๊ทธ๋ฌ๋ ์ผ๋จ ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ๋ ๊ฐ๋จํ๊ฒ ํ์ผ๋ ์ํฌํฌ๋ ํ๋ฒ๋ง ๋๋ ธ๋ค.
์๋ง Accuracy๊ฐ 80% ์ด์์ผ๋ก ๋์๋๊ฑฐ ๊ฐ๋ค.
๊ทธ๋์ ๋ง์กฑํด์ ๋ฐ๋ก ๋๋ด๊ณ Predict๋ก ๋์ด๊ฐ๋ค.
(์๊ฐ์ ๋ง์ด ํฌ์ํ ์ฌ์ ๊ฐ ์์๊ธฐ์..)
""" Predict.py """
import pandas as pd
import torch
from torch.utils.data import DataLoader
from pytorch_transformers import BertTokenizer
import csv
import re
test_data = pd.read_csv('test.csv')
test_df = test_data.fillna("null")
model = torch.load('predict_of_tweet_model.pth')
๋๊ฐ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ก๋ํ๊ณ , test ๋ฐ์ดํฐ์ ๊ณผ ๋ชจ๋ธ์ ๋ถ๋ฌ์ค๊ณ , ๊ฐ๋จํ๊ฒ ๊ฒฐ์ธก์น๋ฅผ "null"๋ก ๋์ฒดํด์คฌ๋ค.
model.to(torch.device('cpu'))
tokenizer = BertTokenizer.from_pretrained('bert-base-multilingual-cased')
test_dataset = test_df["text"] #2,158 Rows
processing_test_dataset = test_dataset.reset_index()["text"]
processing_test_dataset = DataLoader(processing_test_dataset)
test ๋ฐ์ดํฐ์ ์๋ 2,158๊ฐ์ Rows๊ฐ ์์๋ค.
๊ทผ๋ฐ ์ด์ํ๊ฒ ์ฌ๊ธฐ์๋ CUDA๊ฐ ๋ฉ๋ชจ๋ฆฌ ์ด๊ณผ๊ฐ ๊ณ์๋ ์ ๋ฐฉ๋ฒ์ฐพ๋ค๊ฐ ๊ทธ๋ฅ CPU๋ก ๋๋ ค์คฌ๋ค.
id๋ 0๋ถํฐ ์๋๊ฒ ์๋ ๋จ๋ฌธ๋จ๋ฌธ ์์ด์ ์ธ๋ฑ์ค ์ด๊ธฐํํด์ฃผ๊ณ ๋ถ๋ฌ์๋ค.
final = []
for text in processing_test_dataset:
encoding_list = [tokenizer.encode(x, add_special_tokens=True) for x in text]
padding_list = [x + [0]*(256-len(x)) for x in encoding_list]
sample = torch.tensor(padding_list)
sample = sample.to(torch.device('cpu'))
outputs = model(sample)
predict = torch.argmax(outputs[0],dim=1)
print(f'predict -> {predict}')
final.append(predict.int())
์ด๋ฌ๊ณ ์ด์ ๋ชจ๋ธ ํ์ตํ ๋์ ๊ฐ์ด ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ์ ์ด๋ฅผ ๋ชจ๋ธ์ ๋ฃ๊ณ Predict๋ฅผ ์งํํ์๋ค.
์ด๋ ๊ฒ ๋์จ predict ๊ฐ๋ค์ list๋ก appendํด์ ์ ์ฅํด ์ฃผ์๋๋ฐ,
0๊ณผ 1๋ก ๋์ค๋๊ฒ์๋
"Tensor[1], dtype=uint32" ๋ญ ์ด๋ฐ์์ผ๋ก ๋์ด ๋์ค๊ธฐ์ ๋ํ๋ฒ ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ์๋ค.
re_pattern = re.compile(r'\d')
temp = final
target_list = list()
for x in temp :
temp = re.findall(re_pattern, str(x))
target_list.append(temp[0])
์๋ค๋ค์ ์ฒ๋ฆฌํ๋ ค๊ณ ์ ๊ท์์ ๋ฃ์ด์ ์ซ์๋ง ๋ฝ์์ฃผ๋ฉด [์์ธกํ์ผ๊ฐ(0 or 1), 3, 2] ์ด๋ฐ์์ผ๋ก ๋์จ๋ค. ๋ค์ ๋ฐ์ดํฐํ์ ์ ๋ถ๋ ์ซ์๊น์ง ๋ฐ๋ผ ๋์ค๊ธฐ์ ๊ทธ์ค ์ฒซ๋ฒ์งธ ์ซ์๋ง ๋ฝ์์ ์๋ก์ด ๋ฆฌ์คํธ์ ์ ์ฅํด์ฃผ์๋ค.
์ด๋ ๊ฒ๋๋ฉด list์๋ [1,1,0,0,0,0,0,1,0,1,0,1,...] ์ด๋ฐ์์ผ๋ก ์์ธก๊ฐ๋ค์ด ๋์ค๊ฒ ๋๋ค.
with open('predict.csv', 'w', newline='') as f :
writer = csv.writer(f)
writer.writerow(target_list)
data_id = pd.DataFrame(test_data['id'])
data_target = pd.DataFrame(target_list)
result = pd.concat([data_id, data_target], axis=1)
result.to_csv("result.csv")
๊ทธ๋ฌ๋ฉด ์ด ๋์จ ๊ฐ๊ณผ ๊ธฐ์กด์ test ๋ฐ์ดํฐ์ ์ ์๋ id์ ํฉ์ณ์ฃผ๋ฉด ์ต์ข ์ ์ถ ํ์ผ์ด ๋ง๋ค์ด์ง๋ค.

์ด์ ์ด ํ์ผ์ Kaggle์ ๋ณด๋ด์ ์ ์๋ฅผ ํ์ธํด ๋ณด์๋ค.

81์ ์ด ๋์๋ค.
์ด ์ ์๋ 81.428% ๋ง์ถ์๋ค๋ ๊ฒ ๊ฐ๋ค.
๋ฐ์ดํฐ ์ฒ๋ฆฌ ์์ฒญ ๊ฐ๋จํ๊ฒ ํ๋๋ฐ๋ ์๊ฐ๋ณด๋ค ๋์ ์ ์๊ฐ ๋์๋ค.
์ฌ๊ธฐ์ BERT ๋ชจ๋ธ์ ์ด๋ง๋ฌด์ํ ์ฑ๋ฅ์ ๋๋์๊ฐ ์์๋ค..
์ด๋ ๊ฒ ํด์ NLP ๋ํ๋ฅผ ํ๋ฒ ์ฐธ๊ฐํด ๋ณด์๋๋ฐ, ๊ทธ์ ๊น์ง๋งํด๋ NLP ์ด๋ ต๊ณ ์ฌ๋ฏธ์๊ฒ ๋๊ปด์ก๋๋ฐ ๋ง์ ์ง์ ํ์ด๋ณด๋ ๋น์ ๊ณผ ํฌ๊ฒ ๋ค๋ฅผ๊ฒ ์๋ค๊ณ ๋๊ปด์ก๋ค. ๋ ๊ณต๋ถํ๊ณ ๋ ํ๋ด์ผ๊ฒ ๋ค.
Natural Language Processing with Disaster Tweets
Predict which Tweets are about real disasters and which ones are not
https://www.kaggle.com/c/nlp-getting-started
Natural Language Processing with Disaster Tweets | Kaggle
www.kaggle.com
NLP ๊ณต๋ถ๋ฅผ ํ๋ฉด์ ์ด๊ธฐ ๋ ผ๋ฌธ๋ถํฐ ํ๋์ฉ ๋ณด๋ฉด์ ์์ฑํด๋ณด๊ณ , ์ต์ ํธ๋ ๋๋ฅผ ๊ณต๋ถํด๊ฐ๋ฉด์,
์ง์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ถํฐ ๋ชจ๋ธ์ ๋๋ ค๋ณด๊ณ , ์์ฐ์ด๋ฅผ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ๋์ง ๊ณผ์ ์ ์ง์ ๊ฒฝํํด ๋ณด๊ณ ์ถ์๋ค.
์ฆ, NLP ๋ชจ๋ธ์ ๋๋ฆฌ๊ธฐ ์ํ ์ง์ ์ฝ๋ฉ์ ํ๊ณ ์ถ์๋ค.
๊ธฐ์กด์ BERT Model์ ๊ณต๋ถํ๋ฉด์ ์ธํฐ๋ท์ ์๋ ์์ ๋ก ๋ค์ด๋ฒ ๋ฆฌ๋ทฐ ๊ฐ์ฑ๋ถ๋ฅ๋ฅผ ํด๋ณด์์๋๋ฐ,
๋ค๋ฅธ ๋ฌธ์ ๋ฅผ ์ง์ ํ์ด๋ณด๊ณ ์ถ์ด์ Kaggle์ ๋ค์ ๊ฑฐ๋ฆฌ๋ค๊ฐ ์์ฐ์ด์ฒ๋ฆฌ์ ํ์ดํ๋ ๊ฐ์ NLP ๊ณต๋ถ ๋ํ๊ฐ ์์๋ค.

์ด๋ฅผ ๊ธฐ์กด์ ์์ฑํ๋ ์ฝ๋๋ค์ ์์ฉํด์ ์ง์ ๋ํ์ ์ฐธ๊ฐํ์ฌ ์ฝ๋ฉ์ ํด๋ณด์๋ค.
์ด ๋ํ๋ ํธ์ํฐ์ ์ฌ๋ ํธ์์ ๋ถ๋ฅํ๋ ๋ํ์ธ๋ฐ, ํธ์์ ๋ณด๊ณ ์ค์ ๋ก ์ฌ๋์ํฉ์ธ์ง, ๊ฑฐ์ง ์ฌ๋์ํฉ์ธ์ง ๊ตฌ๋ถํ์ฌ ๋ผ๋ฒจ๋งํ๋ Getting Started competitions์ด๋ค.

Train ๋ฐ์ดํฐ์ ์ ์ด๋ฌํ ํ์์ CSV ํ์ผ์ด๋ค.
import pandas as pd
import torch
from torch.utils.data import Dataset, DataLoader
from pytorch_transformers import BertTokenizer, BertForSequenceClassification
from torch.optim import Adam
import torch.nn.functional as F
train_data = pd.read_csv('train.csv')
test_data = pd.read_csv('test.csv')
train_data.head() # 7,613 Rows 5 Columns
train_df = train_data.dropna()
test_df = test_data.dropna()
train_df.shape #5,080 Rows 5 Columns
ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ถ๋ฌ์ค๊ณ ๋ฐ์ดํฐ์ ํ์ผ์ ๋ถ์ํด๋ณด๋ 7,613๊ฐ์ Rows๊ฐ ์์๋ค.
๊ทธ๋ฆฌ ๋ง์ง์์ ๋ฐ์ดํฐ์ด๊ธฐ์ NLP ๊ณต๋ถ๋ฅผ ํ๋ฉด์ ๋ชจ๋ธ์ ๋๋ ค๋ณด๊ธฐ์ ์ข์ ๋ฐ์ดํฐ ๊ฐ์๋ค.
๊ทธ๋ฌ๋ ๋ค๋ฅธ ํ ์ผ๋ค๋ ์๊ณ ์ด ๋ํ์ ๋ง์ ์๊ฐ์ ํฌ์ํ ์ ์๋ ์ํฉ์ด๋ฉฐ, ๊ทธ๋ ๊ธฐ์ ์งง์ ์๊ฐ์ ํ๊ธฐ ์ํด ๊ฐ๋จํ ์ ์ฒ๋ฆฌ๋ฅผ ์งํํด ์ฃผ์๋ค.
์ผ๋จ, ๊ฒฐ์ธก์น๋ฅผ ์ ๋ถ ์ ๊ฑฐํ์๋ค.
๊ฒฐ์ธก์น๋ฅผ ๋์ฒดํ๊ณ ์ด ๋ฐ์ดํฐ๋ฅผ ๋ถ์ํ๊ธฐ์๋ ์๊ฐ์ด ์์๋ฐ..
๊ทธ๋ฌ๋๋ 7,613 -> 5,080์ผ๋ก ๋ฐ์ดํฐ๊ฐ ์ค์๋ค. 5000๊ฐ์ ๋ฐ์ดํฐ๋ก ์ ๋ ๋ ค๋ ๊ฑฑ์ ํ์๋ค.
class load_dataset(Dataset) :
def __init__(self, df):
self.df = df
def __len__(self):
return len(self.df)
def __getitem__(self, item):
text = self.df.iloc[item, 3]
label = self.df.iloc[item,4]
return text, label
๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ๊ฐ๋จํ๊ฒ classํ๋๋ฅผ ์ ์ํ์ฌ text์ label์ด return ๋๋๋ก ๋ง๋ค์๋ค.
train_dataset = load_dataset(train_df)
train_loader = DataLoader(train_dataset, shuffle=True)
๊ทธ๋ฌ๊ณ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด์ keywords, location, Id Column ๊ฐ๋ค์ ์ ๋ถ ์ ๊ฑฐํ๊ณ ๊ฐ๋จํ๊ฒ Text, Label ๊ฐ๋ง ๋ฝ์๋ค.
device = torch.device("cuda")
tokenizer = BertTokenizer.from_pretrained('bert-base-multilingual-cased')
model = BertForSequenceClassification.from_pretrained('bert-base-multilingual-cased')
model.to(device)
optimizer = Adam(model.parameters(), lr=1e-6)
""" ๋ชจ๋ธ ํ์ต """
model.train()
๊ทธ๋ฌ๊ณ ๋ชจ๋ธ์ ๋๋ฆฌ๊ธฐ ์ํด pretrained ๋ Bert์ Classification ๋ชจ๋ธ์ ๋ถ๋ฌ์์ ์ด๋ฅผ CUDA์ ์ฌ๋ฆฌ๊ณ ์ค๋น๋ฅผ ํ์๋ค.
total_corrct = 0
total_len = 0
total_loss = 0
count = 0
for epoch in range(1) :
for text, label in train_loader:
optimizer.zero_grad()
#ํ ๋ฌธ์ฅ์์ ๋จ์ด์ฉ
#<CLS>, <SEP> ๋ฑ์ special token์ ์ถ๊ฐ
encoding_list = [tokenizer.encode(x, add_special_tokens=True) for x in text]
padding_list = [x + [0]*(256-len(x)) for x in encoding_list]
sample = torch.tensor(padding_list)
sample = sample.to(device)
#label = torch.tensor(label)
label = label.to(device)
outputs = model(sample, labels=label)
loss, logits = outputs
print(logits)
predict = torch.argmax(F.softmax(logits), dim=1)
print(predict)
corrct = predict.eq(label)
total_corrct += corrct.sum()
total_len += len(label)
total_loss += loss
loss.backward()
optimizer.step()
break
if count % 1000 ==0 :
print(f'Epoch : {epoch+1}, Iteration : {count}')
print(f'Train Loss : {total_loss/1000}')
print(f'Accuracy : {total_corrct/total_len}\n')
count +=1
model.eval()
๊ทธ๋ฌ๊ณ ์ด๋ ๊ฒ ๋๋ ค์ ๋ํ๋ฅผ ์ํ BERT ๋ชจ๋ธ์ ๋ง๋ค๊ณ , ์ฑ๋ฅ์ ํ๊ฐํ๊ณ ์ด ๋ชจ๋ธ์ ์ ์ฅํ์ฌ ์ฌ์ฉํ์๋ค.
์ํฌํฌ๋ฅผ ์ฌ๋ฌ๋ฒ ๋๋ฆด๊ฑธ ๊ทธ๋ฌ๋ ์ผ๋จ ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ๋ ๊ฐ๋จํ๊ฒ ํ์ผ๋ ์ํฌํฌ๋ ํ๋ฒ๋ง ๋๋ ธ๋ค.
์๋ง Accuracy๊ฐ 80% ์ด์์ผ๋ก ๋์๋๊ฑฐ ๊ฐ๋ค.
๊ทธ๋์ ๋ง์กฑํด์ ๋ฐ๋ก ๋๋ด๊ณ Predict๋ก ๋์ด๊ฐ๋ค.
(์๊ฐ์ ๋ง์ด ํฌ์ํ ์ฌ์ ๊ฐ ์์๊ธฐ์..)
""" Predict.py """
import pandas as pd
import torch
from torch.utils.data import DataLoader
from pytorch_transformers import BertTokenizer
import csv
import re
test_data = pd.read_csv('test.csv')
test_df = test_data.fillna("null")
model = torch.load('predict_of_tweet_model.pth')
๋๊ฐ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ก๋ํ๊ณ , test ๋ฐ์ดํฐ์ ๊ณผ ๋ชจ๋ธ์ ๋ถ๋ฌ์ค๊ณ , ๊ฐ๋จํ๊ฒ ๊ฒฐ์ธก์น๋ฅผ "null"๋ก ๋์ฒดํด์คฌ๋ค.
model.to(torch.device('cpu'))
tokenizer = BertTokenizer.from_pretrained('bert-base-multilingual-cased')
test_dataset = test_df["text"] #2,158 Rows
processing_test_dataset = test_dataset.reset_index()["text"]
processing_test_dataset = DataLoader(processing_test_dataset)
test ๋ฐ์ดํฐ์ ์๋ 2,158๊ฐ์ Rows๊ฐ ์์๋ค.
๊ทผ๋ฐ ์ด์ํ๊ฒ ์ฌ๊ธฐ์๋ CUDA๊ฐ ๋ฉ๋ชจ๋ฆฌ ์ด๊ณผ๊ฐ ๊ณ์๋ ์ ๋ฐฉ๋ฒ์ฐพ๋ค๊ฐ ๊ทธ๋ฅ CPU๋ก ๋๋ ค์คฌ๋ค.
id๋ 0๋ถํฐ ์๋๊ฒ ์๋ ๋จ๋ฌธ๋จ๋ฌธ ์์ด์ ์ธ๋ฑ์ค ์ด๊ธฐํํด์ฃผ๊ณ ๋ถ๋ฌ์๋ค.
final = []
for text in processing_test_dataset:
encoding_list = [tokenizer.encode(x, add_special_tokens=True) for x in text]
padding_list = [x + [0]*(256-len(x)) for x in encoding_list]
sample = torch.tensor(padding_list)
sample = sample.to(torch.device('cpu'))
outputs = model(sample)
predict = torch.argmax(outputs[0],dim=1)
print(f'predict -> {predict}')
final.append(predict.int())
์ด๋ฌ๊ณ ์ด์ ๋ชจ๋ธ ํ์ตํ ๋์ ๊ฐ์ด ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ์ ์ด๋ฅผ ๋ชจ๋ธ์ ๋ฃ๊ณ Predict๋ฅผ ์งํํ์๋ค.
์ด๋ ๊ฒ ๋์จ predict ๊ฐ๋ค์ list๋ก appendํด์ ์ ์ฅํด ์ฃผ์๋๋ฐ,
0๊ณผ 1๋ก ๋์ค๋๊ฒ์๋
"Tensor[1], dtype=uint32" ๋ญ ์ด๋ฐ์์ผ๋ก ๋์ด ๋์ค๊ธฐ์ ๋ํ๋ฒ ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ์๋ค.
re_pattern = re.compile(r'\d')
temp = final
target_list = list()
for x in temp :
temp = re.findall(re_pattern, str(x))
target_list.append(temp[0])
์๋ค๋ค์ ์ฒ๋ฆฌํ๋ ค๊ณ ์ ๊ท์์ ๋ฃ์ด์ ์ซ์๋ง ๋ฝ์์ฃผ๋ฉด [์์ธกํ์ผ๊ฐ(0 or 1), 3, 2] ์ด๋ฐ์์ผ๋ก ๋์จ๋ค. ๋ค์ ๋ฐ์ดํฐํ์ ์ ๋ถ๋ ์ซ์๊น์ง ๋ฐ๋ผ ๋์ค๊ธฐ์ ๊ทธ์ค ์ฒซ๋ฒ์งธ ์ซ์๋ง ๋ฝ์์ ์๋ก์ด ๋ฆฌ์คํธ์ ์ ์ฅํด์ฃผ์๋ค.
์ด๋ ๊ฒ๋๋ฉด list์๋ [1,1,0,0,0,0,0,1,0,1,0,1,...] ์ด๋ฐ์์ผ๋ก ์์ธก๊ฐ๋ค์ด ๋์ค๊ฒ ๋๋ค.
with open('predict.csv', 'w', newline='') as f :
writer = csv.writer(f)
writer.writerow(target_list)
data_id = pd.DataFrame(test_data['id'])
data_target = pd.DataFrame(target_list)
result = pd.concat([data_id, data_target], axis=1)
result.to_csv("result.csv")
๊ทธ๋ฌ๋ฉด ์ด ๋์จ ๊ฐ๊ณผ ๊ธฐ์กด์ test ๋ฐ์ดํฐ์ ์ ์๋ id์ ํฉ์ณ์ฃผ๋ฉด ์ต์ข ์ ์ถ ํ์ผ์ด ๋ง๋ค์ด์ง๋ค.

์ด์ ์ด ํ์ผ์ Kaggle์ ๋ณด๋ด์ ์ ์๋ฅผ ํ์ธํด ๋ณด์๋ค.

81์ ์ด ๋์๋ค.
์ด ์ ์๋ 81.428% ๋ง์ถ์๋ค๋ ๊ฒ ๊ฐ๋ค.
๋ฐ์ดํฐ ์ฒ๋ฆฌ ์์ฒญ ๊ฐ๋จํ๊ฒ ํ๋๋ฐ๋ ์๊ฐ๋ณด๋ค ๋์ ์ ์๊ฐ ๋์๋ค.
์ฌ๊ธฐ์ BERT ๋ชจ๋ธ์ ์ด๋ง๋ฌด์ํ ์ฑ๋ฅ์ ๋๋์๊ฐ ์์๋ค..
์ด๋ ๊ฒ ํด์ NLP ๋ํ๋ฅผ ํ๋ฒ ์ฐธ๊ฐํด ๋ณด์๋๋ฐ, ๊ทธ์ ๊น์ง๋งํด๋ NLP ์ด๋ ต๊ณ ์ฌ๋ฏธ์๊ฒ ๋๊ปด์ก๋๋ฐ ๋ง์ ์ง์ ํ์ด๋ณด๋ ๋น์ ๊ณผ ํฌ๊ฒ ๋ค๋ฅผ๊ฒ ์๋ค๊ณ ๋๊ปด์ก๋ค. ๋ ๊ณต๋ถํ๊ณ ๋ ํ๋ด์ผ๊ฒ ๋ค.