실험 0007 · 국채선물

신경망은 트리를 한 티어에서 넘었다 — 그런데 20분 모멘텀 규칙은 한 티어도 못 넘었다

퍼셉트론·SGD·sklearn MLP·torch MLP·잔차 MLP·임베딩 MLP 로 설정 55개를 티어 넷 × 시드 열 개에 돌렸다. 적합 15,400회, 벽시계 135분.

H17 지지 · H18 지지 1 · 동급 1 · 미지지 2 설정 55 × 티어 4 × 시드 10 정직 선택 · 짝지은 McNemar · 배포 흔들림

H17 지지 — 제대로 탐색한 신경망은 0005 가 쓴 단일 MLP 설정을 넘는다(T4_daily 0.5438 → 0.5785, T1_flow34 0.5704 → 0.5960). H18 은 티어별로 갈렸고 장중 수급 티어 한 자리에서 트리를 넘었다(0.5960 대 0.5678 · McNemar p=0.0416). 그런데 그 자리의 20분 모멘텀 규칙이 0.5933 이고 규칙 대비 McNemar p=0.9037 이다 — 이긴 것은 트리이고 규칙이 아니다. 그 한 승은 튠한 트리 앞에서 사라진다(p=0.0591). 대회 제출 관점에서 이 실험은 배포할 물건을 만들지 못했다.

가설과 결론

가설
선행 실험(0005)의 모델 18종 가운데 신경망은 mlp 하나였고 설정도 hidden_layer_sizes=(32,16) 하나였다. 그 축을 제대로 탐색하면 — 설정 격자를 넓히고, 현대 학습 레시피(LayerNorm·dropout·AdamW· 코사인 스케줄·label smoothing·SWA)를 넣고, 수치 피처 임베딩을 더하면 — 0005 의 단일 MLP 설정을 넘고(H17) 0005 의 정직 선택 트리에 닿는다(H18).
결론
H17 지지. 두 티어에서 승률·유의성·흔들림 문턱 셋을 다 넘었다. H18 은 갈렸다T1_flow34 지지, T5_all 동급, T0_core·T4_daily 미지지. 그러나 네 티어 중 어느 것도 20분 모멘텀 규칙을 유의하게 넘지 못했다, 그리고 지지된 한 자리는 트리가 가장 약한 티어였다. 수치 임베딩이 맨 MLP 를 올린다는 가설(H19)은 미지지(짝 여덟 개 전부 p ≥ 0.3155), 계열 순서 가설(H20′)도 미지지이고 뒤집힌 자리가 셋이다.
이 실험이 바꾼 것
모델 축 하나다. 피처를 새로 만들지 않고 0005 의 캐시를 그대로 읽었다 — 데이터가 같아야 0005 와의 비교가 성립한다.

기호와 데이터

이 문서는 혼자 열린다. 쓰는 낱말을 여기서 정의한다.

P_ref
채점 기준가. 15:45 동시호가 직전의 참조 가격이고 제출 시점에는 관측할 수 없다.
P45
15:45 동시호가로 결정된 종가.
ref_tick
P45P_ref 의 차이를 틱으로 센 값. 이 부호가 맞히려는 것이다. 0이면 그 날을 표본에서 뺀다.
0틱
ref_tick = 0 인 날. 방향이 없어 채점이 성립하지 않으므로 표본에서 제외한다(원시 2,394일 → 유효 1,847일).
승률
예측 부호가 ref_tick 부호와 같은 날의 비율. 이 리포트의 모든 승률은 시험 구간에서만 센 값이다.
워크포워드
연도 확장창. 시험연도 직전까지를 학습으로 쓰고 그 해만 시험한다. 학습이 해마다 자란다 — 344행에서 1,693행까지.
티어
피처 그룹의 묶음. 티어가 다르면 학습 시작연도와 시험 표본이 달라지므로 티어를 섞어 승률을 비교하지 않는다.
정직 선택
설정을 직전 연도까지의 성적만 보고 고르는 절차. 동률이면 이름 순이다. 이 리포트의 머릿수는 전부 정직 선택값이고, 여덟 해를 다 보고 고른 사후 최고는 판정 문장에 쓰지 않는다.
spread_deploy
배포 형태의 시드 흔들림. 시드 열 개에서 크기 5짜리 부분집합 20개를 고정 난수로 뽑아 각 부분집합의 확률 평균으로 승률을 내고, 그 20개의 표준편차를 쓴다. 판정 문턱은 이 값의 2배다.
spread_seed
단일 시드 승률의 표준편차(0005·0006 이 쓴 정의). 참고로만 적고 판정에는 쓰지 않는다.
e_규칙
기준선 하나 — 20분 모멘텀의 부호. 모델이 아니라 규칙이고, 이 실험의 진짜 상대다.
e_적응상수
기준선 하나 — 후행 120영업일의 다수 클래스.
쓴 데이터 — 앞선 실험의 피처 캐시를 그대로 읽었다. 새로 만든 원천이 없다. 결측률은 유효 1,847일 전체에서 센 값이다.
원천기간해상도행수열수결측쓰임
3년 국채선물 근월 (g1_)2016-12-20 ~ 2026-09-181분봉1,847240.06%모멘텀·변동폭·위치. 봉 컷오프 15:34:00
10년선물·커브 (g1p_)같음1분봉1,84760.11%장기 구간과의 관계
장중 투자자 수급 (g2_)2019-01-02 ~ 2026-09-1830초 증분1,8472819.98%수급 컷오프 15:34:00. 2017~18 은 전부 결측이라 이 그룹을 쓰는 묶음은 학습이 2019 부터다
일별·캘린더 (g6_)2016 ~ 2026-09-18일별1,847370.60%전일까지만 쓴다
선물 일봉 전필드 (g7_)2016 ~ 2026-09-18일별 종가 기준1,847480.21%전일 값만. 호가·베이시스·투자자 평균단가
한국은행 국고채 단순매입 (g8_)2019 ~ 2026-09-18사건1,847666.60%공개시장운영 축. 결측이 커서 141열 묶음에서 8열이 분산 0 으로 떨어진다
표본2016-12-20 ~ 2026-09-18일별(라벨)1,847204원시 2,394일에서 장 이상일과 ref_tick = 0 인 날을 뺀 것
분할 — 연도 확장창 워크포워드. 열수는 실측이다(분산 0 열이 폴드 안에서 떨어진다).
피처 묶음그룹선언 열실측 열학습 시작학습 행시험연도시험 행
T0_core 봉·커브·일별달력g1_ g1p_ g6_67652017344 → 1,6932019~20261,497
T4_daily +일봉 전필드+g7_1151132017344 → 1,6932019~20261,497
T1_flow34 +장중 수급+g2_95932019361 → 1,3492021~20261,136
T5_all 새 데이터 전부+g2_ g7_ g8_1491412019361 → 1,3492021~20261,136

