18가지 조합을 다 돌려봤는데, 어떤 조합이 얼마나 좋았는지 기억할 방법이 없으면 곤란하잖아요.
MLflow = 매 실험마다 파라미터, 결과, 모델을 자동으로 저장해주는 도구
크게 세 군데예요.
① 실험 공간 설정
mlflow.set_experiment(EXPERIMENT_NAME)
# "이 노트북의 실험들을 여기다 모아서 저장할게"
② 그리드 서치 중 매 조합마다 기록 (숫자 결과만)
with mlflow.start_run(run_name="ALS_GridSearch") as parent_run: # 전체 실험
for i, params in enumerate(param_grid): # 18번 반복
with mlflow.start_run(run_name=run_name, nested=True): # 각 조합
mlflow.log_params({"rank": rank, "regParam": reg_param}) # 파라미터 저장
mlflow.log_metric("rmse", rmse) # 결과 저장
폴더 구조로 보면 이렇게 쌓여요.
ALS_GridSearch (parent)
├── rank10_reg0.01_iter10 → rmse: 1.23
├── rank10_reg0.01_iter20 → rmse: 1.19
├── rank20_reg0.1_iter10 → rmse: 0.98 ← best
└── ... (18개)
③ 최종 모델 등록 (모델 파일)
with mlflow.start_run(run_name="Final_ALS_Model"):
mlflow.log_params(best_params) # 최적 파라미터
mlflow.log_metric("test_rmse", best_rmse) # 최종 성능
mlflow.spark.log_model( # 모델 파일 자체를 저장
final_model,
registered_model_name=f"{CATALOG}.{SCHEMA}.movie_recommender_als"
)
# 18번 돌릴 때마다 직접 print로 기록하고
print(f"rank=10, reg=0.01 → RMSE: 1.23")
print(f"rank=10, reg=0.1 → RMSE: 1.19")
# ... 나중에 어떤 게 최고였는지 찾아야 하고
# 모델 파일도 직접 저장해야 하고
# 다음 주에 "그때 어떤 파라미터 썼지?" 하면 답 없음
MLflow는 이걸 자동화해주고, Databricks UI에서 표로 한눈에 비교할 수 있게 해줘요.
명령적 (Imperative) — 요리 과정을 직접 지시
"냉장고에서 닭 꺼내, 180도로 예열해, 30분 구워, 소스 발라, 접시에 담아"
선언적 (Declarative) — 결과만 말하기
"치킨 한 마리 주세요"
어떻게 만드는지는 관심 없고, 뭘 원하는지만 말하는 거예요.
from pyspark import pipelines as dp
| Streaming Table | Materialized View | |
|---|---|---|
| 처리 방식 | 새로 들어온 데이터만 증분 처리 | 전체 데이터 재계산 |
| 적합한 작업 | 데이터 수집, 정제 | 집계, 조인 |
| 적합한 레이어 | Bronze, Silver | Gold |
| Python 데코레이터 | @dp.table + readStream | @dp.materialized_view |
| SQL | CREATE OR REFRESH STREAMING TABLE | CREATE OR REFRESH MATERIALIZED VIEW |
@dp.table | @dp.temporary_view | |
|---|---|---|
| 저장 여부 | Delta 테이블로 물리적 저장 | 저장 안 됨 |
| 용도 | Bronze / Silver / Gold 최종 결과 | 중간 계산용 임시 뷰 |
| 유형 | 위반 시 동작 | 사용 레이어 | 전략 |
|---|---|---|---|
@dp.expect() | 경고만, 레코드 유지 | Bronze | 일단 다 쌓고 모니터링 |
@dp.expect_or_drop() | 위반 레코드 제거 | Silver | 불량 데이터 걸러내기 |
@dp.expect_or_fail() | 파이프라인 전체 중단 | Gold | 서비스 품질 보장 |
-- NULL 체크
"column IS NOT NULL"
-- 범위 검증
"amount > 0 AND amount < 1000000"
-- 값 목록
"status IN ('active', 'pending', 'completed')"
-- 패턴 매칭
"email LIKE '%@%'"
| Python | SQL |
|---|---|
@dp.table | CREATE OR REFRESH STREAMING TABLE |
@dp.materialized_view | CREATE OR REFRESH MATERIALIZED VIEW |
@dp.expect_or_drop(...) | CONSTRAINT 이름 EXPECT (...) ON VIOLATION DROP ROW |
Python은 데코레이터로 선언하고, SQL은 키워드로 선언하는 차이만 있을 뿐 SDP가 내부적으로 처리하는 방식은 똑같아요.