Skip to content
View gwon9906's full-sized avatar

Block or report gwon9906

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Content in all repositories owned by your account will be closed.
Maximum 250 characters. Please don’t include any personal information such as legal names or email addresses. Markdown is supported. This note will only be visible to you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse
gwon9906/README.md

이해권 (Haegwon Lee)

무선 신호처리 · 시계열 예측 · 온디바이스 ML

gwon99065@naver.com · Portfolio · Blog


소개

결과를 의심하는 데서 일을 시작합니다. 설명하지 못하는 결과는 좋은 결과가 아닐 확률이 높다고 생각하기 때문입니다.

전력과 연산, 대역폭이 부족한 환경에서 신호와 시계열을 다뤄 왔고, 2026년 2월 동의대학교 컴퓨터공학과를 졸업했습니다. 아래 세 프로젝트에는 결과와 함께 그 결과가 어떤 조건에서 성립하는지 다시 따져 본 기록을 남겼습니다.


핵심 역량

  • 언어: Python(주력), C/C++
  • ML: PyTorch, TensorFlow, ONNX Runtime, scikit-learn
  • 신호처리: de-chirp, FFT, 오버샘플링, 복소 IQ 처리, STFT 스펙트로그램, 순환상관 기반 매치드 필터
  • 시계열: 슬라이딩 윈도우 설계, 누수 없는 평가 분할, 단순 기준선 비교, 시드 반복 측정
  • 온디바이스: 라즈베리파이 배포와 필드테스트, LoRa 모듈 E22-900T22S UART 제어, GPS·IMU

프로젝트

1. 엣지 디바이스 통신 효율화: ML 손실 압축으로 LoRa 전송량 줄이기

2025.03–06 · 캡스톤디자인 · 4인 팀, 기여도 40% · 압축 모델 개발, 데이터 수집·전처리, 필드테스트 담당

문제

LoRa 같은 저전력 장거리 무선에서는 페이로드가 짧을수록 공중 체류 시간(ToA)이 줄어듭니다. 센서값을 잘라내면 정보가 사라집니다. 범용 무손실 압축인 zlib을 먼저 걸어 봤더니 32B가 42B로 오히려 늘었습니다. 반복되는 패턴이 없는 짧은 수치열이라 줄일 곳은 없고 헤더만 붙었습니다. 【확인 필요: zlib 로그·코드 보존 여부】

구현

GPS, 3축 가속도, 3축 각속도, 자세각으로 이뤄진 12차원 시계열을 다층 BAM으로 8차원 잠재 벡터에 담았습니다. 이 벡터를 float으로 직렬화하니 원본보다 커져서 정수형으로 바꿨습니다. 운용 반경 안에서는 정수부가 변하지 않고, 소수부 끝자리는 센서 정밀도보다 세밀해서 둘 다 잘라낼 수 있었습니다. 그렇게 32B를 20B, 원본의 62.5%로 줄였고 복원 오차는 MSE 0.0037이었습니다.

헤더 2B를 더한 실제 송신 프레임은 34B에서 22B가 됩니다. 이 기준으로 ToA를 계산하면 데이터 프레임 한 번의 전송 시간이 1.81초에서 1.48초로 약 18% 짧아집니다.

송신과 수신 양쪽 라즈베리파이에서 압축부터 복원까지 한 번에 돌아가는 파이프라인을 만들어 실외에서 시험했습니다. 설정은 SF12, BW 125kHz, CR 4/5입니다. 【확인 필요: 거리·RSSI 기준값】

재검증

MSE가 낮은데도 복원한 GPS 좌표는 틀려 있었습니다. MSE는 정규화한 12개 값의 평균이라 변동 폭이 큰 IMU 값이 지표를 좌우하고, GPS의 작은 오차는 묻힙니다. 원래 단위로 되돌리니 수백 미터가 어긋나 있었습니다. 성격이 다른 값이 섞인 데이터는 평균 지표 하나로 복원 품질을 판단할 수 없습니다.

전송 성공률이 좋아졌다는 주장은 거둬들였습니다. 측정하는 내내 수신율이 같은 값 근처에서 꿈쩍하지 않아 로그를 다시 열었습니다. 수신 seq를 3으로 나눈 나머지로 묶어 보니 한 그룹 33건에서는 DATA가 한 번도 도착하지 않았습니다. 반면 초반 QUERY 38건은 모두 들어왔고, RSSI도 SF12 수신 감도보다 30dB 넘게 여유가 있었습니다. 세 차례 측정에서 같은 패턴이 되풀이됐으니 무선 구간의 우연한 손실로 볼 수 없었습니다. 원인은 송신 루프의 타이밍이었습니다.

