지노랩 /JinoLab
9. 은닉층(hidden layer) 본문
1. 네트워크 구조
- 입력층 → 은닉층
- 입력 벡터 x∈Rnin
- 가중치 행렬 W(1)∈Rnhid×nin
- 은닉 활성 벡터 h∈Rnhid

- 은닉층 → 출력층
- 은닉 벡터 h
- 가중치 행렬 W(2)∈Rnout×nhid
- 출력 예측 벡터 y∈Rnout

x (n_in) ──▶ W¹ ──▶ h (n_hid) ──▶ W² ──▶ y (n_out)
이번 예제에서는 선형 활성화만 사용합니다. (추후 ReLU, Sigmoid 추가 가능)
2. C 언어 구현
2.1 헤더 파일: simple_mlp.h
#ifndef SIMPLE_MLP_H
#define SIMPLE_MLP_H
/**
* @brief 1층 은닉층을 갖는 MLP 예측 함수 (선형 활성화)
* @param x 입력 벡터 (크기 n_in)
* @param W1 입력→은닉 가중치 행렬 (flatten된 배열, 크기 n_hid * n_in)
* @param n_in 입력 개수
* @param n_hid 은닉 유닛 개수
* @param W2 은닉→출력 가중치 행렬 (flatten된 배열, 크기 n_out * n_hid)
* @param n_out 출력 개수
* @param y 결과 출력 벡터 (크기 n_out)
*/
void predict_mlp(const double *x,
const double *W1,
int n_in,
int n_hid,
const double *W2,
int n_out,
double *y);
#endif // SIMPLE_MLP_H
2.2 구현 파일: simple_mlp.c
#include "simple_mlp.h"
#include <stdlib.h> // malloc, free
// 내부에서 사용할 벡터·행렬 곱 (flattened matrix)
static void matvec(const double *vec, const double *mat,
int rows, int cols, double *out) {
for (int i = 0; i < rows; i++) {
double sum = 0.0;
for (int j = 0; j < cols; j++) {
sum += mat[i * cols + j] * vec[j];
}
out[i] = sum;
}
}
void predict_mlp(const double *x,
const double *W1,
int n_in,
int n_hid,
const double *W2,
int n_out,
double *y) {
// 1) 은닉층 계산: h = W1 · x
double *h = (double*)malloc(sizeof(double) * n_hid);
if (!h) return; // 메모리 할당 실패 시 종료
matvec(x, W1, n_hid, n_in, h);
// 2) 출력층 계산: y = W2 · h
matvec(h, W2, n_out, n_hid, y);
// 3) 동적 메모리 해제
free(h);
}
2.3 메인 파일: main.c
#include <stdio.h>
#include "simple_mlp.h"
// 네트워크 크기 정의
#define N_INPUTS 3 // 온도, 습도, 공기질
#define N_HIDDEN 4 // 은닉 유닛 개수 (예시)
#define N_OUTPUTS 3 // 행복지수, 건강지수, 활동지수
int main(void) {
// 1) 입력 벡터 x
double x[N_INPUTS] = {30.0, 87.0, 110.0};
// 2) 가중치 행렬 W1 (n_hid × n_in)
double W1[N_HIDDEN * N_INPUTS] = {
// 행 0
0.2, 0.5, -0.3,
// 행 1
-0.1, 0.8, 0.4,
// 행 2
0.7, -0.6, 0.1,
// 행 3
0.3, 0.2, 0.9
};
// 3) 가중치 행렬 W2 (n_out × n_hid)
double W2[N_OUTPUTS * N_HIDDEN] = {
// y0 (행복지수) 예측 가중치
0.5, -0.2, 0.1, 0.3,
// y1 (건강지수) 예측 가중치
0.4, 0.7, 0.2, -0.5,
// y2 (활동지수) 예측 가중치
-0.3, 0.4, 0.6, 0.8
};
// 4) 예측 결과 저장 버퍼
double y[N_OUTPUTS];
// 5) MLP 예측 함수 호출
predict_mlp(x, W1, N_INPUTS, N_HIDDEN, W2, N_OUTPUTS, y);
// 6) 결과 출력
const char *labels[N_OUTPUTS] = {
"행복지수", "건강지수", "활동지수"
};
for (int i = 0; i < N_OUTPUTS; i++) {
printf("%s: %.4f\n", labels[i], y[i]);
}
return 0;
}
3. 빌드 & 실행
gcc -o SimpleMLP main.c simple_mlp.c
./SimpleMLP
행복지수 : 20.7700
건강지수 : 79.9300
활동지수 : 58.4600
4. 마무리 및 확장 과제
- 비선형 활성화 함수 추가
- ReLU, Sigmoid 등으로 h[i] = f(h[i]) 처리
- 편향(bias) 항 도입

- 역전파(Backpropagation) 구현해 가중치 학습
- 배치 처리(Batch Processing)
- 학습률(lr), 에포크(epoch) 등 하이퍼파라미터 튜닝
이 예제를 바탕으로, 직접 학습 알고리즘까지 구현해 보며 딥러닝의 기본 원리를 체득해 보시기 바랍니다!
'프로그래밍 > C언어를 이용한 Deep Learning' 카테고리의 다른 글
| 11. 텐서(Tensor) 기본 개념 (2) | 2025.08.06 |
|---|---|
| 10. 비교(compare) / 오차(error) 계산 (1) | 2025.08.05 |
| 8. 다중 입력·다중 출력(Multiple Input, Multiple Output, MIMO) 퍼셉트론 (2) | 2025.08.03 |
| 7. 다중 입력·단일 출력 퍼셉트론을 C 언어로 (1) | 2025.08.02 |
| 6. 3가지 입력(온도·습도·공기질)으로 하나의 출력(행복/슬픔 지수) (2) | 2025.08.01 |