Dacon 도배 하자 질의 응답 처리 경진대회 (1) 대회 탐색

2024. 2. 12. 15:05DL Life

어떤 대회지?

2월 동안 내 코딩 실력을 조금 늘리고자 어떤 활동을 해야할지 고민하고 있을 때, 이 대회를 발견하게 되었다.
마침 연구실에서 A100 서버도 사용할 수 있겠다. 내 코드 활용 능력도 조금 키워보고자 시작해보게 되었다.

목표?

  1. 공유된 코드보다 더 높은 성능의 코드 제출하기
  2. 새로운 아이디어 한 가지 이상 적용해서 성능 향상 시켜보기

탐색 과정

원래는 공유된 코드를 바탕으로 공부를 시작하려고 했는데, 설명도 불친절하고 어떤 방식으로 아이디어를 구상해야되는지도 모르겠어서 일단 가장 먼저 한 것은 공유된 코드를 내 환경에서 실행되는지 파악하는 것.

Dacon 코드 재구현

두 개의 글을 모두 실행해보았고 아이디어빌드는 그대로 진행이 되어서 생략
좀 더 점수가 높은 No Fine-tune / RAG 코드에서 오류가 발생했다

from langchain_community.document_loaders.csv_loader import CSVLoader   loader = CSVLoader(file_path='train_data.csv',encoding='utf-8')  data = loader.load() 

위 부분에서 계속 오류가 발생해서 진도가 더이상 나가지 않았다. 나중에 다시 Jupyter Lab 으로 옮겨 실험을 해보니 쭉 진행이 되어서 일단 넘어갔다.

from langchain_core.prompts import PromptTemplate from langchain_core.runnables import RunnablePassthrough from langchain_core.output_parsers import StrOutputParser  def format_docs(docs):     return "\n\n".join(doc.page_content for doc in docs)  template = """마지막에 질문에 답하려면 다음과 같은 맥락을 사용합니다.  {context}  질문: {question}  유용한 답변:""" custom_rag_prompt = PromptTemplate.from_template(template)  rag_chain = (     {"context": lambda x : retriever | format_docs, "question": RunnablePassthrough()}     | custom_rag_prompt     | hf     | StrOutputParser() )  
rag_chain = (     {"context": lambda x : retriever | format_docs, "question": RunnablePassthrough()}     | custom_rag_prompt     | hf     | StrOutputParser() ) 

이 부분에서 또 다른 오류가 발생해서 lambda x : 를 추가하여 진행하였다
(python - TypeError when chaining Runnables in LangChain: Expected a Runnable, callable or dict - Stack Overflow) 참고


일단은 학습을 진행시켜보았는데 다음과 같이 잘 되고 있는지에 대한 의문이 드는 학습이다. 일단 진행시키면서 다른 코드 참고

Kaggle 코드 재구현

내가 진행하고 있는 챌린지와 같은 문제들이 보통 ODQA(Open Domain Question Answer) 분야여서
해당 부분을 Dacon 이 아닌 Kaggle 에서 찾아보니 좀 더 다양한 챌린지들이 나오고 레퍼런스 코드도 다양했다.

일단 도메인은 잠깐 제쳐두고 챌린지에서 QA 모델이 어떻게 구현되고 활용되는지를 파악하기 위해 한 챌린지의 코드를 참고 해보려고 한다. (참고 코드 : DTC Zoomcamp Q&A Challenge)

보통 QA 문제에서는 SentenceTransformer 라이브러리를 많이 사용하는 것 같다.

Setup

!pip install -U sentence-transformers !pip install datasets  import os import pandas as pd import numpy as np import torch import warnings  from sentence_transformers import SentenceTransformer, models, InputExample, losses from sklearn.metrics.pairwise import cosine_similarity from torch.utils.data import DataLoader from datasets import load_dataset  warnings.filterwarnings("ignore") 

딱히 Dacon 과 다르지 않지만 정리가 잘 되어 있어서 코드를 가져오면서 흐름을 이해해보려고 한다.

Data Loading

test_answers_df = pd.read_csv("/kaggle/input/dtc-zoomcamp-qa- challenge/test_answers.csv") test_questions_df = pd.read_csv("/kaggle/input/dtc-zoomcamp-qa-challenge/test_questions.csv") train_answers_df = pd.read_csv("/kaggle/input/dtc-zoomcamp-qa-challenge/train_answers.csv") train_questions_df = pd.read_csv("/kaggle/input/dtc-zoomcamp-qa-challenge/train_questions.csv") 

이전에는 Langchain CSVLoader 를 사용해서 오류가 났었는데, 그냥 pandas 로 받아도 되는 것 같다. 나는 엄청 큰 차이가 있는줄 알았는데 아닌듯 하다.


데이터는 이런 식으로 되어 있다.

대회 데이터는
id,질문_1,질문_2,category,답변_1,답변_2,답변_3,답변_4,답변_5 식으로 되어있다.

Data Preprocessing

train_questions_df_triplets = pd.DataFrame()  for question_id, question, course, year, candidate_answers, answer_id in train_questions_df.values:     answers_list = candidate_answers.split(',')     negative_ids = [x for x in answers_list if x != str(answer_id)]     negative_list, positive_list = [],[]          for neg_id in negative_ids:         negative_list.append(train_answers_df[train_answers_df.answer_id == int(neg_id)]['answer'].values[0])              positive_list.append(train_answers_df[train_answers_df.answer_id == int(answer_id)]['answer'].values[0])          # Adding a single new row     new_row = {         'question_id': question_id,          'question': question,          'positive': positive_list[0],         'negative': negative_list,     }          train_questions_df_triplets = train_questions_df_triplets._append(new_row, ignore_index=True) 

Processes training data to create triplets of question, positive answer, and negative answers. 라고 하는데
Negative answer 는 정답이 아닌 답변 번호를 저장해서 쓰는 듯 하다

import pandas as pd train = pd.read_csv("train.csv")  from itertools import product   list(product([f"질문_{x}" for x in range(1,3)],[f"답변_{x}" for x in range(1,6)]))   train_data = [] for q,a in list(product([f"질문_{x}" for x in range(1,3)],[f"답변_{x}" for x in range(1,6)])):  	for i in range(len(train)):  		train_data.append( "질문: "+ train.at[i,q] + " 답변 : " + train.at[i,a] ) 

질문 1,2 랑 답변1~5 로 갖고 따로 만든다.
Category 를 사용하지는 않는듯?


“이 글은 Obsidian 에서 작성되어 업로드 되었습니다”