13 Security Lab

[Topic Modeling] TF-IDF 를 이용한 이슈 변화 흐름 분석 본문

Computer Science/Projects

[Topic Modeling] TF-IDF 를 이용한 이슈 변화 흐름 분석

Maj0r Tom 2018. 5. 17. 00:26

정치 이슈에 대해서 TF-IDF 통계기법을 이용하여 기간별 정치기사의 이슈가 어떻게 바뀌어가는지 변화 흐름을 분석한다.

 

TF-IDF 이란 ? TF-IDF 에 대해서 알아보기

 

이를 위해 Topic Model 기법을 응용하여 이슈 변화 흐름 분석을 시도해 보았다.

 

기간: 4/1 ~ 4/30
데이터셋: 450건의 정치기사 (daum.net)

 

 

 

1. 정치기사 수집

 

최초, 4월 한달 간으로 수집하고 DB를 구성하였으며, 각 날짜 별 15건에 대해서 수집을 시도하였다.

 

기사 수집 시 텍스트 파싱에 에러가 나는 데이터셋을 제외하고 441의 데이터를 수집하였다.

 

 news_origin.db

 

 

 

 

 

 

한글 기사 태그 부분(“article_view”)을 파싱하여 기사 내용을 가져왔다.

 

기사에서 공통적으로 끝부분에서 기자 이름과 이메일이 들어가는 것을 확인하여 해당 부분은 제외 되도록 하였다.

 

 getArticle.py

 

 

 

 

영문 번역 및 Topic 추출의 용이성을 위해서 기사의 길이를 400자로 제한하여 재 가공 하였다.

 

 Kor2eng.py

 

 

 

2. 한글 기사 dataset 영문 번역

 

 

Topic Model 기법을 사용하기 위해 한글 기사를 영문으로 번역 시 번역API 할당량의 제한으로 데이터셋을 다 변환하기는 어려운 것으로 판단하였다.

 

따라서 데이터셋을 보름으로 축소하였다.

 

 

영문 번역을 위해서 네이버 NMT(neural machine translation) 엔진 API를 사용하였다.

 

 

 

 

 

아래는 API를 통해 텍스트를 영문으로 변환하는 코드이다.

 

 Kor2eng.py

 

 

 

 

 

변환 된 데이터는 다시 DB(news_eng.db)에 저장 되도록 하였다.


구글의 경우 API 제공은 유료이며, 네이버 번역 API App계정 당 하루 10,000자의 제한이 있다. (유료는 10만자 당 2만원)

 

이로 인해 다수의 계정을 생성하여 진행하였으며 무료로 하기에는 번역에 번거로움이 있다...

 

그리고 번역할 글의 문자수 기준이 아니고 번역된 문자수 기준인 것 같은데... 그러면 한글로는 몇자가 아니어도 번역결과 영문으로 나오게 되서 엄청 길어지면 금방 10,000자를 채워버린다... 이부분은 조금 아쉬운듯

 

그리고 NMT 기반이어서 그런지 상상력이 풍부하게 문장들을 만들어 내는 것 같다. (기계가 상상력이 풍부해?)

 

 Kor2eng.py

 

 

 News_eng.db

 

 

 

 

 

 

아래는 변환 된 영문 텍스트를 예시로 출력한 결과이다.


기사의 한글 텍스트를 400자로 줄여 번역하였으나, 영문 번역결과는 3000자로 늘리는 등 API 호출 제한에 금방 도달한다.. 

 

일부 기사에서는 번역 시 API에러가 발생하여 (그냥 try, except로 예외 처리하고 except에서 로그만 찍는 것이 정신건강에 좋다)

 

일부는 웹에서 수동으로 기계번역을 진행하였다.

 

 



 

3. Topic Model을 통한 키워드 추출 및 이슈 변화 흐름 추적

 

추출한 영문 텍스트 셋을 NMF(Non-negative matrix factorization) 모델을 통한 Topic model 기법을 사용하여 키워드를 추출하였다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# ------------------------------------------------
# data load
with open('news_eng.json', encoding='UTF8') as data_file:
    data = json.load(data_file)
 
