★ 아직 많이 부족합니다. 댓글을 통한 가르침 환영입니다. ★

 

이번에는 뉴스를 가져와서 직접 분석해보도록 하겠습니다.

 

들어가기 앞서, 뉴스 기사를 가져오는데 유용한 라이브러리인 newspaper3k를 설치하도록 하겠습니다.

 

pip install newspaper3k  

 

를 통해 설치해주도록 합니다.

 

newspaper3k를 통해 간략하게 뉴스 제목과 기사를 가져올 수 있는지 확인해보도록 하겠습니다.

 

최근 화두인 비트코인에 대한 뉴스기사를 가져와보도록 하겠습니다.

 

가져올 뉴스 URL : http://v.media.daum.net/v/20171215130602344

 

URL을 정했으면 이제 코드를 작성해보도록 합시다.

 

코드는 매우 간단합니다.

 

1
from newspaper import Article
cs

 

와 같이 import 해줍니다.

 

 

1
2
3
4
5
6
7
url = 'http://v.media.daum.net/v/20171215130602344'
 
article = Article(url, langague='ko')
 
article.download()
 
article.parse()
cs

 

가져올 url을 변수에 담고, 다음과 같이 기사를 파싱해옵니다.

 

마지막으로

 

1
2
3
print (article.title)
 
print (article.text)
cs

 

출력해서 기사를 확인해봅시다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
from newspaper import Article
 
url = 'http://v.media.daum.net/v/20171215130602344'
 
article = Article(url, langague='ko')
 
article.download()
 
article.parse()
 
print (article.title)
 
print (article.text)
cs

 

전체 코드 ↑ / 출력 결과 ↓

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
캐나다 중앙은행 총재 "비트코인 구매는 투자 아닌 도박"
 
 
캐나다 중앙은행인 캐나다은행의 스티븐 폴로즈 총재가 14일(현지시간) 이상 폭등세를 보이는 가상화폐 비트코인 거래에 대해 '도박'이라고 규정, 강력 경고했습니다.
 
폴로즈 총재는 토론토에서 열린 한 경제단체 주최 행사에 참석, 연설을 통해 비트코인 거래에 대해 "투자라기보다는 도박에 가깝다"고 지적했다고 캐나다 통신 등이 전했습니다.
 
폴로즈 총재는 "가상화폐를 사는 것은 위험을 구매하는 것을 의미한다"며 비트코인 구매자들에 "세부 조건을 잘 읽어야 할 것"이라고 권고했습니다.
 
특히 그는 비트코인이 신뢰할 만한 가치 저장 수단이 아니며 "화폐가 아니다"고 강조했습니다.
 
폴로즈 총재는 "통화로 간주되기 위해서는 신뢰할 만한 가치 저장 기능을 해야 한다"며 "가상화폐는 이런 요소를 전혀 갖고 있지 못한 만큼 화폐로 성립되지 않는다"고 말했습니다.
 
또 "현 상황은 심각한 혼란을 초래할 수 있는 요소가 있다"며 "이 시점부터 제도권 시스템이 주의 깊게 다루어 가기를 희망한다"고 밝혔스니다.
 
폴로즈 총재는 "비트코인 거래 차트가 에펠 탑의 왼쪽 편 모양과 같은데 이는 우리가 흔히 볼 수 없는 것"이라며 20여 년 전 유사했던 정보기술(IT) 붐 현상에 언급, "당시 다행스러웠던 것은 전방위적 파급효과는 없이 해당 분야의 주식 거래에 국한됐다는 점"이라고 지적했습니다.
 
그러나 그는 디지털 거래와 전자 화폐 수요가 늘어나는 추세를 거론하며 "중앙은행이 소매 거래에 활용될 디지털 화폐를 발행하는 문제에 대해 적절한 상황을 연구, 검토하고 있다"고 말했습니다.
 
cs

 

이렇게 간단하게 가져온 뉴스기사를 여러개 가져와 유사도 분석을 시도해보도록 하겠습니다. ( 마지막 기자님 성함과 이메일 주소는 뺐습니다. )

 

