ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 1-2. 한국어 띄어쓰기 구현 - N-Gram
    프로젝트/NLP Core 2019. 3. 29. 15:01

    2-1. N-Gram(Bi-Gram)

    N-Gram : 카운트에 기반한 통계적 모델, 영어는 보통 단어 단위로 자르고 한국어는 음절 단위로 자른다.

    N은 자르는 개수인데, N = 1이면 UniGram 2이면 BiGram 3이면 TriGram이라고 부른다. 여기서는 BiGram으로 구현하였다. 확장된 음절 bigram을 이용한 자동 띄어쓰기시스템(강승식) 논문을 참고하여 아래처럼 8가지 상태를 측정하였다.

    "가나" "가나 " "가 나" "가 나 " " 가나" " 가나 " " 가 나" " 가 나 "
    0 1 2 3 4 5 6 7
    def save_bigram(first, second, value):
        if bigram_dict.get(first + second) is None:
            list = np.zeros(8)
        else:
            list = bigram_dict[first + second]
        list[value] = list[value] + 1
        bigram_dict[first + second] = list
    
    
    def bigram(line):
        i = 0
        while i < len(line) - 2:
            j = i
            left, middle, right = False, False, False
    
            if line[j] == " ":
                j += 1
                left = True
            first = line[j]
    
            if j + 1 < len(line) - 1:
                if line[j + 1] == " ":
                    j += 1
                    middle = True
            else:
                break
            j += 1
            second = line[j]
    
            if j + 1 < len(line):
                if line[j + 1] == " " or line[j + 1] == "\n" or line[j + 1] == "\r":
                    right = True
            else:
                break
    
            save_bigram(first, second, count_dict_value(left, middle, right))
            i += 1

    이렇게 입력받은 모든 line에 대해 각 상태를 카운트해 Dictionary로 저장해둔다.
    Key = 두 음절(가나) value는 위의 측정한 list(각 상태별 count)
    이후 띄어쓰기를 확인할 때(Test)에는 좌측, 중앙, 우측에 공백이 있을 확률을 각각 계산해 더해준 값이 Threshold를 넘으면 띄어쓰기를 해준다. Threshold는 0.4 ~ 0.6 사이가 적당해 보이나 직접 해보고 정해야 한다.
    예를 들어 "가나다라"에서 "나다" 사이에 띄어쓰기가 있을 확률("나 다"일 확률)은
    우측 공백 : ("가나 " + "가 나 " + " 가나 " + " 가 나 ") * 0.25
    중앙 공백 : ("나 다" + "나 다 " + " 나 다" + " 나 다 ") * 0.5
    좌측 공백 : (" 다라" + " 다 라" + " 다라 " + " 다 라 ") * 0.25
    곱하는 값이 다른 이유는 보통 중앙에 띄어쓰기가 있는 경우가 큰 영향을 미치기 때문이다.(논문 참고)

    def freq(key, location):
        list = bigram_dict.get(key)
    
        if list is not None:
            total = 0
            for i in range(len(list)):
                total += list[i]
            if location == 0:
                value = get_left_freq(list)
            elif location == 1:
                value = get_middle_freq(list)
            else:
                value = get_right_freq(list)
            return value / total
        else:
            return 0

    if 우측 공백 + 중앙 공백 + 좌측 공백 > Threshold
    띄어쓰기하기
    로 볼 수 있다.

    댓글

Designed by Tistory.