본문 바로가기

ML

BDA_딥러닝의 이해반_250330

728x90

신경망 구현

 

3층 신경망 구현

 

신경망 기초 : 순전파와 활성화 함수 이해하기

  • 이번 공부에서는 신경망의 기본 구조와 순전파(Forward Pass)를 Python 으로 구현하는 방법을 다뤘습니다.
  • 회귀 문제와 분류 문제를 해결하는 간단한 신경망을 구성하고, 이를 확장하여 4층 구조로 변형하는 과정을 공부하겠습니다.

 

신경망 기본 구성 요소

  • 활성화 함수(Activation Functions)
    • 신경망에서 각 층의 출력을 비선형으로 변환하기 위해 활성화 함수를 사용한다. 여기서는 세 가지 함수를 정의해보았습니다.
      • ReLU: relu(z) = np.maximum(0, z)
        • 입력값이 0보다 작으면 0, 크면 그대로 출력.
      • Identity: identify(z) = z
        • 회귀 문제에서 출력층에 사용. 입력값을 그대로 반환.
      • Softmax: softmax(z)
        • 분류 문제에서 사용. 출력값을 확률로 변환.
import numpy as np

# 활성화 함수 정의
# y값 변환주는 함수

# ReLU: 0 이하 값은 0으로, 양수는 그대로
def relu(z):
    return np.maximum(0, z)

# Identity: 회귀 문제 출력층용, 입력값 그대로 반환
def identify(z):
    return z

# Softmax: 분류 문제 출력층용, 확률로 변환
def softmax(z):
    exp_z = np.exp(z - np.max(z, axis=0, keepdims=True))  # 오버플로우 방지
    return exp_z / np.sum(exp_z, axis=0, keepdims=True)

 

순전파(Forward Pass)

  • 순전파는 입력 데이터를 각 층을 거쳐 출력으로 변환하는 과정입니다. 3층 구조(입력층 -> 은닉층 -> 출력층)를 다음과 같이 정의했습니다.
# 순전파 함수
def forward_pass(X, W1, b1, W2, b2, output_activation):
    Z1 = W1 @ X + b1  # 은닉층 선형 결합
    A1 = relu(Z1)     # 은닉층 활성화
    Z2 = W2 @ A1 + b2 # 출력층 선형 결합
    A2 = output_activation(Z2)  # 출력층 활성화
    return A1, Z2, A2
  • X: 입력 데이터 (피처 수 × 샘플 수)
  • W1, b1: 첫 번째 층의 가중치와 편향
  • W2, b2: 두 번째 층의 가중치와 편향
  • output_activation: 출력층에 사용할 활성화 함수

가중치 초기화 - 3층 구조

  • 가중치와 편향을 무작위로 초기화합니다.
# 가중치 초기화 함수
def initialize_parameters(input_size, hidden_size, output_size):
    W1 = np.random.randn(hidden_size, input_size) * 0.1
    b1 = np.random.randn(hidden_size, 1) * 0.1
    W2 = np.random.randn(output_size, hidden_size) * 0.1
    b2 = np.random.randn(output_size, 1) * 0.1
    return W1, b1, W2, b2

 

# 이제 항등합수를 이용해서 회귀문제처럼 풀어보겠습니다.

 

회귀 문제 해결

  • 데이터 생성
    • 집의 면적과 위치 점수를 기반으로 집값을 예측하는 회귀 문제를 설정합니다.
np.random.seed(1)
X_reg = np.random.rand(2, 100)  # 2피처, 100 샘플
Y_reg = (4 * X_reg[0] + 2 * X_reg[1] + 1 + np.random.randn(100) * 0.1).reshape(-1, 1)
  • X_reg: 2개의 피처(랜덤 값)
  • Y_reg: 선형 결합 + 노이즈

초기화 및 순전파 - 회귀

3층 신경망으로 예측합니다.

# 파라미터 초기화 및 순전파 진행
W1_reg, b1_reg, W2_reg, b2_reg = initialize_parameters(2, 3, 1)