전 그룹 204열 묶음은 뺐다 — 첫 학습 폴드의 결측이 42.9% 라 중앙값으로 채운 뒤 재는 승률은 모델이 아니라 대치 방식을 재는 것에 가깝다. 사전등록에 뺀 이유를 적었고 결과를 보고 다시 넣지 않았다.

어떻게 쟀나

사전등록(protocol.md)을 결과 보기 전에 썼고 실행 뒤에 고치지 않았다. 문턱을 두 번 올렸고 두 번 다 결과를 보기 전이다 — 그 사실은 커밋 순서가 증언한다(사전등록 → 문턱 조임 → 라운드 0 → 결과).

티어 넷의 학습·시험창과 T1_flow34 폴드 여섯
(가) 티어 넷의 학습 시작과 시험 구간. T0_core· T4_daily 는 2017 부터 학습해 여덟 해를 시험하고(n=1,497), 수급을 쓰는 T1_flow34·T5_all 은 2019 부터라 여섯 해다(n=1,136). 열 수는 실측값이다 — 분산 0 열이 폴드 안에서 떨어져 선언값(67·115·95·149)보다 적다. (나) T1_flow34 의 폴드 여섯 — 학습이 361일에서 1,349일로 자란다. 막대 안 일수는 정본 런이 직접 기록한 n_train 이다.
판정 규칙 — 사전등록 §4. 세 조건을 모두 넘어야 지지다.
조건무엇
승률비교 대상을 넘는다당연한 최소 조건
유의성같은 시험일에 짝지은 McNemar 양측 p < 0.05불일치 쌍 정확 이항검정. 승률이 높아도 유의하지 않으면 "차이가 있다" 고 쓰지 않는다
흔들림차이 > spread_deploy × 2신경망은 시드가 결론을 흔든다. 0005 의 mlp 폴드 흔들림 중위가 배깅트리의 약 4배였다

0005·0006 과 세 곳을 다르게 했고 이유를 결과 보기 전에 박았다. 시드 3개 → 10개(신경망의 시드 취약성을 재는 것 자체가 이 실험의 일부다). 흔들림 통계를 배포 형태에 맞췄다(0006 은 배포하지 않는 물건의 흔들림으로 12개 조합을 떨어뜨리고 그 보수성을 사후에 적었다). 머릿수를 정직 선택값으로만 판정한다(0006 이 사후↔정직 간극을 1.4%p 로 실측했다).

학습된 모델 셋

모델 일곱 종 — 같은 폴드에서 무엇을 학습하나

아래 그림은 모식도가 아니다. code/render_model7.pyT1_flow34 시험 2026 폴드를 다시 적합해 커밋된 확률이 그대로 나오는지 확인한 뒤, 적합된 객체에서 읽은 값만으로 그린다(docs/AUTORESEARCH.md §1). 일곱을 같은 폴드에 세운 것은 구조를 나란히 읽게 하려는 것이다 — 승률은 이 폴드 하나가 아니라 워크포워드 전체에서 잰 값이고 아래 결과 절에 있다.

