augmask 0.1.0__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.
- augmask-0.1.0/LICENSE +21 -0
- augmask-0.1.0/PKG-INFO +326 -0
- augmask-0.1.0/README.md +286 -0
- augmask-0.1.0/augmask/__init__.py +5 -0
- augmask-0.1.0/augmask/augment.py +192 -0
- augmask-0.1.0/augmask/baselines/__init__.py +1 -0
- augmask-0.1.0/augmask/baselines/forestdiff.py +73 -0
- augmask-0.1.0/augmask/baselines/miwae.py +110 -0
- augmask-0.1.0/augmask/data/__init__.py +7 -0
- augmask-0.1.0/augmask/data/datasets.py +190 -0
- augmask-0.1.0/augmask/data/missingness.py +96 -0
- augmask-0.1.0/augmask/data/scenario.py +221 -0
- augmask-0.1.0/augmask/data/schema.py +60 -0
- augmask-0.1.0/augmask/data/split.py +32 -0
- augmask-0.1.0/augmask/data/transforms.py +78 -0
- augmask-0.1.0/augmask/evaluate.py +164 -0
- augmask-0.1.0/augmask/models/__init__.py +1 -0
- augmask-0.1.0/augmask/models/cdtd.py +301 -0
- augmask-0.1.0/augmask/models/common.py +63 -0
- augmask-0.1.0/augmask/models/tabddpm.py +211 -0
- augmask-0.1.0/augmask/models/tabdiff.py +223 -0
- augmask-0.1.0/augmask/run.py +122 -0
- augmask-0.1.0/augmask.egg-info/PKG-INFO +326 -0
- augmask-0.1.0/augmask.egg-info/SOURCES.txt +34 -0
- augmask-0.1.0/augmask.egg-info/dependency_links.txt +1 -0
- augmask-0.1.0/augmask.egg-info/requires.txt +25 -0
- augmask-0.1.0/augmask.egg-info/top_level.txt +1 -0
- augmask-0.1.0/pyproject.toml +53 -0
- augmask-0.1.0/setup.cfg +4 -0
- augmask-0.1.0/tests/test_cdtd.py +61 -0
- augmask-0.1.0/tests/test_evaluate.py +42 -0
- augmask-0.1.0/tests/test_missingness_baselines.py +89 -0
- augmask-0.1.0/tests/test_pipeline.py +198 -0
- augmask-0.1.0/tests/test_run.py +25 -0
- augmask-0.1.0/tests/test_tabddpm.py +67 -0
- augmask-0.1.0/tests/test_tabdiff.py +53 -0
augmask-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jungkyu Kim, Taeyoung Park, Kibok Lee
|
|
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.
|
augmask-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: augmask
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: AugMask: training diffusion models on incomplete tabular data via stochastic augmentation and masking (ICML 2026)
|
|
5
|
+
Author: Jungkyu Kim, Taeyoung Park, Kibok Lee
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/normal-kim/AugMask
|
|
8
|
+
Project-URL: Paper, https://arxiv.org/abs/2606.03347
|
|
9
|
+
Keywords: diffusion models,tabular data,missing data,data augmentation,synthetic data
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
17
|
+
Requires-Python: <3.13,>=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: numpy<2,>=1.24
|
|
21
|
+
Requires-Dist: pandas>=2.0
|
|
22
|
+
Requires-Dist: scipy>=1.10
|
|
23
|
+
Requires-Dist: scikit-learn>=1.3
|
|
24
|
+
Requires-Dist: lightgbm>=4.0
|
|
25
|
+
Provides-Extra: torch
|
|
26
|
+
Requires-Dist: torch>=2.1; extra == "torch"
|
|
27
|
+
Provides-Extra: data
|
|
28
|
+
Requires-Dist: xlrd>=2.0; extra == "data"
|
|
29
|
+
Provides-Extra: eval
|
|
30
|
+
Requires-Dist: xgboost>=2.0; extra == "eval"
|
|
31
|
+
Requires-Dist: sdmetrics>=0.17; extra == "eval"
|
|
32
|
+
Provides-Extra: baselines
|
|
33
|
+
Requires-Dist: ForestDiffusion==1.0.6; extra == "baselines"
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
36
|
+
Requires-Dist: matplotlib>=3.7; extra == "dev"
|
|
37
|
+
Provides-Extra: all
|
|
38
|
+
Requires-Dist: augmask[baselines,data,dev,eval,torch]; extra == "all"
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
# AugMask
|
|
42
|
+
|
|
43
|
+
Official code for **AugMask: Training Diffusion Models on Incomplete Tabular Data via Stochastic Augmentation and Masking** (ICML 2026).
|
|
44
|
+
Jungkyu Kim, Taeyoung Park, Kibok Lee. [[arXiv]](https://arxiv.org/abs/2606.03347) [[OpenReview]](https://openreview.net/forum?id=Ot8lh7vvGe)
|
|
45
|
+
|
|
46
|
+
## 💡 Why AugMask
|
|
47
|
+
|
|
48
|
+
**Diffusion models for tabular data are built for complete rows**, but real tables have missing entries. The usual workarounds fail:
|
|
49
|
+
|
|
50
|
+
- **Constant fills become data.** A model trained on mean-filled rows *treats the fills as observed values* and learns to reproduce them. Below, the filled rows collapse onto a cross at the column means.
|
|
51
|
+
- **Masking the loss is not enough.** Filled entries left out of the loss are *still read as inputs*, so the model learns from rows that real data rarely contains, such as a hot day paired with the average dew point.
|
|
52
|
+
|
|
53
|
+
AugMask fixes both:
|
|
54
|
+
|
|
55
|
+
1. **Augment.** A missing entry is *unrealized data that could take many different values*, so AugMask *samples* it instead of imputing it deterministically. Each missing entry $`x_j`$ is drawn from a conditional model of its column, $`x_j \sim \hat{p}_j(x_j \mid x_{\mathrm{obs}}, m)`$: the augmenter receives the row's observed values $`x_{\mathrm{obs}}`$ and its missingness mask $`m`$ as inputs. This repository uses LGBM-S, lightweight per-column LightGBM models, as the augmenter; the sampled rows resemble the complete data (right panel).
|
|
56
|
+
2. **Mask.** The denoising loss is computed on observed entries only, so the sampled values serve as *context, never as targets*.
|
|
57
|
+
|
|
58
|
+
<picture>
|
|
59
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/normal-kim/AugMask/main/assets/overview_dark.png">
|
|
60
|
+
<img src="https://raw.githubusercontent.com/normal-kim/AugMask/main/assets/overview_light.png" alt="Mean filling collapses rows onto a cross at the column means; augmented fills follow the joint distribution. Inputs are filled, and the loss uses observed entries only." width="100%">
|
|
61
|
+
</picture>
|
|
62
|
+
|
|
63
|
+
AugMask needs no change to the model itself. This repository applies it to three diffusion models: [TabDDPM](https://proceedings.mlr.press/v202/kotelnikov23a.html) (ICML 2023; [code](https://github.com/yandex-research/tab-ddpm)), [CDTD](https://proceedings.iclr.cc/paper_files/paper/2025/hash/61f4e5747b1b753cb35546b15d981f76-Abstract-Conference.html) (ICLR 2025; [code](https://github.com/muellermarkus/cdtd)) and [TabDiff](https://proceedings.iclr.cc/paper_files/paper/2025/hash/5c882988ce5fac487974ee4f415b96a9-Abstract-Conference.html) (ICLR 2025; [code](https://github.com/MinkaiXu/TabDiff)).
|
|
64
|
+
|
|
65
|
+
## 📦 Install
|
|
66
|
+
|
|
67
|
+
Python 3.10–3.12.
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pip install augmask # the augmentation (LGBM-S) alone
|
|
71
|
+
pip install "augmask[all]" # plus the diffusion backbones, baselines and evaluation
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
To run the experiments, clone this repository and create the exact environment used for the results:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
git clone https://github.com/normal-kim/AugMask.git && cd AugMask
|
|
78
|
+
conda env create -f environment.yml && conda activate augmask
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## 🧩 Use AugMask with your own model
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from augmask import Encoded, LGBMSAugmenter
|
|
85
|
+
|
|
86
|
+
train = Encoded(X_num, X_cat, M_num, M_cat)
|
|
87
|
+
fills = [LGBMSAugmenter(draw=k).augment(train, [], n_categories)[0] for k in range(5)]
|
|
88
|
+
|
|
89
|
+
# train your denoiser on fills[step % 5], with the loss restricted to observed entries
|
|
90
|
+
loss = (per_entry_loss * mask).sum() / mask.sum()
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The augmenter takes an encoded table with `n` rows:
|
|
94
|
+
|
|
95
|
+
| Input | Shape | Type | Content |
|
|
96
|
+
|---|---|---|---|
|
|
97
|
+
| `X_num` | `(n, d_num)` | float | numerical columns, quantile-normal transformed; `NaN` where missing |
|
|
98
|
+
| `X_cat` | `(n, d_cat)` | int | categorical columns, integer encoded as `0 … K_j−1`; `−1` where missing |
|
|
99
|
+
| `M_num`, `M_cat` | same as above | bool | `True` where observed |
|
|
100
|
+
| `n_categories` | `d_cat` | list of int | number of categories `K_j` of each categorical column |
|
|
101
|
+
|
|
102
|
+
`augment` returns `X_num` and `X_cat` with every missing entry filled; each `draw` gives an independent fill, with the observed entries unchanged. In this repository, the backbones receive one fill per training step: `X_num` (float32, standardized) and `X_cat` (int64 codes), together with the masks. The target is one of the columns (the first numerical column for regression, the first categorical column for classification).
|
|
103
|
+
|
|
104
|
+
### Your own augmenter
|
|
105
|
+
|
|
106
|
+
Any object with an `augment` method can replace LGBM-S:
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from augmask.run import run
|
|
110
|
+
|
|
111
|
+
class MyAugmenter:
|
|
112
|
+
def augment(self, train, others, n_categories):
|
|
113
|
+
# fit on `train` (an Encoded table); return [(X_num, X_cat), ...] for `train` and each of `others`,
|
|
114
|
+
# with every missing entry filled: floats in X_num, codes 0 … K_j−1 in X_cat.
|
|
115
|
+
# It is called once per fill (5 by default), so return a new random draw on each call.
|
|
116
|
+
...
|
|
117
|
+
|
|
118
|
+
run("adult", "mcar", 0.5, "tabdiff-augmask", augmenter=MyAugmenter())
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## 🚀 Run
|
|
122
|
+
|
|
123
|
+
Datasets are downloaded from UCI on first use.
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# one method on one scenario: train, sample and evaluate -> runs/<dataset>/<mechanism>/p<p>/seed<s>/<method>.{csv,json}
|
|
127
|
+
python -m augmask.run --dataset adult --mechanism mcar --p 0.5 --method cdtd-augmask
|
|
128
|
+
|
|
129
|
+
# all experiments (6 datasets x 5 missing rates x 3 seeds x 14 methods) followed by the summary tables
|
|
130
|
+
bash scripts/run_all.sh 0 # on GPU 0
|
|
131
|
+
bash scripts/run_all.sh 1 beijing news # or split the datasets across GPUs and servers,
|
|
132
|
+
python scripts/make_tables.py # then summarise the merged runs/
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Methods are `{tabddpm,cdtd,tabdiff}-{noaug,meanmask,augfull,augmask}`, plus the baselines `forestdiff` and `miwae`.
|
|
136
|
+
|
|
137
|
+
| Strategy | Missing inputs filled with | Loss on |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| `noaug` | train mean / mode | all entries |
|
|
140
|
+
| `meanmask` | train mean / mode | observed entries (similar to [MissDiff](https://arxiv.org/abs/2307.00467); Ouyang et al., 2023) |
|
|
141
|
+
| `augfull` (ours) | samples from the augmenter (LGBM-S) | all entries |
|
|
142
|
+
| `augmask` (ours) | samples from the augmenter (LGBM-S) | observed entries |
|
|
143
|
+
|
|
144
|
+
**Alternating fills.** For improved performance, this implementation gives `augfull` and `augmask` 5 independent fills of the missing inputs and alternates between them during training, one per step (`--fills 5`, the default). `--fills 1` uses the single fill of the paper. The gain is largest at high missing rates.
|
|
145
|
+
|
|
146
|
+
**Masks and fills.** The first run of a scenario saves its missingness masks and augmented fills to `artifacts/<dataset>/<mechanism>/p<p>/seed<s>.npz`; later runs of the same scenario reuse them, so LGBM-S runs once per scenario rather than once per method.
|
|
147
|
+
|
|
148
|
+
**Runtime.** LGBM-S takes a few seconds per fill (fit on the train split, fill train and validation; AMD Ryzen 9 5950X, 32 threads); the default 5 fills take about five times as long, once per scenario:
|
|
149
|
+
|
|
150
|
+
| Missing | Adult | Default | Shoppers | Magic | Beijing | News |
|
|
151
|
+
|---|---:|---:|---:|---:|---:|---:|
|
|
152
|
+
| 10% | 3.5 s | 2.0 s | 1.3 s | 0.3 s | 2.9 s | 5.7 s |
|
|
153
|
+
| 50% | 4.5 s | 2.3 s | 1.5 s | 0.3 s | 4.1 s | 4.9 s |
|
|
154
|
+
| 90% | 6.0 s | 2.0 s | 1.1 s | 0.3 s | 5.8 s | 2.9 s |
|
|
155
|
+
|
|
156
|
+
## 📊 Reference results
|
|
157
|
+
|
|
158
|
+
Adult and Beijing, MCAR with 50% and 90% missing, one seed, averaged over the four scenarios (×100, best in bold). Utility is downstream task performance: a model trained on synthetic rows and tested on real ones, relative to training on real rows.
|
|
159
|
+
|
|
160
|
+
- **Missing-aware:** [ForestDiff](https://proceedings.mlr.press/v238/jolicoeur-martineau24a.html) (AISTATS 2024) and [MIWAE](https://proceedings.mlr.press/v97/mattei19a.html) (ICML 2019).
|
|
161
|
+
- **Missing-unaware**, trained with the four strategies above: [TabDDPM](https://proceedings.mlr.press/v202/kotelnikov23a.html) (ICML 2023), [CDTD](https://proceedings.iclr.cc/paper_files/paper/2025/hash/61f4e5747b1b753cb35546b15d981f76-Abstract-Conference.html) (ICLR 2025) and [TabDiff](https://proceedings.iclr.cc/paper_files/paper/2025/hash/5c882988ce5fac487974ee4f415b96a9-Abstract-Conference.html) (ICLR 2025).
|
|
162
|
+
|
|
163
|
+
| Method | Shape ↑ | Trend ↑ | α-Precision ↑ | β-Recall ↑ | Utility ↑ |
|
|
164
|
+
|---|---:|---:|---:|---:|---:|
|
|
165
|
+
| TabDDPM + NoAug | 68.2 | 54.7 | 45.1 | 8.7 | 66.0 |
|
|
166
|
+
| TabDDPM + MeanMask | 94.9 | 88.5 | 91.9 | 28.3 | 74.5 |
|
|
167
|
+
| TabDDPM + AugFull (ours) | 95.7 | 90.2 | 93.5 | 31.7 | 75.6 |
|
|
168
|
+
| TabDDPM + AugMask (ours) | 94.1 | 88.5 | 90.8 | 35.6 | 77.9 |
|
|
169
|
+
| CDTD + NoAug | 68.5 | 55.7 | 44.5 | 9.1 | 66.2 |
|
|
170
|
+
| CDTD + MeanMask | 93.6 | 84.5 | 93.2 | 23.0 | 73.6 |
|
|
171
|
+
| CDTD + AugFull (ours) | 95.5 | 91.0 | 91.2 | 33.2 | 77.2 |
|
|
172
|
+
| CDTD + AugMask (ours) | 97.8 | 93.4 | 98.0 | 37.8 | 76.7 |
|
|
173
|
+
| TabDiff + NoAug | 66.9 | 54.3 | 43.8 | 9.0 | 67.9 |
|
|
174
|
+
| TabDiff + MeanMask | 96.6 | 88.8 | 95.0 | 29.3 | 73.3 |
|
|
175
|
+
| TabDiff + AugFull (ours) | 95.7 | 91.4 | 93.1 | 32.3 | 76.6 |
|
|
176
|
+
| TabDiff + AugMask (ours) | **98.1** | **94.4** | **98.4** | **39.1** | **79.1** |
|
|
177
|
+
| ForestDiff | 69.7 | 66.7 | 65.6 | 22.4 | 66.4 |
|
|
178
|
+
| MIWAE | 97.5 | 85.2 | 97.1 | 29.1 | 72.4 |
|
|
179
|
+
|
|
180
|
+
<details>
|
|
181
|
+
<summary>Per scenario</summary>
|
|
182
|
+
|
|
183
|
+
**Adult, 50% missing**
|
|
184
|
+
|
|
185
|
+
| Method | Shape ↑ | Trend ↑ | α-Precision ↑ | β-Recall ↑ | Utility ↑ |
|
|
186
|
+
|---|---:|---:|---:|---:|---:|
|
|
187
|
+
| TabDDPM + NoAug | 81.9 | 71.9 | 51.5 | 15.5 | 95.9 |
|
|
188
|
+
| TabDDPM + MeanMask | 94.7 | 89.7 | 90.8 | 30.9 | 97.3 |
|
|
189
|
+
| TabDDPM + AugFull (ours) | 97.2 | 92.3 | 97.3 | 35.1 | 96.8 |
|
|
190
|
+
| TabDDPM + AugMask (ours) | 96.2 | 92.6 | 95.7 | 43.3 | 97.2 |
|
|
191
|
+
| CDTD + NoAug | 83.3 | 74.2 | 54.1 | 16.6 | 96.4 |
|
|
192
|
+
| CDTD + MeanMask | 95.3 | 92.0 | 93.1 | 34.4 | 96.8 |
|
|
193
|
+
| CDTD + AugFull (ours) | 96.7 | 94.0 | 94.8 | 37.9 | **97.9** |
|
|
194
|
+
| CDTD + AugMask (ours) | 98.9 | 97.2 | 97.3 | **46.0** | 97.9 |
|
|
195
|
+
| TabDiff + NoAug | 81.0 | 72.3 | 50.8 | 15.9 | 95.1 |
|
|
196
|
+
| TabDiff + MeanMask | 96.2 | 93.6 | 96.1 | 35.7 | 97.5 |
|
|
197
|
+
| TabDiff + AugFull (ours) | 97.1 | 94.2 | 98.1 | 36.5 | 97.2 |
|
|
198
|
+
| TabDiff + AugMask (ours) | **99.1** | **97.8** | **99.4** | 45.4 | 97.7 |
|
|
199
|
+
| ForestDiff | 90.7 | 91.3 | 95.4 | 34.8 | 97.0 |
|
|
200
|
+
| MIWAE | 97.3 | 94.9 | 98.3 | 30.8 | 95.5 |
|
|
201
|
+
|
|
202
|
+
**Adult, 90% missing**
|
|
203
|
+
|
|
204
|
+
| Method | Shape ↑ | Trend ↑ | α-Precision ↑ | β-Recall ↑ | Utility ↑ |
|
|
205
|
+
|---|---:|---:|---:|---:|---:|
|
|
206
|
+
| TabDDPM + NoAug | 66.3 | 46.2 | 10.9 | 1.8 | 71.7 |
|
|
207
|
+
| TabDDPM + MeanMask | 94.6 | 85.4 | 92.9 | 11.8 | 93.7 |
|
|
208
|
+
| TabDDPM + AugFull (ours) | 94.6 | 85.0 | 95.8 | 13.6 | 92.4 |
|
|
209
|
+
| TabDDPM + AugMask (ours) | 93.3 | 85.0 | 90.1 | 30.0 | 94.9 |
|
|
210
|
+
| CDTD + NoAug | 69.0 | 50.1 | 11.9 | 1.9 | 70.0 |
|
|
211
|
+
| CDTD + MeanMask | 93.2 | 75.3 | 90.3 | 9.1 | 87.5 |
|
|
212
|
+
| CDTD + AugFull (ours) | 93.9 | 84.2 | 91.2 | 14.0 | 92.6 |
|
|
213
|
+
| CDTD + AugMask (ours) | **97.9** | 90.9 | **99.1** | 30.9 | 94.0 |
|
|
214
|
+
| TabDiff + NoAug | 65.9 | 47.1 | 10.5 | 1.8 | 78.9 |
|
|
215
|
+
| TabDiff + MeanMask | 95.5 | 87.2 | 90.9 | 10.3 | 91.6 |
|
|
216
|
+
| TabDiff + AugFull (ours) | 94.4 | 85.1 | 94.9 | 14.1 | 93.8 |
|
|
217
|
+
| TabDiff + AugMask (ours) | 97.4 | **91.1** | 97.5 | **33.0** | **95.4** |
|
|
218
|
+
| ForestDiff | 36.3 | 26.9 | 1.4 | 0.3 | 72.3 |
|
|
219
|
+
| MIWAE | 97.6 | 89.1 | 96.5 | 14.2 | 92.0 |
|
|
220
|
+
|
|
221
|
+
**Beijing, 50% missing**
|
|
222
|
+
|
|
223
|
+
| Method | Shape ↑ | Trend ↑ | α-Precision ↑ | β-Recall ↑ | Utility ↑ |
|
|
224
|
+
|---|---:|---:|---:|---:|---:|
|
|
225
|
+
| TabDDPM + NoAug | 74.2 | 64.1 | 70.3 | 15.9 | 50.5 |
|
|
226
|
+
| TabDDPM + MeanMask | 95.3 | 92.1 | 92.0 | 37.4 | 58.0 |
|
|
227
|
+
| TabDDPM + AugFull (ours) | 97.6 | 94.8 | 97.2 | 39.8 | 62.3 |
|
|
228
|
+
| TabDDPM + AugMask (ours) | 97.4 | 93.0 | 94.9 | 39.0 | 65.5 |
|
|
229
|
+
| CDTD + NoAug | 72.2 | 64.8 | 68.1 | 16.6 | 56.4 |
|
|
230
|
+
| CDTD + MeanMask | 95.2 | 92.7 | 97.0 | 39.6 | 64.6 |
|
|
231
|
+
| CDTD + AugFull (ours) | 97.5 | 95.5 | 95.2 | 42.1 | 66.0 |
|
|
232
|
+
| CDTD + AugMask (ours) | 98.5 | 96.0 | 98.5 | **42.9** | 62.8 |
|
|
233
|
+
| TabDiff + NoAug | 72.2 | 64.4 | 69.2 | 16.4 | 53.5 |
|
|
234
|
+
| TabDiff + MeanMask | 97.2 | 94.7 | 97.9 | 38.6 | 59.9 |
|
|
235
|
+
| TabDiff + AugFull (ours) | 97.7 | 95.8 | 95.8 | 40.5 | 64.1 |
|
|
236
|
+
| TabDiff + AugMask (ours) | **98.8** | **96.3** | **98.9** | 40.8 | **67.9** |
|
|
237
|
+
| ForestDiff | 91.9 | 90.6 | 93.1 | 35.1 | 62.4 |
|
|
238
|
+
| MIWAE | 97.8 | 87.1 | 97.2 | 39.2 | 58.3 |
|
|
239
|
+
|
|
240
|
+
**Beijing, 90% missing**
|
|
241
|
+
|
|
242
|
+
| Method | Shape ↑ | Trend ↑ | α-Precision ↑ | β-Recall ↑ | Utility ↑ |
|
|
243
|
+
|---|---:|---:|---:|---:|---:|
|
|
244
|
+
| TabDDPM + NoAug | 50.4 | 36.6 | 47.7 | 1.6 | 46.1 |
|
|
245
|
+
| TabDDPM + MeanMask | 94.9 | 86.6 | 91.7 | 33.3 | 49.1 |
|
|
246
|
+
| TabDDPM + AugFull (ours) | 93.6 | 88.6 | 83.8 | 38.1 | 50.9 |
|
|
247
|
+
| TabDDPM + AugMask (ours) | 89.6 | 83.4 | 82.7 | 30.1 | 53.9 |
|
|
248
|
+
| CDTD + NoAug | 49.5 | 33.7 | 43.8 | 1.0 | 42.0 |
|
|
249
|
+
| CDTD + MeanMask | 90.5 | 78.1 | 92.3 | 9.0 | 45.4 |
|
|
250
|
+
| CDTD + AugFull (ours) | 93.7 | 90.4 | 83.6 | **38.8** | 52.2 |
|
|
251
|
+
| CDTD + AugMask (ours) | 95.6 | 89.6 | 97.0 | 31.6 | 52.1 |
|
|
252
|
+
| TabDiff + NoAug | 48.6 | 33.7 | 44.9 | 1.8 | 44.3 |
|
|
253
|
+
| TabDiff + MeanMask | 97.4 | 79.8 | 95.2 | 32.3 | 44.3 |
|
|
254
|
+
| TabDiff + AugFull (ours) | 93.8 | 90.8 | 83.7 | 38.2 | 51.2 |
|
|
255
|
+
| TabDiff + AugMask (ours) | 97.0 | **92.6** | **98.0** | 37.3 | **55.6** |
|
|
256
|
+
| ForestDiff | 59.7 | 58.1 | 72.4 | 19.6 | 33.7 |
|
|
257
|
+
| MIWAE | **97.5** | 69.5 | 96.2 | 32.3 | 43.9 |
|
|
258
|
+
|
|
259
|
+
</details>
|
|
260
|
+
|
|
261
|
+
## 🔧 Pipeline
|
|
262
|
+
|
|
263
|
+
1. **Collect** the six UCI tables (Adult, Default, Shoppers, Magic, Beijing, News).
|
|
264
|
+
2. **Split** each table 60/20/20 into train, validation and test.
|
|
265
|
+
3. **Mask** train and validation entries (the target included) completely at random (MCAR) or depending on the other columns (MAR); the test split stays complete.
|
|
266
|
+
4. **Encode**, using the observed train entries: numerical columns are quantile-normal transformed, categorical columns are integer encoded.
|
|
267
|
+
5. **Fill** the missing entries with the train mean / mode, or *sample* them with the augmenter (LGBM-S by default; 5 fills, alternated during training).
|
|
268
|
+
6. **Standardize** the numerical columns.
|
|
269
|
+
7. **Train** the backbone and sample as many rows as the train split.
|
|
270
|
+
8. **Map** the samples back to the original columns and values.
|
|
271
|
+
9. **Evaluate** against the complete train and test splits: Shape, Trend, α-Precision, β-Recall and Utility (downstream task performance), following [TabSyn](https://proceedings.iclr.cc/paper_files/paper/2024/hash/e9750610639c3e7a849cff746bf60dbd-Abstract-Conference.html) (ICLR 2024).
|
|
272
|
+
|
|
273
|
+
<details>
|
|
274
|
+
<summary>Repository structure</summary>
|
|
275
|
+
|
|
276
|
+
```
|
|
277
|
+
augmask/
|
|
278
|
+
├── augment.py # step 5: LGBM-S (Algorithm 1), mean/mode fill, the Augmenter interface
|
|
279
|
+
├── run.py # one method on one scenario: build, train, sample, evaluate
|
|
280
|
+
├── evaluate.py # step 9: Shape, Trend, α-Precision, β-Recall, Utility
|
|
281
|
+
├── data/
|
|
282
|
+
│ ├── datasets.py # step 1: download and clean the six UCI tables
|
|
283
|
+
│ ├── split.py # step 2: fixed stratified 60/20/20 split
|
|
284
|
+
│ ├── missingness.py # step 3: MCAR and MAR masks
|
|
285
|
+
│ ├── transforms.py # steps 4 and 6: quantile-normal, integer codes, standardization
|
|
286
|
+
│ ├── scenario.py # steps 3-6 and 8 for one scenario; saves and loads masks and fills
|
|
287
|
+
│ └── schema.py # column types, target and task
|
|
288
|
+
├── models/ # step 7
|
|
289
|
+
│ ├── tabddpm.py, cdtd.py, tabdiff.py # the backbones, each with an optional loss mask
|
|
290
|
+
│ └── common.py # seeding, batching (one fill per step), EMA
|
|
291
|
+
└── baselines/
|
|
292
|
+
├── forestdiff.py # the official ForestDiffusion package, wrapped
|
|
293
|
+
└── miwae.py
|
|
294
|
+
scripts/
|
|
295
|
+
├── run_all.sh # all experiments, then the summary tables
|
|
296
|
+
├── make_tables.py # rank tables with Wilcoxon markers
|
|
297
|
+
└── plot_overview.py # the figure above
|
|
298
|
+
tests/ # pipeline, missingness, baselines, evaluation, each backbone, the runner
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
</details>
|
|
302
|
+
|
|
303
|
+
## 📝 Notes on this release
|
|
304
|
+
|
|
305
|
+
The data pipeline was rebuilt for this release (60/20/20 split, a new MAR generator), so numbers differ slightly from the paper. Most model and training settings follow Appendix C.6 of the paper. The exception is alternating fills: AugFull and AugMask alternate between 5 fills of the missing inputs during training, which performs better at high missing rates in this implementation (`--fills 1` restores the paper's single fill). LGBM-S follows Algorithm 1; `LGBMSAugmenter(log_var_offset=augmask.augment.LOG_CHI2_BIAS)` optionally corrects the downward bias of its variance model.
|
|
306
|
+
|
|
307
|
+
LGBM-S is a per-coordinate augmenter: it samples each missing entry independently given the observed values and the mask, so it does not model the dependence between entries that are missing together. An augmenter that samples the missing coordinates jointly is a natural direction for future work, and can be plugged in as described in [Your own augmenter](#your-own-augmenter).
|
|
308
|
+
|
|
309
|
+
## 📚 Citation
|
|
310
|
+
|
|
311
|
+
```bibtex
|
|
312
|
+
@inproceedings{kim2026augmask,
|
|
313
|
+
title = {{AugMask}: Training Diffusion Models on Incomplete Tabular Data via Stochastic Augmentation and Masking},
|
|
314
|
+
author = {Kim, Jungkyu and Park, Taeyoung and Lee, Kibok},
|
|
315
|
+
booktitle = {Proceedings of the 43rd International Conference on Machine Learning},
|
|
316
|
+
series = {Proceedings of Machine Learning Research},
|
|
317
|
+
volume = {306},
|
|
318
|
+
year = {2026}
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## 🙏 Acknowledgements
|
|
323
|
+
|
|
324
|
+
The backbones are adapted from [TabDDPM](https://github.com/yandex-research/tab-ddpm), [CDTD](https://github.com/muellermarkus/cdtd) and [TabDiff](https://github.com/MinkaiXu/TabDiff) (MIT). The metrics follow [TabSyn](https://github.com/amazon-science/tabsyn) (Apache-2.0), α-Precision/β-Recall follow [synthcity](https://github.com/vanderschaarlab/synthcity), and MIWAE follows [hyperimpute](https://github.com/vanderschaarlab/hyperimpute) (MIT). ForestDiff uses the official [ForestDiffusion](https://github.com/SamsungSAILMontreal/ForestDiffusion) package.
|
|
325
|
+
|
|
326
|
+
Released under the MIT License.
|
augmask-0.1.0/README.md
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
# AugMask
|
|
2
|
+
|
|
3
|
+
Official code for **AugMask: Training Diffusion Models on Incomplete Tabular Data via Stochastic Augmentation and Masking** (ICML 2026).
|
|
4
|
+
Jungkyu Kim, Taeyoung Park, Kibok Lee. [[arXiv]](https://arxiv.org/abs/2606.03347) [[OpenReview]](https://openreview.net/forum?id=Ot8lh7vvGe)
|
|
5
|
+
|
|
6
|
+
## 💡 Why AugMask
|
|
7
|
+
|
|
8
|
+
**Diffusion models for tabular data are built for complete rows**, but real tables have missing entries. The usual workarounds fail:
|
|
9
|
+
|
|
10
|
+
- **Constant fills become data.** A model trained on mean-filled rows *treats the fills as observed values* and learns to reproduce them. Below, the filled rows collapse onto a cross at the column means.
|
|
11
|
+
- **Masking the loss is not enough.** Filled entries left out of the loss are *still read as inputs*, so the model learns from rows that real data rarely contains, such as a hot day paired with the average dew point.
|
|
12
|
+
|
|
13
|
+
AugMask fixes both:
|
|
14
|
+
|
|
15
|
+
1. **Augment.** A missing entry is *unrealized data that could take many different values*, so AugMask *samples* it instead of imputing it deterministically. Each missing entry $`x_j`$ is drawn from a conditional model of its column, $`x_j \sim \hat{p}_j(x_j \mid x_{\mathrm{obs}}, m)`$: the augmenter receives the row's observed values $`x_{\mathrm{obs}}`$ and its missingness mask $`m`$ as inputs. This repository uses LGBM-S, lightweight per-column LightGBM models, as the augmenter; the sampled rows resemble the complete data (right panel).
|
|
16
|
+
2. **Mask.** The denoising loss is computed on observed entries only, so the sampled values serve as *context, never as targets*.
|
|
17
|
+
|
|
18
|
+
<picture>
|
|
19
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/normal-kim/AugMask/main/assets/overview_dark.png">
|
|
20
|
+
<img src="https://raw.githubusercontent.com/normal-kim/AugMask/main/assets/overview_light.png" alt="Mean filling collapses rows onto a cross at the column means; augmented fills follow the joint distribution. Inputs are filled, and the loss uses observed entries only." width="100%">
|
|
21
|
+
</picture>
|
|
22
|
+
|
|
23
|
+
AugMask needs no change to the model itself. This repository applies it to three diffusion models: [TabDDPM](https://proceedings.mlr.press/v202/kotelnikov23a.html) (ICML 2023; [code](https://github.com/yandex-research/tab-ddpm)), [CDTD](https://proceedings.iclr.cc/paper_files/paper/2025/hash/61f4e5747b1b753cb35546b15d981f76-Abstract-Conference.html) (ICLR 2025; [code](https://github.com/muellermarkus/cdtd)) and [TabDiff](https://proceedings.iclr.cc/paper_files/paper/2025/hash/5c882988ce5fac487974ee4f415b96a9-Abstract-Conference.html) (ICLR 2025; [code](https://github.com/MinkaiXu/TabDiff)).
|
|
24
|
+
|
|
25
|
+
## 📦 Install
|
|
26
|
+
|
|
27
|
+
Python 3.10–3.12.
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install augmask # the augmentation (LGBM-S) alone
|
|
31
|
+
pip install "augmask[all]" # plus the diffusion backbones, baselines and evaluation
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
To run the experiments, clone this repository and create the exact environment used for the results:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
git clone https://github.com/normal-kim/AugMask.git && cd AugMask
|
|
38
|
+
conda env create -f environment.yml && conda activate augmask
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 🧩 Use AugMask with your own model
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from augmask import Encoded, LGBMSAugmenter
|
|
45
|
+
|
|
46
|
+
train = Encoded(X_num, X_cat, M_num, M_cat)
|
|
47
|
+
fills = [LGBMSAugmenter(draw=k).augment(train, [], n_categories)[0] for k in range(5)]
|
|
48
|
+
|
|
49
|
+
# train your denoiser on fills[step % 5], with the loss restricted to observed entries
|
|
50
|
+
loss = (per_entry_loss * mask).sum() / mask.sum()
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The augmenter takes an encoded table with `n` rows:
|
|
54
|
+
|
|
55
|
+
| Input | Shape | Type | Content |
|
|
56
|
+
|---|---|---|---|
|
|
57
|
+
| `X_num` | `(n, d_num)` | float | numerical columns, quantile-normal transformed; `NaN` where missing |
|
|
58
|
+
| `X_cat` | `(n, d_cat)` | int | categorical columns, integer encoded as `0 … K_j−1`; `−1` where missing |
|
|
59
|
+
| `M_num`, `M_cat` | same as above | bool | `True` where observed |
|
|
60
|
+
| `n_categories` | `d_cat` | list of int | number of categories `K_j` of each categorical column |
|
|
61
|
+
|
|
62
|
+
`augment` returns `X_num` and `X_cat` with every missing entry filled; each `draw` gives an independent fill, with the observed entries unchanged. In this repository, the backbones receive one fill per training step: `X_num` (float32, standardized) and `X_cat` (int64 codes), together with the masks. The target is one of the columns (the first numerical column for regression, the first categorical column for classification).
|
|
63
|
+
|
|
64
|
+
### Your own augmenter
|
|
65
|
+
|
|
66
|
+
Any object with an `augment` method can replace LGBM-S:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from augmask.run import run
|
|
70
|
+
|
|
71
|
+
class MyAugmenter:
|
|
72
|
+
def augment(self, train, others, n_categories):
|
|
73
|
+
# fit on `train` (an Encoded table); return [(X_num, X_cat), ...] for `train` and each of `others`,
|
|
74
|
+
# with every missing entry filled: floats in X_num, codes 0 … K_j−1 in X_cat.
|
|
75
|
+
# It is called once per fill (5 by default), so return a new random draw on each call.
|
|
76
|
+
...
|
|
77
|
+
|
|
78
|
+
run("adult", "mcar", 0.5, "tabdiff-augmask", augmenter=MyAugmenter())
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## 🚀 Run
|
|
82
|
+
|
|
83
|
+
Datasets are downloaded from UCI on first use.
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# one method on one scenario: train, sample and evaluate -> runs/<dataset>/<mechanism>/p<p>/seed<s>/<method>.{csv,json}
|
|
87
|
+
python -m augmask.run --dataset adult --mechanism mcar --p 0.5 --method cdtd-augmask
|
|
88
|
+
|
|
89
|
+
# all experiments (6 datasets x 5 missing rates x 3 seeds x 14 methods) followed by the summary tables
|
|
90
|
+
bash scripts/run_all.sh 0 # on GPU 0
|
|
91
|
+
bash scripts/run_all.sh 1 beijing news # or split the datasets across GPUs and servers,
|
|
92
|
+
python scripts/make_tables.py # then summarise the merged runs/
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Methods are `{tabddpm,cdtd,tabdiff}-{noaug,meanmask,augfull,augmask}`, plus the baselines `forestdiff` and `miwae`.
|
|
96
|
+
|
|
97
|
+
| Strategy | Missing inputs filled with | Loss on |
|
|
98
|
+
|---|---|---|
|
|
99
|
+
| `noaug` | train mean / mode | all entries |
|
|
100
|
+
| `meanmask` | train mean / mode | observed entries (similar to [MissDiff](https://arxiv.org/abs/2307.00467); Ouyang et al., 2023) |
|
|
101
|
+
| `augfull` (ours) | samples from the augmenter (LGBM-S) | all entries |
|
|
102
|
+
| `augmask` (ours) | samples from the augmenter (LGBM-S) | observed entries |
|
|
103
|
+
|
|
104
|
+
**Alternating fills.** For improved performance, this implementation gives `augfull` and `augmask` 5 independent fills of the missing inputs and alternates between them during training, one per step (`--fills 5`, the default). `--fills 1` uses the single fill of the paper. The gain is largest at high missing rates.
|
|
105
|
+
|
|
106
|
+
**Masks and fills.** The first run of a scenario saves its missingness masks and augmented fills to `artifacts/<dataset>/<mechanism>/p<p>/seed<s>.npz`; later runs of the same scenario reuse them, so LGBM-S runs once per scenario rather than once per method.
|
|
107
|
+
|
|
108
|
+
**Runtime.** LGBM-S takes a few seconds per fill (fit on the train split, fill train and validation; AMD Ryzen 9 5950X, 32 threads); the default 5 fills take about five times as long, once per scenario:
|
|
109
|
+
|
|
110
|
+
| Missing | Adult | Default | Shoppers | Magic | Beijing | News |
|
|
111
|
+
|---|---:|---:|---:|---:|---:|---:|
|
|
112
|
+
| 10% | 3.5 s | 2.0 s | 1.3 s | 0.3 s | 2.9 s | 5.7 s |
|
|
113
|
+
| 50% | 4.5 s | 2.3 s | 1.5 s | 0.3 s | 4.1 s | 4.9 s |
|
|
114
|
+
| 90% | 6.0 s | 2.0 s | 1.1 s | 0.3 s | 5.8 s | 2.9 s |
|
|
115
|
+
|
|
116
|
+
## 📊 Reference results
|
|
117
|
+
|
|
118
|
+
Adult and Beijing, MCAR with 50% and 90% missing, one seed, averaged over the four scenarios (×100, best in bold). Utility is downstream task performance: a model trained on synthetic rows and tested on real ones, relative to training on real rows.
|
|
119
|
+
|
|
120
|
+
- **Missing-aware:** [ForestDiff](https://proceedings.mlr.press/v238/jolicoeur-martineau24a.html) (AISTATS 2024) and [MIWAE](https://proceedings.mlr.press/v97/mattei19a.html) (ICML 2019).
|
|
121
|
+
- **Missing-unaware**, trained with the four strategies above: [TabDDPM](https://proceedings.mlr.press/v202/kotelnikov23a.html) (ICML 2023), [CDTD](https://proceedings.iclr.cc/paper_files/paper/2025/hash/61f4e5747b1b753cb35546b15d981f76-Abstract-Conference.html) (ICLR 2025) and [TabDiff](https://proceedings.iclr.cc/paper_files/paper/2025/hash/5c882988ce5fac487974ee4f415b96a9-Abstract-Conference.html) (ICLR 2025).
|
|
122
|
+
|
|
123
|
+
| Method | Shape ↑ | Trend ↑ | α-Precision ↑ | β-Recall ↑ | Utility ↑ |
|
|
124
|
+
|---|---:|---:|---:|---:|---:|
|
|
125
|
+
| TabDDPM + NoAug | 68.2 | 54.7 | 45.1 | 8.7 | 66.0 |
|
|
126
|
+
| TabDDPM + MeanMask | 94.9 | 88.5 | 91.9 | 28.3 | 74.5 |
|
|
127
|
+
| TabDDPM + AugFull (ours) | 95.7 | 90.2 | 93.5 | 31.7 | 75.6 |
|
|
128
|
+
| TabDDPM + AugMask (ours) | 94.1 | 88.5 | 90.8 | 35.6 | 77.9 |
|
|
129
|
+
| CDTD + NoAug | 68.5 | 55.7 | 44.5 | 9.1 | 66.2 |
|
|
130
|
+
| CDTD + MeanMask | 93.6 | 84.5 | 93.2 | 23.0 | 73.6 |
|
|
131
|
+
| CDTD + AugFull (ours) | 95.5 | 91.0 | 91.2 | 33.2 | 77.2 |
|
|
132
|
+
| CDTD + AugMask (ours) | 97.8 | 93.4 | 98.0 | 37.8 | 76.7 |
|
|
133
|
+
| TabDiff + NoAug | 66.9 | 54.3 | 43.8 | 9.0 | 67.9 |
|
|
134
|
+
| TabDiff + MeanMask | 96.6 | 88.8 | 95.0 | 29.3 | 73.3 |
|
|
135
|
+
| TabDiff + AugFull (ours) | 95.7 | 91.4 | 93.1 | 32.3 | 76.6 |
|
|
136
|
+
| TabDiff + AugMask (ours) | **98.1** | **94.4** | **98.4** | **39.1** | **79.1** |
|
|
137
|
+
| ForestDiff | 69.7 | 66.7 | 65.6 | 22.4 | 66.4 |
|
|
138
|
+
| MIWAE | 97.5 | 85.2 | 97.1 | 29.1 | 72.4 |
|
|
139
|
+
|
|
140
|
+
<details>
|
|
141
|
+
<summary>Per scenario</summary>
|
|
142
|
+
|
|
143
|
+
**Adult, 50% missing**
|
|
144
|
+
|
|
145
|
+
| Method | Shape ↑ | Trend ↑ | α-Precision ↑ | β-Recall ↑ | Utility ↑ |
|
|
146
|
+
|---|---:|---:|---:|---:|---:|
|
|
147
|
+
| TabDDPM + NoAug | 81.9 | 71.9 | 51.5 | 15.5 | 95.9 |
|
|
148
|
+
| TabDDPM + MeanMask | 94.7 | 89.7 | 90.8 | 30.9 | 97.3 |
|
|
149
|
+
| TabDDPM + AugFull (ours) | 97.2 | 92.3 | 97.3 | 35.1 | 96.8 |
|
|
150
|
+
| TabDDPM + AugMask (ours) | 96.2 | 92.6 | 95.7 | 43.3 | 97.2 |
|
|
151
|
+
| CDTD + NoAug | 83.3 | 74.2 | 54.1 | 16.6 | 96.4 |
|
|
152
|
+
| CDTD + MeanMask | 95.3 | 92.0 | 93.1 | 34.4 | 96.8 |
|
|
153
|
+
| CDTD + AugFull (ours) | 96.7 | 94.0 | 94.8 | 37.9 | **97.9** |
|
|
154
|
+
| CDTD + AugMask (ours) | 98.9 | 97.2 | 97.3 | **46.0** | 97.9 |
|
|
155
|
+
| TabDiff + NoAug | 81.0 | 72.3 | 50.8 | 15.9 | 95.1 |
|
|
156
|
+
| TabDiff + MeanMask | 96.2 | 93.6 | 96.1 | 35.7 | 97.5 |
|
|
157
|
+
| TabDiff + AugFull (ours) | 97.1 | 94.2 | 98.1 | 36.5 | 97.2 |
|
|
158
|
+
| TabDiff + AugMask (ours) | **99.1** | **97.8** | **99.4** | 45.4 | 97.7 |
|
|
159
|
+
| ForestDiff | 90.7 | 91.3 | 95.4 | 34.8 | 97.0 |
|
|
160
|
+
| MIWAE | 97.3 | 94.9 | 98.3 | 30.8 | 95.5 |
|
|
161
|
+
|
|
162
|
+
**Adult, 90% missing**
|
|
163
|
+
|
|
164
|
+
| Method | Shape ↑ | Trend ↑ | α-Precision ↑ | β-Recall ↑ | Utility ↑ |
|
|
165
|
+
|---|---:|---:|---:|---:|---:|
|
|
166
|
+
| TabDDPM + NoAug | 66.3 | 46.2 | 10.9 | 1.8 | 71.7 |
|
|
167
|
+
| TabDDPM + MeanMask | 94.6 | 85.4 | 92.9 | 11.8 | 93.7 |
|
|
168
|
+
| TabDDPM + AugFull (ours) | 94.6 | 85.0 | 95.8 | 13.6 | 92.4 |
|
|
169
|
+
| TabDDPM + AugMask (ours) | 93.3 | 85.0 | 90.1 | 30.0 | 94.9 |
|
|
170
|
+
| CDTD + NoAug | 69.0 | 50.1 | 11.9 | 1.9 | 70.0 |
|
|
171
|
+
| CDTD + MeanMask | 93.2 | 75.3 | 90.3 | 9.1 | 87.5 |
|
|
172
|
+
| CDTD + AugFull (ours) | 93.9 | 84.2 | 91.2 | 14.0 | 92.6 |
|
|
173
|
+
| CDTD + AugMask (ours) | **97.9** | 90.9 | **99.1** | 30.9 | 94.0 |
|
|
174
|
+
| TabDiff + NoAug | 65.9 | 47.1 | 10.5 | 1.8 | 78.9 |
|
|
175
|
+
| TabDiff + MeanMask | 95.5 | 87.2 | 90.9 | 10.3 | 91.6 |
|
|
176
|
+
| TabDiff + AugFull (ours) | 94.4 | 85.1 | 94.9 | 14.1 | 93.8 |
|
|
177
|
+
| TabDiff + AugMask (ours) | 97.4 | **91.1** | 97.5 | **33.0** | **95.4** |
|
|
178
|
+
| ForestDiff | 36.3 | 26.9 | 1.4 | 0.3 | 72.3 |
|
|
179
|
+
| MIWAE | 97.6 | 89.1 | 96.5 | 14.2 | 92.0 |
|
|
180
|
+
|
|
181
|
+
**Beijing, 50% missing**
|
|
182
|
+
|
|
183
|
+
| Method | Shape ↑ | Trend ↑ | α-Precision ↑ | β-Recall ↑ | Utility ↑ |
|
|
184
|
+
|---|---:|---:|---:|---:|---:|
|
|
185
|
+
| TabDDPM + NoAug | 74.2 | 64.1 | 70.3 | 15.9 | 50.5 |
|
|
186
|
+
| TabDDPM + MeanMask | 95.3 | 92.1 | 92.0 | 37.4 | 58.0 |
|
|
187
|
+
| TabDDPM + AugFull (ours) | 97.6 | 94.8 | 97.2 | 39.8 | 62.3 |
|
|
188
|
+
| TabDDPM + AugMask (ours) | 97.4 | 93.0 | 94.9 | 39.0 | 65.5 |
|
|
189
|
+
| CDTD + NoAug | 72.2 | 64.8 | 68.1 | 16.6 | 56.4 |
|
|
190
|
+
| CDTD + MeanMask | 95.2 | 92.7 | 97.0 | 39.6 | 64.6 |
|
|
191
|
+
| CDTD + AugFull (ours) | 97.5 | 95.5 | 95.2 | 42.1 | 66.0 |
|
|
192
|
+
| CDTD + AugMask (ours) | 98.5 | 96.0 | 98.5 | **42.9** | 62.8 |
|
|
193
|
+
| TabDiff + NoAug | 72.2 | 64.4 | 69.2 | 16.4 | 53.5 |
|
|
194
|
+
| TabDiff + MeanMask | 97.2 | 94.7 | 97.9 | 38.6 | 59.9 |
|
|
195
|
+
| TabDiff + AugFull (ours) | 97.7 | 95.8 | 95.8 | 40.5 | 64.1 |
|
|
196
|
+
| TabDiff + AugMask (ours) | **98.8** | **96.3** | **98.9** | 40.8 | **67.9** |
|
|
197
|
+
| ForestDiff | 91.9 | 90.6 | 93.1 | 35.1 | 62.4 |
|
|
198
|
+
| MIWAE | 97.8 | 87.1 | 97.2 | 39.2 | 58.3 |
|
|
199
|
+
|
|
200
|
+
**Beijing, 90% missing**
|
|
201
|
+
|
|
202
|
+
| Method | Shape ↑ | Trend ↑ | α-Precision ↑ | β-Recall ↑ | Utility ↑ |
|
|
203
|
+
|---|---:|---:|---:|---:|---:|
|
|
204
|
+
| TabDDPM + NoAug | 50.4 | 36.6 | 47.7 | 1.6 | 46.1 |
|
|
205
|
+
| TabDDPM + MeanMask | 94.9 | 86.6 | 91.7 | 33.3 | 49.1 |
|
|
206
|
+
| TabDDPM + AugFull (ours) | 93.6 | 88.6 | 83.8 | 38.1 | 50.9 |
|
|
207
|
+
| TabDDPM + AugMask (ours) | 89.6 | 83.4 | 82.7 | 30.1 | 53.9 |
|
|
208
|
+
| CDTD + NoAug | 49.5 | 33.7 | 43.8 | 1.0 | 42.0 |
|
|
209
|
+
| CDTD + MeanMask | 90.5 | 78.1 | 92.3 | 9.0 | 45.4 |
|
|
210
|
+
| CDTD + AugFull (ours) | 93.7 | 90.4 | 83.6 | **38.8** | 52.2 |
|
|
211
|
+
| CDTD + AugMask (ours) | 95.6 | 89.6 | 97.0 | 31.6 | 52.1 |
|
|
212
|
+
| TabDiff + NoAug | 48.6 | 33.7 | 44.9 | 1.8 | 44.3 |
|
|
213
|
+
| TabDiff + MeanMask | 97.4 | 79.8 | 95.2 | 32.3 | 44.3 |
|
|
214
|
+
| TabDiff + AugFull (ours) | 93.8 | 90.8 | 83.7 | 38.2 | 51.2 |
|
|
215
|
+
| TabDiff + AugMask (ours) | 97.0 | **92.6** | **98.0** | 37.3 | **55.6** |
|
|
216
|
+
| ForestDiff | 59.7 | 58.1 | 72.4 | 19.6 | 33.7 |
|
|
217
|
+
| MIWAE | **97.5** | 69.5 | 96.2 | 32.3 | 43.9 |
|
|
218
|
+
|
|
219
|
+
</details>
|
|
220
|
+
|
|
221
|
+
## 🔧 Pipeline
|
|
222
|
+
|
|
223
|
+
1. **Collect** the six UCI tables (Adult, Default, Shoppers, Magic, Beijing, News).
|
|
224
|
+
2. **Split** each table 60/20/20 into train, validation and test.
|
|
225
|
+
3. **Mask** train and validation entries (the target included) completely at random (MCAR) or depending on the other columns (MAR); the test split stays complete.
|
|
226
|
+
4. **Encode**, using the observed train entries: numerical columns are quantile-normal transformed, categorical columns are integer encoded.
|
|
227
|
+
5. **Fill** the missing entries with the train mean / mode, or *sample* them with the augmenter (LGBM-S by default; 5 fills, alternated during training).
|
|
228
|
+
6. **Standardize** the numerical columns.
|
|
229
|
+
7. **Train** the backbone and sample as many rows as the train split.
|
|
230
|
+
8. **Map** the samples back to the original columns and values.
|
|
231
|
+
9. **Evaluate** against the complete train and test splits: Shape, Trend, α-Precision, β-Recall and Utility (downstream task performance), following [TabSyn](https://proceedings.iclr.cc/paper_files/paper/2024/hash/e9750610639c3e7a849cff746bf60dbd-Abstract-Conference.html) (ICLR 2024).
|
|
232
|
+
|
|
233
|
+
<details>
|
|
234
|
+
<summary>Repository structure</summary>
|
|
235
|
+
|
|
236
|
+
```
|
|
237
|
+
augmask/
|
|
238
|
+
├── augment.py # step 5: LGBM-S (Algorithm 1), mean/mode fill, the Augmenter interface
|
|
239
|
+
├── run.py # one method on one scenario: build, train, sample, evaluate
|
|
240
|
+
├── evaluate.py # step 9: Shape, Trend, α-Precision, β-Recall, Utility
|
|
241
|
+
├── data/
|
|
242
|
+
│ ├── datasets.py # step 1: download and clean the six UCI tables
|
|
243
|
+
│ ├── split.py # step 2: fixed stratified 60/20/20 split
|
|
244
|
+
│ ├── missingness.py # step 3: MCAR and MAR masks
|
|
245
|
+
│ ├── transforms.py # steps 4 and 6: quantile-normal, integer codes, standardization
|
|
246
|
+
│ ├── scenario.py # steps 3-6 and 8 for one scenario; saves and loads masks and fills
|
|
247
|
+
│ └── schema.py # column types, target and task
|
|
248
|
+
├── models/ # step 7
|
|
249
|
+
│ ├── tabddpm.py, cdtd.py, tabdiff.py # the backbones, each with an optional loss mask
|
|
250
|
+
│ └── common.py # seeding, batching (one fill per step), EMA
|
|
251
|
+
└── baselines/
|
|
252
|
+
├── forestdiff.py # the official ForestDiffusion package, wrapped
|
|
253
|
+
└── miwae.py
|
|
254
|
+
scripts/
|
|
255
|
+
├── run_all.sh # all experiments, then the summary tables
|
|
256
|
+
├── make_tables.py # rank tables with Wilcoxon markers
|
|
257
|
+
└── plot_overview.py # the figure above
|
|
258
|
+
tests/ # pipeline, missingness, baselines, evaluation, each backbone, the runner
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
</details>
|
|
262
|
+
|
|
263
|
+
## 📝 Notes on this release
|
|
264
|
+
|
|
265
|
+
The data pipeline was rebuilt for this release (60/20/20 split, a new MAR generator), so numbers differ slightly from the paper. Most model and training settings follow Appendix C.6 of the paper. The exception is alternating fills: AugFull and AugMask alternate between 5 fills of the missing inputs during training, which performs better at high missing rates in this implementation (`--fills 1` restores the paper's single fill). LGBM-S follows Algorithm 1; `LGBMSAugmenter(log_var_offset=augmask.augment.LOG_CHI2_BIAS)` optionally corrects the downward bias of its variance model.
|
|
266
|
+
|
|
267
|
+
LGBM-S is a per-coordinate augmenter: it samples each missing entry independently given the observed values and the mask, so it does not model the dependence between entries that are missing together. An augmenter that samples the missing coordinates jointly is a natural direction for future work, and can be plugged in as described in [Your own augmenter](#your-own-augmenter).
|
|
268
|
+
|
|
269
|
+
## 📚 Citation
|
|
270
|
+
|
|
271
|
+
```bibtex
|
|
272
|
+
@inproceedings{kim2026augmask,
|
|
273
|
+
title = {{AugMask}: Training Diffusion Models on Incomplete Tabular Data via Stochastic Augmentation and Masking},
|
|
274
|
+
author = {Kim, Jungkyu and Park, Taeyoung and Lee, Kibok},
|
|
275
|
+
booktitle = {Proceedings of the 43rd International Conference on Machine Learning},
|
|
276
|
+
series = {Proceedings of Machine Learning Research},
|
|
277
|
+
volume = {306},
|
|
278
|
+
year = {2026}
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## 🙏 Acknowledgements
|
|
283
|
+
|
|
284
|
+
The backbones are adapted from [TabDDPM](https://github.com/yandex-research/tab-ddpm), [CDTD](https://github.com/muellermarkus/cdtd) and [TabDiff](https://github.com/MinkaiXu/TabDiff) (MIT). The metrics follow [TabSyn](https://github.com/amazon-science/tabsyn) (Apache-2.0), α-Precision/β-Recall follow [synthcity](https://github.com/vanderschaarlab/synthcity), and MIWAE follows [hyperimpute](https://github.com/vanderschaarlab/hyperimpute) (MIT). ForestDiff uses the official [ForestDiffusion](https://github.com/SamsungSAILMontreal/ForestDiffusion) package.
|
|
285
|
+
|
|
286
|
+
Released under the MIT License.
|