Peer Session Badge

1. assignment #2 풀이

입력층, 하나의 은닉층(hidden layer), 그리고 출력층으로 구성된다.

1. 클래스 초기화 및 파라미터 초기화

클래스 TwoLayerNN는 초기화 메서드 __init__와 파라미터 초기화 메서드 initialize_parameters를 가지고 있다.

  • __init__ 메서드: 신경망의 입력 차원(input_dim), 은닉 유닛의 수(num_hiddens), 그리고 클래스의 수(num_classes)를 초기화하고, 이들을 바탕으로 신경망의 가중치와 bias를 초기화한다.

  • initialize_parameters 메서드: Xavier Initialization 방법을 이용해 가중치와 바이어스를 초기화한다. Xavier 초기화는 각 가중치가 정규분포를 따르도록 초기화하여 학습이 잘 진행되도록 돕는다.

2. Forward Pass

Forward pass는 입력 데이터를 신경망에 통과시켜 예측값을 생성하는 과정이다.

  • forward 메서드에서는 입력 데이터 X를 은닉층과 출력층에 통과시켜 최종 예측 y를 계산한다.
  • 입력 데이터 X는 첫 번째 가중치(W1)와 바이어스(b1)에 의해 변환된 후, 시그모이드(sigmoid) 활성화 함수를 거쳐 은닉층의 출력을 생성한다.
  • 이 출력은 다시 두 번째 가중치(W2)와 바이어스(b2)에 의해 변환되고, 마지막으로 소프트맥스(softmax) 함수를 통해 최종 예측 확률이 계산된다.
  • 이 과정에서 ff_dict라는 딕셔너리에 중간 값들을 저장하여 나중에 역전파(backpropagation) 과정에서 사용할 수 있도록 한다.

3. Backward Pass (Backpropagation)

Backward pass는 예측값과 실제값의 차이를 기반으로 가중치와 바이어스를 업데이트하는 과정이다.

  • backward 메서드는 신경망의 각 파라미터에 대한 그라디언트(gradient)를 계산합니다. 이 그라디언트를 사용해 파라미터를 업데이트하면 신경망이 예측을 점점 더 정확하게 하도록 학습한다.
  • 그라디언트는 체인 룰(chain rule)을 사용하여 출력층부터 역순으로 계산된다. 이 과정에서 앞서 저장한 ff_dict의 값들이 사용된다.

4. 파라미터 업데이트 (Gradient Descent)

Gradient Descent는 가중치와 바이어스를 업데이트하는 최적화 기법이다.

  • train_step 메서드는 학습률(lr)을 사용해 계산된 그라디언트를 바탕으로 가중치와 바이어스를 업데이트한다. 신경망이 점차적으로 더 나은 예측을 하게 된다.

5. 손실 함수 및 정확도 평가

신경망의 성능을 평가하기 위해 손실 함수와 정확도를 계산한다.

  • compute_loss 메서드는 예측값과 실제값 간의 엔트로피 손실(cross-entropy loss)을 계산한다. 이 값은 모델이 얼마나 잘 예측하고 있는지 나타낸다.

  • evaluate 메서드는 신경망의 분류 정확도를 계산합니다. 이는 모델이 얼마나 정확하게 클래스를 예측하고 있는지를 퍼센트로 나타낸다.

6. 모델 학습

Training은 신경망이 주어진 데이터를 학습하도록 만드는 과정이다.

  • train 메서드는 주어진 학습 데이터와 검증 데이터에 대해 여러 번의 반복(에포크)을 통해 모델을 학습시킨다. 이 과정에서 미니 배치 경사 하강법(mini-batch gradient descent)을 사용하여 성능을 개선해 나간다.

코드의 주요 개념

  • Xavier 초기화: 학습을 원활히 하기 위한 가중치 초기화 방법.
  • Forward Pass: 입력 데이터를 신경망에 통과시켜 예측값을 계산하는 과정.
  • Backward Pass (Backpropagation): 예측값의 오류를 기반으로 가중치와 바이어스를 업데이트하는 과정.
  • Gradient Descent: 파라미터를 업데이트하여 모델을 학습시키는 방법.
  • 손실 함수: 모델의 예측 성능을 평가하는 지표.
  • 정확도: 모델이 얼마나 정확하게 예측하는지를 나타내는 지표.

2. 마스터클래스

김수경 마스터님 Q&A 요약 정리

질의응답

Q1: 인공지능은 앞으로 어떻게 발전할 것이라고 생각하시나요? 긍정적인 부분과 부정적인 부분에 대해 알고 싶고, 부정적인 부분을 개선하기 위해 수료생이 어떤 마음가짐과 자세로 이 기술을 활용하면 좋을지 궁금합니다.

  • A: 높은 수준의 관리 스킬이 요구될 것이며, 특정 분야의 도메인을 설정하는 것이 중요해질 것입니다.

Q2: 전자공학 석사 취득 후 재료 시뮬레이션에서 머신러닝으로 전향하신 이유가 궁금합니다.

  • A: 현실적인 부분들을 고민해서 전향했습니다.