# 회귀문제 순전파로 풀어 봄
_, _, y_pred_reg = forward_pass(X_reg, W1_reg, b1_reg, W2_reg, b2_reg, identify)

 

소프트맥스 함수를 사용해 이진 분류 문제 해결

#### 소프트맥스 함수를 사용해서 이진 분류 문제 해결 
X_clf=np.random.randn(2,100)
Y_clf_true = ((X_clf[0] * X_clf[1])> 0).astype(int)

Y_clf =np.zeros((2,100))
Y_clf[Y_clf_true, np.arange(100)] = 1

 

데이터 타입을 만들었으니 실제 신경망에 학습함

## 데이터 타입을 만들었으니 실제 신경망에 학습
W1_clf, b1_clf, W2_clf, b2_clf =initialize_parameters(2,3,2)

 

분류문제 순전파로 풀이

## 분류문제 순전파로 풀어 봄
_,_,y_pred_clf =forward_pass(X_clf, W1_clf, b1_clf, W2_clf, b2_clf, softmax)
y_pred_clf
array([[0.45357359, 0.45394567, 0.45126141, 0.46078338, 0.46182956,
        0.46750891, 0.44092459, 0.46029064, 0.46957912, 0.46957912,
        0.45576538, 0.46774883, 0.4564977 , 0.45723816, 0.46408276,
        0.4564989 , 0.45422334, 0.43852023, 0.44684039, 0.46424365,
        0.44929089, 0.46010553, 0.45210385, 0.45805978, 0.4651937 ,
        0.46464154, 0.46445303, 0.46010132, 0.46957912, 0.46665664,
        0.4624558 , 0.46240906, 0.46604321, 0.45494932, 0.45527261,
        0.44409248, 0.44628709, 0.46075686, 0.43274781, 0.45147791,
        0.45366966, 0.44731388, 0.4583828 , 0.45700261, 0.46067911,
        0.46522972, 0.46406566, 0.45398557, 0.46127394, 0.46092419,
        0.45710573, 0.46957912, 0.45689007, 0.45776443, 0.45171147,
        0.46957912, 0.45730534, 0.44749247, 0.46909043, 0.45769332,
        0.46957912, 0.46816914, 0.46367349, 0.45567859, 0.46957912,
        0.46263046, 0.46423095, 0.46532756, 0.45549138, 0.46109211,
        0.46957912, 0.46957912, 0.44967781, 0.45875349, 0.46399956,
        0.45912959, 0.4552199 , 0.46775466, 0.45546222, 0.44587744,
        0.4647066 , 0.45274557, 0.44901334, 0.4491213 , 0.46317171,
        0.44155035, 0.43976131, 0.4669402 , 0.46957912, 0.46957912,
        0.44965955, 0.45241724, 0.44111246, 0.45966016, 0.44018591,
        0.46068036, 0.46854685, 0.45379454, 0.46957912, 0.45278094],
       [0.54642641, 0.54605433, 0.54873859, 0.53921662, 0.53817044,
        0.53249109, 0.55907541, 0.53970936, 0.53042088, 0.53042088,
        0.54423462, 0.53225117, 0.5435023 , 0.54276184, 0.53591724,
        0.5435011 , 0.54577666, 0.56147977, 0.55315961, 0.53575635,
        0.55070911, 0.53989447, 0.54789615, 0.54194022, 0.5348063 ,
        0.53535846, 0.53554697, 0.53989868, 0.53042088, 0.53334336,
        0.5375442 , 0.53759094, 0.53395679, 0.54505068, 0.54472739,
        0.55590752, 0.55371291, 0.53924314, 0.56725219, 0.54852209,
        0.54633034, 0.55268612, 0.5416172 , 0.54299739, 0.53932089,
        0.53477028, 0.53593434, 0.54601443, 0.53872606, 0.53907581,
        0.54289427, 0.53042088, 0.54310993, 0.54223557, 0.54828853,
        0.53042088, 0.54269466, 0.55250753, 0.53090957, 0.54230668,
        0.53042088, 0.53183086, 0.53632651, 0.54432141, 0.53042088,
        0.53736954, 0.53576905, 0.53467244, 0.54450862, 0.53890789,
        0.53042088, 0.53042088, 0.55032219, 0.54124651, 0.53600044,
        0.54087041, 0.5447801 , 0.53224534, 0.54453778, 0.55412256,
        0.5352934 , 0.54725443, 0.55098666, 0.5508787 , 0.53682829,
        0.55844965, 0.56023869, 0.5330598 , 0.53042088, 0.53042088,
        0.55034045, 0.54758276, 0.55888754, 0.54033984, 0.55981409,
        0.53931964, 0.53145315, 0.54620546, 0.53042088, 0.54721906]])

 

