Try   HackMD

VumBleBot Wrap Up Report

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

목차

읽기 전에

다섯명의 팀원들이 함께 작성했기 때문에 용어들이 통일되지 않은 경우가 있습니다. 그래서 헷갈릴 수도 있는 용어들을 미리 적어놓습니다. :)

문서: document, context
질문: question, query
Dense Vector: CLS Token Vector, Dense Embedding


odqa baseline wiki
odqa baseline source code
group activity


Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
팀원 소개

  • Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →
    신지영
    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →
  • Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →
    구건모 (한숨 존)
  • Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →
    김성익
    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →
  • Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →
    이수연
  • Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →
    김종헌

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
팀 목표

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
협업

팀원들 대부분 협업의 경험이 전무했기 때문에 PR이나 Merge에 대한 두려움이 있었지만 협업을 잘하는 것이 개발자에게 중요하다고 판단했기 때문에 이번 Stage에서는 이전과는 달리 강도 높은 협업을 하기로 결정했습니다.

익숙하지는 않지만 협업을 잘 하려고노력했습니다.

Issue 관리 (칸반 보드)

Zenhub 칸반 보드를 사용하여 Issue의 종류를 나눠 관리하고자 했습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Issue templategit message을 사용하여 적는 사람의 부담을 줄이고, 한눈에 어떤 Issue/commit인지 알아볼 수 있도록 하였습니다.

  • Question
    궁금한 점이나, 궁금했었지만 해결된 점들을 기록합니다.
  • Bug
    프로젝트에서 발견한 버그를 기록합니다.
  • Suggest
    프로젝트에 추가되었으면 하는 기능을 제안하고 논의합니다.
  • Todo
    개인/팀별 수행할 Task를 기록합니다.

Issue 정리

매주 목요일에 다 같이 이번 주의 Issue를 체크하고 Close하는 시간을 가졌습니다. 해당 주차의 할 일을 Milestone에 할당해두어 해당 주차의 목표 달성여부를 관리할 수 있었습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Gather Town

PeerSession 이후 개인/팀으로 모여서 짝 프로그래밍 또는 토의하는 시간을 가졌습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

회의록 및 documents 관리

피어세션 타임에 진행된 회의 내용을 모두 정리하여 회의록으로 남기고, 언제든 다시 열람할 수 있도록 github에 공유하였습니다. competition을 위한 논문 review, EDA, further reading follow-up등도 마찬가지로 공유하여 확인할 수 있게 했습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
하나의 코드

"하나의 코드로 관리하는 것이 어떨까요? 그게 진짜 협업 같은데"

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
추상화

하나의 코드로 작성하기 위해 저희가 지켜야 했던 첫 번째 방법은 추상화입니다. 구현해야 할 모델은 크게 RetrieverReader가 있었고 추상화를 위해 RetrieverReader의 역할이 무엇인지 나열하고 흐름을 파악하여 코드를 구현했습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Retriever 클래스 다이어그램

Retriever 흐름

  1. Embedding및 Encoder를 가져온다. ( 없으면 만든다. )
  2. Encoder를 사용하여 Query Embedding을 생성한다.
  3. Query당 TOP-K개의 문서를 반환한다.
합성
합성
합성
합성
상속
상속
상속
상속
합성
HybridRetrieval
encoder
embedding
get_embedding()
get_relevant_doc_bulk()
_rank_fusion_by_hybrid()
SparseRetrieval
encoder
embedding
get_embedding()
get_relevant_doc_bulk()
DenseRetrieval
encoder
embedding
get_embedding()
get_relevant_doc_bulk()
HybridLogisticRetrieval
encoder
embedding
get_embedding()
get_relevant_doc_bulk()
_exec_logistic_regression()
_get_logistic_regression()
Retrieval
encoder
embedding
retrieve()
LogisticRegression
fit()
transform()
DprRetrieval
_exec_embedding()
ColBertRetrieval
_exec_embedding()
DprBert
DprKoBert
ColBert
BM25Retrieval
_exec_embedding()
TfidfRetrieval
_exec_embedding()
Bm25Plus
Bm25L
ATIREBM25
Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Reader 클래스 다이어그램

Reader 흐름

  1. 데이터 셋 전처리를 한다.
  2. 전처리 된 데이터셋을 사용하여 예측을 한다.
  3. 후처리를 통해 정답을 생성한다.
상속
합성
BaseReader
model
metric
set_dataset()
preprocess_dataset()
post_processing_function()
CustomHeadReader
model
get_trainer()
CustomModel
backbone
head_input_size
forward()
random_masking()
get_exact_match_token()
DprQAHead
forward()
CnnQAHead
forward()
LstmQAHead
forward()
ComplexCnnQAHead
forward()
CnnLstmQAHead
forward()

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
꼼꼼한 코드 리뷰

지정된 Reviewer가 팀원의 코드를 읽고 분석하고 테스트함으로써 기술부채가 발생하지 않는 코드를 작성하려고 노력했습니다.

code-review

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
눈으로 읽을 수 있는 코드

utils-qa-refactoring

위의 두 코드는 동일한 기능을 수행하는 코드입니다.

단일 기능 분리세부 기능을 숨기지 않음으로써 눈으로 쉽게 읽을 수 있는 코드를 작성하였습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
꾸준한 리팩토링

이미 구현된 기능을 응집력, 결합력을 고려하여 재작성하고 방어적인 코드를 작성하기 위해 꾸준히 리팩토링을 하였습니다.

refactoring

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
체계적인 실험

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Key, Value로 관리하는 실험 전략

JSON을 사용하여 실험 환경을 관리하였습니다.

retriever

EX) Retriever 단일 모델 비교 실험

  • TFIDF: RET_01_TFIDF.json
  • BM25: RET_02_BM25.json
  • DPRBERT: RET_03_DPRBERT.json
  • ATIREBM25: RET_04_ATIREBM25.json
python -m run_retrieval --strategies RET_01_TFIDF,RET_02_BM25,RET_03_DPRBERT,RET_04_ATIREBM25 --run_cnt 1 --debug False --report False

retriever-compare-top-k

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Slack Bot을 사용한 실험 공유

slack-bot

Slack Bot을 알림용으로 구축하여 실시간으로 실험 공유를 했습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
잘 설계한 모델 검증 전략

Reader모델은EMF1점수로 성능을 평가합니다. 그리고 Retriever모델은 검색한 Top-K개의 문서중에 정답 문서가 얼마나 포함되는지로 성능을 평가합니다. 우리가 모델을 잘 구축했는지의 판단은 검증 전략을 어떻게 하냐에 따라서 달라지게 됩니다.

Reader 모델 검증 전략

transformer에서 제공하는 metricCompetition에서 제공하는 전처리 코드를 사용하여 대회와 똑같은 검증 전략을 사용하였습니다.

Retriever 모델 검증 전략

Retriever는 검증 방식이 대회에서 따로 주어지지 않았습니다. 그래서 Retriever관련 논문에서 검증하는 방식을 가져와 Retriever 모델을 검증했습니다.

또한 검색 데이터셋인 Wiki에 비슷하지만 약간 다른 중복 문서가 포함되어 있는 경우가 있어서 검증할 때 fuzzywuzzy 라이브러리를 사용하여 문서간의 Levenshtein Distance비율로 문서를 잘 가져왔는지 판단했습니다.


Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Data EDA

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
KLUE & KorQuAD dataset

💻 MRC/KorQuAD 데이터 시각화
💻 MRC/KorQuAD EDA 정리

주어진 Wikipedia 데이터셋과 KorQuAD 데이터셋을 비교 및 분석하여 각각의 데이터셋들이 어떤 특징을 가지고 있는지 시각화하였습니다. 세부적으로 수행한 내용은 다음과 같습니다.

​​​​1. Document(context) 내 answer의 위치 시각화
​​​​2. validation에서 정답이 n개인 경우 check
​​​​3. Document [CLS] Token vector - TSNE로 시각화
​​​​4. dataset의 전처리 파이프라인 통과 여부 체크
​​​​5. Exact Match에 영향을 끼치는 Token 체크

1. Document(context) 내 answer의 위치 시각화

시각화를 용이하게 하기위해 feature를 전처리하여 dataframe으로 만들어서 진행하였습니다.

먼저 Answer가 Document에서 위치하는 곳은 Wiki 데이터셋이나 KorQuAD 데이터셋 모두 비교적 문서의 앞쪽 부분에서 정답이 등장했습니다.

그러나 KorQuAD 데이터셋이 주어진 Wiki 데이터셋에 비하여 평균적으로 문서의 길이가 더 짧았습니다(400 vs 800). 이에 따라 정답이 시작하는 구간도 Wiki 데이터셋에 비하여 비교적 앞쪽에 위치했습니다. 따라서 Wiki 데이터셋이 MRC에 좀 더 어려운 데이터라는 것을 예측할 수 있었습니다. 또한, Wiki 데이터셋의 경우 길이 500 이하의 문서들은 (의도적인지는 모르겠지만) 제거되어 있었습니다.

이러한 분석을 기반으로, 추후 KorQuAD 데이터셋을 학습 데이터셋으로 추가할 때 여러 분포를 고려하여 sampling하도록 구현했습니다.

2. validation에서 정답이 n개인 경우 check

두 데이터셋 내에서 answer가 2개 이상인 경우를 체크하였으나, 정답이 여러 개로 주어지는 경우는 없었습니다. 나중에 마스터세션에서 알게 되었지만, ODQA용으로 제작된 데이터셋이 아니었기 때문에 정답이 n개인 경우가 없었던 것 같습니다.

3. Document [CLS] Token vector - TSNE로 시각화

CLS Token vector는 해당 지문의 의미를 벡터값으로 변환한 것이라고 볼 수 있습니다. 문서들의 임베딩 공간을 시각화하기 위해 다국어 BERT Dense Retriever를 이용하여 문서들의 CLS token vector를 뽑아낸 뒤, 이를 TSNE로 2차원 평면상에 시각화하였습니다.

임베딩 공간에서, 문서간에 군집들이 어느정도 존재하는 것을 확인할 수 있습니다. 군집이 여럿 형성되었다는 것은 Dense Retriever가 헷갈릴 만한 문서가 많다는 뜻이므로, 이 상태에서는 TOP-1의 문서를 반환하는 Dense Retriever가 질문에 대응하는 정확한 문서를 가져올 수 없을 것입니다.

따라서 Reader가 올바른 문서를 받기 위해서는 Retriever가 더 많은 문서 후보를 반환할 필요가 있다는 것을 알 수 있습니다.

4. dataset의 전처리 파이프라인 통과 여부 체크

데이터셋의 전처리 필요성을 알아보기 위하여 전처리 파이프라인을 함수별로 나누어 통과 횟수를 체크했습니다. 수행한 전처리는 html 제거, 문장 분리, 이메일 제거, URL 제거, 언론 정보 제거, 의미없는 괄호 제거 등이었습니다.

전체 문서 집합에서 수행되지 않은 전처리는 html 제거, 문장 분리, 이메일 제거 정도로 보였는데, 이것 역시도 올바르게 Counting되지는 못했습니다. Wiki 데이터 셋, KLUE MRC 데이터 셋, KorQuAD 데이터셋 전부 전처리가 수행되지 않았기 때문에 이 전처리가 성능 감소에 영향이 없을거라 판단하였고, 따라서 따로 전처리를 수행하지 않았습니다.

5. Exact Match에 영향을 미치는 Token 체크

Mecab, hannanum, kkma 등의 형태소 분석기를 이용하여 prediction 및 ground truth 토큰을 형태소 후처리로 처리할 수 있는지를 분석하였습니다.

EM으로 처리되지 않은 오답의 형태소를 분석하여 정답과 형태소가 얼마나 겹치는지 분석하기도 하고, 형태소 분석을 통하여 예측을 후처리할 수 있는 경우와 그렇지 않은 경우를 비교했습니다.

이 분석을 통해, 예측 성능을 높이기 위한 데이터 전처리와 후처리의 필요성을 처음으로 확인했습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
ETRI dataset

💻 ETRI Dataset EDA

ETRI에서 제공하는 MRC 데이터셋을 활용하고자 문서의 길이, 답변의 길이, 답변 시작 위치, 답변 종료 위치를 파악하는 EDA를 진행했습니다.

ETRI 데이터는 KLUE에 비해 문서의 길이가 평균적으로 짧았고, 그로 인해 답변이 상대적으로 앞에 위치한다는 특징을 보였습니다. 답변의 길이는 KLUE 데이터셋에 비해 긴 것으로 파악되었습니다. 또한 KLUE 데이터셋은 한 지문 당 질문의 개수가 최대 4개였던 것에 비해 ETRI 데이터셋에서는 한 지문 당 질문의 개수가 7~8개인 경우도 있다는 것을 파악하였습니다.

EDA 결과를 기반으로, 다음과 같은 샘플링 기준을 적용하였습니다.

  1. KLUE 데이터셋의 문서 길이가 500 이상이라는 점을 감안하여 ETRI 데이터셋으로부터 500 이상 길이의 문서들만을 샘플링하였습니다.
  2. 답변 시작 지점이 KLUE와 유사한 데이터에 더욱 가중치를 주어서 샘플링했습니다.
  3. 한 문서 당 질문의 개수가 4개 이상이 되지 않도록 필터링을 적용하였습니다.

위와 같은 기준을 적용하여 KLUE 데이터셋과 ETRI 데이터셋의 비중을 달리 하여 여러 버전의 학습 데이터셋을 생성하였습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Wikipedia dataset

💻 위키피디아 메타 정보 분석

Retriever가 찾아야하는 context의 특징을 분석하고자 주어진 위키피디아 데이터셋에 대한 EDA를 진행했습니다. 진행한 EDA는 다음과 같습니다.

​​​​1. 적절한 top-k의 k값(비슷한 주제로 묶을 수 있는 context의 평균 개수)
​​​​2. context/answer의 평균적인 길이와 이상치
​​​​3. 문서의 형태
​​​​4. (EDA 시점까지 개발된) retriever 성능과 topk 예측 결과
​​​​5. 각 context에서 핵심 단어의 주목도

🔍 적절한 top-k의 k값

먼저, query가 특정 context에서만 specific한 경우도 있지만, 여러 context에 걸쳐 등장하는 인물/사건/장소 등에 대해 묻는 경우도 있었습니다. 이 경우 retriever가 context를 찾는 것이 어려울 수 있습니다. query가 general한 경우, 문맥상 동일한 title을 가진 context들을 retrieve하기 쉽다는 판단하에 unique한 title의 개수와, 한 title에 속한 context의 개수분포를 조사하여 이상적인 top-k 기본치를 설정하고자 했습니다.

