공부 정리 블로그
[학습 데이터 생성]hiiamsid/sentence_similarity_spanish_es 본문
import pandas as pd
from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch
from itertools import combinations
# 1. Load the dataset
file_path = '/mnt/data/final_2023_grouped_categorized_file.xlsx'
data = pd.read_excel(file_path)
# 2. Extract necessary columns
columns_of_interest = ['ActividadEconomicaDesc', 'RutPostulante', 'criteria', 'RespuestaTexto']
data = data[columns_of_interest]
# 3. Group by 'ActividadEconomicaDesc'
grouped_data = data.groupby('ActividadEconomicaDesc')
# Load the model and tokenizer for similarity calculation
similarity_model_name = "hiiamsid/sentence_similarity_spanish_es"
similarity_tokenizer = AutoTokenizer.from_pretrained(similarity_model_name)
similarity_model = AutoModelForSequenceClassification.from_pretrained(similarity_model_name)
# Load the tokenizer for fine-tuning data (preprocessing purposes)
fine_tuning_model_name = "Alibaba-NLP/gte-multilingual-base"
fine_tuning_tokenizer = AutoTokenizer.from_pretrained(fine_tuning_model_name)
# Function to calculate similarity using sliding window
def calculate_similarity_sliding_window(text1, text2, max_length=512, stride=256):
# Tokenize the full texts without truncation
inputs1 = similarity_tokenizer(text1, truncation=False, return_tensors='pt')
inputs2 = similarity_tokenizer(text2, truncation=False, return_tensors='pt')
tokens1 = inputs1['input_ids'][0]
tokens2 = inputs2['input_ids'][0]
max_similarity = 0
for start1 in range(0, len(tokens1), stride):
end1 = min(start1 + max_length, len(tokens1))
chunk1 = tokens1[start1:end1]
for start2 in range(0, len(tokens2), stride):
end2 = min(start2 + max_length, len(tokens2))
chunk2 = tokens2[start2:end2]
# Ensure chunks have the same length by padding shorter chunk
if len(chunk1) < max_length:
padding = torch.full((max_length - len(chunk1),), similarity_tokenizer.pad_token_id, dtype=torch.long)
chunk1 = torch.cat([chunk1, padding])
if len(chunk2) < max_length:
padding = torch.full((max_length - len(chunk2),), similarity_tokenizer.pad_token_id, dtype=torch.long)
chunk2 = torch.cat([chunk2, padding])
# Prepare inputs for the model
inputs = {
'input_ids': torch.stack([chunk1, chunk2]),
'attention_mask': torch.stack([
torch.ones_like(chunk1),
torch.ones_like(chunk2)
])
}
# Compute similarity score
with torch.no_grad():
outputs = similarity_model(**inputs)
scores = torch.nn.functional.softmax(outputs.logits, dim=1)
max_similarity = max(max_similarity, scores[0][1].item())
return max_similarity
# 4. Create fine-tuning data
fine_tuning_data = []
for actividad, group in grouped_data:
# Group by 'criteria' within the same 'ActividadEconomicaDesc'
criteria_grouped = group.groupby('criteria')
for criteria, criteria_group in criteria_grouped:
entries = criteria_group.to_dict('records')
for pair in combinations(entries, 2): # All combinations of pairs within the criteria group
text1 = pair[0]['RespuestaTexto']
text2 = pair[1]['RespuestaTexto']
rut1 = pair[0]['RutPostulante']
rut2 = pair[1]['RutPostulante']
# Handle empty or None texts
if not text1 or not text2:
continue
# Calculate similarity with sliding window
similarity = calculate_similarity_sliding_window(text1, text2)
# Preprocess texts for fine-tuning
preprocessed_text1 = fine_tuning_tokenizer(text1, max_length=512, truncation=True, padding='max_length')
preprocessed_text2 = fine_tuning_tokenizer(text2, max_length=512, truncation=True, padding='max_length')
fine_tuning_data.append({
'ActividadEconomicaDesc': actividad,
'criteria': criteria,
'RutPostulante_1': rut1,
'RutPostulante_2': rut2,
'Text1': text1,
'Text2': text2,
'Similarity': similarity,
'EncodedText1': preprocessed_text1,
'EncodedText2': preprocessed_text2
})
# Convert results to DataFrame and save
fine_tuning_data_df = pd.DataFrame(fine_tuning_data)
output_path = '/mnt/data/fine_tuning_data_with_similarity.xlsx'
fine_tuning_data_df.to_excel(output_path, index=False)
print(f"Fine-tuning data with similarity saved to {output_path}")
# Load the tokenizer for fine-tuning data (preprocessing purposes)
fine_tuning_model_name = "Alibaba-NLP/gte-multilingual-base"
fine_tuning_tokenizer = AutoTokenizer.from_pretrained(fine_tuning_model_name)
이건 왜하는거야?
이 부분은 Alibaba-NLP/gte-multilingual-base 모델을 추후 파인튜닝하기 위해 데이터 전처리를 준비하는 과정입니다. 구체적으로 왜 필요한지 설명하겠습니다:
1. 목적
hiiamsid/sentence_similarity_spanish_es 모델은 코사인 유사도를 계산하기 위해 사용됩니다. 하지만, 최종적으로 파인튜닝할 모델은 Alibaba-NLP/gte-multilingual-base입니다. 따라서, 학습 데이터는 gte-multilingual-base에 맞는 형식으로 전처리되어야 합니다.
2. 왜 전처리 과정이 필요한가?
Alibaba-NLP/gte-multilingual-base 모델은 입력 데이터를 처리할 때 토큰화를 통해 모델에 전달할 수 있는 형식(숫자 ID, 패딩 등)으로 변환해야 합니다. 이를 위해 AutoTokenizer를 사용하며, 여기서 토큰화를 수행합니다:
- 텍스트를 토큰으로 분할
- 최대 토큰 길이를 설정 (512로 제한)
- 패딩 및 트렁케이션 (길이를 맞추기 위해 추가 작업)
3. 결과
fine_tuning_tokenizer로 전처리된 텍스트(EncodedText1, EncodedText2)는 숫자 ID, 어텐션 마스크 등을 포함하는 딕셔너리 형태로 저장됩니다. 이렇게 생성된 데이터는 Alibaba-NLP/gte-multilingual-base 모델에서 바로 학습에 사용할 수 있습니다.
요약
fine_tuning_tokenizer를 사용하는 이유는 최종 파인튜닝 모델(gte-multilingual-base)에 적합한 데이터 형식을 미리 준비하기 위함입니다. 이를 통해 hiiamsid/sentence_similarity_spanish_es로 계산한 유사도 데이터를 효율적으로 활용할 수 있습니다.
최종으로 생성되는 데이터는 fine_tuning_data_with_similarity.xlsx 파일에 저장되며, 데이터 형식은 아래와 같습니다. 각 컬럼의 설명을 포함합니다.
최종 데이터 형식
컬럼 이름 설명
ActividadEconomicaDesc | 동일한 RutPostulante를 비교하는 기준이 되는 ActividadEconomicaDesc 값. |
criteria | 비교가 이루어진 동일한 기준 (criteria) 값. |
RutPostulante_1 | 비교 대상 1의 RutPostulante (식별자). |
RutPostulante_2 | 비교 대상 2의 RutPostulante (식별자). |
Text1 | RutPostulante_1의 RespuestaTexto (비교 대상 텍스트). |
Text2 | RutPostulante_2의 RespuestaTexto (비교 대상 텍스트). |
Similarity | hiiamsid/sentence_similarity_spanish_es 모델로 계산된 두 텍스트의 코사인 유사도 (0~1 사이 값). |
EncodedText1 | Alibaba-NLP/gte-multilingual-base 모델 학습을 위해 전처리된 Text1 데이터 (토큰화 포함). |
EncodedText2 | Alibaba-NLP/gte-multilingual-base 모델 학습을 위해 전처리된 Text2 데이터 (토큰화 포함). |
주요 데이터 예시
ActividadEconomicaDesc criteria RutPostulante_1 RutPostulante_2 Text1 Text2 Similarity EncodedText1 EncodedText2
Comercio | A1 | 12345678-9 | 98765432-1 | Texto de prueba 1 | Texto de prueba 2 | 0.85 | {tokenized data...} | {tokenized data...} |
EncodedText1와 EncodedText2의 구조
이 필드들은 전처리된 텍스트 데이터로, JSON 형태로 저장됩니다. 각각의 필드는 다음을 포함합니다:
- input_ids: 텍스트를 숫자 토큰 ID로 변환한 값.
- attention_mask: 패딩된 부분을 구분하기 위한 마스크 값.
- (추가적으로) 모델에 따라 token_type_ids 등이 포함될 수 있습니다.
예시:
{
"input_ids": [101, 1045, 2572, 1037, 2326, 102],
"attention_mask": [1, 1, 1, 1, 1, 1]
}
이 데이터는 Hugging Face 모델(Alibaba-NLP/gte-multilingual-base)에서 바로 학습에 사용할 수 있습니다.
요약
- 파일은 학습 및 유사도 정보를 포함한 테이블 형식으로 저장됩니다.
- Similarity는 유사도 점수로, hiiamsid/sentence_similarity_spanish_es 모델 결과입니다.
- EncodedText1와 EncodedText2는 gte-multilingual-base 학습용 입력 데이터입니다.
에러 모음집
1.
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-11-86db20f14877> in <cell line: 0>()
19
20 # Calculate similarity with sliding window
---> 21 similarity = calculate_similarity_sliding_window(text1, text2)
22
23 # Preprocess texts for fine-tuning
<ipython-input-9-a388a9b6a1ff> in calculate_similarity_sliding_window(text1, text2, max_length, stride)
19 if len(chunk1) > 0 and len(chunk2) > 0:
20 inputs = {
---> 21 'input_ids': torch.cat([chunk1.unsqueeze(0), chunk2.unsqueeze(0)], dim=0),
22 'attention_mask': torch.cat([
23 torch.ones_like(chunk1).unsqueeze(0),
RuntimeError: Sizes of tensors must match except in dimension 0. Expected size 491 but got size 512 for tensor number 1 in the list.
에러 메시지를 보면, torch.cat 함수에서 두 텐서의 크기가 일치하지 않아 발생한 문제입니다. 슬라이딩 윈도우로 자른 텍스트 청크 중 하나는 길이가 491이고, 다른 하나는 길이가 정확히 512여서 크기가 달라 오류가 발생했습니다.
이 문제를 해결하려면, 슬라이딩 윈도우로 나눠진 텍스트 청크의 길이를 정확히 맞추거나, 모델 입력 전에 길이를 강제로 일치시키는 처리가 필요합니다.
def calculate_similarity_sliding_window(text1, text2, max_length=512, stride=256):
# Tokenize the full texts without truncation
inputs1 = similarity_tokenizer(text1, truncation=False, return_tensors='pt')
inputs2 = similarity_tokenizer(text2, truncation=False, return_tensors='pt')
tokens1 = inputs1['input_ids'][0]
tokens2 = inputs2['input_ids'][0]
max_similarity = 0
for start1 in range(0, len(tokens1), stride):
end1 = min(start1 + max_length, len(tokens1))
chunk1 = tokens1[start1:end1]
for start2 in range(0, len(tokens2), stride):
end2 = min(start2 + max_length, len(tokens2))
chunk2 = tokens2[start2:end2]
# Ensure chunks have the same length by padding shorter chunk
if len(chunk1) < max_length:
padding = torch.full((max_length - len(chunk1),), tokenizer.pad_token_id, dtype=torch.long)
chunk1 = torch.cat([chunk1, padding])
if len(chunk2) < max_length:
padding = torch.full((max_length - len(chunk2),), tokenizer.pad_token_id, dtype=torch.long)
chunk2 = torch.cat([chunk2, padding])
# Prepare inputs for the model
inputs = {
'input_ids': torch.stack([chunk1, chunk2]),
'attention_mask': torch.stack([
torch.ones_like(chunk1),
torch.ones_like(chunk2)
])
}
# Compute similarity score
with torch.no_grad():
outputs = similarity_model(**inputs)
scores = torch.nn.functional.softmax(outputs.logits, dim=1)
max_similarity = max(max_similarity, scores[0][1].item())
return max_similarity
근데 역시나 파일이 너무 커서 중간에 뻗어버림 ㅠ
'proyector en Chile' 카테고리의 다른 글
학습 데이터를 만드는데.. 또 머리 아픔 (0) | 2025.02.07 |
---|---|
0205 hiiamsid/sentence_similarity_spanish_es Alibaba-NLP/gte-multilingual-base 비교 (0) | 2025.02.06 |
0129 진행상황 (0) | 2025.01.30 |
유사도 측정 알고리즘 정교화 방법 (0) | 2025.01.27 |
Box Plot 해석 (0) | 2025.01.24 |