실제 문제처럼 신경망을 이용해서 풀어봄

실제 문제 데이터 생성 - 회귀

집 면적과 위치 점수로 집값 예측

import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

n_samples = 200
X_reg = np.random.rand(2, n_samples)  # 2피처, 100개의 샘플 ## 집의 면적과 위치에 대한 점수
Y_reg = (150 * X_reg[0] + 80 * X_reg[1] + 20 + np.random.randn(n_samples) * 5).reshape(1, -1) ## 집값
데이터 시각화 - 회귀
plt.figure(figsize=(6, 4))
plt.scatter(X_reg[0], Y_reg, label='ft_1', alpha=0.5)
plt.scatter(X_reg[1], Y_reg, label='ft_2', alpha=0.5)
plt.legend()
plt.grid(True)
plt.show()

학습/테스트 분할 및 예측 - 회귀
 
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

## train/test 분할
Xr_train, Xr_test, Yr_train, Yr_test = train_test_split(X_reg.T, Y_reg.T, test_size=0.2, random_state=111)

Xr_train, Xr_test = Xr_train.T, Xr_test.T
Yr_train, Yr_test = Yr_train.T, Yr_test.T

# 초기화 및 예측
W1_reg, b1_reg, W2_reg, b2_reg = initialize_parameters(2, 10, 1)
_, _, y_pred_reg = forward_pass(Xr_test, W1_reg, b1_reg, W2_reg, b2_reg, identify)