메시지 한 번을 주고받으려면 QUERY, PERMIT, DATA, ACK 네 패킷이 오가고 약 4초가 걸립니다. 그런데 전송 간격이 1초로 고정돼 있어 송신 요청이 처리 속도보다 빨리 쌓였고, 넘친 요청은 버려졌습니다. 성공률을 수신 측 seq로 셌기 때문에 아예 나가지 못한 패킷까지 손실로 잡혔습니다. 이런 조건에서 나온 차이를 채널 덕으로 돌릴 수는 없습니다. 압축한 22B 프레임도 ToA가 1.48초라서 1초 간격 설계에서는 압축만으로 실시간 전송을 맞추지 못합니다.

BAM을 고른 근거는 문헌뿐이었습니다. 프로젝트를 마친 뒤 Intel Lab Data로 8차원 센서 벡터를 만들어 같은 조건에서 오토인코더(AE)와 겨뤄 봤는데, BAM이 앞선 구간은 없었습니다. 잠재 차원이 4일 때 AE는 0.897, BAM은 1.435였습니다. 이어서 AE를 ONNX로 내보내 ONNX Runtime 추론을 확인했습니다. batch 차원이 고정돼 여러 입력을 묶으면 실패하던 문제는 dynamic axis로 고쳤고, PyTorch 출력과도 일치했습니다.


2. 초저SNR LoRa 복조 연구: 신경망 복원을 접고 최적 검출기로

2025.09–2026.02 · 개인 수행, 지도교수 자문 · Wireless AIoT System Lab · 종료, 2026.09 재검증

실험 조건: SF9, BW 250kHz, 4배 오버샘플링(fs 1MHz), 심볼 512종, AWGN 시뮬레이션

결과

학습 없이 검출기만 바꿔 −25dB에서 복조 성공률을 13.0%에서 52.6%로 끌어올렸습니다(+39.6%p). 6000 trials에서 구한 95% Wilson 신뢰구간은 각각 [12.2, 13.9], [51.4, 53.9]입니다. 연산량은 기존의 1.1배쯤이며, 시뮬레이션에서 잰 값이라 엣지 기기에서는 아직 재지 않았습니다.

이론 한계를 넘은 결과가 아니라 이론 한계에 닿은 결과입니다. 잡음을 샘플링 대역 1MHz 전체에 더했기 때문에, 여기 적은 SNR은 신호 대역 250kHz 기준으로 보면 약 6dB 낮게 표기돼 있습니다.

원래 목표

잡음 섞인 IQ를 복소 STFT 스펙트로그램으로 바꿔 다층 BAM으로 복원하고, 다시 IQ로 되돌려 de-chirp 심볼 추정에 넣는 denoising front-end를 만들려 했습니다. IQ를 복소수 그대로 다루려고 가중치까지 복소수인 BAM을 짰고, 활성함수(split-tanh)만 실수부와 허수부에 따로 걸었습니다. 안정성은 선행 논문의 Lagrange 조건을 따랐습니다. 학습은 잡음 섞인 입력을 그대로 타깃으로 삼는 자기복원 방식이었습니다.

재검증

비교 기준으로 쓰던 검출기부터 최적이 아니었습니다. 오버샘플링된 신호를 데시메이션 없이 곧장 de-chirp하고 FFT를 걸고 있었는데, 이러면 심볼 에너지가 이웃 bin으로 새고 멀리 떨어진 두 alias 블록으로도 갈라집니다. 가장 큰 bin 하나만 고르는 판정은 그중 한 조각만 봤습니다. 표준 수신기는 심볼당 N샘플로 줄인 뒤 처리하므로 이런 일이 없습니다. 기존 검출기는 최적보다 평균 4.2dB를 손해 보고 있었습니다.

최적 검출기는 적은 연산으로 되살릴 수 있었습니다. 심볼 프로토타입 512개는 모두 하나를 순환 시프트한 모양이라 매치드 필터 뱅크 전체가 순환상관 한 번으로 나옵니다. 512×2048 상관을 직접 계산하지 않아도 2048점 FFT 한 번과 512점 역FFT 한 번이면 같은 판정이 나옵니다.

이 기준 앞에서는 BAM의 개선 폭이 남지 않았습니다. 기존 검출기와 비교해 얻었던 −25dB 27.8%는 최적 검출기의 52.6%에 못 미칩니다.

