참고로 KNN 모델은 MCU 메모리 사용량이 매우 커서 TinyML 변환이 제한적 이다.
아주 간단한 KNN 회귀라면 구현 가능하지만, TinyML 변환은 절대 추천되지 않는다.
KNN은 학습된 모델이 아니라 데이터 전체를 저장하고 비교하는 방식이기 때문이다.
1. 문제해결 시나리오


어느 음료 공장에서는 1시간마다, 발효탱크의 심부 온도 데이터를 수집한다.
발효공정은 총 8시간 이루어지며, 하루의 작업이 끝나면 결과물의 맛(Taste)에 대한 점수를 매긴다.
8시간 마다 이루어지는 온도 데이터 90일 분량과 맛(Taste) 평가 Score 데이터를 기반으로
8개의 온도 데이터를 INPUT 하였을 때, 맛(Taste)에 대한 평가 Score를 예측하여 OUTPUT 하는 아주 간단한 KNN 알고리즘을 만들어보자.
2. 데이터를 준비하자 (시나리오 임의 데이터 생성)
chatGPT에게 부탁하여 90일 분량의 하루 단위 8개의 온도 데이터와 맛 점수 데이터를 만들어달라고 한다.
Day T1 T2 T3 T4 T5 T6 T7 T8 TasteScore
1 20.2 20.4 20.7 20.2 20.2 20.7 20.5 20.1 93.8
2 19.6 19.8 19.2 19.3 19.6 19.5 19.9 19.5 90.3
3 20.7 20.8 20.3 20.6 20.8 20.4 20.8 20.6 90.6
4 20.3 19.7 19.4 19.9 19.3 19.8 19.1 19.3 93.1
5 20.4 20.3 20.3 19.9 20.2 20.2 20.7 20.5 90.9
6 20 20 20.3 20.5 20.4 19.9 20.1 20.3 96
7 19.7 19.4 19.4 20 20.2 19.7 20.1 19.9 93.4
8 20.6 20.2 20.7 19.4 20.4 20.2 20.1 20.2 91.2
9 20 20.3 19.7 19.6 19.7 20.2 20 19.7 96
10 20.3 19.8 20 19.9 19.6 20.1 20.1 20.1 95.5
11 19.2 19.2 19.1 19.2 19.4 19.9 19.3 19.4 90.6
12 19 19.1 19.8 19 19.1 19 18.7 19.4 90.2
13 20.1 20.8 20 20.6 21.1 20.1 20.2 20.4 91.9
14 19.2 18.9 19.4 18.9 19.7 19 19.1 19.5 87.9
15 20.5 19.6 20.2 20.2 20.3 19.7 19.7 20.3 95.9
16 20.2 19.9 20.2 20.2 19.9 20.7 20.3 19.8 95.8
17 19.7 19.9 19.3 19.8 19.6 19.8 20.1 19.4 92.5
18 19.3 19.5 19.7 19.6 19.8 19.6 20 19.5 97.1
19 20.1 20 20.5 20.2 20.5 20.5 20.3 20.1 91.5
20 20 19.8 19.4 19.8 19.9 19.5 19.8 19.8 92.3
21 20.3 20.5 20.5 19.8 19.9 20.3 20.3 20.3 99
22 20.6 20.6 20.5 20.2 20.5 20.1 20.2 20.1 93.3
23 20.6 21.4 20.7 21 21.5 21.2 20.8 20.9 88.9
24 19.7 19.6 19.4 20.3 19.8 19 19.7 19.4 94.2
25 19.6 19.8 19.9 19.2 19.5 19.5 19.4 20.1 93.6
26 19.6 20 19.7 18.9 19.2 19.7 19.2 19.5 93
27 19.5 18.6 19.2 19.5 19.2 20 19.1 19.4 90.7
28 20.3 21.1 20.7 20.4 20.9 20.8 20.5 20.7 90
29 20.3 20.5 19.7 20.7 19.5 20 20.2 20.1 94.1
30 19.7 19.7 20.2 20 19.7 20.2 20 20.1 96.5
31 19.4 19.8 19.8 19.6 19.6 20 19.4 19.7 93
32 20.2 20.1 20.1 20.3 19.9 20.1 19.8 20 95.3
33 20.2 19.8 20.7 19.7 19.7 20.4 20.3 20.2 95.9
34 19.7 20 19.8 20.3 19.9 19.7 19.9 20.1 94.6
35 19.7 19.7 19.4 19.4 19.7 19.2 19.2 19.4 91.4
36 20.6 20.4 20.1 20.1 19.9 20.1 20.1 20.3 93.2
37 20.7 20.2 20.4 20.5 20.1 20.3 20.3 20.3 92
38 20.2 20.4 20.3 20.7 19.8 20.3 20.1 20.7 92.3
39 19.4 18.9 19.4 19.4 19.6 19.7 20.1 19.9 91.5
40 19.7 19.2 20.1 19.9 19.4 19 20 19.5 94.7
41 19 19.2 19.2 19.1 19.4 18.9 19.2 19.2 90
42 20 19.9 20.7 20.5 20.1 20.8 20.4 20.7 93
43 21.6 21 21.3 21.2 21.4 20.7 21.2 21.3 85
44 18.8 19.3 19.6 19.9 19.4 19.9 19 18.9 90.7
45 20.2 19.6 20.2 19.8 20.4 20.3 19.9 20 94
46 20.3 19.7 20.1 19.8 19.7 19.9 19.7 19.8 93.2
47 21 20.8 21 20.9 20.9 21.2 21.2 20.8 87.3
48 19.2 19.4 20.3 20.4 19.8 20 20 20.8 97.6
49 19.6 19.5 20 19.7 19.5 19.7 19.6 20.4 95.3
50 20.4 20 19.7 20.5 20.2 19.7 19.9 19.7 93.8
51 21 20 20.6 20.3 20.3 20.3 20.2 20.5 91.6
52 20.1 20.1 19.9 20 20.4 20.3 19.8 20.2 96.3
53 19.3 19 19.3 18.9 18.6 18.7 19.2 19.2 86.8
54 19.8 20.3 20 20.1 20.3 20.1 20.2 20.6 93.7
55 20.1 20.6 20.9 19.7 20.2 20.6 20.4 20.5 92.1
56 20 20.4 20.1 20.1 19.9 19.9 19.9 20.2 94.9
57 20.8 20.4 20 20.5 20 19.5 19.8 19.6 94.9
58 20.5 20.1 19.9 20.3 19.3 20.1 20.2 19.6 97.7
59 20 20.4 20.9 20.2 20.2 20 19.9 20.4 92.7
60 19.9 20.2 20.1 20.3 19.9 20 19.7 19.9 96.6
61 20.1 20.6 20.8 20.5 20.9 20.1 20 19.8 95.4
62 20.3 20.4 20 21.1 20.4 20.4 20.5 20.5 92.7
63 19.7 20.2 20 20.1 19.5 19.3 19.6 19.6 95.6
64 19.6 19.1 19 18.9 18.7 19.4 19.2 18.8 86.8
65 20.3 19.8 19.4 19.8 19.8 19 19.8 19.8 94.7
66 21.3 20.8 20.6 21.7 20.9 20.9 20.9 21 87.7
67 19.5 19.7 19.6 19.5 19.7 19.6 20.2 18.9 94.3
68 20 20.5 20.5 20.2 20.4 20.3 21.1 20.9 94
69 20 20.2 20.5 20 20.6 20.3 20.2 20.6 94.3
70 20.2 19.5 20 20 19.7 19.9 19.4 20.1 94.5
71 20.1 19.5 19.3 19.3 19.9 19.4 20.3 19.1 95.4
72 20.1 19.9 20.2 20.1 20.4 20.1 20.2 20 94.9
73 19.6 19.7 20.4 20.2 20.1 20.2 20.3 20 94.3
74 19.8 20.2 19.6 20.4 20.2 20.2 20.4 20.6 96.1
75 18.7 18.9 19.1 19.2 18.9 19.1 18.9 18.9 85.6
76 19.1 19.2 19.9 19.3 20.3 19.7 19.6 19.3 93.5
77 19.7 20.5 19.7 20.1 19.5 19.7 20.2 19.5 97.6
78 20.2 20.5 20.6 20.5 19.9 20.1 20.3 20.3 94.5
79 19.7 20.2 20.3 20.3 20.4 20.3 20.2 20.1 92
80 20.3 20.3 19.8 19.9 20.5 20.2 20.4 20.2 94.4
81 20.3 20.5 20.3 20.3 20.4 20.5 20.3 20.8 91.3
82 19.8 20.3 20 20.2 19.5 20 20.2 19.9 97.5
83 20.2 20.4 19.6 19.6 20.2 20.2 19.6 19.6 95
84 19.1 19 19.1 19.3 19.4 19.8 19 19.6 90
85 20.2 19.6 20.1 20 20.1 20.1 20.7 19.8 94.6
86 19.5 19.5 20 20.1 19.5 19.4 19.8 19.5 94.2
87 19.6 20.6 20.6 19.9 20 20.2 20.2 20.3 97.6
88 19.7 19.5 19.7 19.9 20.4 19.8 20 19.9 96.7
89 21.1 21.1 21.6 21.5 21.8 21.4 21.2 21.4 86.6
90 20.6 20.7 20.8 20.8 20.6 20.4 20.5 20.8 89.6
데이터는 90일 분량으로 준비되었다. 이제 이 데이터를 가지고 KNN 예측 모델을 한번 만들어보자.
※ 실 데이터가 아니라 AI가 임의적으로 생성한 데이터이다.
3. Python 코드 작성
# 필요한 관련 라이브러리 (pandas, sklearn)
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsRegressor
from sklearn.metrics import mean_absolute_error, r2_score
- import pandas as pd : 표 형태의 데이터를 불러오고 (DataFrame), 가공과 정리에 사용됨
- from sklearn.model_selection import train_test_split : 전체 데이터를 학습(Train)과 테스트(Test)용으로 자동으로 분리
- from sklearn.neighbors import KNeighborsRegressor : K-최근접 이웃 (KNN) 알고리즘을 이용한 회귀 모델 생성
- from sklearn.metrics import mean_absolute_error, r2_score : 모델 성능 (예측 정확도) 평가
KNN 알고리즘 복습 : 특정 입력 값과 가장 가까운 데이터 K개를 찾고 그 값들의 평균 (또는 가중 평균)을 출력 값으로 예측 (온도 패턴처럼 단순한 경우, 직관적이고 성능도 괜찮다.)
# 1) CSV 파일 불러오기
# - fermentation_90days.csv 는 이전에 만든 90일치 발효 데이터
# - 컬럼: Day, T1~T8, TasteScore
data = pd.read_csv("fermentation_90days.csv") # 데이터프레임으로 저장
# 2) 입력 특징(X)과 타깃(y) 분리
# - X: 하루 동안 매 시간 측정된 온도 8개
# - y: 최종 맛 점수
feature_cols = ["T1", "T2", "T3", "T4", "T5", "T6", "T7", "T8"] # 특성
X = data[feature_cols] # 입력 데이터로 저장
y = data["TasteScore"] # 타겟 데이터로 저장
지도 학습에서 데이터와 정답을 입력(input)과 타겟(target)으로 분류한다.
입력에서 사용된 데이터들을 특성 (feature)라고 한다.
# 3) 학습용 / 테스트용 데이터 분리
# - test_size=0.2 → 전체의 20%를 테스트용으로 사용 ( 90일의 데이터 이니깐 18일을 테스트용으로 )
# - random_state는 재현 가능한 결과를 위해 고정
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# random_state = 42에는 기술적인 의미는 없지만, 머신러닝 업계에서 유명한 밈이자 전통적인 관행..
사이킷런에서 train_test_split() 함수를 사용하면 비율에 맞게 훈련 세트와 테스트 세트로 변환해 준다.
섞을 때 사용하는 랜덤 시드 (seed)를 지정하는 값이 random_state 이다.
random_state를 고정하면 동일한 데이터 일 경우 동일한 결과를 얻을 수 있다.
# 4) KNN 회귀 모델 생성
# - n_neighbors: 이웃의 개수 (여기서는 3일치 데이터를 참고)
# - weights="distance":
# 가까운 이웃일수록 더 큰 영향(가중치)을 주도록 설정
knn = KNeighborsRegressor(
n_neighbors=3,
weights="distance"
)
# 3이나 5는 보편적인 기본값이다.
KNN에서 n_neighbors(이웃 수)는 정답이 없다. 하이퍼파라미터 라서 상황과 데이터에 따라 성능이 달라진다.
※ 하이퍼파라미터 (hyperparameter) 란?
모델이 학습하기 “전에” 사람이 직접 정해주는 설정값.
모델이 스스로 배우는 것이 아니라, 우리가 정해줘야 하는 조절 옵션(스위치, 설정값)
# 5) 모델 학습 (fit)
# - 과거 발효 온도 패턴(X_train)과 맛 점수(y_train)를 이용해
# "비슷한 온도 패턴 → 비슷한 맛 점수" 라는 규칙을 학습
knn.fit(X_train, y_train)