설정 격자 전수 — 정본은 code/nnmodels.py_GRID 다. #00 은 각 모델의 기준 설정이고 mlp_sk#00 은 앞선 실험이 쓴 설정 그대로다.
모델계열설정 수설정
perc퍼셉트론·선형3perc#00 · penalty=None · alpha=0.0
perc#01 · penalty=l2 · alpha=0.0001
perc#02 · penalty=l2 · alpha=0.01
sgd_log퍼셉트론·선형6sgd_log#00 · alpha=0.0001 · penalty=l2
sgd_log#01 · alpha=0.001 · penalty=l2
sgd_log#02 · alpha=0.01 · penalty=l2
sgd_log#03 · alpha=0.0001 · penalty=elasticnet
sgd_log#04 · alpha=0.001 · penalty=elasticnet
sgd_log#05 · alpha=0.01 · penalty=elasticnet
sgd_hinge퍼셉트론·선형4sgd_hinge#00 · alpha=0.0001
sgd_hinge#01 · alpha=0.001
sgd_hinge#02 · alpha=0.01
sgd_hinge#03 · alpha=0.1
mlp_sk얕은신경망16mlp_sk#00 · hidden_layer_sizes=(32, 16) · alpha=0.01 · early_stopping=True
mlp_sk#01 · hidden_layer_sizes=(32, 16) · alpha=0.01 · early_stopping=False
mlp_sk#02 · hidden_layer_sizes=(16,) · alpha=0.01 · early_stopping=True
mlp_sk#03 · hidden_layer_sizes=(64,) · alpha=0.01 · early_stopping=True
mlp_sk#04 · hidden_layer_sizes=(256,) · alpha=0.01 · early_stopping=True
mlp_sk#05 · hidden_layer_sizes=(64, 32) · alpha=0.01 · early_stopping=True
mlp_sk#06 · hidden_layer_sizes=(128, 64) · alpha=0.01 · early_stopping=True
mlp_sk#07 · hidden_layer_sizes=(128, 64, 32) · alpha=0.01 · early_stopping=True
mlp_sk#08 · hidden_layer_sizes=(64, 32) · alpha=0.1 · early_stopping=True
mlp_sk#09 · hidden_layer_sizes=(64, 32) · alpha=0.001 · early_stopping=True
mlp_sk#10 · hidden_layer_sizes=(64, 32) · alpha=1.0 · early_stopping=True
mlp_sk#11 · hidden_layer_sizes=(64, 32) · alpha=0.01 · early_stopping=False
mlp_sk#12 · hidden_layer_sizes=(64, 32) · alpha=0.01 · early_stopping=True · activation=tanh
mlp_sk#13 · hidden_layer_sizes=(64, 32) · alpha=0.01 · early_stopping=True · learning_rate_init=0.01
mlp_sk#14 · hidden_layer_sizes=(64, 32) · alpha=0.01 · early_stopping=True · learning_rate_init=0.0001
mlp_sk#15 · hidden_layer_sizes=(256, 128) · alpha=1.0 · early_stopping=True
mlp_t얕은신경망12mlp_t#00 · d_layers=(64, 32) · dropout=0.1 · swa=False
mlp_t#01 · d_layers=(64, 32) · dropout=0.3 · swa=False
mlp_t#02 · d_layers=(64, 32) · dropout=0.1 · swa=True
mlp_t#03 · d_layers=(128, 64) · dropout=0.1 · swa=False
mlp_t#04 · d_layers=(128, 64) · dropout=0.3 · swa=False
mlp_t#05 · d_layers=(128, 64) · dropout=0.3 · swa=True
mlp_t#06 · d_layers=(256, 128) · dropout=0.3 · swa=False
mlp_t#07 · d_layers=(32,) · dropout=0.1 · swa=False
mlp_t#08 · d_layers=(32,) · dropout=0.1 · swa=True
mlp_t#09 · d_layers=(128, 64, 32) · dropout=0.3 · swa=False
mlp_t#10 · d_layers=(128, 64) · dropout=0.1 · weight_decay=0.1 · swa=False
mlp_t#11 · d_layers=(128, 64) · dropout=0.1 · lr=0.0003 · swa=False
resnet_t깊은신경망6resnet_t#00 · n_blocks=2 · d_main=64 · dropout=0.1
resnet_t#01 · n_blocks=2 · d_main=128 · dropout=0.3
resnet_t#02 · n_blocks=3 · d_main=64 · dropout=0.3
resnet_t#03 · n_blocks=3 · d_main=128 · dropout=0.3
resnet_t#04 · n_blocks=4 · d_main=64 · dropout=0.3
resnet_t#05 · n_blocks=2 · d_main=256 · dropout=0.5
emb_mlp임베딩신경망8emb_mlp#00 · emb=ple · n_bins=16 · d_embedding=16 · d_layers=(64, 32) · dropout=0.1
emb_mlp#01 · emb=ple · n_bins=8 · d_embedding=16 · d_layers=(64, 32) · dropout=0.1
emb_mlp#02 · emb=ple · n_bins=24 · d_embedding=16 · d_layers=(64, 32) · dropout=0.1
emb_mlp#03 · emb=ple · n_bins=16 · d_embedding=24 · d_layers=(128, 64) · dropout=0.1
emb_mlp#04 · emb=ple · n_bins=16 · d_embedding=16 · d_layers=(64, 32) · dropout=0.3
emb_mlp#05 · emb=periodic · d_embedding=16 · d_layers=(64, 32) · dropout=0.1
emb_mlp#06 · emb=periodic · d_embedding=24 · d_layers=(128, 64) · dropout=0.1
emb_mlp#07 · emb=periodic · d_embedding=16 · d_layers=(64, 32) · dropout=0.3
합계계열 455티어 4종 × 시드 10개 = 15,400 적합

격자에서 뺀 모델ft_tr: 라운드 0 실측: 가장 싼 설정(d_token=64·n_blocks=2)이 큰 폴드에서 1,362.6초 — 사전등록 상한 90초의 15배. 한 단계 더 줄여도(d_token=32·n_blocks=1) 약 170초로 1.9배. 본 스윕 예산의 94%(280.9/298.3시간).

퍼셉트론 원형 perc

틀린 날에만 가중치를 그 날 피처만큼 밀어 주는, 1958년의 그 규칙이다. 은닉층이 없어 결정 경계가 초평면 하나다. 확률이 없어 결정함수를 학습 마진의 표준편차로 눌러 0.5 주변 기울기를 맞췄다 — 부호만 쓰는 채점이라 그 변환은 순위를 바꾸지 않는다.

그림 A · 개요 — perc#00 · T1_flow34 시험 2026 입력 데이터 3년 국채선물 근월 1분봉 + 10년·커브 + 일별·캘린더 + 장중 투자자 수급 2016-12-20 ~ 2026-09-18 · 유효 1,847일 · 수급 컷오프 15:34:00 피처 95열 → 실제 93열 중앙값 대치 · 표준화 · 분산 0 열 제거 전처리는 학습창만 보고 적합한다 Perceptron — penalty=None · alpha=0.0 1. 결측 대치 학습창 중앙값으로 채운다(시험연도를 보지 않는다) 2. 표준화 학습창 평균·표준편차로 z 화 — 계수가 서로 비교 가능해진다 3. 선형 결합 z = b + Σ wᵢ·xᵢ (계수 93개) 4. 링크 z → 예상 틱, 부호가 방향 출력 P(ref_tick > 0) 0.5 로 부호를 가른다 계수 — 세팅과 학습 결과 피처 93개 표준화된 공간의 계수 — 서로 크기 비교가 된다 0 이 아닌 계수 93개 절편 b = -4.0000 모든 피처가 학습창 평균일 때의 출발점 평균적인 ref_tick 변화 |w| 최대 = 29.0939 가장 센 피처: g1p_f10_ret_open |w| 중앙값 4.2913 alpha = 0.0 릿지 벌점 클수록 계수를 더 눌러 붙인다
은닉층이 없다 — 결정 경계가 초평면 하나다. 전처리 세 단계는 학습창만 보고 적합한다. 입력이 93열인 것은 분산 0 열이 이 폴드에서 떨어진 결과다(선언 95열).
그림 B · 계수 — perc#00 (표준화 공간, 절대값 상위) ← 하락 쪽 상승 쪽 → g1p_f10_ret_open +29.0939 g2_은행_last30_share -26.9234 g2_보험_last30_share +19.7700 g1_ma_dev_60m +18.3686 g6_baserate_120d -15.9671 g6_is_auction_day -15.5109 g1_rng_20m +14.7685 g1_ret_120m -13.8775 g2_증권_last30_share +13.5791 g6_vol_60d +13.4206 g2_보험_chg_30m +13.4100 g6_baserate_250d +13.3528 g6_prev_ref_tick +13.1008 g2_기금_chg_60m -12.4347 g6_dflow_투신순매수수량 -12.3553 g2_기금_lvl -9.9203 표준화된 공간의 계수 상위 16개 · 절편 b = -4.0000 · 전체 93개 중
표준화된 공간의 계수라 서로 크기 비교가 된다. 적합된 coef_ 에서 읽은 값이다.