총 31755개의 title을 기준으로, 한 title에 해당하는 context 개수 분포를 확인한 결과 약 3만개(약 95%)의 title이 5개 이하의 subcontext들을 가지고 있었습니다. 따라서 전체 문서를 보기 위해서는 retriever의 top-k가 5~10개 정도로 충분하다는 것을 알게 되었습니다.

실제로 이후 predict시에도 retriever의 top-k를 저희가 최적이라고 판단한 3~10 사이로 설정하였습니다.

🔍 Retriever 성능과 top-k 예측 결과

또, TF-IDF retriever 기준으로 top-10의 context를 뽑았을 때 retriever의 성능과 문제점을 정성적으로 파악했습니다. 약 3600개의 query 중 3200개(약 90%) 가량을 top-10으로 찾을 수 있었습니다. 다만 문제가 되는 부분은, query에서 본래의 context와 paraphrase된 단어가 등장했을 경우 retriever의 성능이 급격하게 떨어진다는 것이었습니다.

​​​​Q. 종교적 목적으로 파리 대학교에 교황이 세운 교육 기관은?
​​​​A. 동방 언어 학원

파리 대학교에는 교황에 의해 무슬림들의 개종과 동방 정교회와의 재일치를 위해 그들의 언어를 가르치려는 목적으로 동방 언어 학원이 설립되었다

위의 예시를 볼 때, context의 무슬림들의 개종과 동방 정교회와의 재일치라는 부분이 query에서는 종교적 목적이라는 어구로 paraphrase된 것을 확인할 수 있습니다. 이처럼 겹치는 단어가 등장하지 않고 변형된 어구가 등장할 때, TF-IDF retriever의 특성 상 오히려 query의 다른 부분에 주목하게 되어 결과적으로 top-10으로도 원문을 찾지 못하는 경우가 있었습니다.

생각보다 준수한 TF-IDF의 성능에도 불구하고 이러한 문제점 때문에 문맥상 유사한 어구를 잘 포착해낼 수 있는 Dense Retriever를 병용할 필요성을 느끼게 되었습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Model prediction analysis

💻 예측값 프로파일링

240개 validation example에 대한 해당 시점의 Best MRC model prediction과 ground truth를 비교하여 모델의 문제점을 파악하고 모델 개선의 방향성을 고민하였습니다.

총 240개 example에서 오답의 개수는 96개였는데, 이를 분류하였을 때 다음과 같은 형태로 정리할 수 있었습니다.

  1. 유사관계 : 형식은 맞지만 디테일이 다른 경우

    예측 : 1967년 8월 16일
    정답 : 1967년 11월 15일

  2. 포함관계 : 정답 어구의 일부분만을 예측하거나 정답 어구를 포함한 어구를 예측한 경우

    예측 : 도로스
    정답 : 대형 항공모함 도로스

    예측 : 마거릿 대처 전 영국 수상
    정답 : 마거릿 대처

  3. 의미/분류상 비슷한 관계

    예측 : 대부업
    정답 : 사채회사

  4. query와 전혀 관련없는 불용어

    예측 : 비록
    정답 : 가루아

  5. 서술형

    예측 : "어떤 경우에도 행할 수"
    답변 : 본국 의회가 식민지에 대한 입법을 “어떤 경우에도 행할 수” 있도록 하였다

1. 유사관계

모델이 문맥을 정확히 이해하지 못하고 '날짜' 등의 키워드에 집중하여 독해하였다고 판단하였습니다. 따라서 feature를 늘리든, 모델 사이즈를 늘리든 모델 자체 독해 능력의 개선이 필요했습니다.

2. 포함관계

총 48개로 오답의 절반을 차지해 처리가 꼭 필요한 유형이었습니다. EDA 시점의 best 모델은 EM 스코어와 F1 스코어가 약 16%가량 차이났는데, 다른 팀에 비해 적게는 3~4%, 많게는 6~7%정도 갭이 큰 상태였습니다. 사실 이 유형의 오답 중 대부분은 문맥으로 봤을 때 사실상의 정답이었지만, EM으로 인정되지 않는 것을 포착하고 이를 개선하고자 조사, 관사 등을 제거하는 등 모델의 예측을 후처리하는 개선으로 연결되었습니다. 또, 비록 스코어 개선에는 효과가 없었지만 MRC 모델이 뽑은 정답이 있는 문장을 복원하여 해당 문장에 대해 다시 독해를 수행하는 sentence pick technique을 제안하기도 했습니다.

3.의미/분류상 비슷한 관계

기존 단일 BERT 모델이 파악하지 못하는 문맥이 있다고 판단하였고, 추후 같은 query에 대해 상이한 답변을 내놓는 다른 모델과의 ensemble을 수행하는 것으로 이어졌습니다.

4.query와 전혀 관련없는 불용어

paraphrase된 query를 명확히 이해하지 못하여 범용성이 높은 답변을 내놓는다고 판단했습니다. nbest prediction을 확인하였을 때 정답이 score상에서 불용어에 밀려 순위권 하위에 존재하는 것을 포착했습니다. 따라서 사실상 query에 대해 정답일 가능성이 거의 없는 부사 등의 불용어들을 POS 태깅으로 분석하여 nbest rerank하는 후처리로 이어졌습니다.

5. 서술형

사실상 가장 개선하기 어렵다고 판단했던 오답으로, 기존 valdation set의 example들이 대부분의 답변을 단답형으로 요구했던 것과는 달리, 문장형으로 답변을 요구하는 경우였습니다. vaild set의 정답의 분포에 강건하게 학습시키기 위한 K-fold cross validation으로 이어졌습니다.

💻 예측 score 분석

240개 validation set에 대해 모델의 best-5 prediction을 뽑고, best-5 내의 정답 존재 여부prediction score/probability를 확인했습니다.

먼저 LB score의 기준과 동일하게 evaluate하기 위하여 기호, 띄어쓰기, 문장부호 등을 제거하여 ground truth와 prediction을 비교했습니다. top-5 안으로 정답을 찾지 못한 example은 240개중 총 45개였습니다. evaluate를 수행하지 않고 top-1 predict를 수행했을때에 비교하여 절반으로 떨어진 수치로, 모델의 예측이 생각보다 정답과 동떨어져 있지 않고, 적절한 reranking이나 후처리로 충분히 개선할 수 있음을 확인했습니다. 이후 POS 태깅을 통하여 부적절한 답을 걸러내는 후처리를 추가함으로써 EM 스코어를 올릴 수 있었습니다.

score에 주목하여 오답을 살펴보았을 때, 대부분의 best prediction score가 8을 넘어가지 못하는 것을 확인할 수 있습니다. 기존의 정답군 prediction score는 평균 12~15 사이이므로, prediction score가 어느 정도의 수치를 넘기지 못한다면 사실상 오답일 가능성이 높다는 점을 시사했습니다.

따라서 낮은 prediction score를 가지는 정답들을 nbest 내의 정답으로 대체하기 위한 다른 모델과의 ensemble로도 이어졌습니다.

예를 들어, Pororo MRC 모델과의 ensemble를 꼽을 수 있습니다. Pororo 라이브러리 MRC 모델은 Roberta를 베이스로 하는 모델인데, 내놓는 답은 기존 모델과 꽤 차이가 있었지만 올바르게 예측할 경우 top-1 prediction의 score가 13~16정도로 기존 모델과 거의 비슷했습니다.

따라서 기존 모델의 nbest 중, 모델이 정답을 확신하지 못해 best prediction score가 8이하로 낮으면서, 나머지 nbest prediction 중 (pororo가 내놓은) 정답이 있는 경우 pororo prediction score를 더해주는 형태로 예측을 ensemble했습니다. 비록 앙상블 복잡성의 문제로 최종 제출 모델에는 반영되지 않았지만 유의미한 성능 개선(LB스코어 38%->45%)을 확인했습니다.

이처럼 score를 분석함으로써 사실상 기존 모델이 확신하지 못하는 오답들에 대해 다른 모델의 예측을 수용하는 방식의 ensemble을 수행할 수 있었습니다.


Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Model

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Retriever

Retriever는 Wikipedia에서 query를 기반으로 연관된 문서를 찾아 주는 모델입니다.

Embedding 벡터를 생성하는 방식에 따라, Term Frequency를 사용하여 생성된 Sparse Embedding을 활용하는 Sparse Retriever와 CLS Token을 사용하여 생성된 Dense Embedding을 활용하는 Dense Retriever로 나눌 수 있습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Sparse Retriever

저희 팀에서는 기본 베이스라인 코드로 구성된 TF-IDF를 사용하는 데 그치지 않고, TF-IDF보다 성능이 좋다고 알려져 있는 BM25를 구현하여 리트리버의 성능을 비교하는 실험을 진행했습니다.

기존에 존재하는 BM25 오픈소스는 하나의 query를 기준으로 문서를 retrieve하는 과정에서 매번 context의 embedding을 새로 만들기 때문에 시간이 오래 걸려 효율이 떨어진다는 단점이 존재했습니다.

그래서 sklearnTfidfVectorizer를 활용하여 전체 context를 대상으로 TF, IDF를 계산한 후 저장하고 임베딩은 한 번만 계산하도록 수정하여 BM25 score를 구할 때 이를 재사용하는 방향으로 코드를 리팩토링하여 전체 코드의 실행 속도를 향상시켰습니다.

Sparse Retriever 실험 1: BM25가 TF-IDF보다 우월한가?
Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
TF-IDF

TFIDF는 단어의 등장 빈도(Term의 Frequency)를 활용하여 문장을 추출하는 가장 기본적인 방법으로, 단어의 등장 빈도(Term Frequency, TF)와 단어가 제공하는 정보의 양(Inverse Document Frequency)을 이용한 지표입니다.

이 때

t는 단어(term),
d
는 문서,
D
는 전체 문서의 수
를 의미합니다.

베이스라인 코드에서 구현된 TF-IDF 기준, top1에서 22.08%의 정확도를, top30에서 63.75의 정확도를 보였습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
BM25

BM25 역시 단어의 등장 빈도를 활용한 방법 중 하나입니다. BM25에서 주목할만한 점은, 길이가 긴 문장들이 많은 단어를 가지고 있음으로 인해서 가지게 되는 우위를 조정하기 위해 문서의 길이를 전체 문서 길이의 평균으로 나누어주는 부분을 추가했다는 점입니다.

위 식에서 분모 부분에

D
avgdl
로 나누어 주는 부분이 포함된 것을 확인할 수 있으며, 이 식의 영향력을 조정해주는 변수로
k1
b
가 추가되었습니다.

가로축은 TOP-K, 세로축은 Accuracy를 나타냅니다.

TFIDF와 BM25의 성능을 비교한 결과, BM25가 TFIDF에 비해 성능이 좋아서 최고 성능의 Retriever가 등장하기 전까지 BM25를 사용하였습니다.

Sparse Retriever 실험 2: Term vocab을 구성할 때 max_features를 주는 것이 좋을까?

TOP-K가 크고 xticklabel을 그대로 입력하여 가독성이 좋지 않습니다. TOP-K 1000으로 한 결과입니다.

베이스라인 코드에서는 sklearn 라이브러리에서 제공하는 max_features argument를 사용하여 vocabulary의 크기를 제한하고 있었는데, term frequency가 높은 순으로 vocabulary에 포함되기 때문에 적게 나온 term들이 포함되지 않는다는 이슈가 있었습니다.

이렇게 되면 중요한 term들이 누락될 수 있다고 생각해서 max_features argument를 없애고 실험했더니 성능이 대폭 상승했습니다.

Sparse Retriever 실험 3: 토크나이저에 따라 성능이 다를까?

Term의 기준이 달라진다면 BM25의 성능도 달라질 것이라고 판단하여, 다양한 Tokenizer들로 실험한 결과, 초반 Top-k에서 XLM-Roberta-Large Tokenizer가 비교적 높은 성능을 보였고 그 이후에는 Kobert가 높은 성능을 보였습니다. 이를 바탕으로 XLM-Roberta-Large를 사용하기로 결정했습니다.

Sparse Retriever 실험 4: BM25의 다양한 버전 별로 성능이 다를까?

BM25는 위의 식을 기본 base로 한 다양한 변형들이 존재하며 저희 모델에서는 다양한 BM25들을 가지고 실험한 논문을 바탕으로 ATIRE BM25, BM25L, BM25+의 세 가지 BM25를 구현하였습니다.

세 가지 버전의 BM25의 성능을 비교한 결과, ATIRE BM25가 가장 낮은 top-k(6)로 90%에 도달하는 것을 확인하여 ATIRE BM25를 사용하는 것으로 결정했습니다.

Sparse Retriever 시도했으나 실패한 실험들
  • wiki 문서 중복 제거

wiki 문서에 중복이 많은 것을 발견하여, 중복을 제거하면 top-k 내에서의 중복이 제거되므로 성능이 향상될 것으로 생각해서 중복을 제거하였으나 validation set 기준 큰 성능 향상은 없었습니다.

하지만 reader에게 넘겨줄 때 중복이 없는 문서가 넘어가는 것이 궁극적으로 성능 향상에 기여할 것으로 판단하여 retrieve 시 중복 문서가 존재하면 제거하는 방향으로 코드를 개선하였습니다.

  • wiki 문서 요약 후 BM25를 이용한 추출

한국어 자연어 처리 라이브러리인 PORORO를 이용하면 문서에서 가장 중요한 세 문장을 추출하는 방식으로 문서를 요약할 수 있습니다.

이렇게 search space를 축소하여 query와 유사한 문서를 찾는다면 성능이 올라갈지 궁금해서 PORORO를 이용하여 요약 후 query를 뽑는 방식을 진행해 보았는데 요약 전과 성능이 비슷하게 나왔습니다.

문서의 길이가 짧아져 정보가 축소되었음에도 성능이 떨어지지 않은 점도 신기하지만, 성능이 상승하지는 않았으므로 실패한 실험에 넣었습니다.

  • BM25 hyper parameter 탐색

BM25는

b
k1
이라는 hyper parameter가 존재하고, 이를 조정함으로써 성능을 변화시킬 수 있습니다. 논문에 나온 hyper parameter 외에, 많이 사용된다고 알려진 b=0.75, k1=1.2를 비롯한 다양한 범위의 hyper parameter들을 적용하여 보았으나 논문에 나온 b=0.3, k1=1.1이 가장 높은 성능을 보였습니다.

  • BM25 다양한 데이터 변형 적용

sklearn에서 제공하는 기능들을 활용하여, Term frequency에 smoothing을 주고, Term frequency를 normalize하는 등 여러 데이터 변형을 적용해 보았으나 성능 향상이 없었습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Dense Retriever

ODQA에서 Retriever의 역할은 사용자 질문(이하 쿼리)에 대한 답변이 될 수 있는 문서를 추출하는 것입니다. 이 과정에는 전통적으로 본 글에서 언급된 TF-IDF, BM25 등의 Sparse Retriever들이 활용되었습니다.