# 6) 테스트 데이터에 대해 예측 수행
y_pred = knn.predict(X_test)
# 7) 성능 평가
# - MAE(Mean Absolute Error): 예측 오차의 평균 (단위: 점수)
# - R²(R-squared): 1에 가까울수록 설명력이 좋음
mae = mean_absolute_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print("=== KNN 회귀 모델 성능 ===")
print(f"평균 절대 오차(MAE): {mae:.3f}")
print(f"결정 계수(R²): {r2:.3f}")

과대적합 (overfitting) : 훈련 데이터에만 너무 맞춰져서 새로운 데이터(테스트)에 약함
과소적합 (underfitting) : 모델이 너무 단순해서 데이터의 패턴을 제대로 학습하지 못한 상태
평균 절대 오차 (MAE) = 1.489
평균적으로 약 1.5점 정도의 오차 발생
실전에서는 꽤 준수한 오차 수준
R² = 0.537
1.0이면 완전한 모델, 0.537 이면 전체 변동의 약 53%만 설명한다는 의미이며 즉, 절반 정도는 맞추고 절반 정도는 놓친다라는 수준이다. 아주 좋은 모델은 아니다.
결론은 해당 모델은 약한 과소적합 경향이 있다. (패턴을 충분히 학습하지 못했다)
테스트 수준이 중간 정도 수준
모델을 개선하는 하는 것은 다양한 문제점과 원인을 분석해야 할 수 있다.
원인은 하이퍼파라미터 일 ( hyperparameter)수도 있고, 특성(feature)이 부족하였을 수도 있으며 훈련 데이터가 많거나 적었을 수도 있다. 즉 좋은 AI 모델을 만드려면 다양한 방면에서의 원인을 분석하는 시각을 가져야 한다.
# 8) 새로운 발효 온도 패턴을 넣어보자 !
# - 예: 오늘 발효 중 8시간 온도가 아래와 같다고 가정
new_day_temps = [[
20.0, 20.1, 19.9, 20.2, 20.3, 20.1, 20.0, 19.9
]]
# - KNN 모델에 새로운 온도 패턴을 넣고, 예상 맛 점수를 받아온다.
new_pred = knn.predict(new_day_temps)
print("\n=== 새로운 발효 품질 예측 ===")
print("입력 온도 패턴(8시간):", new_day_temps[0])
print(f"예상 맛 점수: {new_pred[0]:.2f}")

predict() 함수는 새로운 입력을 받아 최종 예측 값을 반환 한다.
'임베디드 AI > TinyML' 카테고리의 다른 글
| 선형 회귀 (Linear Regression)와 다항 회귀(Polynomial Regression) 알고리즘 (0) | 2025.11.19 |
|---|---|
| TinyML (온 디바이스 AI) (0) | 2025.11.14 |
| K-최근접 알고리즘02 (훈련세트/테스트세트) (0) | 2023.01.24 |
| 머신러닝 알고리즘 분류 (지도학습/비지도학습/강화학습) (0) | 2023.01.24 |
| 머신러닝 K-최근접 이웃 알고리즘(K-Nearest Neighbors) (0) | 2023.01.24 |