[일일리포트] Day 78 (Lelvel2_MRC_8)

해당 일일리포트에서는 네이버 커넥트에서 진행하는 '부스트캠프 AI Tech 3기'에서 배운 내용을 다루고 있습니다. 저작권 이슈 때문에 관련 자료를 올릴 수는 없기에 핵심 이론과 코드를 요약해서 올리고 있기에 내용이 부족할 수 있습니다.
▶ Today I Learned (핵심 요약 정리)
Curriculum Learning 구현
오늘은 어제 정리했던 내용들을 토대로 우리 Task에 당장 적용시킬 수 있을만한 방법들만 고려해서 구현을 진행했다. 우선, 난이도 측정 방식의 경우 논문에서 얘기했던 Cross Review까지는 힘들고 대신 데이터셋을 10개로 나눠서 각 모델에 대한 f1-score를 계산하는 방식으로 진행했다. Epoch나 Learning_rate를 어떻게 세팅할 지 고민을 했는데, difficulty만 결정하는 부분이기에 동일한 세팅값으로만 진행해도 괜찮을 것 같아서 동일하게 Epoch 3에 Learning_rate 9e-6으로 세팅했다(이전까지 SOTA 세팅값). 각 모델을 돌려서 나온 결과를 토대로 동일한 step에서 f1을 뽑아 계산을 수행했고, 높은 f1을 보인 데이터셋이 난이도가 낮은 모델이라고 가정하고 데이터 셋의 순서를 변경했다.

이렇게 나온 난이도를 기준으로 f1이 높은 데이터셋이 앞에, 낮은 데이터셋이 뒤에 올 수 있게 배치를 해서 새로 데이터셋을 만들었다. 이렇게 만든 데이터셋을 이전 학습 코드에서 동일하게 적용시킬 계획이었는데 Train할 때, DataLoader에서 RandomSampler를 사용하면 순서가 의미가 없어질 것 같았다. 따라서 SequentialSampler를 사용하려고 했기 때문에 데이터를 그냥 concat하는 것이 아니라 sample함수를 통해 한번 뒤섞어서 배치 내에서 random하게 섞어서 concat을 수행했다.
# 10개의 데이터셋 배치를 한 번씩 더 섞어준다.
difficulty_order = [6, 7, 0, 5, 4, 9, 2, 3, 1, 8]
k = len(train_df)//10
datasets_10 = [train_df.loc[i:i+k-1, :] for i in range(0, len(train_df), k)][:-1]
ordered_df = datasets_10[difficulty_order[0]].sample(frac=1).reset_index(drop=True)
Dataset.from_pandas(ordered_df)
for i in difficulty_order[1:]:
n_dataset = datasets_10[i].sample(frac=1).reset_index(drop=True)
ordered_df = pd.concat([ordered_df, n_dataset])
train_reorder = Dataset.from_pandas(ordered_df.reset_index(drop=True)) # 왜인지 reset_index를 해줘야 한다.
dataset = DatasetDict({'train': train_reorder, 'validation': dataset["validation"]})
실제 학습 그래프를 보면, 이전 SOTA모델에 비해서 성능 향상이 크지 않았었다. 3 Epoch로 돌렸을 때, EM Score의 성능이 높았던 step의 체크포인트를 가져와서 BM-25(top_k:40)를 retreval로 사용해서 제출을 했고, 성능 향상이 있었다. 이전 모델의 Score(66.2500) 대비 3.75점 향상된 70점의 점수를 받을 수 있었다.
추가적으로 Step800정도는 1Epoch였기 때문에, 1Epoch으로 다시 한 번 학습 했을 때는 Lr_Scheduler도 달라지다보니 성능이 하락하는 모습을 보여줬다.

마지막으로 이번 reader모델의 개선이 있다고 생각해서 Retrieval에서 BM-25말고 ElasticSearch도 이용해서 학습을 진행했다. 지금까지는 동일 reader모델 대상으로 ElasticSearch를 사용했을 때 리더보드 기준 EM Score 3점 정도 차이가 있었기 때문에 더 큰 성능향상이 있을 것이라고 기대했다. 하지만 오히려 점수가 더 떨어졌다.
처음에는 다른 분께서 구현하신 코드를 사용하는 과정에서 실수가 있는 줄 알았는데 그게 아니었다. 그래서 이유에 대해서 생각해보다가 이번 대회를 진행하기 전에 멘토님께서 reader모델과 retrieval가 맞아야 성능 향상이 있을 것이라고 얘기하신 부분이 생각났다. 확실히 저번 주까지는 크게 Reader모델에 변형을 주지 않았었지만, 오늘 Sampler도 변경하고, 데이터의 순서도 바꾸는 등의 변화를 시도했기 때문에 해당 모델에 맞는 Retrieval가 달라지지 않았을까 하는 생각을 했다. (근데 ElasticSearch도 BM-25를 사용하는 것으로 아는데 차이가 꽤 커서..의문이긴 하다)
내일은 대회 마지막 날이기 때문에 새로운 것을 구현한다기 보다는 지금 구현된 모델의 성능을 향상시킬 수 있는 방법에 대해서 생각해볼 계획이다.
▶ Review (생각)
처음 커리큘럼 러닝을 구현하려고 ,논문을 보면서 어떤 식으로 구현할 수 있을지 감이 잘 잡히지 않았었다. 레퍼런스 코드나 자료도 없었고, 커리큘럼 러닝에 대한 개념이 주로 CV쪽 도메인에 특화되어 있다보니 정보를 찾기 수월하지 않았었다. 그러다 멘토님게 조언을 구했을 때, 논문 자체 구현이 너무 어렵게 되어있기 때문에 필요한 부분만 구현하는 방식을 말씀해주셨다. 그리고 어느정도 적당한 타협점을 생각하다보니 구현을 할 수 있을만한 실마리가 보였고, 오늘 구현을 진행해 점수를 올릴 수 있었다.
이번에 코드를 구현하면서 팀원들에게도 어떤 방향이 좋을지, 이 방향이 맞을지 등에 대해서 얘기를 나눴었다. 그리고 그 과정에서 많은 도움을 받을 수 있었다고 생각한다. 협업을 진행하면서 꾸준히 소통의 시간이 매우 중요하다는 것을 느끼는 것 같다. 내가 무엇을 모르고 있는지, 이것을 어떻게 전해야 할 것인지에 대해서 더 고민하고 생각할 필요가 있는 것 같다. 왜 많은 멘토님이나 마스터님들께서 질문을 잘 하는 것의 중요성에 대해서 강조하신 이유를 알 것 같다.
내일은 커리큘럼 러닝 중에서 난이도 측정 이후 어떤 방식으로 모델을 학습시킬 것인가에 대한 방법으로 한 번에 데이터를 넣어주는 방법과 어제 읽었던 논문에서 나온 방법대로 난이도가 어려운 데이터의 비율을 늘리면서 학습하는 방법이 있었다. 오늘은 구현이 간단하다고 느꼈던 한 번에 데이터를 넣어주는 방식으로 진행했는데, 내일은 다른 방식으로 수행해보는 것도 괜찮을 것 같다.