본문 바로가기
교육/SK네트웍스 Family AI 캠프

[플레이데이터 SK네트웍스 Family AI캠프 14기] 8주차 회고

by shining park 2025. 6. 2.

Class Daily Log

 

 

✏️8주차 진행 내용 : Deep Learning

 

 

📍이번주의 중요 내용

 

PyTorch

  • torch 모델 학습 생명주기
    • 생명주기를 크게 살펴보고 안의 내용을 앞으로 배울 예정
    • PyTorch의 텐서(tensor)는 자동 미분(autograd) 기능을 갖고 있음
    • PyTorch 텐서와 모델 파라미터들이 자동으로 연결되어 있어서, loss.backward() 한 줄만 써주면 모든 가중치의 기울기를 자동으로 계산해줌 (이걸 수학적으로 일일이 미분하지 않아도 됨) → 따라서 이제 이전 예제처럼 가중치를 직접 넘기는 일은 없음
    • grad = Gradient = 기울기 = 미분값
import torch.nn as nn
import torch.optim as optim

# 데이터 준비
X = torch.tensor([[0, 0], [0, 1], [1, 0], [1, 1]], dtype=torch.float)
y = torch.tensor([[0], [1], [1], [0]], dtype=torch.float)

print(X, type(X)) # <class 'torch.Tensor'>
print(y, type(y))


# 모델 생성
# - ⭐nn.Module 상속
class XORNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.hidden = nn.Linear(2, 4) # (입력 속성 개수 2, 출력 속성 개수 4) -> 내부 계층
        self.output = nn.Linear(4, 1) # (입력 속성 개수 4, 철력 속성 개수 1) -> 출력 레이어
        self.relu = nn.ReLU() # 은닉층 활성화 함수
        self.sigmoid = nn.Sigmoid() # 출력층 활성화 함수 (Step function의 역할을 대체한 부분)

    # 실제 연결은 forward 안에서 진행
    def forward(self, x):
        x = self.hidden(x)
        x = self.relu(x)
        x = self.output(x)
        x = self.sigmoid(x)
        return x

# 모델/손실함수/최적화함수 선언
model = XORNet()
criterion = nn.BCELoss() # 이진분류용 손실함수 (손실/기울기 계산)
optimizer = optim.Adam(model.parameters(), lr=0.01) # 최적화 함수 (학습률 lr 기본값 0.001)

model
"""
XORNet(
  (hidden): Linear(in_features=2, out_features=4, bias=True)
  (output): Linear(in_features=4, out_features=1, bias=True)
  (relu): ReLU()
  (sigmoid): Sigmoid()
)
"""

 

Activation Function ⭐

  • 활성화 함수
  • 모델 안의 레이어 다음, 은닉층과 출력층에서 사용됨
  • 실제 노드에서 계산된 값의 ⭐비선형성(non-linearity)을 부여함
  • 활성화 함수가 없다면 딥러닝 모델은 선형 함수들의 조합에 불과해 어떤 복잡한 문제도 해결하지 못함
    • Sigmoid
    • Tanh
    • ReLU
    • Leaky ReLU
    • Softmax
    • 주요 활성화 함수 정리

 

Torch Tensor > Image Data Process

  • 이미지 데이터 처리
    • 컬러 이미지 한장(pytorch기준): (채널, 높이, 너비)
    • 컬러 이미지 한장(opencv, matplotlib): (높이, 너비, 채널)
    • 컬럼 이미지 여러장(pytorch기준): (batch, 채널, 높이, 너비)
# 3차원 데이터(C, H, W)의 mean 연산
# - axis=0 Channel축을 따라 평균 (H, W)
# - axis=1 Height축을 따라 평균 (C, W)
# - axis=0 Weight축을 따라 평균 (C, H)
x = np.arange(1, 25).reshape(2, 3, 4)
print(x)
print()
# ✅결과값 보고 다시 생각해보기
print('axis=0 : ', x.mean(axis=0).shape) # 채널 평균값
print('axis=1 : ', x.mean(axis=1).shape) # 채널별 높이 평균값
# x.mean(axis=1)
print('axis=0 : ', x.mean(axis=2).shape) # 채널별 너비 평균값
x.mean(axis=2)

"""
[[[ 1  2  3  4]
  [ 5  6  7  8]
  [ 9 10 11 12]]

 [[13 14 15 16]
  [17 18 19 20]
  [21 22 23 24]]]

axis=0 :  (3, 4)
axis=1 :  (2, 4)
axis=0 :  (2, 3)
"""
  • 이미지 한장 시각화
# 이미지 한장 시각화
import matplotlib.pyplot as plt

channels = 3 # rgb 채널 수
height = 32
width = 32

# torch 이미지 순서를 따르고 있음
image = np.random.rand(channels, height, width)
# np.clip(arr, min, max): arr 요소 중에 min보다 작은 값은 min으로, max보다 큰 값은 max로 클리핑
bright_image = np.clip(image + 0.2, 0, 1) # -> 1 흰색, 0 검은색
print(bright_image.shape) # (3, 32, 32)