# MSE 계산
mse = mean_squared_error(Yr_test.flatten(), y_pred_reg.flatten())
print(f"MSE: {mse}"
18039.627135504823
Yr_test.flatten()
array([ 79.61511275, 153.96364596, 104.52077469, 134.16832042,
        98.76949409, 187.07464587, 213.07545066,  89.41348882,
       130.82195925,  75.12044304,  79.49712396, 185.04189686,
       132.93228303,  98.49354465, 135.62399298, 211.48939181,
       130.43970054, 154.39974627,  72.69893227, 131.34846281,
        98.43418282,  75.92826905, 181.18289628,  67.02901064,
       186.87219599, 113.60252368,  52.65981642, 138.77790125,
       185.35792922, 120.54869772, 173.11080948, 124.03034714,
        83.29643241,  52.83630021,  51.04366086, 118.64456577,
       222.931479  , 167.05645502,  73.36393222, 145.89866674])

 

mean_squared_error(Yr_test.flatten(), y_pred_reg.flatten())
18081.877245910116

3. 분류 문제 해결

데이터 생성 - 분류

이진 분류를 위한 데이터셋 생성

X_clf = np.random.randn(2, 100)  # 2피처, 100 샘플
Y_clf_true = ((X_clf[0] * X_clf[1]) > 0).astype(int)  # 곱이 양수면 1, 음수면 0
Y_clf = np.zeros((2, 100))
Y_clf[Y_clf_true, np.arange(100)] = 1
초기화 및 순전파 - 분류
W1_clf, b1_clf, W2_clf, b2_clf = initialize_parameters(2, 3, 2)
_, _, y_pred_clf = forward_pass(X_clf, W1_clf, b1_clf, W2_clf, b2_clf, softmax)

# 결과 출력
print(y_pred_clf)
출력은 각 샘플에 대한 클래스 확률(2×100 배열).

 

필수과제 1

 

  • 1. PDF파일의 신경망 3층 구조를 -> 4층으로 만들어서 직접 손으로 (펜,종이, 아이패드 상관없음) - 계산되는 과정 모두 다 적어주세요. ( PDF 파일처럼 직접 노드 그려서 벡터 선형 결합 적고, 직접 활성화 함수 지정해서 어떤 식으로 계산되는지 적어주세요! )

필수과제 2

  • 2. 실제 분류 문제도 동일하게 200개 정도 데이터셋을 만들어서 코드와 함께 직접 구현 - Ipynb 로 제출 요구

필수과제 1: 신경망 4층 구조 계산 과정

1. 신경망 구조

  • 신경망은 입력층, 은닉층, 출력층으로 구성됩니다. 여기서 4층 신경망을 만든다는 것은 입력층 + 3개의 은닉층 + 출력층을 만들게 됩니다.
  • 각 층은 뉴런들이 연결된 구조로, 각 뉴런에서 계산된 값은 다음 층으로 전달됩니다.

2. 구성 요소

여기서 W_i 는 각 층의 가중치, b_i 는 편향, a_i 는 활성화 함수가 적용된 출력 값입니다.

3. 계산 과정

4. 활성화 함수

활성화 함수는 각 층에서 출력값을 비선형적으로 변화시키는 역할을 합니다. 일반적으로 사용하는 함수는 다음과 같다

 

5. 연산 예시 (4층 신경망)

Input X = [x1, x2, ..., xn]  

Layer 1: 
z1 = W1 * X + b1
a1 = ReLU(z1)

Layer 2: 
z2 = W2 * a1 + b2
a2 = ReLU(z2)

Layer 3: 
z3 = W3 * a2 + b3
a3 = ReLU(z3)

Output Layer: 
z4 = W4 * a3 + b4
a4 = Softmax(z4)  (예를 들어 다중 클래스 분류라면)

 

6. 직접 손으로 계산

 

필수과제 2: 분류 문제 구현

이제 분류 문제를 해결하는 코드를 작성할 차례입니다. 이 예시에서는 간단한 이진 분류 문제를 다루며, 데이터셋은 랜덤으로 생성하여 사용할 수 있다.

Python의 scikit-learn 라이브러리를 사용하여 분류 문제를 풀 수 있습니다.

 

1. 필수과제 2: 코드 예시

# 필수과제 2: 이진 분류 문제 해결

import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_classification
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import classification_report, accuracy_score

# 데이터셋 생성 (200개 샘플)
X, y = make_classification(n_samples=200, n_features=2, n_classes=2, random_state=42)

# 훈련 데이터와 테스트 데이터로 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 신경망 모델 생성 (MLP: 다층 퍼셉트론)
model = MLPClassifier(hidden_layer_sizes=(4,), max_iter=1000, activation='relu', solver='adam', random_state=42)

# 모델 학습
model.fit(X_train, y_train)

# 예측
y_pred = model.predict(X_test)

# 평가
print(f"Accuracy: {accuracy_score(y_test, y_pred)}")
print(classification_report(y_test, y_pred))

# 시각화 (결과)
plt.figure(figsize=(8, 6))
plt.scatter(X_test[:, 0], X_test[:, 1], c=y_pred, cmap=plt.cm.coolwarm)
plt.title("Predicted Classes")
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.show()

 

2. 코드 설명

  • 데이터셋: make_classification을 사용하여 이진 분류 문제를 위한 200개 샘플을 생성합니다.
  • 훈련 및 테스트 데이터 분리: train_test_split을 사용하여 70%는 훈련용, 30%는 테스트용 데이터로 분리합니다.
  • 모델 생성: MLPClassifier를 사용하여 다층 퍼셉트론 신경망을 생성합니다. 4개의 뉴런을 가진 은닉층을 설정했습니다.
  • 훈련 및 예측: 모델을 훈련시키고 테스트 데이터에 대해 예측합니다.
  • 평가: 정확도와 분류 보고서를 출력하여 모델 성능을 평가합니다.
  • 시각화: matplotlib을 사용하여 테스트 데이터와 예측된 클래스를 시각화합니다.
728x90

'ML' 카테고리의 다른 글