일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- airflow
- SparkSQL
- DataFrame Spark
- 빅쿼리 튜닝
- LLM
- 언어모델
- 시각화
- docker
- 도커exec
- 데이터엔지니어링
- Big Query
- spark explode
- BigQuery
- 프로그래머스 파이썬
- pyspark오류
- ifkakao2020
- 데이터 시각화
- Docker error
- 로컬 pyspark
- PySpark
- 태블로
- 도커오류
- 도커
- dataframe
- 코테
- tableau
- sparkdf
- spark df
- spark #스파크
- 빅쿼리
- Today
- Total
SOGM'S Data
[PaperReview]SimCSE: Simple Contrastive Learning of Sentence Embeddings (1) (작성중) 본문
[PaperReview]SimCSE: Simple Contrastive Learning of Sentence Embeddings (1) (작성중)
왈왈가부 2024. 1. 8. 09:06def train_dataloader(train_dataset):
train_sampler = RandomSampler(train_dataset)
model_collate_fn = functools.partial(
process_batch,
tokenizer=tokenizer,
max_len=args.max_seq_length
)
train_dataloader = DataLoader(train_dataset,
batch_size=args.batch_size,
sampler=train_sampler,
collate_fn=model_collate_fn)
return train_dataloader
view raw
논문 리뷰내용은 추가예정
1.논문에서 학습에 구현된 wikiDataset
class wikiDataset(Dataset):
def __init__(self, csv_path, training=True, full=False):
dataset_df = pd.read_csv(csv_path,names=["text"])
dataset_df.dropna(inplace=True)
source_texts = dataset_df["text"].values
target_texts = dataset_df["text"].values
data = list(zip(source_texts,target_texts))
if full:
self.data = data
else:
train_data,val_data = train_test_split(data,test_size=0.15,random_state=42,shuffle=False)
self.data = train_data if training else val_data
def __len__(self):
return len(self.data)
def __getitem__(self,idx):
return self.data[idx]
2.source (anchor)와 target (positive)를 구분하는 작업 추가
def process_batch(txt_list,tokenizer,max_len=args.max_seq_length):
source_ls = [source for source,target in txt_list]
target_ls = [target for source,target in txt_list]
source_tokens = tokenizer(source_ls,truncation=True,padding="max_length",max_length=args.max_seq_length)
target_tokens = tokenizer(target_ls,truncation=True,padding="max_length",max_length=args.max_seq_length)
input_ids = []
attention_mask = []
token_type_ids = []
for i in range(len(source_tokens["input_ids"])):
input_ids.append(source_tokens["input_ids"][i])
input_ids.append(target_tokens["input_ids"][i])
attention_mask.append(source_tokens["attention_mask"][i])
attention_mask.append(target_tokens["attention_mask"][i])
token_type_ids.append(source_tokens["token_type_ids"][i])
token_type_ids.append(target_tokens["token_type_ids"][i])
return torch.tensor(input_ids),torch.tensor(attention_mask),torch.tensor(token_type_ids)
3.데이터 로더
데이터 로더
def train_dataloader(train_dataset):
train_sampler = RandomSampler(train_dataset)
model_collate_fn = functools.partial(
process_batch,
tokenizer=tokenizer,
max_len=args.max_seq_length
)
train_dataloader = DataLoader(train_dataset,
batch_size=args.batch_size,
sampler=train_sampler,
collate_fn=model_collate_fn)
return train_dataloader
view raw
4.옵티마이저 정의
아담 사용, warm up 으로 학습속도 초반에 빠르게 해줌
param_optimizer = list(model.named_parameters())
no_decay = ['bias','LayerNorm.weight']
optimizer_grouped_parameters = [
{'params': [p for n, p in param_optimizer if not any(nd in n for nd in no_decay)], 'weight_decay': args.weight_decay},
{'params': [p for n, p in param_optimizer if any(nd in n for nd in no_decay)], 'weight_decay': 0.0}
]
warmup_steps = int(args.warmup_proportion * num_train_optimization_steps)
optimizer = AdamW(optimizer_grouped_parameters,lr=args.learning_rate,eps=args.adam_epsilon)
scheduler = get_linear_schedule_with_warmup(
optimizer,
num_warmup_steps=warmup_steps,
num_training_steps=num_train_optimization_steps)
+) 위 코드 부연 설명
위의 코드는 PyTorch에서 Transformers 라이브러리를 사용하여 모델 파라미터를 최적화하기 위한 Optimizer와 Scheduler를 설정하는 부분입니다. 코드를 간략히 설명
1. param_optimizer = list(model.named_parameters()): 모델의 모든 파라미터를 가져와서 (파라미터 이름, 파라미터 값) 쌍의 리스트로 저장
2. no_decay = ['bias', 'LayerNorm.weight']: 가중치 decay 지정 , 여기서는 바이어스(bias)와 LayerNormalization의 가중치(weight)에 대해 가중치 decay를 적용하지 않을 것으로 설정
3. optimizer_grouped_parameters: Optimizer에 전달할 파라미터 그룹 설정, 두 개의 그룹으로 나누어집니다. 첫 번째 그룹은 'no_decay'에 포함된 파라미터를 제외한 모든 파라미터에 대해 가중치 decay 를 적용, 두 번째 그룹은 'no_decay'에 해당하는 파라미터에 대해 가중치 decay 적용 x
4. warmup_steps = int(args.warmup_proportion * num_train_optimization_steps): 학습률 스케줄러에서의 웜업 단계를 설정합니다.
5. scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps=warmup_steps, num_training_steps=num_train_optimization_steps): 웜업 및 학습률 감소 스케줄러를 설정. 초기에 빠르게 학습하는데 도움이 됨. transformer 모듈에 있음.
5. Bert, Roberta 모델 init
class BertForCL(BertPreTrainedModel):
_keys_to_ignore_on_load_missing = [r"position_ids"]
def __init__(self, config):
super().__init__(config)
#self.model_args = model_kargs["model_args"]
self.bert = BertModel(config)
cl_init(self, config)
def forward(self,
input_ids=None,
attention_mask=None,
token_type_ids=None,
position_ids=None,
head_mask=None,
inputs_embeds=None,
labels=None,
output_attentions=None,
output_hidden_states=None,
return_dict=None,
sent_emb=False,
):
if sent_emb:
return sentemb_forward(self, self.bert,
input_ids=input_ids,
attention_mask=attention_mask,
token_type_ids=token_type_ids,
position_ids=position_ids,
head_mask=head_mask,
inputs_embeds=inputs_embeds,
labels=labels,
output_attentions=output_attentions,
output_hidden_states=output_hidden_states,
return_dict=return_dict,
)
else:
return cl_forward(self, self.bert,
input_ids=input_ids,
attention_mask=attention_mask,
token_type_ids=token_type_ids,
position_ids=position_ids,
head_mask=head_mask,
inputs_embeds=inputs_embeds,
labels=labels,
output_attentions=output_attentions,
output_hidden_states=output_hidden_states,
return_dict=return_dict,
)
cl_init 함수에 대한 간단한 구조 : https://gist.github.com/bhuvanakundumani/dc933afece8dcebdcf841a73b84666e1
6. encoder (embedding하기)
# Get raw embeddings
outputs = encoder(
input_ids,
attention_mask=attention_mask,
token_type_ids=token_type_ids,
position_ids=position_ids,
head_mask=head_mask,
inputs_embeds=inputs_embeds,
output_attentions=output_attentions,
output_hidden_states=False if args.pooler_type == 'cls' else True,
return_dict=True,
)
# Pooling
pooler_output = cls.pooler(attention_mask, outputs)
pooler_output = pooler_output.view((batch_size, args.num_sent, pooler_output.size(-1))) # (bs, num_sent, hidden)
# If using "cls", we add an extra MLP layer
# (same as BERT's original implementation) over the representation.
if cls.pooler_type == "cls":
pooler_output = cls.mlp(pooler_output)
# Separate representation
z1, z2 = pooler_output[:,0], pooler_output[:,1]
- cls token output을 사용할거면 MLP Layer를 한 번 통과시킴.
- last_hidden[:, 0] as the pooler_output with a shape torch.Size([16, 768]) . (batch_size, model_dim)
- input_ids[0] has the ids for source texts and input_ids[1] has the ids for target texts.
-pooler_output = pooler_output.view((batch_size, args.num_sent, pooler_output.size(-1))) 해당 코드로인해The pooler_output with the shape torch.Size([16, 768]) is reshaped to torch.Size([8, 2, 768])
- 즉 , [8, 0, 768] are the outputs for the source texts , [8, 1, 768] are the outputs for the target texts.
- 또한 아래 코드로 인해 Source 와 target 을 구분하게 된다.
z1, z2 = pooler_output[:,0], pooler_output[:,1]
* 참고 : bert의 Output은 아래 3가지다 .
(last_hidden_state,pooler_output,hidden_states) = model(token_ids, attention_mask = attention_mask)
last_hidden_state : 최종 인코더 계층의 모든 output
*last_hidden_state[:,0,:] 하면 cls 토큰만을 선택할 수 있으나, 바로 아래 소개하는 pooler_output과는 완전히 같지않음.
pooler_output : 최종 인코더 계층의[CLS] 토큰 표현. 선형 및 tanh 함수를 거쳐 계산
hidden_states : 모든 인코더 계층에서 얻은 모든 토큰의 표현.
7. Loss function
7. Loss function
cos_sim = cls.sim(z1.unsqueeze(1), z2.unsqueeze(0))
labels = torch.arange(cos_sim.size(0)).long().to(cls.device)
loss_fct = nn.CrossEntropyLoss()
loss = loss_fct(cos_sim, labels)
- cosine 유사도를 구하기위한 unsqueeze를 서로 반대로 해주는 모습.
참고 출처 :
1.https://github.com/princeton-nlp/SimCSE/blob/main/simcse/models.py
'About Data > AI Paper' 카테고리의 다른 글
[base] 내가 개인적으로 정리하는 중요 기초 논문 리스트 (0) | 2023.05.01 |
---|---|
1) [논문리뷰] Collaborative Filtering for Implicit Feedback Datasets, IEEE (4) | 2020.11.02 |