확률적 경사하강 · 로그 손실 sgd_log

같은 초평면을 로지스틱 손실로 찾는다. 퍼셉트론과 다른 것은 손실 하나뿐이라, 둘의 차이가 «틀린 날만 보나 vs 확신까지 보나» 를 가른다.

그림 A · 개요 — sgd_log#00 · T1_flow34 시험 2026 입력 데이터 3년 국채선물 근월 1분봉 + 10년·커브 + 일별·캘린더 + 장중 투자자 수급 2016-12-20 ~ 2026-09-18 · 유효 1,847일 · 수급 컷오프 15:34:00 피처 95열 → 실제 93열 중앙값 대치 · 표준화 · 분산 0 열 제거 전처리는 학습창만 보고 적합한다 SGDClassifier — alpha=0.0001 · penalty=l2 1. 결측 대치 학습창 중앙값으로 채운다(시험연도를 보지 않는다) 2. 표준화 학습창 평균·표준편차로 z 화 — 계수가 서로 비교 가능해진다 3. 선형 결합 z = b + Σ wᵢ·xᵢ (계수 93개) 4. 링크 σ(z) → 확률 출력 P(ref_tick > 0) 0.5 로 부호를 가른다 계수 — 세팅과 학습 결과 피처 93개 표준화된 공간의 계수 — 서로 크기 비교가 된다 0 이 아닌 계수 93개 절편 b = +0.2767 모든 피처가 학습창 평균일 때의 출발점 기저율 쏠림이 여기에 담긴다 |w| 최대 = 3.5584 가장 센 피처: g2_외국인합_lvl |w| 중앙값 0.3589 alpha = 0.0001 릿지 벌점 클수록 계수를 더 눌러 붙인다
은닉층이 없다 — 결정 경계가 초평면 하나다. 전처리 세 단계는 학습창만 보고 적합한다. 입력이 93열인 것은 분산 0 열이 이 폴드에서 떨어진 결과다(선언 95열).
그림 B · 계수 — sgd_log#00 (표준화 공간, 절대값 상위) ← 하락 쪽 상승 쪽 → g2_외국인합_lvl -3.5584 g2_증권_lvl -3.0357 g6_dflow_증권선물순매수수량 -2.0468 g6_dflow_외국인합순매수수량 -1.9490 g2_은행_lvl -1.7976 g2_외국인합_last30_share -1.7565 g6_dflow_은행순매수수량 -1.3236 g1_ma_dev_20m +1.2339 g1_ret_120m -1.1554 g6_vol_60d +1.0906 g1_ma_dev_60m +1.0847 g6_baserate_120d -1.0723 g6_rate_통안1년 -1.0426 g1_pos_20m -1.0124 g2_투신_last30_share -0.9813 g1p_f10_ret_open +0.9413 표준화된 공간의 계수 상위 16개 · 절편 b = +0.2767 · 전체 93개 중
표준화된 공간의 계수라 서로 크기 비교가 된다. 적합된 coef_ 에서 읽은 값이다.

확률적 경사하강 · 힌지 손실 sgd_hinge

여유(margin)를 두고 가르는 손실이다. 선형 SVM 과 같은 목적을 온라인으로 푼다. T5_all 의 정직 선택이 2022년에 이것을 골랐다.

그림 A · 개요 — sgd_hinge#00 · T1_flow34 시험 2026 입력 데이터 3년 국채선물 근월 1분봉 + 10년·커브 + 일별·캘린더 + 장중 투자자 수급 2016-12-20 ~ 2026-09-18 · 유효 1,847일 · 수급 컷오프 15:34:00 피처 95열 → 실제 93열 중앙값 대치 · 표준화 · 분산 0 열 제거 전처리는 학습창만 보고 적합한다 SGDClassifier — alpha=0.0001 1. 결측 대치 학습창 중앙값으로 채운다(시험연도를 보지 않는다) 2. 표준화 학습창 평균·표준편차로 z 화 — 계수가 서로 비교 가능해진다 3. 선형 결합 z = b + Σ wᵢ·xᵢ (계수 93개) 4. 링크 z → 예상 틱, 부호가 방향 출력 P(ref_tick > 0) 0.5 로 부호를 가른다 계수 — 세팅과 학습 결과 피처 93개 표준화된 공간의 계수 — 서로 크기 비교가 된다 0 이 아닌 계수 93개 절편 b = -0.4935 모든 피처가 학습창 평균일 때의 출발점 평균적인 ref_tick 변화 |w| 최대 = 4.0876 가장 센 피처: g2_증권_lvl |w| 중앙값 0.5699 alpha = 0.0001 릿지 벌점 클수록 계수를 더 눌러 붙인다
은닉층이 없다 — 결정 경계가 초평면 하나다. 전처리 세 단계는 학습창만 보고 적합한다. 입력이 93열인 것은 분산 0 열이 이 폴드에서 떨어진 결과다(선언 95열).
그림 B · 계수 — sgd_hinge#00 (표준화 공간, 절대값 상위) ← 하락 쪽 상승 쪽 → g2_증권_lvl -4.0876 g2_외국인합_lvl -3.5308 g6_dflow_증권선물순매수수량 -3.0834 g1_pos_60m +2.5030 g6_dflow_외국인합순매수수량 -2.2757 g1_ret_120m -2.1611 g2_투신_last30_share -2.1356 g6_dow +1.9825 g2_은행_lvl -1.7470 g1_ma_dev_60m +1.7355 g1_ret_open -1.6827 g2_외국인합_last30_share -1.6643 g2_개인_lvl -1.6084 g6_px_chg_20d +1.5876 g6_rate_통안1년 -1.5335 g2_투신_chg_30m -1.3609 표준화된 공간의 계수 상위 16개 · 절편 b = -0.4935 · 전체 93개 중
표준화된 공간의 계수라 서로 크기 비교가 된다. 적합된 coef_ 에서 읽은 값이다.