그래서 종료 근거도 새로 세웠습니다. AWGN 채널에서 에너지가 같고 서로 직교하는 심볼 집합이라면 프로토타입 상관 벡터가 충분통계량입니다. data processing inequality에 따라 심볼 단위 front-end는 BAM이든 CNN이든 정보를 늘리지 못합니다. BAM의 첫 연산 Wy = Σ s_m⟨s_m, y⟩ 안에 이미 매치드 필터 상관이 들어 있고, 뒤따르는 반복과 비선형 연산은 그 통계량을 가공할 뿐입니다. 막힌 곳은 모델의 표현력이 아니라 한 심볼만 들여다보는 관측 범위였습니다.

처음 종료 근거로 삼았던 SOM 분석은 거둬들였습니다. LoRa 심볼은 직교하도록 설계돼 잡음이 없어도 모든 쌍의 거리가 같습니다. 이웃한 심볼끼리 신호가 닮았다고 보고 라벨을 묶은 SOM의 전제부터 틀렸습니다. 대조군도 MNIST가 아니라 잡음 없는 LoRa 신호여야 했습니다. raw IQ에서 가장 가까운 프로토타입을 찾기만 해도 −25dB에서 절반 넘게 맞혔으니, 신호에 구분할 정보가 없다는 판단은 잘못이었습니다. SOM 코드는 저장소에 남아 있지 않아 다시 돌려 볼 수 없습니다.

실험 설계에도 빈틈이 있었습니다. 학습은 − 7.5~0dB, 평가는 − 30 ~ − 5dB에서 했고, 학습과 평가에 같은 심볼 512개를 썼습니다.

남은 문제

주파수 오프셋(CFO)이 일정하면 격자 탐색이 genie 상한과 1.0~2.9%p 차이까지 따라가고, 선형으로 흘러가면 오프셋과 기울기를 함께 찾는 2차원 탐색이 1.83%p 차이까지 좁힙니다. 여기까지는 고전 방법으로 풀립니다. 여지가 크게 남는 경우는 CFO가 무작위로 떠돌아 정수 bin 경계를 넘는 시점을 저차 모델로 예측하지 못할 때입니다. 흔들림 폭이 1bin이면 22.1%p, 2bin이면 32.1%p가 회수되지 않습니다. 상한을 계산할 수 있는 조건이어서 어떤 방법을 넣든 성과를 숫자로 검증할 수 있습니다.

재현 스크립트: verification/ 【확인 필요: 저장소 실행 오류 수정 여부】


3. 산업용 밸브 유량 예측: 모델보다 평가 기준을 다시 세운 기록

2024.07–12 · 개인 수행 · 연구실에서 받은 과제 주제를 직접 문제로 정의하고 구현 · TensorFlow

문제

받은 주제는 밸브 유량 예측 하나였습니다. 나중에 예지보전에 쓰려고, 지금 값을 추정하는 대신 앞으로의 값을 맞히는 문제로 정했습니다. 1초 간격으로 잰 압력과 개도율의 최근 40초를 보고 5초 뒤 유량을 예측합니다. 데이터는 3~7bar 압력 조건 다섯 가지와 따로 떼어 둔 holdout 파일 하나였습니다.

구현

시퀀스를 저차원으로 압축하는 인코더가 실제로 도움이 되는지 보려고 Encoder-LSTM과 단일 LSTM을 중간 Dense 층까지 똑같이 맞췄습니다. 두 모델은 인코더 병목 블록 하나만 다릅니다. 개도율이 0이 되면 hidden state를 초기화했고, 손실 함수는 MSE 대신 Huber를 썼습니다.

결과

Test MAE Holdout MAE Test MAPE
Encoder-LSTM (시드 3회) 0.540 ± 0.147 0.955 ± 0.164 1.98%
단일 LSTM (시드 3회) 0.548 ± 0.186 1.156 ± 0.224 2.00%
직전 값 유지 0.136 0.612 0.79%

유량 컬럼에는 단위가 적혀 있지 않습니다. 전체 115,839행의 평균은 40.6, 범위는 1.7~76.9입니다.

재검증

처음에는 로그 변환한 타깃으로 평가 지표를 계산하고 있었습니다. MAPE의 분모가 유량이 아니라 log(1+유량)이었으니, 성능이라고 읽던 숫자는 유량 오차율이 아니었습니다. 원래 값으로 되돌린 뒤 계산하도록 고쳤습니다.