먼저, 분석을 위해 각 문장에 있는 명사들을 추출하는 작업을 진행해보도록 하겠습니다.

 

상단에

 

1
from konlpy.tag import Kkma, Twitter
cs

 

를 추가해줍니다. 이번에는 Kkma와 Twitter 모두 사용하여 유사한 내용의 뉴스와 전혀 다른 뉴스의 내용의 유사도를 어떻게 출력하는지 확인해보겠습니다.

 

기본 틀은 kkma class를 활용해서 짜고, 후에 Twitter class를 통한 분석에 대한 내용을 덧붙이도록 해보죠.

 

 

 

 

이와 같은 플로우로 구현을 해보겠습니다.

 

그러기에 앞서 다음과 같이 kkma.nouns를 사용하여 출력해보면,

 

1
print (kkma.nouns(article.text))
cs

 

 

1
2
3
4
5
6
7
['캐나다''중앙''중앙은행''은행''캐나다은행''스티븐''폴''폴로즈''로즈''총재''14''14일''일''현지',
 '현지시간''시간''이상''폭등''폭등세''세''가상''가상화폐''화폐''비트''비트코''코''거래''도''도박''박'
'규정''경고''토론토''한''경제''경제단체''단체''주최''행사''참석''연설''투자''투자라기보''라''기보''고''지적''통신',
 '등''위험''구매''의미''구매자''세부''조건''권고''비트코인''인''신뢰''가치''저장''수단''통화''간주''기능''요소''만큼',
 '성립''현''상황''혼란''초래''수''시점''제도권''시스템''주의''가기''희망''밝혔스니''차트''에펠''탑''왼쪽''편''모양''이'
'우리''20''20여''여''년''전''유사''정보''정보기술''기술''붐''현상''언급''당시''다행''전방위''파급''파급효과''효과''해당''분야',
 '주식''국한''점''그''디지털''전자''수요''추세''거론''소매''활용''발행''문제''연구''검토']
cs

 

이와 같이 list에 담겨 나오게됩니다.

 

이렇게 추출한 명사를 하나의 document 형태로 만들기 위해 각 명사들을 띄어쓰기로 구분하여 이어 붙여주도록 하겠습니다.

 

1
2
3
4
5
6
7
mydoclist_kkma = []
 
nouns = ' '.join(kkma.nouns(article.text))
 
mydoclist_kkma.append(nouns)
 
print (nouns)
cs

 

1
캐나다 중앙 중앙은행 은행 캐나다은행 스티븐 …(중략)… 추세 거론 소매 활용 발행 문제 연구 검토 
cs

 

이렇게 mydoclist_kkma에는 Kkma class로 추출한 명사로 이루어진 하나의 document가 자리잡게 됩니다.

 

자 그럼 큰 틀을 잡았으니,

 

첫 번째 뉴스 : http://v.media.daum.net/v/20171215130602344  (비트코인 관련 )

 

두 번째 뉴스 : http://v.media.daum.net/v/20171215130312300  ( 비트코인 관련 )

 

세 번째 뉴스 : http://v.media.daum.net/v/20171215111203921 ( 비트코인 관련 )

 

네 번째 뉴스 : http://v.media.daum.net/v/20171216002700566 ( 날씨 관련 )

 

다섯 번째 뉴스 : http://v.media.daum.net/v/20171215214505350(날씨 관련 )

 

이렇게 5개의 뉴스를 분석해보도록 하겠습니다.

 

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
from newspaper import Article
from konlpy.tag import Kkma, Twitter
from sklearn.feature_extraction.text import TfidfVectorizer
 
url_list = ['http://v.media.daum.net/v/20171215130602344',
            'http://v.media.daum.net/v/20171215130312300',
            'http://v.media.daum.net/v/20171215111203921',
            'http://v.media.daum.net/v/20171216002700566',
            'http://v.media.daum.net/v/20171215214505350']
 
twitter = Twitter()
kkma = Kkma()
 
mydoclist_kkma = []
mydoclist_twitter = []
 
