두 가지 실습을 진행
- 실습 1. DPO 데이터 전처리
- 실습 2. DPO 데이터 생성하기
[실습 1. DPO 데이터 전처리]
Contents
- Import Packages
- Load Datasets
- EDA
- 중복 제거 (Deduplicate)
- 예시 확인
1. Import Packages
from datasets import load_dataset
import pandas as pd
from datasketch import MinHash, MinHashLSH
from tqdm import tqdm
import re
2. Load Datasets
DPO를 위한 dataset을 load한다.
- DPO 데이터셋: 선호 (1) & 비선호 (0) 답변 존재
총 7576개의 데이터가 존재한다.
data= load_dataset('DopeorNope/New_DPO_dataset')
train_df= pd.DataFrame(data['train'])
print(len(train_df))
7576
3. EDA
데이터셋이 어떻게 생겼는지 확인하기!
train_df.head()
일부 데이터셋의 경우, 중복된 질문이 있음을 알 수 있다.
train_df['question'].value_counts()
약 182개의 중복된 데이터셋 (duplicate_questions
)이 존재함을 알 수 있다.
duplicate_questions = train_df['question'][train_df['question'].duplicated(keep=False)]
print(len(duplicate_questions))
182
4. 중복 제거 (Deduplicate)
중복 제거 방법: MinHash LSH.
기준 설정하기!
SIMILARITY_THRESHOLD = 0.8
NUM_PERMS = 256
SHINGLE_SIZE = 5
전처리를 위해 필요한 함수 불러오기
def preprocess(string, maxlen=500):
return ''.join(e for e in string[:maxlen] if e.isalnum()).lower()
def _shingle(string, shingle_size=4):
return {string[i : i + shingle_size] for i in range(len(string) - shingle_size + 1)}
LSH (Locality-Sensitive Hashing)
lsh = MinHashLSH(threshold=SIMILARITY_THRESHOLD, num_perm=NUM_PERMS)
minhashes = {}
for i, doc in tqdm(enumerate(train_df['question'])):
shingles = _shingle(preprocess(doc), shingle_size=SHINGLE_SIZE)
minhash = MinHash(num_perm=NUM_PERMS)
for shingle in shingles:
minhash.update(shingle.encode('utf8'))
lsh.insert(f'doc_{i}', minhash)
minhashes[f'doc_{i}'] = minhash
제거하기
to_remove = set()
for i, minhash in minhashes.items():
dups = lsh.query(minhash)
# 인덱스 추출 및 비교
dups = [int(dup.split('_')[1]) for dup in dups if int(dup.split('_')[1]) > int(i.split('_')[1])]
to_remove.update(dups)
지워야 할 duplicated된 데이터 확인하기
len(to_remove)
387
제거하기
removed_df = train_df.loc[list(to_remove)]
removed_df=removed_df.reset_index(drop=True)
5. 예시 확인하기
question_to_check='발에 물집이 생겼다.'
matched_rows = removed_df[removed_df['question'].str.contains(re.escape(question_to_check), regex=True)]
print(matched_rows)
[실습 2. DPO 데이터 생성하기]
Contents
vllm
패키지 소개- Import Packages
- Load Datasets
- EDA
- 중복 제거 (Deduplicate)
- 예시 확인
1. vllm
패키지 소개
위의 실습에서 사용한 DPO 데이터셋를 얻는 방법은?
( = 선호 (1), 비선호 (0) 답변을 얻는 방법은? )
- 선호 답변: 실제 정답 label을 사용하면 됨
- 비선호 답변: LLM (모델)의 output으로 사용하기
vllm
패키지
- LLM의 고속 추론을 가능하게 하는 오픈소스 라이브러리
- 주로 효율적인 메모리 관리와 병렬 처리 기술을 활용해, 빠르고 확장성 있는 LLM 추론을 제공
from vllm import LLM
llm = LLM(model="meta-llama/Llama-2-7b-chat-hf")
output = llm.generate("Hello, how are you?")
print(output)
2. Import Packages
from datasets import load_dataset
import vllm
from vllm import LLM, SamplingParams
import pandas as pd
from typing import List
from vllm.outputs import RequestOutput
3. Load Datasets
data= load_dataset('DopeorNope/Ko-Optimize_Dataset_train')
df= pd.DataFrame(data['train'])
모델에 넣을 프롬프트 생성
prompts = list(map(lambda x:
f"아래는 문제를 설명하는 지시사항과, 구체적인 답변 방식을 요구하는 입력이 함께 있는 문장입니다. 이 요청에 대해 적절하게 답변해주세요.\n\n###지시사항:\n{x['instruction']}\n\n###입력:\n{x['input']}\n\n###답변:\n"
if x['input'] else
f"아래는 문제를 설명하는 지시사항입니다. 이 요청에 대해 적절하게 답변해주세요.\n\n###지시사항:\n{x['instruction']}\n\n###답변:\n",
df.to_dict('records')))
4. Load Model
LLama3 모델을 불러온다.
base_model= 'DopeorNope/Single_GPU_Llama3-8B'
gpu_num = 4
max_token = 4096
model = LLM(model=base_model, tensor_parallel_size=gpu_num, max_model_len=max_token, gpu_memory_utilization=0.6)
5. 생성 (Sampling)
Hyperparameters
sampling_params = SamplingParams(top_k=5, top_p=1, max_tokens=max_token,
stop=['<|endoftext|>', '</s>', '<|im_end|>','<|end_of_text|>'])
생성하기
outputs: List[RequestOutput] = model.generate(prompts, sampling_params)
예시 확인
outputs[0].prompt
'아래는 문제를 설명하는 지시사항입니다. 이 요청에 대해 적절하게 답변해주세요.\n\n###지시사항:\nk > 0,$ 의 배율로 팽창을 나타내는 행렬을 $\\mathbf{D}$ 라 하고, 원점을 중심으로 시계 반대 방향으로 $\\theta$ 의 각도로 회전하는 것을 나타내는 행렬을 $\\mathbf{R}$ 이라 합니다. 다음과 같은 경우\n\\[\\mathbf{R} \\mathbf{D} = \\begin{pmatrix} 8 & -4 \\\\ 4 & 8 \\end{pmatrix},\\]라면 $\\tan \\theta.$를 구합니다.\n\n###답변:\n'
최종 생성 결과 정리
extracted_prompts = list(map(lambda x: x.prompt, outputs))
extracted_generated_texts = list(map(lambda x: x.outputs[0].text, outputs))
Reference
https://fastcampus.co.kr/data_online_gpu