Preview:
Machine Learning vs Deep Learning
๋จธ์ ๋ฌ๋: ์ธ๊ณต์ง๋ฅ์ ํ ๋ถ์ผ๋ก data์ Pattern์ ํ์ต. (์ด๋, ๋น๊ต์ ์ ์ ์์ ๊ตฌ์กฐํ๋ data๋ก๋ ์๋๊ฐ๋ฅ)
๋ฅ๋ฌ๋: ๋จธ์ ๋ฌ๋์ ํ ๋ถ์ผ๋ก ๋ณต์กํ ๊ตฌ์กฐ, ๋ง์ ๊ณ์ฐ๋ฆฌ์์ค ๋ฐ ๋ฐ์ดํฐ๋ฅผ ํ์๋ก ํจ.
Transformer(Attention is All You Need-2017)
Transformer ๋ชจ๋ธ์ ํต์ฌ:
โ input sequence ๋ณ๋ ฌ์ฒ๋ฆฌ
โ Only Use Attention Mechanism (Self Attention)
โ ์์ฐจ์ ์ฒ๋ฆฌ, ๋ฐ๋ณต์ฐ๊ฒฐ, ์ฌ๊ท ๋ชจ๋ ์ฌ์ฉโ
Transformer ๋ชจ๋ธ๊ตฌ์กฐ:
โ Embedding: token2dense-vector (์ด๋, ๋จ์ด๊ฐ์ ์๋ฏธ์ ์ ์ฌ์ฑ์ ๋ณด์กดํ๋ ๋ฐฉํฅ์ผ๋ก ๋ชจ๋ธ์ด ํ์ต๋๋ค.)
โ Positional Encoding: input sequence์ token์์น์ ๋ณด๋ฅผ ์ถ๊ฐ๋ก ์ ๊ณต
โ Encoder&Decoder: Embedding+PE๋ผ๋ ํ์ต๋ vector๋ฅผ Input์ผ๋ก ๋ฐ์(๋ฒกํฐ ๊ฐ์ Pretrained weight or ํ์ต๊ณผ์ ์ค ์ต์ ํ๋จ.)
- MHA & FFN: token๊ฐ ๊ด๊ณ๋ฅผ ํ์ต, FFN์ผ๋ก ๊ฐ ๋จ์ด์ ํน์ง๋ฒกํฐ ์ถ์ถ (์ด๋, ๊ฐ Head๊ฐ์ ์๋ก ๋ค๋ฅธ ๊ฐ์ค์น๋ฅผ ๊ฐ์ ธ input sequence์ ๋ค์ํ ์ธก๋ฉด ํฌ์ฐฉ๊ฐ๋ฅ.)
- QKV: Query(ํ์ฌ์์น์์ ๊ด์ฌ์๋๋ถ๋ถ์ ๋ฒกํฐ), Key(๊ฐ ์์น์ ๋ํ ์ ๋ณด์ ๋ฒกํฐ), Value(๊ฐ ์์น์ ๋ํ ๊ฐ ๋ฒกํฐ)
ex) The student studies at the home
query: student
--> Q: student์ ๋ณด๋ฅผ ์ป๊ธฐ ์ํ ๋ฒกํฐ๊ฐ
--> K: The, studies, at, the, home ๋ฒกํฐ๊ฐ
--> V: ๋ฌธ๋งฅ, ์๋ฏธ๋ฑ์ ๊ด๋ จ์ ๋ณด์ ๋ํ ๋ฒกํฐ๊ฐ
--> 3-Head๋ผ๋ฉด: ๊ฐ ํค๋๋ณ ์ญํ ์ด Syntax, Semantics, Pragmatics ๋ฑ์ ์ง์คํ ์ ์๋ค๋ ๊ฒ.
Huggingface Transformers
Library ์๊ฐ
Tokenizer
๋ณดํต subword๋ก tokenํ(token์ผ๋ก ๋ถํ )ํ๋ ๊ณผ์ ์ ์งํ. ๋ถ์์ ์ผ๋ก "ํ ์คํธ ์ ๊ทํ, ๋ถ์ฉ์ด์ ๊ฑฐ, Padding, Truncation ๋ฑ" ๋ค์ํ ์ ์ฒ๋ฆฌ ๊ธฐ๋ฅ๋ ์ ๊ณตํ๋ค.
Diffusers Library
txt-img์์ฑ๊ด๋ จ ์์ ์ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก Stable Diffusion, DALL-E, LDM ๋ฑ ๋ค์ํ ์์ฑ๋ชจ๋ธ์ ์ง์.
- DDPM, DDIM, LDM๋ฑ ๋ค์ํ Diffusion๊ธฐ๋ฐ ์๊ณ ๋ฆฌ์ฆ ์ ๊ณต
- Batch Inference, ๋ณ๋ ฌ, ํผํฉ์ ๋ฐ๋ํ์ต ๋ฑ ์ง์Accelerate
๋ถ์ฐ์ ๋ต์ ๊ฐ๋จํ ์ถ์ํํด API๋ก ์ ๊ณต, FP16 ๋ฐ BF16๋ฑ์ ๋ฎ์ ํผํฉ์ ๋ฐ๋ํ์ต์ "์๋์ง์"
- ๋ถ์ฐํ์ต ์ง์: Data Parallel, Model Parallel ๋ฑ ์ง์.
- Automatic Mixed Precision์ง์: FP16, FP32 ๋ฑ dataํ์์ ์๋์ผ๋ก ํผํฉ, ๋ฉ๋ชจ๋ฆฌ์ฌ์ฉ๋↓, ์๋↑- Gradient Accumulation: ์ฌ๋ฌ ๋ฏธ๋๋ฐฐ์น์ ๊ทธ๋๋์ธํธ๋ฅผ ๋์ ํ์ฌ ํฐ ๋ฐฐ์น ํจ๊ณผ๋ฅผ ๋ด๋ ๊ธฐ๋ฒ
- Gradient Checkpointing: ์ค๊ฐ activation๊ณ์ฐ์ ์ ์ฅํ๋ ๋์ , ํ์ํ ๋ ์ฌ๊ณ์ฐํ๋ ๋ฐฉ๋ฒ
Model ์ค์
๋ชจ๋ธ ์ค์ ํด๋์ค๋ ๋ชจ๋ธ๊ตฌ์กฐ์ hyperparameter๊ฐ์ "๋์ ๋๋ฆฌ"ํํ๋ก JSONํ์ผ์ ์ ์ฅํ๋ค.
๋ฐ๋ผ์ ๋ชจ๋ธ์ ๋ถ๋ฌ์ค๋ฉด ๋ชจ๋ธ๊ฐ์ค์น์ ํจ๊ป ์ด ๊ฐ์ด ๋ถ๋ฌ์์ง๋ค. (์๋ ์ฌ์ง์ฒ๋ผ)
PretrainedConfig & ModelConfig
๋ง์ฐฌ๊ฐ์ง๋ก ๋ชจ๋ธ๊ตฌ์กฐ, hyperparameter๋ฅผ ์ ์ฅํ๋ ๋์ ๋๋ฆฌ๋ฅผ ํฌํจ
[์์์ธ์ ์ค๋ช ]:
- vocab_size: ๋ชจ๋ธ์ด ์ธ์๊ฐ๋ฅํ ๊ณ ์ ํ ํฐ ์
- output_hidden_states: ๋ชจ๋ธ์ ๋ชจ๋ hidden_state๋ฅผ ์ถ๋ ฅํ ์ง ์ฌ๋ถ
- output_attentions: ๋ชจ๋ธ์ ๋ชจ๋ attention๊ฐ์ ์ถ๋ ฅํ ์ง ์ฌ๋ถ
- return_dict: ๋ชจ๋ธ์ด ์ผ๋ฐ ํํ๋์ , ModelOutput๊ฐ์ฒด๋ฅผ ๋ฐํํ ์ง ๊ฒฐ์ .
๊ฐ ๋ชจ๋ธ ๊ตฌ์กฐ๋ณ PretrainedConfig๋ฅผ ์์๋ฐ์ ์ ์ฉ ๋ชจ๋ธ ์ค์ ํด๋์ค๊ฐ ์ ๊ณต๋๋ค.
(ex. BertConfig, GPT2Config ํน์ ์๋ ์ฌ์ง์ฒ๋ผ...)์ด๋, ์ค์ ๊ฐ์ด ์๋ชป๋๋ฉด ๋ชจ๋ธ์ฑ๋ฅ์ด ํฌ๊ฒ ๋จ์ด์ง ์ ์๊ธฐ์ ๋ณดํต "from_pretrained"๋ฅผ ์ด์ฉํด ๊ฒ์ฆ๋ pretrainedํ์ต์ค์ ๊ฐ์ ๋ถ๋ฌ์จ๋ค.
PreTrainedTokenizer & ModelTokenizer & PretrainedTokenizerFast
[์์์ธ์ ์ค๋ช ]:
- max_model_input_sizes: ๋ชจ๋ธ์ ์ต๋์ ๋ ฅ๊ธธ์ด
- model_max_length: tokenizer๊ฐ ์ฌ์ฉํ๋ ๋ชจ๋ธ์ ์ต๋์ ๋ ฅ๊ธธ์ด
(์ฆ, ํ ํฌ๋์ด์ ์ model_max_length๋ ๋ชจ๋ธ์ max_model_input_sizes๋ณด๋ค ํฌ์ง ์๋๋ก ์ค์ ํด์ผ ๋ชจ๋ธ์ด ์ ์์ ์ผ๋ก ์ ๋ ฅ์ ์ฒ๋ฆฌํ ์ ์๋ค.)
- padding_side/truncation_side: padding/truncation์์น(left/right) ๊ฒฐ์
- model_input_names: ์์ ํ์ ์ ๋ ฅ๋๋ tensor๋ชฉ๋ก(ex. input_ids, attention_mask, token_type_ids)
cf) decode๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด token_id ๋ฌธ์ฅ์ ์๋ ๋ฌธ์ฅ์ผ๋ก ๋ณต์ํ๋ค.
cf) PretrainedTokenizerFast๋ Rust๋ก ๊ตฌํ๋ ๋ฒ์ ์ผ๋ก Python Wrapper๋ฅผ ํตํด ํธ์ถ๋๋, ๋ ๋น ๋ฅธ tokenizer๋ค.
Datasets
Dataset Upload ์์ :
images ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ: images โฟ A.jpg โฟ B.jpg ... import os from collections import defaultdict from datasets import Dataset, Image, DatasetDict data = defaultdict(list) folder_name = '../images' for file_name in os.listdir(folder_name): name = os.path.splittext(file_name)[0] path = os.path.join(folder_name, file_name) data['name'].append(name) data['image'].append(path) dataset = Dataset.from_dict(data).cast_column('image', Image()) # print(data, dataset[0]) # ํ์ธ์ฉ dataset_dict = DatasetDict({ 'train': dataset.select(range(5)), 'valid': dataset.select(range(5, 10)), 'test': dataset.select(range(10, len(dataset))) } ) hub_name = "<user_name>/<repo_name>" # dataset์ ์ฅ๊ฒฝ๋ก token = "hf_###..." # huggingface token์ ๋ ฅ datasetdict.push_to_hub(hub_name, token=token)
๐ค Embedding๊ณผ์ ์์ ์ ๋ฆฌ!!
from transformers import BertTokenizer, BertModel tokenizer = BertTokenizer.from_pretrained('bert-base-uncased') model = BertModel.from_pretrained("bert-base-uncased") txt = "I am laerning about tokenizers." input = tokenizer(txt, return_tensors="pt") output = model(**input) print('input:', input) print('last_hidden_state:', output.last_hidden_state.shape)
input: {'input_ids': tensor([[ 101, 1045, 2572, 2474, 11795, 2075, 2055, 19204, 17629, 2015, 1012, 102]]), 'token_type_ids': tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]), 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])} last_hidden_state: torch.Size([1, 12, 768])
- input ๋์ ๋๋ฆฌ
- input_ids:
- ๊ฐ ๋จ์ด์ ํน์ ํ ํฐ์ด BERT์ ์ดํ ์ฌ์ ์ ๋งคํ๋ ๊ณ ์ ํ ์ ์ ID๋ก ๋ณํ๋ ๊ฒฐ๊ณผ์ ๋๋ค.
- ์์: 101์ [CLS] ํ ํฐ, 102๋ [SEP] ํ ํฐ.
- ์ ์ฒด ์ํ์ค: [CLS] I am laerning about tokenizers. [SEP]
- ๊ธธ์ด: 12๊ฐ์ ํ ํฐ (๋ฌธ์ฅ ์ ์ฒด์ ํน์ ํ ํฐ ํฌํจ)
- token_type_ids:
- ๋ฌธ์ฅ ๋ด์ ๊ฐ ํ ํฐ์ด ์ด๋ segment์ ์ํ๋์ง๋ฅผ ๋ํ๋.
- BERT๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ ๊ฐ์ ์ธ๊ทธ๋จผํธ(์: ๋ฌธ์ฅ A์ ๋ฌธ์ฅ B)๋ฅผ ๊ตฌ๋ถ๊ฐ๋ฅ.
- ์ฌ๊ธฐ์๋ ๋จ์ผ ๋ฌธ์ฅ์ด๋ฏ๋ก ๋ชจ๋ ๊ฐ์ด 0์ด๋ค.
- attention_mask:
- ๋ชจ๋ธ์ด ๊ฐ ํ ํฐ์ ์ฃผ์๋ฅผ ๊ธฐ์ธ์ฌ์ผ ํ๋์ง๋ฅผ ๋ํ๋ธ๋ค.
- 1์ ํด๋น ํ ํฐ์ด ์ค์ ๋ฐ์ดํฐ์์ ์๋ฏธํ๊ณ , 0์ ํจ๋ฉ ํ ํฐ์ ์๋ฏธ.
- ์ฌ๊ธฐ์๋ ํจ๋ฉ์ด ์์ผ๋ฏ๋ก ๋ชจ๋ ๊ฐ์ด 1์ด๋ค.
- last_hidden_state
- Shape: [1, 12, 768]
- Batch Size (1): ํ ๋ฒ์ ํ๋์ ์ ๋ ฅ ๋ฌธ์ฅ์ ์ฒ๋ฆฌ.
- Sequence Length (12): ์ ๋ ฅ ์ํ์ค์ ํ ํฐ ์ (ํน์ ํ ํฐ ํฌํจ).
- Hidden Size (768): BERT-base ๋ชจ๋ธ์ ๊ฐ ํ ํฐ์ ๋ํด 768์ฐจ์์ ๋ฒกํฐ ํํ์ ์์ฑํ๋ค.
- ์๋ฏธ:
- last_hidden_state๋ ๋ชจ๋ธ์ ๋ง์ง๋ง ์๋ ๊ณ์ธต์์ ๊ฐ ํ ํฐ์ ๋ํ ๋ฒกํฐ ํํ์ ๋ด๊ณ ์๋ค.
- ์ด ๋ฒกํฐ๋ค์ ๋ฌธ๋งฅ ์ ๋ณด๋ฅผ ํฌํจํ๊ณ ์์ผ๋ฉฐ, ๋ค์ํ NLP ์์ (์: ๋ถ๋ฅ, ๊ฐ์ฒด๋ช ์ธ์ ๋ฑ)์ ํ์ฉ๋ ์ ์๋ค.
์ค๋ช )
ex-1) Embedding Lookup Table๊ณผ์ ์ฝ๋
train_data = 'you need to know how to code' # ์ค๋ณต์ ์ ๊ฑฐํ ๋จ์ด๋ค์ ์งํฉ์ธ ๋จ์ด ์งํฉ ์์ฑ. word_set = set(train_data.split()) # ๋จ์ด ์งํฉ์ ๊ฐ ๋จ์ด์ ๊ณ ์ ํ ์ ์ ๋งตํ. vocab = {word: i+2 for i, word in enumerate(word_set)} vocab['<unk>'] = 0 vocab['<pad>'] = 1 print(vocab) # {'need': 2, 'to': 3, 'code': 4, 'how': 5, 'you': 6, 'know': 7, '<unk>': 0, '<pad>': 1} # ๋จ์ด ์งํฉ์ ํฌ๊ธฐ๋งํผ์ ํ์ ๊ฐ์ง๋ ํ ์ด๋ธ ์์ฑ. embedding_table = torch.FloatTensor([[ 0.0, 0.0, 0.0], [ 0.0, 0.0, 0.0], [ 0.2, 0.9, 0.3], [ 0.1, 0.5, 0.7], [ 0.2, 0.1, 0.8], [ 0.4, 0.1, 0.1], [ 0.1, 0.8, 0.9], [ 0.6, 0.1, 0.1]]) sample = 'you need to run'.split() idxes = [] # ๊ฐ ๋จ์ด๋ฅผ ์ ์๋ก ๋ณํ for word in sample: try: idxes.append(vocab[word]) # ๋จ์ด ์งํฉ์ ์๋ ๋จ์ด์ผ ๊ฒฝ์ฐ <unk>๋ก ๋์ฒด๋๋ค. except KeyError: idxes.append(vocab['<unk>']) idxes = torch.LongTensor(idxes) # ๊ฐ ์ ์๋ฅผ ์ธ๋ฑ์ค๋ก ์๋ฒ ๋ฉ ํ ์ด๋ธ์์ ๊ฐ์ ๊ฐ์ ธ์จ๋ค. lookup_result = embedding_table[idxes, :] print(lookup_result) print(lookup_result.shape) # tensor([[0.1000, 0.8000, 0.9000], # [0.2000, 0.9000, 0.3000], # [0.1000, 0.5000, 0.7000], # [0.0000, 0.0000, 0.0000]]) # torch.Size([4, 3])
ex-2) Embedding lookup table๊ณผ์ ์ฝ๋์ nn.Embedding๊ฐ ๋น๊ต
train_data = 'you need to know how to code' # ์ค๋ณต์ ์ ๊ฑฐํ ๋จ์ด๋ค์ ์งํฉ์ธ ๋จ์ด ์งํฉ ์์ฑ. word_set = set(train_data.split()) # ๋จ์ด ์งํฉ์ ๊ฐ ๋จ์ด์ ๊ณ ์ ํ ์ ์ ๋งตํ. vocab = {tkn: i+2 for i, tkn in enumerate(word_set)} vocab['<unk>'] = 0 vocab['<pad>'] = 1 embedding_layer = nn.Embedding(num_embeddings=len(vocab), embedding_dim=3, padding_idx=1) print(embedding_layer.weight) print(embedding_layer) # tensor([[ 0.7830, 0.2669, 0.4363], # [ 0.0000, 0.0000, 0.0000], # [-1.2034, -0.0957, -0.9129], # [ 0.7861, -0.0251, -2.2705], # [-0.5167, -0.3402, 1.3143], # [ 1.7932, -0.6973, 0.5459], # [-0.8952, -0.4937, 0.2341], # [ 0.3692, 0.0593, 1.0825]], requires_grad=True) # Embedding(8, 3, padding_idx=1)
ex-3) Embedding ์์์ฝ๋
class BertEmbeddings(nn.Module): def __init__(self, config): super().__init__() self.config = config self.word_embeddings = nn.Embedding(config.vocab_size, config.emb_size, padding_idx=config.pad_token_id) self.position_embeddings = nn.Embedding(config.max_seq_length, config.emb_size) self.token_type_embeddings = nn.Embedding(2, config.emb_size) self.LayerNorm = nn.LayerNorm(config.emb_size, eps=config.layer_norm_eps) self.dropout = nn.Dropout(config.dropout) # position ids (used in the pos_emb lookup table) that we do not want updated through backpropogation self.register_buffer("position_ids", torch.arange(config.max_seq_length).expand((1, -1))) def forward(self, input_ids, token_type_ids): word_emb = self.word_embeddings(input_ids) pos_emb = self.position_embeddings(self.position_ids) type_emb = self.token_type_embeddings(token_type_ids) emb = word_emb + pos_emb + type_emb emb = self.LayerNorm(emb) emb = self.dropout(emb) return emb
NLP
BERT - Classification
NER (Named Entity Recognition)
Token Classification, ์ฆ ๋ฌธ์ฅ์ ๊ตฌ์ฑํ๋ ๊ฐ token์ label์ ํ ๋นํ๋ Task์ด๋ค.
๋จผ์ ์์๋ก BIO Tagging์ ๋ค๋ฉด ์๋์ ๊ฐ๋ค:
์ด๋, B๋ Begin(๊ฐ์ฒด๋ช ์ ์์)์, I๋ Inside(๊ฐ์ฒด๋ช ์ ์ฐ์)๋ฅผ, O๋ Outside(๊ฐ์ฒด๋ช ์ด ์๋๊ฒ)๋ฅผ ์๋ฏธํ๋ค.ex) ์ธ๊ณต์ง๋ฅ(AI)์์ ๋ฅ๋ฌ๋์ ๋จธ์ ๋ฌ๋์ ํ ๋ถ์ผ์ ๋๋ค. --> <์ธ๊ณต์ง๋ฅ:B-Tech> <(:I-Tech> <AI:I-Tech> <):I-Tech> <์์:O> <๋ฅ๋ฌ๋:B-Tech> <์:O> <๋จธ์ ๋ฌ๋:B-Tech> <์:O> <ํ:O> <๋ถ์ผ:O> <์ ๋๋ค:O> <.:O>
์ด๋ฐ NER์์ ์์ฃผ์ฌ์ฉ๋๋ ๋ชจ๋ธ์ด ๋ฐ๋ก BERT์ด๋ค.
BERT - MLM, NSP
๋ฌธ์ฅ๊ฐ ๊ด๊ณ(์์ฝ ๋ฑ)๋ฅผ ์ดํดํ๊ธฐ ์ํด ํ์ฉ๋๋ [CLS]ํ ํฐ์ด ์ฌ์ฉ๋๋ค.
BERT์์๋ ์ด 3๊ฐ์ง Embedding์ด Embedding Layer์์ ํ์ฉ๋๋ค:
1. Token Embedding:
- ์ ๋ ฅ๋ฌธ์ฅ embedding
2. Segment Embedding:
- ๋ชจ๋ธ์ด ์ธ์ํ๋๋ก ๊ฐ ๋ฌธ์ฅ์ ๊ณ ์ ๋ ์ซ์ ํ ๋น.
3. Position Embedding:
- input์ ํ๋ฒ์ ๋ชจ๋ ๋ฐ์ด๋ฃ๊ธฐ์(= ์์ฐจ์ ์ผ๋ก ๋ฃ์ง ์์)
- Transformer Encoder๋ ๊ฐ token์ ์๊ฐ์ ์์๋ฅผ ์์ง ๋ชปํจ
- ์ด๋ฅผ ์ํด ์์น์ ๋ณด๋ฅผ ์ฝ์ ํ๊ธฐ์ํด sine, cosine์ ์ฌ์ฉํ๋ค.
BART - Summarization
Abstractive & Extractive Summarization
์ถ์์์ฝ: ์๋ฌธ์ ์์ ํ ์ดํด --> ์๋ก์ด ๋ฌธ์ฅ์ ์์ฑํด ์์ฝํ๋ ๋ฐฉ์.
์ถ์ถ์์ฝ: ์๋ฌธ์์ ๊ฐ์ฅ ์ค์ํ๊ณ ๊ด๋ จ์ฑ ๋์ ๋ฌธ์ฅ๋ค๋ง ์ ํํด ๊ทธ๋๋ก ์ถ์ถ.
(์์ฝ๋ฌธ์ด ๋ถ์์ฐ์ค๋ฌ์ธ ์๋ ์์ผ๋ฉฐ, ์ค๋ณต์ ๊ฑฐ๋ฅ๋ ฅ์ด ํ์ํจ.)
BART (Bidirectional & Auto Regressive Transformers)
Encoder-Decoder ๋ชจ๋ ์กด์ฌํ๋ฉฐ, ํนํ๋ Embedding์ธต์ ๊ณต์ ํ๋ Shared Embedding์ ์ฌ์ฉํด ๋๊ฐ์ ์ฐ๊ฒฐ์ ๊ฐํํ๋ค.
Encoder๋ Bidirectional Encoder๋ก ๊ฐ ๋จ์ด๊ฐ ๋ฌธ์ฅ ์ ์ฒด์ ์ข์ฐ context๋ฅผ ๋ชจ๋ ์ฐธ์กฐ๊ฐ๋ฅํ๋ฉฐ,
Decoder์์ Auto-Regressive๋ฐฉ์์ผ๋ก ์ด์ ์ ์์ฑํ ๋จ์ด๋ฅผ ์ฐธ์กฐํด ๋ค์ ๋จ์ด๋ฅผ ์์ธกํ๋ค.
๋ํ, Pre-Train์ Denoising Auto Encoder๋ก ํ์ตํ๋๋ฐ, ์์๋ก noisingํ, ๋ณต์ํ๊ฒ ํ๋ค.
RoBERTa, T5- TextQA
Abstractive & Extractive QA
์ถ์์ง์์๋ต: ์ฃผ์ด์ง ์ง๋ฌธ ๋ด์์ ๋ต๋ณ์ด ๋๋ ๋ฌธ์์ด ์ถ์ถ (์ง๋ฌธ-์ง๋ฌธ-์ง๋ฌธ๋ด๋ต๋ณ์ถ์ถ)
์ถ์ถ์ง์์๋ต: ์ง๋ฌธ๊ณผ ์ง๋ฌธ์ ์ ๋ ฅ๋ฐ์ ์๋ก์ด ๋ต๋ณ ์์ฑ (์ง๋ฌธ-์ง๋ฌธ-๋ต๋ณ)
RoBERTa
max_len, pretrain-dataset์์ด ๋์ด๋ฌ์ผ๋ฉฐ, Dynamic Masking๊ธฐ๋ฒ ๋์ ์ด ํต์ฌ.
Dynamic Masking: ๊ฐ ์ํญ๋ง๋ค ๋ค๋ฅธ ๋ง์คํนํจํด ์์ฑ. (NSP๋ ์์ฐ.)
BPE Tokenization ์ฌ์ฉ: BERT๋ wordpiece tokenize.
T5- Machine Translation
SMT & NMT
ํต๊ณ์ ๊ธฐ๊ณ๋ฒ์ญ: ์๋ฌธ-๋ฒ์ญ์ ๊ธฐ๋ฐ, ๋จ์ด์์ ๋ฐ ์ธ์ดํจํด์ ์ธ์ --> ๋๊ท๋ชจ dataํ์
์ ๊ฒฝ๋ง ๊ธฐ๊ณ๋ฒ์ญ: ๋ฒ์ญ๋ฌธ๊ณผ ๋จ์ด์ํ์ค๊ฐ ๊ด๊ณ๋ฅผ ํ์ต
T5 (Text-To-Text Transfer Transformer)
tast๋ณ ํน์ Promptํ์์ ์ฌ์ฉํด ์ ์ ํ ์ถ๋ ฅ์ ์์ฑํ๊ฒ ์ ๋๊ฐ๋ฅํ๋ค.
์ฆ, ๋จ์ผ ๋ชจ๋ธ๋ก ๋ค์ํ NLP Task๋ฅผ ์ฒ๋ฆฌ๊ฐ๋ฅํ seq2seq๊ตฌ์กฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ค.
T5์ ๋ ํนํ์ ์ ๋ชจ๋ธ๊ตฌ์กฐ์ฐจ์ ๊ฐ ์๋, "์ ์ถ๋ ฅ ๋ชจ๋ Txtํํ๋ก ์ทจ๊ธํ๋ seq2seq๋ก ์ ๊ทผํด Pretrain๊ณผ์ ์์ "Unsupervised Learning"์ ํตํด ๋๊ท๋ชจ corpus(์ฝ 75GB)๋ฅผ ์ฌ์ฉํ๋ค๋ ์ ์ด๋ค." ์ด๋ฅผ ํตํด ์ธ์ด์ ์ผ๋ฐ์ ํจํด๊ณผ ์ง์์ ํจ๊ณผ์ ์ผ๋ก ์ต๋ํ๋ค.
LLaMA - Text Generation
Seq2Seq & CausalLM
Seq2Seq: Transformer, BART, T5 ๋ฑ Encoder-Decoder๊ตฌ์กฐ
CausalLM: ๋จ์ผ Decoder๋ก ๊ตฌ์ฑ
LLaMA-3 Family
2024๋ 4์, LLaMA-3๊ฐ ์ถ์๋์๋๋ฐ, LLaMA-3์์๋ GQA(Grouped Query Attention)์ด ์ฌ์ฉ๋์ด Inference์๋๋ฅผ ๋์๋ค.
LLaMA-3๋ Incontext-Learning, Few-Shot Learning ๋ชจ๋ ๋ฐ์ด๋ ์ฑ๋ฅ์ ๋ณด์ธ๋ค.Incontext-Learning: ๋ชจ๋ธ์ด ์ ๋ ฅํ ์คํธ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์๋ก์ด ์์ ์ ์ฆ์์์ ์ํํ๋ ๋ฅ๋ ฅ
์ถ๊ฐ์ ์ผ๋ก 2024๋ 7์, LLaMA-3.1์ด ๊ณต๊ฐ๋์๋ค. LLaMA-3.1์ AI์์ ์ฑ ๋ฐ ๋ณด์๊ด๋ จ ๋๊ตฌ๊ฐ ์ถ๊ฐ๋์๋๋ฐ, Prompt Injection์ ๋ฐฉ์งํ๋ Prompt Guard๋ฅผ ๋์ ํด ์ ํดํ๊ฑฐ๋ ๋ถ์ ์ ํ ์ฝํ ์ธ ๋ฅผ ์๋ณํ๊ฒ ํ์๋ค.
์ถ๊ฐ์ ์ผ๋ก LLaMA-3 ์๋ฆฌ์ฆ๋ ๋ค์๊ณผ ๊ฐ์ ์ฃผ์ ํน์ง์ด ์กด์ฌํ๋ค:
- RoPE(Rotary Position Embedding): Q, K์ ์ ์ฉ
- GQA(Grouped Query Attention): K, V๋ฅผ ์ฌ๋ฌ ๊ทธ๋ฃน์ผ๋ก ๋ฌถ์ด attention์ฐ์ฐ์ํ --> ํจ์จ์ ์ถ๋ก
- RMS Norm: ์์ ์ ํ์ต ๋ฐ ๊ณ์ฐ์ ํจ์จ์ฑ
- KV cache: ์ถ๋ก ์ K,V๋ฅผ cache์ ์ ์ฅ --> ์ฐ์ฐ์ ํจ์จ์ฑ
LLaMA-3 ์ต์ ํ๊ธฐ๋ฒ: SFT . RLHF . DPO
SFT(Supervised Fine-Tuning): ์ฌ๋์ด ์์ฑํ ๊ณ ํ์งQA์์ผ๋ก ๋ชจ๋ธ์ ์ง์ ํ์ต์ํค๋ ๋ฐฉ๋ฒ
RLHF: PPO์๊ณ ๋ฆฌ์ฆ๊ธฐ๋ฐ, ๋ชจ๋ธ์ด ์์ฑํ ์ฌ๋ฌ ์๋ต์ ๋ํด ์ฌ๋์ด ์์๋ฅผ ๋งค๊ธฐ๊ณ ์ด๋ฅผ ๋ฐํ์ผ๋ก ์ฌํ์ต.
DPO(Direct Preference Optimization): RLHF์ ๋ณต์ก์ฑ์ ์ค์ด๋ฉด์ ํจ๊ณผ์ ํ์ต์ ๊ฐ๋ฅ์ผํจ.(์ฌ๋์ด ๋งค๊ธด ์๋ต์์๋ฅผ ์ง์ ํ์ต; ๋ค๋ง ๋์ฑ ๊ณ ํ์ง ์ ํธ๋ data๋ฅผ ํ์๋กํจ.)
Computer Vision
์ฃผ๋ก CV(Computer Vision)๋ถ์ผ์์ CNN๊ธฐ๋ฒ์ด ๋ง์ด ํ์ฉ๋์๋ค.(VGG, Inception, ResNet, ...)
๋ค๋ง, CNN based model์ ์ฃผ๋ก ๊ตญ์์ (local) pattern์ ํ์ตํ๊ธฐ์ ์ ์ญ์ ์ธ ๊ด๊ณ(global relation)๋ชจ๋ธ๋ง์ ํ๊ณ๊ฐ ์กด์ฌํ๋ค.
์ถ๊ฐ์ ์ผ๋ก ์ด๋ฏธ์ง ํฌ๊ธฐ๊ฐ ์ปค์ง์๋ก ๊ณ์ฐ๋ณต์ก๋ ๋ํ ์ฆ๊ฐํ๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ViT(Vision Transformer)๊ฐ ์ ์๋์์ผ๋ฉฐ, ๋๊ท๋ชจ dataset์ผ๋ก ํจ์จ์ ์ผ๋ก ํ์ตํ๋ค.
ViT์ ๊ฐ์ฅ ๋ํ์ ์ธ ๊ฒฉ์ธ CLIP, OWL-ViT, SAM์ ๋ํด ์์๋ณด์.
Zero shot classification
Zero Shot Classification: CLIP, ALIGN, SigLIP
์ฌ์ค CLIP์ ๋ค์ํ Task์์ ๋ง์ด ํ์ฉ๋๋ ๋ณธ ๊ธ์ Train dataset์ ์๋ Label์ ๋ํด Image Classification์ ์ํํ๋ ๊ธฐ์ ์ ํ์ฉ๋๋ ๋ฐฉ๋ฒ์ผ๋ก ์์๋ณด๊ณ ์ ํ๋ค.
์๋ก์ด Label์ด ์ถ๊ฐ๋ ๋๋ง๋ค ์ฌํ์ต์ด ํ์ํ๋ฐ, ์ด๋ฅผ ํผํ๋ ค๋ฉด Zero shot๊ธฐ๋ฒ์ ๋ฐํ์์ ์ด๊ธฐ ๋๋ฌธ์ด๋ค.
CLIP (Contrastive Language-Image Pre-training)
Model Architecture Input_Size Patch_Size #params openai/clip-vit-base-patch32 ViT-B/32 224×224 32×32 1.5B openai/clip-vit-base-patch16 ViT-B/16 224×224 16×16 1.5B openai/clip-vit-large-patch14 ViT-L/14 224×224 14×14 4.3B openai/clip-vit-large-patch14-336 ViT-L/14 336×336 14×14 4.3B ์์ patch_size: ๋ ์ธ๋ฐํ ํน์ง์ถ์ถ, ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ๋ฐ ๊ณ์ฐ์๊ฐ ์ฆ๊ฐ
ํฐ patch_size: ๋น๊ต์ ๋ฎ์ ์ฑ๋ฅ, ๋น ๋ฅธ ์ฒ๋ฆฌ์๋
๊ธฐ์กด Supervised Learning๊ณผ ๋ฌ๋ฆฌ 2๊ฐ์ง ํน์ง์ด ์กด์ฌํ๋ค:
1.๋ณ๋์ Label์์ด input์ผ๋ก image-txt์๋ง ํ์ต.
- img, txt๋ฅผ ๋์ผํ embedding๊ณต๊ฐ์ ์ฌ์(Projection)
- ์ด๋ฅผ ํตํด ๋ Modality๊ฐ ์๋ฏธ์ ์ ์ฌ์ฑ์ ์ง์ ์ ์ผ๋ก ์ธก์ ๋ฐ ํ์ต๊ฐ๋ฅ
- ์ด ๋๋ฌธ์ CLIP์ img-encoder, txt-encoder ๋ชจ๋ ๊ฐ๊ณ ์์
2. Contrastive Learning:
- "Positive Sample": ์ค์ img-txt์ --> img-txt๊ฐ ์๋ฏธ์ ์ ์ฌ์ฑ ์ต๋ํ
- "Negative Sample": randomํ๊ฒ pair๋ ๋ถ์ผ์นimg-txt์ --> ์ ์ฌ์ฑ ์ต์ํ
- ์ด๋ฅผ ์ํด Cosine Similarity๊ธฐ๋ฐ์ Contrastive Learning Loss๋ฅผ ์ฌ์ฉ.
Zero-Shot Classification ์์
from datasets import load_dataset from transformers import CLIPProcessor, CLIPModel import torch model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32") processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32") dataset = load_dataset("sasha/dog-food") images = dataset['test']['image'][:2] labels = ['dog', 'food'] inputs = processor(images=images, text=labels, return_tensors="pt", padding=True) print('input_ids: ', inputs['input_ids']) print('attention_mask: ', inputs['attention_mask']) print('pixel_values: ', inputs['pixel_values']) print('image_shape: ', inputs['pixel_values'].shape) # ======================================================= # input_ids: tensor([[49406, 1929, 49407], [49406, 1559, 49407]]) # attention_mask: tensor([[1, 1, 1], [1, 1, 1]]) # pixel_values: tensor([[[[-0.0113, ...,]]]]) # image_shape: torch.Size([2, 3, 224, 224])
CLIPProcessor์๋ CLIPImageProcessor์ CLIPTokenizer๊ฐ ๋ด๋ถ์ ์ผ๋ก ํฌํจ๋์ด ์๋ค.
input_ids์์ 49406๊ณผ 49407์ ๊ฐ๊ฐ startoftext์ endoftext๋ฅผ ๋ํ๋ด๋ ํน๋ณํ ๊ฐ์ด๋ค.
attention_mask๋ ๋ณํ๋ token_types๋ก
๊ฐ์ด 1์ด๋ฉด ํด๋น์์นํ ํฐ์ด ์ค์ ๋ฐ์ดํฐ๊ฐ์ ๋ํ๋ด๊ณ , 0์ [PAD]๋ฅผ ์๋ฏธํ๋ค.with torch.no_grad(): outputs = model(**inputs) logits_per_image = outputs.logits_per_image probs = logits_per_image.softmax(dim=1) print('outputs:', outputs.keys()) print('logits_per_image:', logits_per_image) print('probs: ', probs) for idx, prob in enumerate(probs): print(f'- Image #{idx}') for label, p in zip(labels, prob): print(f'{label}: {p.item():.4f}') # ============================================ # outputs: odict_keys(['logits_per_image', 'logits_per_text', 'text_embeds', 'image_embeds', 'text_model_output', 'vision_model_output']) # logits_per_image: tensor([[23.3881, 18.8604], [24.8627, 21.5765]]) # probs: tensor([[0.9893, 0.0107], [0.9640, 0.0360]]) # - Image #0 # dog: 0.9893 # food: 0.0107 # - Image #1 # dog: 0.9640 # food: 0.0360
Zero shot Detection
์์ฐ์ด์ ์ค๋ช ์๋ ์ด๋ฏธ์ง ๋ด ๊ฐ์ฒด์ ๊ฐ๋ต์ ์์น์ ๋ณด๋ฅผ ์์์ ์ผ๋ก ํฌํจํ๋ค.
CLIP์์ img-txt์์ผ๋ก ์๊ฐ์ ํน์ง๊ณผ ํ ์คํธ๊ฐ ์ฐ๊ด์ฑ์ ํ์ต๊ฐ๋ฅํจ์ ๋ณด์๊ธฐ์,
์ถ๋ก ์, ์ฃผ์ด์ง txt prompt๋ง ์ ์ค๊ณํ๋ค๋ฉด ๊ฐ์ฒด์ ์์น๋ฅผ ์์ธกํ ์ ์๊ฒ๋๋ค.
๋ฐ๋ผ์ zero-shot object detection์์๋ ์ ํต์ ์ธ annotation์ ๋ณด ์์ด๋ ์๊ฐ๊ณผ ์ธ์ด๊ฐ์ ์๊ด๊ด๊ณ๋ฅผ ํ์ตํ์ฌ ์๋ก์ด ๊ฐ์ฒดํด๋์ค๋ฅผ ๊ฒ์ถํ ์ ์๊ฒ ํด์ค๋ค.
OWL-ViT์ ๊ฒฝ์ฐ, Multi-Modal Backbone๋ชจ๋ธ๋ก CLIP๋ชจ๋ธ์ ์ฌ์ฉํ๋ค.
OWLv2 (OWL-ViT)
OWL-ViT๋ img-txt์์ผ๋ก pretrainํ์ฌ Open-Vocabulary๊ฐ์ฒดํ์ง๊ฐ ๊ฐ๋ฅํ๋ค.
OWLv2๋ Self-Training๊ธฐ๋ฒ์ผ๋ก ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์์ผฐ๋ค.
์ฆ, ๊ธฐ์กด Detector๋ก Weak Supervision๋ฐฉ์์ผ๋ก ๊ฐ์์ Bbox-Annotation์ ์๋์์ฑํ๋ค.
ex) input: img-txt pair[๊ฐ์์ง๊ฐ ๊ณต์ ๊ฐ์ง๊ณ ๋ ธ๋]
๊ธฐ์กด detector: [๊ฐ์์ง bbox] [๊ณต bbox] ์๋์์ธก, annotation์์ฑ
--> ๋ชจ๋ธ ํ์ต์ ์ด์ฉ (์ฆ, ์ ํํ ์์น์ ๋ณด๋ ์์ง๋ง ๋ถ๋ถ์ supervision signal๋ก weak signal๊ธฐ๋ฐ, ๋ชจ๋ธ์ด ๊ฐ์ฒด์ ์์น ๋ฐ ํด๋์ค๋ฅผ ์ถ๋ก , ํ์ตํ๊ฒ ํจ)
Zero-Shot Detection ์์
import io from PIL import Image from datasets import load_dataset from transformers import Owlv2Processor, Owlv2ForObjectDetection processor = Owlv2Processor.from_pretrained("google/owlv2-base-patch16") model = Owlv2ForObjectDetection.from_pretrained("google/owlv2-base-patch16") dataset = load_dataset('Francesco/animals-ij5d2') print(dataset) print(dataset['test'][0]) # ========================================================== # DatasetDict({ # train: Dataset({ # features: ['image_id', 'image', 'width', 'height', 'objects'], # num_rows: 700 # }) # validation: Dataset({ # features: ['image_id', 'image', 'width', 'height', 'objects'], # num_rows: 100 # }) # test: Dataset({ # features: ['image_id', 'image', 'width', 'height', 'objects'], # num_rows: 200 # }) # }) # {'image_id': 63, 'image': <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=640x640 at 0x7A2B0186E4A0>, 'width': 640, 'height': 640, 'objects': {'id': [96, 97, 98, 99], 'area': [138029, 8508, 10150, 20624], 'bbox': [[129.0, 291.0, 395.5, 349.0], [119.0, 266.0, 93.5, 91.0], [296.0, 280.0, 116.0, 87.5], [473.0, 284.0, 167.0, 123.5]], 'category': [3, 3, 3, 3]}}
- Label ๋ฐ Image ์ ์ฒ๋ฆฌ
images = dataset['test']['image'][:2] categories = dataset['test'].features['objects'].feature['category'].names labels = [categories] * len(images) inputs = processor(text=labels, images=images, return_tensors="pt", padding=True) print(images) print(labels) print('input_ids:', inputs['input_ids']) print('attention_mask:', inputs['attention_mask']) print('pixel_values:', inputs['pixel_values']) print('image_shape:', inputs['pixel_values'].shape) # ========================================================== # [<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=640x640 at 0x7A2ADF7CF790>, <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=640x640 at 0x7A2ADF7CCC10>] # [['animals', 'cat', 'chicken', 'cow', 'dog', 'fox', 'goat', 'horse', 'person', 'racoon', 'skunk'], ['animals', 'cat', 'chicken', 'cow', 'dog', 'fox', 'goat', 'horse', 'person', 'racoon', 'skunk']] # input_ids: tensor([[49406, 4995, 49407, 0], # [49406, 2368, 49407, 0], # [49406, 3717, 49407, 0], # [49406, 9706, 49407, 0], # [49406, 1929, 49407, 0], # [49406, 3240, 49407, 0], # [49406, 9530, 49407, 0], # [49406, 4558, 49407, 0], # [49406, 2533, 49407, 0], # [49406, 1773, 7100, 49407], # [49406, 42194, 49407, 0], # [49406, 4995, 49407, 0], # [49406, 2368, 49407, 0], # [49406, 3717, 49407, 0], # [49406, 9706, 49407, 0], # [49406, 1929, 49407, 0], # [49406, 3240, 49407, 0], # [49406, 9530, 49407, 0], # [49406, 4558, 49407, 0], # [49406, 2533, 49407, 0], # [49406, 1773, 7100, 49407], # [49406, 42194, 49407, 0]]) # attention_mask: tensor([[1, 1, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], # [1, 1, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [1, 1, 1, 1], [1, 1, 1, 0], # [1, 1, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], # [1, 1, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [1, 1, 1, 1], [1, 1, 1, 0]]) # pixel_values: tensor([[[[ 1.5264, ..., ]]]]) # image_shape: torch.Size([2, 3, 960, 960])
- Detection & Inference
import torch model.eval() with torch.no_grad(): outputs = model(**inputs) print(outputs.keys()) # odict_keys(['logits', 'objectness_logits', 'pred_boxes', 'text_embeds', 'image_embeds', 'class_embeds', 'text_model_output', 'vision_model_output'])
- Post Processingimport matplotlib.pyplot as plt from PIL import ImageDraw, ImageFont # ์์ธกํ๋ฅ ์ด ๋์ ๊ฐ์ฒด ์ถ์ถ shape = [dataset['test'][:2]['width'], dataset['test'][:2]['height']] target_sizes = list(map(list, zip(*shape))) # [[640, 640], [640, 640]] results = processor.post_process_object_detection(outputs=outputs, threshold=0.5, target_sizes=target_sizes) print(results) # Post Processing for idx, (image, detect) in enumerate(zip(images, results)): image = image.copy() draw = ImageDraw.Draw(image) font = ImageFont.truetype("arial.ttf", 18) for box, label, score in zip(detect['boxes'], detect['labels'], detect['scores']): box = [round(i, 2) for i in box.tolist()] draw.rectangle(box, outline='red', width=3) label_text = f'{labels[idx][label]}: {round(score.item(), 3)}' draw.text((box[0], box[1]), label_text, fill='white', font=font) plt.imshow(image) plt.axis('off') plt.show() # ============================================== # [{'scores': tensor([0.5499, 0.6243, 0.6733]), 'labels': tensor([3, 3, 3]), 'boxes': tensor([[329.0247, 287.1844, 400.3372, 357.9262], # [122.9359, 272.8753, 534.3260, 637.6506], # [479.7363, 294.2744, 636.4859, 396.8372]])}, {'scores': tensor([0.7538]), 'labels': tensor([7]), 'boxes': tensor([[ -0.7799, 173.7043, 440.0294, 538.7166]])}]
Zero shot Semantic segmentation
Image Segmentation์ ๋ณด๋ค ์ ๋ฐํ, ํฝ์ ๋ณ ๋ถ๋ฅ๋ฅผ ์ํํ๊ธฐ์ ๋์ ๊ณ์ฐ๋น์ฉ์ด ๋ค๋ฉฐ, ๊ด๋ฒ์ํ train data์ ์ ๊ตํ ์๊ณ ๋ฆฌ์ฆ์ ํ์๋ก ํ๋ค.
์ ํต์ ๋ฐฉ๋ฒ์ผ๋ก๋ threshold๊ธฐ๋ฐ binary classification, Edge Detection๋ฑ์ด ์์ผ๋ฉฐ
์ต์ ๋ฐฉ๋ฒ์ผ๋ก๋ ๋ฅ๋ฌ๋๋ชจ๋ธ์ ์ด์ฉํด Image Segmentation์ ์งํํ๋ค.
์ ํต์ ๋ฐฉ๋ฒ์ ๋จ์ํ๊ณ ๋น ๋ฅด์ง๋ง ๋ณต์กํ๊ฑฐ๋ ๋ค์ํ ์กฐ๋ช ์กฐ๊ฑด ๋ฑ์์ ์ฑ๋ฅ์ด ํฌ๊ฒ ์ ํ๋๋ ๋จ์ ์ด ์กด์ฌํ๋ค.
SAM (Segment Anything Model)
Model Architecture Input_Size Patch_Size #params facebook/sam-vit-base ViT-B/16 1024×1024 16×16 0.9B facebook/sam-vit-large ViT-L/16 1024×1024 16×16 3.1B facebook/sam-vit-huge ViT-H/16 1024×1024 16×16 6.4B
SAM์ Meta์์ ๊ฐ๋ฐํ ๋ค์ํ ๋๋ฉ์ธ์์ ์์งํ 1100๋ง๊ฐ ์ด๋ฏธ์ง๋ฅผ ์ด์ฉํด ํ์ตํ ๋ชจ๋ธ์ด๋ค.
๊ทธ๋ ๊ธฐ์ ๋ค์ํ ํ๊ฒฝ์์ image segmentation์์ ์ ๊ณ ์์ค์ผ๋ก ์ํ๊ฐ๋ฅํ๋ค.
SAM์ ์ด์ฉํ๋ฉด ๋ง์๊ฒฝ์ฐ, ์ถ๊ฐ์ ์ธ Fine-Tuning์์ด, ๋ค์ํ Domain image์ ๋ํ segmentation์ด ๊ฐ๋ฅํ๋ค.
SAM์ prompt๋ฅผ ๋ฐ์์๋ ์๊ณ , ๋ฐ์ง ์์๋ ๋๋๋ฐ, prompt๋ ์ขํ, bbox, txt ๋ฑ ๋ค์ํ๊ฒ ์ค ์ ์๋ค.
์ถ๊ฐ์ ์ผ๋ก prompt๋ฅผ ์ฃผ์ง ์์ผ๋ฉด img ์ ์ฒด์ ๋ํ ํฌ๊ด์ ์ธ Segmentation์ ์งํํ๋ค.
๋ค๋ง, Inference๊ฒฐ๊ณผ๋ก Binary Mask๋ ์ ๊ณตํ์ง๋ง pixel์ ๋ํ ๊ตฌ์ฒด์ class์ ๋ณด๋ ํฌํจํ์ง ์๋๋ค.
SAM ํ์ฉ ์์
import io from PIL import Image from datasets import load_dataset from transformers import SamProcessor, SamModel def filter_category(data): # 16 = dog # 23 = giraffe return 16 in data["objects"]["category"] or 23 in data["objects"]["category"] def convert_image(data): byte = io.BytesIO(data["image"]["bytes"]) img = Image.open(byte) return {"img": img} model_name = "facebook/sam-vit-base" processor = SamProcessor.from_pretrained(model_name) model = SamModel.from_pretrained(model_name) dataset = load_dataset("s076923/coco-val") filtered_dataset = dataset["validation"].filter(filter_category) converted_dataset = filtered_dataset.map(convert_image, remove_columns=["image"])
import numpy as np from matplotlib import pyplot as plt def show_point_box(image, input_points, input_labels, input_boxes=None, marker_size=375): plt.figure(figsize=(10, 10)) plt.imshow(image) ax = plt.gca() input_points = np.array(input_points) input_labels = np.array(input_labels) pos_points = input_points[input_labels[0] == 1] neg_points = input_points[input_labels[0] == 0] ax.scatter( pos_points[:, 0], pos_points[:, 1], color="green", marker="*", s=marker_size, edgecolor="white", linewidth=1.25 ) ax.scatter( neg_points[:, 0], neg_points[:, 1], color="red", marker="*", s=marker_size, edgecolor="white", linewidth=1.25 ) if input_boxes is not None: for box in input_boxes: x0, y0 = box[0], box[1] w, h = box[2] - box[0], box[3] - box[1] ax.add_patch( plt.Rectangle( (x0, y0), w, h, edgecolor="green", facecolor=(0, 0, 0, 0), lw=2 ) ) plt.axis("on") plt.show() image = converted_dataset[0]["img"] input_points = [[[250, 200]]] input_labels = [[[1]]] show_point_box(image, input_points[0], input_labels[0]) inputs = processor( image, input_points=input_points, input_labels=input_labels, return_tensors="pt" ) # input_points shape : torch.Size([1, 1, 1, 2]) # input_points : tensor([[[[400.2347, 320.0000]]]], dtype=torch.float64) # input_labels shape : torch.Size([1, 1, 1]) # input_labels : tensor([[[1]]]) # pixel_values shape : torch.Size([1, 3, 1024, 1024]) # pixel_values : tensor([[[[ 1.4612, ...]]])
input_points: [B, ์ขํ๊ฐ์, ์ขํ] -- ๊ด์ฌ๊ฐ๋ ๊ฐ์ฒด๋ ์์ญ์ง์ ์ขํ
input_labels: [B, ์ขํB, ์ขํ๊ฐ์] -- input_points์ ๋์๋๋ label์ ๋ณด
- input_labels์ข ๋ฅ:
๋ฒํธ ์ด๋ฆ ์ค๋ช 1 foreground ํด๋์ค ๊ฒ์ถํ๊ณ ์ ํ๋ ๊ด์ฌ๊ฐ์ฒด๊ฐ ํฌํจ๋ ์ขํ 0 not foreground ํด๋์ค ๊ด์ฌ๊ฐ์ฒด๊ฐ ํฌํจ๋์ง ์์ ์ขํ -1 background ํด๋์ค ๋ฐฐ๊ฒฝ์์ญ์ ํด๋นํ๋ ์ขํ -10 padding ํด๋์ค batch_size๋ฅผ ๋ง์ถ๊ธฐ ์ํ padding๊ฐ (๋ชจ๋ธ์ด ์ฒ๋ฆฌX) [Processor๋ก ์ฒ๋ฆฌ๋ ์ดํ ์ถ๋ ฅ๊ฒฐ๊ณผ]
input_points: [B, ์ขํB, ๋ถํ ๋ง์คํฌ ๋น ์ขํ๊ฐ์, ์ขํ์์น]
input_labels: [B, ์ขํB, ์ขํ๊ฐ์]
import torch def show_mask(mask, ax, random_color=False): if random_color: color = np.concatenate([np.random.random(3), np.array([0.6])], axis=0) else: color = np.array([30 / 255, 144 / 255, 255 / 255, 0.6]) h, w = mask.shape[-2:] mask_image = mask.reshape(h, w, 1) * color.reshape(1, 1, -1) ax.imshow(mask_image) def show_masks_on_image(raw_image, masks, scores): if len(masks.shape) == 4: masks = masks.squeeze() if scores.shape[0] == 1: scores = scores.squeeze() nb_predictions = scores.shape[-1] fig, axes = plt.subplots(1, nb_predictions, figsize=(30, 15)) for i, (mask, score) in enumerate(zip(masks, scores)): mask = mask.cpu().detach() axes[i].imshow(np.array(raw_image)) show_mask(mask, axes[i]) axes[i].title.set_text(f"Mask {i+1}, Score: {score.item():.3f}") axes[i].axis("off") plt.show() model.eval() with torch.no_grad(): outputs = model(**inputs) masks = processor.image_processor.post_process_masks( outputs.pred_masks.cpu(), inputs["original_sizes"].cpu(), inputs["reshaped_input_sizes"].cpu(), ) show_masks_on_image(image, masks[0], outputs.iou_scores) print("iou_scores shape :", outputs.iou_scores.shape) print("iou_scores :", outputs.iou_scores) print("pred_masks shape :", outputs.pred_masks.shape) print("pred_masks :", outputs.pred_masks) # iou_scores shape : torch.Size([1, 1, 3]) # iou_scores : tensor([[[0.7971, 0.9507, 0.9603]]]) # pred_masks shape : torch.Size([1, 1, 3, 256, 256]) # pred_masks : tensor([[[[[ -3.6988, ..., ]]]]])
iou_scrores: [B, ์ขํ๊ฐ์, IoU์ ์]
pred_masks: [B, ์ขํB, C, H, W]
input_points = [[[250, 200], [15, 50]]] input_labels = [[[0, 1]]] input_boxes = [[[100, 100, 400, 600]]] show_point_box(image, input_points[0], input_labels[0], input_boxes[0]) inputs = processor( image, input_points=input_points, input_labels=input_labels, input_boxes=input_boxes, return_tensors="pt" ) model.eval() with torch.no_grad(): outputs = model(**inputs) masks = processor.image_processor.post_process_masks( outputs.pred_masks.cpu(), inputs["original_sizes"].cpu(), inputs["reshaped_input_sizes"].cpu(), ) show_masks_on_image(image, masks[0], outputs.iou_scores)โ
Zero shot Instance segmentation
Zero shot Detection + SAM
SAM์ ๊ฒฝ์ฐ, ๊ฒ์ถ๋ ๊ฐ์ฒด์ ํด๋์ค๋ฅผ ๋ถ๋ฅํ๋ ๊ธฐ๋ฅ์ด ์๋ค.
์ฆ, ์ด๋ฏธ์ง ๋ด ๊ฐ์ฒด๋ฅผ ํฝ์ ๋จ์๋ก ๊ตฌ๋ถํ๋ instance segmentation์์ ์๋ ์ด๋ ค์์ด ์กด์ฌํ๋ค.
์ด๋ฐ ํ๊ณ๊ทน๋ณต์ ์ํด zero-shot detection model๊ณผ SAM์ ํจ๊ป ํ์ฉํ ์ ์๋ค:
1) zero shot detection๋ชจ๋ฐ๋ก ๊ฐ์ฒด ํด๋์ค์ bbox์์ญ ๊ฒ์ถ
2) bbox์์ญ๋ด SAM๋ชจ๋ธ๋ก semantic segmentation ์งํ.from transformers import pipeline generator = pipeline("mask-generation", model=model_name) outputs = generator(image, points_per_batch=32) plt.imshow(np.array(image)) ax = plt.gca() for mask in outputs["masks"]: show_mask(mask, ax=ax, random_color=True) plt.axis("off") plt.show() print("outputs mask์ ๊ฐ์ :", len(outputs["masks"])) print("outputs scores์ ๊ฐ์ :", len(outputs["scores"])) # outputs mask์ ๊ฐ์ : 52 # outputs scores์ ๊ฐ์ : 52
detector = pipeline( model="google/owlv2-base-patch16", task="zero-shot-object-detection" ) image = converted_dataset[24]["img"] labels = ["dog", "giraffe"] results = detector(image, candidate_labels=labels, threshold=0.5) input_boxes = [] for result in results: input_boxes.append( [ result["box"]["xmin"], result["box"]["ymin"], result["box"]["xmax"], result["box"]["ymax"] ] ) print(result) inputs = processor(image, input_boxes=[input_boxes], return_tensors="pt") model.eval() with torch.no_grad(): outputs = model(**inputs) masks = processor.image_processor.post_process_masks( outputs.pred_masks.cpu(), inputs["original_sizes"].cpu(), inputs["reshaped_input_sizes"].cpu() ) plt.imshow(np.array(image)) ax = plt.gca() for mask, iou in zip(masks[0], outputs.iou_scores[0]): max_iou_idx = torch.argmax(iou) best_mask = mask[max_iou_idx] show_mask(best_mask, ax=ax, random_color=True) plt.axis("off") plt.show() #{'score': 0.6905778646469116, 'label': 'giraffe', 'box': {'xmin': 96, 'ymin': 198, 'xmax': 294, 'ymax': 577}} #{'score': 0.6264181733131409, 'label': 'giraffe', 'box': {'xmin': 228, 'ymin': 199, 'xmax': 394, 'ymax': 413}}
Image Matching
image matching์ ๋์งํธ ์ด๋ฏธ์ง๊ฐ ์ ์ฌ์ฑ์ ์ ๋ํ, ๋น๊ตํ๋ ๋ฐฉ๋ฒ์ด๋ค.
์ด๋ฅผ image์ feature vector๋ฅผ ์ถ์ถํ์ฌ ๊ฐ image vector๊ฐ ์ ์ฌ๋(๊ฑฐ๋ฆฌ)๋ฅผ ์ธก์ ํ์ฌ ๊ณ์ฐํ๋ค.
๊ทธ๋ ๊ธฐ์ ์ด๋ฏธ์ง ๋งค์นญ์ ํต์ฌ์ "์ด๋ฏธ์ง ํน์ง์ ํจ๊ณผ์ ์ผ๋ก ํฌ์ฐฉํ๋ feature vector์ ์์ฑ"์ด๋ค.
(๋ณดํต ํน์ง๋ฒกํฐ๊ฐ ๊ณ ์ฐจ์์ผ์๋ก ๋ ๋ง์ ์ ๋ณด๋ฅผ ํฌํจํ๋ฉฐ, ์ด ํน์ง๋ฒกํฐ๋ classification layer์ ๊ฐ์ ์ธต์ ํต๊ณผํ๊ธฐ ์ง์ (= Feature Extractor์ ๊ฒฐ๊ณผ๊ฐ = Classifier ์ง์ ๊ฐ) ๋ฒกํฐ๋ฅผ ๋ณดํต ์๋ฏธํ๋ค.)
ex) ViT๋ฅผ ์ด์ฉํ ํน์ง๋ฒกํฐ ์ถ์ถ ์์ import torch from datasets import load_dataset from transformers import ViTImageProcessor, ViTModel dataset = load_dataset("huggingface/cats-image") image = dataset["test"]["image"][0] model_name = "google/vit-base-patch16-224" processor = ViTImageProcessor.from_pretrained(model_name) model = ViTModel.from_pretrained(model_name) inputs = processor(image, return_tensors="pt") with torch.no_grad(): outputs = model(inputs["pixel_values"]) print("๋ง์ง๋ง ํน์ง ๋งต์ ํํ :", outputs["last_hidden_state"].shape) print("ํน์ง ๋ฒกํฐ์ ์ฐจ์ ์ :", outputs["last_hidden_state"][:, 0, :].shape) print("ํน์ง ๋ฒกํฐ :", outputs["last_hidden_state"][:, 0, :]) # ๋ง์ง๋ง ํน์ง ๋งต์ ํํ : torch.Size([1, 197, 768]) # ํน์ง ๋ฒกํฐ์ ์ฐจ์ ์ : torch.Size([1, 768]) # ํน์ง ๋ฒกํฐ : tensor([[ 2.9420e-01, 8.3502e-01, ..., -8.4114e-01, 1.7990e-01]])
ImageNet-21K๋ผ๋ ๋ฐฉ๋ํ ์ฌ์ Dataset์ผ๋ก ํ์ต๋์ด ๋ฏธ์ธํ ์ฐจ์ด ๋ฐ ๋ณต์กํ ํจํด์ ์ธ์ํ ์ ์๊ฒ ๋๋ค.
ViT์์ feature vector์ถ์ถ ์, ์ฃผ๋ชฉํ ์ ์ last_hidden_state ํค ๊ฐ์ด๋ค:
์ถ๋ ฅ์ด [1, 197, 768]์ [B, ์ถ๋ ฅํ ํฐ์, feature์ฐจ์]์ ์๋ฏธํ๋๋ฐ, 197๊ฐ์ ์ถ๋ ฅํ ํฐ์ ๋ค์์ ์๋ฏธํ๋ค.
224×224 --> 16×16(patch_size) --> 196๊ฐ patches,
197 = [CLS] + 196 patches๋ก ์ด๋ฃจ์ด์ง ์ถ๋ ฅํ ํฐ์์ [CLS]๋ฅผ ํน์ง๋ฒกํฐ๋ก ์ฌ์ฉํ๋ค.
FAISS (Facebook AI Similarity Search)FAISS๋ ๋ฉํ์์ ๊ฐ๋ฐํ ๊ณ ์ฑ๋ฅ ๋ฒกํฐ์ ์ฌ๋๊ฒ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.
์ด๋ "๋๊ท๋ชจ ๊ณ ์ฐจ์ ๋ฒกํฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ ์ฌํ ๋ฒกํฐ๋ฅผ ๊ฒ์"๊ฐ๋ฅํ๊ฒ ์ค๊ณ๋์๋ค.
cf) [๋ฒกํฐ ์ ์ฅ ๋ฐ ๊ด๋ฆฌ๋ฐฉ์]
- ๋ก์ปฌ ์ ์ฅ ์ฅ์น: SSD๋ NVMe๊ฐ์ ๊ณ ์์ ์ฅ์ฅ์น๋ฅผ ์ฌ์ฉํด ๋น ๋ฅธ ๋ฐ์ดํฐ ์ ๊ทผ์ด ๊ฐ๋ฅ.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์คํ : PstgreSQL, pgvectorํ์ฅ์ด๋ MongoDB์ Atlas Vector Search๊ฐ์ ๋ฒกํฐ๊ฒ์๊ธฐ๋ฅ์ ์ง์ํ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ํ์ฉ
- ํด๋ผ์ฐ๋ ๋ฒกํฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค: Amazon OpenSearch, Ggogle Vetex AI๋ฑ ํด๋ผ์ฐ๋ ์๋น์ค๋ ๋๊ท๋ชจ ๋ฒกํฐ๋ฐ์ดํฐ์ ์ ์ฅ ๋ฐ ๊ฒ์์ ์ํ ํนํ๋ ์๋ฃจ์ ์ ์ ๊ณต
- ๋ฒกํฐ๊ฒ์์์ง: Milvus, Qdrant, Weaviate, FAISS ๋ฑ์ ๋ฒกํฐ ๋ฐ์ดํฐ ๋ฒ ์ด์ค๋ ๋๊ท๋ชจ ๋ฒกํฐ dataset์ ํจ์จ์ ์ ์ฅ ๋ฐ ๊ณ ์ฑ๋ฅ ๊ฒ์์ ์ํด ์ต์ ํ๋์ด ANN(Approximate Nearest Neighbor)์๊ณ ๋ฆฌ์ฆ์ผ๋ก ๋น ๋ฅธ ์ ์ฌ๋๊ฒ์์ ์ง์, ์ค์๊ฐ ๊ฒ์์ด ํ์ํ ๊ฒฝ์ฐ ํนํ๋ ์ ํฉํ๋ค.
ex) CLIP์ ์ด์ฉํ ์ด๋ฏธ์ง ํน์ง๋ฒกํฐ ์ถ์ถ ์์ import torch import numpy as np from datasets import load_dataset from transformers import CLIPProcessor, CLIPModel dataset = load_dataset("sasha/dog-food") images = dataset["test"]["image"][:100] model_name = "openai/clip-vit-base-patch32" processor = CLIPProcessor.from_pretrained(model_name) model = CLIPModel.from_pretrained(model_name) vectors = [] with torch.no_grad(): for image in images: inputs = processor(images=image, padding=True, return_tensors="pt") outputs = model.get_image_features(**inputs) vectors.append(outputs.cpu().numpy()) vectors = np.vstack(vectors) print("์ด๋ฏธ์ง ๋ฒกํฐ์ shape :", vectors.shape) # ์ด๋ฏธ์ง ๋ฒกํฐ์ shape : (100, 512)
dog-food dataset์์ 100๊ฐ ์ด๋ฏธ์ง๋ฅผ ์ ํ → ๊ฐ ์ด๋ฏธ์ง ๋ฒกํฐ๋ฅผ ์ถ์ถ
→ vectors๋ฆฌ์คํธ์ ์ ์ฅ → ndarrayํ์์ผ๋ก ๋ณํ
์ด๋ฐ ํน์ง๋ฒกํฐ๋ฅผ ์ ์ฌ๋ ๊ฒ์์ ์ํ ์ธ๋ฑ์ค ์์ฑ์ ํ์ฉ๊ฐ๋ฅํ๋ค:
์์ฑ๋ ์ธ๋ฑ์ค์ ์ด๋ฏธ์ง ๋ฒกํฐ๋ฅผ ๋ฑ๋กํ๊ธฐ ์ํด add๋ฅผ ์ฌ์ฉํ๋๋ฐ, ์ด๋ ์ ๋ ฅ๋๋ ์ด๋ฏธ์ง ๋ฒกํฐ๋ ๋ฐ๋์ numpy์ ndarrayํ์์ [๋ฒกํฐ๊ฐ์, ๋ฒกํฐ์ฐจ์์] ํํ๋ก ๊ตฌ์ฑ๋์ด์ผ ํ๋ค!!import faiss dimension = vectors.shape[-1] index = faiss.IndexFlatL2(dimension) if torch.cuda.is_available(): res = faiss.StandardGpuResources() index = faiss.index_cpu_to_gpu(res, 0, index) index.add(vectors) import matplotlib.pyplot as plt search_vector = vectors[0].reshape(1, -1) num_neighbors = 5 distances, indices = index.search(x=search_vector, k=num_neighbors) fig, axes = plt.subplots(1, num_neighbors + 1, figsize=(15, 5)) axes[0].imshow(images[0]) axes[0].set_title("Input Image") axes[0].axis("off") for i, idx in enumerate(indices[0]): axes[i + 1].imshow(images[idx]) axes[i + 1].set_title(f"Match {i + 1}\nIndex: {idx}\nDist: {distances[0][i]:.2f}") axes[i + 1].axis("off") print("์ ์ฌํ ๋ฒกํฐ์ ์ธ๋ฑ์ค ๋ฒํธ:", indices) print("์ ์ฌ๋ ๊ณ์ฐ ๊ฒฐ๊ณผ:", distances) # ์ ์ฌํ ๋ฒกํฐ์ ์ธ๋ฑ์ค ๋ฒํธ: [[ 0 6 75 1 73]] # ์ ์ฌ๋ ๊ณ์ฐ ๊ฒฐ๊ณผ: [[ 0. 43.922516 44.92473 46.544144 47.058586]]
์ ๊ณผ์ ์ ํตํด 100๊ฐ์ ๋ฒกํฐ๋ฅผ ์ ์ฅํ FAISS ์ธ๋ฑ์ค๊ฐ ์์ฑ๋๋ฉฐ, ๊ฒ์ํ๊ณ ์ํ๋ ์ด๋ฏธ์ง์ ํน์ง๋ฒกํฐ๋ฅผ ์ ๋ ฅ์ผ๋ก ์ธ๋ฑ์ค ๋ด์์ ๊ฐ์ฅ ์ ์ฌํ ๋ฒกํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ์ถ์ถ๊ฐ๋ฅํ๋ค.
๋ค๋ง, ์ธ๋ฑ์ค์ ์ ์ฅ๋ ๋ฒกํฐ์ ๋ํด์๋ง ๊ฒ์์ด ๊ฐ๋ฅํ๊ธฐ์ ๊ฒ์๋ฒ์๋ฅผ ํ์ฅํ๊ณ ์ ํ๋ค๋ฉด ๋ ๋ง์ ๋ฒกํฐ๋ฅผ ์ธ๋ฑ์ค์ ์ถ๊ฐํด์ผํ๋ค.์ ์ฝ๋๋ฅผ ๋ณด๋ฉด ์๋์ ๊ฐ์ ์ฝ๋๊ฐ ์๋๋ฐ, FAISS ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์๋ ๋ค์ํ ์ธ๋ฑ์ค์ ํ๋ค์ ์ ๊ณตํ๋ค:
index = faiss.IndexFlatL2(dimension)
์ด๋ฆ ์ ํ๋ ์๋ ํน์ง IndexFlatL2 ๊ฐ์ฅ ๋์ ๊ฐ์ฅ ๋๋ฆผ ๋ชจ๋ ๋ฒกํฐ์ ๋ํ ์์ ํ์์ ์ํ IndexHNSW ๋์ ๋ณดํต ๊ทธ๋ํ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํด ํจ์จ์ ๊ฒ์ IndexIVFlat ๋ณดํต ๊ฐ์ฅ ๋น ๋ฆ ๋ฒกํฐ๊ฐ clustering์ผ๋ก ํ์๋ฒ์๋ฅผ ์ค์ฌ ๊ฒ์
Multi-Modal
Image Captioning (img2txt)
BLIP
BLIP์ ํต์ฌ์์ด๋์ด๋ "img์ Txt์ ์ํธ์์ฉ์ ๋ชจ๋ธ๋งํ๋ ๊ฒ"์ด๋ค.
์ด๋ฅผ ์ํด img-encoder, txt-encoder๋ก ๊ฐ๊ฐ์ feature vector๋ฅผ ์ฐ๊ฒฐํด ํตํฉ ํํ์ ์์ฑํ๋ค.BLIP2๋ Q-Former๋ฅผ ๋์ ํด img-txt๊ฐ ์ํธ์์ฉ๊ณผ ์ ๋ณด๊ตํ์ ํฅ์์์ผฐ๋ค:
[img-txt๋์กฐํ์ต, ITM, img๊ธฐ๋ฐ txt์์ฑ] --> ๋์์ ํ๋์ Encode-Decoder๊ตฌ์กฐ๋ก ์ํ
Q-Former๋ ์ ๋ ฅ์ผ๋ก ๊ณ ์ ๋ ์ด๋ฏธ์ง feature embedding์ ๋ฐ์ ํ
img-txt๊ด๊ณ๊ฐ ์ ํํ๋ Soft visual prompt Embedding์ ์ถ๋ ฅํ๋ค.
DocumentQA
DQA(DocumentQA)๋ ์์ฐ์ด์ฒ๋ฆฌ + ์ ๋ณด๊ฒ์๊ธฐ์ ์ ์ตํฉํด QA๋ฅผ ์งํํ๋ ๊ฒ์ด๋ค.
DQA๋ ์๊ฐ์ ๊ตฌ์กฐ์ Layout์ ๊ณ ๋ คํด์ผํ๋๋ฐ, ์ด ์ค ๊ฐ์ฅ ์ฃผ๋ชฉ๋ฐ๋ ๋ชจ๋ธ ์ค ํ๋๊ฐ ๋ฐ๋ก LayoutLM์ด๋ค.
LayoutLM (Layout-aware Language Model)
LayoutLM์ Microsoft์์ ๋ฌธ์ ์ด๋ฏธ์ง์ txt๋ฟ๋ง์๋๋ผ Layout์ ๋ณด๊น์ง ํจ๊ป Pre-Train๋ ๋ชจ๋ธ์ด๋ค.
[LayoutLMv1]BERT๋ฅผ ๊ธฐ๋ฐ์ผ๋ก txt์ ํจ๊ป txt์ ์์น์ ๋ณด๋ฅผ ์ ๋ ฅ์ผ๋ก ์ฌ์ฉํ๋ค.
Faster R-CNN๊ฐ์ OCR๋ชจ๋ธ๋ก txt์ bbox๊ฒฝ๊ณ๋ฅผ ์ถ์ถ, position embedding์ผ๋ก ์ถ๊ฐํ๋ฉฐ ๋จ์ด์ image patch(feature)๋ model์ ์ ๋ ฅํ๋ค. ๋ค๋ง, LayoutLMv1์ image feature๊ฐ ๋งจ ๋ง์ง๋ง์ ์ถ๊ฐ๋์ด Pretrain์ ์ค์ ๋ก ํ์ฉํ ์ ์๋ค๋ ๋จ์ ์ด ์กด์ฌํ๋ค.
LayoutLMv2๋ image embedding์ ์ถ๊ฐ๋ก ๋์ ํด ๋ฌธ์์ ์๊ฐ์ ์ ๋ณด๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๋ฐ์ํ๋ค.
LayoutLMv2์์ visual embedding์ด ResNeXT-FPN์ผ๋ก ์ถ์ถ๋๋ค.
์ฆ, txt, img-patch, layout์ ๋ณด๋ฅผ ๋์์ ์ ๋ ฅ์ผ๋ก ๋ฐ์ Self-Attention์ ์ํํ๋ค.
- ํ์ต ์ฃผ์ ๋ชฉํ:
i) Masked Visual-Language Modeling: ๋ฌธ์ฅ์ ๋น์นธ ์์ธก
ii) ITM: ํน์ ํ ์คํธ์ ํด๋น ์ด๋ฏธ์ง๊ฐ์ ์ฐ๊ด์ฑ ํ์ต
iii)Text-Image Alignment: ์ด๋ฏธ์ง์์ ํน์ ๋จ์ด๊ฐ ๊ฐ๋ ค์ก์ ๋, ๊ทธ ์์น๋ฅผ ์๋ณํ๋ ๋ฅ๋ ฅ
LayoutLMv3๋ Faster R-CNN, CNN๋ฑ์ Pre-Trained Backbone์ ์์กดํ์ง ์๋ ์ต์ด์ ํตํฉ MLLMs์ด๋ค.
์ด๋ฅผ ์ํด ์ ๊ณผ ๋ฌ๋ฆฌ ์๋ก์ด ์ฌ์ ํ์ต์ ๋ต ๋ฐ ๊ณผ์ ๋ฅผ ๋์ ํ์๋ค:
i) Masked Language Modeling(MLM): ์ผ๋ถ ๋จ์ด token ๋ง์คํน
ii) Masked Image Modeling(MIM): ๋ง์คํน๋ token์ ํด๋นํ๋ ์ด๋ฏธ์ง ๋ถ๋ถ์ ๋ง์คํน
iii) Word Patch Alignment(WPA): img token๊ณผ ๋์๋๋ Txt token์ ๋ง์คํน์ฌ๋ถ๋ฅผ ์ด์ง๋ถ๋ฅ, ๋ ๋ชจ๋ฌ๋ฆฌํฐ๊ฐ ์ ๋ ฌ์ ํ์ต
<LayoutLMv3 ๊ตฌ์กฐ>: embedding๊ณ์ธต, patch_embedding๋ชจ๋, encoder
1) embedding์ธต์ ๋ค์ํ ์ ํ์ Embedding์ ํตํฉ:
- word_embed + token_type_emb + pos_emb + (x_pos_emb , y_pos_emb, h_pos_emb, w_pos_emb)
2) patch_embedding๋ชจ๋์ ์ด๋ฏธ์ง๋ฅผ ์ฒ๋ฆฌ:
- patch๋ก ๋ถํ ํ๊ณ ๊ฐ patch๋ฅผ embedding์ผ๋ก ๋ณํํ๋ ViT์ญํ
3) encoder
- ์ฌ๋ฌ Transformer์ธต์ผ๋ก ๊ตฌ์ฑ.
VQA
VQA process: ์๊ฐ์ ํน์ง ์ถ์ถ → Q์๋ฏธํ์ →์๊ฐ์ ํน์ง๊ณผ Q์ txt์ ๋ณด๋ฅผ ํตํฉํด ์๋ฏธ์๋ ํํ(A)์์ฑ
์ด๋ฅผ ์ํด ๋ฑ์ฅํ ๊ฒ์ด ๋ฐ๋ก ViLT์ด๋ค.
ViLT (Vision-and-Language Transformer)
์๊ฐ์ ์ ๋ ฅ์ txt์ ๋ ฅ๊ณผ ๋์ผํ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํ๋ ๋จ์ผ๋ชจ๋ธ๊ตฌ์กฐ๋ก ๊ตฌ์ฑ๋์ด ์๋ค.
์ด๋, ๋ ๋ชจ๋ฌ๋ฆฌํฐ ๊ตฌ๋ถ์ ์ํด ๋ชจ๋ฌํ์ embedding์ด ์ถ๊ฐ๋๋ฉฐ,
ํ์ต๊ณผ์ ์์ 3๊ฐ์ง ์์คํจ์๋ฅผ ํตํด ์ด๋ค์ง๋ค:
- ITM: ์ฃผ์ด์ง Image์ Text๊ฐ ์๋ก ์ฐ๊ด๋์ด์๋์ง ํ๋จ.
- MLM: ๋จ์ด๋จ์์ Masking์ผ๋ก ์ ์ฒด ๋จ์ด๋งฅ๋ฝ ํ์
- WPA: img-txt๊ฐ ๋ฒกํฐ ์ ์ฌ๋ ์ต๋ํ
๊ฒฐ๊ณผ์ ์ผ๋ก img+txt๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ฒฐํฉํด, ๋จ์ผ embedding๊ณต๊ฐ์ ํํํ๋ค.cf) collate_fn์ pytorch์ dataloader๋ก batch๋ฅผ ๊ตฌ์ฑํ ๋, ๊ฐ sample์ ์ด๋ป๊ฒ ๊ฒฐํฉํ ๊ฒ์ธ์ง ์ ์ํ๋ ํจ์๋ค.
Image Generation
์ด๋ฏธ์ง ์์ฑ์ prompt๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ดํดํ์ฌ GAN์ด๋ Diffusion Model์ ์ด์ฉํด prompt์ ์ธ๋ถ์ ํน์ง์ ์ ์ก์๋ด ์๋ก์ด img๋ฅผ ์์ฑํ๋ ๊ธฐ์ ์ ์๋ฏธํ๋ค.
Diffusion Model
[Forward process]: src_img์ ์ ์ง์ ์ ๊ท๋ถํฌ Noise ์ถ๊ฐ
[Reverse process]: pure_noise์์ ์๋ณธ์ผ๋ก ๋ณต์(by ํ๊ท ๊ณผ ํ์คํธ์ฐจ ๊ฐฑ์ )[Stable-Diffusion 1]
- 512×512 img ์์ฑ
- txt2img, img2img, inpainting ๋ฑ์ ๊ธฐ๋ฅ
[Stable-Diffusion 2]
- 768×768 img ์์ฑ
- OpenCLIP์ผ๋ก ๋ ๋์ WPA ์ ๊ณต, ์ธ๋ถ์ ๋ฌ์ฌ ๊ฐ์
[Stable-Diffusion 3]
- ๋์ฑ ๊ณ ํด์๋ ์ด๋ฏธ์ง ์์ฑ
- Rectified flow๊ธฐ๋ฐ์ ์๋ก์ด ๋ชจ๋ธ๊ตฌ์กฐ
- txt์ img token๊ฐ ์๋ฐฉํฅ ์ ๋ณดํ๋ฆ์ ๊ฐ๋ฅํ๊ฒํ๋ ์๋ก์ด ๋ชจ๋ธ๊ตฌ์กฐ
etc
Hyperparameter Tuning - ray tune
raytune์ ๋ถ์ฐ hypereparameter ์ต์ ํ framework์ด๋ค.
๋๊ท๋ชจ ๋ถ์ฐ์ปดํจํ ํ๊ฒฝ์์ ๋ค์ํ hyperparameter ํ์ ์๊ณ ๋ฆฌ์ฆ(random, greedy ๋ฑ)์ ์ง์ํ๋ฉฐ, Early Stopping ๋ํ ์ ๊ณตํ๋ค.
์ถ๊ฐ์ ์ผ๋ก ์คํ๊ฒฐ๊ณผ ์ถ์ ๋ฐ ์๊ฐํ ๋๊ตฌ ๋ํ ์ ๊ณตํ๋ฉฐ, ์ต์ ์ hyperparameter ์กฐํฉ ๋ํ ํจ๊ณผ์ ์ผ๋ก ์๋ณํ ์ ์๊ฒ ๋์์ค๋ค.
!pip3 install ray[tune] optuna
ex) NER RayTune ์์
i) ํ์ต ์ค๋น
from datasets import load_dataset from transformers import AutoModelForTokenClassification, AutoTokenizer def preprocess_data(example, tokenizer): sentence = "".join(example["tokens"]).replace("\xa0", " ") encoded = tokenizer( sentence, return_offsets_mapping=True, add_special_tokens=False, padding=False, truncation=False ) labels = [] for offset in encoded.offset_mapping: if offset[0] == offset[1]: labels.append(-100) else: labels.append(example["ner_tags"][offset[0]]) encoded["labels"] = labels return encoded dataset = load_dataset("klue", "ner") labels = dataset["train"].features["ner_tags"].feature.names model_name = "Leo97/KoELECTRA-small-v3-modu-ner" tokenizer = AutoTokenizer.from_pretrained(model_name) model = AutoModelForTokenClassification.from_pretrained( model_name, num_labels=len(labels), ignore_mismatched_sizes=True ) processed_dataset = dataset.map( lambda example: preprocess_data(example, tokenizer), batched=False, remove_columns=dataset["train"].column_names )
ii) hyperparameter ํ์from ray import tune from functools import partial from transformers import Trainer, TrainingArguments from transformers.data.data_collator import DataCollatorForTokenClassification def model_init(model_name, labels): return AutoModelForTokenClassification.from_pretrained( model_name, num_labels=len(labels), ignore_mismatched_sizes=True ) def hp_space(trial): return { "learning_rate": tune.loguniform(1e-5, 1e-4), "weight_decay": tune.loguniform(1e-5, 1e-1), "num_train_epochs": tune.choice([1, 2, 3]) } def compute_objective(metrics): return metrics["eval_loss"] training_args = TrainingArguments( output_dir="token-classification-hyperparameter-search", evaluation_strategy="epoch", per_device_train_batch_size=32, per_device_eval_batch_size=32, # learning_rate=1e-4, # weight_decay=0.01, # num_train_epochs=5, seed=42 ) trainer = Trainer( model_init=partial(model_init, model_name=model_name, labels=labels), args=training_args, train_dataset=processed_dataset["train"], eval_dataset=processed_dataset["validation"], data_collator=DataCollatorForTokenClassification(tokenizer=tokenizer, padding=True) ) best_run = trainer.hyperparameter_search( backend="ray", n_trials=5, direction="minimize", hp_space=hp_space, compute_objective=compute_objective, resources_per_trial={"cpu": 2, "gpu": 1}, trial_dirname_creator=lambda trial: str(trial) ) print(best_run.hyperparameters)
model_init ํจ์: ๋ชจ๋ธ ์ธ์คํด์ค ์์ฑ (์ฌ๋ฌ ์คํ์ ํตํด ์ต์ ์ hyperparameter ํ์ํ๊ฒ ํ ๋น๋จ.)
์ฆ, ๊ฐ ์คํ๋ง๋ค ์ผ๊ด๋ ์ด๊ธฐ์ํ๋ฅผ ๋ณด์ฅํจ.
hp_space ํจ์: ์ต์ ํ ๊ณผ์ ์์ ํ์ํ hyperparameter ์ข ๋ฅ์ ๊ฐ์ ๋ฒ์ ์ง์ .
compute_objective ํจ์: ์ต์ ํ ๊ณผ์ ์์ ์ฌ์ฉํ "ํ๊ฐ์งํ"๋ก ๋ณดํต eval_loss๋ eval_acc๋ฅผ ๊ธฐ์ค์ผ๋ก ์ค์ .
TrainingArguments ํจ์: lr, weight_decay, train_epochs๊ฐ hp_space์์ ํ์๋๊ธฐ์ ๋ฐ๋ก ํ ๋นX
Trainer ํจ์: ๊ณ ์ ๋ ๋ชจ๋ธ์ธ์คํด์ค๊ฐ ์๋, model_init์ ์ฌ์ฉ.
์ถ๋ ฅ ์์)+-------------------------------------------------------------------+ | Configuration for experiment _objective_2024-11-18_05-44-18 | +-------------------------------------------------------------------+ | Search algorithm BasicVariantGenerator | | Scheduler FIFOScheduler | | Number of trials 5 | +-------------------------------------------------------------------+ View detailed results here: /root/ray_results/_objective_2024-11-18_05-44-18 To visualize your results with TensorBoard, run: `tensorboard --logdir /tmp/ray/session_2024-11-18_05-44-11_866890_872/artifacts/2024-11-18_05-44-18/_objective_2024-11-18_05-44-18/driver_artifacts` Trial status: 5 PENDING Current time: 2024-11-18 05:44:18. Total running time: 0s Logical resource usage: 0/2 CPUs, 0/1 GPUs (0.0/1.0 accelerator_type:T4) +-------------------------------------------------------------------------------------------+ | Trial name status learning_rate weight_decay num_train_epochs | +-------------------------------------------------------------------------------------------+ | _objective_27024_00000 PENDING 2.36886e-05 0.0635122 3 | | _objective_27024_00001 PENDING 6.02131e-05 0.00244006 2 | | _objective_27024_00002 PENDING 1.43217e-05 1.7074e-05 1 | | _objective_27024_00003 PENDING 3.99131e-05 0.00679658 2 | | _objective_27024_00004 PENDING 1.13871e-05 0.00772672 2 | +-------------------------------------------------------------------------------------------+ Trial _objective_27024_00000 started with configuration: +-------------------------------------------------+ | Trial _objective_27024_00000 config | +-------------------------------------------------+ | learning_rate 2e-05 | | num_train_epochs 3 | | weight_decay 0.06351 | +-------------------------------------------------+ ...
GPTQ (Generative Pre-trained Transformer Quantization)
GPTQ๋ ๋ชจ๋ธ ์ต์ ํ๋ฐฉ์์ผ๋ก LLM์ ํจ์จ์ฑ์ ํฌ๊ฒ ํฅ์๊ฐ๋ฅํ๋ค.
๋ชจ๋ธ์ ๊ฐ์ค์น๋ฅผ ๋ฎ์ bit์ ๋ฐ๋๋ก ์์ํํด ๋ชจ๋ธํฌ๊ธฐ๋ฅผ ์ค์ด๊ณ ์ถ๋ก ์๋๋ฅผ ๋์ธ๋ค.
์๋ ์์ ์ ์ถ๋ ฅ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด ์ ์ ์๋ฏ, ๋ชจ๋ธ ํฌ๊ธฐ๋ฅผ ์๋นํ ํฐ ํญ์ผ๋ก ์ค์ผ ์ ์๋๋ฐ,
GPTQ๋ฐฉ๋ฒ์ GPT๊ณ์ด๋ฟ๋ง ์๋๋ผ ๋ค๋ฅธ Transformer ๊ธฐ๋ฐ ๋ชจ๋ธ๋ค ๋ชจ๋ ์ ์ฉ ๊ฐ๋ฅํ๋ค.
GPTQ๋ฅผ ์ด์ฉํ ๋ชจ๋ธ ์์ํ ์์
from transformers import GPTQConfig from transformers import AutoModelForCausalLM, AutoTokenizer model_name = "facebook/opt-125m" tokenizer = AutoTokenizer.from_pretrained(model_name) quantization_config = GPTQConfig( bits=4, dataset="c4", tokenizer=tokenizer ) quantized_model = AutoModelForCausalLM.from_pretrained( model_name, device_map="auto", quantization_config=quantization_config )
from transformers import pipeline origin_generator = pipeline("text-generation", model="facebook/opt-125m") quantized_generator = pipeline("text-generation", model=quantized_model, tokenizer=tokenizer) input_text_list = [ "In the future, technology wil", "What are we having for dinner?", "What day comes after Monday?" ] print("์๋ณธ ๋ชจ๋ธ์ ์ถ๋ ฅ ๊ฒฐ๊ณผ:") for input_text in input_text_list: print(origin_generator(input_text)) print("์์ํ ๋ชจ๋ธ์ ์ถ๋ ฅ ๊ฒฐ๊ณผ:") for input_text in input_text_list: print(quantized_generator(input_text)) # ์๋ณธ ๋ชจ๋ธ์ ์ถ๋ ฅ ๊ฒฐ๊ณผ: # [{'generated_text': 'In the future, technology wil be used to make the world a better place.\nI think'}] # [{'generated_text': 'What are we having for dinner?\n\nWe have a great dinner tonight. We have a'}] # [{'generated_text': "What day comes after Monday?\nI'm guessing Monday."}] # ์์ํ ๋ชจ๋ธ์ ์ถ๋ ฅ ๊ฒฐ๊ณผ: # [{'generated_text': 'In the future, technology wil be able to make it possible to make a phone that can be'}] # [{'generated_text': "What are we having for dinner?\n\nI'm not sure what to do with all this"}] # [{'generated_text': "What day comes after Monday?\nI'm not sure, but I'll be sure to check"}]
์ถ๋ ฅ๊ฒฐ๊ณผ, ์ ํ๋๊ฐ ๋ค์ ๋จ์ด์ง๊ธด ํ๋ ์๋ณธ๋ชจ๋ธ๊ณผ ํฐ ์ฐจ์ด๊ฐ ์์์ ํ์ธํ ์ ์๋ค.
import time import numpy as np def measure_inference_time(generator, input_text, iterations=10): times = [] for _ in range(iterations): start_time = time.time() generator(input_text) end_time = time.time() times.append(end_time - start_time) avg_time = np.mean(times) return avg_time def calculate_model_size(model): total_params = sum(p.numel() for p in model.parameters()) total_memory = sum(p.numel() * p.element_size() for p in model.parameters()) total_memory_mb = total_memory / (1024 ** 2) return total_memory_mb, total_params test_input = "Once upon a time in a land far, far away, there was a small village." size_original, total_params_original = calculate_model_size(origin_generator.model) avg_inference_time_original = measure_inference_time(origin_generator, test_input) size_quantized, total_params_quantized = calculate_model_size(quantized_generator.model) avg_inference_time_quantized = measure_inference_time(quantized_generator, test_input) print("์๋ณธ ๋ชจ๋ธ:") print(f"- ๋งค๊ฐ๋ณ์ ๊ฐ์: {total_params_original:,}") print(f"- ๋ชจ๋ธ ํฌ๊ธฐ: {size_original:.2f} MB") print(f"- ํ๊ท ์ถ๋ก ์๊ฐ: {avg_inference_time_original:.4f} sec") print("์์ํ ๋ชจ๋ธ:") print(f"- ๋งค๊ฐ๋ณ์ ๊ฐ์: {total_params_quantized:,}") print(f"- ๋ชจ๋ธ ํฌ๊ธฐ: {size_quantized:.2f} MB") print(f"- ํ๊ท ์ถ๋ก ์๊ฐ: {avg_inference_time_quantized:.4f} sec") # ์๋ณธ ๋ชจ๋ธ: # - ๋งค๊ฐ๋ณ์ ๊ฐ์: 125,239,296 # - ๋ชจ๋ธ ํฌ๊ธฐ: 477.75 MB # - ํ๊ท ์ถ๋ก ์๊ฐ: 0.1399 sec # ์์ํ ๋ชจ๋ธ: # - ๋งค๊ฐ๋ณ์ ๊ฐ์: 40,221,696 # - ๋ชจ๋ธ ํฌ๊ธฐ: 76.72 MB # - ํ๊ท ์ถ๋ก ์๊ฐ: 0.0289 sec
์ถ๋ก ๊ณผ์ ์ ๋ํ ์ถ๋ ฅ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด, ์๋ณธ์ ๋นํด ๋ชจ๋ธ์ ๋นํด ํฌ๊ธฐ๊ฐ ํฌ๊ฒ ์ค๋ฉฐ ๋ ๋น ๋ฅธ ์ฒ๋ฆฌ๋ฅผ ํตํด ์ค์๊ฐ ์๋ต์ ๋ํด ๋งค์ฐ ํจ์จ์ ์ผ ์ ์์์ ํ์ธ๊ฐ๋ฅํ๋ค.
'HuggingFace๐ค' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
HuggingFace(๐ค)-Tutorials (1) | 2024.07.31 |
---|---|
[Data Preprocessing] - Data Collator (1) | 2024.07.14 |
QLoRA ์ค์ต & Trainer vs SFTTrainer (0) | 2024.07.12 |
[QLoRA] & [PEFT] & deepspeed, DDP (0) | 2024.07.09 |