for url in url_list:
    article = Article(url, langague='ko')
    article.download()
    article.parse()
 
    kkma_nouns = ' '.join(kkma.nouns(article.text))
    twitter_nouns = ' '.join(twitter.nouns(article.text))
    mydoclist_kkma.append(kkma_nouns)
    mydoclist_twitter.append(twitter_nouns)
 
tfidf_vectorizer = TfidfVectorizer(min_df=1)
tfidf_matrix_kkma = tfidf_vectorizer.fit_transform(mydoclist_kkma)
tfidf_matrix_twitter = tfidf_vectorizer.fit_transform(mydoclist_twitter)
 
document_distances_kkma = (tfidf_matrix_kkma * tfidf_matrix_kkma.T)
document_distances_twitter = (tfidf_matrix_twitter * tfidf_matrix_twitter.T)
 
print ('Kkma class를 활용한 유사도 분석을 위해 ' + str(document_distances_kkma.get_shape()[0]) + 'x' + str(document_distances_kkma.get_shape()[1]) + ' matrix를 만들었습니다.')
print(document_distances_kkma.toarray())
 
 
 
print ('Twitter class를 활용한 유사도 분석을 위해 ' + str(document_distances_twitter.get_shape()[0]) + 'x' + str(document_distances_twitter.get_shape()[1]) + ' matrix를 만들었습니다.')
print(document_distances_twitter.toarray())
cs

 

전체 코드입니다.

 

결과는 다음과 같습니다.

 

 

< Kkma 이용 결과 >

 

< Twitter class 이용 결과 >

 

이렇게 뉴스 분석까지 끝마쳤습니다.

 

개인적으로 봤을 땐 Twitter class가 비슷한 주제라면 더욱 직관적이긴 한 것 같습니다.

 

마지막으로, 형태소 분석에 이용되는 class에 따라 더 나아가 형태소 분석이 어떻게 되는지에 따라 결과가 달라질수도 있지만 꽤나 유의미한 결과를 보여주었다고 생각합니다.

'텍스트 분석' 카테고리의 다른 글

텍스트 유사도 분석 - 2  (0) 2017.12.14
텍스트 유사도 분석 - 1  (0) 2017.12.13

★ 아직 많이 부족합니다. 댓글을 통한 가르침 환영입니다. ★

 

이어 두 번째 시간에는 문장에서 조사를 떼어내고, 명사만 활용하여 분석을 시도해보도록 하겠습니다.

 

그러기 위해서, 한글 형태소 분석을 위한 '한국어 정보처리 파이썬 패키지'인 konlpy를 설치해줍니다.

 

Windows 10에서 konlpy를 설치하기 위해, http://konlpy-ko.readthedocs.io/ko/v0.4.3/install/#id2를 참고합니다.

 

저는 Python 3.5.4 버전에 Windows 10이 64bit이므로

 

https://www.lfd.uci.edu/~gohlke/pythonlibs/#jpype에 접속하여, JPype1‑0.6.2‑cp35‑cp35m‑win_amd64.whl 을 다운받고,

 

프롬프트에서 whl 설치 폴더로 이동하여,

 

pip install --upgrade pip  

 

pip install JPype1‑0.6.2‑cp35‑cp35m‑win_amd64.whl  

 

와 같이 설치해줍니다.

 

최종적으로

 

pip installl konlpy 

 

를 설치해줍니다.

 

+) JAVA환경변수가 설정되어있지 않으신 분들은 http://konlpy-ko.readthedocs.io/ko/v0.4.4/install/#id2 를 참고하여 환경변수를 설정해주시면 됩니다.

 

 

 

형태소 분석을 위해 Konlpy의 사용법을 익혀보도록 하겠습니다.

 

Konlpy의 Kkma class를 사용해보겠습니다

 

1
2
3
4
5
6
7
8
9
10
11
12
from konlpy.tag import Kkma
from konlpy.utils import pprint
 
kkma = Kkma()
 
