• transformer 구조을 알기 위해서는 attention is all you need라는 논문을 보면된다.
  • transformer 구조는 아래그림과 같다.

 

  • 여기서 정리할것들
    • self attention
    • multi head attention
    • feed forward
    • add & Norm

 

1. Self Attention

 

참조 (아래 더보기 클릭)

  • 위의 구조가 self-attention의 핵심구조이다.
  • (MASK 모듈은 생성형 AI에 주로 쓰이니 생략해도 된다고 함)

 

<self attention 설명>

  • embedding_dimension이 d_model
  • I love you가 입력 x 이고  가로는 d_m or d_model이라고 부를거고 세로는 T개라고 명명하겠음
  • wq,wk,wv는 파라미터
  • Q,K,V는 X(입력벡터시퀀스)에 WQ,Wk,WV를 곱해서 구해준다.
  • WQ,Wk,WV는 Task(예: 기계 번역)를 가장 잘 수행하는 방향으로 학습 과정에서 업데이트됨
  • QK^T를 곱한 이유는 각 단어와 단어간의 상관관계를 보기위해서
    • Q의 (0,0) K의 (0,0)를 곱한숫자는 I와 I간의 상관관계가 어느정도인지 나타낸것과 같다고 볼 수 있다.
    • dk^1/2를 나눠주는 이유는 숫자가 극단적으로 갈수있는것을 예방하여 smoothing 한것과 동일하게 이해하면 된다
  • softmax를 적용한이유는 0-1사이의 숫자로 나타내주기위함
  • softmax(QK^T)를 해준다음 V를 곱한것의 의미는
    • I love you라는 문장에 각 i,love,you와의 상관관계를 적용해준것과 같다.
    • 예를들어서 배를 먹었더니 배가 아프다 라는 문장에서 먹는배와 , 신체 배의 차이를 극대화하는 과정과 같다. 먹었다,아프다 라는단어와의 상관관계를 분석하여 배라는 단어가 어떤것에 더 가까운지 확실히하는 과정이라고 생각하면 된다.
  • 위사진에서 4, embedding dimension이 의미하는것은?
    • 자연어처리에서는 단어가 들어오면 단어를 토큰화하고, word embedding을 통해서 벡터화한다.
      • 어떤흐름으로 진행되는지는 아래 그림을 참조
      • integer부분이 토큰화, lookup table에서 한줄 뽑아온것(위그림의 단어별로 존재하는 리스트) 바로 임베딩 벡터를 의미한다.

⇒ 한마디로 이과정은 각각의 단어들을 비교해서 문맥을 파악하고, 벡터표현값을 업데이트하는 과정

 

< 헷갈리는것들 >

여기서 간과하면 안되는점 : Wq의 크기는 d_model x d_model이다. (Tx d_model) x (d_model*d_model) 이렇게 행렬곱셈을 하면 결과값 크기도 input과 동일한 T x d_model이 나옴

 

<추가설명>

  • 위사진에서 4, embedding dimension이 의미하는것은?
    • 자연어처리에서는 단어가 들어오면 단어를 토큰화하고, word embedding을 통해서 벡터화한다.
      • 어떤흐름으로 진행되는지는 아래 그림을 참조하자
      • 아래그림에서 integer부분이 토큰화, lookup table에서 한줄 뽑아온것(위그림의 단어별로 존재하는 리스트) 바로 임베딩 벡터를 의미한다.

 

 

2. Multihead attention

 

참조 (아래 더보기 클릭)

위 그림이 논문에 나온 그림이다.

 

  • h는 사용자가 직접 정해준다. 멀티헤드를 몇개로 지정해줄것인가를 뜻한다.
  • h(멀티헤드 갯수)를 직접 정해주지않으면 디폴트값은 12개이다.
  • 앞에서 self attention으로 구한 블럭을 가로로 나란히 h개 붙인다
  • 그다음, w0 행렬에 곱해서 linear하게 재정렬한다.
  • 한마디로 맨위에서 wo랑 곱하는 과정이 concat
  • concat를 해서 리니어하게 재정렬 된다는것을 의미한다.
  • transformer paper에서 w0는 가로세로 길이가 같음 (d0=dv*h)

 

 

참조 : https://medium.com/analytics-vidhya/understanding-bert-architecture-3f35a264b187

위 링크에서 보면 keras_bert로 multihead attention이 끝나고 파라미터수가 Bert는 인코더수가 12개이기 때문에 encoder-1의 multihead self attnetion의 파라미터수가 2,362,368개가 나오는지 계산해보자

import keras
from keras_bert import get_base_dict, get_model, compile_model, gen_batch_inputs

model = get_model(
    token_num=30000,
    head_num=12,
    transformer_num=12,
    embed_dim=768,
    feed_forward_dim=3072,
    seq_len=500,
    pos_num=512,
    dropout_rate=0.05
)
model.summary()

  • parameter를 구하기위해서는 위에서 wq,wk,wv랑 w0의 수를 모두 더해주면된다.
  • 일반적으로 self-attention에서는 w1q크기가 d_model x d_model이지만 여기서는 multihead attention이기 떄문에 d_model x d_model/h 로 구성되게 된다.
    • 위의 예제에서 dm = 768, h=12로 지정해준 상태이다.
    • 그렇다면 wq의 크기는 768*64 근데 이게 k,v,q 이렇게 3개가 있으니까 3을 곱해주고, 헤드가 12개니까 12도 곱해준다.
    • 그런데 바이어스도 더해줘야한다고함..
    • 그렇다면 wq,wv,wk의 모든 파라미터갯수는 76864312+7683
    • w0은 쉽다. d_model x d_model인데 여기도 바이어스값을 더해줘야한다고
      • 그래서 768*768 + 768
    • 모두다 더해주면 2362368개의 파라미터수가 나온다!

 

 

3. Layer Norm

 

  • 그림에서는 norm이 multihead 다음, 피드 포워드 다음에 진행되지만 최근 LLM모델들은 전부 norm을 먼저 진행한다고 한다 (최근은 순서가 반대라고함)
    • 실제로 아래 BERT모델을 보면 Layer norm을 먼저하고나서 multihead attention을 진행한다.

  • 먼저 딥러닝을 진행할때 activation function에서 input데이터들이 너무 왼쪽이나 너무 오른쪽에 붙으면 문제가 생김
  • 그걸 방지하고자 nomarlization을 진행, 이때 정규화분포의 모양과 위치는 감마와 베타가 결정함.

  • Multihead attention을 적용하기 전에 normalization을 적용
  • 세로 한줄 한줄씩 정규화하여 감마와 베타값도 구함.
  • 이렇게 정규화한 값들을 가지고 멀티헤드 어텐션을 구함
  • 원본과 멀티헤드 어텐션으로 나온값을 더해준다.

 

 

4. Feed Forward

참조 (아래 더보기 클릭)

여기까지 싹하고나면, 아래 그림은 인코더 부분을 정리해서 나타낸 그림.

 

 

이것도 파라미터수가 feed forward후에 왜 4722432개 나오는 이유를 보자

 

'<개념> > Deep learning' 카테고리의 다른 글

What is Agent Force?  (0) 2024.11.03
LLAMA Inference  (0) 2024.05.17
T5 inference in inferentia  (0) 2024.04.08
openai gpt3 inference in inferentia2(neruon)  (0) 2024.03.28
GPT2 Text-generation을 AWS환경의 GPU/CPU/Inf2/Trn1에서..  (1) 2024.01.29

LLAMA 너무 커서 inf2.24large에서 시작하기 (허깅 페이스 토큰도 만들어야함)

AMI : Deep Learning AMI Neuron PyTorch 1.13 (Ubuntu 20.04) 20231003

source /opt/aws_neuron_venv_pytorch/bin/activate
pip3 install transformers-neuronx --extra-index-url=https://pip.repos.neuron.amazonaws.com
pip3 install optimum
pip3 install -U "huggingface_hub[cli]"
huggingface-cli login

 

llama 사용권한요청1 : https://llama.meta.com/llama-downloads/

llama 사용권한요청2 : https://huggingface.co/meta-llama/Llama-2-7b-hf

코드1

