정말 나의 리뷰 프로젝트를 heroku 무료 서버에 올리기 힘들었다. 메모리 개선만을 위해 거의 일주일을 불태웠다.
저장 용량은 단 500MB만 허락되는데 konlpy, django를 비롯해 꼭 필요한 패키지들과 RNN 학습 모델, 토크나이저 등 꼭 필요한 파일들만 heroku에 올렸을 때 497.8MB로 간당간당하게 올라갔었다.
하지만 메모리 제한에 막혔었다. heroku 무료 서버 기준 512MB까지 RAM을 사용할 수 있지만 1024MB까지는 ERROR R14를 띄우면서 허용해준다. worker가 죽지 않는다는 뜻이다. 1024MB를 넘어가면 ERROR R15를 띄우면서 강제 종료된다. 저장 용량부터 거의 500MB였기 때문에 쉽게 worker가 강제 종료됐다.
자연어 처리를 heroku 무료 서버에서 돌리기 위해 어떤 과정들을 겪었는지 정리해본다.
Okt
처음에는 konlpy의 okt만을 이용해서 heroku 무료 서버에서 작동 가능했다. 1000MB 조금 안 되는 선에서 잘 돌아갔다. 돌이켜보면 konlpy에서는 (mecab은 돌려보지 않아서 잘 모르겠지만) okt가 가장 메모리를 적게 사용했다.
하지만 okt를 사용해서 키워드 추출을 하니 정말 이상하게 형태소를 나눴다. 일단 '블레이저' 같은 단어는 '블''과 '레이저'로 나눴으며 합성어를 '한 글자' + '여러 글자'로 나누는 일이 빈번했다.
그리고 가장 큰 문제는 수사, 의존 명사까지 하나의 명사 범주에 들어가기 때문에 수사, 의존 명사를 전부 stopwords에 직접 추가해야 하는 불편함이 있었다.
로컬 서버에서 테스트를 해본 결과 꼬꼬마(kkma)가 단어를 가장 잘 분리해냈다. 그래서 꼬꼬마를 heroku 서버에 올려보았다.
Okt + Kkma
사용하고 있던 RNN 모델은 Okt를 통해 학습한 모델이었다. 그래서 감성 분류는 Okt가 쪼갠 결과를 통해 학습하고 키워드 추출만 꼬꼬마로 처리를 하는 로직을 짰다.
Okt 생성자를 루트 함수에서 호출해도, 감성 분류 함수에서 호출해도 꼬꼬마를 사용하는 함수까지만 가면 worker가 메모리 초과로 죽기 일쑤였다. 1200MB 넘는 숫자까지 봤다.
heroku 테스트 결과 kkma가 konlpy tag 중에 가장 메모리를 많이 차지했다. 어쩌면 한번에 가장 많은 메모리를 요구했던 것일 수도 있다.
그래서 꼬꼬마는 안 되겠다 싶어서 꼬꼬마 다음으로 명사를 잘 추려냈던 코모란을 선택하게 됐다.
Okt + Komoran
Okt를 통해 감성 예측을 하고 코모란으로 키워드를 추출하는 로직이다.
Okt + Kkma를 사용할 때랑 크게 다를 바 없었다. 조금 더 적은 메모리에서 죽기는 했다. 1100MB 조금 안 되는 정도에서 ERROR R15로 worker가 죽어버렸다.
Okt와 다른 tagger를 같이 쓰는 건 메모리 때문에 불가능하다는 결론에 이르렀다. 그래서 꼬꼬마는 메모리를 너무 많이 쓰기 때문에 안 될 것 같았고 오직 코모란만 사용하기로 했다.
Komoran
Okt를 안 쓰고 오직 코모란만 쓰니까 이제는 당연히 되겠지라는 기대가 있었다.
그러나 코모란 생성자 하나만 호출했을 뿐인데 1057MB 메모리를 사용했다며 강제 종료됐다.
다른 로직에서 메모리를 줄이기 위해 많은 디버깅을 해봤지만 그래도 죽는 건 마찬가지였다. 사용하는 변수 메모리를 다 더해봤지만 겨우 50MB 근처였다. 몇백 MB를 사용했을 리는 없다.
그래서 다음과 같은 결론에 이르렀다.
Konlpy 자체의 함수 처리 로직에서 메모리를 많이 사용하고 있다.
그렇기 때문에 konlpy를 버려야 했고 품사 태깅, 형태소 분석을 위한 다른 패키지가 필요했다.
koalanlp
검색을 해보다가 처음 알게 된 패키지가 있었으니 koalanlp이다. koalanlp는 너무나 생소했다. 다들 konlpy를 쓰고 읽었던 자연어 처리 관련 책에서도 konlpy에 대한 언급만 있었다.
중간에 테스트하는 과정에서 java package 관련 에러 메시지가 나와서 정확한 테스트가 불가능했다.
그래도 머릿속 로직대로 코드를 변경한 뒤 저장했다. 윈도우 서버에서는 안 돼도 리눅스 서버에서는 될지도 모른다고 긍정적으로 생각해봤다.
메모리를 konlpy보다 적게 사용하기를 간절히 원하면서 koalanlp를 사용해서 heroku 서버에 올려봤다.
첫 번째 테스트에서 성공???? 메시지가 떴다. okt를 포기한 뒤로는 처음 보는 성공이었다.
하지만 task가 끝나자마자 worker가 메모리 관련 에러 메시지는 아니지만 다른 에러 메시지를 띄우며 죽었다. 해당 에러를 구글링 해보니 메모리 문제일 가능성이 높다는 결론을 얻을 수 있었다.
게다가 분명 성공 메시지는 받았지만 데이터베이스에는 적용이 되어있지 않았다. (이 부분은 키워드를 잘못 뽑아내는 오류를 초반에 인지하지 못했어서 단정해서 말하기 어렵다)
그래도 성공했었으니까 기쁜 마음에 한 번 더 task를 수행해봤다. 1041MB를 사용했다고 worker가 죽었다. 첫 번째 task는 메모리 초과가 났지만 운 좋게도 이루어진 성공이었나 보다.
결국 koalanlp도 사용할 수 없게 되었다. 그리고 새로운 대안인 PyKomoran을 찾았다.
PyKomoran
PyKomoran 패키지 또한 Koalanlp만큼 생소했다. 하지만 Komoran을 만든 회사에서 직접 배포한 python wrapper였기 때문에 믿어보기로 했다.
github.com/shineware/PyKOMORAN
일단 Konlpy와 사용 방법이 조금 달랐다.
PyKomoran 사용 방법은 후에 다른 포스팅에서 정리하겠다.
일단 pip install PyKomoran을 통해 설치를 했을 때 konlpy보다 용량이 적어서 좋았다.
konlpy는 19MB이다. 하지만 PyKomoran은 7.9MB이다.
konlpy는 komoran을 비롯해 여러 tagger가 들어있기 때문에 큰 게 당연하다. 하지만 komoran만 사용한다면 용량을 반으로 줄일 수 있다.
PyKomoran에 맞게 코드를 바꾼 뒤 heroku에 배포를 했다.
Komoran이 메모리를 적게 사용한다고 github readme에 적혀있기 때문에 잔뜩 기대를 하고 task를 실행했다.
!! 할렐루야!!
약 50건의 리뷰에 대해 612MB로 task가 성공적으로 처리됐다.
konlpy를 사용할 때는 약 20건의 리뷰에 대해서도 처음부터 700, 900MB가 떴기 때문에 이렇게 적은 메모리를 사용할 줄은 꿈에도 몰랐다.
정말 komoran 개발자들이 메모리 효율에 신경을 많이 썼음이 느껴졌다. 존경스럽습니다.
두 번째로 약 30건의 리뷰를 처리하는 task에서는 ERROR R14(메모리 초과)가 뜨지 않고 처리됐다. 굉장히 뿌듯하고 기쁜 상태이다. 어디 가서 PyKomoran 찬양하고 다녀야겠다.
어쩌면 메모리 개선에 기여?!
감성 예측을 위해 저장해놓았던 모델과 토크나이저를 기존에는 루트 함수에서 호출해놓고 함수에 매개변수로 전달을 했었다. 하지만 최종 코드에서는 노드 함수에서 모델과 토크나이저를 로드했다. 기대한 바대로 작동했다면 함수 종료와 함께 로드했던 모델과 토크나이저는 메모리에서 사라졌을 것이다.
Komoran(DEFAULT_MODEL['LIGHT'])
PyKomoran은 LIGHT 모델, FULL 모델 두 가지를 제공한다.
테스트를 해봤는데 두 모델의 결과가 계속 같았다. (물론 많은 데이터로 테스트해보지는 않았다)
그래서 LIGHT 모델을 사용해 배포했다.
루트 함수에서 Komoran 생성자를 한 번만 호출하고 komoran이 필요할 때마다 노드 함수에 매개변수로 전달했다.
남은 과제
아직 감성 분류 모델 성능 개선, 테스트 코드 작성의 숙제는 남아있다.
메모리 효율 체크를 위해 bulk_create 대신 하나씩 create 하도록 코드를 변경했었다. 이 또한 많은 양의 데이터를 가지고 테스트를 해봐야 할 것이다.
PyKomoran은 UserDict 또한 제공하기 때문에 이상하게 쪼개지는 단어를 등록할 수 있다. 리뷰를 조금 더 등록해보고 자주 등장하지만 이상하게 쪼개지는 단어를 찾아내야겠다.
'프로젝트 > 리뷰집' 카테고리의 다른 글
[리뷰집] 프로젝트 소개 (0) | 2021.02.15 |
---|---|
PyKomoran 사용법 정리 (0) | 2021.02.15 |
OrderedDict의 배신 - not ordered (0) | 2021.02.15 |
python 메모리와의 전쟁 - pandas의 거대함, pickle의 압축력 (0) | 2021.02.15 |
꼬꼬마(kkma)의 메모리 효율 문제 - konlpy 품사 태거에 대해 (0) | 2021.02.14 |