Q3: 환경이나 기상 분석 분야에 관심이 있는데, 기상 분야에서 GIS 외에도 어떤 연구가 이루어지는지 궁금합니다. 에너지, 환경 도메인 쪽 취업을 목표로 하고 있는데 실무에서는 어떤 업무를 하는지도 알고 싶습니다.

  • A: 실무에서는 여전히 GIS를 많이 이용하며, 연구 분야에서는 다양하게 활용되고 있습니다.

Q4: 미국 대학원 진학을 준비 중인데 어떤 것을 준비하면 좋을까요? 한국에서 학교를 다니다가 미국으로 가서 어려움이 있었는지, 그리고 미국 대학원 진학 스토리가 궁금합니다.

  • A: 고등학생 때부터 유학의 꿈을 가지고 준비했습니다. 머신러닝 분야에서 Second 티어 정도의 논문이 1~2개는 있어야 한다고 생각합니다. 영어만 잘 한다면 한국 대학보다 크게 어렵지 않을 것입니다.

Q5: 주변의 AI 연구자나 AI 엔지니어 중 본받을만한 사람의 예시가 있을까요?

  • A: 사람마다 다릅니다. 유학이 아니더라도 국내에서 연구하고 성공한 분들도 많습니다.

Q6: 도메인마다 XAI 평가 방법이 상이할 것 같은데, 도메인에 따라 XAI 평가 방법 사례를 듣고 싶습니다.

  • A: 도메인이 아니라 모델에 따라 다릅니다.

Q7: XAI 연구 분야가 활발히 적용되는 산업과 사례가 궁금합니다. XAI의 전반적인 전망은 어떤가요?

  • A: 리스크가 큰 분야에서 XAI가 중요합니다.

Q8: XAI를 통해 모델의 설명 가능성을 판단하고 해석할 때, 사용자에게 제공되는 형식과 사례가 궁금합니다.

  • A: 수학식이나 그래프 등과 같은 시각화 도구로 제공됩니다.

Q9: 함수들의 수식을 보는 것이 어렵습니다. 개발 경험이 없는데, 라이브러리를 통해 어려움을 넘기고 나중에 수식을 공부해도 괜찮을까요?

  • A: 직군에 따라 다릅니다. 과학 관련 직군에서는 수학이 중요하지만, 엔지니어 및 프로그래밍 직군에서는 비교적 덜 중요합니다.

Q10: 대학원을 준비 중인 대학생인데, 논문을 처음 읽어보려면 어떻게 시작해야 할까요? 기초적인 논문부터 읽어야 할지, 최신 논문부터 읽어야 할지 궁금합니다.

  • A: 블로그에서 제대로 다루고 있는 경우가 많으니 블로그를 참고하는 것을 추천합니다. AI tech 과정을 성실히 따라가고 이해하는 것이 우선입니다.

Q11: 기후를 결정하는 변수들이 복잡한데, 네트워크가 이러한 feature를 학습하기 쉽지 않을 것 같습니다. 얼마나 많은 데이터와 복잡한 모델이 필요할까요?

  • A: 생각보다 복잡한 모델은 요구되지 않으며, 데이터 사이즈가 중요합니다.

Q12: 할루시네이션이 보통 부정적으로 인식되는데, 예술 분야에서 창의적 생각의 근거가 될 가능성이 있을까요?

  • A: 예술적인 분야에서는 근거가 될 가능성이 있다고 봅니다.

Q13: 현재 비디오 데이터 분야는 어떻게 발전되고 있나요?

  • A: 모든 모델들이 Transformer로 통합 중입니다. 비디오 데이터 분야에서는 ViT가 발전하고 있습니다.

Q14: 여러 XAI 기법 중 어떤 것을 적용할지 정성적으로 평가하는 사례가 있나요?

  • A: 정성적인 평가는 User Study를 많이 진행합니다. Ground Truth가 명확하지 않기 때문입니다.

캠퍼들에게 한 마디

네이버 AI Tech 커리큘럼은 석사과정에서 요구하는 것 이상으로 퀄리티가 높습니다. 성실히 따라가고 역량을 갖춘다면 굉장히 큰 기회가 올 것이라고 생각합니다.

3.assignment#3 풀이

Multi-head Self-attention Model 구현

1) Self-attention: \(\text{Attention}(Q,K,V)=\text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V\) 2) Multi-head Self-attention의 개념 3) 알고리즘 구현

CustomMultiHeadAttention클래스를 정의 이 클래스는 MLP(Multi-Head Attention)를 구현한다. 이는 Transformer 모델의 핵심 구성 요소 중 하나로, 다양한 헤드로 정보를 나누어 병렬적으로 처리하는 방법을 제공한다.

클래스 초기화 (__init__ 메서드)

