Link Search Menu Expand Document

뉴스 기사 Clustering


Table of contents
  1. 뉴스 기사 Clustering
    1. 뉴스 기사 준비
    2. tokenize & 명사만 저장
    3. Text Vector화 & 학습
    4. 학습 결과 확인

뉴스 기사 Clustering

  • 뉴스 기사의 내용을 바탕으로 유사한 기사끼리 묶어보려고 함
# 사용할 library를 먼저 모두 import
import pandas as pd
import konlpy
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import AgglomerativeClustering

뉴스 기사 준비

  • 우선, Clustering할 기사 데이터를 수집
  • 다음 뉴스에서, ‘국회/정당’, ‘금융’, ‘건강’, ‘사건/사고’ 4개 토픽의 기사를 조금씩 수집해 옴
## '다음 뉴스'에서 직접 수집해 온 데이터를 dataframe으로 정리해 둠
news_df.head()
  topic article_title news_text
0 국회/정당 [포토]재보선 D-1, ‘시민들의 선택은?’ [국회사진취재단] 6일 오후 서대문구 홍제역에서 열린 박영선 더불어민주당 서울시장…
1 국회/정당 “약속 지킨다”..김종인, 8일 국민의힘 떠난다 김종인 국민의힘 비상대책위원장이 5일 오후 서울 관악구 서울대입구역에서 오세훈 서울…
2 국회/정당 “위선·무능 정부 심판해야”..빨강 운동화에 ‘골목’ 찾은 오세훈 오세훈 국민의힘 서울시장 후보가 6일 서울 성북구 정릉시장에서 만난 한 시민에게 허…
3 국회/정당 김종인, 강남 대치역 찾아 오세훈 후보 지지호소 (서울=뉴스1) 국회사진취재단 = 김종인 국민의힘 비상대책위원장이 6일 오후 서울…
4 국회/정당 이낙연 “특권층 득세하고 차별하는 서울로 퇴보할 텐가” [이데일리 이정현 기자] 이낙연 더불어민주당 상임선대위원장이 6일 오세훈 국민의힘..

 

news_df.groupby('topic')[['article_title']].count()
topic article_title
건강 16
국회/정당 13
금융 15
사건/사고 15

tokenize & 명사만 저장

  • 기사의 주제를 판단하는 데에 명사가 가장 중요하다고 생각해 명사만 사용
documents_processed = []

for text in news_df['news_text']:
    okt = konlpy.tag.Okt() 
    okt_pos = okt.pos(text)

    words = []
    for word, pos in okt_pos:
        if 'Noun' in pos:
            words.append(word)

    documents_processed.append(' '.join(words))

print(len(documents_processed))
documents_processed[0]
59
'국회 진취 재단 오후 서대문구 홍제역 박영선 민주당 서울시장 후보 집중 유세 시민 휴대폰 관심 표명 노진환'

Text Vector화 & 학습

tfidf_vectorizer = TfidfVectorizer(min_df=1, ngram_range=(1,1))

tfidf_vector = tfidf_vectorizer.fit_transform(documents_processed)

tfidf_dense = tfidf_vector.todense()   ## sparse array로는 Agg.Clustering 학습이 안되어서, dense array로 바꿔줘야 함

*TfidfVectorizer: 각 단어의 Term Frequency - Inverse Document Frequency를 기반으로 text를 vector화.

  • ngram_range: (1, 1) means only unigrams, (1, 2) means unigrams and bigrams, and (2, 2) means only bigrams. (default: (1,1))
  • min_df: ignore terms that have a document frequency strictly lower than the given threshold. (default: 1)

→ AgglomerativeClustering으로 학습

model = AgglomerativeClustering(linkage='complete', affinity='cosine', n_clusters=4)
model.fit(tfidf_dense)
model.labels_
array([3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
       0, 1, 1, 1, 1, 1, 2, 0, 1, 2, 0, 2, 2, 2, 0, 2, 0, 2, 0, 2, 2, 2,
       0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 3], dtype=int64)

학습 결과 확인

  • 원래 daum에서 분류되어 있던 주제와 비교해서, 유사한 기사끼리 잘 묶였나 확인
# topic, article_title에 cluster를 붙여서 확인

cluster_df = pd.DataFrame(zip(news_df['topic'], news_df['article_title'], model.labels_), columns=['topic', 'title', 'cluster'])
cluster_df.head()
  topic title cluster
0 국회/정당 [포토]재보선 D-1, ‘시민들의 선택은?’ 3
1 국회/정당 “약속 지킨다”..김종인, 8일 국민의힘 떠난다 3
2 국회/정당 “위선·무능 정부 심판해야”..빨강 운동화에 ‘골목’ 찾은 오세훈 3
3 국회/정당 김종인, 강남 대치역 찾아 오세훈 후보 지지호소 3
4 국회/정당 이낙연 “특권층 득세하고 차별하는 서울로 퇴보할 텐가” 3

→ 각 topic별 cluster 배정 현황을 확인:

cluster_df.groupby(['topic', 'cluster'])[['cluster']].count()
topic cluster count
건강

0 5
1 1
2 10
국회/정당
1 2
3 11
금융
0 2
1 13
사건/사고
0 13
3 2
  • 주로 ‘건강’: 2, ‘국회/정당’: 3, ‘금융’: 1, ‘사건/사고’: 0으로 많이 배정되었음을 확인

→ daum의 분류와 다른 부분을 확인:

cluster_df[cluster_df['topic'] == '국회/정당']
  topic title cluster
0 국회/정당 [포토]재보선 D-1, ‘시민들의 선택은?’ 3
1 국회/정당 “약속 지킨다”..김종인, 8일 국민의힘 떠난다 3
2 국회/정당 “위선·무능 정부 심판해야”..빨강 운동화에 ‘골목’ 찾은 오세훈 3
3 국회/정당 김종인, 강남 대치역 찾아 오세훈 후보 지지호소 3
4 국회/정당 이낙연 “특권층 득세하고 차별하는 서울로 퇴보할 텐가” 3
5 국회/정당 시민들과 기념사진 찍는 김종인 비대위원장 3
6 국회/정당 강남 찾아 오세훈 지지호소하는 김종인 3
7 국회/정당 김종인, 오세훈 후보 지원유세 3
8 국회/정당 지원유세 마치고 차량에 오른 김종인 3
9 국회/정당 오세훈 후보 지원유세하는 김종인 3
10 국회/정당 내 선거’처럼 뛴 안철수는 국민의힘에서 무엇이 될까 3
11 국회/정당 웹툰에서도 부딪히는 네이버 vs 카카오..’원조 국밥집’ 논란도? 1
12 국회/정당 토스, 매출 230% 급증..”출범 후 처음으로 매출 이익 동시 개선” 1
  • topic 간 경계가 모호한 기사의 경우 daum에서 배정한 topic과 다른 cluster로 묶인 것…

Copyright © 2021 Chaeyun.
This site uses Just the Docs, a Jekyll theme.