from transformers import AutoTokenizer, LlamaForCausalLM
from huggingface_hub import login

login("본인 허깅페이스 토큰~")

model = LlamaForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf")
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")

prompt = "Hey, are you conscious? Can you talk to me?"
inputs = tokenizer(prompt, return_tensors="pt")

# Generate
generate_ids = model.generate(inputs.input_ids, max_length=30)
output = tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
print(output)

코드2

import time
import torch
from transformers import AutoTokenizer
from transformers_neuronx import LlamaForSampling
from huggingface_hub import login

login("본인토큰")
  
# load meta-llama/Llama-2-13b to the NeuronCores with 24-way tensor parallelism and run compilation
neuron_model2 = LlamaForSampling.from_pretrained('meta-llama/Llama-2-7b-chat-hf', batch_size=1, tp_degree=12, amp='f16')
neuron_model2.to_neuron() 

# construct a tokenizer and encode prompt text
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-chat-hf")

prompt = ["Hello, I'm a language model,"]
#input_ids = tokenizer.encode(prompt, return_tensors="pt")
encoded_input = tokenizer(prompt, return_tensors='pt')

# run inference with top-k sampling
with torch.inference_mode():
    start = time.time()
    generated_sequences = neuron_model2.sample(encoded_input.input_ids, sequence_length=128, top_k=50)
    elapsed = time.time() - start

generated_sequences = [tokenizer.decode(seq) for seq in generated_sequences]
print(f'generated sequences {generated_sequences} in {elapsed} seconds')

https://awsdocs-neuron.readthedocs-hosted.com/en/latest/src/examples/pytorch/torch-neuronx/t5-inference-tutorial.html

source /opt/aws_neuron_venv_pytorch/bin/activate
pip install transformers-neuronx --extra-index-url=https://pip.repos.neuron.amazonaws.com
pip install --upgrade transformers==4.31.0 optimum-neuron==0.0.8
pip install torch_xla

AMI는

코드는 아래 더보기 누르기~

더보기
import torch
import datetime


from transformers.models.t5.modeling_t5 import T5Stack, T5LayerCrossAttention

class EncoderWrapper(torch.nn.Module):
    '''
        We will trace an instance of the EncoderWrapper.
        This wrapper just converts positional args to kwargs.
    '''

    def __init__(self,
                 encoder,
                 decoder,
                 model_config,
                 batch_size,
                 max_length,
                 device,
                 num_beams,
                 tp_degree=None):

        super().__init__()
        self.encoder = encoder
        self.decoder = decoder
        self.batch_size = batch_size
        self.max_length = max_length
        self.model_config = model_config
        self.device = device
        self.num_beams = num_beams
        self.num_attention_heads_per_partition = model_config.num_heads
        self.tp_degree = tp_degree

    def forward(self, input_ids, attention_mask):
        '''
            This is the core functionality we want to trace.
        '''
        encoder_output =  self.encoder(input_ids=input_ids,
                                       attention_mask=attention_mask,
                                       output_attentions=False,
                                       output_hidden_states=False)

        last_hidden_state = encoder_output["last_hidden_state"]
        encoder_hidden_states = torch.concat([tensor.unsqueeze(0).repeat(self.num_beams, 1, 1) for tensor in last_hidden_state])

        decoder_blocks = self.decoder.block
        present_key_value_states_sa = []
        present_key_value_states_ca = []

        for i, block in enumerate(decoder_blocks):

            # Cross attention has to be initialized with the encoder hidden state
            cross_attention: T5LayerCrossAttention = block.layer[1]
            attention = cross_attention.EncDecAttention

            def shape(states):
                """projection"""
                return states.view(self.batch_size, -1, self.num_attention_heads_per_partition, attention.key_value_proj_dim).transpose(1, 2)

            key_states = shape(attention.k(encoder_hidden_states))
            value_states = shape(attention.v(encoder_hidden_states))

            # cross_attn_kv_state
            present_key_value_states_ca.append(key_states)
            present_key_value_states_ca.append(value_states)

            # Self attention kv states are initialized to zeros. This is done to keep the size of the kv cache tensor constant.
            # The kv cache will be an input to the decoder trace. Any traced function will have a fixed control flow. What this means
            # is that the trace performs the exact same computations on inputs of the same shape in each invocation. So the attention
            # kv cache is padded here to keep a fixed shape.
            present_key_value_states_sa.append(torch.zeros((self.batch_size,                                                     # key states
                                                            self.model_config.num_heads,
                                                            self.max_length-1,
                                                            self.model_config.d_kv), dtype=torch.float32, device=self.device))
            present_key_value_states_sa.append(torch.zeros((self.batch_size,                                                     # value states
                                                            self.model_config.num_heads,
                                                            self.max_length-1,
                                                            self.model_config.d_kv), dtype=torch.float32, device=self.device))

        return present_key_value_states_sa + present_key_value_states_ca


class DecoderWrapper(torch.nn.Module):

    def __init__(self,
                 decoder: T5Stack,
                 lm_head: torch.nn.Linear,
                 model_config,
                 num_beams: int,
                 max_length: int,
                 device: str,
                 tp_degree=None):
        super().__init__()
        self.decoder = decoder
        self.lm_head = lm_head
        self.model_dim=model_config.d_model
        self.device = device
        self.num_beams = num_beams
        self.batch_size = 1
        self.config = model_config

        num_heads=model_config.num_heads
        num_decoder_layers=model_config.num_decoder_layers

        self.num_attention_heads_per_partition = num_heads

        # (num_beams, n_heads, seq_length, dim_per_head)
        if device == "cpu":
            self.past_key_values_sa = [torch.ones((num_beams,num_heads,max_length-1,model_config.d_kv), dtype=torch.float32) for _ in range(num_decoder_layers * 2)]
            self.past_key_values_ca = [torch.ones((num_beams,num_heads,max_length,model_config.d_kv), dtype=torch.float32) for _ in range(num_decoder_layers * 2)]
        elif device == "xla":
            self.past_key_values_sa = torch.nn.ParameterList([torch.nn.Parameter(torch.ones((num_beams,self.num_attention_heads_per_partition,max_length-1,model_config.d_kv), dtype=torch.float32), requires_grad=False) for _ in range(num_decoder_layers * 2)])
            self.past_key_values_ca = torch.nn.ParameterList([torch.nn.Parameter(torch.ones((num_beams,self.num_attention_heads_per_partition,max_length,model_config.d_kv), dtype=torch.float32), requires_grad=False) for _ in range(num_decoder_layers * 2)])

    def update_past(self, past_key_values):
        new_past_sa = []
        new_past_ca = []
        for past_layer in past_key_values:
            new_past_layer = list(past_layer)
            for i in range(len(new_past_layer[:2])):
                new_past_layer[i] = past_layer[i][:, :, 1:]
            new_past_sa += [new_past_layer[:2],]
            new_past_ca += [new_past_layer[2:],]
        return new_past_sa, new_past_ca

    def reorder_cache(self, past_key_values, beam_idx):
        for i in range(len(past_key_values)):
            gather_index = beam_idx.view([beam_idx.shape[0],1,1,1]).expand_as(past_key_values[i])
            past_key_values[i] = torch.gather(past_key_values[i], dim = 0, index=gather_index)
        return past_key_values

    def forward(self,
                input_ids,
                decoder_attention_mask,
                encoder_hidden_states,
                encoder_attention_mask,
                beam_idx,
                beam_scores,
                **kwargs):

        if self.num_beams > 1:
            # We reorder the cache based on the beams selected in each iteration. Required step for beam search.
            past_key_values_sa = self.reorder_cache(self.past_key_values_sa, beam_idx)
            past_key_values_ca = self.reorder_cache(self.past_key_values_ca, beam_idx)
        else:
            # We do not need to reorder for greedy sampling
            past_key_values_sa = self.past_key_values_sa
            past_key_values_ca = self.past_key_values_ca

        # The cache is stored in a flatten form. We order the cache per layer before passing it to the decoder.
        # Each layer has 4 tensors, so we group by 4.
        past_key_values = [[*past_key_values_sa[i*2:i*2+2], *past_key_values_ca[i*2:i*2+2]] for i in range(0, int(len(past_key_values_ca)/2))]

        decoder_output = self.decoder(
            input_ids=input_ids,
            attention_mask=decoder_attention_mask,
            past_key_values=past_key_values,
            encoder_hidden_states=encoder_hidden_states,
            encoder_attention_mask=encoder_attention_mask,
            use_cache=True,
            output_attentions=False,
            output_hidden_states=False)

        last_hidden_state = decoder_output['last_hidden_state']
        past_key_values = decoder_output['past_key_values']

        if self.config.tie_word_embeddings:
            # Rescale output before projecting on vocab
            # See https://github.com/tensorflow/mesh/blob/fa19d69eafc9a482aff0b59ddd96b025c0cb207d/mesh_tensorflow/transformer/transformer.py#L586
            last_hidden_state = last_hidden_state * (self.model_dim**-0.5)

        lm_logits = self.lm_head(last_hidden_state)

        past_key_values_sa, past_key_values_ca = self.update_past(past_key_values)

        # We flatten the cache to a single array. This is required for the input output aliasing to work
        past_key_values_sa = [vec for kv_per_layer in past_key_values_sa for vec in kv_per_layer]
        past_key_values_ca = [vec for kv_per_layer in past_key_values_ca for vec in kv_per_layer]

        if self.device == "cpu":
            self.past_key_values_sa = past_key_values_sa
            self.past_key_values_ca = past_key_values_ca

        # We calculate topk inside the wrapper
        next_token_logits = lm_logits[:, -1, :]

        if self.num_beams > 1:
            # This section of beam search is run outside the decoder in the huggingface t5 implementation.
            # To maximize the computation within the neuron device, we move this within the wrapper
            logit_max, _ = torch.max(next_token_logits, dim=-1, keepdim=True)
            logsumexp = torch.log(torch.exp(next_token_logits - logit_max).sum(dim=-1, keepdim=True))
            next_token_scores = next_token_logits - logit_max - logsumexp
            next_token_scores = next_token_scores + beam_scores[:, None].expand_as(next_token_scores)

            # reshape for beam search
            vocab_size = next_token_scores.shape[-1]
            next_token_scores = next_token_scores.view(self.batch_size, self.num_beams * vocab_size)
            next_token_scores = next_token_scores * 1

            # Sample 2 next tokens for each beam (so we have some spare tokens and match output of beam search)
            next_token_scores, next_tokens = torch.topk(
                next_token_scores, 2 * self.num_beams, dim=1, largest=True, sorted=True
            )

            next_indices = torch.div(next_tokens, vocab_size, rounding_mode="floor")
            next_tokens = next_tokens % vocab_size

            return [next_token_scores, next_tokens, next_indices] + past_key_values_sa + past_key_values_ca
        else:
            # Greedy
            next_tokens = torch.argmax(next_token_logits, dim=-1)
            return [next_tokens] + past_key_values_sa + past_key_values_ca