데이터 분할은 두 번 어긋났습니다. 슬라이딩 윈도우에서는 이웃한 시퀀스가 40스텝 중 39스텝을 공유해서, 무작위로 나누면 사실상 같은 샘플이 학습셋과 테스트셋에 함께 들어갑니다. 시간 순서로 나누자 이번에는 압력 조건이 차례로 놓여 있던 탓에 학습에 없던 압력 구간으로 평가하게 됐습니다. 조건마다 블록을 번갈아 배정하고 경계 구간을 버려 두 문제를 함께 피했습니다.

시드에 따른 편차가 모델 사이의 차이보다 컸습니다. 한 번만 돌렸다면 시드에 따라 정반대 결론이 나왔을 데이터였고, 인코더 구조가 낫다고 말할 근거는 없었습니다.

가장 단순한 기준에도 졌습니다. 프로젝트를 마친 뒤 직전 값을 그대로 내놓는 기준선을 같은 분할로 계산했더니, test와 holdout 모두에서 두 모델보다 오차가 작았습니다. 이 기준선의 test MAE는 평균 유량의 0.33%에 그칩니다. 1초 간격 데이터에서 5초 앞은 대부분 정상 상태여서 애초에 학습 모델이 필요 없는 설정이었습니다. test와 holdout의 오차가 4.5배 벌어진 데서 holdout 파일에 과도 구간이 많다고 짐작하고, 변화가 큰 구간만 떼어 모델과 기준선을 다시 비교하는 중입니다.

이 프로젝트에서 건진 성과는 모델 성능이 아닙니다. 데이터 누수, 학습 범위 밖 평가, 빠진 기준선을 하나씩 걷어내며 숫자의 의미를 확인한 평가 절차입니다.


세 프로젝트에서 되풀이해 빠진 함정이 두 가지 있습니다. 하나는 변환한 공간의 지표를 원래 값의 지표로 읽은 일입니다. 압축에서는 정규화 공간의 MSE 0.0037이 거의 완벽해 보였지만 실제 좌표는 틀렸고, 유량 예측에서는 로그 공간에서 잰 오차가 모델을 실제와 다르게 보이게 했습니다. 다른 하나는 비교 기준을 의심하지 않은 일입니다. 복조 연구에서는 최적이 아닌 검출기를 잣대로 개선 폭을 쟀고, 유량 예측에서는 직전 값 유지라는 가장 단순한 잣대를 처음에 세우지 않았습니다. 좋아 보이는 숫자든 나빠 보이는 숫자든, 무엇과 견준 값인지, 왜 그 값이 나왔는지 설명하기 전에는 결론으로 삼지 않습니다.


연구 및 활동

Wireless AIoT System Lab 학부연구생, 동의대학교 (2024.07~2026.02)

  • 초저SNR 무선 신호 복조 연구
  • 엣지·무선 환경 센서 데이터 압축과 전송
  • 산업 센서 시계열 예측

자격 정보처리기사 (2025.06)


학습 중

모델 양자화를 공부하고 있습니다. PTQ와 QAT, 대칭·비대칭 양자화, 채널 단위와 텐서 단위 양자화, 캘리브레이션을 다룹니다. 압축 프로젝트에서 ONNX 변환까지 확인했으니, 다음에는 라즈베리파이에서 INT8 모델의 지연 시간과 메모리를 직접 재 보려 합니다.


연락처

Pinned Loading

  1. 4xvgal/ChirpChirp 4xvgal/ChirpChirp Public

    센서 데이터를 머신러닝 기반으로 압축하고 LoRa 통신을 통해 전송하는 저전력/고효율 데이터 송수신 시스템입니다.

    Python 1

  2. Lightweight-MF-BAM Lightweight-MF-BAM Public

    A lightweight NumPy implementation of the MF-BAM model (Rolon-Mérette et al., 2023) for learning non-linear tasks without deep-learning frameworks.

    Python 1

  3. Denoise-and-Classify Denoise-and-Classify Public

    SNR (Signal-to-Noise Ratio) 환경에서의 이미지 복원 및 분류 성능을 개선하기 위한 딥러닝 연구 프로젝트입니다.

    Jupyter Notebook

  4. lora-cfo-headroom-map lora-cfo-headroom-map Public

    Where classical CFO estimation stops paying in ultra-low-SNR LoRa — a genie-bounded headroom map with paired confidence intervals. Three self-refutations included.

    Jupyter Notebook

  5. sensor-compression-onnx sensor-compression-onnx Public

    압축 모델의 ONNX export 및 ONNX Runtime 검증. batch 차원 고정으로 batch>1 입력이 실패하던 문제를 dynamic axis로 수정하고 PyTorch와 출력 일치 확인.

    Python