그러나 최근에는 신경망을 이용해 쿼리와 제공된 문서의 Dense vector 간의 내적을 극대화하는 것으로 근거 문서를 추출하고 있습니다. Sparse vector가 단어 집합 크기의 차원과 One-Hot 벡터로 표현 되는 것과 달리 Dense vector는 Hidden Size및 Latent Vector로 표현됩니다.

또한 Sparse Vector는 Lexical Overlap이 중요하게 활용되어야 하는 QA task에, Dense Vector는 Semantic한 해석이 활용되어야 하는 QA task에 적용될 수 있습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
DPR

DPR은 Dense Vector를 활용하는 Retrieve를 수행하되, Answer Extraction을 수행하는 Document Reader와 관련 문서를 뽑아오는 Passage Retrieve를 별도로 훈련하여 활용하는 방안을 제시하였습니다.

이 중 Retriever를 담당한 파트에서는 2개의 BERT 모델을 활용해 Passage Retriever를 구성하고자 했으며, Encoder로 사용한 Backbone모델과 Negative Sampling 방식을 다르게 구현하여 두가지 실험을 진행하였습니다.

첫 번째 방식bert-base-multilingual-cased를 Backbone으로 하여 쿼리를 인코딩하기 위한 BERT 모델과 문서 집합을 인코딩하기위한 BERT 모델을 파인튜닝한 방식입니다. 이 훈련 과정에서는 다른 질문에 대한 답을 포함한 문서를 Negative Sample로 설정하는 In-batch Negative 방식을 선택하였으며 positive sample에 대한 negative log likelihood loss를 활용해 훈련을 진행하였고 optimizer로는 AdamW, 0.01 수준의 weight decay를 설정한 스케줄러, 30번의 epochs 등의 파라미터 설정을 통해 Reader에게 전달할 Top3 문서의 신뢰도를 50~63% 수준으로 확보하였습니다.

두 번째 방식haystack 오픈소스를 활용해 transformers의 DPRContextEncoder와 DPRQuestionEncoder 두가지 인코더를 파인 튜닝하는 방식(💻실험 노트북)입니다.

Negative Sampling 방식으로는 BM25에 의해 높은 순위권에 해당하지만 정답 스팬은 포함하지 않는 Negative Sample로 설정한 방식을 활용하였고, 이때 필요한 💻dataset을 생성하여 Robust한 Dense Encoder를 만들기 위해 노력하였습니다.

또한 DPR을 사용한 인덱싱은 모든 문서 집합을 변환하는 과정을 매번 거치기 때문에 InMemoryDocumentStore를 함께 작동시켜 계산 효율을 높였습니다. 그러나 안타깝게도 이 실험을 통해 Reader에게 전달할 Top3 문서 신뢰도는 9~18%수준에 머물렀습니다.

성능이 낮은 이유를 회고해보면,
(1) 모델 학습 시 4192개의 수준으로 적은 데이터셋만을 의존했다는 점
(2) dense encoder로 들어가는 context의 chunk 사이즈를 다양하게 변화시키지 않았다는 점
(3) optimal한 hyper parameter을 찾으려는 실험 관리 전략이 부재했다는 점을 들 수 있겠습니다.

[ Negative sampling에 필요한 데이터셋 재구축 예시 ]

    {
        "dataset": "klue-train-psgs_2100",
        "question": "처음으로 부실 경영인에 대한 보상 선고를 받은 회사는?",
        "answers": [
            "한보철강"
        ],
        "positive_ctxs": [
            {
                "text": "순천여자고등학교 졸업, 1973년 이화여자대학교를 졸업하고...",
                "title": "전효숙",
                "score": 731.0,
                "title_score": 0,
                "psg_id": 9027
            }
        ],
        "negative_ctxs": [],
        "hard_negative_ctxs": [
            {
                "title": "바운더리 거리",
                "text": "1860년에 있었던 제2차 아편 전쟁의 결과로 베이징 조약에서 주룽 반도의 홍콩 섬에 가까운 지역의 ...",
                "score": 41.86300700253766,
                "title_score": 0,
                "psg_id": "4459"
            },
                      {
                "title": "윤치호",
                "text": "이후 윤치호는 계몽운동에 진력하며 실력 양성론을 주장하였다. 그의 실력 양성론은 후....",
                "score": 41.862880985791804,
                "title_score": 0,
                "psg_id": "5294"
            },
          ...
        ]
    },
Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
ColBert

ColBert는 Context Level 수준의 상호작용으로 문서를 검색하던 기존 Dense Retriever에서 더 나아가서 Token Level 수준의 상호작용으로 문서를 검색하는 방법입니다.

dense-retriever-types

ColBERT: Efficient and Effective Passage Search via Contextualized Late Interaction over BERT
Omar Khattab, Matei Zaharia

베이스라인 코드에서 제공된 DPR 모델이 (1)에 해당하는 방법론이고 (3)에 해당하는 방법론이 ColBert모델입니다.

Dense Retriever가 Sparse Retriever의 성능을 뛰어넘은 것이 최근에 일어난 일이라는 점을 고려하여 Dense Retriever를 잘 활용하기 위해서는 (3)에 해당하는 ColBert를 구현해야 된다는 생각이 들었습니다.

다만 ColBert를 구현했음에도 불구하고 성능 측정 및 사용을 하지 못했는데 그 이유는 아래와 같습니다.

  1. Dense Retriever의 특성상 속도 향상을 위해 문서 임베딩을 미리 저장해야 되는 점
  2. 한 개의 CLS Token 대신 512개의 Token을 저장함으로써 저장공간이 부족했다는 점

서버의 저장 공간이 50G가 밖에 되지 않아서 Embedding을 저장한 후 Query Encoder를 저장할 공간이 부족하여 사용하지 못했습니다.

너무 아쉽습니다..

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Hybrid Retriever

Sparse vector와 Dense vector를 결합하여 Retrieve를 시도하는 논문들을 접하며 Hybrid Retriever의 필요성을 느끼게 되었습니다.

저희가 구현한 모델은 retrieve 과정에서 Sparse/Dense vector들을 결합하는 방식은 아니지만,

  1. Sparse Retriever와 Dense Retriever가 도출한 문서 유사도를 Weightd RankFusion하여 문서의 순위를 재조정하는 Weighted RankFusion Retriever

  2. Sparse Retriever가 추출한 문서 Score에서 Feature Vector를 추출한 후 Logistic 분류기를 통해 Sparse Retriever와 Dense Retriever 사용 여부를 결정하는 Logistic Hybrid Retriever 입니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Weighted RankFusion Retriever

Weighted RankFusion Retriever는 Sparse와 Dense Retriever가 도출한 topk의 문서 유사도를 Weighted RankFusion하여 문서의 순위를 재조정하는 방식입니다.

두 개의 Retriever가 도출한 문서들이 중복 될 경우 문서 중요도를 높이는 것에서 더 나아가, 하나의 Retriever의 상대적인 기여도를 가중치로 활용해 두 종류의 결과값을 정규화된 가중 합계로 구성하는 방식입니다.

이러한 접근은 topic 중요도를 rerank하는 참고 논문pyserini 오픈소스에서 제안된 공식을 바탕으로 생성되었습니다. 해당 공식을 바탕으로 Sparse Retriever의 상대적인 기여도(alpha)를 0.1로 조정하였고, 이 값은 차원 수에 따라 달라지는 Dense Retriever가 반환하는 유사도 점수의 분포에 따라 재조정될 수 있습니다.

0.1의 값은 Sparse Retriever, Dense Retriever의 성능을 고려하여 결정하였습니다.

    def _rank_fusion_by_hybrid(self, dense_hits, sparse_hits, topk):
        ranks = []
        min_dense_score, min_sparse_score = min(dense_hits.values()), min(sparse_hits.values())

        for doc in set(dense_hits.keys()) | set(sparse_hits.keys()):
            if doc not in dense_hits:  
                score = self.args.retriever.alpha * sparse_hits[doc] + min_dense_score
            elif doc not in sparse_hits:  
                score = self.args.retriever.alpha * min_sparse_score + dense_hits[doc]
            else:  
                score = self.args.retriever.alpha * sparse_hits[doc] + dense_hits[doc]

            ranks.append((doc, score))

        ranks = sorted(ranks, key=lambda x: x[1], reverse=True)[: topk]
        doc_index, doc_score = zip(*ranks)
        doc_index, doc_score = list(doc_index), list(doc_score)

        return doc_score, doc_index
Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Logistic Hybrid Retriever

Sparse Retriever와 Dense Retriever는 주어지는 문서 특성에 따라 상이한 성능을 가져옵니다. 만약 IR 과정에 Sparse Retriever와 Dense Retriever를 선택해서 IR을 할 수 있다면, 하나의 Retriever를 사용하는 것보다 더 좋은 성능 향상을 얻을 것이라고 판단했습니다.

따라서 이 논문을 참고해 BM25로 쿼리와 문서 간 유사도를 내림차순한 결과값(S)을 도출한 뒤, 상위

2k(
k
는 feature size)개의 원소를 대상으로 softmax로 정규화하였으며 아래 수식으로 유도되는 feature vector 원소를 feature_size만큼 구성하여 Logistic Regression을 진행하였습니다.

fi=mean(S[0:2i])(i=1,2,..,feature size)

학습 데이터셋의 경우 feature vector와 TOP-k bound내에 정답 문서가 포함되어 있는지 안 되어있는지를 기준으로 X, Y 데이터 셋을 구축하였습니다.

feature-vector

feature size와 kbound는 각각 3으로 설정하였습니다.

feature vector는 feature size의 크기가 클수록 더 많은 정보를 담고 있습니다. 그래서 원래는 feature size가 4일 때 더 많은 정보를 가졌어야 했지만 T-SNE 알고리즘으로 시각화를 진행했을 때 feature size가 4일 때와 3일 때 큰 변화를 띄지 않았고 이는 추가된 정보가 기존 정보와 큰 변화가 없음을 의미합니다. 그래서 feature size는 3이면 정보를 표현하기에 충분하다고 판단을 했습니다.

kbound를 설정할 때는 세 가지를 고려하였는데

  1. Sparase Retriever의 TOP-K 그래프가 K 어느 값에서 기울기가 미미한지를 고려하였고
  2. 분류기의 학습 데이터셋을 Imbalance하지 않게 구축하는 것을 고려
  3. 마지막으로 임베딩 공간 상에서 군집을 잘 형성하는지

위의 세 가지에 해당하는 kbound는 3으로 설정하였는데, 밸런스한 데이터셋을 구축할 수 있는 적절한 값이었고 TOP-3 이후로는 Sparse Retriever의 성능이 미미하게 증가했습니다. 마지막으로 kbound값이 4인 경우 형성된 오렌지 군집에 파란색 점이 증가하는 것을 확인할 수 있습니다. kbound가 3일 때는 이런 경향이 덜 했습니다.

정리해보자면 TOP-8을 뽑아와서 feature size가 3인 feature vector를 만들고 TOP-3안에 정답이 있을 경우 1, 없을 경우 0인 데이터셋을 만들어 학습을 진행했습니다.

위 데이터로 학습시킨 Logistic 분류기를 사용하여 Sparse Retriever에만 의존하는 대신 feature vector를 추론한 값이 임계값보다 낮을 시 Dense Retriever를 사용하는 방법을 구현하였습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Sparse / Dense / Hybrid Retriever 성능 비교

fig_image

다양한 Retriever들을 설계한 목적은 Reader에게 문서를 최대한 간결하고 정확하게 전달하는 것에 있었습니다. 설계 목적에 부합하는 Retriever를 선별하기 위해 4가지 시나리오를 통해 마련된 Retriever간 성능을 비교하였습니다.

  1. [Sparse] BM25
  2. [Dense] In-batch negative sampling 방식으로 구현된 DPR
  3. [Hybrid] Weighted RankFusion 방식으로 조합된 BM25와 DPR
  4. [Hybrid] Logistic Regression 과정 이후 맞물리게 동작하는 BM25와 DPR

유관 문서 중 3개의 문서를 가장 정확하게 전달하는 Retriever은 4 > 1 > 3 > 2 순이었으며, top-k 상한을 늘려갈수록 3 > 4 > 1 > 2 순으로 정확도가 향상되었습니다. 본 실험을 통해 Hybrid Retriever의 우수성 및 활용 가능성을 확인할 수 있었습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Reader

Reader는 주어진 질문과 Retriever로부터 검색된 문서간 관계를 파악하여 정답의 위치를 도출해내는 모델입니다. 문서에 존재하는 각 토큰이 정답의 시작 위치일 확률(logit)과 정답의 마지막 위치일 확률(logit)을 각각 구하여 이들의 합이 최대가 되는 문자열을 정답으로 예측합니다.

데이터의 양이 적었기 때문에 저희는 한국어 pretrained backbone 모델을 최대한 활용하고자 하였으며, 주로 뒷단의 head를 fine-tuning 하는 데에 집중하였습니다. 그 외 학습 단계에서 지문의 일부를 masking하거나 모델의 예측을 돕는 임베딩 토큰을 추가로 활용하기도 하였습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Head fine-tuned

장비의 한계 및 데이터 부족으로 백본의 구조를 바꾸어 모델을 처음부터 pretrain할 수는 없었습니다. 따라서 백본의 구조는 그대로 두되, Head 구조를 어떻게 바꾸면 성능이 더 좋을지 연구해보았습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Dense based(DPR)

dense

Dense based head는 QuestionAnswering task에서 가장 범용적으로 사용되는 head 구조입니다.

weight parameter 수가 상대적으로 적은 편이라 처음에는 이 헤드가 많은 정보를 표현해내지 못할 것이라고 생각했지만 의외로 다른 헤드와 충분히 견줄 수 있을만한 성능을 보였습니다.

backbone의 사이즈가 이미 거대하기 때문에 head의 input vector에는 이미 많은 정보가 담겨있어 잘 동작했던 것으로 추측됩니다. 헤드에는 오히려 노이즈 없이 양질의 vector값만 들어가기 때문에 추가적인 레이어를 통한 input 값의 큰 조정이 필요하지 않을 것입니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
CNN based

CNN

CNN 기반 모델은 'start/end logit을 구할 때 한 개의 word token만 봐도 되는걸까?'라는 의문에서 시작되었습니다.

Dense based head는 토큰 한 개의 임베딩(768차원)을 input으로 받아 해당 토큰에 대한 start logit과 end logit을 내놓습니다. 그런데 실제 답은 대부분 2개 이상, 많게는 10개 이상의 토큰으로 이루어져있습니다.

그렇다면 dense layer의 약점은 무엇일까요? 예를 들어 아래와 같은 질문을 봅시다.

박지훈은 1라운드에서 몇 순위를 차지했는가?