sklearn 다층 퍼셉트론 — 0005 가 쓴 그 설정 mlp_sk#00

은닉 두 층(32·16)에 L2 벌점 0.01, 조기 종료를 켠 구성이다. 앞선 실험의 신경망은 이것 하나였고 0007 은 이 자리에서 시작한다 — H17 의 비교가 같은 코드 경로 위에서 성립하게 #00 에 박았다.

그림 A · 개요 — mlp_sk#00 · T1_flow34 시험 2026 입력 데이터 3년 국채선물 근월 1분봉 + 10년·커브 + 일별·캘린더 + 장중 투자자 수급 2016-12-20 ~ 2026-09-18 · 유효 1,847일 · 수급 컷오프 15:34:00 피처 95열 → 실제 93열 중앙값 대치 · 표준화 · 분산 0 열 제거 전처리는 학습창만 보고 적합한다 MLPClassifier — hidden_layer_sizes=(32, 16) · alpha=0.01 · early_stopping=True 1. 결측 대치 학습창 중앙값으로 채운다(시험연도를 보지 않는다) 2. 표준화 학습창 평균 0 · 표준편차 1 3. 순전파 3개 가중치 층을 지난다 4. 역전파 학습 adam · 손실 log-loss 출력 P(ref_tick > 0) 0.5 로 부호를 가른다 세팅과 학습 결과 hidden_layer_sizes = (32, 16) 은닉층의 폭 — 세팅 실현: 가중치 층 3개 · 파라미터 3,553개 alpha = 0.01 L2 벌점 — 클수록 가중치를 0 쪽으로 민다 learning_rate_init = 0.001 adam 의 초기 보폭 실현: 마지막 손실 0.5046 max_iter = 600 반복 상한 — 세팅 실현: 37 반복에서 멈췄다 early_stopping = True 검증 0.1 로 20회 나아지지 않으면 멈춘다 검증 최고 0.6519 ŷ(x) = softmax(W₂ · relu(W₁ · relu(W₀x + b₀) + b₁) + b₂) T1_flow34 · 시험 2026 (학습 1,349행 · 시험 148일) · 시드 0
0005 의 mlp 설정 그대로다 — H17 의 비교가 같은 코드 경로 위에서 성립하게 #00 에 박았다. 전처리 세 단계는 학습창만 보고 적합한다.
그림 B · 층 구조 — 가중치 층 3개 · 파라미터 3,553개 깊이 = 가중치 층 3개 (은닉 2개 + 출력 1개) · 파라미터 3,553개 입력 피처 93개 표준화된 값 은닉 1 층 93 → 32 활성 relu 가중치 93×32 편향 32 파라미터 3,008 층 1 은닉 2 층 32 → 16 활성 relu 가중치 32×16 편향 16 파라미터 528 층 2 출력 층 16 → 1 활성 logistic 가중치 16×1 편향 1 파라미터 17 층 3 출력 P(상승) 0.5 기준 방향 ← 깊이 3 층 →
층·모양·파라미터 수는 적합된 coefs_에서 읽은 값이다. 입력이 93열인 것은 분산 0 열 둘이 이 폴드에서 떨어진 결과다(선언 95열).
그림 C · 손실 곡선 — 세팅 상한과 실제로 멈춘 반복 멈춘 지점 — 반복 37 최대 반복 600 손실 0.7524 손실 0.5046 (최저) 조기 종료 켬 · 검증 최고 정확도 0.6519
37 반복에서 멈췄다. 세팅 상한은 max_iter=600 이고 조기 종료가 먼저 물었다.

torch 다층 퍼셉트론 mlp_t#00

같은 은닉 구조를 직접 학습한다. sklearn 으로는 못 쓰는 것들이 여기 들어간다 — 층마다 층 정규화드롭아웃, AdamW코사인 스케줄, 라벨 평활 0.05. H19 의 짝 비교에서 임베딩 쪽의 상대다.

그림 A · 구조 — mlp_t#00 · T1_flow34 시험 2026 T1_flow34 · 시험 2026 (학습 1,349행 · 시험 148일) · 시드 0 · 에폭 60/200 · 배치 128 · 검증 뒷부분 135행 입력 — 피처 93개(표준화·분산 0 열 제외) · 출력 — 2class logit → softmax → P(ref_tick > 0) 0 Linear 93 → 64 파라미터 6,016 weight [64, 93] bias [64] 1 1 LayerNorm 정규화 64 파라미터 128 weight [64] bias [64] 2 4 Linear 64 → 32 파라미터 2,080 weight [32, 64] bias [32] 3 5 LayerNorm 정규화 32 파라미터 64 weight [32] bias [32] 4 8 Linear 32 → 2 파라미터 66 weight [2, 32] bias [2] 5 파라미터 합계 8,354개 · 파라미터를 가진 모듈 5개 (번호가 순전파 순서다)
상자 하나가 파라미터를 가진 모듈 하나이고 번호가 순전파 순서다. 이름·모양·원소 수는 적합된 모듈의 named_parameters() 에서 읽었다 — 손으로 적은 숫자가 없다. 상자 안의 텐서는 앞의 둘만 적었고 전수는 아래 표에 있다.
mlp_t#00 의 파라미터 텐서 전수 — T1_flow34 시험 2026 · 시드 0.
#모듈종류텐서모양원소 수
10Linearweight[64, 93]5,952
bias[64]64
21LayerNormweight[64]64
bias[64]64
34Linearweight[32, 64]2,048
bias[32]32
45LayerNormweight[32]32
bias[32]32
58Linearweight[2, 32]64
bias[2]2
합계10개 텐서8,354
그림 B · 학습 손실 — mlp_t#00 · T1_flow34 시험 2026 멈춘 지점 — 반복 60 최대 반복 200 손실 0.7526 손실 0.2049 (최저) 조기 종료 켬
에폭당 학습 손실이다. 60에폭에서 멈췄다 — 사전등록 상한 200에폭이 아니라 min_epochs=60 바닥이 멈춤 지점을 정했다. 검증 집합이 135행뿐이라 조기 종료 신호가 잡음이기 때문이다(protocol.md §8-2).

