ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [NLTK] 자연어 처리2 - NLTK로 데이터 탐색
    💫 Computer Science/Python & AI Framework 2020. 1. 31. 11:58

    NLTK는 Natural Language ToolKit의 약자로 자연어 처리 및 분석, 텍스트마이닝을 위한 파이썬 패키지 입니다. NLTK는 토큰생성, 형태소 분석, 품사태깅 등의 다양한 기능을 제공하고 예제로 활용할 수 있는 말뭉치도 제공하고 있습니다.

     

     

     

     

    ● NLTK 설치

    저는 아나콘다 환경에서 파이썬을 사용하고 있으므로 이미 루트 가상환경에 NLTK가 설치가 되어있었습니다. KoNLPy와 다르게 별도의 설정등을 해줄 필요가 없습니다.아나콘다 내에서 가상환경을 따로 만들어 설치를 해줄시엔 해당 가상환경 activate 후에

    > conda install nltk]
    > conda update nltk

    위 명령어를 입력하여 설치해주면 됩니다.

     

    하지만 예제를 수행하면 여러 에러 메세지들을 볼 수 있습니다. 예를들어 nltk.download('words'), nltk.download('maxent_ne_chunker')를 하라는 등의 메세지가 뜨면 오류메세지에 뜬 명령어 그대로 입력해서 별도의 모듈들을 설치해주면 됩니다.

     

     

    ○ 예제 시행해보기

    from nltk import word_tokenize, pos_tag, ne_chunk
    
    sentence = 'Mike is working at IT Centre'
    
    # 토큰화, 품사태깅 pos_tag 후 -> ne_chunk 개체명인식
    sentence = pos_tag(word_tokenize(sentence))
    print(sentence)
    
    # 개체명 인식
    sentence = ne_chunk(sentence)
    print(sentence)
    

     

    결과

    # [('Mike', 'NNP'), ('is', 'VBZ'), ('working', 'VBG'), 
    # ('at', 'IN'), ('IT', 'NNP'), ('Centre', 'NNP')]
    # (S
    #   (GPE Mike/NNP)
    #   is/VBZ
    #   working/VBG
    #   at/IN
    #   (ORGANIZATION IT/NNP Centre/NNP))

     

     

     

     

     

    ○ 몇 가지 기능 살펴보기

     

    1. nltk.Text()

     

    nltk.Text()는 자연어 데이터의 탐색을 편리하게 해주는 다양한 기능들을 제공합니다.

    import nltk
    from nltk.corpus import gutenberg
    from nltk import regexp_tokenize
    
    f = gutenberg.fileids()
    doc_en = gutenberg.open('austen-emma.txt').read()
    
    pattern = r'''(?x) ([A-Z]\.)+ | \w+(-\w+)* | \$?\d+(\.\d+)?%? | \.\.\. | [][.,;"'?():-_`]'''
    tokens_en = regexp_tokenize(doc_en, pattern)
    
    en = nltk.Text(toekns_en)

     

    테스트를 하기 위해 NLTK에서 제공하는 제인오스틴의 소설 Emma데이터를 다운받습니다. 이후 문서를 토큰으로 나누는 작업을 해주었는데 한국어를 토크나이즈하거나 품사태깅, 개체명 태깅 등을 할 때는 KoNLPy를 이용하는 것이 훨씬 낫다고 봅니다.

    2020/01/28 - [SW개발/Framework Library] - [파이썬패키지] 자연어 처리를 위한 패키지1 - KoNLPy

    예를 들어 NLTK에서 '나는 바보다'라는 문장에서 '바보다'라는 토큰의 개체명을 'Organization'으로 인식하는 등의 문제가 있습니다. 그래서 한국어 처리를 할 때에는 nltk를 데이터를 탐색하는 용도로 많이 사용하는 듯 합니다.

     

     

    2. 그래프 그리기

     

    en.plot(50) 

    en문서의 50개의 토큰만 플롯으로 그려보았습니다.

     


    en.dispersion_plot(['Emma','Frank','Jane'])

     


     

     

     

     

     

     

     

    3. 문서 탐색

     

    print(len(en.tokens)) # 토큰의 개수 확인
    print(len(set(en.tokens))) # Unique 토큰의 개수 확인
    en.vocab() # Frequency Distribution 확인
    print(en.count('Emma')) # 'Emma'의 개수
    en.concordance('Emma', lines=5) # 'Emma'가 들어있는 5개의 문장만 출력
    en.similar('Emma')
    en.similar('Frank') # 비슷한 단어 찾기
    > 결과
    
    > 191061
    > 7927
    > FreqDist({',': 12018, '.': 8853, 'to': 5127, 'the': 4844, 'and': 4653, 'of': 4278, '"': 4187, 'I': 3177, 'a': 3000, 'was': 2385, ...})
    > 865
    > Displaying 5 of 865 matches:
                                         Emma by Jane Austen 1816 ] VOLUME I CHAPT
                                         Emma Woodhouse , handsome , clever , and
    both daughters , but particularly of Emma . Between them it was more the int
     friend very mutually attached , and Emma doing just what she liked ; highly e
    r own . The real evils , indeed , of Emma situation were the power of havi
    > she it he i harriet you her jane him that me and all they them there herself was hartfield be
    mr mrs emma harriet you it her she he him hartfield them jane that isabella all herself look i me

     

    그래프를 그리는 것 외에도 토큰의 개수나 frequency distribution등을 확인하여 데이터의 구조를 살펴보는데 좋은 기능들도 많이 제공하고 있습니다.

     

     


    4. Chunking nltk.RegexParser()

     

    Chunking 얕은 구문 분석, 음성 및 단구 (명사구와 같은)를 식별하는 것

    tokens = "The little yellow dog barked at the Persian cat".split()
    tags_en = nltk.pos_tag(tokens)
    
    parser_en = nltk.RegexpParser("NP: {<DT>?<JJ>?<NN.*>*}")
    chunks_en = parser_en.parse(tags_en)
    chunks_en.draw()
    결과
    
    [('The', 'DT'),
     ('little', 'JJ'),
     ('yellow', 'NN'),
     ('dog', 'NN'),
     ('barked', 'VBD'),
     ('at', 'IN'),
     ('the', 'DT'),
     ('Persian', 'NNP'),
     ('cat', 'NN')]

     

     


    5. 워드클라우드 그리기

     

    import nltk
    ko = nltk.Text(tokens_ko, name='대한민국 국회 의안 제 1809890호')
    

     한국어 예제를 하나 불러옵니다.

     

    # 예제의 빈도분포(frequency distribution) 살펴보기
    
    print(ko.vocab())
    type(ko.vocab()) # 데이터타입, 속성목록 확인
    dir(ko.vocab()) # 예제문서의 단어사전 살펴보기
    
    data = ko.vocab().items()
    print(data)
    print(type(data)) # items()를 이용하면 빈도분포의 item 전체를 set형태로 확인 가능합니다.
    > 결과
    
    > FreqDist({'.': 61, '의': 46, '육아휴직': 38, '을': 34, '(': 27, ',': 26, '이': 26, ')': 26, '에': 24, '자': 24, ...})
    > nltk.probability.FreqDist
    > ['B',
     'N',
     ...
     'items',
     ...
     'pop',
     'popitem',
     'pprint',
     'r_Nr',
     'setdefault',
     'subtract',
     'tabulate',
     'unicode_repr',
     'update',
     'values']
     
     > dict_items([('명', 5), ('예상된', 3), ('하나', 1), ('11', 2), ('팀', 2), ...])
    <class 'dict_items'>

    데이터 탐색@@

     

    import csv
    with open('words.csv', 'w', encoding='utf-8') as f:
        f.write('word,freq\n')
        writer = csv.writer(f)
        writer.writerows(data)

    탐색한 데이터 set을 words.csv라는 파일에 저장하여 워드클라우드를 그리는데 이용하도록 하겠습니다.

     

    <!DOCTYPE html>
    <html>
    <head>
      <style>
        text:hover {
            stroke: black;
        }
      </style>
      <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
      <script src="d3.layout.cloud.js"></script>
    </head>
    <body>
      <div id="cloud"></div>
      <script type="text/javascript">
        var weight = 3,   // change me
            width = 960,
            height = 500;
    
        var fill = d3.scale.category20();
        d3.csv("words.csv", function(d) {
            return {
              text: d.word,
              size: +d.freq*weight
            }
          },
          function(data) {
            d3.layout.cloud().size([width, height]).words(data)
              //.rotate(function() { return ~~(Math.random() * 2) * 90; })
              .rotate(0)
              .font("Impact")
              .fontSize(function(d) { return d.size; })
              .on("end", draw)
              .start();
    
            function draw(words) {
              d3.select("#cloud").append("svg")
                  .attr("width", width)
                  .attr("height", height)
                .append("g")
                  .attr("transform", "translate(" + width/2 + "," + height/2 + ")")
                .selectAll("text")
                  .data(words)
                .enter().append("text")
                  .style("font-size", function(d) { return d.size + "px"; })
                  .style("font-family", "Impact")
                  .style("fill", function(d, i) { return fill(i); })
                  .attr("text-anchor", "middle")
                  .attr("transform", function(d) {
                    return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
                  })
                .text(function(d) { return d.text; });
            }
          });
      </script>
    </body>
    </html>

    위 코드를 index.html로 저장하고 words.csv가 있는 폴더내에 저장합니다.

     

    python -m http.server 8888 

    그리고 프롬프트웨 위 명령어를 입력하여 실행시켜준 뒤, http://localhost:8888로 접속하면,

     

    생성된 워드클라우드를 확인할 수 있습니다.

     

     


     

    자연어처리를 위한 파이썬 패키지 시리즈

    KoNLPy 데이터 전처리

    2020/01/28 - [SW개발/Framework Library] - [파이썬패키지] 자연어 처리를 위한 패키지1 - KoNLPy로 데이터 전처리

    NLTK 데이터 탐색

    2020/01/31 - [SW개발/Framework Library] - [파이썬패키지] 자연어 처리를 위한 패키지2 - NLTK로 데이터 탐색

    Gensim 토픽 모델링

    2020/02/17 - [SW개발/Framework Library] - [파이썬패키지] 자연어 처리를 위한 패키지3 - Gensim의 Word2Vec으로 토픽모델링

     

     


     

     

    ** 아래 링크가 사라졌네요.. 이 포스팅은 lucy park 님의 글을 따라해보며 정리한 글입니다.

    한국어와 NLTK, Gensim의 만남 (Lucy Park)

    참고 문서 : https://datascienceschool.net/view-notebook/8895b16a141749a9bb381007d52721c1/

    댓글

Designed by Tistory.