이 질문의 정답은 전체 4순위입니다. 튜닝 이전의 모델은 이에 대한 답으로 4순위를 예측했습니다. 예측이 완전히 틀린 것은 아니지만, 보다 디테일한 정보를 완벽히 담아내지는 못했습니다. 저희는 그 이유가 모델이 로짓값을 내놓을 때 토큰 한 개만을 보았기 때문이라고 생각했습니다.

CNN in NLP

Understanding how Convolutional Neural Network (CNN) perform text classification with word embeddings

1D CNN을 이용하면 이러한 문제를 일부 극복할 수 있습니다. CNN의 경우 dense layer와 달리 span 2 이상의 embedding vector들을 한 번에 고려할 수 있기 때문입니다. 위와 같은 문제에서도 전체 4순위 라는 큰 단위의 토큰을 기준으로 start/end logit을 도출해내므로 전체 토큰에도 높은 수준의 start logit이 부여되는 효과를 기대할 수 있습니다.

물론 backbone이 self-attention 구조이므로 head로 들어가는 벡터는 이미 주변 context를 고려하여 생성되기는 합니다. 하지만 일반적인 self-attention 구조는 전체 context를 균일하게 고려하지, 주변 word에 더 큰 가중치를 주지는 않습니다. Q/K/V matrix가 주변 word에 더 가중치를 줄 수 있도록 학습될 수 있지만 모든 context에 대하여 실제로 그러한 효과를 줄 수 있는 방향으로 학습되고 있는지는 현실적으로 직접 판단하기 어렵습니다(blackbox). 하지만 head에 CNN을 활용한다면 보다 명확하게 주변 word에 더 큰 가중치를 부여하는 효과를 기대할 수 있습니다.

이 모델을 통해 LB 기준 EM에서 약 2% 가량의 성능 향상을 얻을 수 있었습니다.
CNN_visualization

Validation set 기준 F1 score 및 EM score

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
CNN_v2

CNN_v2

이전 CNN 헤드를 설계하면서, 해당 모델이 768채널을 바로 2채널로 축소하므로 정보를 고르게 담아낼 수 없겠다는 생각이 들었습니다. CNN을 쌓아가면서 채널을 조금씩 축소하는 방법도 생각해보았지만, 모델의 복잡도가 너무 커질 것 같다는 우려가 있었습니다. 결론적으로 먼저 CNN 층을 통해 768채널을 256채널로 축소 후 concat하여 마지막에는 FC layer를 통과시키는 방법을 고안하였습니다.

벡터 크기의 급격한 축소로 인한 정보 손실을 방지할 수 있는 한편, 모델의 복잡도 또한 이전과 거의 비슷하게 유지할 수 있으므로, 결과적으로 이 모델은 이전 모델의 장점은 최대한 살리되 단점은 제거할 수 있습니다.

또한 CNN층과 Linear층 사이에 Dropout을 추가하였습니다. 우리에게 주어진 학습 데이터는 약 4000개 정도입니다. 모델의 복잡도에 비해 턱없이 적은 양이라고 생각했고, 이렇게 되면 모델이 적은 epoch에서도 금방 overfitting 될 우려가 있습니다.

저희는 Dropout을 통해 이를 해결하고자 하였고, 다양한 Dropout 수치를 실험해본 결과 0.5 이상의 비교적 높은 수치에서 유의미한 성능 향상이 나타나는 것을 확인하였습니다. 모델의 사이즈는 크고 학습 데이터의 양은 적은, 어떻게 보면 다소 비정상적인 구조였기 때문에 Dropout 수치를 크게 높이는 것이 유효했던 것 같습니다.

이전 CNN 모델에 비해 LB 기준 성능 향상은 거의 없었지만, Validation set 기준 시각화해보았을 때 어느정도 의미있는 성능 지표를 보였다고 생각합니다.
CNN_v2_visualization

Validation set 기준 F1 score 및 EM score
학습 step수가 상이하여 train_samples_per_second는 바르게 출력되지 않았습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
CNN-LSTM based

CNN-LSTM

CNN-LSTM 모델은 backbone의 output이 먼저 LSTM을 거친 이후, 다시 위에서 제시한 CNN_v2를 통과하는 구조로 이루어져있습니다.

이 모델을 통해 저희는 CNN보다 더욱 강력하게 주변 단어에 가중치를 실어주고자 하였습니다. LSTM과 같은 RNN 구조의 경우 sequence의 길이가 길어지면 앞단 input의 영향이 조금씩 소실되는 문제점이 있습니다. 하지만 거꾸로 생각하면 RNN 기반 구조는 멀리 있는 단어보다 주변 단어에 자연스럽게 더 큰 가중치를 실어줄 수 있습니다.

따라서 Bi-Directional LSTM을 통해 양방향의 주변 단어를 중점적으로 고려한 새로운 임베딩을 생성할 수 있다고 생각했습니다.

다만 이 모델을 통해 기대했던만큼의 성능 향상을 얻지는 못했습니다. 일단 LSTM을 붙인 이상, 모델의 복잡도가 급격히 증가하게 된다는 단점이 있고 이는 앞서 언급했던 overfitting 문제와도 연결됩니다.

이러한 문제점을 해소하기 위해 헤드 단의 모델 복잡도를 키우고 backbone은 프리징하여 학습하는 방법도 고안해보았지만, 결과적으로 실패하였습니다. 실패한 이유는 역시 데이터셋이 적다보니 backbone이 저희의 학습 데이터에 어느정도 fine-tuning 될 필요성이 있었기 때문일 것입니다.

성능상으로는 큰 효과가 없었지만, 그럼에도 만약 데이터가 많고 head를 빠르게 바꾸어가며 튜닝해야하는, 저희의 실험환경과는 조금 다른 상황이었다면! backbone을 프리징하고 LSTM을 포함한 뒷단의 모델만을 학습시키는 방식으로 CNN-LSTM 구조를 활용할 수 있지 않을까라는 생각이 들었습니다.

CNN-LSTM_visualization

Validation set 기준 F1 score 및 EM score
학습 step수가 상이하여 train_samples_per_second는 바르게 출력되지 않았습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Exact Match(EM) embedding

ODQA의 포문을 연 Reading Wikipedia to Answer Open-Domain Questions 논문을 리뷰하면서 모델이 학습을 잘 할 수 있도록 추가적인 feature를 model의 input으로 함께 넣어주는 아이디어를 얻게 되었습니다. 모델에게 일종의 힌트를 제공하는 것이라고 볼 수 있는데, 힌트의 질이 좋다면 모델의 학습에도 도움이 될 것입니다.

그 중에서도, 저희는 해당 논문에서도 활용하고 있는 Exact Match feature(이하 EM feature)를 넣어보기로 하였습니다. EM feature는 지문과 질문 간 공통 토큰에 특정 임베딩 값을 더해주는 방식으로 활용합니다.

아래와 같은 질문/지문 쌍을 예로 들겠습니다.

Question
문법 측면에서 더 보수적인 포르투갈어 표준은?

Context
... 브라질 포르투갈어와 유럽 포르투갈어는 현재 별도의 유사한 철자 표준을 각각 두고 있다 ...

위 예시에서는 포르투갈##어 토큰이 질문과 지문에 공통으로 존재합니다.

따라서 아래와 같이 지문의 해당 토큰 위치에 기학습된 임베딩 값을 더해줍니다.

exact-match

일치/불일치 여부로 binary 토큰(

E0 혹은
E1
)을 더해주는 방식도 생각해보았지만, 저희는 위와 같이 토큰의 위치별로 EM feature의 값을 달리하여 더해주었습니다. 우선 정답 위치가 질문별로 고르게 퍼져있을 경우 전체 위치의 EM embedding이 비슷한 값으로 학습될 것입니다(binary와 비슷한 효과). 그리고 만약 서로 다른 지문들에서 정답이 비슷한 곳에 위치한다면, binary로 더해줄 때보다 지금의 방식이 모델에게 더 강력한 힌트를 줄 수 있을 것이라고 생각했습니다.

이와 같이 EM embedding을 더해주면, 궁극적으로 지문이 정답을 찾을 때 어느 부분이 찾고자하는 답과 연관되어있는지 알 수 있습니다. 참고 논문에서도 강력한 방법이라고 제시하였고 실제로도 의미있는 방법이라고 생각하였습니다.

다만 아쉬웠던 점은, 이러한 임베딩을 함께 활용하였는데도 이전과 성능은 비슷하였다는 점입니다. 이에 대한 원인 분석을 해보자면,

1. backbone과 head 사이에서 EM embedding을 더해주었다.

저희가 활용한 모델 구조는 아래와 같습니다.
em-architecture

처음에는 backbone에 들어가기 이전에 미리 EM embedding을 더해주려고 하였습니다. 하지만 저희는 pretrained model을 가져와서 사용하고 있기 때문에 backbone 이전에 embedding layer을 하나 더 추가하기는 어려웠습니다. 따라서 저희는 backbone을 통과하고 나온 토큰별 임베딩에 EM embedding 값을 더해준 후 head단으로 이를 넘겨주었습니다.

즉, 현재 모델 구조에서는 처음부터 EM embedding을 넣어주지 않았기 때문에 backbone에서는 우리가 의도한 형태의 학습을 진행하지 못합니다. 우리의 모델에서 가장 거대한 부분이 바로 backbone단인데 이 부분이 의도한대로 학습을 진행하지 못한다는 점은 전략에 있어서 큰 약점이 되었다고 생각합니다.

2. EM embedding이 모델에게 유의미한 힌트를 줄 수 있을까?

1번 이유와도 연결되는데, 사실 self-attention 구조는 EM embedding이 가져올 수 있는 장점을 이미 어느정도 가지고 있습니다. self-attention 연산 시에 동일한 토큰 간의 내적값은 최대가 되기 때문입니다. 따라서 모델은 이미 EM embedding 없이도 의도하는 바와 유사한 형태의 학습을 하고 있었을 것입니다.

하지만 저희는 Head단에서 한 번 더 Exach match 부분을 강조하는 것이 여전히 효과가 있을 만하다고 생각합니다. 따라서 이 부분이 진짜 성능 저조의 원인이었을지는 여전히 의문으로 남습니다.

3. EM embedding layer가 충분히 학습되지 못했을 것이다.

이 방법이 유효하려면 무엇보다도 많은 양의 데이터를 통해 EM embedding layer의 학습이 충분히 이루어졌어야 할텐데 약 4000개 가량 되는 데이터셋으로는 상당히 어려웠다고 생각합니다. 저희 competition 데이터셋의 정답 위치 분포와 KorQuAD 등 공개된 데이터셋의 정답 위치 분포가 어느정도 차이를 띄었기 때문에 추가적인 데이터셋을 활용하기에도 어려움이 있었습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Span masking

BERT 모델은 input 단어의 일부를 masking하고 이를 예측하는 방식의 학습법을 활용하고 있으며, 실제로 이러한 방식의 학습은 효과를 인정받고 여타 많은 모델에서도 현재까지 활용되고 있습니다.

저희 역시 이 방법이 저희 task에 fine-tuning할 때 함께 활용하기에 적절하다고 판단, input token의 일부를 마스킹하여 학습하는 방식을 활용해보았습니다. 특히, 앞서 CNN 모델을 활용한 이유과 같은 맥락에서 저희는 SpanBERT의 Span masking 학습 방법을 활용하였습니다.

Spanbert

SpanBERT: Improving Pre-training by Representing and Predicting Spans.
Mandar Joshi, Danqi Chen, Yinhan Liu, Daniel S. Weld, Luke Zettlemoyer, Omer Levy

Span masking은 위와 같이 연속된 sequence를 한번에 masking하는 방법입니다. 특히 저희 task에서는 내놓은 예측에서 token이 하나라도 빠지면 EM score를 얻지 못하기 때문에 연속 masking을 통해 얻을 수 있는 이점이 더 크다고 생각했습니다.

하지만 이 방법을 사용했을 때에도 성능 향상이 크게 없었습니다. 역시 원인을 생각해보자면

1. 정답까지 masking 될 수 있다.

random masking을 활용하였기 때문에, 정답의 일부가 masking될 수 있습니다. 이렇게 되면 모델이 정답 자체를 보지 못하기 때문에 학습에 치명적일 수 있습니다.

다만 정답 자체가 3개 이상의 토큰으로 이루어진 경우도 있었으므로 이게 진짜 원인인지는 좀 더 생각해볼 문제인 것 같습니다. 오히려 정답의 일부만이 masking된 문서에서 모델이 masking되지 않은 나머지 정답이라도 뽑아낼 수 있도록 학습된다면 보다 강건한 모델을 구축할 수 있을 것입니다.

2. masking의 위치를 한정해볼 생각을 하지 못했다.

추후 회고 세션에서 다른 팀에게 듣기로는, context는 masking하지 않고 question만을 masking했을 때 성능이 크게 향상되었다고 합니다. 저희는 처음에 masking 방법을 구현하고 성능이 안나왔을 때, 이 방법을 더 고도화할 방안을 생각하지 못했고 그냥 마스킹 방법을 사용하지 않기로 결정했습니다. 조금만 더 생각해보았으면 여러 시각에서 실험을 진행해볼 수 있었을텐데, 기존 방법을 더 발전시켜나가지 못한 점은 아쉬우면서, 또 반성할 부분입니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Sentence Pick & Re-predict

우리 모델의 예측이 실제 정답과 크게 다르지 않다는 점을 발견하고 생각해낸 아이디어입니다.

앞서 EDA 파트에서도 언급하였지만, 저희는 모델이 내놓은 예측에 대한 EDA를 진행하면서 정답과 예측값이 서로 포함관계인 경우가 많다는 점을 확인했습니다. 예를 들어 아래와 같은 사례가 존재합니다.

## 예측 ⊂ 정답
질문: 러셀은 누구의 가족과 함께 1889년 파리 박람회에 갔는가?
정답: 퀘이커 교도였던 앨리스 페어살 스미스
예측: 앨리스 페어살 스미스

## 정답 ⊂ 예측
질문: 악단이 재정적으로 힘들 때 단원들은 어디서 돈을 벌었는가?
정답: 카바레나 클럽
예측: 카바레나 클럽 등에서 부업

위 사례들은 모델이 예측을 잘 내놓았지만, EM score를 얻지 못하는 케이스입니다. 240개 가량의 validation set에서 무려 200개 이상의 예측이 정답과 포함관계였습니다. 이러한 부분을 잘 활용하려면 어떻게 해야할까요? 저희는 그 열쇠가 질문과 지문간의 관계를 파악하는 모델을 새로 설계하는 데에 있다고 생각했습니다. 즉, ① Retriever가 문서를 뽑아내고 ② Reader가 정답의 위치를 찾은 이후 ③ 이 모델이 질문의 의도를 파악하여 최종 정답을 뽑아내는 것입니다.