잔차 연결 다층 퍼셉트론 resnet_t#00

층을 더 쌓되 각 블록이 입력을 그대로 더해 통과시킨다. 깊이를 늘려도 학습이 무너지지 않게 하는 구조이고, T5_all(141열)의 정직 선택이 이것을 골랐다.

그림 A · 구조 — resnet_t#00 · T1_flow34 시험 2026 T1_flow34 · 시험 2026 (학습 1,349행 · 시험 148일) · 시드 0 · 에폭 60/200 · 배치 128 · 검증 뒷부분 135행 입력 — 피처 93개(표준화·분산 0 열 제외) · 출력 — 2class logit → softmax → P(ref_tick > 0) first Linear 93 → 64 파라미터 6,016 weight [64, 93] bias [64] 1 blocks.0.norm LayerNorm 정규화 64 파라미터 128 weight [64] bias [64] 2 blocks.0.lin1 Linear 64 → 128 파라미터 8,320 weight [128, 64] bias [128] 3 blocks.0.lin2 Linear 128 → 64 파라미터 8,256 weight [64, 128] bias [64] 4 blocks.1.norm LayerNorm 정규화 64 파라미터 128 weight [64] bias [64] 5 blocks.1.lin1 Linear 64 → 128 파라미터 8,320 weight [128, 64] bias [128] 6 blocks.1.lin2 Linear 128 → 64 파라미터 8,256 weight [64, 128] bias [64] 7 head.0 LayerNorm 정규화 64 파라미터 128 weight [64] bias [64] 8 head.2 Linear 64 → 2 파라미터 130 weight [2, 64] bias [2] 9 파라미터 합계 39,682개 · 파라미터를 가진 모듈 9개 (번호가 순전파 순서다)
상자 하나가 파라미터를 가진 모듈 하나이고 번호가 순전파 순서다. 이름·모양·원소 수는 적합된 모듈의 named_parameters() 에서 읽었다 — 손으로 적은 숫자가 없다. 상자 안의 텐서는 앞의 둘만 적었고 전수는 아래 표에 있다.
resnet_t#00 의 파라미터 텐서 전수 — T1_flow34 시험 2026 · 시드 0.
#모듈종류텐서모양원소 수
1firstLinearweight[64, 93]5,952
bias[64]64
2blocks.0.normLayerNormweight[64]64
bias[64]64
3blocks.0.lin1Linearweight[128, 64]8,192
bias[128]128
4blocks.0.lin2Linearweight[64, 128]8,192
bias[64]64
5blocks.1.normLayerNormweight[64]64
bias[64]64
6blocks.1.lin1Linearweight[128, 64]8,192
bias[128]128
7blocks.1.lin2Linearweight[64, 128]8,192
bias[64]64
8head.0LayerNormweight[64]64
bias[64]64
9head.2Linearweight[2, 64]128
bias[2]2
합계18개 텐서39,682
그림 B · 학습 손실 — resnet_t#00 · T1_flow34 시험 2026 멈춘 지점 — 반복 60 최대 반복 200 손실 0.6965 손실 0.1300 (최저) 조기 종료 켬
에폭당 학습 손실이다. 60에폭에서 멈췄다 — 사전등록 상한 200에폭이 아니라 min_epochs=60 바닥이 멈춤 지점을 정했다. 검증 집합이 135행뿐이라 조기 종료 신호가 잡음이기 때문이다(protocol.md §8-2).

임베딩 다층 퍼셉트론 emb_mlp#06 — H18 이 지지된 자리

수치 피처 하나를 주기 함수 묶음으로 펼쳐 24차원 벡터로 만든 뒤 다층 퍼셉트론에 넣는다. 표 데이터에서 다층 퍼셉트론의 이득이 가장 큰 기법으로 보고된 축이고, 이 실험에서 계열 1위가 됐다 — 다만 그 순서를 «차이» 라고 부를 근거는 없다(H19 미지지).

그림 A · 구조 — emb_mlp#06 · T1_flow34 시험 2026 T1_flow34 · 시험 2026 (학습 1,349행 · 시험 148일) · 시드 0 · 에폭 60/200 · 배치 128 · 검증 뒷부분 135행 입력 — 피처 93개(표준화·분산 0 열 제외) · 출력 — 2class logit → softmax → P(ref_tick > 0) emb PeriodicEmbeddings 파라미터 220,968 periodic.weight [93, 48] linear.weight [93, 96, 24] 1 body.0 Linear 2232 → 128 파라미터 285,824 weight [128, 2232] bias [128] 2 body.1 LayerNorm 정규화 128 파라미터 256 weight [128] bias [128] 3 body.4 Linear 128 → 64 파라미터 8,256 weight [64, 128] bias [64] 4 body.5 LayerNorm 정규화 64 파라미터 128 weight [64] bias [64] 5 body.8 Linear 64 → 2 파라미터 130 weight [2, 64] bias [2] 6 파라미터 합계 515,562개 · 파라미터를 가진 모듈 6개 (번호가 순전파 순서다)
상자 하나가 파라미터를 가진 모듈 하나이고 번호가 순전파 순서다. 이름·모양·원소 수는 적합된 모듈의 named_parameters() 에서 읽었다 — 손으로 적은 숫자가 없다. 상자 안의 텐서는 앞의 둘만 적었고 전수는 아래 표에 있다.
emb_mlp#06 의 파라미터 텐서 전수 — T1_flow34 시험 2026 · 시드 0.
#모듈종류텐서모양원소 수
1embPeriodicEmbeddingsperiodic.weight[93, 48]4,464
linear.weight[93, 96, 24]214,272
linear.bias[93, 24]2,232
2body.0Linearweight[128, 2232]285,696
bias[128]128
3body.1LayerNormweight[128]128
bias[128]128
4body.4Linearweight[64, 128]8,192
bias[64]64
5body.5LayerNormweight[64]64
bias[64]64
6body.8Linearweight[2, 64]128
bias[2]2
합계13개 텐서515,562
그림 B · 학습 손실 — emb_mlp#06 · T1_flow34 시험 2026 멈춘 지점 — 반복 60 최대 반복 200 손실 0.7428 손실 0.1305 (최저) 조기 종료 켬
에폭당 학습 손실이다. 60에폭에서 멈췄다 — 사전등록 상한 200에폭이 아니라 min_epochs=60 바닥이 멈춤 지점을 정했다. 검증 집합이 135행뿐이라 조기 종료 신호가 잡음이기 때문이다(protocol.md §8-2).

