본문 바로가기

dev_AI_framework

문제 해결 완료, XOR 수렴 확인 야호~

1) 손실 값이 0 ↔ 16으로 요동친 이유와 해결

원인

  • BCE에 시그모이드 확률이 아니라 로짓(선형 출력) 이 들어감 → log(1−yp)에서 음수/1 경계값으로 폭주 → 손실이 극단값(≈16)로 튐.
  • 배치 단위/요소 단위 평균을 중복으로 나눔(double averaging) 가능성도 기울기를 지나치게 작게 만들어 수렴을 방해.

해결

  • run_graph_with_loss_cuda에서 최종 y_pred를 ‘LOSS 노드 입력(=마지막 Activation 출력)’로 강제:
    • 마지막 op가 LOSS면 pred_id = E.back().input_id 로 지정.
    • BCE에는 반드시 [0,1] 확률이 들어가도록 고정.
  • BCE 경로에서 평균은 한 번만:
    • compute_bce_loss_cuda는 전체 n으로 한 번 평균.
    • bce_loss_backward는 최종적으로 dL/dz = (a - y) / batch_size만 적용(다른 곳에서 또 나누지 않음).

 

2) 메모리 포인터/버퍼 문제(멈춤, 이상치)와 해결

원인

  • run_graph_cuda가 중간 출력 버퍼를 계속 cudaMalloc하고, 호출 종료 후 free하지 않아 누적 → evaluate/fit 중 특정 시점에 멈춤(메모리 고갈/드라이버 sync 지연).
  • 또한, 어느 버퍼가 사용자 쪽에서 전달된 포인터인지와 내부에서 임시로 만든 포인터인지 구분이 없어, 정리 타이밍이 애매했음.

해결

  • run_graph_with_loss_cuda에서 **호출 이전의 텐서 키 스냅샷(user_keys)**을 만들어 두고,
    • **사용자가 넘긴 포인터(user_keys)**와 **결과 출력(pred_id)**는 보존.
    • 그 외 이번 forward에서 새로 생성된 임시 출력 버퍼만 cudaFree로 정리.
  • 에러 핀포인트용으로 CUDA 오류 체크 + deviceSynchronize를 손실 계산 전후에 배치.

 

3) 활성화 함수 출력이 음수로 나온 문제와 해결

원인

  • BCE 디버그에서 y_pred가 음수로 보였던 건, 실제 y_pred(Activation 출력)가 아니라 Dense 선형 출력(로짓) 버퍼를 읽고 있었기 때문(포인터/변수 참조 착오).
  • 출력 지점(변수명) 혼동으로 “시그모이드 이후 값을” 본다고 생각했는데 실제로는 이전 레이어 버퍼를 찍은 경우가 있었음.

해결

  • 손실 계산부에서 y_pred로 사용하는 포인터를 ‘마지막 Activation 출력’로 명확히 고정.
  • 디버그 시 [PTR] y_pred=..., act_out=..., dense_out=... 를 함께 출력해 포인터 착오를 즉시 발견할 수 있게 함.
  • 필요 시 샘플 값 4~8개만 호스트로 복사해 범위([0,1])를 즉시 검증.

 

4) safe sigmoid의 문제(완전 포화)와 해결

원인

  • safe_sigmoid가 x<-30 → 0, x>30 → 1로 완전 고정 → 그 구간에 들어가면 기울기 0으로 학습이 “얼어붙음”.
  • 큰 학습률/초기치로 한 번만 튀어도 포화에 갇혀서 손실이 더 안 내려감.

해결

  • ε 여유를 둔 클램프:→ 포화 구간에서도 미세한 gradient가 살아 있어 탈출 가능.
  • 학습 안정화를 위해 LR 튜닝(SGD 0.1, Adam 1e‑2 권장) 및 히든 활성화 tanh 선택(표현력/분리력 ↑).
  •  
const float eps = 1e-7f;
if (x < -30.0f) return eps;
if (x >  30.0f) return 1.0f - eps;