하지만 이 방법도 결국 활용하지 못했습니다. 활용하지 못한 가장 큰 이유는 저희 데이터셋에 있는 질문들이, 그 의도가 불분명하다는 점때문이었습니다.

아래 예시를 봅시다.

지문: 2020년 4월 4일, 도널드 트럼프 미국 대통령이 나렌드라 모디 인도 총리에게 말라리아와 
루푸스 치료제인 하이드록시클로로퀸 출하를 요청했다.
질문: 인도 총리에게 말라리아와 루푸스 치료제를 보내달라고 요구한 인물은?
답: '도널드 트럼프 미국 대통령'
---
지문: 유진길과 그의 동료들의 호소문으로 인하여 1831년 9월 9일에 교황 그레고리오 16세는
조선에 베이징에서 분리된 하나의 대목구를 설정했고 파리 외방전교회의 바르톨로메오 브뤼기에르
신부를 그곳의 초대 주교로 임명했다. 
질문: 1831년 조선 대목구의 첫 주교 직위를 맡은 사람은?
답: '바르톨로메오 브뤼기에르'

저희는 처음에 답에 직위명인 미국 대통령, 신부 등이 일정한 규칙에 따라 포함되거나, 포함되지 않을 것으로 예상했습니다. 다만 위와 같이 실제로는 그럴듯한 규칙이 없었고 결국 저희가 기존에 생각했던 질문의 의도는 따로 존재하지 않는다는 것을 확인하였습니다.

이 모델을 활용했을 때 성능이 조금 상승하기는 하였으나, 성능 상승 폭에 비해 computational cost 및 time cost가 지나치게 컸기 때문에 곧 방법을 폐기하게 되었습니다. 모델의 구조를 앞서 언급한 것과 같이 바꾸면 활용하는 모델이 총 3개가 되기 때문에 자연스럽게 학습 및 예측에 필요한 cost가 높아지기 때문입니다. 조금의 성능 향상을 위해 이 방법을 활용하기는 다소 부담스러웠습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Backbone

저희의 task에 맞는 적절한 pretrained backbone을 정하는 것도 매우 중요합니다. backbone이 내놓는 output이 양질의 것이어야 head 역시 좋은 방향으로 학습할 수 있기 때문입니다.

저희가 주요하게 활용했던 backbone은 huggingface transformers 모델 기준 아래와 같습니다.

  • xlm-roberta-base/large
  • monologg/koelectra-base-v3-discriminator
  • monologg/koelectra-base-v3-finetuned-korquad

validation score 상으로는 koelectra-base-v3 기반의 백본이 확실히 우세한 성능을 보였습니다. 아무래도 한국어 기반으로 학습된 모델이다보니 상대적으로 더 좋은 성능을 보였던 것으로 추측됩니다.

xlm-roberta-base/large의 경우 성능이 가장 좋을 것이라고 예상했지만 의외로 validation score는 매우 저조하였습니다. xlm-roberta model을 KorQuAD에 fine-tuning하고 활용한다면 성능이 더 좋을 수 있겠다는 생각을 했지만, 저희 팀에 V100 GPU를 가지고 있는 피어가 없었기 때문에 보장되지 않은 방법에 오랜 시간 그래픽 카드 하나를 소모한다는 점이 부담스러워 이 부분은 진행하지 못했습니다.

결국 저희 팀은 어느정도 성능이 보장되었으며 동시에 빠르게 학습할 수 있는 monologg/koelectra-base-v3-finetuned-korquad 혹은 monologg/koelectra-base-v3-discriminator 모델을 주로 활용하게 되었습니다.

다만 역시 추후 회고 세션때 알게된 사실인데, xlm-roberta-large 모델이 validation은 저조했지만 오히려 LB score는 높았다고 합니다. 저희가 validation score를 어느정도 신뢰하고 있었기 때문에 LB에 많이 제출을 해보지는 않았었는데 지금 와서 생각해봐도 고작 240개라는 적은 양의 validation data로부터 도출된 지표를 너무 맹신하지는 않았나 하는 생각이 들기도 합니다. 역시 반성할 부분입니다.

Hyperparameter 실험은 솔직히 많이 해보지는 못했습니다. 대부분의 시간을 모델 구조에 대한 생각을 하는데에 사용하였고 hyperparameter tuning은 들이는 시간에 비해 얻는 것이 적다고 생각했습니다. 아래는 실험해본 주요 hyperparameter 목록입니다.

  • learning_rate: 1e-5, 3e-5, 1e-6, 3e-6
  • scheduler: linear, cosine, warmup
  • batch_size: 8, 16

learning rate의 경우 scheduler가 있기 때문에 크게 신경쓰지 않았습니다. 성능면에서도 두드러진 차이는 없었습니다. batch size의 경우 P40 환경에서는 16 정도가 최대라서 더 큰 사이즈에서 실험해보지 못했습니다. 4는 너무 작다고 판단하여 실험하지 않았습니다. scheduler도 3개 정도를 바꿔가며 실험해보았는데 결과적으로 모두 성능 차이가 크게 나지 않았습니다.

결과적으로 이러한 일련의 실험들이 당장은 큰 의미가 없다고 판단하였으며, 따라서 hyperparameter는 주로 성능보다도 활용하기 편한 것들을 활용하였습니다. batch size는 8이어야 다른 실험을 하면서 동시에 학습을 진행할 수 있었기 때문에 거의 항상 8을 활용하였습니다. scheduler는 default가 linear였기 때문에 그대로 linear scheduler를 사용했습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
(번외) ETRI KorBERT

ETRI KorBERT는 한국어로 학습된 유명한 BERT 모델들 중 하나입니다.
이 모델은 특히 한국어 형태소 기반 토크나이저를 활용하기 때문에, 이 모델을 활용하여 MRC task를 진행한다면 QA task에서 예측값에 부적절한 조사나 부사가 포함되는 경우를 미연에 방지할 수 있다고 생각했습니다.

하지만 안타깝게도 ETRI KorBERT는 당시 API가 제대로 작동하지 않아 제대로 써보지도 못하였습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
물론 저희가 직접 설계한 모델이 아니기 때문에 활용에도 어느정도 한계가 있었을 것 같기는 하지만 모델 자체의 성능이 일반적인 xlm-roberta/bert-multilingual/ko-electra 등의 모델보다 월등할 것이라고 생각했습니다.

적어도 저희가 커스텀한 모델이 현재 어느정도의 성능을 보이는지 비교 대상 지표로라도 활용할 수 있었을 것 같은데 당시 API서버가 다운되어 이를 활용하지 못했다는 사실은 못내 아쉽습니다.


Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Ensemble

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
K-Fold Cross Validation & Bagging

기존 모델의 성능 개선을 위해 Model Prediction Anlysis를 하면서, 매번 모델이 틀리는 example은 동일한 example이라는 점에서 K-Fold cross validation을 수행해야겠다는 아이디어를 얻었습니다.

k-fold

K-Fold cross validation

학습용 dataset에서 train data example은 3192개, valid data example은 240개 가량으로 구성되어 있었는데, 총 4100개 가량의 example 중 5%를 조금 넘는 240개만으로 학습시킬 시 너무 적은 양의 valid set 기준으로 loss를 계산하게 됩니다. 이 때문에 정답 분포가 편향되어 valid set에 overfitting된 모델을 만들게 되었을 가능성이 있다고 판단했습니다. 따라서 K-Fold cross validation을 통하여 모델의 overfitting을 검증하고자 했습니다.

Bagging

또한, K-fold로 학습한 모델들은 동일한 알고리즘을 가지고 있으면서 학습데이터의 일부만 바꾼 모델들입니다. 이러한 모델들의 추정치를 평균내는 Bagging을 수행하면 모델의 variance를 줄여 overfitting을 피할 수 있을것이라고 판단했습니다. Bagging으로 사용하는 각 모델의 학습은 대부분 중복된 데이터지만, validation set과 일부 train set에 차이가 있습니다. 이에 따라 각 모델은 각자 조금씩 다른 예측을 수행하게 되고, 이들을 합침으로써 특정 data set의 영향력을 보정해줄 수 있습니다.

top-k개의 context는 각 MRC 모델들을 거치며 토큰별 start logit과 end logit으로 변형됩니다. 한개의 context에 대해 k개의 모델이 추정한 각 start logit과 end logit을 평균내어서, 이를 마치 하나의 모델이 prediction한 것처럼 후처리로 넘겨주도록 하였습니다.이 때 시간관계상 k는 5로 설정하였습니다. 따라서 validation set은 240개 -> 898개로 대폭 늘어났습니다.

아쉬운 점은 코드가 너무 늦게 완성되어 bagging의 성능 결과를 LB 스코어상에서 확인해보지 못했다는 것입니다. k개의 모델을 각각 학습시켜야 하기 때문에 기존 학습 시간(약 30분)의 k배가 걸려서, 제출 시간이 지난 후에야 학습이 종료되어 prediction을 도출해낼 수 있었습니다. 그럼에도 불구하고, 5개의 fold 모델 중 2개의 checkpoint를 기존 모델의 ensemble에 추가하였을때 각각 LB스코어 기준으로 1~1.5%씩 성능이 올라, overfitting을 피하기 위한 유의미한 전략이었다고 생각합니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Soft Voting

Reader 모델은 학습시에 CrossEntropy를 사용합니다. 즉, Category분포를 가정하여 문제를 푸는 것을 알 수 있습니다.

Category분포라면 당연하게 Soft Voting을 할 수 있을 것이라고 생각을 하였고 생각없이 코드를 작성하면서 금방 두 개의 문제에 직면했습니다.

문제 1: 학습과 추론시 의미있는 Token의 개수가 다르다.

logits

학습 할 때는 전체 Logits에 SoftMax를 씌운 후 정답 Index와 CrossEntropy를 하여 Loss값을 계산하면 됩니다.

추론 할 때는 전체 Logits에서 의미있는 Logit만 여러 개 뽑습니다. 여기서 발생하는 문제점은 모델마다 의미있는 Logit의 개수가 다릅니다.

Soft Voting을 위해서 각 모델의 Logit값을 더하거나 확률 값을 더해주어야 하지만 Logit의 개수가 각각 달라서 확률 값을 더해주는 것은 사용할 수 없었습니다.

SoftMax사용 시 토큰 개수에 따라 확률 분포가 튈 가능성이 높기 때문입니다.

important-logits

Logit 사용시 유의할 점은 Logit의 분포또한 모델마다 다르다는 것입니다. 그래서 모델마다 Logit 분포를 맞춰주기 위해서 모델 전체 Logit을 대상으로 Standardization를 하였습니다.

문제 2: Tokenizer마다 다른 Token을 생성한다.

Tokenizer마다 다른 토큰을 생성하기 때문에 토큰 단위로 Soft Voting을 진행할 수 없었습니다.

다국어 Bert Tokenizer : "[하, ##원의]",
Koelectra Tokenizer : "[하원]"

offset

그래서 마지막 후처리 단계인 Offset 기준으로 Logit값을 더함으로써 Soft Voting을 사용하였습니다.

Offset은 글자가 문서의 어느 위치에 있는 것을 나타냅니다. 즉, Tokenizer에 상관없이 Soft Voting을 진행할 수 있습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Soft Voting Use Offset

Offset을 사용하여 Soft Voting을 진행하는 Ensemble 방법입니다.

def update_offsets(start_scores, end_scores, logits):
    for logit in logits:
        start_scores[logit["offsets"][0]] += logit["start_logit"]
        end_scores[logit["offsets"][1]] += logit["end_logit"] 

soft-offset

정답을 예측할 때는 Start Logit이 가장 큰 값을 가져오고 그 다음 가능한 값들 중에서 End Logit이 가장 큰 값을 사용합니다.

Soft Offset 추론 결과는 "대통령인 빌헬름 미클라스"입니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Soft Voting Use Span

Start Offset과 End Offset사이의 Span 값을 사용하여 Soft Voting을 진행하는 Ensemble 방법입니다. Span값은 Start logit과 End logit의 합입니다.

def update_spans(span_scores, logits):
    for logit in logits:
        span_scores[logit["offsets"][0] : logit["offsets"][1]] += logit["start_logit"] + logit["end_logit"]  # broadcast

span-ensemble

정답을 예측할 때는 Logit값을 다 더한 후 75% 이상에 해당하는 Logit값만 사용하여 정답을 예측합니다.

Soft Span의 추론 결과는 "빌헬름 미클라스"(실제 정답)입니다.

Span같은 경우 성능 향상에 주요하다고 생각 했지만 구현 미비로 큰 성능 향상은 얻지 못했습니다.

75% 기준으로 정답을 가져오는 방법은 이상치 값이 있을경우 잘 작동하지 않았습니다. 다른 방법을 고려해야 했으나 시간이 늦어 더 고려하지 못했습니다

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Hard Voting

Hard voting은 대회 마지막날, 약 10% 이상의 성능 향상을 이끌어낸 방법입니다.

부수적인 것을 제외하고, 가장 기본적인 구조는 아래와 같습니다.

먼저 save된 prediction json 파일들을 불러옵니다.

files = ['output_1.json', 'output_2.json', ...] # 불러올 파일들 경로
json_files = []
for file in files:
    with open(f"./{file}") as f:
        json_file = json.load(f)
        json_files.append(json_file)

불러온 파일들을 대상으로 아래와 같이 hard voting을 진행합니다.

result = dict()
    
for key in json_files[0].keys(): 
    polls = defaultdict(int)
    
    for json_file in json_files:
        predict = json_file[key]
        polls[predict] += 1

    sorted_polls = sorted(voting.items(), key=lambda x: x[1], reverse=True)
    voted = sorted_polls[0][0]

    result[key] = voted

위와 같이 자연어 그대로를 voting 대상으로 활용하였습니다. 물론 상기 코드는 많이 축약된 버전이고 실제 활용한 코드에는 같은 수의 투표를 받은 정답에 대한 여러 후처리, 조사/부사 등에 대한 형태소 후처리도 포함되었습니다.

Hard voting을 하면서 가장 놀라웠던 점은 아무리 저조한 LB score를 보인 예측 파일도 추가하면 추가할수록 성능이 올랐다는 점입니다. 앞서 K-Fold 파트에서도 언급하였지만 이 사실을 너무 뒤늦게 확인하여 이에 대한 충분한 실험을 진행해보지 못했지만 지나고 생각해보니 그렇게 될 수 밖에 없었던 근거가 존재했습니다.

