oqboost 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
oqboost-0.1.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 cree1116
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,4 @@
1
+ include LICENSE
2
+ include README.md
3
+ include README.ko.md
4
+ recursive-include src/oqboost/_ext *.cpp *.h
oqboost-0.1.1/PKG-INFO ADDED
@@ -0,0 +1,313 @@
1
+ Metadata-Version: 2.4
2
+ Name: oqboost
3
+ Version: 0.1.1
4
+ Summary: GG-SRP hereditary oblique GBDT — native NaN/categorical, high-performance C++ backend
5
+ License: MIT
6
+ Project-URL: Homepage, https://github.com/cree1116/oqboost
7
+ Project-URL: Repository, https://github.com/cree1116/oqboost
8
+ Project-URL: Issues, https://github.com/cree1116/oqboost/issues
9
+ Project-URL: Documentation, https://github.com/cree1116/oqboost/tree/main/docs
10
+ Keywords: gradient-boosting,oblique-trees,machine-learning,tabular-data,random-projection
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
+ Requires-Python: >=3.10
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: matplotlib>=3.10.9
23
+ Requires-Dist: numpy>=1.24
24
+ Requires-Dist: pandas>=2.3.3
25
+ Requires-Dist: scikit-learn>=1.3
26
+ Requires-Dist: torch>=2.12.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=8.0; extra == "dev"
29
+ Requires-Dist: pytest-cov; extra == "dev"
30
+ Requires-Dist: pandas; extra == "dev"
31
+ Requires-Dist: matplotlib; extra == "dev"
32
+ Provides-Extra: full
33
+ Requires-Dist: pandas; extra == "full"
34
+ Requires-Dist: matplotlib; extra == "full"
35
+ Dynamic: license-file
36
+
37
+ # OQBoost
38
+
39
+ **Gradient-boosted oblique decision trees with hereditary projection evolution.**
40
+
41
+ OQBoost replaces axis-aligned splits with gradient-guided oblique hyperplanes that are inherited and mutated from parent nodes — exploiting the geometric structure of the data without expensive numerical optimization.
42
+
43
+ <p align="center">
44
+ <img src="docs/diverse_boundaries.png" alt="OQBoost Decision Boundaries" width="800">
45
+ </p>
46
+
47
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
48
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/)
49
+ [![CI](https://github.com/cree1116/oqboost/actions/workflows/ci.yml/badge.svg)](https://github.com/cree1116/oqboost/actions)
50
+ [![PyPI](https://img.shields.io/pypi/v/oqboost)](https://pypi.org/project/oqboost/)
51
+
52
+ ---
53
+
54
+ ## Key Properties
55
+
56
+ | Feature | OQBoost |
57
+ |---------|---------|
58
+ | Split type | Oblique (linear projection of multiple features) |
59
+ | Direction finding | GG-SRP: gradient-guided sparse random projection |
60
+ | Inheritance | Parent weight inheritance with depth-decayed mutation |
61
+ | Missing values | Native — NaN handled via mean imputation in C++ |
62
+ | Categorical features | Native — gradient-rank encoding per round |
63
+ | API | scikit-learn compatible |
64
+ | Backend | Compiled C++ with OpenMP parallelism |
65
+
66
+ ---
67
+
68
+ ## Install
69
+
70
+ ```bash
71
+ pip install oqboost
72
+ ```
73
+
74
+ Pre-compiled wheels are available for macOS (arm64, x86_64) and Linux (x86_64).
75
+ On unsupported platforms, `clang++` or `g++` is required to compile from source.
76
+
77
+ ---
78
+
79
+ ## Quickstart
80
+
81
+ ```python
82
+ from oqboost import OQBoostClassifier
83
+
84
+ clf = OQBoostClassifier(
85
+ n_estimators=500,
86
+ learning_rate=0.05,
87
+ max_depth=6,
88
+ random_state=42,
89
+ )
90
+
91
+ clf.fit(X_train, y_train, eval_set=[(X_val, y_val)])
92
+ clf.predict(X_test)
93
+ clf.predict_proba(X_test)
94
+ ```
95
+
96
+ ### Native NaN support
97
+
98
+ ```python
99
+ import numpy as np
100
+ X_train[50, 3] = np.nan # NaN anywhere is fine
101
+ clf.fit(X_train, y_train)
102
+ clf.predict(X_test) # NaN → column-mean imputation at inference
103
+ ```
104
+
105
+ ### Native categorical support
106
+
107
+ ```python
108
+ import pandas as pd
109
+
110
+ df = pd.read_csv("data.csv")
111
+ X = df.drop(columns=["target"])
112
+ y = df["target"]
113
+
114
+ # auto-detects pandas Categorical / object columns
115
+ clf = OQBoostClassifier(n_estimators=500)
116
+ clf.fit(X, y)
117
+
118
+ # or specify explicitly
119
+ clf = OQBoostClassifier(cat_features=["city", "product"])
120
+ clf.fit(X, y)
121
+ ```
122
+
123
+ ### Early stopping
124
+
125
+ ```python
126
+ clf = OQBoostClassifier(n_estimators=2000, early_stopping_rounds=50)
127
+ clf.fit(X_train, y_train, eval_set=[(X_val, y_val)])
128
+ print(f"Stopped at {clf.get_n_trees()} trees")
129
+ ```
130
+
131
+ ### Save / load
132
+
133
+ ```python
134
+ clf.save("model.joblib")
135
+ from oqboost import load_model
136
+ clf2 = load_model("model.joblib")
137
+ ```
138
+
139
+ ---
140
+
141
+ ## Benchmark Results
142
+
143
+ All benchmarks: 80/20 train-test split, 3 repetitions, mean ± standard deviation reported. All models (XGBoost, LightGBM, CatBoost, OQBoost) were hyperparameter-tuned using Optuna for 50 trials.
144
+
145
+ ### Main Benchmark Table
146
+
147
+ | Dataset | Model | Accuracy | Bal. Acc. | F1 Macro | Log Loss | Train (s) | Infer (s) |
148
+ |---------|-------|----------|-----------|----------|----------|-----------|-----------|
149
+ | **Adult** | XGBoost | 0.8736±0.0033 | 0.7990±0.0065 | 0.8159±0.0055 | 0.2760±0.0018 | **0.83±0.10** | **0.01±0.00** |
150
+ | | LightGBM | **0.8746±0.0041** | **0.8002±0.0079** | **0.8173±0.0069** | 0.2755±0.0021 | 2.80±0.27 | 0.06±0.00 |
151
+ | | CatBoost | 0.8745±0.0040 | 0.7963±0.0065 | 0.8156±0.0063 | **0.2737±0.0018** | 7.83±0.86 | 0.05±0.00 |
152
+ | | OQBoost | 0.8717±0.0023 | 0.7985±0.0073 | 0.8141±0.0050 | 0.2768±0.0025 | 4.16±0.30 | 0.04±0.01 |
153
+ | **Credit Default** | XGBoost | 0.8206±0.0018 | 0.6584±0.0015 | 0.6836±0.0022 | 0.4280±0.0010 | **0.19±0.01** | **0.00±0.00** |
154
+ | | LightGBM | **0.8223±0.0019** | 0.6585±0.0018 | 0.6844±0.0025 | **0.4239±0.0012** | 5.56±0.32 | 0.07±0.01 |
155
+ | | CatBoost | 0.8220±0.0010 | **0.6603±0.0021** | **0.6859±0.0024** | 0.4274±0.0004 | 0.56±0.08 | **0.00±0.00** |
156
+ | | OQBoost | 0.8211±0.0025 | 0.6569±0.0057 | 0.6824±0.0064 | 0.4251±0.0006 | 0.75±0.03 | **0.00±0.00** |
157
+ | **Give Me Credit** | XGBoost | 0.7400±0.0312 | 0.6381±0.0349 | 0.6488±0.0398 | 0.5093±0.0266 | 0.16±0.03 | **0.00±0.00** |
158
+ | | LightGBM | 0.7417±0.0321 | 0.6250±0.0360 | 0.6341±0.0420 | 0.5051±0.0320 | 0.38±0.20 | **0.00±0.00** |
159
+ | | CatBoost | **0.7650±0.0173** | **0.6750±0.0167** | **0.6888±0.0196** | 0.4951±0.0382 | **0.12±0.02** | **0.00±0.00** |
160
+ | | OQBoost | 0.7600±0.0397 | 0.6651±0.0791 | 0.6719±0.0867 | **0.4940±0.0566** | 0.18±0.02 | **0.00±0.00** |
161
+ | **CoverType** | XGBoost | 0.9704±0.0008 | 0.9392±0.0042 | 0.9460±0.0034 | 0.0789±0.0017 | **74.01±0.27** | 4.06±0.08 |
162
+ | | LightGBM | 0.9704±0.0008 | 0.9397±0.0052 | 0.9466±0.0045 | 0.0823±0.0021 | 286.03±2.17 | 35.09±0.18 |
163
+ | | CatBoost | 0.9588±0.0005 | 0.9303±0.0038 | 0.9371±0.0038 | 0.1171±0.0017 | 130.84±0.51 | **0.19±0.01** |
164
+ | | OQBoost | **0.9752±0.0008** | **0.9495±0.0032** | **0.9543±0.0027** | **0.0762±0.0013** | 219.58±0.85 | 2.66±0.08 |
165
+ | **Higgs** | XGBoost | 0.7304±0.0052 | 0.7291±0.0054 | 0.7293±0.0053 | 0.5259±0.0045 | **5.74±0.81** | 0.08±0.01 |
166
+ | | LightGBM | **0.7319±0.0037** | **0.7307±0.0037** | **0.7309±0.0037** | 0.5255±0.0044 | 33.07±5.15 | 0.46±0.08 |
167
+ | | CatBoost | 0.7293±0.0055 | 0.7279±0.0055 | 0.7281±0.0055 | 0.5296±0.0043 | 11.91±2.24 | **0.01±0.00** |
168
+ | | OQBoost | 0.7311±0.0043 | 0.7300±0.0043 | 0.7301±0.0043 | **0.5243±0.0043** | 45.69±7.71 | 0.74±0.11 |
169
+ | **Rotated Synth.** | XGBoost | 0.9758±0.0014 | 0.9758±0.0015 | 0.9758±0.0014 | 0.0819±0.0023 | **6.46±0.29** | 0.11±0.02 |
170
+ | | LightGBM | 0.9763±0.0017 | 0.9763±0.0017 | 0.9763±0.0017 | 0.0835±0.0023 | 17.72±0.58 | 0.33±0.08 |
171
+ | | CatBoost | 0.9772±0.0019 | 0.9772±0.0019 | 0.9772±0.0019 | 0.0818±0.0034 | 20.75±9.69 | **0.02±0.01** |
172
+ | | OQBoost | **0.9795±0.0013** | **0.9795±0.0013** | **0.9795±0.0013** | **0.0724±0.0027** | 32.08±11.30 | 0.51±0.12 |
173
+
174
+ ### Highlights
175
+
176
+ - **Outstanding on CoverType:** OQBoost achieves **0.9495±0.0032** Balanced Accuracy (outperforming LightGBM's 0.9397 and XGBoost's 0.9392) and the lowest Log Loss of **0.0762** (vs XGBoost's 0.0789 and CatBoost's 0.1171).
177
+ - **Superior on Rotated Synthetic:** OQBoost achieves **0.9795±0.0013** Balanced Accuracy and **0.0724±0.0027** Log Loss, outperforming all baselines (CatBoost 0.9772, LightGBM 0.9763, XGBoost 0.9758). This validates the oblique split advantage on rotated decision boundaries.
178
+ - **Lowest Log Loss on Give Me Credit & Higgs:** OQBoost achieves the lowest Log Loss on Give Me Credit (**0.4940±0.0566** vs CatBoost's 0.4951) and Higgs (**0.5243±0.0043** vs LightGBM's 0.5255).
179
+ - **Strong Performance on Give Me Credit & Adult:** OQBoost performs competitively, scoring **0.6651±0.0791** Balanced Accuracy on Give Me Credit (outperforming XGBoost's 0.6381 and LightGBM's 0.6250) and **0.7985±0.0073** on Adult Income.
180
+
181
+ ### Figure 1 — Balanced Accuracy Comparison
182
+
183
+ ![Balanced Accuracy](benchmark/results/figures/fig2_balanced_accuracy.png)
184
+
185
+ ### Figure 2 — Performance vs Training Cost
186
+
187
+ ![Perf vs Cost](benchmark/results/figures/fig5_perf_vs_cost.png)
188
+
189
+ ### Figure 3 — Rotation Robustness
190
+
191
+ ![Rotation Robustness](benchmark/results/figures/fig6_rotation_robustness.png)
192
+
193
+ ### Figure 4 — Missing Value Robustness
194
+
195
+ ![Missing Value](benchmark/results/figures/fig7_missing_value.png)
196
+
197
+ ### Figure 5 — Categorical Cardinality Robustness
198
+
199
+ ![Categorical](benchmark/results/figures/fig8_categorical.png)
200
+
201
+ ---
202
+
203
+ ## Algorithm
204
+
205
+ OQBoost uses three-stage hereditary projection evolution:
206
+
207
+ **Stage 1 — GG-SRP (Gradient-Guided Sparse Random Projection)**
208
+ Features are sampled with probability proportional to SIS gradient-importance scores. Each selected feature gets a weight sign aligned with the steepest gradient descent direction. No Gram matrix, no linear system — $O(D)$ per node.
209
+
210
+ **Stage 2 — Parent Weight Inheritance**
211
+ Child nodes inherit their parent's split direction and apply two mutation strategies:
212
+ - *Strategy A:* axis-maintaining noise (tilt the boundary by ±10%)
213
+ - *Strategy B:* new-axis borrowing (add a high-correlation feature not in the parent's support)
214
+
215
+ **Stage 3 — Global-Local Crossover + Depth Decay**
216
+ - *Strategy C:* random blend of the current parent direction with a globally top-performing direction from the ring buffer (last 32 rounds)
217
+ - *Depth decay:* mutation strength decreases as $1/\sqrt{1 + d}$ — wide exploration at shallow depth, fine-tuning at deep nodes
218
+
219
+ See [`docs/algorithm.md`](docs/algorithm.md) for the full derivation and [`docs/THEORY.md`](docs/THEORY.md) for theoretical insights and experiment logs.
220
+
221
+ ---
222
+
223
+ ## Parameters
224
+
225
+ | Parameter | Default | Description |
226
+ |-----------|---------|-------------|
227
+ | `n_estimators` | 500 | Number of boosting rounds |
228
+ | `learning_rate` | 0.05 | Shrinkage per tree |
229
+ | `max_depth` | 6 | Leaf budget = 2^max_depth (64 leaves, matches XGBoost/CatBoost) |
230
+ | `reg_lambda` | 1.0 | L2 leaf regularization |
231
+ | `subsample` | 0.8 | Row fraction per tree |
232
+ | `early_stopping_rounds` | 50 | Stop if class-weighted val loss stagnates |
233
+ | `cat_features` | None | Categorical column names or indices |
234
+ | `class_weight` | None | Reweight by inverse class frequency (e.g. "balanced") |
235
+ | `inherited_rp_ratio` | 1.0 | Fraction of candidates from inheritance + cache |
236
+ | `mutation_rate` | 0.1 | Base noise scale for axis mutations |
237
+ | `mutation_strength` | 0.5 | Base weight for new-axis borrowing |
238
+ | `pobs` | False | Inject Haar-orthogonal POBS candidates into every node's tournament |
239
+ | `random_state` | None | Seed |
240
+ | `verbose` | False | Print per-round metrics |
241
+
242
+ ---
243
+
244
+ ## Running Benchmarks
245
+
246
+ ```bash
247
+ cd benchmark
248
+
249
+ # Run all (takes ~hours for Higgs + CoverType)
250
+ python run_all.py
251
+
252
+ # Skip large datasets
253
+ python run_all.py --skip higgs covertype
254
+
255
+ # Individual benchmarks
256
+ python adult.py
257
+ python rotated_synthetic.py
258
+ python missing_value_robustness.py
259
+ python categorical_robustness.py
260
+
261
+ # Generate figures from completed results
262
+ python generate_figures.py
263
+
264
+ # Generate summary table (results/summary.md)
265
+ python generate_tables.py
266
+ ```
267
+
268
+ Large datasets require manual download:
269
+ - **HIGGS**: https://archive.ics.uci.edu/dataset/280 → `benchmark/data/HIGGS.csv.gz`
270
+ - **Give Me Some Credit (Kaggle)**: https://www.kaggle.com/competitions/GiveMeSomeCredit → `benchmark/data/cs-training.csv`
271
+
272
+ ---
273
+
274
+ ## Repository Structure
275
+
276
+ ```
277
+ oqboost/
278
+ ├── src/oqboost/
279
+ │ ├── __init__.py
280
+ │ ├── _classifier.py # OQBoostClassifier
281
+ │ ├── _oqboost.py # C bindings + OQBoostTree, OQBoostContext
282
+ │ └── _ext/
283
+ │ ├── oqboost.cpp # full engine: boosting round, routing, serialization
284
+ │ ├── oqboost_types.h # OQTree structure
285
+ │ ├── oqboost_core.h # Shared constants and helpers
286
+ │ └── liboqboost.dylib / .so / .dll (compiled)
287
+ ├── benchmark/
288
+ │ ├── *.py # Per-dataset benchmark scripts
289
+ │ ├── _utils.py # Shared train/eval utilities
290
+ │ ├── generate_figures.py
291
+ │ ├── generate_tables.py
292
+ │ ├── run_all.py
293
+ │ └── results/
294
+ │ ├── csv/ # Raw results
295
+ │ ├── figures/ # Generated plots
296
+ │ └── summary.md
297
+ ├── docs/
298
+ │ ├── algorithm.md # Theory and derivations
299
+ │ ├── api.md # Full API reference
300
+ │ └── quickstart.md
301
+ ├── tests/
302
+ └── pyproject.toml
303
+ ```
304
+
305
+ ---
306
+
307
+ ## License
308
+
309
+ [MIT](LICENSE) — Copyright (c) 2025 cree1116
310
+
311
+ ---
312
+
313
+ [한국어 버전 (Korean Version)](README.ko.md)
@@ -0,0 +1,278 @@
1
+ # OQBoost
2
+
3
+ **유전적 사영 진화를 기반으로 한 경사 부스팅 사선 결정 트리 (Gradient-boosted oblique decision trees with hereditary projection evolution)**
4
+
5
+ OQBoost는 기존의 축 정렬 분기(axis-aligned splits) 대신 그라디언트(gradient)에 의해 정렬되는 사선 하이퍼플레인(oblique hyperplanes) 분기를 수행합니다. 이 분기 방향들은 부모 노드로부터 상속 및 변이되는 유전적 파이프라인을 거치며, 값비싼 수치 최적화 없이도 데이터의 고유한 기하학적 구조를 효과적으로 캡처합니다.
6
+
7
+ <p align="center">
8
+ <img src="docs/diverse_boundaries.png" alt="OQBoost 결정 경계" width="800">
9
+ </p>
10
+
11
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
12
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/)
13
+ [![CI](https://github.com/cree1116/oqboost/actions/workflows/ci.yml/badge.svg)](https://github.com/cree1116/oqboost/actions)
14
+ [![PyPI](https://img.shields.io/pypi/v/oqboost)](https://pypi.org/project/oqboost/)
15
+
16
+ ---
17
+
18
+ ## 핵심 특징 (Key Properties)
19
+
20
+ | 특징 | 설명 |
21
+ |------|------|
22
+ | **분기 타입 (Split type)** | 사선 분기 (Oblique split, 여러 피처들의 선형 사영 결합) |
23
+ | **방향 탐색 (Direction finding)** | GG-SRP: 그라디언트 유도형 희소 무작위 사영 |
24
+ | **상속 구조 (Inheritance)** | 부모 노드의 분기 방향 가중치를 상속하고 깊이에 비례해 감쇠하는 변이 적용 |
25
+ | **결측치 지원 (Missing values)** | 네이티브 지원 — C++ 내부에서 실시간 평균 대체로 NaN 처리 |
26
+ | **범주형 피처 지원 (Categorical features)** | 네이티브 지원 — 라운드별 그라디언트 랭크(gradient-rank) 타겟 인코딩 |
27
+ | **API 호환성** | scikit-learn API 완벽 호환 |
28
+ | **백엔드 엔진** | OpenMP 병렬 컴파일된 C++ 백엔드 |
29
+
30
+ ---
31
+
32
+ ## 설치 (Install)
33
+
34
+ ```bash
35
+ pip install oqboost
36
+ ```
37
+
38
+ macOS (arm64, x86_64) 및 Linux (x86_64) 환경을 위한 사전 빌드된 휠(wheel) 패키지가 배포됩니다.
39
+ 지원되지 않는 플랫폼의 경우, 소스코드 컴파일을 위해 `clang++` 또는 `g++`가 필요합니다.
40
+
41
+ ---
42
+
43
+ ## 퀵스타트 (Quickstart)
44
+
45
+ ```python
46
+ from oqboost import OQBoostClassifier
47
+
48
+ clf = OQBoostClassifier(
49
+ n_estimators=500,
50
+ learning_rate=0.05,
51
+ max_depth=6,
52
+ random_state=42,
53
+ )
54
+
55
+ clf.fit(X_train, y_train, eval_set=[(X_val, y_val)])
56
+ clf.predict(X_test)
57
+ clf.predict_proba(X_test)
58
+ ```
59
+
60
+ ### 네이티브 결측치(NaN) 지원
61
+
62
+ ```python
63
+ import numpy as np
64
+ X_train[50, 3] = np.nan # 데이터의 임의 영역에 NaN 존재 허용
65
+ clf.fit(X_train, y_train)
66
+ clf.predict(X_test) # 추론 시점에 컬럼 평균 대체 방식 적용
67
+ ```
68
+
69
+ ### 네이티브 범주형 피처 지원
70
+
71
+ ```python
72
+ import pandas as pd
73
+
74
+ df = pd.read_csv("data.csv")
75
+ X = df.drop(columns=["target"])
76
+ y = df["target"]
77
+
78
+ # 방법 1: pandas의 Categorical 또는 object 컬럼 자동 감지
79
+ clf = OQBoostClassifier(n_estimators=500)
80
+ clf.fit(X, y)
81
+
82
+ # 방법 2: 명시적으로 범주형 컬럼 지정
83
+ clf = OQBoostClassifier(cat_features=["city", "product"])
84
+ clf.fit(X, y)
85
+ ```
86
+
87
+ ### 조기 종료 (Early Stopping)
88
+
89
+ ```python
90
+ clf = OQBoostClassifier(n_estimators=2000, early_stopping_rounds=50)
91
+ clf.fit(X_train, y_train, eval_set=[(X_val, y_val)])
92
+ print(f"조기 종료 지점: {clf.get_n_trees()} 번째 트리")
93
+ ```
94
+
95
+ ### 모델 저장 및 로드 (Save / Load)
96
+
97
+ ```python
98
+ clf.save("model.joblib")
99
+ from oqboost import load_model
100
+ clf2 = load_model("model.joblib")
101
+ ```
102
+
103
+ ---
104
+
105
+ ## 벤치마크 결과 (Benchmark Results)
106
+
107
+ 모든 벤치마크는 80/20 학습-평가 스플릿으로 3회 반복 실행하여 평균 및 표준편차(mean ± std)를 계산했습니다. 비교군 모델(XGBoost, LightGBM, CatBoost, OQBoost)의 하이퍼파라미터는 모두 동일하게 **Optuna를 사용하여 50회(trials) 튜닝**된 최적 값을 적용했습니다.
108
+
109
+ ### 메인 벤치마크 테이블 (Main Benchmark Table)
110
+
111
+ | 데이터셋 | 모델 | 정확도 (Accuracy) | 균형 정확도 (Bal. Acc.) | F1 매크로 (F1 Macro) | 로그 손실 (Log Loss) | 학습 시간 (Train, 초) | 추론 시간 (Infer, 초) |
112
+ |---------|-------|----------|-----------|----------|----------|-----------|-----------|
113
+ | **Adult** | XGBoost | 0.8736±0.0033 | 0.7990±0.0065 | 0.8159±0.0055 | 0.2760±0.0018 | **0.83±0.10** | **0.01±0.00** |
114
+ | | LightGBM | **0.8746±0.0041** | **0.8002±0.0079** | **0.8173±0.0069** | 0.2755±0.0021 | 2.80±0.27 | 0.06±0.00 |
115
+ | | CatBoost | 0.8745±0.0040 | 0.7963±0.0065 | 0.8156±0.0063 | **0.2737±0.0018** | 7.83±0.86 | 0.05±0.00 |
116
+ | | OQBoost | 0.8717±0.0023 | 0.7985±0.0073 | 0.8141±0.0050 | 0.2768±0.0025 | 4.16±0.30 | 0.04±0.01 |
117
+ | **Credit Default** | XGBoost | 0.8206±0.0018 | 0.6584±0.0015 | 0.6836±0.0022 | 0.4280±0.0010 | **0.19±0.01** | **0.00±0.00** |
118
+ | | LightGBM | **0.8223±0.0019** | 0.6585±0.0018 | 0.6844±0.0025 | **0.4239±0.0012** | 5.56±0.32 | 0.07±0.01 |
119
+ | | CatBoost | 0.8220±0.0010 | **0.6603±0.0021** | **0.6859±0.0024** | 0.4274±0.0004 | 0.56±0.08 | **0.00±0.00** |
120
+ | | OQBoost | 0.8211±0.0025 | 0.6569±0.0057 | 0.6824±0.0064 | 0.4251±0.0006 | 0.75±0.03 | **0.00±0.00** |
121
+ | **Give Me Credit** | XGBoost | 0.7400±0.0312 | 0.6381±0.0349 | 0.6488±0.0398 | 0.5093±0.0266 | 0.16±0.03 | **0.00±0.00** |
122
+ | | LightGBM | 0.7417±0.0321 | 0.6250±0.0360 | 0.6341±0.0420 | 0.5051±0.0320 | 0.38±0.20 | **0.00±0.00** |
123
+ | | CatBoost | **0.7650±0.0173** | **0.6750±0.0167** | **0.6888±0.0196** | 0.4951±0.0382 | **0.12±0.02** | **0.00±0.00** |
124
+ | | OQBoost | 0.7600±0.0397 | 0.6651±0.0791 | 0.6719±0.0867 | **0.4940±0.0566** | 0.18±0.02 | **0.00±0.00** |
125
+ | **CoverType** | XGBoost | 0.9704±0.0008 | 0.9392±0.0042 | 0.9460±0.0034 | 0.0789±0.0017 | **74.01±0.27** | 4.06±0.08 |
126
+ | | LightGBM | 0.9704±0.0008 | 0.9397±0.0052 | 0.9466±0.0045 | 0.0823±0.0021 | 286.03±2.17 | 35.09±0.18 |
127
+ | | CatBoost | 0.9588±0.0005 | 0.9303±0.0038 | 0.9371±0.0038 | 0.1171±0.0017 | 130.84±0.51 | **0.19±0.01** |
128
+ | | OQBoost | **0.9752±0.0008** | **0.9495±0.0032** | **0.9543±0.0027** | **0.0762±0.0013** | 219.58±0.85 | 2.66±0.08 |
129
+ | **Higgs** | XGBoost | 0.7304±0.0052 | 0.7291±0.0054 | 0.7293±0.0053 | 0.5259±0.0045 | **5.74±0.81** | 0.08±0.01 |
130
+ | | LightGBM | **0.7319±0.0037** | **0.7307±0.0037** | **0.7309±0.0037** | 0.5255±0.0044 | 33.07±5.15 | 0.46±0.08 |
131
+ | | CatBoost | 0.7293±0.0055 | 0.7279±0.0055 | 0.7281±0.0055 | 0.5296±0.0043 | 11.91±2.24 | **0.01±0.00** |
132
+ | | OQBoost | 0.7311±0.0043 | 0.7300±0.0043 | 0.7301±0.0043 | **0.5243±0.0043** | 45.69±7.71 | 0.74±0.11 |
133
+ | **Rotated Synth.** | XGBoost | 0.9758±0.0014 | 0.9758±0.0015 | 0.9758±0.0014 | 0.0819±0.0023 | **6.46±0.29** | 0.11±0.02 |
134
+ | | LightGBM | 0.9763±0.0017 | 0.9763±0.0017 | 0.9763±0.0017 | 0.0835±0.0023 | 17.72±0.58 | 0.33±0.08 |
135
+ | | CatBoost | 0.9772±0.0019 | 0.9772±0.0019 | 0.9772±0.0019 | 0.0818±0.0034 | 20.75±9.69 | **0.02±0.01** |
136
+ | | OQBoost | **0.9795±0.0013** | **0.9795±0.0013** | **0.9795±0.0013** | **0.0724±0.0027** | 32.08±11.30 | 0.51±0.12 |
137
+
138
+ ### 하이라이트 지표 (Highlights)
139
+
140
+ - **CoverType 데이터셋 우수한 성능:** OQBoost는 **0.9495±0.0032**의 균형 정확도를 달성하여 기존 베이스라인 모델인 LightGBM(0.9397) 및 XGBoost(0.9392)를 유의미하게 능가했으며, 로그 손실률 역시 최저 수치인 **0.0762**를 기록했습니다.
141
+ - **Rotated Synthetic 강건성 검증:** 회전 공간에서 오블리크 분기의 진가가 입증되어 베이스라인 전체(CatBoost 0.9772, LightGBM 0.9763, XGBoost 0.9758)를 누르고 **0.9795±0.0013**의 가장 높은 균형 정확도 및 **0.0724±0.0027**의 최저 로그 손실을 기록했습니다.
142
+ - **Give Me Credit & Higgs 로그 손실 최소화:** OQBoost는 Give Me Credit (**0.4940±0.0566**) 및 Higgs (**0.5243±0.0043**) 데이터셋에서 베이스라인 모델보다 낮은 로그 손실(Log Loss)을 기록하며 우수한 확률 보정 품질을 나타냈습니다.
143
+ - **Adult & Give Me Credit 경쟁력**: OQBoost는 Give Me Credit에서 균형 정확도 **0.6651±0.791**을 기록하여 XGBoost(0.6381) 및 LightGBM(0.6250)을 앞서는 등 탁월한 성능 경쟁력을 보였습니다.
144
+
145
+ ### 그림 1 — 균형 정확도 비교 (Balanced Accuracy Comparison)
146
+
147
+ ![Balanced Accuracy](benchmark/results/figures/fig2_balanced_accuracy.png)
148
+
149
+ ### 그림 2 — 성능 대 학습 속도 비교 (Performance vs Training Cost)
150
+
151
+ ![Perf vs Cost](benchmark/results/figures/fig5_perf_vs_cost.png)
152
+
153
+ ### 그림 3 — 회전 강건성 평가 (Rotation Robustness)
154
+
155
+ ![Rotation Robustness](benchmark/results/figures/fig6_rotation_robustness.png)
156
+
157
+ ### 그림 4 — 결측치 내성 평가 (Missing Value Robustness)
158
+
159
+ ![Missing Value](benchmark/results/figures/fig7_missing_value.png)
160
+
161
+ ### 그림 5 — 범주 카디널리티 내성 평가 (Categorical Cardinality Robustness)
162
+
163
+ ![Categorical](benchmark/results/figures/fig8_categorical.png)
164
+
165
+ ---
166
+
167
+ ## 알고리즘 개요 (Algorithm)
168
+
169
+ OQBoost는 다음과 같은 3단계 유전적 사영 진화 파이프라인을 가동합니다.
170
+
171
+ **1단계 — GG-SRP (그라디언트 유도형 희소 무작위 사영)**
172
+ 각 노드에서 샘플 오차 정보를 담은 SIS 그라디언트 중요도 스코어에 비례하여 피처들을 서브 공간에 샘플링합니다. 그 후 각 피처의 가중치 부호를 가장 가파른 오차 경사하강 방향과 일치하도록 정렬합니다. 이 모든 연산은 그람 행렬 구축이나 연립 방정식 계산 없이 $O(D)$의 선형 복잡도로 수행됩니다.
173
+
174
+ **2단계 — 부모 방향 상속 (Parent Weight Inheritance)**
175
+ 자식 노드는 부모 노드의 우수한 스플릿 방향 가중치를 물려받아 아래의 두 가지 유전적 변이를 거쳐 후보군으로 추가합니다.
176
+ - *Strategy A (축 유지 변이)*: 결정 경계선을 미세하게 비틀어 탐색 각도를 미세 조정합니다 (±10%).
177
+ - *Strategy B (상관 축 확장 변이)*: 부모 노드의 피처 세트에 신규 피처를 확장 병합합니다.
178
+
179
+ **3단계 — 글로벌-로컬 크로스오버 + 깊이 감쇠**
180
+ - *Strategy C (크로스오버)*: 이전 라운드에서 우수했던 상위 32개 사영 축을 담은 전역 버퍼 `dir_cache`와 부모 노드의 방향을 무작위 비율로 섞어 하이브리드 후보를 생산합니다.
181
+ - *깊이 감쇠 (Depth Decay)*: 상위 노드에서는 탐색(exploration)이 중요하지만 하위 노드에서는 오버핏을 억제해야 하므로, 노드 깊이에 반비례하여 변이 노이즈 강도를 $1/\sqrt{1 + d}$ 로 감쇠시킵니다.
182
+
183
+ 수리적 유도 과정은 [`docs/algorithm.md`](docs/algorithm.md)에서, 상세 연구 및 실험 로그는 [`docs/THEORY.md`](docs/THEORY.md)에서 확인하실 수 있습니다.
184
+
185
+ ---
186
+
187
+ ## 매개변수 명세 (Parameters)
188
+
189
+ | 매개변수 (Parameter) | 기본값 (Default) | 설명 (Description) |
190
+ |-----------|---------|-------------|
191
+ | `n_estimators` | 500 | 부스팅 반복 라운드 수 (트리 개수) |
192
+ | `learning_rate` | 0.05 | 트리가 앙상블에 기여하는 학습 축소 계수 |
193
+ | `max_depth` | 6 | 리프 노드 수 한도 = $2^{\text{max_depth}}$ (64개) |
194
+ | `reg_lambda` | 1.0 | 리프 스코어 가중치에 대한 L2 규제 강도 |
195
+ | `subsample` | 0.8 | 각 트리를 빌드할 때 무작위 샘플링할 샘플 비율 |
196
+ | `early_stopping_rounds` | 50 | 검증 데이터 손실이 정체될 시 조기 종료 임계치 |
197
+ | `cat_features` | None | 범주형 피처 컬럼 명칭(DataFrame) 또는 컬럼 인덱스 목록 |
198
+ | `class_weight` | None | `"balanced"` 설정 시 빈도 역수에 비례하여 의사결정 선값을 보정 |
199
+ | `inherited_rp_ratio` | 1.0 | 상속 및 캐시 패밀리가 스캔 후보 풀에서 차지하는 비율 |
200
+ | `mutation_rate` | 0.1 | Strategy A 축 변이의 노이즈 강도 파라미터 |
201
+ | `mutation_strength` | 0.5 | Strategy B 상관 피처 차용 시의 기본 가중치 |
202
+ | `pobs` | False | Haar-orthogonal 기반의 무작위 직교 블록 후보 주입 여부 |
203
+ | `random_state` | None | 난수 고정 시드 |
204
+ | `verbose` | False | 학습 과정 모니터링 출력 여부 |
205
+
206
+ ---
207
+
208
+ ## 벤치마크 실행 방법 (Running Benchmarks)
209
+
210
+ ```bash
211
+ cd benchmark
212
+
213
+ # 전체 벤치마크 가동 (Higgs + CoverType 포함 시 몇 시간 소요될 수 있음)
214
+ python run_all.py
215
+
216
+ # 대용량 데이터셋 제외하고 실행
217
+ python run_all.py --skip higgs covertype
218
+
219
+ # 개별 데이터셋 전용 벤치마크 실행
220
+ python adult.py
221
+ python rotated_synthetic.py
222
+ python missing_value_robustness.py
223
+ python categorical_robustness.py
224
+
225
+ # 벤치마크 완료 후 결과 이미지(차트)들 생성
226
+ python generate_figures.py
227
+
228
+ # 벤치마크 완료 후 결과 테이블 생성 (results/summary.md)
229
+ python generate_tables.py
230
+ ```
231
+
232
+ 일부 대량 데이터셋은 아래 링크에서 수동 다운로드하여 데이터 경로에 위치시켜야 합니다.
233
+ - **HIGGS**: https://archive.ics.uci.edu/dataset/280 → `benchmark/data/HIGGS.csv.gz`
234
+ - **Give Me Some Credit (Kaggle)**: https://www.kaggle.com/competitions/GiveMeSomeCredit → `benchmark/data/cs-training.csv`
235
+
236
+ ---
237
+
238
+ ## 디렉터리 구조 (Repository Structure)
239
+
240
+ ```
241
+ oqboost/
242
+ ├── src/oqboost/
243
+ │ ├── __init__.py
244
+ │ ├── _classifier.py # OQBoostClassifier 래퍼
245
+ │ ├── _oqboost.py # C++ 바인딩 + OQBoostTree, OQBoostContext
246
+ │ └── _ext/
247
+ │ ├── oqboost.cpp # 핵심 빌딩 엔진, 정렬 스캔, 직렬화
248
+ │ ├── oqboost_types.h # OQTree 노드 구조 선언
249
+ │ ├── oqboost_core.h # 핵심 수학 및 공유 상수 라이브러리
250
+ │ └── liboqboost.dylib / .so / .dll (컴파일 바이너리)
251
+ ├── benchmark/
252
+ │ ├── *.py # 데이터셋별 평가 스크립트
253
+ │ ├── _utils.py # 공통 학습/평가 지표 래퍼
254
+ │ ├── generate_figures.py
255
+ │ ├── generate_tables.py
256
+ │ ├── run_all.py
257
+ │ └── results/
258
+ │ ├── csv/ # 가공 이전 벤치마크 원본 데이터
259
+ │ ├── figures/ # 최종 시각화 차트 이미지
260
+ │ └── summary.md
261
+ ├── docs/
262
+ │ ├── algorithm.md # 사선 수학 및 알고리즘 명세
263
+ │ ├── api.md # 파이썬 전체 API 명세서
264
+ │ └── quickstart.md # 빠른 사용법 가이드
265
+ ├── tests/
266
+ │ └── test_classifier.py
267
+ └── pyproject.toml
268
+ ```
269
+
270
+ ---
271
+
272
+ ## 라이선스 (License)
273
+
274
+ [MIT](LICENSE) — Copyright (c) 2025 cree1116
275
+
276
+ ---
277
+
278
+ [English Version (영문 버전)](README.md)