sentence = u'영희와 철수는 백구를 산책시키기 위해 한강에 갔다. 한강에 도착하여 누렁이를 만났다.'
 
print('형태소 : ' + str(kkma.morphs(sentence)))
 
print('명사 : ' + str(kkma.nouns(sentence)))
 
print('품사 : ' + str(kkma.pos(sentence)))
cs

 

출력결과는

 

1
2
3
4
5
6
7
8
9
10
형태소 : ['영희''와''철수''는''백구''를''산책''시키''기''위하''어''한강''에''가''었''다''.''한강''에''도착''하''여''누렁이''를''만나''었''다''.']
 
 
명사 : ['영희''철수''백구''산책''한강''도착''누렁이']
 
 
품사 : [('영희''NNP'), ('와''JKM'), ('철수''NNG'), ('는''JX'), ('백구''NNG'), ('를''JKO'), ('산책''NNG'), ('시키''XSV'),
        ('기''ETN'), ('위하''VV'), ('어''ECS'), ('한강''NNP'), ('에''JKM'), ('가''VV'), ('었''EPT'), ('다''EFN'), ('.''SF'), ('한강''NNP'),
        ('에''JKM'), ('도착''NNG'), ('하''XSV'), ('여''ECS'), ('누렁이''NNG'), ('를''JKO'), ('만나''VV'), ('었''EPT'), ('다''EFN'), ('.''SF')]
 
cs

 

와 같이 조사를 제거하고 명사를 잘 추출하는 것을 볼 수 있습니다.

 

또 다른 class인 Twitter을 사용해보도록 하겠습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
from konlpy.tag import Twitter
from konlpy.utils import pprint
 
twitter =Twitter()
 
sentence = u'영희와 철수는 백구를 산책시키기 위해 한강에 갔다. 한강에 도착하여 누렁이를 만났다.'
 
print('형태소 : ' + str(twitter.morphs(sentence)))
 
print('명사 : ' + str(twitter.nouns(sentence)))
 
print('품사 : ' + str(twitter.pos(sentence)))
cs

 

 

1
2
3
4
5
6
7
8
형태소 : ['영희''와''철수''는''백구''를''산책''시키''기''위해''한강''에''갔''다''.''한강''에''도착하여''누렁이''를''만났''다''.']
 
명사 : ['영희''철수''백구''산책''위해''한강''한강''누렁이']
 
품사 : [('영희''Noun'), ('와''Josa'), ('철수''Noun'), ('는''Josa'), ('백구''Noun'), ('를''Josa'), ('산책''Noun'), 
        ('시키''Verb'), ('기''Eomi'), ('위해''Noun'), ('한강''Noun'), ('에''Josa'), ('갔''Verb'), ('다''Eomi'), ('.''Punctuation'), ('한강''Noun'), 
        ('에''Josa'), ('도착하여''Verb'), ('누렁이''Noun'), ('를''Josa'), ('만났''Verb'), ('다''Eomi'), ('.''Punctuation')]
 
cs

 

Twitter class 역시 어느정도 분석을 잘하는 것을 확인할 수 있습니다.

 

 

하나만 더 비교해보도록 하겠습니다.

 

이전 포스팅의 각 문서 1, 2, 3을 조금 수정해보았습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
from konlpy.tag import Kkma, Twitter
from konlpy.utils import pprint
 
mydoclist = ['영희가 사랑하는 강아지 백구를 산책시키고 있다.',
             '철수가 사랑하는 소 누렁이를 운동시키고 있다.',
             '영희와 철수는 소와 강아지를 산책 및 운동시키고 있다.']
 
twitter = Twitter()
kkma = Kkma()
 
 
print('명사 : ' + str(kkma.nouns(mydoclist[0])))
print('명사 : ' + str(twitter.nouns(mydoclist[0])))
cs

 

첫번째 문서인 '영희가 사랑하는 강아지 백구를 산책시키고 있다.'를 분석한 결과는 다음과 같습니다.

 

