Giter Site home page Giter Site logo

vumblebot / odqa_baseline_code Goto Github PK

View Code? Open in Web Editor NEW
76.0 0.0 12.0 6.95 MB

Baseline code for Korean open domain question answering(ODQA)

Home Page: https://bit.ly/3fvgZZ0

License: Apache License 2.0

Python 98.70% Shell 1.30%
pytorch odqa machine-reading-comprehension mrc korquad question-answering bert electra openqa

odqa_baseline_code's People

Contributors

agnes-u avatar ebbunnim avatar ggm1207 avatar olenmg avatar seongikkim avatar sooyounlee avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

odqa_baseline_code's Issues

<feature> debug 기능 추가

사용법

python -m run --strategis ST01,ST02 --run_cnt 3 --debug true
python -m run --strategis ST01,ST02 --run_cnt 3 --debug True

코드
args.debug로 접근 가능.
debug: default 값은 False로 두고 True시에 아래 처럼 parameter 수정

수정 해야 될 것들

  • epoch 1로 설정 ( run.py 반복문 안에서 )
  • run_cnt 1로 설정 ( run.py 반복문 돌기 전에 )
  • 학습 시에 datasets['train'] 5%만 사용하도록 코드 수정 ( prepare.py )

기능 설명

  • 잘 돌아가는지 미리 체크해보는 기능

[BUG] Pororo 설치 후 학습 속도 느려지는 문제

🐞 버그 제보

  • pororo 설치 후 run_mrc 학습이 느려지는 버그

==========

  • pororo에서 사용하는 torch 버전으로 torch를 재설치함에 따라서 GPU를 사용하지 않게 되고 속도가 느려지게 된다.

pip install torch==1.7.1+cu101 torchvision==0.8.2+cu101 torchaudio==0.7.2 -f https://download.pytorch.org/whl/torch_stable.html

저는 위 명령어로 torch를 재설치 하니 속도가 다시 빨라졌습니다! GPU 사용이 가능해졌어요 😄

[BUG] xlm-roberta-large 모델 run시 struct.error 발생 관련

xlm-roberta-large 등 큰 모델 돌리면 공통적으로 발생하는 문제입니다.

🐞 버그 제보

  • 현재 베이스라인 기준 xlm-roberta-large 모델으로 돌리면 struct.error: 'i' format requires -2147483648 <= number <= 2147483647 에러 발생합니다.
  • 위 에러 해결하면 현재 README.md의 예시 strategy로 돌렸을때 기준 OSError: [Errno 12] Cannot allocate memory가 추가적으로 뜹니다.