import torch
import torch_xla.core.xla_model as xm

from transformers import T5Tokenizer, T5ForConditionalGeneration
from transformers.modeling_outputs import BaseModelOutput, Seq2SeqLMOutput
from transformers.models.t5.modeling_t5 import T5Stack, T5LayerCrossAttention
from transformers.generation.utils import ModelOutput
from typing import Any, Dict, List, Optional, Tuple, Union
from transformers.generation.beam_search import BeamScorer, BeamSearchScorer

from optimum.neuron.generation import NeuronGenerationMixin

from transformers.generation.logits_process import (
    LogitsProcessorList,
)
from transformers.generation.stopping_criteria import (
    MaxLengthCriteria,
    MaxTimeCriteria,
    StoppingCriteriaList,
    validate_stopping_criteria,
)

from transformers.generation.utils import (
    BeamSearchOutput,
    GreedySearchOutput,
)

class T5Wrapper(T5ForConditionalGeneration, NeuronGenerationMixin):

    def _prepare_encoder_decoder_kwargs_for_generation(
        self,
        inputs_tensor: torch.Tensor,
        model_kwargs,
        model_input_name: Optional[str] = None
    ) -> Dict[str, Any]:
        encoder = self.get_encoder()
        model_kwargs["encoder_outputs"]: ModelOutput = encoder(inputs_tensor, model_kwargs["attention_mask"])
        return model_kwargs

    # Override to cut the input_ids to just last token
    def prepare_inputs_for_generation(
        self,
        input_ids,
        past_key_values=None,
        attention_mask=None,
        head_mask=None,
        decoder_head_mask=None,
        decoder_attention_mask=None,
        cross_attn_head_mask=None,
        use_cache=None,
        encoder_outputs=None,
        **kwargs,
    ):
        # cut decoder_input_ids as past is cached
        input_ids = input_ids[:, -1:]

        return {
            "decoder_input_ids": input_ids,
            "past_key_values": past_key_values,
            "encoder_outputs": encoder_outputs,
            "attention_mask": attention_mask,
            "head_mask": head_mask,
            "decoder_head_mask": decoder_head_mask,
            "decoder_attention_mask": decoder_attention_mask,
            "cross_attn_head_mask": cross_attn_head_mask,
            "use_cache": use_cache,
        }

    '''
        We update the cache in the decoder trace, so lets override the _update_model_kwargs_for_xla_generation in NeuronGenerationMixin
    '''
    def _update_model_kwargs_for_xla_generation(
        self,
        model_kwargs: Dict[str, Any],
        batch_size: int,
        is_encoder_decoder: bool = False,
        standardize_cache_format: bool = False,
        max_length: Optional[int] = None,
        seq_length: Optional[int] = None,
        use_cache: bool = True,
    ) -> Dict[str, Any]:

        def _update_attention(model_kwargs, is_encoder_decoder):
            """Updates the appropriate attention mask -- encoder-decoder models use `decoder_attention_mask`"""

            attention_mask_name = "decoder_attention_mask" if is_encoder_decoder else "attention_mask"
            attention_mask = model_kwargs.pop(attention_mask_name)
            attention_mask_update_slice = torch.ones(
                (batch_size, 1), dtype=attention_mask.dtype, device=attention_mask.device
            )
            attention_mask = torch.cat([attention_mask[:, 1:], attention_mask_update_slice], dim=-1)
            mask = {attention_mask_name: attention_mask}
            return mask

        mask = _update_attention(model_kwargs, is_encoder_decoder)
        # sets the updated variables (mask and past_key_values)
        model_kwargs.update(mask)

        # Set a mock cache tensor
        model_kwargs["past_key_values"] = torch.tensor([])

        return model_kwargs

    def _reorder_cache(self, past_key_values, beam_idx):
        '''
            This is needed for beam search and not greedy sampling
            We reorder the cache within the trace so we can skip it in modelling_t5.py. So we override the _reorder_cache
        '''
        self.beam_idx = beam_idx
        return past_key_values

    def generate(self,
                tokenizer: T5Tokenizer,
                prompt: str,
                max_length: int,
                num_beams: int,
                num_return_sequences: int,
                device: str):

        batch_encoding = tokenizer(prompt, max_length=max_length, truncation=True, padding='max_length',
                                return_tensors="pt")

        past_key_values = self.encoder(batch_encoding['input_ids'],batch_encoding['attention_mask'])

        decoder_attention_mask = torch.cat([torch.zeros((1, max_length-1), dtype=torch.int32),
                                            torch.ones((1, 1), dtype=torch.int32)], axis=1)

        # copy the new cache state to the decoder
        if device == "xla":
            for state, tensor in zip(self.decoder.parameters(), past_key_values):
                state.copy_(tensor)
        else:
            # First half of the cache is self attention and the rest is cross attention
            self.decoder.past_key_values_sa = past_key_values[:len(past_key_values)//2]
            self.decoder.past_key_values_ca = past_key_values[len(past_key_values)//2:]

        output = super().generate(**batch_encoding,
                                max_length=max_length,
                                num_beams=num_beams,
                                num_return_sequences=num_return_sequences,
                                do_sample=False,
                                use_cache=True,
                                decoder_attention_mask=decoder_attention_mask,
                                encoder_outputs={"last_hidden_state": torch.ones((1,128,1))}) # Pass fake encoder_outputs so the transfomers code will not invoke the encoder
        return output

    def forward(
        self,
        attention_mask: Optional[torch.FloatTensor] = None,
        decoder_input_ids: Optional[torch.LongTensor] = None,
        decoder_attention_mask: Optional[torch.BoolTensor] = None,
        encoder_outputs: Optional[Tuple[Tuple[torch.Tensor]]] = None,
        beam_scores = None,
        **kwargs
    ) -> Union[Tuple[torch.FloatTensor], Seq2SeqLMOutput]:

        hidden_states = encoder_outputs["last_hidden_state"]

        if not hasattr(self, 'beam_idx'):
            # Infering the number of beams from the attention mask
            num_beams = attention_mask.shape[0]
            self.beam_idx = torch.arange(0, num_beams, dtype=torch.int64)

        decoder_outputs = self.decoder(
            decoder_input_ids,
            decoder_attention_mask,
            hidden_states,
            attention_mask,
            self.beam_idx,
            beam_scores
        )

        # lm_logits = decoder_outputs[0]
        next_token_scores = decoder_outputs[0]
        next_tokens = decoder_outputs[1]
        next_indices = decoder_outputs[2]

        return next_token_scores, next_tokens, next_indices

    def beam_search(
        self,
        input_ids: torch.LongTensor,
        beam_scorer: BeamScorer,
        logits_processor: Optional[LogitsProcessorList] = None,
        stopping_criteria: Optional[StoppingCriteriaList] = None,
        max_length: Optional[int] = None,
        pad_token_id: Optional[int] = None,
        eos_token_id: Optional[Union[int, List[int]]] = None,
        output_attentions: Optional[bool] = None,
        output_hidden_states: Optional[bool] = None,
        output_scores: Optional[bool] = None,
        return_dict_in_generate: Optional[bool] = None,
        synced_gpus: Optional[bool] = False,
        seq_length: Optional[int] = None,
        **model_kwargs,
    ) -> Union[BeamSearchOutput, torch.LongTensor]:

        logits_processor = logits_processor if logits_processor is not None else LogitsProcessorList()
        stopping_criteria = stopping_criteria if stopping_criteria is not None else StoppingCriteriaList()
        pad_token_id = pad_token_id if pad_token_id is not None else self.generation_config.pad_token_id
        eos_token_id = eos_token_id if eos_token_id is not None else self.generation_config.eos_token_id
        if isinstance(eos_token_id, int):
            eos_token_id = [eos_token_id]
        output_scores = output_scores if output_scores is not None else self.generation_config.output_scores
        output_attentions = (
            output_attentions if output_attentions is not None else self.generation_config.output_attentions
        )
        output_hidden_states = (
            output_hidden_states if output_hidden_states is not None else self.generation_config.output_hidden_states
        )

        batch_size = len(beam_scorer._beam_hyps)
        num_beams = beam_scorer.num_beams

        batch_beam_size, cur_len = input_ids.shape

        # Overwrite cur_len
        cur_len = seq_length

        if num_beams * batch_size != batch_beam_size:
            raise ValueError(
                f"Batch dimension of `input_ids` should be {num_beams * batch_size}, but is {batch_beam_size}."
            )

        # init attention / hidden states / scores tuples
        scores = () if (return_dict_in_generate and output_scores) else None
        beam_indices = (
            tuple(() for _ in range(batch_beam_size)) if (return_dict_in_generate and output_scores) else None
        )

        # initialise score of first beam with 0 and the rest with -1e9. This makes sure that only tokens
        # of the first beam are considered to avoid sampling the exact same tokens across all beams.
        # beam_scores = torch.zeros((batch_size, num_beams), dtype=torch.float, device=input_ids.device)
        beam_scores_device = "cpu"
        beam_scores = torch.zeros((batch_size, num_beams), dtype=torch.float, device=beam_scores_device)
        beam_scores[:, 1:] = -1e9
        beam_scores = beam_scores.view((batch_size * num_beams,))

        while True:
            # prepare model inputs
            # From max_length-sized input_ids, select first
            # cur_len - 1 values.
            update_indices = torch.stack(
                [torch.arange(input_ids.size(0)), torch.tensor(cur_len - 1).repeat(input_ids.size(0))], dim=-1
            )
            input_ids_ = input_ids[update_indices[:, 0], update_indices[:, 1], None]
            model_inputs = self.prepare_inputs_for_generation(input_ids_, **model_kwargs)

            next_token_scores, next_tokens, next_indices = self(
                **model_inputs,
                return_dict=True,
                output_attentions=output_attentions,
                output_hidden_states=output_hidden_states,
                beam_scores=beam_scores
            )

            # stateless
            beam_outputs = beam_scorer.process(
                input_ids.to("cpu")[:, :cur_len],
                next_token_scores.to("cpu"),
                next_tokens.to("cpu"),
                next_indices.to("cpu"),
                pad_token_id=pad_token_id,
                eos_token_id=eos_token_id,
                beam_indices=beam_indices,
            )

            beam_scores = beam_outputs["next_beam_scores"]
            beam_next_tokens = beam_outputs["next_beam_tokens"]
            beam_idx = beam_outputs["next_beam_indices"]

            update_indices = torch.stack(
                [torch.arange(batch_beam_size), torch.tensor(cur_len - 1).repeat(batch_beam_size)], dim=-1
            )
            update_indices_2 = torch.stack(
                [torch.arange(batch_beam_size), torch.tensor(cur_len).repeat(batch_beam_size)], dim=-1
            )
            # First select beam_indices
            device = input_ids.device
            beam_idx_device = beam_idx.to(device=input_ids.device)
            input_ids[:, :] = input_ids[beam_idx_device.long(), :]

            # Then append new tokens
            input_ids[update_indices_2[:, 0], update_indices_2[:, 1], None] = beam_next_tokens.unsqueeze(-1).to(device).to(torch.long)
            input_ids = input_ids * 1  # Hack to materialize tensor

            # update generated ids, model inputs, and length for next step
            model_kwargs = self._update_model_kwargs_for_xla_generation(
                model_kwargs,
                batch_size=batch_beam_size,
                is_encoder_decoder=self.config.is_encoder_decoder,
                max_length=stopping_criteria.max_length,
                seq_length=cur_len,
                use_cache=model_kwargs["use_cache"],
            )
            if model_kwargs["past_key_values"] is not None:
                model_kwargs["past_key_values"] = self._reorder_cache(model_kwargs["past_key_values"], beam_idx.to(torch.int64))

            if return_dict_in_generate and output_scores:
                beam_indices = tuple((beam_indices[beam_idx[i]] + (beam_idx[i],) for i in range(len(beam_indices))))

            # increase cur_len
            cur_len = cur_len + 1

            # stop when each sentence is finished, or if we exceed the maximum length
            stop_criterion_1 = beam_scorer.is_done
            if isinstance(stopping_criteria, list):
                if len(stopping_criteria) == 1:
                    stopping_criteria = stopping_criteria[0]

            # Cases that can be handled in XLA without requiring
            # non-padded input_ids
            if isinstance(stopping_criteria, MaxLengthCriteria):
                stop_criterion_2 = cur_len >= stopping_criteria.max_length
            elif isinstance(stopping_criteria, MaxTimeCriteria):
                stop_criterion_2 = stopping_criteria(input_ids, scores)
            else:
                # Other cases will be handled on CPU
                batch_size, _ = input_ids.shape
                input_ids_cpu = input_ids.to("cpu")
                mask = torch.cat(
                    [torch.ones(batch_size, cur_len), torch.zeros(batch_size, input_ids.shape[1] - cur_len)], dim=1
                ).bool()
                input_ids_cpu = torch.masked_select(input_ids_cpu, mask).reshape((batch_size, cur_len))
                scores_cpu = scores.to("cpu") if torch.is_tensor(scores) else scores
                stop_criterion_2 = stopping_criteria(input_ids_cpu, scores_cpu)

            if stop_criterion_1 or stop_criterion_2:
                if not synced_gpus:
                    break
                else:
                    this_peer_finished = True

        sequence_outputs = beam_scorer.finalize(
            input_ids.to("cpu"),
            beam_scores.to("cpu"),
            next_tokens.to("cpu"),
            next_indices.to("cpu"),
            pad_token_id=pad_token_id,
            eos_token_id=eos_token_id,
            max_length=stopping_criteria.max_length,
            beam_indices=beam_indices,
        )

        for k, v in sequence_outputs.items():
            if type(v) == torch.Tensor:
                sequence_outputs[k] = sequence_outputs[k].to(input_ids.device)

        return sequence_outputs["sequences"]


    def greedy_search(
        self,
        input_ids: torch.LongTensor,
        logits_processor: Optional[LogitsProcessorList] = None,
        stopping_criteria: Optional[StoppingCriteriaList] = None,
        max_length: Optional[int] = None,
        pad_token_id: Optional[int] = None,
        eos_token_id: Optional[Union[int, List[int]]] = None,
        output_attentions: Optional[bool] = None,
        output_hidden_states: Optional[bool] = None,
        output_scores: Optional[bool] = None,
        return_dict_in_generate: Optional[bool] = None,
        seq_length: Optional[int] = int,
        streamer: Optional["BaseStreamer"] = None,
        **model_kwargs,
    ) -> Union[GreedySearchOutput, torch.LongTensor]:
        """
            Overriding greedy sampling to use next tokens returned from neuron device instead of logits.
        """
        # init values
        logits_processor = logits_processor if logits_processor is not None else LogitsProcessorList()
        use_cache = model_kwargs["use_cache"] if "use_cache" in model_kwargs else False
        stopping_criteria = stopping_criteria if stopping_criteria is not None else StoppingCriteriaList()
        pad_token_id = pad_token_id if pad_token_id is not None else self.generation_config.pad_token_id
        eos_token_id = eos_token_id if eos_token_id is not None else self.generation_config.eos_token_id
        if isinstance(eos_token_id, int):
            eos_token_id = [eos_token_id]
        eos_token_id_tensor = torch.tensor(eos_token_id).to(input_ids.device) if eos_token_id is not None else None
        output_scores = output_scores if output_scores is not None else self.generation_config.output_scores
        output_attentions = (
            output_attentions if output_attentions is not None else self.generation_config.output_attentions
        )
        output_hidden_states = (
            output_hidden_states if output_hidden_states is not None else self.generation_config.output_hidden_states
        )

        # init attention / hidden states / scores tuples
        scores = () if (return_dict_in_generate and output_scores) else None
        decoder_attentions = () if (return_dict_in_generate and output_attentions) else None
        cross_attentions = () if (return_dict_in_generate and output_attentions) else None
        decoder_hidden_states = () if (return_dict_in_generate and output_hidden_states) else None


        # keep track of which sequences are already finished
        unfinished_sequences = torch.ones(input_ids.shape[0], dtype=torch.long, device=input_ids.device)

        this_peer_finished = False  # used by synced_gpus only
        while True:

            # prepare model inputs
            # From max_length-sized input_ids, select first
            # seq_length - 1 values.

            if model_kwargs.get("past_key_values") is None:
                input_ids_ = input_ids[:, :seq_length]
            else:
                update_indices = torch.stack(
                    [torch.arange(input_ids.size(0)), torch.tensor(seq_length - 1).repeat(input_ids.size(0))],
                    dim=-1,
                )
                input_ids_ = input_ids[update_indices[:, 0], update_indices[:, 1], None]

            model_inputs = self.prepare_inputs_for_generation(input_ids_, **model_kwargs)

            # forward pass to get next token
            output = self(
               **model_inputs,
                return_dict=True,
                output_attentions=output_attentions,
                output_hidden_states=output_hidden_states,
            )
            next_tokens = output[0]

            # finished sentences should have their next token be a padding token
            if eos_token_id is not None:
                if pad_token_id is None:
                    raise ValueError("If `eos_token_id` is defined, make sure that `pad_token_id` is defined.")
                next_tokens = next_tokens * unfinished_sequences + pad_token_id * (1 - unfinished_sequences)

            # update generated ids, model inputs, and length for next step

            batch_size, _ = input_ids.shape
            update_indices = torch.stack(
                [torch.arange(batch_size), torch.tensor(seq_length).repeat(batch_size)], dim=-1
            )
            input_ids[update_indices[:, 0], update_indices[:, 1]] = next_tokens[:]
            model_kwargs = self._update_model_kwargs_for_xla_generation(
                model_kwargs,
                batch_size=batch_size,
                is_encoder_decoder=self.config.is_encoder_decoder,
                max_length=stopping_criteria.max_length,
                seq_length=seq_length,
                use_cache=use_cache,
            )

            seq_length += 1

            # if eos_token was found in one sentence, set sentence to finished
            if eos_token_id_tensor is not None:
                unfinished_sequences = unfinished_sequences.mul(
                    next_tokens.tile(eos_token_id_tensor.shape[0], 1).ne(eos_token_id_tensor.unsqueeze(1)).prod(dim=0)
                )

            # stop when each sentence is finished, or if we exceed the maximum length
            stop_criterion_1 = unfinished_sequences.max() == 0

            if isinstance(stopping_criteria, list):
                if len(stopping_criteria) == 1:
                    stopping_criteria = stopping_criteria[0]

            # Cases that can be handled in XLA without requiring
            # non-padded input_ids
            if isinstance(stopping_criteria, MaxLengthCriteria):
                stop_criterion_2 = seq_length >= stopping_criteria.max_length
            elif isinstance(stopping_criteria, MaxTimeCriteria):
                stop_criterion_2 = stopping_criteria(input_ids, scores)
            else:
                # Other cases will be handled on CPU
                batch_size, _ = input_ids.shape
                mask = torch.cat(
                    [torch.ones(batch_size, seq_length), torch.zeros(batch_size, input_ids.shape[1] - seq_length)],
                    dim=1,
                ).bool()
                input_ids_cpu = torch.masked_select(input_ids, mask).reshape((batch_size, seq_length)).to("cpu")
                scores_cpu = scores.to("cpu") if torch.is_tensor(scores) else scores
                stop_criterion_2 = stopping_criteria(input_ids_cpu, scores_cpu)

            if stop_criterion_1 or stop_criterion_2:
                this_peer_finished = True

            if this_peer_finished:
                break

        if streamer is not None:
            streamer.end()

        return input_ids


# Let's set some run parameters

model_name = "t5-large"
num_beams = 1
num_return_sequences = 1
max_length = 128

from transformers import T5Tokenizer


prompt="translate English to German: Lets eat good food."

tokenizer = T5Tokenizer.from_pretrained(model_name, model_max_length=max_length)
model = T5Wrapper.from_pretrained(model_name)

model.encoder = EncoderWrapper(model.encoder, model.decoder, model.config, num_beams, max_length, "cpu", num_beams)
setattr(model.encoder, 'main_input_name', 'input_ids')  # Attribute required by beam search

model.decoder = DecoderWrapper(decoder=model.decoder,
                                lm_head=model.lm_head,
                                model_config=model.config,
                                num_beams=num_beams,
                                max_length=max_length,
                                device="cpu")
start = datetime.datetime.now()
output = model.generate(tokenizer=tokenizer,
                        prompt=prompt,
                        max_length=max_length,
                        num_beams=num_beams,
                        num_return_sequences=num_return_sequences,
                        device="cpu")
end = datetime.datetime.now()
total = end - start
print("Execution time: ", total)

results = [tokenizer.decode(t, skip_special_tokens=True) for t in output]

print('Results:')
for i, summary in enumerate(results):
    print(i + 1, summary)

 

import openai

openai.api_key = 'mykey'

response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role": "user", "content": "Hello, I'm a language model,"}
    ]
)
print(response['choices'][0]['message']['content'])

 