1
2
3
명사 : ['영희''사랑''강아지''백구''산책'# Kkma class
 
명사 : ['영희''강아지''백구''산책'# Twitter class
cs

 

Twitter은 '사랑하-'를 '동사'로 인식하여 이 부분은 추출하지 못하는 것을 볼 수 있습니다.

 

 

+) 추가적으로 위의 수정한 문서를 통한 TfidfVectorizer의 결과는 아래와 같습니다.

 

 

 

어느 정도 유사한 문장이 있음에도 불구하고 유사도가 6~22% 남짓 나오고 있습니다.

 

 

다시 돌아와, 분석에 조금 더 용이할 것 같아 Kkma class를 활용해 분석해보도록 하겠습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from sklearn.feature_extraction.text import TfidfVectorizer
from konlpy.tag import Kkma, Twitter
from konlpy.utils import pprint
 
mydoclist = ['영희가 사랑하는 강아지 백구를 산책시키고 있다.',
             '철수가 사랑하는 소 누렁이를 운동시키고 있다.',
             '영희와 철수는 소와 강아지를 산책 및 운동시키고 있다.']
 
kkma = Kkma()
 
doc_nouns_list = []
 
for doc in mydoclist:
    nouns = kkma.nouns(doc)
    doc_nouns = ''
 
    for noun in nouns:
        doc_nouns += noun + ' '
 
    doc_nouns_list.append(doc_nouns)
 
for i in range(03):
    print('doc' + str(i + 1+ ' : ' + str(doc_nouns_list[i]))
cs

 

먼저 추출한 명사를 doc_nouns_list에 넣어주었습니다.

 

1
2
3
4
5
doc1 : 영희 사랑 강아지 백구 산책 
 
doc2 : 철수 사랑 소 누렁이 운동 
 
doc3 : 영희 철수 소 강아지 산책 운동 
cs

 

출력 결과는 위와 같습니다.

 

이제 이전 포스팅에서 사용했던 TfidfVectorizer을 활용하여 비교해보도록 하겠습니다. 아래쪽에 코드를 더 추가해줍니다.

 

1
2
3
4
5
6
7
8
tfidf_vectorizer = TfidfVectorizer(min_df=1)
tfidf_matrix = tfidf_vectorizer.fit_transform(doc_nouns_list)
 
document_distances = (tfidf_matrix * tfidf_matrix.T)
 
print ('유사도 분석을 위한 ' + str(document_distances.get_shape()[0]) + 'x' + str(document_distances.get_shape()[1]) + ' matrix를 만들었습니다.')
 
print(document_distances.toarray())
cs

 

 

결과는

 

 

 

형태소를 분석하여 비교하니 세번째 문서와 첫번째 문서 그리고 세번째 문서와 두번째 문서가 어느정도 유사함을 보이는게 보이는군요 !

 

 

다음 포스팅에서는 간단하게 이를 활용하여 뉴스를 분석해보도록 하겠습니다.

 

'텍스트 분석' 카테고리의 다른 글

텍스트 유사도 분석 - 3  (0) 2017.12.15
텍스트 유사도 분석 - 1  (0) 2017.12.13

★ 아직 많이 부족합니다. 댓글을 통한 가르침 환영입니다. ★

 

오늘은 Python을 활용하여 TF-IDF 알고리즘을 활용하여 뉴스 기사를 분석해보도록 하겠습니다.

 

[ Python 3.5.4 버전을 활용하며, 개발 툴은 Pycharm을 사용 ]

 

 

1. TF-IDF 알고리즘

 

'TF-IDF(Term Frequency - Inverse Document Frequency)는 정보 검색과 텍스트 마이닝에서 이용하는 가중치로, 여러 문서로 이루어진 문서군이 있을 때 어떤 단어가 특정 문서 내에서 얼마나 중요한 것인지를 나타내는 통계적 수치.

문서의 핵심어를 추출하거나, 검색 엔진에서 검색 결과의 순위를 결정하거나, 문서들 사이의 비슷한 정도를 구하는 등의 용도로 사용' 한다고 합니다.

 

TF : 문서에 나타난 빈도

IDF : 단어가 나타난 문서의 빈도

 

 

즉, 문서의 수와 그 문서에 나타난 단어의 빈도수를 분석하여 유사도를 나타내는 것입니다.

 

더욱 자세한 사항은 https://ko.wikipedia.org/wiki/TF-IDF 에서 확인이 가능하십니다.

 

그렇다면,  TF-IDF의 복잡한 수식 없이 scikit-learnTfidfVectorizer을 활용하여 분석해보도록 하겠습니다.

 

먼저,

 

pip install scikit-learn 

 

을 통해 라이브러리를 설치해줍니다.

 

 

 

Pycharm을 통해 라이브러리 설치를 확인합니다.

 

ImportError: No module named 'scipy' 

 

와 같은 Error가 발생하면

 

pip install scipy 

 

를 통해 설치 후 해결해주도록 합니다.

 

뉴스 기사의 유사도를 분석하기에 앞서, 간단하게 코드를 보겠습니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
from sklearn.feature_extraction.text import TfidfVectorizer
 
mydoclist = ['find what you love''do what you love'"don't do what you hate"]
 
tfidf_vectorizer = TfidfVectorizer(min_df=1)
tfidf_matrix = tfidf_vectorizer.fit_transform(mydoclist)
 
document_distances = (tfidf_matrix * tfidf_matrix.T)
 
print ('유사도 분석을 위한 ' + str(document_distances.get_shape()[0]) + 'x' + str(document_distances.get_shape()[1]) + ' matrix를 만들었습니다.')
 
print(document_distances.toarray())
 
cs

 

 

 

TfdifVectorizer을 import 한 후,

 

mydoclist에 비교하고자하는 문장을 담아줍니다. 우선 영어로 문서를 작성해보도록 하겠습니다.

 

다음과 첫번째 문서가 'find what you love', 두번째 문서가 'do what you love', 세번째 문서가 'dont't do what you hate'가 되겠네요 

 

분석 결과는 위와 같습니다.

 

 

그렇다면, 이번엔 한글로 mydoclist를 작성해보겠습니다.

 

다음과 같이 list에 3개의 한 문장으로 이루어진 문서를 넣어보았습니다.

 

mydoclist = ['영희가 좋아하는 사람은 철수다.',  '철수를 영희가 좋아한다.',  '영희는 철수를 좋아하고 있다.']

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from sklearn.feature_extraction.text import TfidfVectorizer
 
mydoclist = ['영희가 좋아하는 사람은 철수다.',
             '철수를 영희가 좋아한다.',
             '영희는 철수를 좋아하고 있다.']
 
tfidf_vectorizer = TfidfVectorizer(min_df=1)
tfidf_matrix = tfidf_vectorizer.fit_transform(mydoclist)
 
document_distances = (tfidf_matrix * tfidf_matrix.T)
 
print ('유사도 분석을 위한 ' + str(document_distances.get_shape()[0]) + 'x' + str(document_distances.get_shape()[1]) + ' matrix를 만들었습니다.')
 
print(document_distances.toarray())
 
cs

 

 

 

첫번째 문서인 '영희가 좋아하는 사람은 철수다' 와 두번째 문서인 '철수를 영희가 좋아한다'의 유사도가 20%밖에 안나오네요

 

심지어, 첫번째 문서인 '영희가 좋아하는 사람은 철수다'와 세번째 문서인 '영희는 철수를 좋아하고 있다'는 유사도가 0%로 나오는걸 볼 수 있습니다.

 

우수한 한글의 특성상 조사에 따라 '단어'를 다르게 인식하는게 문제로 보이네요.

 

이러한 문제를 해결하기 위해, 다음 포스팅에서는 형태소 분석을 진행하여 명사에 붙은 조사를 떼어내고, 명사만으로 비교를 통해 유사도가 얼마나 올라가는지 비교해보도록 하겠습니다.

'텍스트 분석' 카테고리의 다른 글

텍스트 유사도 분석 - 3  (0) 2017.12.15
텍스트 유사도 분석 - 2  (0) 2017.12.14

+ Recent posts