👣 버그 발견 과정

  • 돌려보다가 발견했습니다.. :(

🤔 Bug shooting

struct error

  • 일단 첫번째 에러는 이 글이랑 연관됩니다.
  • 요약하면 Python 자체 버그로 최신 버전에서는 이슈 리포팅이 되어 수정이 되었으나, 저희 베이스라인 및 conda 기본 세팅이 Python==3.6.6혹은 Python==3.7.7이라 해당 버그가 수정되지 않은 버전입니다.
    • 해결방법은 위 글에서 말하는대로 직접 코드를 추가/수정하거나 Python==3.8 설치하면 됩니다.
    • 저는 귀찮아서 그냥 새로 가상환경파서 3.8 설치했는데 세팅이 생각보다 오래 걸려서.. 비추천드립니다.
    • 근데 글을 제대로 안읽어봐서 직접 코드 수정하는게 더 오래 걸릴지도 모릅니다ㅋㅋ
    • 3.8로 가상환경 새로 설치하실경우 일단 mecab에러없게 설치 먼저 하시고, wandb 등 필요한 모듈 추가적으로 설치하고 conda install pytorch==1.7.1 torchvision==0.8.2 torchaudio==0.7.2 cudatoolkit=10.1 -c pytorch로 pytorch 설치하시면 됩니다. (저희 서버 cuda 버전 10.1에 맞는 설치 명령어입니다)

OSError

  • 두번째 에러는 원인은 잘 모르겠고 ST00.json에서 dataprocessing_num_workers를 1로 주면 해결됩니다. 저건 GPU나 디스크 문제가 아니고 RAM 용량 문제인 것 같은데 아무튼 이러면 해결되는 것 같네요

  • (추가) xlm-roberta-large는 checkpoint 하나당 6.3GB의 디스크용량을 잡아먹으니 돌릴 때 디스크 용량도 주의해주세요! 제 기준 epoch 3.0에 예상시간 1시간~2시간 뜹니다. 왔다갔다거리네요


📸 스크린샷 첨부

  1. 첫번째 에러
    image (1)

  2. 두번째 에러
    image


🌏 환경 세팅

  • 부캠 서버

[SUGGEST] evaluation.py 이전

✔️ 추가하고싶은 기능

  • 프로젝트에 덧붙이고 싶은 기능들을 제안합니다. 아래의 종류에 맞게 체크해주세요.

  • Data

  • Preprocessing

  • Model

  • Feature

  • Paper

  • Serving

  • ETC (ex - library, reference.

==========

기존 baseline code의 evaluation.py와 같은 역할을 하는 코드를(혹은 동일한 코드를) 저희 베이스라인에도 넣으려고 합니다.
실제 리더보드에서의 성능평가 방법과 동일 방식으로 최대한 정확한 validation score를 측정 및 저장하고자 합니다.

==========


📚 레퍼런스 첨부

  • 해당 기능에 대한 정보를 어디서 알게되었는지 출처를 기록해주세요!
  • 책, 블로그, 유튜브, 논문 등

📸 스크린샷

  • 해당 기능을 적용시켰을 때의 사례를 미리볼 수 있게 사진 등으로 첨부해주세요.

[BUG] Trainer에 인자를 잘 못 넘겨주고 있었습니다..!!!

🐞 버그 제보

def get_trainer(self):
    trainer = QuestionAnsweringTrainer(
        model=self.model,
        args=self.args.train,
        custom_args=self.args,
        train_dataset=self.train_dataset,
        eval_dataset=self.eval_dataset,
        eval_examples=self.datasets["validation"],  # self.datasets로 넘겨주면 안됨.
        tokenizer=self.tokenizer,
        data_collator=self.data_collator,
        post_process_function=self._post_processing_function,
        compute_metrics=self._compute_metrics,
    )

self.datasets는 retrieve되기 전의 dataset이어서 top_k가 적용되지 않았습니다. ( 무조건 top-1 )

==========

  • eval_examples에 retrieve 되기 전의 Data를 넘겨주고 있었습니다.
  • top-k가 1일 때는 문제가 되지 않지만, top-k가 2 이상일 때는 context mapping이 제대로 되지 않습니다.

==========


👣 버그 발견 과정

  • 후처리 부분을 직접 타이핑하다가 발견함.

🤔 원래 예상했던 결과

  • 버그가 발생하기 이전, 내가 기대한 작동과정과 결과값의 형태를 간략히 서술해주세요.

📸 스크린샷 첨부

  • 버그 발생 당시의 스크린샷을 첨부해주세요.

🌏 환경 세팅

  • OS, 라이브러리 버젼 등을 명시해주세요.

[TODO] predict.py refactoring

📌 요약

  • (수행 전) predict.py 좀 더 쉽게 사용 할 수 있도록 리팩토링 하려고 합니다.

  • (수행 후) 결과는 어땠는지

📔 상세

Before

  • predict.py, model_oath 대신에 전략 입력하도록
    • ST01, ST02, ST03 처럼 여러개 입력해도 동작하도록 수정
      • emsemble True 면 1개의 결과 반환 아니면 각각 반환
    • --cheat 인자 추가, 정보 유출된 정보를 사용할지 말지를 결정
    • --ensemble 인자 추가, 전략에 해당하는 모델들의 결과를 Ensemble
      • Retriver 모델은 가장 성능 좋은 모델로 고정
      • Reader 모델은 전략에 따라 Update 된다.

After

[TODO] slack 포함 api key값 분리

✔️ 추가하고싶은 기능

  • 프로젝트에 덧붙이고 싶은 기능들을 제안합니다. 아래의 종류에 맞게 체크해주세요.

  • Data

  • Preprocessing

  • Model

  • Feature

  • Paper

  • Serving

  • ETC (ex - library, reference)

==========

slack_api.py를 포함해 혹시 추후에 api를 사용하는 환경에서 token이나 secret_key가 필요할 경우 github에 올라가지 않도록. input 디렉토리 아래에 secret.json을 따로 두어 key 및 token 값을 관리하고자 합니다.

단순히 같은 디렉토리에 숨김파일로 만들고 .gitignore로 처리해도되겠지만 의미상 input 디렉토리 아래에 두는게 좋을 것 같습니다!
괜찮으시면 기존 PR merge 이후에 제가 PR 날리겠습니다.

==========


📚 레퍼런스 첨부

  • 해당 기능에 대한 정보를 어디서 알게되었는지 출처를 기록해주세요!
  • 책, 블로그, 유튜브, 논문 등

📸 스크린샷

  • 해당 기능을 적용시켰을 때의 사례를 미리볼 수 있게 사진 등으로 첨부해주세요.

[TODO] BM25 사용하여 question,document pair 데이터 셋 만든 후 성능 실험해보기

📌 요약

  • (수행 전) question, document dataset 만들기

  • (수행 후) 학습 시간이 너무 오래 걸리고, 적당한 HyperParameter 찾기가 어려울 것 같다.

📔 상세

Before

  • question, documents (16개) 데이터 셋
  • document, questions (128개) 데이터 셋

After

우선 학습이 굉장히 오래 걸려서 한 번 실험하기가 너무 어렵다...

  • 무조건 Batch 1로 학습을 해야 돼서 시간이 오래 걸린다. accumulation step 을 적용해서 gradient update를 해야 될 것 같다.

[TODO] DPRElectra

📌 요약

  • (수행 전) Electra로 Dense Retriever 만들어보려고 합니다.

[TODO] wiki 중복 문서 제거

📌 요약

  • (수행 전) wiki에 중복 문서 제거해서 retriever 돌려보기

  • (수행 후)

    • Wiki EDA 수행함
      • fuzzy ratio가 아예 다른 문서의 경우 0.1이 나옴 - 0.5정도의 threshold도 넉넉할 것으로 보임
    • Exact Match 제거한 문서로는 성능 향상이 크지 않음
    • Exact Match 제거한 후 topk=1로 돌렸을 때, 제거 전과 서로 잘 뽑아오는 문서가 \n인지 \n 인지에 따라 갈림 - sparse retriever 성능을 위해서는 \n을 모두 제거하고 넣어주는 것이 성능이 더 향상될 것으로 보임
    • 유사 문서 제거는 5만개 document 대상 embedding을 구해서 유사도를 계산해야 하는데, 서버가 자꾸 터지고, EM 제거 후 결과를 보았을 때 추가적으로 노력을 투입해야하는지 의문스러움

📔 상세

Before

  • 현재 wiki에 중복문서들이 많아, top-k에 유사한 문서들이 중복되서 뽑히기도 함. 유사한 문서를 제거한다면 성능 향상이 기대됨.

After

  • 우선적으로 Exact Match를 제거하고 retriever를 돌려 봤는데, 슬프게도 성능 향상이 없었음...ㅜㅜ
    image
  • Wiki EDA 결과 fuzzy ratio를 0.5로 두어도 괜찮다는 소기의 성과 - 0.5로 두었을 때 성능이 소폭 향상한 것을 확인할 수 있음
  • Exact Match 제거한 후 topk=1로 돌렸을 때, 제거 전과 서로 잘 뽑아오는 문서가 \n인지 \n 인지에 따라 갈림 - sparse retriever 성능을 위해서는 \n을 모두 제거하고 넣어주는 것이 성능이 더 향상될 것으로 보임

[TODO] DashBoard 제작

📌 요약

  • (수행 전) Bokeh 를 사용한 Dash Board 제작

  • (수행 후) 결과는 어땠는지

📔 상세

Before

  • embedding.bin
  • wiki dataset
  • top k 데이터

이 세 가지를 잘 결합하면 Retriever 분석에 큰 도움이 될 것 같습니다! 필요한 기능 있으시면 댓글 달아주세요

  • EX) 틀린 정답들의 문서 별 길이 보여주는 기능.

After

[TODO] ColBERT 구축, Dense Retriever

📌 요약

  • (수행 전) Token 수준의 Interaction을 하는 Dense Retriever를 구축합니다.

  • (수행 후) TOP-3 90%인데 이걸 굳이? 라는 느낌이 드네요..

📔 상세

Before

After

  • Token Level의 상호작용이란, Token dim의 크기에 따라서 Size가 더 커질 수 있다는 걸 의미한다는 사실을... 깨닫지 못했습니다. ㅠ
    • Embedding 하나에 15G 사용
    • 성능만 좋다면 미리 Test Dataset에 Validation을 결합하는 방식도 좋을 것 같습니다.

[QA/REVIEW] DPR retrieval 학습 관련 질문입니다.

📸 코드

  • 코드나 코드에 대한 스크린샷을 첨부해주세요.

vumblebot_prepare

🤔 궁금한 점

  • 궁금한 점, 리뷰할 점을 상세히 기술해주세요.

안녕하세요, 좋은 repository 공유해주셔서 감사합니다.
retrieval 의 DPRBERT embedding을 처음부터 다시 학습하려고 하는데, 궁금한점이 있어서 문의드립니다.
README 의 내용을 참고해서, "retriever_name": "DPRBERT", "retrain": true, "dense_train_dataset": "train_dataset", 등으로 설정하고 30 epoch을 돌렸는데, loss 는 떨어지는데 retrieve된 결과가 좀 이상한것 같습니다.

DPRBERT 학습 시, BaseTrainMixin 의 _train() 함수로 학습을 시작하는데, 혹시 제가 뭔가 잘못 진행하고 있는걸까요?
가능하다면, DPRBERT 학습에 필요한 전략 파일 설정을 받을 수 있을까요?
감사합니다!

아래는 제가 사용했던 전략 파일 내용입니다.
{
"alias": "EXAMPLES DPRBERT",
"model": {
"retriever_name": "DPRBERT",
"tokenizer_name": ""
},
"data": {
"dataset_name": "squad_kor_v1",
"sub_datasets": ""
},
"train": {
"save_total_limit": 2,
"save_steps": 100,
"logging_steps": 100,
"overwrite_output_dir": true,
"do_train": true,
"do_eval": true,
"do_predict": false,
"report_to": ["wandb"]
},
"retriever": {
"retrain": true,
"dense_train_dataset": "train_dataset",
"topk": 10,
"learning_rate": 3e-5,
"per_device_train_batch_size": 4,
"per_device_eval_batch_size": 4,
"num_train_epochs": 30,
"weight_decay": 0.01
}
}

📚 레퍼런스 첨부

  • 의문 해결에 도움을 주는 참고 문헌이 있다면 기록해주세요!
  • 책, 블로그, 유튜브, 논문 등

[BUG] eval results 업데이트 미갱신

🐞 버그 제보

        if args.train.do_eval:
            eval_results = trainer.evaluate()
            evaluation(args)
            print(eval_results)

여기서 찍히는 eval_results 값이 저장되는 값이랑 다릅니다!

==========

  • evlauation 모듈이 추가 되면서 값이 달라지게 된 것 같습니다.
        if args.train.do_eval:
            eval_results = trainer.evaluate()
            results = evaluation(args)
            ## 여기서 eval_results 를 갱신한다음 Print 하는 방향으로 진행하겠습니다!
            print(eval_results)

==========


👣 버그 발견 과정

  • slack_api 추가 과정 중 발견했습니다!

[TODO] Wiki pre-processing 바꿔서 retriever 성능 향상 실험해보기

📌 요약

  • title 별로 문서 묶어보기
  • 질문들에 한자/ 고대한국어/ 외국어 있는지 확인 후, 없다면 문서에서 한자 없애기/ 한자가 많은(50% 이상?) 문서 아예 제거
  • question들 tokenizing 후 주요 단어들이 잘려서 들어간다면 다시 붙여서 넣는 방법 생각해보기
    -> 성익님 전처리에서 다룰 예정

📔 상세

Title 별로 문서 묶어보기 (묶지 않은 경우 non_agg, 묶은 경우 agg)

  1. BM25로 실험: 동일 parameter 기준
  • non_agg: topk=1에서 56.67%
  • agg: topk=1에서 70%
  • 하지만 90%는 aggnon_agg보다 늦게 달성. 파라미터 차이일 수도.
    image
  1. TFIDF로 실험: parameter 영향을 제외하고 보기 위해, TFIDF로 두 조건 구동.
  • non_agg: topk=1에서 43.33%, topk=2에서 63.75%, topk=3에서 70.83%, topk=100에서 94.17%
  • agg: topk=1에서 57.08%, topk=2에서 70%, topk=3에서 73.33%, topk=100에서 95%
    image
  1. BM25 파라미터 바꿔보기:
  • 파라미터를 바꾸니 오히려 결과가 떨어짐. 현재 찾아 놓은 파라미터가 최적이었음.
    image

[SUGGEST] document random masking

✔️ 추가하고싶은 기능

  • 프로젝트에 덧붙이고 싶은 기능들을 제안합니다. 아래의 종류에 맞게 체크해주세요.

  • Data

  • Preprocessing

  • Model

  • Feature

  • Paper

  • Serving

  • ETC (ex - library, reference.

Reader 모델 학습 시 document를 random으로 masking해서 task의 난이도를 상승시킴


📚 레퍼런스 첨부


📸 스크린샷

  • 해당 기능을 적용시켰을 때의 사례를 미리볼 수 있게 사진 등으로 첨부해주세요.

코드 리뷰 및 질의

일단 제가 나중에 보려고 이해한 내용을 적어보았고, 아직 안보신 분들께도 도움이 될 수도 있어 올립니다 😊

run.py 동작

python -m run strategies ST01 --run_cnt 1

  • tool.get_args로 argument 가져오기
  • train_reader 실행
    1. argument setup - tools.update_args 실행
      • update_args는 config에서 json 파일 불러와서 반영할(덮어쓸) argument를 args에 넣어주는 역할
    2. dataset setup - prepare.prepare_dataset 실행
      • 지정된 경로에서 dataset 가져와서 반환, train/valid에 따라 구분
    3. model & tokenizer setup - prepare.get_reader_model 실행
      • pretrained_model을 불러온다. (저장된거 or huggingface에서)
        ! (참고) args.modelargs.model_path
        • args.model = ModelArguments(model_name_or_path='monologg/koelectra-small-v3-discriminator', ...)
        • args.model_path = '/input/checkpoint/ST01_0_temp/checkpoint-500'
    4. retriever setup - prepare.get_retriever 실행
      • tfidf retriever면 retrieval.SpraseRetrieval 객체 생성(이건 이전과 동일한 코드)
        ! 현재 다른 retriever에 대한 옵션 추가 필요, 물론 [다른 retriever]도 만들어야 함
    5. retriever sparse embedding으로 세팅
      ! 이것도 dense 코드 추가되면 분기 나눠줘야함
    6. train dataset 전처리 - prepare.preprocess_dataset
      • 원래 베이스라인과 동일한 함수로 dataset 정제
    7. valid dataset 전처리(1) - prepare.retrieve_pipeline, prepare.preprocess_dataset
      ! 여기서는 가장 관련성 높은 context를 찾아 반환한다. (ground-truth 말고 tfidf로 retrieve 예측된거)
      • 일단 retrieve_pipeline 실행
        • self.retrieve 실행
          • valid set의 전체 query에 대한 전체 문서의 유사도 구해서 가장 큰 거 score 및 index 반환
        • dataframe으로 넣기 위해 question, id, context_id, context, original_context, answers 정제
          ! 여기서 id는 질문의 id(mrc-0-0000, ...), context_id는 지문의 id(0, 1, 2, ...)임
          ! context는 예측한 지문, original_context는 ground truth 지문
          ! answers 내에는 answer_start, text가 들어있음
        • dataframe으로 넣고 반환
      • dataset 형태 정하기 - predict 중인가? validation 중인가?
        • predict 중이면 answer는 모르니까 빼고 넣기
        • validation 중이면 answer도 넣기
      • dataframe 반환
        ! 전처리 전 features: ['__index_level_0__', 'answers', 'context', 'document_id', 'id', 'question', 'title']
        ! 전처리 후 features: ['answers', 'context', 'id', 'question']
      1. valid dataset 전처리(2) - prepare.preprocess_dataset
        ! retrieve한 문서가 valid dataset의 context로 설정된 상태
      • 원래 베이스라인과 동일한 함수로 dataset 정제
    8. data_collator 불러오기
    9. train, eval 모드 설정
    10. train/evaluation

질문 및 제안

질문1

valid dataset 정제시 retrieve에서 실제로 활용하는 column은 위에서 언급했듯이 ['answers', 'context', 'id', 'question'] 뿐인데 다른 column값들(context_id, original_context 등)을 굳이 넣어야할까요? 아니면 나중에 다른 곳에 쓰일수도 있기 때문에 다른 부분도 넣는걸까요? (사실 이건 그렇게 주요한 사안은 아닙니다. 😕 가볍게 생각해주세요)

제안1

args.train.do_train, args.train.do_evaltrain_reader에서 설정해주지 말고, 사용자의 argument 입력으로부터 정보를 얻어와서update_args에서 값 설정해주고 아래

train_results = trainer.train()
eval_results = trainer.evaluate()

이 부분과 eval_dataset 불러오는 부분도 이에 맞춰 분기 나눠주면 좋을 것 같습니다.

제안2

추후 retriever가 여러개 생겼을 때를 대비하여 run.py 에서 retriever 불러오는 부분을 수정하는게 좋을 것 같습니다.

get_sparse_embedding()을 아예 get_retriever내부로 넣는 방향으로요!

수정 전

#run.py
...
retriever = get_retriever(args)
retriever.get_sparse_embedding()
...
#prepare.py 
...
def get_retriever(args):
    if args.model.retriever_name == "tfidf":
        from konlpy.tag import Mecab

        mecab = Mecab()
        retriever = SparseRetrieval(args, tokenize_fn=mecab.morphs)
    return retriever
...

수정 후

#run.py
...
retriever = get_retriever(args)
...
#prepare.py 
...
def get_retriever(args):
    if args.model.retriever_name == "tfidf":
        from konlpy.tag import Mecab

        mecab = Mecab()
        retriever = SparseRetrieval(args, tokenize_fn=mecab.morphs)
        retriever.get_sparse_embedding()
    elif ... 
    return retriever
...

리팩토링하려다가 실패한 부분

현재 post_processing_function을 train/eval dataset 전처리마다 한번씩 리턴해주고, train만 할때는 사용하지도 않는 함수라서 이 함수를 그냥 밖으로 빼려고 했는데 생각해보니까 args 변수때문에 밖으로 뺄 수가 없더라구요.
굳이 뺄 필요가 없긴 한데, 그래도 현재 코드가 완전히 깔끔한 구조라고는 볼 수 없을 것 같습니다.
이 부분에 대해서 아이디어 있으신 분은 제안 부탁드립니다!

[TODO] 답 post-processing

nbest 생성된 답/context pair 바탕으로, 답이 속한 문장을 pos tagging한 뒤 답을 후처리하는 노트북 코드를 작성했습니다.
EM 혹은 F1 스코어가 상승하는 것으로 보입니다. 다만 첫 번째 뽑힌 답이 부적절해서 필터링이 되고, 후순위에 답이 있을 경우에만 유의미합니다.
노트북 파일 참조

노트북파일 받으셔서 서버에 올리시고 아래 변수 바꿔주시면 사용하실 수 있습니다.
image

저는 F1 스코어가 상승했고,
image.png

건모님 파일 post-processing한 결과 EM이 상승하셨다고 합니다.
image.png

다만 약간 너무 인간이 필터링한...느낌이라서... 종헌님/지영님께서 하시는 작업으로 이런 이상한 답들이 다 걸러지길 기대해봅니다 ㅎㅎ
image.png

<refactor> SparseRetrieval 클래스 이름 변경

추후 Retrieval이 얼마나 많이 생길진 모르겠지만, 좀 더 명확한 구분을 위해
SparseRetrieval -> TfIdfRetrieval 혹은 TfIdf 등으로 클래스명 변경하는 것이 좋을 것 같습니다.

수연님께서 구현해주신 BM25도 Sparse Retrieval의 일종이기도 하구요!
프로젝트가 더 커지기전에 이름 변경 미리 해두는게 좋을 것 같아요

[QA/REVIEW] 비슷한 정답을 LB스코어에서 EM으로 인정하는가?

📸 코드

  1. 테스트데이터셋 mrc-0-002191

Screen Shot 2021-05-13 at 11 52 52 AM
Screen Shot 2021-05-13 at 11 53 06 AM

정답(추측) : 빌헬름 미클라스

기존의 prediction : 대통령인 빌헬름 미클라스

  • 빌헬름 미클라스로 바꾸고 제출했을때
    • EM : 32.08% → 32.50%
    • F1 : 43.34% → 43.44%
  1. 테스트 데이터셋 mrc-0-002169

Screen Shot 2021-05-13 at 11 54 04 AM
Screen Shot 2021-05-13 at 11 54 17 AM

정답(추측) : 다케다 한시, 다케다 한시(武田範之)

기존의 prediction : 다케다 한시(武田範之)

  • 다케다 한시로 바꾸고 제출했을때
    • EM : 32.08% → 31.67%
    • F1 : 43.34% → 43.22%
  1. 테스트 데이터셋 mrc-0-000898

Screen Shot 2021-05-13 at 11 54 47 AM
Screen Shot 2021-05-13 at 11 55 00 AM

정답(추측) : 이회창, 이회창 후보

기존의 prediction : 이회창 후보

  • 이회창으로 바꾸고 제출했을때
    • EM : 32.08% → 31.67%
    • F1 : 43.34% → 43.24%

Screen Shot 2021-05-13 at 11 56 01 AM


🤔 궁금한 점

  • 생각보다 정답 기준이 빡빡합니다. 동일한 맥락/동일한 의미의 단어라도 호칭 등이 붙지 않으면 EM 스코어가 찍히지 않습니다.
    • 비슷한 단어를 정답으로 인정해주는 경우는 "<중앙일보>" == "중앙일보" 정도일것같습니다.
  • reader 모델이 어떻게 해야할까요?
    • 정답 단어를 살펴보면 정확히 질문의 답변에 해당하는 문장에서 나온 단어임을 알수 있습니다(ex- 이회창 대신 이회창 후보).
    • reader 모델이 정답을 뽑을 때 context 전체에서 답변을 뽑아내지말고, context에서 정답이 들어있을법한 문장을 logit값으로 뽑은 뒤 그 내부에서 정답을 찾아내도록 하는건 어떨까요?
      • 이렇게 되면 정답이 들어있을법한 문장도 k개(혹은 j개)를 뽑아야 할까요?

📚 레퍼런스 첨부

  • 의문 해결에 도움을 주는 참고 문헌이 있다면 기록해주세요!
  • 책, 블로그, 유튜브, 논문 등

[QA] DPR 오픈소스를 쓰기 위한 데이터 형식 매칭

질문

  • 새로운 Dense Retrieval를 고민하다가 DPR 오픈소스를 사용해보려고 합니다.
  • 그런데, training 시에 기존에 학습된 데이터셋 형태로 맞춰달라는 요구사항이 있었습니다.
{
        "dataset": str,
        "question": str,
        "answers": list of str
        "positive_ctxs": list of dictionaries of format {'title': str, 'text': str, 'score': int, 'title_score': int, 'passage_id': str}
        "negative_ctxs": list of dictionaries of format {'title': str, 'text': str, 'score': int, 'title_score': int, 'passage_id': str}
        "hard_negative_ctxs": list of dictionaries of format {'title': str, 'text': str, 'score': int, 'title_score': int, 'passage_id': str}
    }

출처

negative_ctxs은 저희가 논의한 negative sample을 넣는 컬럼 같습니다!
조교님 추천에 계속 등장하는 논문의 구현체들이라, 꼭 사용해보고 싶은데 늘 데이터셋 형식을 맞추는 것에서 발목을 잡히네요.

혹시 이 오픈소스를 사용할 수 있는 방법 (haystack은 DPR 오픈소스를 쉽게 사용할 수 있도록 도와주는 오픈소스입니다) 떠오르시는 분들은 알려주시면 좋겠습니다. ㅠㅠ

[TODO] DPR에 evaluation 추가

📌 요약

  • (수행 전) Dense retriever training 쪽에 evaluation이 없어서 과적합 판단이 어려운 상황입니다. evaluation 코드를 추가하고자 합니다.

  • (수행 후) 결과는 어땠는지

📔 상세

Before

After

[SUGGEST] reader의 datasets 로딩

✔️ 추가하고싶은 기능

  • Data
  • Preprocessing
  • Model
  • Feature
  • Paper
  • Serving
  • ETC (ex - library, reference.

보이는대로 갈아버리고 피드백을 받아보자 하고 올리는거라 이건 아닌거같다 싶으면 말씀해주세요

주요 내용

  • BaseReader 클래스의 __init__()에서 dataset 초기화 관련 내용 삭제

  • 대신 BaseReader 클래스의 set_dataset() 메소드에서 train_dataset, eval_dataset, 초기화

    • set_dataset()에서 is_run arg삭제, train_dataset, eval_dataset argument 유무로 판단
      • run*.py의 경우 set_dataset()에서 train_dataset, eval_dataset 모두 넘겨줌
      • predict.py의 경우 set_dataset()에서 eval_dataset 부분만 argument로 넘겨줌
  • BaseReader 클래스의 preprocess_dataset()에서 is_train을 통해 datasets['train']을 가져올지, datasets['validation']을 가져올지 결정하는 부분 삭제

    • 이게 필요한 이유는 datasets에 2개 key(train, validation)가 있어서 어떤걸 preprocessing할지 고르기 위해서였는데 애초 넘겨줄 때부터 datasets 대신 datasets['train'] 혹은 datasets['validation']을 넘겨주면 이런 과정 필요 없음
    • 근데 어차피 is_trainprepare_*_features() 가져올 때 필요해서 꼭 필요한 수정 사항은 아님 (오히려 과한 수정일수도 있음)
  • 적용 예시

#base_reader.py
class BaseReader:
    def __init__(self, args, model, tokenizer):
        self.args = args
        self.metric = load_metric("squad")
        self.model, self.tokenizer = model, tokenizer

        self.data_collator = DataCollatorWithPadding(
            self.tokenizer, pad_to_multiple_of=8 if self.args.train.fp16 else None
        )

        self.train_dataset = None
        self.eval_dataset = None
        self.eval_examples = None

    def set_dataset(self, train_dataset=None, eval_dataset=None):
        if train_dataset:
            self.train_dataset = self.preprocess_dataset(train_dataset, is_train=True)
        if eval_dataset:
            self.eval_dataset = self.preprocess_dataset(eval_dataset, is_train=False)
            self.eval_examples = eval_dataset

    def preprocess_dataset(self, dataset, is_train=True):
        column_names = dataset.column_names

        self.question_column_name = "question" if "question" in column_names else column_names[0]
        self.context_column_name = "context" if "context" in column_names else column_names[1]
        self.answer_column_name = "answers" if "answers" in column_names else column_names[2]

        self.pad_on_right = self.tokenizer.padding_side == "right"
        self.max_seq_length = min(self.args.data.max_seq_length, self.tokenizer.model_max_length)

        prepare_func = self._prepare_train_features if is_train else self._prepare_validation_features

        dataset = dataset.map(
            prepare_func,
            batched=True,
            batch_size=self.args.data.batch_size,
            num_proc=self.args.data.preprocessing_num_workers,
            remove_columns=column_names,
            load_from_cache_file=not self.args.data.overwrite_cache,
            cache_file_name=self.args.data.cache_file_name
        )

        return dataset

    ...

    def get_trainer(self):
        trainer = QuestionAnsweringTrainer(
            model=self.model,
            args=self.args.train,  # training_args
            custom_args=self.args,
            train_dataset=self.train_dataset,
            eval_dataset=self.eval_dataset,
            eval_examples=self.eval_examples,
            tokenizer=self.tokenizer,
            data_collator=self.data_collator,
            post_process_function=self._post_processing_function,
            compute_metrics=self._compute_metrics,
        )

        return trainer
# predict.py (예시)
def predict(args):
    strategies = args.strategies

    for idx, strategy in enumerate(strategies):
        args = update_args(args, strategy)  # auto add args.save_path, args.base_path
        args.strategy = strategy
        args.train.output_dir = p.join(args.path.checkpoint, strategy)

        datasets = get_dataset(args, is_train=False)
        retriever = get_retriever(args)
        eval_dataset = retriever.retrieve(datasets["validation"], topk=args.retriever.topk)['validation']
        
        reader = get_reader(args)
        reader.set_dataset(eval_dataset=eval_dataset)
        # run_*.py의 경우 reader.set_dataset(train_dataset=datasets['train'], eval_dataset=eval_dataset)

피드백은 언제나 환영입니다. ^^
다 해놓고 보니 유의미한지 저조차 의문입니다ㅋㅋ;


📚 레퍼런스 첨부

  • 해당 기능에 대한 정보를 어디서 알게되었는지 출처를 기록해주세요!
  • 책, 블로그, 유튜브, 논문 등

📸 스크린샷

  • 해당 기능을 적용시켰을 때의 사례를 미리볼 수 있게 사진 등으로 첨부해주세요.

[TODO] 핵심 문장과 질문간 관계 파악을 위한 BERT 모델 제안

📌 요약

  • (수행 전) 핵심 문장(1개 or nbest concat)과 질문간의 관계 파악을 통해 정답을 추출하는 BERT 모델을 구현하고자 합니다.

  • (수행 후) 결과는 어땠는지

📔 상세

Before

  • 현재 MRC 모델의 validation/LB 성능이 낮게 나오는 주요 원인은, 충분히 정답으로 인정해줄만한 것들을 LB or Validation에서는 정답으로 인정하지 않는 데에 있습니다.
    • 정답과 예측값 간 포함관계를 출력해보면, 240개 예측값 중 약 200개에 가까운 예측값이 정답과 서로 포함관계에 있습니다. (예측값이 정답 내에 존재 or 정답이 예측값 내에 존재)
  • 사람이 보면 정답인 것들을 LB에서는 오답으로 지적하고 있으므로, 모델 자체의 이해력을 높이기보다는 채점 시스템에 맞는 정답을 뽑아내고자 합니다.
  • 핵심 문장은 정답으로 예측한 토큰이 존재하는 문장 1개를 대상으로 합니다. 성능이 좀 나오면 추후 nbest로도 확장할 생각입니다.
  • 만들고자 하는 모델은 독해를 위한 모델이 아니라, 말그대로 질문과 문장간의 관계 추출을 통해, 질문의 의도를 파악하여 딱 필요한 부분만 정답에 넣고(ex. 베게티우스 -> 작가 베게티우스) 필요하지 않은 부분은 제거하는(잦은 이슬비 가루아 -> 가루아) 작업을 수행하는 모델입니다.

After

[BUG] pororo 사용시 python-mecab-ko 설치 경로 오류

🐞 버그 제보

  • 버그가 어떻게 발생했는지 간략하게 요약하여 적어주세요.

==========

pororo branch merge 이후 python-mecab-ko가 설치되어 있음에도 불구하고 python 인식하지 못하는 문제

==========


👣 버그 발견 과정

  • 어떤 식으로 코드를 작동했을때 버그가 발생했는지 기록해주세요.
    ex)
  1. run_mrc, run, predict 등 모델 inference, eval 등을 수행
  2. pororo가 설치되어 있지 않거나, python-mecab-ko를 찾을 수 없다는 오류

해결 방법

  1. pororo 및 fairseq 라이브러리 설치
pip install pororo
pip install fairseq
  1. python-mecab-ko 심볼릭 링크 설정
  • 기존 베이스라인 코드를 돌릴 때 shell 파일로 python-mecab-ko를 아마 다 설치하셨기 때문에 실제로는 설치가 되어있는 상태입니다.
  • 그럼에도 불구하고 python-mecab-ko가 설치되어있지 않다는 오류가 뜨실 수 있습니다. 일단 pip install python-mecab-ko를 수행해보시고, 오류가 안뜨면 그대로 사용하시고 설치 중 오류가 나서 설치가 안된다면 다음을 따라해주세요.
  • 먼저 opt/conda/bin 디렉토리 하위에 mecab-config 디렉토리가 있는지 확인해봅니다.
  • 없다면, 아마도 /usr/local/bin 디렉토리 하위에 mecab-config 디렉토리가 있을 겁니다.
  • 기존에 설치된 mecab-config에 심볼릭 링크를 설정하여 conda activate시 python-mecab-ko를 찾는 경로로 이어줍니다(바로가기를 만든다고 생각하시면 됩니다.)
    • sudo ln -s /usr/local/bin/mecab-config /opt/conda/bin/mecab-config
    • 이후 다시 pip install python-mecab-ko를 수행하시면 됩니다.
  1. 정상적으로 심볼릭 링크가 연결되고 설치가 되었다면 그대로 run,run_mrc,predict를 수행하셨을 때 오류가 뜨지 않습니다.

혹시 문제가 있을 경우 noti해주세요!


참고 레퍼런스


📸 스크린샷 첨부

  • 버그 발생 당시의 스크린샷을 첨부해주세요.

🌏 환경 세팅

  • OS, 라이브러리 버젼 등을 명시해주세요.

[TODO] (05.06) 현재 MRC 모델의 성능과 valid set

📌 요약

  • 현재 베이스라인을 이용하여 xlm-roberta-base로 성능 측정하였습니다.

📔 상세

사실 아직 모델 하나 돌린거라 큰 의미는 없지만 xlm-roberta-large가 오류로 안돌아가서 xlm-roberta-base로 측정한 결과 먼저 공유드립니다. evaluation.py로 평가된 지표 기준입니다.

먼저 문서는 정답 문서로 고정시켜놓고 MRC 모델만 돌렸을 때의 성능입니다.

{
    "EM": {
        "value": "47.08%",
        "rank": true,
        "decs": true
    },
    "F1": {
        "value": "67.94%",
        "rank": false,
        "decs": true
    }
}

다음으로 MRC 모델 + Retriever 모델 모두 돌렸을 때 기준입니다.
현재 validation 및 predict에서 top-k개를 가져오지 않기 때문에 top-1로 생각하시면 될 것 같고 Retriever는 TF-IDF 사용했습니다.

{
    "EM": {
        "value": "21.67%",
        "rank": true,
        "decs": true
    },
    "F1": {
        "value": "36.00%",
        "rank": false,
        "decs": true
    }
}

문서만 어느정도 잘 가져온다면 EM 40% 정도는 넘을 수 있을 것 같습니다.

또한 이 모델로 prediction(LB 제출) 진행한 결과 EM 23.75%, F1 38.74% 얻었습니다.
이전에 튜닝 없이 진행했을 때 동일 백본(xlm-roberta-base)으로 EM 12.92% F1 20.26% 얻었던거 생각해보면 TF-IDF에서 max_features 없앤게 역시 주효했다고 볼 수 있을 것 같습니다.

지금 당장 이전과 다른게 TF-IDF의 max_features 없앤거밖에 생각이 안나서 이렇게 생각했는데 혹시 다른거 달라진게 있다면 댓글로 부탁드립니다!

그리고 지금 validation의 score와 LB score가 거의 비슷한 것 같은데, 지금 당장 여러 모델을 돌려보지는 못해서 확신할 수는 없지만, validation score도 의미있다고 생각할 수 있을 것 같습니다.
이건 추후에 모델 더 돌려보고 관련한 정보 더 공유드릴게요!

지금까지 나온 스코어들을 보고 드는 생각은

  1. retriever는 top-k로 어느정도 스코어를 보정할 수 있으니 성능이 더 올라갈 수 있음.
  2. MRC 모델만으로 나오는 스코어가 생각보다 불안정함. 현재 47%/67%에서 더 개선할 다른 방법을 찾아보아야함.
    (수정) 생각해보니 MRC 모델도 epoch 더 돌리면 스코어 올라갈 수 있을 것 같네요! 현재는 3epoch 기준입니다.

2번 문제의 경우 제가 읽기로한 논문 읽어보고 개선 방향 생각해보겠습니다.

05.07 수정 (xlm-roberta large 추가)

LB Eval-MRC+RT Eval-MRC
base 23.75/38.74 21.67/36.00 47.08/67.94
large 27.92/44.63 21.25/37.48 50.83/74.25

Suggest to loosen the dependency on fuzzywuzzy

Hi, your project odqa_baseline_code(commit id: 45954be) requires "fuzzywuzzy==0.18.0" in its dependency. After analyzing the source code, we found that the following versions of fuzzywuzzy can also be suitable, i.e., fuzzywuzzy 0.7.0, 0.8.0, 0.8.1, 0.8.2, 0.9.0, 0.10.0, 0.11.0, 0.11.1, 0.12.0, 0.13.0, 0.14.0, 0.15.0, 0.15.1, 0.16.0, 0.17.0, since all functions that you directly (1 APIs: fuzzywuzzy.fuzz.ratio) or indirectly (propagate to 5 fuzzywuzzy's internal APIs and 3 outsider APIs) used from the package have not been changed in these versions, thus not affecting your usage.

Therefore, we believe that it is quite safe to loose your dependency on fuzzywuzzy from "fuzzywuzzy==0.18.0" to "fuzzywuzzy>=0.7.0,<=0.18.0". This will improve the applicability of odqa_baseline_code and reduce the possibility of any further dependency conflict with other projects.

May I pull a request to further loosen the dependency on fuzzywuzzy?

By the way, could you please tell us whether such an automatic tool for dependency analysis may be potentially helpful for maintaining dependencies easier during your development?

[BUG] run_mrc.py 실행 시 context_id key error 발생

🐞 버그 제보

  • 메인 브랜치 기준
  • 현재 run_mrc를 debug 모드로 돌리면 evaluation 과정에서 'context_id'로 key error 발생합니다.
  • 다른 분들도 동일 에러 발생하시는지 궁금합니다. 제 브랜치가 방금 좀 꼬였어서 제 로컬 코드 문제인지도 봐야할 것 같습니다.

👣 버그 발견 과정

  • python -m run_mrc --strategies ST01 --debug True --report False --run_cnt 1로 실행
  • README의 config와 동일 전략 사용

🤔 원래 예상했던 결과


📸 스크린샷 첨부

image


🌏 환경 세팅

  • OS, 라이브러리 버젼 등을 명시해주세요.

[BUG] predict.py --do_predict 인자 Update 순서

🐞 버그 제보

  • 모델 성능 평가를 위해서 predict 실행하다가 발견했습니다!

==========

if __name__ == "__main__":
    # 생략
    args.train.do_predict = True  # <- 여기서 실행 된 이후로 update_args에서 do_predict가 False로 초기화됩니다.
    for idx, strategy in enumerate(strategies):
        args = update_args(args, strategy)  # auto add args.save_path, args.base_path
        args.strategy = strategy
        args.train.output_dir = p.join(args.path.checkpoint, strategy)
        args.train.do_predict = True

        datasets = get_dataset(args, is_train=False)

do_predict를 main 함수의 반복문 안에서 호출하도록 변경하겠습니다!

predict.py는 코드 리팩토링이 좀 필요한 코드이기도 합니다만.. 하나의 모델만 predict 하도록 유의하면서 코드를 사용하시면 괜찮습니다!!

[BUG] run 모듈 실행시에도 train dataset의 크기 출력 / run에도 debug/report가 필요할까요?

🐞 버그 제보

  • run 모듈은 오직 validation을 위한 모듈이라 train dataset을 사용하지 않는데, prepare.pyget_dataset()을 가져올 때 train dataset의 크기까지 출력해줍니다. run의 경우 train 폴더의 validation set을 활용해야하기 때문에, is_train=True로 들어가서 발생하는 현상입니다.
    • 사실 큰 상관 없긴한데, 혹시 몰라 말씀드립니다!
  • 그리고 마찬가지 이유로, run에서는 train을 하지 않기 때문에 debug 및 report가 필요 없는 것 같습니다.
    • debug는 train set의 크기를 100으로 만드는게 가장 큰 의의라 그렇게 생각했구요!
    • 코드상 변화는 필요 없을 것 같고, README에서 해당 부분 없애주는게 좋을 것 같습니다.

👣 버그 발견 과정

  • run 모듈 실행

🤔 원래 예상했던 결과

  • train dataset의 크기가 출력되지 말아야 합니다. (필수는 아닙니다..!)

📸 스크린샷 첨부

  • 버그 발생 당시의 스크린샷을 첨부해주세요.

🌏 환경 세팅

  • OS, 라이브러리 버젼 등을 명시해주세요.

[BUG] BM25 관련 발견한 이슈들

🐞 버그 제보

  1. bm25.pysparse_base.py에 구현되어있는 get_embedding() 메소드가 똑같이 구현되어있습니다.
  2. 현재 BM25Retriever에서 생성되는 embedding.binBM25.binBM25/디렉토리에 들어가지 않습니다.
  3. prepare.pyBM25Retriever을 불러오기 위한 코드 구현이 안되어있습니다.
  4. BM25 + mrc 돌리면 성능이 {'exact_match': 6.25, 'f1': 10.223824786324787, 'epoch': 3.0}로 슬랙에 올린 TFIDF의 성능보다 현저히 떨어집니다. 이건 근데 BM25의 문제인지 다른 문제인지 확인이 필요할 것 같습니다.
  5. (번외) model_args.py의 retriever_name의 default 값이 tfidf인데 현재는 tfidf를 TFIDF라는 이름으로 사용중입니다.

👣 버그 발견 과정

  • train/eval 돌려보면서 발견했습니다

🤔 수정 방향

  1. bm25.pyget_embedding메소드 구현 삭제
  2. 지금 얼핏 보기에는 args.path.embed = p.join(args.data_path, "embed")이고 self.embed_path = p.join(args.path.embed, "embedding.bin")로 들어가는 형태라서 이 부분을 self.embed_path = p.join([args.path.embed, self.name, "embedding.bin"]) 뭐 이런식으로 들어가야 할 것 같습니다.
  3. prepare.pyRETRIEVER에 BM25Retrieval 추가하고 BM25Retrieval 모듈 import하면 됩니다.
  4. 4번째 이슈의 경우 추가적인 확인이 필요할 것 같습니다 (이 부분은 아직 확인 안했습니다)
  5. 이것도 그냥 config/model_args.py 고치면 됩니다.

다른건 다 고쳤는데 4번 이슈만 아직 못 고쳤습니다! 확인해주시면 해당사항 반영하여 PR 넣겠습니다.


📸 스크린샷 첨부

(2번이슈)
image


🌏 환경 세팅

  • OS, 라이브러리 버젼 등을 명시해주세요.

<bug> topk의 개수에 상관없이 첫 번째 context만 사용하는 Issue

doc_scores, doc_indices = self.get_relevant_doc_bulk(query_or_dataset["question"], k=1)
for idx, example in enumerate(tqdm(query_or_dataset, desc="Sparse retrieval: ")):
tmp = {
"question": example["question"],
"id": example["id"],
"context_id": doc_indices[idx][0], # retrieved id
"context": self.contexts[doc_indices[idx][0]], # retrieved doument
}
if "context" in example.keys() and "answers" in example.keys():
tmp["original_context"] = example["context"] # original document
tmp["answers"] = example["answers"] # original answer

122, 123 번 째 줄을 보면 여러 개의 문서를 반환해도 한 개의 문서만 사용하는 코드인 것을 확인할 수 있습니다.

수정 건의 사항

  • topk 개의 문서를 반환받도록 수정하고
  • post_processing에서 topk 개의 문서에서 정답을 출력하도록 수정

[QA] GPU 연결 끊김현상 미치겠습니다...

📸 코드

  • 학습을 시작하기 전에 연결 끊기는 현상

스크린샷 2021-05-12 오전 9 42 49

  • 학습 중에 갑자기 연결 끊기는 현상

스크린샷 2021-05-12 오후 1 10 17

정말.... 제가.... 뭘 잘못하고 있는 걸까요?????
왜 제가 학습을 돌리기만 하면 이렇게 이슈들이 있을까요. run_retrieval, run 모두에 해당하는 이슈들입니다 ㅠㅠ

[TODO] Kobert Tokenizer, PretrainedFastTokenizer랑 기능 맞추기

📌 요약

  • (수행 전) Kobert Tokenizer, PretrainedFastTokenizer랑 기능 맞추기

    • return_offsets_mapping
    • return_overflowing_tokens
  • (수행 후) Kobert, Distillkobert를 사용하지 않는 방향으로 결정했습니다.

📔 상세

Before

  • Reader모델에서 한국어로 사전 학습한 모델이 성능이 좋게 나오는 것 같아서, Kobert Tokenizer를 빨리 업그레이드 해야될 것 같습니다.

After

  • 성능이 좋았던 모델은 Koelectra 모델이였고 Kobert는 성능이 좋지 않았는데 그 이유가 턱없이 부족한 vocab size인 걸로 판단이 되었기 때문입니다.
  • kobert의 vocab size는 8002개로 한국어 vocab을 표현하기에 적당한 개수인 30000개 보다 턱없이 부족합니다.

<fix> 함수 내 module import 관련 issue

def get_retriever(args):
    if args.model.retriever_name == "tfidf":
        from konlpy.tag import Mecabmecab = Mecab()
        retriever = SparseRetrieval(args, tokenize_fn=mecab.morphs)
    return retriever

위와 같이 함수 내 분기에 따라 module을 import 하는 방식에 대한 의견을 여쭙고 싶습니다!

모듈 상단에서만 import할 시

  • 코드가 깔끔해짐
  • 속도가 조금 더 느림

모듈 내 분기에 따라 import할 시

  • 코드가 좀 난잡해보일 수 있음
  • 분기를 거치지 않을 경우 해당 모듈 import하지 않으므로 속도에 이점이 있음

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.