결과 — 티어 넷

티어별 정직 선택 승률과 비교 대상 둘, 판정 문턱
남색이 0007 의 신경망, 주황이 0005 의 트리, 회색이 20분 모멘텀 규칙이다. 신경망 막대의 오차 막대가 판정 문턱(±2×spread_deploy) 이다. T1_flow34 에서만 남색이 주황을 넘는다 — 그리고 그 자리에서 남색과 회색이 거의 같다. T4_daily 는 반대로 주황이 가장 높다.
H18 — 정본 results/20260922_144439_nn/. 머릿수는 전부 정직 선택값이다.
티어n신경망 정직누적틱e_0005정직문턱 ±2σMcNemar p판정
T0_core1,4970.5665+4410.5905−0.02400.01780.0642미지지
T4_daily1,4970.5785+5150.5999−0.02140.01100.0676미지지
T1_flow341,1360.5960+5510.5678+0.02820.01200.0416지지
T5_all1,1360.5757+4090.5766−0.00090.01711.0000동급

T5_all 의 동급은 사전등록 정의를 그대로 만족한다 — 차이 0.0009 가 문턱 0.0171 안이고 p=1.0000 이다. "신경망이 트리와 같다" 가 아니라 "이 표본에서 둘을 가르지 못했다" 고 읽는다.

e_0005정직 은 저장소에 두 절차로 두 숫자가 있었다. 0005 의 run2.honest_pick(동률을 이름 순으로, 첫 해 대체가 et)와 0006 의 prior_ranking(동률을 열 순서로, 첫 해 대체가 순위 첫 열)이다. 둘 다 정당하므로 티어별로 큰 쪽을 박았다 — 어느 동률 규칙을 쓰든 신경망이 넘어야 한다. 문턱을 높이는 선택이고, 결과를 보기 전에 했다.

H18b — 0005 라운드 2 의 튠한 트리(격자 171구성)와 일자 단위 짝 비교. 규칙은 사전등록 §3-2 에 미리 박았다.
티어신경망 정직튠한 트리 정직문턱 ±2σMcNemar p짝 일수판정
T0_core0.56650.5752−0.00870.01780.54401,497동급
T4_daily0.57850.5965−0.01800.01100.13901,497미지지
T1_flow340.59600.5687+0.02730.01200.05911,136미지지
T5_all0.57570.5731+0.00260.01710.90111,136동급

T1_flow34 의 승이 여기서 사라진다. 승률 차이(+2.73%p)와 흔들림 문턱은 그대로 통과하는데 McNemar 가 0.0416 에서 0.0591 로 올라 문턱 0.05 를 넘는다. 사전등록 문장은 셋을 다 요구한다.

T4_daily 와 T1_flow34 의 연도별 승률과 규칙
사전등록 §4-2 7번이 이 표 없이 판정하지 말라고 요구한 자리다. T4_daily 의 초반 두 폴드(학습 344일·522일)가 0.5393 · 0.4809 로 무너지고, 학습이 705일을 넘는 2021 부터 0.6289 로 올라온다. 합산 승률만 보면 안 보인다. T1_flow34 는 여섯 해 전부 56% 이상이지만 규칙(점선)을 넘은 해는 2023·2025 둘뿐이고 2026 은 규칙에 4.7%p 뒤진다.

규칙을 못 넘었다

기준선 대조 — 이 절이 이 실험의 핵심이다.
티어신경망 정직e_규칙문턱 ±2σ규칙 대비 McNemar pe_적응상수사후 최고
T0_core0.56650.5878−0.02140.01780.15870.55040.6019
T4_daily0.57850.5878−0.00940.01100.51570.55040.6005
T1_flow340.59600.5933+0.00260.01200.90370.55370.5968
T5_all0.57570.5933−0.01760.01710.32460.55370.6004

네 티어 중 규칙을 넘은 것은 하나뿐이고, 그 하나도 +0.26%p · p=0.9037 이다 — 문턱 0.0120 의 5분의 1에 못 미친다. 적응상수는 네 티어 다 넘는다.

대조가 이 실험의 결론을 정한다. 0005 라운드 1 의 트리는 T4_daily 에서 규칙을 +1.21%p 넘었다(정직 0.5999 대 0.5878). 신경망은 그 티어에서 0.5785 로 규칙 아래다. 즉 H18 이 지지된 자리는 트리가 가장 약한 티어이고, 그 티어에서는 신경망도 규칙 수준이다. 신경망이 이긴 것은 상대가 약한 자리였다.

흔들림을 다시 정의한 자리

사전등록 §4-1 에서 흔들림 통계를 배포하는 물건(시드 평균)에 맞춰 다시 정의했다. 0006 은 배포하지 않는 물건(단일 시드 모델)의 흔들림으로 12개 조합을 전부 떨어뜨리고 그 보수성을 결과를 본 뒤에 적었다. 0007 은 먼저 적었다.

바꾼 정의가 판정을 사 왔는지 옛 정의로도 다시 재서 확인한다.