< setting>

AMI : Deep Learning AMI Neuron PyTorch 1.13 (Ubuntu 20.04) 20240102

인스턴스 : Inf2.xlarge

source /opt/aws_neuron_venv_pytorch/bin/activate

pip install transformers-neuronx --extra-index-url=https://pip.repos.neuron.amazonaws.com

python3 sample.py

 

 

**코드 참조 : https://platform.openai.com/docs/guides/rate-limits/error-mitigation?context=tier-free 

**코드 참조 2 : 챗지피티4

** openai에서 사용가능한 모델 : https://platform.openai.com/docs/models/overview

첨에 RateLimitError 에러가 나서 limit 확인

https://platform.openai.com/docs/guides/rate-limits/usage-tiers?context=tier-free

 

RateLimitError 해결해볼라고 14000원 결제도 함..

1. GPU / CPU

 

GPU AMI : 

 

CPU AMI : 그냥 ubuntu 20.0 서버

 

참조 : https://github.com/huggingface/transformers/tree/main/examples/pytorch/text-generation

sudo apt-get update
pip3 install accelerate
pip3 install transformers
pip3 install torch
git clone https://github.com/huggingface/transformers.git

cd transformers/examples/pytorch/text-generation

python3 run_generation_inf2.py --model_type gpt2 --model_name_or_path gpt2 --num_return_sequences 1 --prompt="“Hello, I’m a language model,”:" --temperature 0.7

 **  --model_name_or_path gpt2 이부분을 gpt2, gpt2-medium, gpt2-large, gpt2-xl, openai-gpt 로 바꿔줄 수 있음

 