Corpus_set = []
for article in data:
    Corpus_set.append(article['eng_contents'])
data_samples = Corpus_set
 
print("done in %0.3fs." % (time() - t0))
 
 
# -----------------------------------------------------------------
# Use tf-idf features for NMF.
print("Extracting tf-idf features for NMF...")
tfidf_vectorizer = TfidfVectorizer(max_df=0.95, min_df=2,
                                   max_features=n_features,
                                   stop_words='english')
t0 = time()
tfidf = tfidf_vectorizer.fit_transform(data_samples)
print("done in %0.3fs." % (time() - t0))
 
# Use tf (raw term count) features for LDA.
print("Extracting tf features for LDA...")
tf_vectorizer = CountVectorizer(max_df=0.95, min_df=2,
                                max_features=n_features,
                                stop_words='english')
 
 
 
# Fit the NMF model
print("Fitting the NMF model (Frobenius norm) with tf-idf features, "
      "n_samples=%d and n_features=%d..."
      % (n_samples, n_features))
t0 = time()
nmf = NMF(n_components=n_components, random_state=1,
          alpha=.1, l1_ratio=.5).fit(tfidf)
print("done in %0.3fs." % (time() - t0))
 
print("\nTopics in NMF model (Frobenius norm):")
tfidf_feature_names = tfidf_vectorizer.get_feature_names()
topic_set = print_top_words(nmf, tfidf_feature_names, n_top_words)
 
 
 

 

 

1
2
3
4
5
6
7
8
def print_top_words(model, feature_names, n_top_words):
    topic_set = []
    for topic_idx, topic in enumerate(model.components_):
        message = "Topic #%d: " % topic_idx
        message += " ".join([feature_names[i] for i in topic.argsort()[:-n_top_words - 1:-1]])
        topic_set.append([feature_names[i] for i in topic.argsort()[:-n_top_words - 1:-1]])
 
    return topic_set
 

 

 

 

 

 

 

Topic 0에서는 주로 north, south, korea북한남한을 의미하는 단어 등 최근 남북정상회담에 이은 여러 이슈들에 대한 기사들이 주로 포착된 것으로 보인다.

 

Topic 1에서는 party, president, moon 등으로 정당문재인 대통령, 그리고 elections, democratic 등으로 곧 있을 지방선거와 관련 된 이슈들이 포착 된 것으로 보인다.

 

출력결과 아래와 같은 형태를 띄었으며 variance가 크긴 하지만 시간이 지남에 따라 Topic 0 에서 Topic 1으로의 이동이 있는 것으로 아래와 같이 나타났다.


데이터를 가져오는 과정에서 그날의 데이터를 23:59부터 역순으로 가져왔기 때문에 데이터가 날짜 별로 세로 열 형태로 세워져 있는 형태를 띄고 있다.

 

 시계열 데이터 그래프 출력 < Topic 0양수 방향으로 표현, Topic 1음수 방향으로 표현 >

 

 
 

좀더 가시적으로 보기 위해 데이터간 간격을 균일하게 하여 아래와 같이 출력하여 시간 별 Topic의 이동을 보여준다.

 

 데이터 간격 균일 그래프

 

 
 
 

 

topic을 구하고 나서 유사한 기사끼리 묶기 위한 주요 코드이다.

 

 Topic.py



이 Topic 단어로 추출 된 값의 포함 여부로 vector값을 구하였다.

 

topic 0 또는 topic 1 에 존재하면 1을 추가하고, 반복 횟수에 따라 해당단어횟수*1/10 만큼 가중치를 주어 유사한 기사끼리 분류 되도록 하였다.

 

Topic 0는 양의 값으로 표현, Topic 1은 음의 값으로 표현하였다.

 

 

 

 

 

Ref. https://github.com/sharpduckk/Study/tree/master/Topic-Modeling/Topic-changes-over-time

 

 

Comments