본문 바로가기
Programming_Collective Intelligence/3.군집발견

지도/비지도 학습 /단어 벡터

by 볼록티 2019. 12. 29.
728x90
반응형

 이번 3장에서는 2장의 아이디어를 이용하여 유사항목을 가진 그룹을 자동으로 검출하는 군집 기법 2개를 소개한다.

즉, 인기 블로그 집합에서 그리고 소셜 네트워킹 웹 사이트로부터의 사람들의 요구에서 그룹을 찾기 위해 군집을 사용하는 방법을 보여준다.

 

지도/비지도 학습

 

 지도 학습: 정답 값을 가진 데이터를 토대로 입출력을 사용하여 새로 주어진 데이터에 대한 답을 찾도록 학습하는 방법. 신경망, 결정트리, SVM, 베이지안 필터링 등.

 비지도 학습: LABEL값이 주어지지 않고, 데이터 집합 내에서 구조를 발견하는데 의의가 있는 학습 방법. 군집 알고리즘.

 

 

 

단어 벡터

 

군집용 데이터를 준비하는 일반적인 방법은 항목 비교에 사용될 숫자 특성들의 공통집합을 결정하는 것이다. 예컨데 2장에서 평론가의 평가점수를 영화의 공통집합과 비교했던 경우가 있다.

 

블로거 분류

http://kiwitobes.com 여기서 블로그 정보를 가져오게 된다.

 

Toby Segaran

Experiments in electronics, data, art, cocktails and physics

kiwitobes.com

 

import feedparser
import re

#한 RSS 피드 안에 있는 제목과 단어 출현 횟수 딕셔너리를 리턴함
def getwordcounts(url):
    #피드를 파싱함
    d=feedparser.parse(url)
    wc={}
    
    #모든 게시글별로 루프를 돔
    for e in d.entries:
        if 'summary' in e: summary=e.summary
        else: summary = e.discription
            
        #단어 목록을 추출함
        words = getwords(e.title+' '+summary)
        for word in words:
            wc.setdefault(word,0)
            wc[word]+=1
    return d.feed.title, wc

feedparser 모듈을 사용하여 제목, 링크, 게시글을 RSS나 Atom피드에서 쉽게 얻을 수 있다. 새로운 파이썬 파일인 generatefeedvector.py를 위의 함수를 시작으로 만들었다.

 

RSS와 Atom 피드는 항상 제목과 게시글의 몸ㄱ록으로 구성된다. 각 게시글은 보통 summary나 description태그를 가지고 있어 게시글의 실제 텍스트를 담고 있다.

 

이제 위의 코드에 포함된 getwords함수를 만들어서 HTML코드를 제거하고 전처리를 할 함수를 만들어 준다.

 

 

우선 feedparser.parse("http://feeds.feedburner.com/37signals/beMH") 는 아래와 같은 결과를 보여준다.

그 결과값의 키들만 뽑아보았다. 그냥 이렇게 url 속에 있는 html코드를 예쁘게 분해시켜주는 모듈, 함수라 생각하면 될 듯하다.

 

 

 

 

데이터가 오래되고 해서 블로그에 이런 저런 이상현상이 발생하여서, 예외처리를 추가하였다.

 

apcount = {}
wordcounts={}
with open('data/feedlist.txt','r') as f:
    for feedurl in f.readlines():
        try:
            title, wc = getwordcounts(feedurl)
            wordcounts[title]=wc
            for word, count in wc.items():
                apcount.setdefault(word,0)
                if count > 1:
                    apcount[word]+=1
        except Exception as ex:
            print('블로그 없음', ex)
            continue

feedlist.txt는 아래의 참조에 저자 깃헙사이트에서 복붙할 수 있다. 위의 코드를 통해서 67개 정도의 블로그에서 단어 빈도를 추출해볼 수 있었다. 아래와 같은 에러가 꽤 많이 발생하였다.

 

어쨌든 이제 다음 단계에서는 각 블로그별로 집계할 단어 목록을 생성하는 것이다. 어떤 단어들을 집계해볼 것인가?

'the'와 같은 단어는 비중이 낮다. 하지만 'flim-flam'과 같은 단어는 거의 한번 밖에 나타나지 않을 것이므로 최대와 최소 비중내에 있는 단어들만 선택하여 포함시키는 방식으로 전체 단어 수를 절약할 수 있다. 즉 너무 많이 나타나는 단어나 너무 적은 단어를 조금 제외해보자는 얘기이다. 

 10% ~ 50% 사이로 시작을 할 수 있지만, 고빈도어나 저빈도어가 너무 많이 나타난다면 값을 조절해보자.

 

아래의 코드를 통해서 단어가 출현한 횟수가 10%~50% 정도 되는 단어만 가져온다는 것이다. 실제로 feedparser를 통해서 15139개의 단어장을 가지고 있기 때문에 당연히 sparse해져있으므로 이를 컷트할 필요가 있다.

 

단어장의 모든 단어에 대해서 블로그에 있는 단어들에 대해 총 빈도를 매겨놓은 것이다. 중간에 0이나 1 과같은 저빈도 단어가 보이며, 이러한 것을 좀 제거해준다는 것이다. 

 

아래의 코드를 통해 제거할 것을 제거. 그리하면 534개가 남게 된다.

wordlist = []
for w,bc in apcount.items():
    frac = float(bc)/len(wordcounts)
    if frac > 0.1 and frac < 0.5: wordlist.append(w)

 

 

이제 마지막 단계로 단어목록과 블로그 목록을 사용해서 각 블로그 내에 단어들의 횟수를 담고 있는 행렬을 만들어 텍스트 파일로 저장하는 것이다.

 

하다보니까 하고 싶은게 생겨서 군집을 나만의 방법으로 적용시켜보려한다. 여기서 접고 다음 장부터 진행해보도록 하겠다.

 

참조:https://github.com/arthur-e/Programming-Collective-Intelligence/tree/master/chapter3

728x90
반응형

댓글