2. Inf2.xlarge / Trn1.2xlarge

 

AMI : Neruon + Pytorch + ubuntu 20.0 조합 아무거나

( Deep Learning AMI Neuron PyTorch 1.13 (Ubuntu 20.04) 20240102 )

참조 : https://awsdocs-neuron.readthedocs-hosted.com/en/latest/libraries/transformers-neuronx/transformers-neuronx-developer-guide.html

source /opt/aws_neuron_venv_pytorch/bin/activate
pip install transformers-neuronx --extra-index-url=https://pip.repos.neuron.amazonaws.com
from transformers_neuronx.gpt2.model import GPT2ForSampling
from transformers_neuronx.generation_utils import HuggingFaceGenerationModelAdapter
from transformers_neuronx.module import save_pretrained_split
from transformers import AutoModelForCausalLM, AutoTokenizer
import datetime

# Load and save the CPU model
model_cpu = AutoModelForCausalLM.from_pretrained('gpt2-xl')
save_pretrained_split(model_cpu, 'gpt2-split')

# Create and compile the Neuron model
model_neuron = GPT2ForSampling.from_pretrained('gpt2-split', batch_size=1, tp_degree=2, n_positions=256, amp='f32', unroll=None)
model_neuron.to_neuron()

# Use the `HuggingFaceGenerationModelAdapter` to access the generate API
model = HuggingFaceGenerationModelAdapter(model_cpu.config, model_neuron)

