본문으로 바로가기

제가 S/W나 H/W 혹은 인터넷에서 본 재미있는 아이들을 소개한 적도 있지만, 가끔 인물 자체를 -그것도 잘 알지도 못하면서- 소개한 적이 있습니다. 예를 들면, 많은 글을 적진 않으셨지만, MATLAB에 대해 재미난 글이 많은 theta님이 있었구요... 그리고 최근에는 대한민국 지도를 그릴때 소개해 드린, 혜식님도 있었습니다. 그리고 오늘 또 한 분의 고수를 소개해 드릴까합니다. 사실 이 분은 제 블로그에서 한 번 출연(^^)을 하셨었습니다. 바로 서울시 범죄 현황을 분석하던 글[바로라기]에서 folium으로 지도를 표현할 때 서울시 구별 경계선 데이터를 얻어왔던 한국 지도 데이터가 있던 github[바로가기]을 운영하시던 분 e9t라는 분인데요... 오늘 소개해 드릴 Lucy Park이라는 분입니다.

한글 자연어 처리 부분에 대한 자료를 처음 뒤지던 때~~ 저에게 보인 논문한 편이 있었지요^^

바로 위 논문입니다. KoNLPy : 쉽고 간결한 한국어 정보처리 파이썬 패키지라는 좀 멋져보이는 제목의 논문이었지요^^

그 논문 중에 KoNLPy의 설계 철학으로 쉽고 간단한 사용법, 확장성, 상세한 문서, 개방과 공유를 언급하고 있었습니다. 이것도 멋져보이더라구요^^ 그래서 전... KoNLPy도 공부하고~~~ 그리고 Lucy Park이라는 분도 알게되었지요(뭐 직접 만난적은 한 번도 없습니다. 그저... 인터넷에 공개된 자료만 읽었다는...^^ 소심하게... 팬~이라고 말씀드리고 싶습니다.^^)

일단.. Lucy Park님의 PPT자료 하나 소개합니다. PyCon Korea 2014에 발표된 자료로 KoNLPy를 소개하고 있습니다. [바로가기]

거기서는 KoNLPy를 소개하고

역시 본인도 소개를 하고 있으십니다~^^

자연어 처리에서의 기본적 개념에 대해 이야기를 하고 있구요~

형태소~라는 아이의 개념을 이야기해주고 있습니다.

위 홈페이지는 Lucy Park님의 개인 홈페이지[바로가기]입니다.

그리고 최근 업데이트가 되고 있진 않은듯 하지만, 대한민국 정치의 모든 것이라는 사이트[바로가기]의 운영진 중 한 분 입니다.

이제 Lucy Park님 이야기는 그만하고... KoNLPy 데리고 논것 이야기 해야죠~~

문장(sentences), 명사(nouns), 형태소(pos) 분석 결과를 바로 한 번 테스트 해보았습니다.

이번엔 한나눔으로~~

이번엔... '메리가 좋다', '고양이도 좋다', '난 수업이 지루하다', '메리는 이쁜 고양이야', '난 마치고 메리랑 놀거야' 등으로 형태소 분석을 해보았습니다.^^ 각각에 대해 positive한지 negative한지 알려주구요...

그리고.. list안의 list를 하나의 list로 만들어주고~

훈련(train)시키고~~~ 비록 문장 4개지만~^^

'난 수업이 마치면 메리랑 놀거야'라는 문장이 긍정적인지 부정적인지 확인하죠^^ 이때 사용하는 분류기(Classifier)는 NLTK가 제공해주는 Naive Bayes 방법을 사용합니다. ^^

흠... '난'이 있을때 부정적이고, '메리'가 없을 때 부정적이군요~^^

아무튼~~~

훈련때랑 동일과정을 슬~쩍 거쳐보면~

