[NLP] 한글을 다양하게 조작해보기

2023. 11. 12. 14:51Developers 공간 [Shorts]/Vision & Audio

728x90
반응형
<분류>
A. 수단
- OS/Platform/Tool : Linux, Kubernetes(k8s), Docker, AWS
- Package Manager : node.js, yarn, brew, 
- Compiler/Transpillar : React, Nvcc, gcc/g++, Babel, Flutter

- Module Bundler  : React, Webpack, Parcel

B. 언어
- C/C++, python, Javacsript, Typescript, Go-Lang, CUDA, Dart, HTML/CSS

C. 라이브러리 및 프레임워크 및 SDK
- OpenCV, OpenCL, FastAPI, PyTorch, Tensorflow, Nsight

 


1. What? (현상)

 

이번 글에서는 데이터를 다룰 때 한글을 다양하게 조작하는 방법을 정리해보고자 합니다.

 

다뤄보려는 방법은 아래 3가지 입니다. 

  • 풀어쓰기 : 한글을 자소단위로 풀어쓰는 방법입니다.
  • 모아쓰기 : 자소단위로 풀어져있는 한글을 모아쓰기 하는 방법입니다.
  • G2P(Grapheme to Phoneme) : 한글 자소를 음소로 바꿔주는 모델입니다. 즉, 발음 모델로 바꿔주는 방법입니다.

2. Why? (원인)

  • X

3. How? (해결책)

시작하기 전에 한글인지 확인하는 함수를 먼저 확인하겠습니다.

def isHangeul(one_character):
    return 0xAC00 <= ord(one_character[:1]) <= 0xD7A3

 

위 결과를 아래와 같이 실행해보고 결과를 보겠습니다.

print(isHangeul("한"))
print(isHangeul("2"))
True
False

 

1. 풀어쓰기

 

먼저, 한글을 풀어쓰는 함수를 보겠습니다. 해당코드는 다른 git자료(https://github.com/fd873630/RNN-Transducer/blob/master/model_rnnt/hangul.py)를 ㅊ팜조했으며, 아래 사용하는 함수들을 간단히 설명하면 아래와 같습니다.

  • ord() 함수 : 하나의 문자 → 유니코드 정수
    ex) ord('a') → 97
  • hex() 함수 : 10진수 값 → 16진수 값
    ex) hex(98) → 0x62
  • chr() 함수 : 하나의 정수 → 유니코드 문자
    ex) chr(97) → 'a'
chosung = ("ㄱ", "ㄲ", "ㄴ", "ㄷ", "ㄸ", "ㄹ", "ㅁ", "ㅂ", "ㅃ", "ㅅ", "ㅆ", "ㅇ", "ㅈ", "ㅉ", "ㅊ", "ㅋ", "ㅌ", "ㅍ", "ㅎ")
jungsung = ("ㅏ", "ㅐ", "ㅑ", "ㅒ", "ㅓ", "ㅔ", "ㅕ", "ㅖ", "ㅗ", "ㅘ", "ㅙ", "ㅚ", "ㅛ", "ㅜ", "ㅝ", "ㅞ", "ㅟ", "ㅠ", "ㅡ", "ㅢ", "ㅣ")
jongsung = ("", "ㄱ", "ㄲ", "ㄳ", "ㄴ", "ㄵ", "ㄶ", "ㄷ", "ㄹ", "ㄺ", "ㄻ", "ㄼ", "ㄽ", "ㄾ", "ㄿ", "ㅀ", "ㅁ", "ㅂ", "ㅄ", "ㅅ", "ㅆ", "ㅇ", "ㅈ", "ㅊ", "ㅋ", "ㅌ", "ㅍ", "ㅎ")

def hangeulExplode(one_hangeul):
    a = one_hangeul[:1]
    if isHangeul(a) != True:
        return False
    b = ord(a) - 0xAC00
    cho = b // (21*28)
    jung = b % (21*28) // 28
    jong = b % 28
    if jong == 0:
        return (chosung[cho], jungsung[jung])
    else:
        return (chosung[cho], jungsung[jung], jongsung[jong])

def pureosseugi(inputtext):
    result = ""
    for i in inputtext:
        if isHangeul(i) == True:
            for j in hangeulExplode(i):
                result += j
        else:
            result += i
    return result

 

그럼 아래와 같이 실행해보고 결과를 확인해보겠습니다.

sentence = "모르는 것이 낫다고"
result = pureosseugi(sentence)
print(result)
ㅁㅗㄹㅡㄴㅡㄴ ㄱㅓㅅㅇㅣ ㄴㅏㅅㄷㅏㄱㅗ

 

2. 모아쓰기

 

이번엔 반대로 한글을 모아쓰는 함수를 보겠습니다.

def hangeulJoin(inputlist):
    result = ""
    cho, jung, jong = 0, 0, 0
    inputlist.insert(0, "")
    while len(inputlist) > 1:
        if inputlist[-1] in jongsung:
            if inputlist[-2] in jungsung:
                jong = jongsung.index(inputlist.pop())
            else:
                result += inputlist.pop()
        elif inputlist[-1] in jungsung:
            if inputlist[-2] in chosung:
                jung = jungsung.index(inputlist.pop())
                cho = chosung.index(inputlist.pop())
                result += chr(0xAC00 + ((cho*21)+jung)*28+jong)
                cho, jung, jong = 0, 0, 0
            else:
                result += inputlist.pop()
        else:
            result += inputlist.pop()
    else:
        return result[::-1]

def moasseugi(inputtext):
    t1 = []
    for i in inputtext:
        t1.append(i)
    return hangeulJoin(t1)

 

그럼 아래와 같이 실행해보고 결과를 확인해보겠습니다.

sentence = "ㅁㅗㄹㅡㄴㅡㄴ ㄱㅓㅅㅇㅣ ㄴㅏㅅㄷㅏㄱㅗ"
result = moasseugi(sentence)
print(result)
모르는 것이 낫다고

 

3. Graphemes to Phonemes

 

먼저 설치해보곘습니다. 관련된 자료는 g2pk라는 패키지의 자료(https://github.com/Kyubyong/g2pK)를 참조하시면 좋습니다.

pip3 install nltk g2pk

 

그럼 아래와 같이 실행해보고 결과를 확인해보겠습니다.

from g2pk import G2p
g2p = G2p()
result = g2p("어제는 날씨가 맑았는데, 오늘은 흐리다.")
print(result)
어제는 날씨가 말간는데, 오느른 흐리다.

https://blockdmask.tistory.com/544

728x90
반응형