# Get a tokenizer and exaple input
tokenizer = AutoTokenizer.from_pretrained('gpt2-xl')
tokenizer.pad_token_id = tokenizer.eos_token_id
tokenizer.padding_side = 'left'
text = "Hello, I'm a language model,"
encoded_input = tokenizer(text, return_tensors='pt', padding=True)

# Run inference using temperature
model.reset_generation()
start = datetime.datetime.now()
sample_output = model.generate(
    input_ids=encoded_input.input_ids,
    attention_mask=encoded_input.attention_mask,
    do_sample=True,
    max_length=20,
    temperature=0.7,
)
end = datetime.datetime.now()
total = end - start
print("Execution time: ", total)
print([tokenizer.decode(tok) for tok in sample_output])

위 코드 포함하는 sample.py 생성

** 저 코드에서 gpt2-xl 이부분도 gpt2, gpt2-medium, gpt2-large, gpt2-xl 로 바꿔줄수 있음

Python3 sample.py

 

 

첫번째시도(실패)

- hugging face에서 제공하는 pytorch 코드로 돌리면 손을좀 봐야한다. 이유는 해당코드가 gpu/cpu 전용으로 만들어졌기 때문. 

( https://github.com/huggingface/transformers/blob/main/examples/pytorch/text-generation/run_generation.py )

- torch.jit.trace와 torch_neuron.trace는 모두 PyTorch 모델을 최적화하여 pytorch 모델을 TorchScript로 바꿔주는데 사용함. 그런데 전자는 cpu/gpu 용도이고 후자가 inferentia용으로 Nueron 호환 형식으로 변환. 그래서 후자로 변환해줘야함

- 변환해줘도 뉴런코어의 사용률이 0%

 

두번째시도(성공)

- hugging face 를 베이스로한 다른 추론코드를 찾음. 뉴런코어를 잘 사용함. ( https://awsdocs-neuron.readthedocs-hosted.com/en/latest/libraries/transformers-neuronx/transformers-neuronx-developer-guide.html )

- 사용한 aws ami : AMI : Deep Learning AMI Neuron PyTorch 1.13 (Ubuntu 20.04) 20240102

- 아래 실행해주면됨.

# 참조 : https://github.com/aws-neuron/transformers-neuronx
pip install transformers-neuronx --extra-index-url=https://pip.repos.neuron.amazonaws.com
source /opt/aws_neuron_venv_pytorch/bin/activate
python3 sample.py

- 모니터링 참조는 https://awsdocs-neuron.readthedocs-hosted.com/en/latest/tools/neuron-sys-tools/neuron-monitor-user-guide.html

neuron-monitor -c monitor.conf >> output.json

 

Luminol을 알려면 Bitmap이 뭔지를 알아야함 (깃허브 살펴보면, bitmap 논문 참조했다고 주석에 나옴 http://alumni.cs.ucr.edu/~ratana/KumarN.pdf)

<1차이해>

우선 Bitmap은 카오스게임방식으로 패턴을 나타낸다. 이것은 단순한 숫자를 문자로 변환하여 패턴을 한눈에 살펴볼수 있도록 하는 알고리즘입니다. 하지만 이 알고리즘을 적용하기위해서는 이산 시퀀스형태로 만들어야하는데 우리가 사용하고자 하는 데이터는 시계열 실수 데이터. 이런 시계열 데이터를 이산 시퀀스로 변환해주는것이 바로 SAX알고리즘입니다 SAX 알고리즘은 타임시리즈 실수 데이터를 동일한 크기의 구간으로 나눕니다. 나눈 구간의 평균값을 계산한다음 그 구간을 전부다 그 평균값으로 대체해버리는 방식으로 타임시리즈 데이터를 이산시퀀스로 변환해줍니다. 그리하여 연속된 실수값 타임시리즈값을 → 일정 구간으로 나누어 평균값으로 바꾸어버려 이산시퀀스로 만들고 → 구간별로 baabccbc같은 문자로 패턴을 얻을수 있다. → 얻어낸 문자패턴을 카오스게임에 적용하여 시각화할수 있습니다.

anomaly detection을 하는방법은 다음과 같습니다. 1) 타임시리즈는 lead 윈도우와 lag 윈도우로 나뉜다. 두개의 크기는 다를수 있으며 lead window는 예측하고자하는 window, lag window는 선행 윈도우로 대체적으로 lead window이전의값을 의미합니다. 이 각각의 window에 속한 타임시리즈는 앞에서처럼 sax알고리즘을 사용하여 문자열로 바꾸고 → 문자열로 바꾼값을 quad tree안에 집어넣어서 정리하여 두개의 bitmap를 생성합니다.→ 두개 비트맵사이의 거리는 아래식으로 구합니다. (이 구한 숫자가 바로 이상탐지값이고, 이 숫자 높을수록 이상치값이 높다고 판단합니다.) 이 과정을 쭉 반복하면서 이상치값을 구하고 새롭게 구한 이상치값으로 재구성한 그래프를 내놓은게 바로 luminol 입니다.

 

코드를 살펴본결과 Luminol울 수행할때 lead window, lag window 의 디폴트 크기는 전체 데이터 길이의 0.2/16 즉 약 1.25% 를 차지하도록 설정해줍니다. 그리고 너무 작은 데이터사이즈나 너무 큰 데이터 사이즈의 경우를 대비해서 min,max사이즈도 정해두었습니다. 아래코드처럼 chunk_size(=윈도우크기)를 사용자가 직접 설정하지 않으면 디폴트값으로 진행되는것으로 확인하였습니다.

그리고 lag window와 future_window(=lead window)값을 비교하는 함수를 살펴보니 위논문에서 구한 식과 동일한것을 확인하였습니다.

 

<2차이해>

 

더욱 구체적인 예제로는 https://www.researchgate.net/publication/249889424_Time-series-bitmap_Based_Approach_to_Analyze_Human_Postural_Control_and_Movement_Detection_Strategies_during_Small_Anterior_Perturbations 논문과, luminol github에서 참조하였다는 bitmap논문의 이전버전 논문인 http://alumni.cs.ucr.edu/~ratana/KumarN.pdf 를 참조하였습니다.

  1. 슬라이딩 윈도우방식으로 타임시리즈데이터를 처음부터 2개윈도우창으로 나누어서 끝까지 훝는다. 2개 window는 Lag window와 Lead window(github에서는 future 윈도우)
  2. SAX알고리즘을 통해 타임시리즈 데이터를 문자열로 만들어줍니다. (연속된 실수를 일정단위별로 끊어서 평균값을 구하고 계단형으로 변환, 그 변환된것을 문자열로 변경
  3. 아래 예제에서는 4*4 크기 윈도우를 사용하였고 aaaaaaaa에서 aa가 8개 존재하기 때문에 aa항에 7을 넣어줍니다. aaaa의 경우는 aa가 3개 있기 때문에 aa항에 3을 넣어줍니다.
  4. 이 윈도우를 0-1사이의값으로 변환해줍니다. 왼쪽 figure에서는 0-white, 1-black으로 변환해준다라고 표현하였고, 오른쪽 figure에서는 normalize한다라고 표현하였습니다.
  5. 0-1로 재구성한 4*4그래프 2개값을 가지고 score를 구합니다. 오른쪽 figure를 기준으로 살펴보면 aaaaaaaa 와 aaa의 차이는(lagwindow-futurewindow)^2로 구하며 (1-1)^2=0으로 anomaly score이 0입니다.

github에서 소개하는 bitmap 논문의 이전 버전 논문을 찾아낸본결과(http://alumni.cs.ucr.edu/~ratana/KumarN.pdf) normalize해서 색깔별로 나타내보면 다음과같이 비슷한 타임시리즈 데이터일수록 매우 흡사한 컬러배치를 보인다는것을 알수 있습니다.

moving average가 가장 평균적으로 많이 쓰이는 smoothing 방식입니다. 이는 주어진 데이터 전/후의 일정 개수의 데이터의 평균이나 중간값을 그 데이터의 값으로 추정하는 방법입니다. 그에 반해 savgol filter은 특정구간의 평균/중간값이 아니라, 특정구간을 ax^2 + bx + c 같은 회귀모델을 이용한 smoothing을 수행합니다.

xi의 새로운 값은 양쪽 근방 2n+1 개의 점으로 다항식 회귀한 식으로부터 다시 추정해 내는 것이 핵심 아이디어입니다. 즉, xi 를 포함하고 있는 양쪽 근방 2n+1 개의 점으로 다항식 회귀한 식 Si을 찾고, Si(xi)로 xi 를 대체하는 것입니다. (** 2n+1인이유는 오른쪽으로 n개, 왼쪽으로 n개 , xi 1개해서 2n+1로 셉니다. 그래서 윈도우 갯수는 홀수입니다.) 아래 그림을 예제로 들면 25값을 기준으로 오른쪽으로3개 왼쪽으로3개값을 떼서 7개 데이터를 윈도우로 떼서 봅니다. 7개데이터를 가지고 회귀곡선을 새롭게 그린다음 25에 해당하는 Y값을 새로이 지정해줍니다.

여기서 가장 큰 문제는 xi를 구하기위해 앞뒤 데이터들을 합친 2n+1개 윈도우를 떼서 새로이 다항회귀식(si)를 재구성하는것입니다.

(출처 : https://eigenvector.com/wp-content/uploads/2020/01/SavitzkyGolay.pdf)

Si 회귀함수를 구하고, 그에 맞는 새로운값을 구하는과정은 아래와같이 구해질수 있습니다.

 

 

1) 일단 내 계정으로 접속

2) sudo -i 로 root 계정으로 변환하기

3) sudo useradd [newuser_name] 로 사용자추가 해주기

3) su - [newuser_name] 로 신규 유저계정으로 접속

4) 아무것도 없어서 그냥 mkdir ~/.ssh   + vi authorized_keys 로 파일 생성해주기

