지노랩 /JinoLab

18. 은닉층·출력층 가중치 행렬 본문

프로그래밍/C언어를 이용한 Deep Learning

18. 은닉층·출력층 가중치 행렬

지노랩/JinoLab 2025. 8. 13. 09:56

은닉층·출력층 가중치 행렬을 0~1 사이의 난수로 초기화

  • random_init(rows, cols, W) 함수를 통해 임의의 실수를 생성해 W[i][j]에 저장
  • RAND_MAX를 이용해 rand()/(double)RAND_MAX 형태로 0~1 구간 난수 생성
  • srand(time(NULL))으로 시드 초기화
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

/**
 * @brief rows×cols 크기의 행렬 W 를 0~1 난수로 채웁니다.
 * @param rows  행(첫 차원) 크기
 * @param cols  열(둘째 차원) 크기
 * @param W     결과를 저장할 2D 배열 (row-major)
 */
void random_init(int rows, int cols, double W[rows][cols]) {
    // 난수 시드: 실행할 때마다 다른 값 생성
    srand((unsigned)time(NULL));
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            // 0 <= rand()/RAND_MAX < 1
            W[i][j] = rand() / (double)RAND_MAX;
        }
    }
}

int main(void) {
    // --- 네트워크 구조 예시 ---
    // 입력층 → 은닉층 (2→3), 은닉층 → 출력층 (3→1)
    const int N_INPUT  = 2;  // 입력 노드 수
    const int N_HIDDEN = 3;  // 은닉 노드 수
    const int N_OUTPUT = 1;  // 출력 노드 수

    // 가중치 행렬 버퍼 선언
    double W1[N_INPUT][N_HIDDEN];  // (2×3) 행렬: 입력→은닉
    double W2[N_HIDDEN][N_OUTPUT]; // (3×1) 행렬: 은닉→출력

    // --- 난수 초기화 호출 ---
    random_init(N_INPUT,  N_HIDDEN, W1);
    random_init(N_HIDDEN, N_OUTPUT, W2);

    // --- 초기화된 가중치 출력 ---
    printf("W1 (입력→은닉  %d×%d):\n", N_INPUT, N_HIDDEN);
    for (int i = 0; i < N_INPUT; i++) {
        for (int j = 0; j < N_HIDDEN; j++) {
            printf("%6.4f ", W1[i][j]);
        }
        printf("\n");
    }
    printf("\n");

    printf("W2 (은닉→출력  %d×%d):\n", N_HIDDEN, N_OUTPUT);
    for (int i = 0; i < N_HIDDEN; i++) {
        for (int j = 0; j < N_OUTPUT; j++) {
            printf("%6.4f ", W2[i][j]);
        }
        printf("\n");
    }
    printf("\n");

    return 0;
}

설명

  1. random_init 함수
    • srand(time(NULL))로 한 번만 시드를 설정
    • rand() / (double)RAND_MAX로 [0,1)[0,1) 구간의 실수 난수 생성
    • 이중 for문으로 행·열 순회하며 W[i][j]에 대입
  2. main 함수
    • 예시로 입력 2 → 은닉 3 → 출력 1 구조 사용
    • W1[2][3], W2[3][1] 배열 선언 후 random_init 호출
    • 초기화된 행렬을 [row][col] 형태로 보기 좋게 출력

이제 이 가중치 행렬을 이용해 순전파(Forward Propagation)와 역전파(Backpropagation)를 구현하면, 완전한 학습 루프를 구성할 수 있습니다.