# pd.DataFrame(image[0])

gray_image = np.mean(image, axis=0) # axis 축을 따라 연산을 하므로, 그 축이 사라짐
print(gray_image.shape) # 채널 차원 제거 (32, 32)

# 이미지 출력을 위한 변환
# (C, H, W) -> (H, W, C)
# ndarray.transpose(*axes): 원하는 축의 인덱스를 작성
image_trans = image.transpose(1, 2, 0)
bright_image_trans = bright_image.transpose(1, 2, 0)

# 이미지 시각화
plt.subplot(1, 3, 1) # 131 -> 서브플랏 그릴 위치: 1행3열 중 1번째에 그려라
plt.imshow(image_trans)
plt.title('Original')
plt.axis('off')

plt.subplot(1, 3, 2)
plt.imshow(bright_image_trans)
plt.title('Brightened')
plt.axis('off')

plt.subplot(133) # (1, 3, 3)
plt.imshow(gray_image, cmap='gray')
plt.title('Grayscale')
plt.axis('off')

plt.show()

# PyCharm의 테마가 dark에서 Brightened이 살짝 어둡게 보이는 것ㅋㅋㅋ -> 정상처리됨
# 결과 이미지 : Invert Image 하면 light 테마 버전으로 볼 수 있음

 

Output Layer & Loss Function Connection

  • 출력층과 손실함수 연계
  • 분류
    • ‼️출력층에 활성화함수 사용X
    • ‼️ 이진분류 손실함수 : BCEWithLogitsLoss (내부적으로 sigmoid 활성화 함수 처리)
    • ‼️ 다중분류 손실함수 : CrossEntropyLoss(내부적으로 softmax 활성화 함수 처리)
  • 회귀
    • ‼️ 출력층에 활성화함수 사용X
    • ‼️ 손실함수 : MSELoss, … (선택지 더 있음)

 

Deep Learning > Backpropagation

  • ⭐오차 역전파
  • 출력층에서 입력층으로 오차를 전파하면서 가중치를 업데이트
  • 오차 역전파에는 ⭐미분의 연쇄법칙이 적용됨
  • 오차 역전파의 단계
    • 순전파(Forward Propagation): 입력 데이터가 네트워크를 통과하며 예측값을 생성
    • 오차 계산(Error Calculation): 예측값과 실제 목표값 사이의 오차를 계산. 대표적인 오차 함수는 평균 제곱 오차(MSE)
    • 오차 역전파(Backpropagation): 오차를 네트워크의 각 가중치로 전파하여 가중치를 조정 → 오차 E를 최소화하기 위해 각 가중치 w1(입력 ~ 은닉층) 과 w2(은닉층 ~ 출력층)에 대한 편미분을 구함
    • 가중치 갱신(Update Weights): 경사하강법을 통해 오차가 감소하도록 각 가중치를 갱신 → 각 가중치는 학습률 lr과 오차 기울기ㅡㄹ 사용해 갱신
  • ⭐ 다층 순전파/역전파 + torch version
# 다층 순전파/역전파
layer1 = lambda x: x ** 2
layer2 = lambda y: y * 2

def forward(x):
    y = layer1(x)
    z = layer2(y)
    return z

layer2_derivative = lambda y: 2
layer1_derivative = lambda x: 2 * x
def backward(x):
    """⭐forward함수의 도함수"""
    dz_dy = layer2_derivative(x) # layer2 도함수
    dy_dx = layer1_derivative(x) # layer1 도함수
    dz_dx = dz_dy * dy_dx
    return dz_dx

x = 3.0
print(forward(x)) # 18.0
# forward함수를 x로 미분하면?
# x가 변할 때 forward함수(z)는 얼마나 변하나?
print(backward(x)) # 12.0

# torch version
layer1 = lambda x: x ** 2
layer2 = lambda y: y * 2

def forward(x):
    y = layer1(x)
    z = layer2(y)
    return z

x = torch.tensor([3.0], requires_grad=True)
z = forward(x)
print(z) # tensor([18.], grad_fn=<MulBackward0>)

z.backward()
print(x.grad.item()) # 12.0

 

 

 

Keep

  • 실습과제를 빼먹지 않은 것
  • 복습을 그 날 못한 경우 다음날에라도 진행한 것
  • 주 3일 이상 도시락을 싸간 것

Problem

  • 점심 이후 오후 강의시간에 집중을 잘 못하는 것
  • 평일 운동을 자주 하지 못한 것
  • 개인 일정으로 금요일 강의를 못듣게 된 것

Try

  • 지하철 이용 시간에 독서나 Daily Log를 통한 복습을 진행할 것
  • 복습을 미루지 말 것
  • 휴가로 인한 금요일 강의 내용 꼭 공부하기
  • 운동을 꾸준히 해서 체력을 늘릴 것
  • 두번째 단위프로젝트(머신러닝) 열심히 참여할 것