5) new user한테 rsa키 ( ~/.ssh/id_rsa.pub) 받아서 복붙넣어주기

6) new user가 이제 서버에 ssh 접속할수 있음 끝~

stackingregressor 은 이미 있는 모델들 여러개를 합쳐서 사용하는 메타모델

 

sequential로 만든 모델을 그대로 넣어주면 에러남.

 

1. 아래처럼 KerasRegressor 로 감싸주고 집어넣어줘야함.

2. 맨위에 import KerasRegressor 설치&추가해주면됨.

 

from keras.wrappers.scikit_learn import KerasRegressor
from sklearn.ensemble import StackingRegressor

from keras.wrappers.scikit_learn import KerasRegressor
dnn_estimator = KerasRegressor(build_fn=build_dnn_model(epochs=300, batch_size=16, verbose=1))
estimators = [('br', linear_model.BayesianRidge()),('dnn',dnn_estimator)]
reg = StackingRegressor(estimators=estimators,final_estimator=RandomForestRegressor(n_estimators=10,random_state=42))
reg.fit(train_x, train_y)
reg_pred = reg.predict(test_x).reshape(-1, 1)

 

데이터는 kaggle 주택데이터 사용했고 데이터 다운은 아래 더보기 클릭 

 

X      = train_data[features]
y      = np.log1p(train_data["SalePrice"]) # log1p !!!!!!!!!!!
X_test = test_data[features]
y_true = solution["SalePrice"]
import pandas as pd
import numpy  as np
from pytorch_tabnet.tab_model import TabNetRegressor
from sklearn.model_selection import KFold

pd.set_option('display.max_columns', None) # dataframe 잘림없이 출력
pd.set_option('display.max_rows', None)
pd.set_option('display.max_seq_items', None) # 리스트 잘림없이 출력
pd.options.display.float_format = '{:.5f}'.format  # e, 지수없이 출력
pd.set_option('display.max_colwidth', -1) #pd로 볼때 ...없이 출력
import warnings # warning 무시
warnings.filterwarnings('ignore')
pd.set_option('mode.chained_assignment',  None) # SettingWithCopyWarning 경고끄기
train_data = pd.read_csv('./train.csv')
test_data  = pd.read_csv('./test.csv')
sample     = pd.read_csv('./sample_submission.csv')
solution   = pd.read_csv('./solution.csv')

print(len(train_data))
print(len(test_data))
print(len(sample))
print(len(solution))
features = ['LotArea', 'OverallQual', 'OverallCond', 'YearBuilt', 
            'YearRemodAdd', 'BsmtFinSF1', 'BsmtFinSF2', 'TotalBsmtSF', 
            '1stFlrSF', 'LowQualFinSF', 'GrLivArea', 'BsmtFullBath', 
            'BsmtHalfBath', 'HalfBath', 'BedroomAbvGr',  'Fireplaces', 
            'GarageCars', 'GarageArea', 'WoodDeckSF', 'OpenPorchSF', 
            'EnclosedPorch',  'PoolArea', 'YrSold']
X      =      X.apply(lambda x: x.fillna(x.mean()),axis=0)
X_test = X_test.apply(lambda x: x.fillna(x.mean()),axis=0)

X      = X.to_numpy()
y      = y.to_numpy().reshape(-1, 1)
X_test = X_test.to_numpy()

# 결측지 해결
X = np.nan_to_num(X) 
X_test = np.nan_to_num(X_test) 
y = np.nan_to_num(y) 
y_true = np.nan_to_num(y_true)
kf = KFold(n_splits=5, random_state=42, shuffle=True) # 5개로 나누기
predictions_array = []
predictions_array2 = []
CV_score_array    = []
for train_index, test_index in kf.split(X): # train_index는 kfold1회에서 train조합, test_index는 테스트조합
    X_train, X_valid = X[train_index], X[test_index]  # train,valid 조합을 나나눠줌
    y_train, y_valid = y[train_index], y[test_index]  # y도 마찬가지
    regressor = TabNetRegressor(verbose=0,seed=42) # 모델정의
    regressor.fit(X_train=X_train, y_train=y_train, # fit + eval_set 추가
              eval_set=[(X_valid, y_valid)],
              patience=300, max_epochs=2000, #patience=성능이좋지않은 epoch 300번이상 반복되면 그마해라
              eval_metric=['rmse'])
    CV_score_array.append(regressor.best_cost) # 5회반복중에 가장좋은점수 저장저장
    predictions_array.append(np.expm1(regressor.predict(X_test)))