가장 큰 근거는 서로 다른 구조와 서로 다른 데이터 분포에서 학습된 모델들이 각자 어느정도 그럴듯한 답을 내놓고 있었다는 점입니다. 특히 여러 모델들의 성능이 상이했던 이유가, 모두 비슷한 예측을 내놓으면서 한 두개 문제의 예측이 달랐기 때문이 아니라는 점이 가장 중요합니다. 각 모델들은 각자가 잘 맞히는 문제가 있었고 잘 맞히지 못하는 문제도 있었습니다. 다만 그 중에서도 좀 더 맞히거나 좀 덜 맞히는 모델이 있었을 뿐입니다.

따라서 많은 양의 모델들을 앙상블하면 모델들이 서로 맞히지 못하는 문제를 상호보완하고 어느정도 정답에 가까운 예측만을 내놓을 수 있게 되는 것입니다. 저희는 최종적으로 10개 가량의 prediction 파일들을 앙상블했는데, 한 개를 추가할 때마다 최소 1% 이상의 성능 향상이 있었습니다.

지금까지는 앙상블이 반드시 비슷한 성능의 모델들을 결합하여야만 보다 높은 성능을 얻을 수 있다고 생각했었는데, 이번 대회를 거치며 이러한 고정관념을 깨부술 수 있었습니다. 서로 다른 두 모델의 예측값이 아예 다르다보니 score에서 다소 차이가 나더라도 앙상블에서 긍정적인 효과를 얻을 수 있었습니다.

10개의 모델을 앙상블하여 최종제출한 이유가, 사실은 더 추가했을때 성능이 저조해서가 아니라 시간이 없어 더 이상의 예측 파일을 만들어내지 못했다는 점은 좀 아쉬운 부분입니다. 다만 촉박한 시간 속에서 귀중한 사실들을 깨달았기 때문에 이번 대회에서의 hard voting은 그 자체로 가치가 있었던 방법이었습니다.


Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
회고

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
팀 회고

팀 순위 - 9팀4등

LB SCORE

  • EM : 60.83%
  • F1 : 71.85%

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
개인 회고

이수연(Human Reader)

지난 Stage를 마무리하면서, 이번 Stage 때 하고 싶은 일들을 정리했었습니다. 그리고 이번 Stage를 시작하며 자기소개를 작성하면서, Stage 3을 성공이라고 할 수 있는 부분들을 생각해 보았습니다. 이를 바탕으로 Stage 3에서 달성하고 싶었던 항목과 각 항목에 대한 개인적인 점수는 다음과 같습니다.

  • 리더보드 50% 이상 100%
    리더보드 50% 이상이 되지 않으면 좀 슬플 것 같아서 목표로 적어 두었다가, 그래도 이번에는 LB에 좀 덜 신경쓰고싶어서 찍찍 지워 두었었는데 막판 앙상블 덕에 달성할 수 있었습니다.
  • Git으로 팀플을 잘 해보기 100%
    이번에 특히 Git을 많이 활용해 본 경험이 좋았고, 특히 개인 branch에서 작업한 뒤 Pull Request를 보내서 피어 분들의 리뷰를 받고 리뷰를 하는 경험이 좋았습니다. Git의 장점을 많이 배우고 활용할 수 있었던 stage였다고 생각합니다.
  • 팀플 과정을 잘 정리해서 블로그나 깃허브에 공유할 수 있으면 좋겠음 100%
    팀플 과정부터 모든 회의록이 md파일로 정리되어 깃허브에 바로바로 올라갔고, 중간에는 zenhub을 활용하여 과정을 한 눈에 볼 수 있었으며, 팀플이 끝난 후에도 멋진 wiki까지 작성되어 문서화에 있어서는 매우 만족스러웠던 stage였습니다. 팀원 여러분 덕분에 md파일 어떻게 작성하는지 많이 배운 것 같습니다 (이 전까지는 어떻게하는지 하나도 몰랐어요..) 이 wrap-up report까지 다들 너무 열심히 작성해주고 계셔서 너무 감사합니다.. 다만 스스로 문서화에 있어서 게을렀던 부분들이 잘 개선이 되지 않았고, 팀원들께서 도와주신 덕분에 100%를 달성할 수 있었다고 생각해서 다음 stage에서는 좀 더 성실하게 문서화에 방점을 두고자 합니다.
  • 실험에 대한 탄탄한 가설과 결과 분석해보기 80%
    실험 관련해서는, 팀원들과 항상 토의하며 실험을 진행했기 때문에 '그냥' 구현한 파트가 없었다고 생각합니다. 나름의 이유를 가지고 실험을 진행했으며 결과 또한 이해하려는 노력을 들였으므로 80%를 주었습니다.
  • 새로운 모델 구축 시도해보기 60%
    새로운 모델 구축 시도를 위한 노력에는 논문을 읽고, 이해하고, 구현하는 것이 있다고 생각하는데, 논문을 읽고 이해해서 팀원들에게 전달하려는 노력을 했고, 딥러닝 모델은 아니지만 Sparse retriever를 수식을 기반으로 구현했다는 점에서 60%를 주었습니다. 하지만 Deep Learning 모델을 직접 수정해보지 못했다는 아쉬움이 남고, 다음 Stage에서 이 부분을 보완해보고 싶습니다.
  • 자연어에 대한 더 깊은 이해(토크나이징 등) 40%
    wiki 중복 EDA과 자연어 후처리를 진행하면서 자연어에 대한 이해가 약간은 높아졌으나, 토큰 단위를 직접 보지는 않았습니다. 하지만 피어세션에서 토크나이저도 리뷰해주시고 여러 데이터셋에 대한 EDA를 진행해주셔서 덕분에 어느 정도 이해의 수준은 높아졌다고 생각합니다. 다음에 또 자연어와 관련된 task에 도전할 기회가 있다면, 한국어에 대한 이해를 바탕으로 이것 저것 실험을 해볼 수 있었으면 좋겠습니다.
  • WandB의 다양한 기능을 활용해보기 30%
    WandB의 기능들을 더 활용해보고 싶었는데, 주로 retriever를 구현했다보니 해당 기능을 많이 활용해보지 못해 아쉽습니다. 다음 stage 때는 좀 더 적극적으로 WandB를 활용하면 좋을 것 같습니다.
  • 기계독해를 활용한, AI를 경험해볼 수 있는 뭔가를 웹서버에 올려보면 좋겠음 0%
    구현한 모델을 서비스로까지 서버에 올리고싶다는 생각이 있었는데, 아쉽게도 달성하지는 못했지만 그 외에 많은 것들이 우선순위로 실현되었기 때문에 괜찮다고 생각하고, 다음 DKT에서 충분히 달성할 수 있다고 생각합니다.

다음 Stage 때 하고 싶은 것들은 다음과 같습니다.

  • WandB 활용해서 모델 파라미터 찾는 것 자동화 (Stage 1 때 적용했던 것)
  • 더 나은 실험 관리 (naming convention 등)
  • 새로운 아이디어 바탕으로 딥러닝 모델 '직접' 고치거나 구현해보기
  • 가설이 있는 실험, 결과 분석 및 문서화(!!!)
  • 웹서버에 결과물 뭔가를 올려보면 좋겠음
  • 팀플 더 잘 해보기 (온라인 커뮤니케이션의 한계 극복 고민)

수연님, 제가 이전에도 말씀 드렸지만 수연님 코드 보면서 정말 많이 감탄하고 놀랬습니다. 자료구조, 알고리즘기반 지식 없이 그렇게 논문을 구현할 수 있는 것은 정말 재능입니다. 제가 표현을 잘 못해서 이 감탄을 말하지는 못했지만 정말 놀랐어요. 특히 제가 구현해놓은 추상화를 자유자재로 쓰는 모습(제가 코드를 열심히 보거든요! ㅋㅋ)은 이미 클래스, 객체 지향을 잘 알고 있는 사람처럼 느껴졌습니다. 수연님은 팀에 정말 도움이 되는 사람입니다. 나중에 돈 많이 벌면 재이 타요 장난감 하나 사서 선물하도록 하겠습니다! 나중에 DKT 프로젝트 같이하면 좋을 것 같습니다! (저한테) 수연님 이번 스테이지 무던히도 고생하셨습니다!! 건모

수연님 아무 생각없이 팀원 안구하고있던 저에게 처음으로 DM 보내주시고 덕분에 좋은 팀원들 많이 만나서 정말 너무너무 감사했습니다! 그땐 정말 한줄기 빛이었어요 랜덤 세션 어떻게 할지 고민하고있었는데 ㅋㅋㅋㅜㅜ 또 이후에도 팀에서 수연님이 내색없이 묵묵하게 해주신 것들이 너무 많았어서 감사했습니다. 항상 느꼈지만 바쁘신데도 조용히 모든 일들을 다 잘해주셔서 너무 존경스러웠어요 저도 그런걸 보면서 더 열심히 하려고 많이 자극 받았던 것 같아요 진짜로.. 우리팀이 이렇게 와해의 위기에 처해 너무 아쉽지만ㅠㅠㅠ 지금의 이 결속력을 잊지 말고 나중에 같이 다른 프로젝트도 꼭 했으면 좋겠습니다! 그때는 각자 아쉬운 점 없이 지금 보다 더 잘 해낼 수 있을거예요 😊 인턴도 꼭 함께 잘 해내봅시다ㅋㅋㅋㅋㅋ 인턴 메이트 화이팅! 종헌

수연님이 저 팀에 넣어주셔서 너무 다행입니다 평생 감사하며 살겠습니다 사실 처음 랜덤피어세션에서 봤을때부터 같이 팀하고싶다는 생각은 했었는데, 같이 팀하고 나니 두 배로 더 매력적인 팀원이셨습니다. 선아수연님의 능숙한 커뮤니케이션 덕분에 저희팀 TMI 세션이 풍부해서 너무 즐거웠습니다. 팀프로젝트 하면서 이렇게 서로 열심히 하고, 분위기 좋은 팀에서 일하는게 정말 오랜만이었는데, 거기엔 수연님 몫이 8할이라고 생각합니다. 그리고 competition 내내 논문 리뷰하시고 공유하시는 모습 보고 솔직히 너무너무 멋있고 부러웠습니다. 원래 자기가 가지지 못한걸 부러워하게 된다는데, 수연님은 너무 다방면으로 뛰어난 인재같아요! 다음팀도 수연님이랑 같이했으면 많이 배우고 너무 좋았을텐데 아쉽습니다. 꼭 부캠 끝나도 저희 다들 연락하고 지내요!! 성익

수연님 매일 논문 리뷰해주시고, 정리해주시고, BM25는 거의 끝까지 성능 올려주시고 주어진 일이라면 정말 완벽히 수행하시는 모습 보면서 진짜 멋있다고 생각했습니다. ㅠㅠ 피어세션때도 정말 활발히 의견 제시하시고 지식 공유하시는 모습 보면서 대단하시다고 혼자 감탄하고 있었습니다.. 같은 팀이어서 너무 든든했고 감사했습니다. ㅎㅎ 수연님의 웃음소리 그리울 것 같아요 재이의 웃음소리두요 ㅠㅠ <- 이거 진짜.억 제거 댓글길이 왜 밀려났죠..?ㅋㅋㅋㅋ 그리고 저번에 우산 같이 쓰고 가자고 전화주신 그 따뜻함 잊지 못할 거에요 엉엉 ㅠㅠ 차가운 머리와 따뜻한 가슴 둘 다 가지고 계신 수연님 정말 감사했습니다ㅎㅎ 지영

김성익(Robot)

저번 스테이지를 진행하며 타인의 코드를 따라치는 게 아니라 제 코드를 직접 짜는 것이 얼마나 중요한 지 깨달았습니다. Stage 2에서는 매일매일의 daily mission과 강의를 따라가기에 급급했고, 일단 시키는대로 열심히 따라치고 나면 어떻게든 되겠지라는 생각이 있었습니다. 결국 저번 대회를 마무리할 때쯤 결국 이런 방식의 코드가 당장 모델 성능은 낼 수 있어도, 생각하는 힘은 길러주지 못한다는것을 느꼈습니다.

그렇기 때문에 이번에 팀 단위로 협업할 때에는 최대한 많은 코드를 뜯어보고 제 코드로 만들어보고 싶었습니다. 그러려면 팀끼리 소통이 정말 잘 되어야했고, 무엇보다 저와 비슷하게 주어진 코드를 따라가지 않으려는 분들이 많아야 했습니다. 그런 점에서 범블봇은 팀으로서 궁합이 정말 잘 맞았다고 생각합니다.

이번 스테이지에서 배운것, 얻어간 것의 대부분은 협업이었다고 생각합니다. 개발을 시작한 이후로 처음으로 PR을 날려보고, 코드리뷰를 받아보고, 짝프로그래밍을 했습니다. 가끔 도저히 오류를 알 수없는 날이면 zoom에서 화면을 공유하며 팀원들과 같이 디버깅을 하기도 했습니다. 덕분에 혼자였으면 해결할 수 없는 많은 문제들을 해결할 수 있었습니다.

팀원끼리 첫 소개를 할 때, 긴 회의를 싫어한다고 했었는데, 저희팀 회의는 매번 2시간 가까이 해도 정말 즐거웠습니다. TMI 세션도 처음에는 어색했지만 가면 갈수록 서로 썰자랑하는게 너무 귀엽고 재미있었습니다. 덕분에 단순히 피어로서가 아니라, 인간적으로 팀원들을 더 알아가고 싶다는 생각이 들었습니다.

또, 개인적으로는 Stage 1과 2를 거치면서 계속 AI를 공부하는게 맞나, 길을 잘못든 건 아닌가 하는 깊은 고민이 있었습니다. Stage 3때에도 초반에 팀원의 코드를 follow up하기도 힘든 스스로를 보면서 자괴감에 빠지는 날도 많았지만, 지금 돌이켜 보고 나니 그런 시간들이 있어서 좀 더 뻔뻔하게 모르는 것을 모른다고 말하고, 물을 수있게 되었습니다. 덕분에 '아무것도 모르는 사람'에서 '뭘 모르는지 아는 사람'으로 한발짝 다가섰다고 생각합니다.

좋은 점은 이야기하자면 끝도 없기때문에, 개인적인 아쉬운 점을 남기자면 다음과 같습니다.

    1. 논문 읽는 것에 대한 두려움이 있습니다.
    2. 수행한 task가 EDA나 Ensemble에 치중되어 있습니다. 다시 말하자면, ODQA의 핵심이 되는 Retriever 파트나 Reader 파트를 제대로 다뤄보지 못했습니다.
    3. 하이퍼파라미터 실험을 많이 하지 못했습니다.
    4. 개인적인 강점을 살리지 못했습니다.