아하... 수업 마치고 메리랑 놀겠다는건 긍정적이네요^^ 뭐 예시는 허접하지만.. 여하튼 오늘은 Lucy Park이라는 미모의 개발자께서 만들어주신 한글 자연어 처리기인 KoNLPy와 자연어 처리에서 유명한 Python 모듈인 NLTK를 사용해서 형태소 분석을 하고, NLTK의 Naive Bayes Classifier를 사용해서 긍정/부정에 대한 분류를 해보았습니다.^^ 킁킁.. 재미있죵^^


댓글을 달아 주세요

  1. BlogIcon 『방쌤』 2017.05.23 14:07 신고

    하하핫,,,,^^;;

    날씨가 많이 덥네요~
    건강 챙기시는 그런 행복한 하루 보내세요!

  2. BlogIcon pennpenn 2017.05.24 07:19 신고

    제목과 내용이 너무 전문가 수준이어서
    컴맹인 저로서는 쇠귀에 경읽기입니다.
    ㅎ ㅎ

    전국적으로 미세먼지가 없는 깨끗한 날입니다.
    수요일을 잘 보내세요.

  3. BlogIcon 봉리브르 2017.05.24 07:40 신고

    재미있는 시간을 보내셨군요.
    여느사람들은 어렵기만 할 것 같은데요..ㅎㅎ

  4. BlogIcon GeniusJW 2017.05.24 10:05 신고

    자연어 처리할 때 사용하는 파이썬 소개 잘 보았습니다~~ㅋㅋ
    우리는 무의식 적으로 사용하는 걸 기계들이 학습하는 방식이 달라 생소하네요~~

  5. 빡공 2017.11.14 13:36 신고

    안녕하세요. 블로그를 보고 우연히 따라하다가 보니 코드에 train쓰는 부분에서 에러가 납니다.
    train부분이 정의되어 있지 않다고 하는데요. 혹시 방법이 있을까요? 코드가 일부로 보여집니다. ln171부터요

    • BlogIcon PinkWink 2017.11.14 14:59 신고

      아이쿠~ 예제 문장을 주지 않았네요..ㅜㅜ
      아래와 같은 입력이 먼저 들어가야 합니다.

      from konlpy.tag import Twitter
      pos_tagger = Twitter()

      train = [('메리가 좋아', 'pos'),
      ('고양이도 좋아', 'pos'),
      ('난 수업이 지루해', 'neg'),
      ('메리는 이쁜 고양이야', 'pos'),
      ('난 마치고 메리랑 놀거야', 'pos')]

  6. BlogIcon 일 상 생 활 2017.12.10 10:16 신고

    댓글 감사합니다. 댓글 적는게 여기 있는지 몰라서 다른곳에다 여쭤봤네요. ㅎㅎ

    • BlogIcon PinkWink 2017.12.11 10:14 신고

      아닙니다.. 사실 크게 상관없지만, 그래도 약간 관련있는 글들을 모을려는 작은 시도(^^)로 생각해 주세요^^

    • 일 상 생 활 2017.12.11 10:30 신고

      감사합니다.
      블로그를 보고 많이 배워갑니다.^^
      아직은 많이 미숙하지만..
      쬐끔 감을 잡았습니다.^^

    • BlogIcon PinkWink 2017.12.11 11:12 신고

      매우 핫~ 한 분야라서 은근 원하는 분들이 많은것 같아요.. 오프라인 모임도 많이들 하시는 것 같던데요..^^

  7. BlogIcon 일 상 생 활 2017.12.11 18:18 신고

    안녕하세요. 금일 또 이렇게 문의드리네요 ㅜㅜ
    다름이 아니오라 혹시 소스 185번에서 단어의 카운도 뽑아 낼수 있는지 해서 문의드립니다.
    이를테면
    난/Noun [1]
    수업/Noun [2]
    이/Josa [3]
    마치/Noun [4]
    면/Josa [5]
    메리/Noun [6]
    랑/Josa [7]
    놀다/Verb [8]

    test_sentence 에서 던진 단어의 카운터를 뺄수 있는지 궁금합니다.
    죄송하지만 조언 부탁드립니다.
    감사합니다.

  8. 일 상 생 활 2017.12.14 10:50 신고

    안녕하세요. 금일 또 문의를 매번 번거롭게 해 드려 죄송합니다.
    궁금한 사항이 있는데요.
    test_sentence에 train_data에서 교육을 안 시킨 문장을 입력하면 neg로 나오는게 맞지 않나싶어서요. 문장을 입력을 안해도 무조건 print(classifier.classify(test_sent_features)) 이 부분에서 pos로 떨어지더라구요..

    제가 테스트를
    test_sentence = '강아지'
    test_docs = tokenize(test_sentence)
    # print(test_docs)
    test_sent_features = {word: (word in tokens) for word in test_docs}
    print(test_sent_features)
    print(classifier.classify(test_sent_features))

    이렇게 해 놓고 결과 값을 보면
    [(['메리/Noun', '가/Josa', '좋다/Adjective'], 'pos'), (['고양이/Noun', '도/Josa', '좋다/Adjective'], 'pos'), (['난/Noun', '수업/Noun', '이/Josa', '지루하다/Adjective'], 'neg'), (['메리/Noun', '는/Josa', '이쁘다/Adjective', '고양이/Noun', '야/Josa'], 'pos'), (['난/Noun', '마치/Noun', '고/Josa', '메리/Noun', '랑/Josa', '놀다/Verb'], 'pos')]
    <----------------------------------------------------------------------------->
    {'강아지/Noun': False}
    pos

    이렇게 나오는데 제가 이해를 잘 못해서요. 강아라라는 단어를 교육을 안 시켰으면 neg로 나와야 하는게 아닌가 싶어서 이렇게 문의를 드립니다. 매번 이렇게 문의만 드려 죄송합니다. 많은 조언 부탁드립니다. 감사합니다.

    • BlogIcon PinkWink 2017.12.14 13:02 신고

      형태소 분석을 하고.. 난 후 조각난 형태소를 확률로 계산하는 것입니다.
      문장에서 한 번도 나타나지 않은 한 단어로 된 문장에 대한 결과는 neg일 수도 pos일 수도.. 뭐가 나타나도 이상하지 않을 것 같아요...
      보다 많은 문장을 주시면.. 더 재미있는 결과를 얻을 수 있을 겁니다.

    • 일 상 생 활 2017.12.14 18:01 신고

      그럼 학습데이터를 많이 넣으면 좋은건가요??? 그리고 test_sentence에 문장을 많이 주면 되는거지요??? 말씀하신데로 열심히 한번 돌려 보겠습니다.

      여기다 계속 도배하는 느낌이라 문의 드리는것도 이제는 죄송스럽네요..

      지금 제가 하고 있는 테스트는
      test_sentence = '무궁화 꽃이 피웠습니다. 우리나라 꽃은 무궁화'

      즉 test_sentence의 단어의 카운터를 집계하려 합니다. 일전에 알려주신 방법으로 카운터는 집계가 되었으나 조금 더 병합을 하고 싶어서 이리저리 알아보고 해 보는데도 오류가 나서 또 ㅜㅜ 한번 문의 드립니다. 이러면 안되는데 혼자서 하다보니 물어볼 사람도 없고 아는 사람도 없어서 이렇게 자꾸 문의를 드리네요. 다시 한번 죄송하다는 말씀 드립니다.

      test_sentence = '무궁화 꽃이 피웠습니다. 우리나라 꽃은 무궁화'
      test_docs = tokenize(test_sentence)
      # print(test_docs)
      test_sent_features = {word: (word in tokens) for word in test_docs}

      tokens_ko = Counter(test_docs)
      tags2 = tokens_ko.most_common()

      print(tags2)
      print(test_sent_features)
      # print(classifier.classify(test_sent_features))

      [('무궁화/Noun', 2), ('꽃/Noun', 2), ('이/Josa', 1), ('피우다/Verb', 1), ('./Punctuation', 1), ('우리나라/Noun', 1), ('은/Josa', 1)]
      {'무궁화/Noun': False, '꽃/Noun': False, '이/Josa': True, '피우다/Verb': False, './Punctuation': False, '우리나라/Noun': False, '은/Josa': False}

      결과값은 위와 같은데 제가 하고 싶은것은 {'무궁화/None': False, 2, '꽃/None': False, 2, '이/Josa': True, 1, '피우다/Verb': False, '1, ./Punctuation': False, 1, '우리나라/Noun': False, 1, '은/Josa': False, 1}

      이렇게 출력하고 싶은데
      타입때문에 잘 안되더라구요.
      딕셔너리에서 리스트로, 리스트에서 딕셔너리로, 듀플에서 딕셔리리로 여러가지 방법으로 해 보았지만 합치기가 힘들더라구요. 죄송합니다. 자꾸만 문의만 드려서... 조금이나마 작은 도움을 주시면 감사하겠습니다. 감사합니다.

    • BlogIcon PinkWink 2017.12.15 11:42 신고

      T/F가 붙어 나오는건 NaiveBayesClassifier가 동작한 후 입니다. 그 후 데이터를 편집을 하시면 될 것 같긴 하네요... 저는 그렇게 안해서... 당장 생각나는 건 없습니다ㅠㅠ.
      그러나 약간 글 초반의 느낌을 본다면... 이 영역은 바로 결과를 얻으려 하시지 말고 초반 지식과 파이썬 문법에 대한 이해가 약간 선행되어야 할 듯 합니다. 그게 향후 접근하시는데 더 유리할 듯 합니다.^^

    • 일 상 생 활 2017.12.18 16:07 신고

      감사합니다.
      머리 좀 굴리고 굴려 아는 지인한데 힌트 받아 구현이 완료되었습니다.
      하고 싶었던것은 sent에 던진 문장들에 대해 긍정,부정 및 단어의 카운트를 집계를 하려 했습니다. 모쪼록 많은 도움을 얻었습니다. ^^

    • BlogIcon PinkWink 2017.12.18 20:08 신고

      네 도움이 되지는 못했지만, 그래도 성과를 얻으셨다니 다행입니다. 화이팅입니다^^

  9. 도롱도롱 2018.09.03 21:07 신고

    안녕하세요~ 좋은 글 감사합니다! 다름이 아니라, konlpy를 이용하여 한글 텍스트를 이용해 워드클라우드를 만들고 싶다면 konlpy을 이용해 단어들을 쪼개고 그것을 워드클라우드 모듈에 넣으면 되는건가요? 혼자 공부하는 데에 어려움이 있어 질문 드립니다 ㅠㅠ 감사합니다!

    • BlogIcon PinkWink 2018.09.04 17:21 신고

      그냥 워드클라우드가 목적이라면 wordcloud 모듈에 텍스트를 직접 넣으셔도 됩니다. 이 글에서 하고 있듯이요.

  10. BlogIcon 술퍼맨 2018.09.20 16:50 신고

    정말 많은 공부가 되었습니다.

    근데, classifier에 test sentence를 뭘 집어넣어도 결과는 pos가 나오구요.. 학습데이터에서 neg로 되어 있는 문장을 넣어도 결과는 pos만 나와요.

    보니까, 학습을 시킬때는 term_exists() 함수를 통해서 'exists' 문자열이 포함되는데.. classify 할때는 그 문자열이 없는 것으로 들어가서 그랬던 것 같습니다.

    def term_exists(doc):
    # return {'exists({})'.format(word): (word in set(doc)) for word in tokens}
    return {'{}'.format(word): (word in set(doc)) for word in tokens}

    요렇게 바꾸니까 neg/pos를 잘 잡아내는 것 같습니다.

    감사합니다.