predictions = np.mean(predictions_array,axis=0)
print("The CV score is %.5f" % np.mean(CV_score_array,axis=0) ) # cv score 평균값
# from sklearn.metrics import mean_squared_log_error
# RMSLE = np.sqrt( mean_squared_log_error(y_true, predictions) )
# print("The LB score is %.5f" % RMSLE )

def mape(y_test, pred):
    y_test, pred = np.array(y_test), np.array(pred)
    mape = np.mean(np.abs((y_test - pred) / y_test))
    return mape

print(mape(y_true, predictions)*100)

 

 

여기서 y값에 log1p해주고 마지막에 expm1 해주는이유가 궁금했는데

 

 

Q. log말고 log1p해주는 이유?

로그그래프는 아래 그림처럼 0에 가까운 매우 작은수의 경우 무한 음수로 바뀜. 그래서 데이터보면 -Inf상태로 바뀌는걸 볼수가 있음. 그래서 이걸 방지하기 위해 1을 더해주어 방지하는것임.

Q. 굳이 log 씌워서 진행하는 이유?

데이터가 어떤 구간에 엄청 몰려있는 경우가 있음. 이럴때 log를 씌워주면 정규분포 비슷한 형태로 만들어줄수가 있음. 데이터 불균형을 풀어주기위한 방법

 

 

 

 

참조 

 

'<개념> > 기타' 카테고리의 다른 글

FPGA, NPU 초간단 개념  (0) 2022.02.28
푸리에 변환 초간단 정리  (0) 2022.01.30
SHIFT 개념 이해하기 예제 with SIN/COS/TAN  (0) 2021.12.30
자주나오는 이산수학관련 내용  (0) 2021.11.28
RestfulAPI 개념정리  (0) 2021.08.14

1. .DS_Store 파일이 이미 존재하는경우

~ Documents/GItHub/레포이름

터미널에 해당주소로 이동한다음,

find . -name .DS_Store -print0 | xargs -0 git rm --ignore-unmatch -f

 

그다음에 변경된내용(DS_Store파일 삭제) PUSH

 

 

2. 앞으로 DS_Store 파일 생성안하게 설정

터미널 열고 다음입력

defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool TRUE

 

 

 

 

 

 

 

 

참조

 

DTW(Dynamic time warping) :

  • 속도가 다른 2개 시계열 패턴이 들어올때 유사성을 측정하는 알고리즘
  • 0에 가까울수록 그래프가 유사하다고 볼수있음 (0이면 동일한 그래프)
  • 주로 음성인식에 사용됨(두개 목소리를 비교해서 동일인지 확인)
  • 장점 : 두개 매트릭의 길이가 달라도 비교가 가능

 

ED(Euclidean distance) :

  • 유클리드 거리는 정의에 따라 두 시계열 샘플의 해당 관측치 간에 일대일 매핑을 시행하는 두 벡터 간의 유사도 측정에 널리 사용됨
  • 단점 : 두개 간에 길이가 다를경우 오차가 엄청크게 나올수 있음.
  • 이방법을 사용하기위해서는 두개 매트릭을 1) 정규화해주고 2)길이도 맞추어주어야한다.

 

LCSS(Longest common subsequence) 2016

  • 유사성 임계값을 정의하고 결정해서 시계열 유사성을 측정하도록 개발
  • 장점 : 길이차이가 많이나는 시계열에 대해서도 우수한 결과를 보여줌
  • 단점 : 임계값에 따라 결과가 천차만별이 될수있다.

 

DLCSS(Developed Longest Common Subsequence) (2020년)

  • LCSS가 오래된 방법이다보니 더 업데이트한 버전,LCSS, DTW보다 우수하다고 주장
  • 1-Nearest Neighbor 및 k-medoids 클러스터링 기술을 사용

 

TLCC(Time Lagged Cross correlation) & windowed TLCC (2015)

  • 하나의 time series 를 조금씩 shifting 시키면서 데이터 전체 범위에 대해서 pearson 상관계수를 계산하여 나타낸다. pearson,kendal 과는 다르게 두 데이터 사이에서의 인과관계를 파악할수 있다고함.
  • 단점으로는 신호가 동시에 발생함, 데이터가 유사함이라는 기본전제를 깔고간다.
  • 시간에 따라 상세하게 분석을 원한다면 windowed TLCC 를 사용하면 된다고함 ( 데이터를 여러개의 window 로 나눠서 TLCC 분석을 각 window 마다 행함
  •  

 

commit은 내 컴퓨터 로컬파일에 변경내용 표시 (노트북내)

push는 깃허브 로컬파일이 해당된 리포지토리에 변경내용 표시 (깃허브 웹페이지)

 

 

Fork 는 복사

clone은 인터넷의 레포지토리와 내 컴퓨터의 파일이랑 연동시키는걸 의미

 

[Github] Repository 만들기 (2가지방법)

1. 깃허브에서 직접 만들기 + 깃허브 데스크탑이랑 연동

2.  Github Desktop에서 리포지터리

 

 

<사용방법>

1. master - develop - branch1, branch2 .... 이렇게만들고 develop브랜치를 마스터처럼 관리하기

(커밋삭제할떄 마스터보다 브랜치가 훨 간단하고 쉽다/ 머지시킨후 삭제시 골치아프기 때문에)

2. 이슈 발행 ( #넘버 확인하고)

3. 커밋할떄 #넘버 (내용)이렇게 쓰고~

4. 이슈에 에러적으면 다같이 공유하고 해답찾기 가능

5. 마일스톤이라고 만들어놓고 이슈옆 택으로 달아놓으면 좋음 ( 중간평가1, 중간평가2, 이렇게)

1. reset  - <돌아가고싶은 커밋>을 HEAD로 두고 그 후에 커밋된내용 싹다 삭제 

 

$ git reset <선택사항3종> <돌아가고싶은 커밋>

$ git reset --hard a4bef7f

돌아가려는 커밋이후 모든내용 삭제

 

soft, mixed도 있다.

 

 

git reset --hard a05d5bf
git push -f origin feature/web

이런식으로 a05d5bf부분이 head로 저부분은 사라지지않는다 head다음 커밋들이 싹다 되돌려진다.

feature/web은 브랜치 이름이다.

(그리고 꼭 push해주기!)

 

이래서 꼭 origin에 푸시하지말고 깃허브 쓸떄 origin - develop 브랜치를 파서 develop을 기점으로 작업하고 origin은 배포할때만 쓰라는건가보다

 

 

 

2. revert - revert이력이 남음 (DELETE했다고 커밋이 남음)

 

$ git revert <되돌릴 커밋> 

git revert a4bef7f

 단점: 하나하나 revert해주려면 귀찮다. + 단계별로 순서대로 revert해줘야한다.

 

 

 

ㄴ이런 merge됬다는 커밋은 에러가 난다.

 

 

 

3. github desktop - 간편간편

-> revert기록이남음

 

*************************************************************************************************************

깃 명령어 실행하는 방법은

해당 리포지토리의 로컬파일을 연다음 거기에 Git Bash 를 열고 실행해준다. 

git branch (브랜치위치 확인)

git checkout 이동하고자하는 브랜치이름

get reset --hard 49ce4ad 

요렇게 적어주면 된다.

 

 

sudo apt update
sudo apt install python3.7  # 일단 설치부터

update-alternatives --config python3
(에러나오는게 정상)
which python3.7  #위치 다시한번 확인

sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.7 1
-> python을 치면 3.7 을 기본으로 하라는 뜻
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.7 1
=> python3을 치면 3.7 을 기본으로 하라는 뜻

ㄴ원래 python3 버전이 3.6이였던게 지정해준뒤로 3.7로 바뀐걸 확인

+ Recent posts