문턱 두 정의로 다시 잰 H18 — 판정이 하나도 바뀌지 않는다.
티어차이새 문턱 (배포 ×2)옛 문턱 (단일시드 ×2)새 정의옛 정의
T0_core−0.02400.01780.0387못 통과못 통과
T4_daily−0.02140.01100.0191못 통과못 통과
T1_flow34+0.02820.01200.0260통과통과
T5_all−0.00090.01710.0266동급동급

T1_flow34 는 옛 문턱(0.0260)으로도 차이 0.0282 가 넘는다 — 간발이지만 넘는다. 재정의는 판정을 사 온 것이 아니고, 0006 이 사후에 "보수적이었다" 고 적은 자리를 사전에 정리한 것이다.

설정 220개의 배포 흔들림 대 단일시드 흔들림
점 하나가 설정 하나(티어 4 × 설정 55 = 220개)다. 무리가 두 선 사이에 놓이고 중위가 절반 선 쪽이다 — 감소 배율 중위 1.80배 (사분위 1.48~2.14). 예측한 √5 ≈ 2.24배에는 못 미치고, 설정 28% 는 1.5배 미만으로 단일시드와 크게 다르지 않다. 세로 점선은 0005 의 mlp 폴드 흔들림 중위 0.0275 다. 시드 열 개를 평균하는 것만으로 신경망의 시드 취약성이 배깅트리 수준(0.0071)까지 내려온다 — 배포 중위가 0.0049~0.0070 이다.

계열 순서 — 예측이 틀렸다

사전등록 §6 에 이렇게 적었다: "학습 폴드가 344~1,693행이라 용량이 구속 조건이므로 용량이 작은 쪽이 이긴다." 표 데이터 딥러닝 문헌의 순서(임베딩 > FT-T ≈ ResNet > MLP)와 다르게 적은 것이 이 실험의 예측이었다.

관측은 반대다. 임베딩(파라미터 515,562개)이 맨 MLP(23,362개)를 이겼다.

계열 중위 승률 — H20′ 판정의 근거. 모델별 정직 선택값의 중위다.
계열중위 승률사전등록 자리관측 자리
임베딩신경망 (emb_mlp)0.58552위1위
깊은신경망 (resnet_t)0.57593위2위
얕은신경망 (mlp_sk·mlp_t)0.57551위3위
퍼셉트론·선형 (perc·sgd_*)0.53274위4위
계열별 설정 승률 분포와 모델별 정직 선택
회색 점이 설정 하나(사후), 남색 다이아가 모델×티어 정직 선택, 주황 막대가 계열 중위다. 앞 세 자리가 뒤집혔지만 차이가 작다 — 임베딩과 얕은신경망의 중위 차이가 1.00%p 인데 계열 흔들림 문턱이 0.01 안팎이다. 그래서 관측 순서를 근거로 "임베딩이 낫다" 고도 쓰지 않는다. 같은 폭·깊이로 짝지어 비교한 H19 가 미지지(짝 여덟 개 전부 p ≥ 0.3155)인 것과 같은 말이다.

맞은 것 하나 — 퍼셉트론·선형이 꼴찌다(0.5327, 위 세 계열과 4.3%p 차). 퍼셉트론 원형(perc)은 네 티어에서 0.5255~0.5331 로 e_적응상수(0.5504)조차 못 넘는다. 적응상수 대비 McNemar p < 0.05 를 통과한 모델은 emb_mlp·resnet_t 둘뿐이고, mlp_sk·mlp_t·perc· sgd_* 는 한 자리도 없다.

놀란 자리: periodic 임베딩이 사후 최고 넷 중 둘이고 ple(분위수 조각선형)는 상위에 한 번도 없다. 학습 344행에서 구간당 7행이라 지나치게 잘게 쪼갠 것으로 보인다 — 구간 수를 학습행/8 로 이미 물려 놓았음에도 그렇다.

FT-Transformer 는 이 실험에 없다. 라운드 0 의 비용 측정에서 가장 싼 설정(d_token=64 · n_blocks=2)이 큰 폴드에서 1,362.6초 — 사전등록 상한 90초의 15배이고 본 스윕 예산의 94% (직렬 298.3시간 중 280.9시간)였다. 폭·깊이를 한 단계 더 줄여도 약 170초로 1.9배다. 사전등록 규약대로 격자에서 뺐고 이름을 적었다. 그래서 계열 다섯을 묶던 원래 H20 은 미판정으로 남긴다 — 조용히 지우지 않는다.

한계

초반 폴드가 결론을 끌어내린다. 최소 학습 폴드 344행 · 실측 113열 이면 행/피처가 3.04 다. 두 티어가 그 자리에서 50% 아래로 내려간다. 이것은 데이터의 성질이고, 고치려면 모델이 아니라 표본이 필요하다.

T1_flow34·T5_all 은 n=1,136 이고 시험이 여섯 해뿐이다. n=1,497 · 여덟 해인 두 티어와 승률을 섞어 비교하지 않았다.

ple 임베딩이 이 표본 크기에서 제대로 시험되지 않았다. 구간을 학습행/8 로 물려도 344행에서 구간당 7행이다.

조기 종료의 실제 구속은 검증이 아니라 min_epochs 다. torch 네 모델이 전부 60에폭(바닥)에서 멈췄다 — 작은 폴드의 검증 집합이 34행 뿐이라 그 신호가 잡음이기 때문이다. "학습을 언제 멈추나" 는 이 실험이 탐색하지 않은 축이다.

GPU 가 없다. CPU 12스레드 · torch 2.14.0+cpu. 벽시계는 기록했지만 모델 선택의 근거로 쓰지 않았다. 레짐별 분해도 하지 않았다.

캐파시티·비용 축은 비해당(방향 채점 게임 — 체결이 없다).

산출물

  • 사전등록protocol.md
  • 분석·판정analysis.md
  • 정본 런results/20260922_144439_nn/
  • 모델 격자·학습기code/nnmodels.py
  • 그림code/render_figures.py
  • 구조도code/render_model7.py
  • 입력(0005)experiments/0005_flow_api_model_zoo/