본문 바로가기
AI SCHOOL/TIL

[DAY 64] 뉴스 토픽 분류 - KoNLpy, 어간 추출, 불용어 제거, TfidfVectorizer

2023. 3. 28.

데이콘 뉴스 토픽 분류 AI 경진대회를 통해 자연어 처리를 경험했다.

어간추출, 조사, 어미, 구두점 제거 및 불용어 제거 후 TfidfVectorizer를 이용해 벡터화하여 학습 및 예측을 했다.

데이터 로드

train = pd.read_csv("train_data.csv")
test = pd.read_csv("test_data.csv")

train은 45654행 3열, test는 9131행 2열의 데이터다.

traintest

뉴스 제목과 토픽 인덱스를 학습시킨 후, 뉴스 제목을 통해 토픽을 예측하는 경진대회다.

topic
topic

총 7개의 토픽으로 분류되어 있다.

텍스트 전처리

정규표현식을 사용하여 한글, 영문, 숫자가 아닌 경우 공백으로 대체했다. 그 결과 특수문자와 한자가 제거되었다.

화살표, 점, 美 등이 제거된 것을 확인할 수 있다.

어간 추출
konlpy의 Okt를 통해 품사 태깅을 할 수 있다.
from konlpy.tag import Okt가 선행된다.

okt_pos = okt.pos('버스의 운행시간을 문의한다. 어?!', norm=True, stem=True)
okt_pos

위 문장을 어간 추출한 결과를 아래와 같다.

djrks

동사, 명사, 조사 등 품사가 태깅되어 튜플의 리스트 형태로 반환되었다. 또한 동사는 원형을 얻을 수 있다.

# 조사, 어미, 구두점 제거
word_list = []
for word in okt_pos:
    if word[1] not in ['Josa', 'Eomi', 'Punctuation']:
        word_list.append(word[0])

' '.join(word_list)

# 실행 결과
'버스 운행 시간 문의 하다'

조사, 어미, 구두점인 '의', '을', '.', '어', '?!' 가 제거된 형태가 되었다.

불용어 제거

# 불용어 제거 함수
def remove_stopwords(text):
    tokens = text.split(' ')
    stops = [ '합니다', '하는', '할', '하고', '한다', 
             '그리고', '입니다', '그', '등', '이런', '및','제', '더']
    meaningful_words = [w for w in tokens if not w in stops]
    return ' '.join(meaningful_words)

이후 불용어를 제거하여 의미있는 단어만을 남긴다.

train["title"] = train["title"].map(remove_stopwords)
test["title"] = test["title"].map(remove_stopwords)

train set과 test set의 title에 적용하여 아래와 같은 형태로 바꿨다.

train2
불용어 제거 train

조사, 어미, 구두점과 불용어가 제거된 형태가 되었다. 이제 전처리가 완료되었고 벡터화 후 학습한다.

학습 및 예측

X_train_text = train['title']
X_test_text = test['title']
y_train = train['topic_idx]

학습과 예측을 위해 X_train_text, X_test_text, y_train으로 나누어 준비했다.

벡터화

tfidfvect = TfidfVectorizer(min_df=2, max_df=0.95)
tfidfvect.fit(X_train_text)
X_train = tfidfvect.transform(X_train_text)
X_test = tfidfvect.transform(X_test_text)
X_train.shape, X_test.shape

# 실행 결과
((45654, 17830), (9131, 17830))

TfidfVectorizer를 임포트 한 후 생성했고, 변환할 어휘를 학습하고 transform하여 X_train, X_test에 할당했다. 벡터화 결과 차원이 매우 높아진 것을 확인할 수 있다.

모델 생성, cross validation

model_lgbm = LGBMClassifier(random_state=42)
y_val_predict = cross_val_predict(model_lgbm, X_train, y_train, cv=3)
y_val_predict

# 실행 결과
array([2, 0, 4, ..., 1, 3, 2])

모델은 lightgbm의 분류모델을 사용하여 cross_val_predict 했다.

score = (y_train == y_val_predict2).mean()
score

# 실행 결과
0.7801726026197048

그 결과 정확도는 약 0.78을 얻었다.

이제 데이콘에 제출하기 위해 X_train, y_train을 학습하고 X_test에 대한 예측을 해보자.

y_pred = model_lgbm.fit(X_train, y_train).predict(X_test)
y_pred

# 실행 결과
array([2, 3, 2, ..., 4, 0, 6])

X_test에 대한 토픽 예측 결과가 y_pred에 담겼다.

submission
제출 형태

각 index에 대한 토픽 예측을 topic_idx에 할당한 형태다.

subresult

데이콘에 예측 결과를 제출하여 public score 0.76254, private score 0.75186이라는 점수를 받았다.

NLP는 정형 데이터에 비해 훨씬 더 복잡한 개념인 것 같다. 재미있었다.

반응형

댓글