본문 바로가기

AI

RAG를 위한 파인 튜닝 데이터셋 실습 EDA

728x90

RAG를 위한 파인 튜닝 데이터셋 실습

https://huggingface.co/datasets/iamjoon/klue-mrc-ko-rag-dataset

 

iamjoon/klue-mrc-ko-rag-dataset · Datasets at Hugging Face

[ "블리자드 엔터테인먼트(Blizzard Entertainment, Inc.)의 인기 디지털 카드 게임 하스스톤(Hearthstone®) e스포츠를 대표하는 세계 최고의 선수들 여덟 명이 챔피언의 전당에 이름을 올리기 위해 벌이는

huggingface.co

pip install datasets
import numpy as np
import matplotlib.pyplot as plt
from datasets import load_dataset
dataset = load_dataset("iamjoon/klue-mrc-ko-rag-dataset")

 

이제 허깅페이스로부터 데이터를 로드하고 이를 출력해보겠습니다. 데이터셋을 Hugging Face의 datasets 라이브러리를 사용하여 불러옵니다. 데이터셋 이름은 "iamjoon/klue-mrc-ko-rag-dataset"입니다.

 

로드된 데이터셋을 판다스 데이터프레임으로 변환합니다. 데이터프레임으로 변환한 이유는 데이터 조작과 분석을 보다 쉽게 하기 위함입니다.

데이터프레임에서 실습에 필요한 열만 선택하여 새로운 데이터프레임을 만듭니다. 선택된 열은 question, search_result, answer, extracted_ref_numbers, type입니다.

마지막으로 데이터프레임의 상위 5개 행을 출력하여 데이터의 구조와 내용을 확인합니다.

df = dataset['train'].to_pandas()
df = df[['question', 'search_result', 'answer', 'extracted_ref_numbers', 'type']]
df.head()
print('데이터 타입 종류:',df['type'].unique())

 

type에는 총 5가지 종류의 값이 존재합니다.

 mrc_question, mrc_question_with_1_to_4_negative, synthetic_question, paraphrased_question, no_answer 해당 값들은 각각 데이터의 유형을 나타내는데 데이터의 유형은 다음과 같습니다.

 

  • mrc_question: 장소나 이름, 날짜 등을 묻는 지엽적인 질문. 검색 결과는 5개로 고정.
  • mrc_question_with_1_to_4_negative: 장소나 이름, 날짜 등을 묻는 지엽적인 질문. 단, 검색 결과는 1~4개를 가진다.
  • paraphrased_question: 장소나 이름, 날짜 등을 묻는 지엽적인 질문. 단, 질문의 형태를 명사구로 변경하였다. 검색 결과는 5개로 고정.
  • synthetic_question: 이유, 장점, 단점 등과 같은 포괄적인 질문. 검색 결과는 5개로 고정.
  • no_answer: 질문에 대한 답이 검색 결과에 없는 데이터. 검새 결과는 5개로 고정.

1. mrc_question: 지엽적인 질문 + 검색 결과는 5개로 고정

print('5번 샘플의 타입:', df['type'].loc[5])
print('5번 샘플의 질문:', df['question'].loc[5])

5번 샘플의 타입: mrc_question

5번 샘플의 질문: 에티하드 웰니스 프로그램의 일환으로 위생에 관한 정보를 제공하는 것은 누구인가?

 

print('5번 샘플의 답변:', df['answer'].loc[5])

5번 샘플의 답변: 에티하드 웰니스 프로그램의 일환으로 위생에 관한 정보를 제공하는 사람은 특별 훈련 과정을 거친 에티하드항공의 웰니스 엠버서더입니다. 이들은 여행 전 과정에 걸쳐 조언과 건강 및 위생 조치에 대한 세부 사항을 공유하며 맞춤화된 정보를 제공합니다 [[ref3]].

 

print('5번 샘플의 답변에서 인용한 문서 번호:', df['extracted_ref_numbers'].loc[5])

5번 샘플의 답변에서 인용한 문서 번호: [3]

 

print('5번 샘플의 검색 결과 개수:', len(df['search_result'].loc[5]))

5번 샘플의 검색 결과 개수: 5

 

print('5번 샘플의 검색 결과 중 세번째 문서:', df['search_result'].loc[5][2])

5번 샘플의 검색 결과 중 세번째 문서: 아랍 에미리트의 국영항공사 에티하드항공이 지난 10월 21일 열린 ’2020비즈니스 트래블러 중동 어워드(Business Traveller Middle East Awards 2020)에서 ‘최고의 이코노미 클래스(Best Economy Class)’와 ‘최고의 상용고객 프로그램(Best Frequent Flyer Programme’)’상의 영예를 안았다. 이는 2012년과 2013년에 열린 비즈니스 트래블러 중동 어워드에서 각각 최고의 이코노미 클래스, 최고의 상용 고객프로그램 분야의 첫 수상을 한 이래로 2회째 수상 기록이다. 지난 해, 에티하드항공은 다양한 수상 경력을 지닌 비즈니스, 퍼스트, 더 레지던스 캐빈에서 펼쳐 온 혁신과 마찬가지로 이코노미석에서도 기내식 선택권을 넓히고 무선 기내 엔터테인먼트, 인체공학적 디자인으로 설계된 좌석과 여유로운 레그룸을 가진 이코노미석 도입을 비롯해 옆 좌석 비우기, 보다 넉넉한 이코노미 스페이스 석 선택 옵션, 선호좌석 선택 사항을 제공하는 등 기내 경험에 대한 더욱 다양한 선택권을 제공해 왔다. 이를 통해 승객이 개인의 필요와 요구에 맞는 맞춤화된 선택을 할 수 있도록 돕고 만족도 높은 항공 여행을 할 수 있도록 서비스와 상품 개선에 투자를 지속해 왔다. 또한, 에티하드항공은 항공사의 건강 및 위생 프로그램인 ‘에티하드 웰니스’프로그램을 통해 신종코로나바이러스로 인한 전례 없는 시기에 필수적인 여행을 해야만 하는 여행자들에게 마음의 평화와 여행에 대한 자신감을 심어주기 위해 펼친 다양한 노력이 고객의 긍정적인 평가를 받았다고 전했다. 예약 과정에서부터 공항 이용은 물론 항공여행에 이르기까지 인공지능 기술을 비롯한 최신 기술을 과감히 도입해 광범위한 예방 조치를 시행하고 있으며 업계 최초로 선보인 에티하드 웰니스 프로그램에서는 특별 훈련 과정을 거친 에티하드항공의 웰니스 엠버서더가 여행 전 과정에 걸친 조언과 건강 및 위생 조치에 대한 세부 사항을 공유하며 맞춤화된 정보를 제공한다. 한 해 동안, 에티하드항공은 에티하드 게스트 회원의 경험을 향상시키고 혜택의 범위를 확장함으로써 더 나은 가치를 선사하기 위한 노력을 펼쳐왔다. 최근에는 “당신의 특별한 손님(Your Special Guest)” 캠페인과 함께 삶의 소중한 사람을 지정해 선물을 보내주는 캠페인을 펼치며 비대면의 시대에서도 따뜻한 마음과 정을 표현할 수 있는 기회를 제공했다. 더불어 코로나19로 인한 팬데믹 상황을 고려해 추가 마일리지를 지급하거나 항공권 예약 및 변경에 있어 유연한 정책 도입을 도입함은 물론 파트너십의 범위를 확장해 회원 등급을 유지하기 위한 마일리지를 적립할 수 있는 방법을 다양화 했다. 한편, 신종코로나바이러스 상황으로 인해 올해 2020비즈니스 트래블러 중동 어워드는 온라인으로 개최되었으며 독자의 투표를 기반으로 선정됐다.

 

df['search_result_len'] = df['search_result'].apply(len)
df['extracted_ref_len'] = df['extracted_ref_numbers'].apply(len)

 

def plot_lengths_by_type(df, plot_type):
    """
    특정 type의 데이터에 대해 extracted_ref_len과 search_result_len의 분포를 시각화하고 값 출력.

    Parameters:
    df (pd.DataFrame): 데이터프레임
    plot_type (str): 시각화할 데이터의 type 값 (예: 'qa', 'summarize' 등)
    """
    # 유효한 type 값인지 검증
    if plot_type not in df['type'].unique():
        print(f"'{plot_type}'는 유효하지 않은 타입입니다. 데이터프레임에 존재하는 타입을 확인하세요.")
        return

    # 해당 type의 데이터만 필터링하고 전체 개수 계산
    df_type = df[df['type'] == plot_type]
    total_count = len(df_type)

    # 길이별 값 계산
    # extracted_ref_len: 실제 인용된 문서의 개수
    # search_result_len: 검색으로 조회된 문서의 개수
    extracted_counts = df_type['extracted_ref_len'].value_counts().sort_index()
    search_counts = df_type['search_result_len'].value_counts().sort_index()

    # 분석 결과 출력
    # 전체 데이터 수와 각 길이별 분포를 출력
    print(f"타입: {plot_type}")
    print(f"전체 데이터 수: {total_count:,}개")
    print("\n문서 인용 분포:")
    for length, count in extracted_counts.items():
        print(f"{length}개의 문서를 인용한 샘플: {count}개")
    print("\n검색된 문서 분포:")
    for length, count in search_counts.items():
        print(f"검색 문서로 {length}개가 존재하는 경우: {count}개")

    # 시각화를 위한 subplot 생성
    # figsize(5, 2.5): 적당한 크기의 그래프를 위한 설정
    fig, axes = plt.subplots(1, 2, figsize=(5, 2.5))

    # 두 그래프 사이의 간격 설정 (타이틀이나 레이블이 겹치지 않도록)
    plt.subplots_adjust(wspace=0.6)

    # 왼쪽 그래프: 인용된 문서 수 분포
    extracted_counts.plot(
        kind='bar',
        ax=axes[0],
        xlabel='extracted_ref_len',  # 인용된 문서의 개수
        ylabel='Count',             # 해당 개수의 출현 빈도
        grid=True                   # 격자 표시
    )

    # 오른쪽 그래프: 검색된 문서 수 분포
    search_counts.plot(
        kind='bar',
        ax=axes[1],
        xlabel='search_result_len',  # 검색된 문서의 개수
        ylabel='Count',             # 해당 개수의 출현 빈도
        grid=True                   # 격자 표시
    )

    # 그래프의 레이아웃 자동 조정
    plt.tight_layout()
    plt.show()

 

이 코드는 데이터프레임에서 type이 'mrc_question'인 데이터의 extracted_ref_numbers 열에 들어 있는 리스트 값이 각각 몇 개의 항목(길이)을 가지고 있는지 확인하려는 목적을 가지고 있습니다.

 

이를 통해 각 리스트가 얼마나 많은 참조 번호를 포함하고 있는지 분포를 파악할 수 있습니다. 예를 들어, 길이가 0인 리스트(참조 번호가 없는 경우), 1인 리스트(참조 번호가 1개인 경우), 2인 리스트(참조 번호가 2개인 경우) 등의 개수를 계산하여 데이터의 특성을 이해하는 데 도움을 줄 수 있습니다.

 

mrc_question 타입의 데이터는 대부분 참조 번호가 하나라는 것을 의미합니다. 데이터의 extracted_ref_numbers 열은 참조 번호를 리스트 형태로 저장하고, 이 리스트의 길이가 참조 번호의 개수를 나타냅니다.

 

plot_lengths_by_type(df, 'mrc_question')
타입: mrc_question
전체 데이터 수: 491개

문서 인용 분포:
1개의 문서를 인용한 샘플: 439개
2개의 문서를 인용한 샘플: 44개
3개의 문서를 인용한 샘플: 7개
4개의 문서를 인용한 샘플: 1개

검색된 문서 분포:
검색 문서로 5개가 존재하는 경우: 491개

 

결과를 보면, 리스트 길이가 1인 데이터가 439개로 가장 많습니다. 이는 대부분의 데이터가 하나의 문서만 참조하고 있다는 뜻입니다. 리스트 길이가 2인 데이터는 44개로 두 개의 문서를 참조하는 경우가 그다음으로 많습니다. 리스트 길이가 3인 데이터는 7개, 길이가 4인 데이터는 1개로 여러 문서를 참조하는 데이터는 매우 드물다는 것을 보여줍니다.

 

결론적으로, mrc_question 타입의 데이터는 대부분 단일 문서를 참조하고 있으며, 다수의 문서를 참조하는 경우는 거의 없음을 알 수 있습니다. 이는 데이터 분석이나 추가 처리를 고려할 때 유용한 정보입니다.

 

2. mrc_question_with_1_to_4_negative: 지엽적인 질문 + 검색 결과는 1~4개 사이

plot_lengths_by_type(df, 'mrc_question_with_1_to_4_negative')
타입: mrc_question_with_1_to_4_negative
전체 데이터 수: 296개

문서 인용 분포:
1개의 문서를 인용한 샘플: 282개
2개의 문서를 인용한 샘플: 12개
3개의 문서를 인용한 샘플: 1개
4개의 문서를 인용한 샘플: 1개

검색된 문서 분포:
검색 문서로 1개가 존재하는 경우: 80개
검색 문서로 2개가 존재하는 경우: 75개
검색 문서로 3개가 존재하는 경우: 59개
검색 문서로 4개가 존재하는 경우: 82개

 

출력된 결과를 보면 데이터의 유형인 mrc_question_with_1_to_4_negative의 경우, 대부분의 데이터에 해당하는 282개의 데이터가 답변 시 1개의 문서를 인용하는 데이터입니다. 이는 해당 유형의 데이터가 질문이 매우 지엽적인 관계로 답변 시 다수의 문서를 인용하는 경우가 극히 드물다는 것을 보여줍니다.

 

또한 이전에 소개한 데이터 유형 mrc_question에서는 검색 문서의 수가 전부 5개로 동일하였던 것과는 달리 mrc_question_with_1_to_4_negative의 경우, 검색 문서가 1개, 2개, 3개, 4개인 경우가 균일하게 분포된 것을 확인할 수 있습니다.

3. synthetic_question: 넓은 질문 + 검색 결과는 5개로 고정

질문이 넓기 때문에 일반적으로 다수의 문서를 인용해서 답변하는 경향이 있는 데이터입니다.

print('데이터의 유형:', df['type'].loc[787])
print('질문:', df['question'].loc[787])
print('답변:', df['answer'].loc[787])
print('답변에서 인용한 문서:', df['extracted_ref_numbers'].loc[787])
데이터의 유형: synthetic_question
질문: 한국전력 본사 부지 매각이 서울 강남 지역에 미칠 영향은 무엇인가요?
답변: 한국전력 본사 부지 매각이 서울 강남 지역에 미칠 영향은 여러 가지로 분석될 수 있습니다.

첫째, 한국전력 본사 부지는 서울 강남권의 마지막 대규모 개발 부지 중 하나로, 매각이 성사되면 대규모 개발 프로젝트가 진행될 가능성이 큽니다. 이는 강남 지역의 부동산 시장에 큰 영향을 미칠 수 있습니다. 예를 들어, 삼성전자와 현대자동차 등 대기업들이 이 부지에 관심을 보이고 있으며, 이들이 부지를 매입해 고층 빌딩이나 연구개발(R&D) 센터, 본사 등을 건설할 경우 강남 지역의 상업 및 업무 환경이 크게 변화할 수 있습니다 [[ref1]], [[ref3]], [[ref4]].

둘째, 부지 매각 후 개발이 진행되면 강남 지역의 부동산 가치가 상승할 가능성이 있습니다. 특히, 서울시가 이 부지를 일반상업지역으로 용도 변경할 계획이 있어, 용적률이 높아지면 더 많은 건물이 들어설 수 있게 됩니다. 이는 강남 지역의 상업적 가치를 더욱 높일 수 있습니다 [[ref4]].

셋째, 한국전력 본사 부지에는 지하 변전소가 있어, 이를 처리하는 문제도 중요한 변수로 작용할 것입니다. 변전소를 이전하거나 지하 더 깊은 곳으로 옮기는 등의 작업이 필요할 수 있으며, 이는 개발 비용에 반영될 것입니다. 이러한 기술적 문제들이 해결되면 개발 속도가 빨라질 수 있습니다 [[ref3]].

넷째, 부지 매각 방식이 공개 경쟁입찰로 결정됨에 따라, 매각 대금이 최대한 높아질 가능성이 있습니다. 이는 한국전력의 재무 상황 개선에도 긍정적인 영향을 미칠 수 있습니다 [[ref4]].

이와 같이 한국전력 본사 부지 매각은 강남 지역의 부동산 시장, 상업 환경, 그리고 한국전력의 재무 상황 등에 다양한 영향을 미칠 것으로 예상됩니다.
답변에서 인용한 문서: [1 3 4]
 
plot_lengths_by_type(df, 'synthetic_question')
 
타입: synthetic_question
전체 데이터 수: 497개

문서 인용 분포:
1개의 문서를 인용한 샘플: 157개
2개의 문서를 인용한 샘플: 196개
3개의 문서를 인용한 샘플: 102개
4개의 문서를 인용한 샘플: 35개
5개의 문서를 인용한 샘플: 7개

검색된 문서 분포:
검색 문서로 5개가 존재하는 경우: 497개

 

이 결과는 데이터 타입이 synthetic_question인 데이터에서 extracted_ref_numbers 열의 리스트 길이별 분포를 보여줍니다.

 

리스트 길이가 2인 데이터가 196개로 가장 많습니다. 이는 대부분의 synthetic_question 데이터가 두 개의 문서를 참조하고 있음을 의미합니다. 리스트 길이가 1인 데이터가 157개로 그다음으로 많으며, 단일 문서를 참조하는 경우를 나타냅니다. 리스트 길이가 3인 데이터는 102개로, 세 개의 문서를 참조하는 경우도 상당히 존재합니다.

 

리스트 길이가 4인 데이터는 35개, 길이가 5인 데이터는 7개로, 네 개 이상의 문서를 참조하는 경우는 상대적으로 적습니다.

 

결론적으로, synthetic_question 타입 데이터는 주로 두 개 이상의 문서를 참조하며, 특히 두 개의 문서를 참조하는 경우가 가장 일반적입니다.

 

4. paraphrased_question: 질문의 형태가 명사구. 검색 결과는 5개로 고정.

print('데이터의 유형:', df['type'].loc[1285])
print('질문:', df['question'].loc[1285])
데이터의 유형: paraphrased_question
질문: 송파구청장이 사시에 합격한 연도
 
 
plot_lengths_by_type(df, 'paraphrased_question')
타입: paraphrased_question
전체 데이터 수: 196개

문서 인용 분포:
1개의 문서를 인용한 샘플: 177개
2개의 문서를 인용한 샘플: 13개
3개의 문서를 인용한 샘플: 4개
4개의 문서를 인용한 샘플: 2개

검색된 문서 분포:
검색 문서로 5개가 존재하는 경우: 196개

 

paraphrased_question 유형의 데이터는 기본적으로 질문이 명사구라는 점만 제외하면 mrc_question 유형의 데이터와 동일한 성격을 가집니다. 지엽적인 질문이기때문에 대부분의 데이터가 1개의 문서만 인용하는 경향을 갖고 있으며, 

 

paraphrased_question 유형의 데이터는 mrc_question 유형의 데이터와 동일하게 검색 결과는 모든 데이터가 5개로 동일합니다.

5. no_answer: 검색 결과에 질문에 대한 답이 존재하지 않음. 검색 결과는 5개로 고정.

print('데이터의 유형:', df['type'].loc[1480])
print('질문:', df['question'].loc[1480])
print('답변:', df['answer'].loc[1480])
print('답변에서 인용한 문서:', df['extracted_ref_numbers'].loc[1480])
데이터의 유형: no_answer
질문: 원종 설립 당시 일본 정부의 반응은 어떠했나요?
답변: 검색 결과에는 원종 설립 당시 일본 정부의 반응을 찾을 수 없습니다.
답변에서 인용한 문서: []
 
plot_lengths_by_type(df, 'no_answer')
타입: no_answer
전체 데이터 수: 404개

문서 인용 분포:
0개의 문서를 인용한 샘플: 404개

검색된 문서 분포:
검색 문서로 5개가 존재하는 경우: 404개

 

no_answer 유형의 데이터는 검색 결과는 전부 5개이며 질문에 대한 답이 존재하는 경우가 없는 유형이므로 모든 데이터가 0개의 문서를 인용. 즉, 모든 데이터가 단 1개의 문서도 인용하지 않는 데이터입니다.

728x90

'AI' 카테고리의 다른 글

여러 문서에서 찾아서 답변하는 챗봇 만들기  (0) 2025.04.08
LoRA Tuning  (0) 2025.04.08
Fine-tuning For RAG  (0) 2025.04.04
MultipleNegativesRankingLoss를 활용한 임베딩 파인 튜닝  (0) 2025.04.04
RAG 실습 이후 + LLM 추천  (0) 2025.04.04