ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Text 전처리(preprocessing)- korean 한글편
    Text Analysis 2021. 11. 24. 18:15

    *본 게시물은 21-2학기 연세대학교 일반대학원 온라인데이터수집과분석(이상엽 교수님) 수업 내용을 정리한 것입니다.

     

      드디어 한글 전처리입니다.

      앞서 영어는 단어가 token이 된다고 했습니다. 때문에 띄어쓰기를 기준으로 간단하게 토크나이징을 할 수 있었는데요, 한글은 다릅니다 ㅠ_ㅠ 한글은 '형태소'를 단위로 하기 때문입니다.

      학창시절 배우셨듯이 한국어는 교착어적 특성을 가집니다. 즉 조사, 어미가 붙어 다양한 곡용, 활용이 이루어집니다. 때문에 tokenizing을 위해서는 이 조사, 어미까지 고려하는 tokenization이 필요합니다. 가령 '나는 티스토리에 글을 쓴다'라는 문장의 경우, '나, 는, 티스토리, 에, 글, 을, 쓰, ㄴ다'와 같이 조사, 어미까지 분리하는 토크나이징이 이루어지게 됩니다.  

     

      한글 전처리 단계도 실은 영어와 비슷합니다. 다만 영어의 '토크나이징, 품사 찾기, 원형찾기'가 한번에 이루어집니다. 또한 한글 전처리의 결과물도 역시 '불용어가 제거된, 최종 분석에서 사용하고자 하는 품사의 단어'가 됩니다. 

    단계 설명 konlpy 예시
    1. 정제
    (cleaning)
    불필요한 기호(! . ' " ;...), 표현 제거 .replace('!', '')
    re.sub('[^\w\d\s]','',content)
    2. 형태소 분석
      (토크나이징
       +품사 태깅
       + 원형 찾기)
    형태소 분석기가 텍스트 어절 단위 분리, 어절 내 형태소 인식 및 품사 태깅, 원형 복원을 해주기 때문에 한번에 가능
    1) 토큰화: 형태소 기준으로 토크나이징
    2) 품사 태깅: .pos()로 가능
    3) 원형 찾기: 파라미터 중 stem으로 가능 
    5개의 형태소 분석기 존재
    주로 Okt, mecab, komoran 사용 
    (형태소 사전이 자주 업데이트 되기 때문)

    twitter= konlpy.tag.Twitter()
    twitter_morphs = twitter.pos(filtered_content, stem=True, norm=True)
    3. 원하는 품사만 찾기 원하는 품사의 단어들만 선택할 경우 분석 결과의 정확도가 향상됨 Noun_words = twitter.nouns(filtered_content) 
    4. 불용어 제거 한국어는 기본 불용어 사전이 없음
    stopwords = ['연합뉴스', '네이버', '기자'] #리스트로 만들어줌 
    unique_Noun_words = set(Noun_words)
    for word in unique_Noun_words:
        if word in stopwords:
            while word in Noun_words: Noun_words.remove(word)

     

      확실히 영어보다는 짧지만 복잡하다는 느낌이 듭니다 ^^;;ㅋㅋ 이 위의 단계들을 실제 코드로 보면 다음과 같습니다.

     

    한글 text 전처리 코드

      일단 필요한 모듈과 text 데이터를 불러오겠습니다. 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    !pip install konlpy
     
    # 잘 import 되었는지 test
    import konlpy
    import konlpy.tag # 하위 모듈 임포트
    import re #정규식 모듈 임포트
    text = '오늘은 금요일'
    komoran = konlpy.tag.Komoran()
    komoran.pos(text) # [('오늘', 'NNG'), ('은', 'JX'), ('금요일', 'NNP')]
     
     
    # 텍스트 불러오기
    with open('naver_news.txt''r', encoding='utf8'as f:
        content = f.read() # 기사가 raw한 상태, 전처리 해야 함 
    print(content)
    '''
    北, 단계적 조치 요구…美, 이행기간 압축한 '큰 거래' 원해 폼페이오·볼턴...
    '''
    cs

     

      첫 번째로는 일단 영어와 같이. 1. 정제(cleaning)를 거쳐야 합니다. 

    1
    2
    3
    4
    5
    6
    7
    # 1. Text cleaning: re.sub로 불필요한 기호 삭제
     
    filtered_content = re.sub('[^\s\w\d]',' ', content)
    print(filtered_content)
    '''
    北  단계적 조치 요구 美  이행기간 압축한  큰 거래  원해 폼페이오 볼턴
    '''
    cs

      정규식을 활용하여 정제가 이루어졌습니다. 다음은 많은 것들을 해치우는 단계인 2. 형태소 분석 입니다.

     

    2. 형태소 분석에서는 형태소 분석기를 통해 단어의 어절에서 1) 형태소를 찾고(토크나이징), 3) stemming을 하고, 그리고 2) 품사 태깅이 이루어집니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 2. konlpy를 사용한 형태소 분석 시작 
    # Twitter has changed to Okt since 0.4.5
     
    twitter= konlpy.tag.Twitter()
    twitter_morphs = twitter.pos(filtered_content, stem=True, norm=True# 보편적으로 True
    # 트위터의 pos 펑션을 통해 형태소 분석 가능, 불필요한 기호가 삭제된 txt를 인자로 입력 
    # 파라미터 중 스템: 동사, 형용사의 원형을 찾아줌, norm: ㅋㅋㅋㅋ 이런 것들에 대해 ㅋㅋㅋ으로 치환
    print(twitter_morphs)# 결과가 영어 txt에 대해 pos 태깅을 한 것 과 거의 비슷하게 나옴
     
    '''
    [('', 'Foreign'), ('단계', 'Noun'), ('', 'Suffix'), ('조치', 'Noun')
    '''
    # 형태소 분석의 결과물 = 리스트 데이터, 리스트가 가진 원소가 하나의 튜플, 튜플 안 2개 원소는 형태소-품사 태그로 구성
    cs

    주석에서도 보시다시피 트위터 형태소 분석기가 Okt라는 이름으로 변경되었습니다. okt = konlpy.tag.Okt()로 쓰기도 합니다. 위의 코드에서는 1) 토크나이징을 하는 .pos(), 3) stemming을 하는 stem=True, 그리고 2) 품사 태깅 결과 역시 확인할 수 있습니다. 이처럼 형태소 분석 결과물은 리스트로 반환되며, 리스트 안의 각 원소는 튜플('형태소', '품사태그')로 반환되기도 합니다.

    (혹은 그냥 리스트 안에 형태소들이 원소로 나열되어 있는 형태도 있습니다.)

     

      형태소 분석이 끝났으면 연구 문제 해결을 위해 필요한 최종 분석과 관련된 특정 품사들의 단어를 뽑아야 합니다. 3. 즉 품사별 형태소 찾기를 진행하게 됩니다. 

    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
    # 3. 빈도 분석을 위한 특정 품사만 선택하기 
     
    # 3.1. 명사만 추출하고자 하는 경우: 형태소 분석기 function 사용
    Noun_words = twitter.nouns(filtered_content) # nouns라는 funciton 사용 시 명사만 골라짐 
    print(Noun_words)
    '''
    ['단계', '조치', '요구', '이행', '기간', '압축', '거래', '폼페이', '', '볼턴'...]
    '''
     
    # 3.2. 제어문과 .append()를 통해 원하는 품사 골라담기
    # 명사만 담고 싶을 때? nouns라는 펑션이 있기 때문에 제어문을 사용하지 않아도 괜찮긴 함
    #Featured_POS = ['Noun']#명사만 고를 때
     
    #명사, 동사, 형용사를 담고 싶을 때
    Featured_POS = ['Noun''Verb''Adjective'
    selected_words = []
    for word, pos in twitter_morphs:
        if pos in Featured_POS:
            selected_words.append(word)
    print(selected_words)
     
    # 동사만을 고를 때
    Verb_words = []
    for word, pos in twitter_morphs:
        if pos == 'Verb':
            Verb_words.append(word)
    print(Verb_words)
    cs

     

      원하는 품사 골라담기까지 했으면 4. 불용어 제거도 해야 합니다. 내가 원하는 품사 안에도 불용어가 존재할 수 있기 때문입니다(밑의 예시의 연합뉴스, 네이버, 기자 등은 기사에서 별로 중요하지 않은 정보를 담고 있으나 빈도가 매우 높은 단어들입니다)

    한국어는 nltk 혹은 konlpy에 별도의 불용어 사전이 없으므로, customize해서 사용해야 합니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 4. 불용어 제거를 위한 별도의 사전 (list 변수) 구축
    # konlpy는 기본 불용어 사전이 없으므로 따로 사전을 만들어줘야함 
     
    stopwords = ['연합뉴스''네이버''기자'#리스트로 만들어줌 
    unique_Noun_words = set(Noun_words)
    for word in unique_Noun_words:
        if word in stopwords:
            while word in Noun_words: Noun_words.remove(word)
     
     
    # 1음절의 단어 없애기: 많은 경우에 불용어로 간주: 왜냐면 주로 조사들이 1음절... 
    final_words = [word for word in Noun_words if len(word)>1]
    cs

     

      영어에서도 그랬던 것처럼 이렇게 전처리 과정을 거쳐 특정 품사만 모아진 데이터들은 빈도분석에 활용할 수 있습니다. 빈도분석은 Counter를 사용합니다. 

    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
    from collections import Counter #Counter로 본격적으로 빈도 세기 
     
    #Counter로 빈도 세기
    = Counter(final_words)
    print(c)
    '''
    Counter({'북한': 27, '미국': 13, '비핵화': 12, '이행': 9...})
    '''
     
    print(c.most_common(10))
    '''
    [('북한', 27), ('미국', 13), ('비핵화', 12), ('이행', 9),..)]
    '''
     
    # 빈도 정보를 바탕으로 워드클라우드 그리기
    from wordcloud import WordCloud
    import matplotlib.pyplot as plt
    from os import path
     
    FONT_PATH = '/content/malgun.ttf' # For Korean characters: 한글 폰트가 깨질 경우 사용
     
    noun_text = ' '.join(final_words) # 리스트를 문자열로 만들어줌 
     
    wordcloud = WordCloud(max_font_size=60, relative_scaling=.5, font_path=FONT_PATH)
    wordcloud.generate(noun_text) # generate() 는 하나의 string value를 입력 받음
    plt.figure()
    plt.imshow(wordcloud, interpolation='bilinear')
    plt.axis("off")
    plt.show()
     
     
    # 에러 발생?
    # OSError: cannot open resource  >>>>>> 한글 폰트가 적용이 안되서임
    cs

     

    미등록 단어(OOV; Out Of Vocabulary) 문제

      그런데 여기까지 오다보니 드는 의문점들이 있습니다.

      형태소 분석에는 형태소 분석기들이 가진 형태소 사전을 사용한다고 했습니다. 그렇다면 신조어, 고유명사, 전문용어 등은 어떻게 처리해야 할까요? 실제로 이러한 종류의 단어들에 아무런 처리를 하지 않을 경우 형태소 분석이 잘못되는 등의 Out Of Vocabulary 문제가 발생합니다.

      즉, 사전 안에 단어가 등록되어 있지 않기 때문에 올바르게 토큰으로 분석되지 않는 문제를 말합니다. 이 문제를 해결하지 않을 경우 형태소 분석 오류가 높아져 텍스트 분석 결과의 정확도가 낮아집니다. 특히 키워드 분석, 네트워크 분석에서 치명적입니다.

      이를 해결하기 위해서는 customized_konlpy 모듈을 사용합니다. 이후에 불용어 처리와는 반대로, 미등록 단어를 사전에 추가한 후 형태소 분석을 진행하게 됩니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    # customized_konlpy (ckonlpy)를 사용해서 새로운 단어 추가하기
    # 원래 konlpy 가지고는 하기가 힘듦, 추가로 customized_konlpy 사용
    !pip install customized_konlpy
     
    from ckonlpy.tag import Twitter
     
    twitter = Twitter() # 객체 만들기
    twitter.add_dictionary('파이콘''Noun'# Add a new word to the dictionary temporarily 
    # 즉 이 주피터 노트북 안에서만 일시적으로 허용하는 것, 영구하지 않음
    # 인자는 넣고자 하는 단어/단어 리스트, 품사 2가지를 넣어야 함 
    print(twitter.pos(text1))
    '''
    [('파이콘', 'Noun'), ('', 'Josa'),..]
    '''
     
    #한번에 여러 단어 추가하기
    # 인자는 넣고자 하는 단어/단어 리스트, 품사 2가지를 넣어야 함 
    twitter.add_dictionary(['파이콘','최순실'], 'Noun')
    twitter.pos(text2)
    '''
    [('최순실', 'Noun'), ('국정', 'Noun'), ('농단', 'Noun')]
    '''
    cs

     

     

    'Text Analysis' 카테고리의 다른 글

    빈도 분석(frequency analysis)- 영어편  (0) 2021.11.24
    Text 전처리(preprocessing)- english 영어편  (0) 2021.11.24
    Text Analysis의 시작  (0) 2021.11.23

    댓글

Designed by Tistory.