Closed eubinecto closed 2 years ago
main_test.py:238: AssertionError
-------------------------------------------------------------------------- Captured stdout call --------------------------------------------------------------------------
l_last = ['ㅈ', 'ㅜ', 'ㅂ']
r_first = ['ㅇ', 'ㅓ', ' ']
ㅂ 불규칙: 주워요
======================================================================== short test summary info =========================================================================
FAILED main_test.py::TestStyler::test_irregular_jup - AssertionError: '저 쓰레기를 주웁시다.' != '저 쓰레기를 줍웁시다.'
def test_irregular_jup(self):
sent = "저 쓰레기를 줍자."
self.assertEqual("저 쓰레기를 줍자.", self.styler(sent, self.ban[0], self.ban[1])) # noqa
self.assertEqual("저 쓰레기를 주워요.", self.styler(sent, self.jon[0], self.jon[1]))
self.assertEqual("저 쓰레기를 주웁시다.", self.styler(sent, self.formal[0], self.formal[1]))
줍 + 어요 -> 주워요는 오케이. 하지만 줍 + ㅂ시다 -> 주웁시다는 not okay.
아.. if-else문의 반복이기에, 두개 이상의 케이스에 해당돼도 한 케이스만 적용하고 끝나버리기 때문인 것으로 보인다.
if-else의 연속을 여러개의 if문의 나열로 바꿔야한다. 음.. 그게 말이 쉽지..ㅠㅠ
일단 방법을 한번 생각해보자. soynlp에서는 어떻게 하고 있지? 어떻게 여러개의 규칙을 적용하고 있을까? 분명 순서가 중요해질텐데...
# ㄷ 불규칙 활용: 깨달 + 아 -> 깨달아
if l_last[2] == 'ㄷ' and r_first[0] == 'ㅇ':
l = stem[:-1] + compose(l_last[0], l_last[1], 'ㄹ')
surface = l + ending
candidates.add(surface)
candidates.add(stem + ending) # 받 + 았다 -> 받았다
if debug:
print('ㄷ 불규칙: {}'.format(surface))
# 르 불규칙 활용: 구르 + 어 -> 굴러
if ( (l_last_ == '르' and stem[-2:] != '푸르') and
(r_first_ == '아' or r_first_ == '어') and l_len >= 2 ):
c0, c1, c2 = decompose(stem[-2])
l = stem[:-2] + compose(c0, c1, 'ㄹ')
r = compose('ㄹ', r_first[1], r_first[2]) + ending[1:]
surface = l + r
candidates.add(surface)
if debug:
print('르 불규칙: {}'.format(surface))
soynlp는 여러개가 순차적으로 적용되는 건 고려하지 않는다. 즉... 줍 + ㅂ시다 -> 줍웁시다 -> 주웁시다 이렇게 변화하는 과정은 고려하지 않고. 줍 + ㅂ시다 -> 줍웁시다 (1) 줍 + ㅂ시다 -> 주ㅂ시다 (2)
이렇게 두가지가 존재한다고 보는듯. 음... 나는 순서까지 고려를 해야할 것 같다. 이것에 대한 고민은 내일 이어서하기
어간의 활용 알고리즘을 수정하고 있다. "줍 + ㅂ시다 -> 주웁시다"가 가능토록 하는게 목표인데. 현재 내 코드는 "줍 + ㅂ시다 -> 줍웁시다" 라고 출력한다. 즉 ㅂ탈락이 일어나야하는데 내 코드 상에서는 일어나지 않는다. 이 원인이 무엇인지 파악을 해야하는데, 시간상 일단 문제인식에 의의를 두고 내일로 넘기겠다!
지금은 애초에 계획했던 테스트만 쓰고 끝내자. TDD라고 생각하면 된다. 일단 failing test를 만들고, 나중에 하나씩 pass하도록 바꾸면 된다.
다음과 같이, soynlp에서 소개한 용언의 활용 케이스를 그대로 테스트에 옮겼다:
하나만 예를 들며 설명해보자면 이런걸 테스트하고 있다:
입력 = "하늘이 파랗다." 인 경우.
-어요
를 붙여서 "하늘이 파래요"를 출력해야한다. 파랗 + 어요의 과정에서 ㅎ
과 ㅓ
가 합쳐저 ㅐ
로 축약된다.-습니다
를 붙여서 "하늘이 파랗습니다"를 출력해야한다. 습니다
는 모음으로 시작하는 것이 아니므로 ㅎ탈락이 일어나지 않는다.저 테스트를 돌려보면 아직 완벽하지 않기 때문에 20개 중 8개는 패스하지 못한다. 하지만 개발을 시작하기전, 분명한 목표를 설정해둔다는 것에 오늘의 활동에 의의를 둔다.
... 그런데 이렇게 복잡한 한국어를 난 도대체 어떻게 하고 있는거지? 체득된 문법이란 참 신기한 것 같다.
1 -> 2, 3 2 -> 3 으로 가는 것은 허용하지만, 3 -> 1, 2는 허용하지 않는 편이 개발이 더 편할 것 같다.
왜? 예를 들면 이런 예시를 일일히 수작업으로 고쳐야 한다:
위가 무엇을 보여주는 것인가? 다음은 가능하다:
하지만
곱습니다 -> 고와
는 불가능하다:왜? 습니다의 경우 1, 2의 경우가 전부
어
또는어요
로 통일되기 때문이다. 원래의 어미가 무엇이었는지... 알길이 없다. 이건어요
도 마찬가지이지만, 위에서 볼 수 있듯어요
의 초성은어
와 마찬가지로 모음이라, 1일 때의 어간활용을 어지간해서는 그대로 따라간다. 하지만습니다
의 초성은 자음이다. 그래서 위처럼 어간의 활용이 1, 2인 경우와 다를 수 밖에 없다.어차피 반말부터 공부하는 외국인들은 숫자가 커지는 경우를 더 필요로 할것이기 때문에, politeness를 줄이는 알고리즘은 data augmentation의 용도가 아닌이상.. 굳이 필요없다.
그래서 우리는... 더이상 3 -> 1, 2는 지원하지 않겠다...! 그래야 개발에 속도가 붙을 것 같다.