아직 학부 저학년으로 논문을 접할 일이 잘 없었고, 개인적인 관심도 연구보다는 엔지니어링이나 비즈니스 자체에 초점이 맞춰져 있는 터라 AI 분야에서는 필수적인 논문 리딩을 거의 해보지 못했습니다. 팀원들이 survey 논문/ SOTA 논문 / QA 분야의 유명한 논문들을 읽고 공유해주는데, 들었을 때 이해가 되지 않는 부분이 대부분이었습니다. 기초가 부족한 것도 맞지만, 중요한 점은 심리적 허들이 있다는 것입니다. 영어로 된 논문을 읽고, 수식을 이해하고, 타인에게 공유한다는 것 자체를 두려워하는 것 같습니다. 다음 스테이지에서는 가능하다면 한 개 이상의 paper을 직접 찾고 연구해보고 싶습니다.

또, task의 핵심 파트를 얼마 건드리지 못했다는것도 굉장히 아쉽습니다. 첫 주차에는 새로 짠 베이스라인 코드를 이해하느라, 둘째 주차에서는 모델을 건드릴 엄두가 나지 않아 EDA를 진행하느라, 셋째 주차와 넷째 주차에서는 ensemble을 진행하느라 NLP 모델의 원리를 확실히 이해하고 커스텀해보지는 못했습니다. 팀으로서는 제가 기여 할 수 있는 부분을 하려고 노력했다고 생각하지만, 개인적으로는 모델을 밑바닥부터 짜보고, 내 방식대로 실험해보고, 다른 팀원들에게 insight를 줄 수 있는 사람이 되고 싶었는데 그러지 못했습니다. 지금까지 한번도 수행해보지 못했던 ensemble을 했다는 것은 좋은 일이지만, 다음 스테이지에서는 베이스라인 코드부터 심도있게 짜기 시작하여 모델 및 파이프라인 구현 위주로 많이 수행해보고 싶습니다.

기존의 stage에서 대부분의 모델 개선이 feature engineering과 하이퍼파라미터 조정에 그쳤기 때문에, 하이퍼파라미터로 실험하는데에는 조금 거부감이 있었습니다. 그럼에도 불구하고, 성능을 올리려면 방법의 개선 뿐만 아니라 다양한 하이퍼파라미터로 실험해보는 시간이 반드시 필요하다고 생각합니다. 건드리는 부분이 파이프라인 전체를 거치다 보니 디버깅이나 feature 추가에 시간을 많이 쏟았고, 이 때문에 실험을 위한 파이프라인이 굉장히 잘 구성되어있음에도 불구하고 GPU를 많이 놀려뒀습니다. 어차피 막바지에는 여러 실험을 수행하느라 놀고있는 GPU가 없게 되므로, 일찍부터 다양한 하이퍼파라미터를 시도해보는 것이 좋다는 생각이 들었습니다.

마지막으로, competition을 진행하면서 개인적인 강점을 잘 살리지 못했다는 것이 아쉽습니다. AI는 처음이라 많이 주눅들고 물어보곤 했는데, 정작 관심있던 모델 serving과 클라우드를 사용한 다양한 시도들은 해보지 못했습니다. 부스트캠프 외에도 개인적으로 진행하고 있는 스터디나 동아리에서 배웠던 인프라 지식들을 나름 활용할 수도 있었을텐데 그러질 못했습니다. 다음 stage에서는 GCP나 AWS를 이용하여 특정 task의 머신러닝을 빠르게 수행하거나, serving을 지향하는 DKT인만큼 API 형태로 model이 serving까지 이루어질 수 있도록 배포를 꼭 해보고 싶습니다.

한달이 정말 일주일 같을 정도로 너무 빠르게 지나갔는데, 나름 열심히 했지만 원하던 기준에는 못미친 것 같아 아쉽습니다. 저희 팀은 죄송하다거나 미안하다는 말을 하면 벌금이 10만원이기 때문에, 미안하다는 회고는 하지 않도록 하겠습니다!

성익님, 많은 생각이 들도록 하는 회고입니다 처음 봤을 때부터 많은 점을 배울 수 있는 사람이라 생각했었는데 마지막 회고에서까지도 많은 점을 배우네요. 저는 성익님이 있어서 피어세션이 120% 알찼습니다. 그냥 존재만으로 좋아요 ㅋㅋ. 어느 날 갑자기 피어세션때 민폐를 끼쳐서 죄송하다고 말할 때 정말 민폐끼치는 사람을 랜덤 피어세션때 안 만나봤구나라는 생각이 들었습니다. 성익님은 어딜 가든 도움이 되는 사람이니 앞으로 그런 말씀 안하셔도 돼요. 그냥 존재만으로 민폐는 이미 벗어나셨습니다! 그리고 도움이 될 만큼의 실력을 가지시기도 했구요. 슬랙에서 봤을 때 항상 친해지고 싶다는 생각을 했었는데 이번 기회에 정말 정말 ~~~ 많이 친해져서 너무 좋았습니다! DKT 스테이지에서도 우리 같이 잘해봐요! 스테이지 3 항상 회의록 작성해주시느라 고생하셨습니다!! 건모

성익님 저는 성익님을 성실함의 끝판왕이라고 생각합니다.. 보면서 저렇게 노력하시니까 코딩도 잘하시고 캠퍼님들의 존경을 받는구나 감탄하고 있습니다.ㅎㅎ 새벽 4시에 게더타운에 들어오시는 모습 잊지 못할 것 같아요 ㅋㅋㅋ 그리고 매일 따뜻한 말을 해주시고 저희 팀원분들 모두 배려해주시는 모습 인상적이었습니다.ㅎㅎ 겸손함과 성실함 다 갖추신 성익님.. 뵙게 돼서 넘넘 즐거웠습니다!.. 억 처음에 제 댓글이 제일 길었는데 갑자기 꼴찌가 되었네요ㅋㅋㅋ 질 수 없습니다! 성익님 덕분에 토크나이징 관련 정보들도 다양하게 알게 되었고, 진행하신 EDA에서 예측값과 실제 값과의 차이도 잘 알 수 있었습니다. 마지막 갓kfold까지 성익님은 기울기가 거의 수직에 가까우신 ㅠㅠ ㅎㅎ 다시 한번 감사드려요!
지영

성익님 뭔가 성익님이 아쉬워했던 점들을 보니 죄송한 마음이 드네요(10만원) 뭔가 저희끼리 소통이 어느정도 잘 되긴 했지만 초반에는 그래도 어색한 분위기가 좀 있다보니 각자 원하는 것을 확실하게 말하지 못했던 것 같기도 합니다ㅠㅠ 그래도 성익님 진짜 저희 팀에서 많은 것들을 해주셨고 특히 막판에 성능에도 큰 기여를 하셨잖아요!! 조금 방향이 달랐을 수는 있지만 뭔가를 많이 성취하셨을 것이라고 생각하고, 저 또한 성익님 덕분에 많은 인사이트를 얻을 수 있었습니다. 직접 생각하시기에 강점인 것들을 다음에 같이 프로젝트할 때 발휘해주시면 더 많이 배우고 성장할 수 있을 것 같아요!! 성익님이 늘 부족하다고 미안해하셨던 부분들 사실 저는 모두 만족스러웠는데..ㅋㅋㅋ 그럼 대체 강점을 가진 부분에서는 얼마나 잘하실지.. 정말 기대됩니다!! 그러니까 다음에 꼭 같이 프로젝트 합시당

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
종헌

매번 마스터세션 성실히 작성해주시던 성익님을 팀으로 모시게 되어서 영광이었습니다 같은 팀해서 너무 좋았어요헤어지기 아쉽다ㅜㅜ 제가 제일 못하는 문서화를 너무 성실히 열심히 잘해주시는 모습 보고 많이 배웠고 다음 stage 목표로 저도 문서화를 넣었습니당ㅎㅎㅎ 성익님 회고를 보니 하고싶던 것들을 못하신게 좀 있는 것 같아 저도 괜히 죄송하네요(10만원) 다음 스테이지에서는 꼭꼭 계획하신 목표들 다 달성하실 수 있기를 응원해봅니당! 다른 팀이지만 DKT 같이 공부 열심히 해봐요!! 너무 바쁘신 것 같아 그 이후에도 같이 프로젝트 해보자고 하기가 조심스러웠는데 이제 말해봅니다 다음에 꼭 같이 프로젝트 합시당222 그리고 많은 활동들로 엄청 바쁘신 것 같은데 건강 잘 챙겨가면서 일하시면 좋겠습니다!! 수연

구건모(Humer Computer)

명언: 별꼴이야 정말🙄😊
명언: 전 거짓말을 안해요.. 😎

여러모로 정말 인상깊었던 스테이지였습니다. 스테이지를 마무리하면서 처음 세웠던 1순위 목표가 많이 달라졌다는 것을 느꼈습니다. 물론 나머지 목표들은 어느정도 잘 수행했습니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

원래 제 1순위 목표는 체계적인 실험을 통한 성능 향상이었습니다. 팀원분들한테 말은 안했지만 사실 1주차 되기전에 방향을 틀었습니다. 이유는 별거 없습니다. 저보다 실험을 더 잘 하시는 팀원 분들이 너무 많았거든요 ㅎㅎ..

피어세션때 팀원분들이 실험 공유를 하시고 IDEA를 제시하는 것을 들으면서 내가 실험을 하는 것이 팀에 도움이 되는 방향인가? 라는 의문이 들었습니다. 실험을 하는 것도 좋지만 저보다 실험을 더 잘하시는 분들이 있는데 내 욕심으로 실험을 고집하는 것이 맞을까? 라는 생각이 들었습니다.

그런 의문이 들고난 이후로 곰곰이 고민하여 이번 스테이지에서는 팀원분들의 실험을 서포트하기로 결정했습니다. 결정을 했던 이유 중 중요한 한 가지는 제가 엔지니어링 쪽으로 큰 도움이 될거라는 강한 확신이 있었고 그게 팀원들한테 날개를 달아주지 않을까? 라는 생각이 있었습니다. 마음은 그렇게 먹었는데 실제로 제가 얼만큼의 도움을 줬었는지는 확신을 못하는 것이 옥의티네요.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

엔지니어링과는 별개로 이번 스테이지를 하면서 성능 향상에 중요하다고 느꼈던 것은 공유였습니다. 어느 정도의 공유가 얼마만큼 활발하게 일어나는지가 전체적인 방향을 빠르게 잡고 성능 향상을 높였던 것 같습니다.

공유는 만족스러우면서도 아쉬움이 많습니다. 왜냐하면 초반에는 서로가 조심스러웠기 때문에 정해진 피어세션 시간외에는 공유가 그렇게 활발하게 이뤄지지 못했습니다. 이 부분이 저희 팀이 초반에 주춤거리는데 영향을 끼쳤다고 생각을 합니다. 그래도 2주차, 3주차에 들어서면서 점차 공유가 피어세션 이외의 시간에도 활성화가 되었고 모델 성능 향상에 더 큰 도약이 되었다고 생각합니다.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

마지막으로 제가 팀에 속한 팀원으로서 지향했던 것은 나의 성장이 아닌 그룹의 성장이였고 그 결실을 지금의 Wrap Up 리포트MRC 팀들 중 유일무이한 하나의 베이스라인 코드 그리고 LB 점수로 증명한 것 같아서 보람찹니다.

좋은 팀이였고 앞으로도 좋은 팀으로 남았으면 합니다. 감사합니다.

처음에 건모님 봤을때보다 친해지게 되어 너무 좋습니다. 사실 상 저희 팀 전력의 대부분을 맡고 계신데, 매번 엔지니어링과 실험을 너무 즐거워하시는 모습 보고 정말 자극이 많이 됐습니다. 예전에도 말씀드렸지만 건모님은 첫 인상에 비해 너무 유하신 것 같아요. 코딩으로나, 팀원으로서 협업하는 부분이나 건모님 덕분에 팀활동이 너무 보람차고 즐거웠습니다. Stage 4에는 우리 더 좋은 결과 내봐요! 성익

건모님 덕분에 많이 배웠습니다!정말 새벽까지 저를 가르쳐주시고 일러주시고ㅋㅋㅋㅋ 해주셔서 많이 성장했습니다. 장난 아니구 진짜에요! 저한테 시간 투자해주셔서 정말 감사드려요 ㅎㅎ 프로그래밍을 할때 잊고 있었던 중요한 점들도 덕분에 많이 알게되었습니다. 그리고 저한테 코드 개선할 점들을 차분하게 일러주신 점도 인상적이었습니다. 건모님 뵙게 돼서 너무 유익했고 감사했습니다! 억 건모님꺼 메시지 길이 갑자기 밀려났네요ㅋㅋㅋ뭔가 기술적인 도움은 너무 많이 받았고 그 외로도 취업 준비나 여러 얘기들 많이 드린 것 같은데 잘 들어주시고 조언해주신 점도 너무 감사했습니다.ㅎㅎ
지영

건모님 덕분에 처음부터 끝까지 동작하는 실험 코드 경험해볼 수 있었습니다 베이스라인 코드에서 갑자기 그래프가 뚝딱뚝딱 그려지고 완디비로 다 넘어가고 이런거 너무 좋았어요..ㅋㅋㅋ 그리고 무엇보다도 열정을 많이 배워갑니다 주말에 수업이 없어서 하고싶은 코딩을 할 수 있어서 좋다고 말씀하신게 너무 인상적이고 기억에 남아요..^^ 덕분에 저도 열정 끌어올려서 이번 스테이지 열심히 할 수 있었습니다! 너무 많이 배웠는데 헤어지자니 아쉽네요 ㅜㅜ 그래도 우리 계속 같이 스터디 잘 해봐요 ㅋㅋ 수연

건모님!! 초반에 팀원들을 위해 많은 시간을 쏟으시는걸 보면서 많은걸 느꼈어요 그리고 MRC 기간 내내 이걸 즐기고있다는게 눈에 보여서 또 존경스러웠습니다.. 뭔가 할 일을 대하는 자세가 남다른 것을 보고 아 나도 얼른 저렇게 되어야지라는 생각을 많이 했던 것 같아요 항상 팀원들에게 여러 TMI 공유를 통해 활기도 많이 불어넣어주시고 코딩 인사이트도 많이 제공해주셔서 저희팀의 기둥같은 존재였습니다!! 지금 팀과 Stage4때도 이어서 같이 하고 싶었는데ㅠㅠ 바꿀 기회를 이제 안주더라구요 😡 부캠 끝나면 꼭 같이 프로젝트 해요!! 범블봇 만드실때 저 빼고 만들지 마시구요ㅋㅋㅋㅋㅋㅋ😜 나중에도 많이 만나서 더 많은 것들을 배우고 싶다는 생각이 듭니다!!! 제가 많이 질척거릴게요 크하하 종헌

김종헌(Human)

