안녕하세요. 이번 포스팅에서는 지난 포스팅에 이어 올해 1학기에 진행했던 프로젝트에 대해서 얘기해보려고 합니다.
프로젝트 주제 : <제주어, 표준어 양방향 음성 번역 모델 생성 프로젝트>
분야 : NLP, Translation, Deep-Learning, STS
1. 인퍼런스 결과
저번 포스팅에서
1) 주제 선정
2) 데이터셋 EDA
3) 데이터 전처리
4) 모델 선택 및 파인튜닝
까지 보았습니다.
파인튜닝시킨 초기 모델의 성능은 그렇게 높지 않았습니다.
아래 표에서 4월달에 해당하는 수치인데요.
날짜 | 04-13 | 05-03 | 05-06 | 05-13 | 05-21 | 05-24 | 05-26 |
제주어 -> 표준어 BLEU | 0.56 | 0.59 | 0.42 | 0.64 | 0.70 | 0.74 | 0.76 |
표준어 -> 제주어 BLEU | 0.35 | 0.37 | 0.26 | 0.37 | 0.39 | 0.46 | 0.5 |
성능이 제대로 나오지 않았던 이유를 분석해보니
- 다양한 도메인의 데이터가 필요했음
- 기존에 사용하던 발화 데이터는 주로 일상에 관련된 이야기 데이터라서 범용적이지 못했음
- 기본적인 전처리를 해주었지만 아직 세부적인 전처리가 더 필요했음
- 생성 Task가 아니라 Text-to-Text Task로 진행했기 때문에 문맥에 맞게 정확한 세부 전처리가 필요함
- 스스로 제주어에 대한 이해가 부족해 번역 품질이 좋게 나온건지 아닌지 판단이 어려웠음
이 정도가 있었습니다.
그래서 이후에 위의 문제점을 하나씩 보완하였습니다.
2. 제주어 데이터 추가 수집
그래서 기존 데이터 외에 추가 데이터 수집을 하기로 결정했습니다.추가로 수집한 데이터는 아래와 같습니다.
- 중,노년층 한국어 방언 데이터(제주도) : 사투리를 주로 중,노년층에서 사용할거라 생각해 수집
- 카카오브레인 JIT 제주 방언 데이터 : 깃허브에서 수집
- 제주도청 주관 제주어 사전 데이터
- 밤양갱, 부럽지가 않아 제주 가사 데이터 : 유튜버 뭐랭하맨의 영상에서 참고하여 수집
- 그 외 제주 방언 도서, 서적 등
위의 데이터를 전부 받아서 가공하니까 약 100만 행 정도의 데이터가 완성되더라구요.
또 너무 커지면 제 메모리가 감당을 못해서.. 100만 개의 제주어 - 표준어 데이터만 사용했습니다.
3. 더욱 세부적인 데이터 가공
더 세부적으로 데이터를 가공해야겠다고 생각한 가장 큰 원인은 '안녕하세요'조차 '안녕하수꽈'로 잘 나오지 않았던 것입니다.
또 제가 노가다랑 데이터 전처리 전문이라 열심히 데이터를 파고 또 팠죠.
1) 불용어 제거
이 전에도 불용어 제거를 하긴 했었는데 제대로 안 되어 있었나봐요.
그래서 이번에는 한국어, 영어, 공백, 숫자, 문장부호 외에 다른 문자가 있는 경우를 하나씩 확인해보았습니다.
그 결과 #, @, *, /, 이름, 이중괄호 등을 발견하였고 ( 매우 지저분하죠 데이터가 ㅎㅎ )
이런 불용어를 모두 제거해주었습니다.
아래는 그 코드입니다.
## 한국어, 영어, 숫자, 공백, 문장부호만 허용
allowed_pattern = r'^[\uAC00-\uD7A3a-zA-Z0-9\s.,?!]+$'
## 위 조건에 맞지 않는 행 필터링
invalid_rows = df[
~df['dialect_form'].str.match(allowed_pattern, na=False) |
~df['standard_form'].str.match(allowed_pattern, na=False)
]
## 주로 어떤 불용어들이 있는지 확인
invalid_rows.dialect_form.value_counts()
## 불용어제거
invalid_rows['standard_form'] = invalid_rows['standard_form'].apply(lambda x : x.replace('#', ''))
invalid_rows['dialect_form'] = invalid_rows['dialect_form'].apply(lambda x : x.replace('#', ''))
invalid_rows['standard_form'] = invalid_rows['standard_form'].apply(lambda x : x.replace('@', ''))
invalid_rows['dialect_form'] = invalid_rows['dialect_form'].apply(lambda x : x.replace('@', ''))
invalid_rows['standard_form'] = invalid_rows['standard_form'].apply(lambda x : x.replace('*', ''))
invalid_rows['dialect_form'] = invalid_rows['dialect_form'].apply(lambda x : x.replace('*', ''))
invalid_rows['standard_form'] = invalid_rows['standard_form'].apply(lambda x : x.replace('/', ''))
invalid_rows['dialect_form'] = invalid_rows['dialect_form'].apply(lambda x : x.replace('/', ''))
2) 잘못된 부분 바로잡기
데이터 중에 제주어 / 표준어 딱딱 잘 나뉘어져 있는 경우도 있지만
애매한 내용들은 (제주어)/(표준어) <- 이렇게 함께 있는 경우가 있었습니다.
그래서 앞 단어를 제주어 열에 붙이고 뒤 단어를 표준어 열에 붙여서 처리를 해주었는데
(같애) / (같아), (걍) / (그냥) 처럼 사투리가 아닌데 나뉘어져 있는 경우가 있어서 이런 부분들을 세부적으로 처리해주었습니다.
아래는 그 코드입니다.
## 사투리가 아닌데 나뉜 경우 제거
merged_df = merged_df.loc[merged_df.extracted != '(같애)/(같아)']
merged_df = merged_df.loc[merged_df.extracted != '(같애.)/(같아.)']
merged_df = merged_df.loc[merged_df.extracted != '(거)/(그거)']
merged_df = merged_df.loc[merged_df.extracted != '(거)/(거야)']
merged_df = merged_df.loc[merged_df.extracted != '(거?)/(거야?)']
merged_df = merged_df.loc[merged_df.extracted != '(거.)/(거야.)']
merged_df = merged_df.loc[merged_df.extracted != '(건)/(그건)']
merged_df = merged_df.loc[merged_df.extracted != '(것도)/(그것도)']
merged_df = merged_df.loc[merged_df.extracted != '(그래가지고)/(그래서)']
merged_df = merged_df.loc[merged_df.extracted != '(걍)/(그냥)']
merged_df = merged_df.loc[merged_df.extracted != '(뭐?)/(뭐야?)']
merged_df = merged_df.loc[merged_df.extracted != '(뭔)/(무슨)']
merged_df = merged_df.loc[merged_df.extracted != '(싶)/(싶어)']
merged_df = merged_df.loc[merged_df.extracted != '(싶.)/(싶어.)']
merged_df = merged_df.loc[merged_df.extracted != '(않애?)/(않아?)']
merged_df = merged_df.loc[merged_df.extracted != '(해가지고)/(해서)']
## (근데)/(그런데) <-- 이 경우에는 근데를 겐디로 변경
merged_df.loc[merged_df.extracted == '(근데)/(그런데)', 'dialect_form'] = merged_df.loc[merged_df.extracted == '(근데)/(그런데)', 'dialect_form'].apply(lambda x: x.replace('근데', '겐디'))
## (그니까)/(그러니까) <-- 이 경우에는 그니까를 게난으로 변경
merged_df.loc[merged_df.extracted == '(그니까)/(그러니까)', 'dialect_form'] = merged_df.loc[merged_df.extracted == '(그니까)/(그러니까)', 'dialect_form'].apply(lambda x: x.replace('그니까', '게난'))
## (그니까)/(그러니까) <-- 이 경우에는 그니까를 게난으로 변경
merged_df.loc[merged_df.extracted == '(진짜이)/(진짜)', 'dialect_form'] = merged_df.loc[merged_df.extracted == '(진짜이)/(진짜)', 'dialect_form'].apply(lambda x: x.replace('진짜이', '진짜'))
## (닮)/(같아) <-- 이 경우에는 닮을 같아로 변경, 띄어쓰기로 구분해서 변경
merged_df.loc[merged_df.extracted == '(닮)/(같아)', 'dialect_form'] = merged_df.loc[merged_df.extracted == '(닮)/(같아)', 'dialect_form'].apply(lambda x: ' '.join(word.replace('닮', '같아') if word == '닮' else word for word in x.split()))
merged_df.loc[merged_df.extracted == '(닮.)/(같아.)', 'dialect_form'] = merged_df.loc[merged_df.extracted == '(닮.)/(같아.)', 'dialect_form'].apply(lambda x: ' '.join(word.replace('닮.', '같아.') if word == '닮.' else word for word in x.split()))
3) 명사 단어 교정
다음 작업은 명사 단어가 잘못 매핑되어 있는 부분을 올바르게 수정하는 것이었습니다.
제주어 column 인데 표준어로 쓰인 명사 표현에 대해 제주어 표현으로 바꾸고
표준어 column 인데 제주어로 쓰인 명사 표현에 대해 표준어 표현으로 바꾸는 작업을 수행했습니다.
구체적인 코드는 깃허브에 올려놨으니 깃허브 참고해주시면 좋을 것 같습니다.
주로 1) 인사말 2) 동물 3) 일상단어 4) 신체 5) 농사 6) 식물 에 관련한 단어를 교정하였습니다.
4) 받침 교정
제주어는 구조적으로 쌍시옷 받침이 나올 수 없다고 해요.
모든 표기를 그래서 시옷받침으로 해야 하는데 데이터에 쌍시옷 받침이 참 많더라구요..
그래서 모든 쌍시옷 받침을 일일이 찾아서 수정해주었습니다.
그리고 되 발음은 뒈가 되어야 하고
문장 부호 앞의 동사는 간소화되는 특징이 있어 이를 모두 반영해 받침 교정 부분을 마무리했습니다.
구체적인 코드는 깃허브에 올려놨으니 깃허브 참고해주시면 좋을 것 같습니다.
4. 제주 방언 공부
위 사진은 제가 실제로 제주어 프로젝트 할 때 읽었던 책들인데요.
제주어때문에 몇 년 만에 도서관을 다시 간지 모르겠네요 ^^
제가 만든 모델이 내뱉는 문장이 실제로 제주어를 잘 얘기하고 있는지
번역의 질적인 평가가 괜찮은지를 위해서 제가 스스로 제주어를 공부했습니다.
나중에 제주도 여행가면 시장가서 제주어로 스몰토킹이 가능할지도 모르겠네요 ㅋㅋ
5. 다시 Inference
그래서 위 그래프는 저희 모델의 시간에 따른 성능 그래프인데요.
위의 세부적인 전처리와 데이터 수집으로 0.76까지 성능을 올리긴 했습니다.
다음 포스팅에서는 5월 첫째주에 있었던 갑작스러운 성능 저하 사건과
저희 번역 모델을 어떻게 쓸 수 있는지 가이드를 올릴 계획입니다.
긴 글 읽어주셔서 감사합니다.
'프로젝트' 카테고리의 다른 글
[프로젝트] 제주어, 표준어 양방향 음성 번역 모델 생성 프로젝트 리뷰 (3) (2) | 2024.12.09 |
---|---|
[프로젝트] 제주어, 표준어 양방향 음성 번역 모델 생성 프로젝트 리뷰 (1) (6) | 2024.12.03 |
[프로젝트] HR_면접자 정보 맞추기 프로젝트 (3) (2) | 2024.10.12 |
[프로젝트] HR_면접자 정보 맞추기 프로젝트 (2) (1) | 2024.10.04 |
[프로젝트] HR_면접자 정보 맞추기 프로젝트 (1) (4) | 2024.10.01 |
[프로젝트] Whisper 파인튜닝 (3) | 2024.09.21 |
[프로젝트] 티스토리 블로그 Web Crawling (11) | 2024.09.14 |
[프로젝트] 2024 하반기 ICT 학점연계 프로젝트 인턴십 합격 후기 (0) | 2024.08.14 |