def __init__(self, num_heads, model_dim):
    super().__init__()
    self.num_heads = num_heads
    self.head_dim = model_dim // num_heads
    self.all_heads_dim = self.head_dim * num_heads

    self.query_proj = nn.Linear(model_dim, self.all_heads_dim)
    self.key_proj = nn.Linear(model_dim, self.all_heads_dim)
    self.value_proj = nn.Linear(model_dim, self.all_heads_dim)

    # Output projection layer
    self.out_proj = nn.Linear(self.all_heads_dim, model_dim)
  • num_heads: 어텐션에서 몇 개의 헤드를 사용할지 정하는 변수이다. 보통 8 또는 16으로 설정된다.
  • model_dim: 입력 벡터의 차원 수이다. 이 값은 모델의 전체 차원을 의미한다.
  • head_dim: 각 헤드가 처리할 차원 수를 나타낸다. model_dimnum_heads로 나눈 값이다.
  • query_proj, key_proj, value_proj: 각각 쿼리, 키, 값에 대해 선형 변환을 적용하는 레이어다. 이들은 입력 데이터를 각 헤드로 나누기 전에 변환하기 위해 사용된다.
  • out_proj: 모든 헤드의 출력을 결합한 후, 다시 원래 모델 차원으로 투영하는 선형 변환 레이어이다.

split_heads 메서드

def split_heads(self, tensor):
    batch_size, seq_len, _ = tensor.size()
    tensor = tensor.view(batch_size, seq_len, self.num_heads, self.head_dim)
    return tensor.permute(0, 2, 1, 3)
  • 이 메서드는 입력 텐서를 여러 헤드로 분리한다.
  • tensor.view(batch_size, seq_len, self.num_heads, self.head_dim): 입력 텐서를 batch_size, seq_len, num_heads, head_dim의 형태로 변환한다. 각 헤드가 처리할 차원으로 나누는 것이다.
  • tensor.permute(0, 2, 1, 3): 텐서의 차원을 재배열하여 헤드를 첫 번째 차원으로 이동시킨다. 배열은 이후 행렬 연산을 효율적으로 수행하기 위함이다.

forward 메서드

def forward(self, x):
    Q = self.split_heads(self.query_proj(x))
    K = self.split_heads(self.key_proj(x))
    V = self.split_heads(self.value_proj(x))

    attn_weights = torch.matmul(Q, K.transpose(-1, -2)) / math.sqrt(self.head_dim)
    attn_weights = nn.Softmax(dim=-1)(attn_weights)
    attn_output = torch.matmul(attn_weights, V)

    # Concatenate all heads
    attn_output = attn_output.permute(0, 2, 1, 3).contiguous()
    concat_output = attn_output.view(attn_output.size(0), attn_output.size(1), -1)

    final_output = self.out_proj(concat_output)
    return final_output
  1. 쿼리(Q), 키(K), 값(V) 계산
    • Q = self.split_heads(self.query_proj(x))
    • K = self.split_heads(self.key_proj(x))
    • V = self.split_heads(self.value_proj(x))
    • 입력 x에 대해 각각의 선형 변환(query_proj, key_proj, value_proj)을 통해 쿼리, 키, 값을 계산한다. 그런 다음, split_heads 메서드를 통해 각 텐서를 여러 헤드로 분리한다.
  2. 어텐션 가중치 계산
    • attn_weights = torch.matmul(Q, K.transpose(-1, -2)) / math.sqrt(self.head_dim)
    • 쿼리 Q와 키 K의 내적(dot product)을 통해 어텐션 가중치(스코어)를 계산합니다. 이때, 내적 결과는 head_dim의 제곱근으로 나누어 스케일링합니다. 이는 수치 안정성을 높이기 위한 방법이다.
    • attn_weights = nn.Softmax(dim=-1)(attn_weights)
    • 소프트맥스 함수를 적용하여 어텐션 가중치를 확률로 변환한다. 각 가중치는 0과 1 사이의 값이 되며, 합은 1이 된다.
  3. 어텐션 출력 계산
    • attn_output = torch.matmul(attn_weights, V)
    • 계산된 어텐션 가중치와 값 V의 곱을 통해 어텐션 출력을 계산한다. 이는 각 헤드에 대한 출력이다.
  4. 헤드 결합 및 최종 출력 계산:
    • attn_output = attn_output.permute(0, 2, 1, 3).contiguous()
    • concat_output = attn_output.view(attn_output.size(0), attn_output.size(1), -1)
    • 여러 헤드의 출력을 하나의 텐서로 결합하기 위해 차원을 다시 정렬하고, 이어서 view 메서드를 사용하여 원래의 형태로 재배열한다.
    • final_output = self.out_proj(concat_output)
    • 결합된 출력을 다시 원래 모델 차원으로 변환하여 최종 출력을 생성한다.

알고리즘

  1. 쿼리, 키, 값 계산: 입력 데이터를 쿼리(Q), 키(K), 값(V)로 변환한다.
  2. 헤드 분할: Q, K, V를 다중 헤드로 분리한다.
  3. 어텐션 가중치 계산: Q와 K를 내적하여 어텐션 가중치를 계산하고, 소프트맥스 함수를 통해 확률 분포로 변환한다.
  4. 어텐션 출력 계산: 가중치와 V를 곱하여 각 헤드의 어텐션 출력을 생성한다.
  5. 헤드 결합: 각 헤드의 출력을 결합하여 하나의 텐서로 만들고, 최종 선형 변환을 통해 모델 차원으로 복원한다.