이번 Stage에서는 지난 Stage 1, 2에서는 해보지 못했던 많은 일들을 해낸 것 같아 너무 뿌듯했습니다. 지난 스테이지들에서 저는 항상 리더보드 스코어만을 맹목적으로 좇았고 그 과정에서 결과적으로 남은 것이 적다는 느낌을 많이 받았습니다. 하지만 이번 스테이지에서는 제대로 된 협업 프로세스를 구축하고 정말 내가 잘하는 것이 뭔지, 내가 팀에게 기여할 수 있는 것이 뭔지 많이 생각해볼 수 있었습니다. 무엇보다도 지금까지의 부스트캠프 기간 중 지난 한 달의 시간동안 가장 많은 것을 얻었던 것 같습니다.

일단 저는 git을 잘 써보자!라는 막연한 목표를 가지고 이번 stage를 시작했습니다. 이전에 제대로 된 협업을 해본 경험이 없었고 옛날부터 항상 이 부분에 대한 갈증이 늘 심했었습니다. 그런데 결과적으로 이 부분에서는 제 자신에게 100점을 줄 수 있을 정도로, 목표 달성에 성공하였다고 생각합니다! git에 익숙한 팀원들에게 issue 관리, branch 관리 등 여러 git의 유용한 기능들을 다양하게 배울 수 있었고 ZenHub등의 플러그인을 활용하여 보다 효율적인 업무 시스템을 구축할 수 있었습니다. 가장 중요한 것은 좋은 도구들을 굉장히 효율적으로 사용했다는 점입니다. 늘 협업을 제대로 해보고 싶다라는 생각을 해왔었는데 좋은 팀원들 덕분에 이 모든 갈증을 해소할 수 있었다는 점에 너무 뿌듯하고 감사합니다.

다음으로 저는 하고 있는 것을 제대로 이해하자라는 목표도 있었습니다. 이전 스테이지들에서 너무 성능을 올리는 데에만 치중하며 시간을 보낸 나머지 코드 관리나 원리에 대한 깊은 이해 등을 제대로 해내지 못했기 때문입니다. Stage 2에서는 이러한 점을 스스로 인식하고 고치려고 노력하였으나 여전히 쉽지 않았습니다. 하지만 이 목표 역시 이번 스테이지의 팀원들과 함께 배워나가며 자연스레 이루어낼 수 있었습니다. 팀 내 뭐든 다같이 소통하며 해결나가자라는 분위기가 잘 형성되어 있었기 때문에 잘 이해되지 않는 것들은 소통을 통해 해결하였고, 다들 언제나 성심성의껏 답변해주셔서 스스로의 성장에 큰 도움이 되었던 것 같습니다. 오히려 너무 저 혼자 모르는 것들을 해결하고 남들에게는 공유하지 못했던 것은 아닌가 하는 생각이 들어 지금와서 이런 부분에 대한 반성을 하게 되네요..

저는 그동안 어떤 목표를 세우고 이를 성취하는 데에 실패했던 경험이 아주 많았습니다. 그래서 사실 이번 대회를 시작할 때에도 제가 세웠던 목표를 이룰 수 있을지, 뭔가 확신이 없었습니다. 그런데 한 달을 정신 없이 보내고나서 되돌아보니 목표 대부분을 이루어낸 것 같다는 생각이 듭니다. 굳이 의식하지 않았는데도요..! 세운 목표를 이루기 위해 제가 의식적으로 노력하는 것보다도, 자연스럽게 목표를 이룰 수 있도록 환경을 잘 조성하는 것이 얼마나 중요한지 깨달을 수 있었습니다.

가장 만족스러웠던 점은, 이렇게 어려운 task를 다루면서도 한 달이라는 긴 시간을 너무나 즐겁게 보낼 수 있었다는 것입니다. 한편으로는 이번 한 달이 너무나 빠르게 지나가 아쉽기도 합니다. Stage 4에서 과연 이보다 잘할 수 있을지, 이보다 더 만족스러운 한 달을 보낼 수 있을지 솔직히 두렵지만 부스트캠프 기간을 거치면서 계속해서 성장해왔기 때문에 다음 스테이지에서도 잘 할 수 있겠지 생각하며 이번 스테이지 회고를 마칩니다 😊

저는 종헌님한테 사과 드릴 점이 한 두개가 아닙니다 첫 번째로 Reader모델 도움을 드리지 못했던 것. 종헌님이 어떻게든 성능을 끌어올려주실꺼라고 생각을 했기 때문에 (결과적으로 성능도 올리셨지만

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
) Reader모델에 큰 관심을 두지 않았습니다. 근데 Reader모델 성능이 낮다고 github에서 미안하다고 말할 때 정말 정말 죄송했어요. 이 부분 꼭 사과하고 싶었습니다. 적고 나니 사과드릴게 한 개 밖에 없네요 ㅎ. 그리고 초반에 스테이지 4때 경량화 하셔서 같은 팀 못한다고 했을 때 많이 아쉬웠습니다. 그냥 뭔가 큰 대들보가 가는 느낌이 들었거든요 ㅎㅎ. 스테이지 4에서는 함께 못해서 아쉽지만 부스트캠프 끝나고 꼭 같이 프로젝트 하도록 합시다!! 전 A형이니 연락을 기다리도록 하겠습니다!!! 다시 한번 더 Stage 3 저희 팀 이끌어주느라 고생하셨습니다!!! 건모

다른 캠퍼님들께도 호들갑 떨었지만 종헌님은 저랑 비슷한 나이임에도 불구하고 항상 제가 배워갈 점이 정말 많은 팀장님이신것 같아요. 그런 종헌님과 새벽에 코딩하면서 이야기했을때, 종헌님이 저랑 비슷한 감정을 느끼셨다는 이야기를 듣고 너무 신기했어요. 제 입장에서는 가장 어려워보이는 파트를 맡으시며 정말 다양한 실험을 묵묵히 하시고 공유해주시는 모습이 정말 인상깊었어요. 제가 아직까지 아주 많은 사람을 만나보진 않았는데, 그중 멋있는 성취를 이룬 사람들은 종헌님을 많이 닮아있는것같아요. 한달 간 같이 프로젝트해본 경험 상 종헌님은 앞으로 훨씬 더 많은 성공을 이루실거같습니다. 대신 그때까지 밥은 꼭 두 숟갈 이상 뜨도록 하세요. 성익

제가 스테이지 2에서 제일 잘한 일은 종헌님에게 같은 팀을 하자고 한 일이었던 것 같습니다 그 한마디에 일사천리로 홍보도 해주시고 팀도 모아주시고 저는 너무 좋았습니당 제가 물어온 논문도 뚝딱뚝딱 구현해주시고 리액션도 항상 알차게 해주시고 다른 팀원들 사기도 북돋아주시고 2인자 역할을 좋아하신다고 하셨지만 너무 팀장 역할을 잘해주셔서 저희 팀이 잘 돌아갔던 것 같아요! 스테이지 4때 같은 팀이 아니라는게 너무 아쉽네요 ㅜㅜ 그래도 같이 스터디 잘 해봅시다!! 수연

종헌님 제가 말은 안했지만 제일 의지한 팀원분이세요..제 DM 몇번 받아보셨죠??ㅋㅋㅋ 뭔가 처음 팀빌딩할 때도 종헌님의 robust한 모습 보면서 팀 같이 하고 싶다는 생각 했었는데 같이 하게 되어서 너무 재밌고 즐거웠습니다. ㅎㅎ 책임감 있게 저희팀 잘 이끌어주셔서 너무 감사했습니다. 그리고 종헌님이랑 ETRI 관련해서 결과물을 잘 내보고 싶었는데 그러지 못해서 아쉬워요 ㅠㅠ 다음엔 도움 드릴 수 있게 더 머리를 굴려볼게요 흐흐 그리고 저희 맨 처음 베이스라인 코드 리뷰할 때 디버깅 툴 엄청 잘쓰시면서 분석해오신거 아직도 기억이 나요ㅎㅎ 짱짱! 지영

신지영(Human Retriever)

팀원들에게 도움을 받은 점, 그리고 그 과정에서 제가 느낀 점 위주로 서술하겠습니다.

  • 느낀점 1 : Clean Code를 지향하자

    파이썬을 오랫동안 쓰면서도 코드를 추상화하고 정리하는 일은 많이 없었던 것 같습니다. 그러나 이번 대회에서 피어님들과 코드 리뷰를 진행하면서 함수명 설정/변수명 설정/doc string 작성 등이 코드 가독성을 위해 얼마나 중요한지 알 수 있었습니다. 또한 제 코드를 리팩토링해주시는 피어님들을 보면서 깨끗한.. 코드.. 똑똑한.. 코드를 먼저 생각하고 짜야겠다는 생각이 많이 들었습니다. 앞으로는 1. 코드 간 중복 줄이기 2. 변수/클래스명을 잘 설정하여 표현력 높이기 3. 구현 초반부터 간단한 추상화 고려하기 등등 세가지 규칙을 토대로 코드를 짜볼 예정입니다.

  • 느낀점 2 : 부단히 노력하자

    저는 대회 중에 Dense Retriever 성능을 끌어올리지 못해서 많이 침울해져 있었습니다. 피어세션이 돌아올 때마다, 오픈소스를 써보거나 베이스라인 백본 코드를 바꿔보거나 등등 여러 시도를 했음에도 성능이 안나와 피어님들께 뭐라고 말씀을 드려야 할지 걱정부터 앞섰습니다. 순위권 팀들의 발표를 들어보니 모두 elastic search를 썼던데 주어진 시간동안 그 방법을 알아내지 못했다니.. 흑흑 너무 안타깝습니다. 제가 기운이 빠져있는 걸 아셨는지 피어님들이 시도해본 것에 의미를 두자고 위로해주시고 매순간 따뜻한 말들을 건네주셨습니다(ㅠ^ㅠ). AI 부스트캠프에 들어온 이후로 능력의 한계를 많이 느끼는데, 이번 팀원분들을 뵙게 되면서 어려움 속에서도 끝까지 버틸 수 있었습니다. 그리고 AI에 관한 지식들을 피어세션 때 정말 많이 배울 수 있었습니다. 이번 프로젝트에서 제가 느낀 미안한 감정들, 좌절감 등을 끝까지 잊지 않고 다음번에 만날 새로운 동료들에게는 도움이 될 수 있도록 더 노력해야겠습니다.

지영님~ 지영님이 만들어주신 hybrid 리트리버가 이번 대회 최고성능인데 elastic search가 다 무슨 소용이겠어요 이미 리트리버 파트에 너무 큰 기여를 해주셨어요! (이런 말 싫어하시는거같지만) 항상 별거 아닌거 했다고 생각하시는데 남들에게는 정말 큰 일이라는걸 알아주셨으면 좋겠습니다ㅠㅠ 진짜 자신감을 가져도 되실 실력이세요 초반에 지영님 없었으면 세팅 하나도 못했을거고 여러모로 우왕좌왕했을거예요 저희 협업 파이프라인 구축 지분의 절반 이상은 지영님이 이뤄내주셨어요 아마 stage 4때는 그래서 지영님이 에이스 아닐지⁉ 그러니까 그때는 주변분들께 미안한 감정 가지지 마시구요😥 아무튼.. 무엇보다도 항상 남들이 보지 못하는 디테일을 캐치하시는 지영님! 다음에 할때는 좀 더 편하고 재밌게 다같이 열심히 해봅시다 🥰😄 (프로젝트 같이 하실거죠?

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
) 너무 감사했습니다~! 종헌

저는 지영님 보면서 정말 항상 대단하다고 생각했습니다. 지영님이 지금까지 해오신 성실함도 그렇고, 협업을 수행하는 방식이나 끈기있게 코딩하는 모습 모두 너무 멋있었어요. 지영님 github에 있는 블로그 몰래 들어갔을때, 공부의 흔적들 보면서 정말 본받고싶다고 생각했습니다. 인프라 공부도 쉽지 않고, dense retriever도 쉽지 않았을텐데 너무너무 잘해내신 지영님이 팀원으로서 자랑스럽고 뿌듯합니다! 제가 볼땐 누구보다 기울기가 크신 분같습니다(개발 공부하는 많은 사람들을 봐왔지만 지영님 같은 분은 정말 잘 없으세요). 그리구 elastic search는 안써도 저희가 이겼습니다~ 아마 성능이 좋다해도 저는 안쓰는 게 더 좋았을거라고 생각해요. 속상해하지 말아요! 성익

지영님 너무 겸손하신 마음을 가지고 계셔서 더더 기여하고싶어해주신 덕분에 저는 그냥 앉아서 멋진 댄스🎶 리트리버와 위키를 얻었습니다.. 깃헙도 안쓴지 너무 오래돼서 쓰기가 무서웠는데 먼저 잘 준비해주셔서 용기를 가지고 커밋할 수 있었어요!! 위에 성익님도 말씀하셨지만 elastic search 안쓴건 아쉬워하지 않으셔도 됩니당.. 어차피 sparse retriever 기반이라 아쉬워해야 할 사람은 저이므로ㅋㅋㅋ 그래도 외부 API에 의존하지 않고 저희끼리 으쌰으쌰 개발한게 저도 더 좋았다고 생각해요!! 담당(?)이었던 저도 안아쉬우니까 지영님도 아쉬워하지 않기~ 그리고 어제도 말씀드렸지만 침울해하셨던 Dense retriever 성능 저희 팀이 1등인거 아시죠..?ㅋㅋ 같은 팀이어서 너무 좋았는데 헤어진다니 너무 아쉬워요 ㅜㅜ 저번에 말씀하신 것처럼 잘 되셔서 나중에 같이 또 프로젝트 하면 좋겠어요! 그 날만을 기다려봅니당

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
수연

O형이지만 A형 같은 지영님! 위의 댓글을 읽어보시면 아시겠지만 지영님은 정말 대단한 사람이니 풀 안죽으셔도 됩니다!! 지영님이 왜 대단하시냐면 처음에 팀원들을 위해서 Follow Up 해줬던 것 (Follow Up은 아무도 안하신 거 아시죠?) 그리고 ZenHub 사용과 Baseline Code 구축할 수 있도록 큰 의견을 실어 주시기도 했구요! 그리고 Hybrid Retrieval을 구현하겠다고 말씀하셨던 것 (1등 리트리버!) 그리고 ETRI API 사용까지!! ( ETRI가 적용됐다면 성능 향상에 큰 도움이 됐을 겁니다!) 곰곰이 잘 생각해보면 성능 향상에 큰 기여가 됐던 아이디어의 물꼬는 다 지영님한테 시작됐던 것 같네요! 지영님 구현은 익숙해지면 누구나 하게 되는 거지만 옳은 방향으로 이끄는 것은 아무나 못하는 겁니다. 그거 머리 좋은 사람만 하는거에요.. 그러니 나중에 같이 프로젝트 할 때는 자신감 넘치는 모습으로 봤으면 좋겠습니다! 이번 스테이지 정말 고생하셨습니다!!! 건모