Extrudability classifier (AutoGluon, tabular)
Binary classifier that predicts whether a desk-scale object can be manufactured by a straight extrusion of its top-down silhouette, from hand-measured geometry. Built for Homework 2 (AutoML) of Designing with AI by YOUR NAME.
Purpose
Given the measured bounding dimensions, wall thickness, hole and edge counts, silhouette family, and material of
a part, predict extrudable (1) versus not_extrudable (0). The intended use is coursework and prototyping:
a fast feasibility check in front of a sketch-to-STL pipeline. It is not suitable for engineering,
manufacturing, tolerance, or safety decisions.
Data origin and splits
- Dataset:
sunkaiwen/sketch2stl-parts-tabular, by Serena Sun, CC-BY-4.0. Not my own dataset and not my Project 1 partner's. - 34 hand-measured desk-scale objects, split 70/15/15 over objects, stratified on the target, before augmentation; 400 label-preserving synthetic rows were then derived from the 23 training objects only.
- Splits were used exactly as shipped: train 423 rows (23 measured objects + synthetic descendants), validation 5 objects, test 6 objects. No re-splitting, because re-splitting would scatter jittered copies of held-out objects into training.
- Verified in the notebook: no object appears in two splits, no synthetic row descends from a held-out object, the holdout splits contain measured rows only, and every synthetic row's label matches both of its parents.
Features and target
Target: extrudable (0 = not extrudable, 1 = extrudable). Positive class = 1.
Numeric inputs (10): length_mm, width_mm, height_mm, wall_thickness_mm (all mm);
n_through_holes, n_straight_edges (counts); aspect_ratio, flatness, hole_density (unitless);
footprint_mm2 (mm²).
Categorical inputs (2): silhouette_class, material.
Excluded to prevent leakage:
extrusion_depth_mm— the dataset's other shipped target. Audited in the notebook: it is greater than zero exactly when the label is 1, on 100.0% of rows, making it the label in disguise.object_name— flagged as label-revealing by the dataset card, and inherited by synthetic rows, so it also acts as an object identifier.
Excluded as provenance: object_id, source_object_id, split_source, aug_technique, split. These are
used only for lineage checks and for grouping the cross-validation folds.
Preprocessing
Minimal and deliberate. Measurements keep their physical magnitudes in mm; no scaling, binning, or imputation is
applied (the dataset has no missing values, which is asserted). Categorical levels are fixed across all three
splits so that singleton levels such as wood and ceramic are encoded consistently. AutoGluon applies its own
internal encoding on top of this.
Training setup
- AutoGluon
TabularPredictor,autogluon.tabular==1.6.1,problem_type="binary",positive_class=1,eval_metric="balanced_accuracy". num_bag_folds=0,num_stack_levels=0, with the shipped validation objects passed explicitly astuning_data. This is the key setting: ~95% of training rows are synthetic siblings of 23 parent objects, so AutoGluon's default internal re-splitting would place jittered copies of the same object on both sides of a fold boundary and report an optimistic internal score.- Seed
24679for all splits and shuffles under our control; AutoGluon seeds its own model internals separately and reportsmodel_random_seed = 0.
Search: two passes
Search A — model portfolio. presets="medium_quality", time_limit=300 s. This preset fits a
fixed portfolio of model families (LightGBM variants, XGBoost, CatBoost, random forests, extra trees, k-NN,
neural networks) at their default hyperparameter configurations. It searches over families, not over
hyperparameters, so any "hyperparameters" it reports for a winner are stock values.
Selected: WeightedEnsemble_L2, validation balanced accuracy 0.833. The appended WeightedEnsemble_L2 reduces to LightGBMXT with weight 1.0 — verified by identical predicted probabilities — so it is a passthrough, not a blend. Note also that
AutoGluon fits the weighted ensemble's weights on the validation data and then scores it on that same data, so
its leaderboard score is optimistically biased relative to every base model.
| model | score_val | fit_time |
|---|---|---|
| XGBoost | 0.833 | 3.369 |
| NeuralNetTorch | 0.833 | 3.347 |
| LightGBMXT | 0.833 | 2.314 |
| WeightedEnsemble_L2 | 0.833 | 2.673 |
| LightGBM | 0.75 | 3.466 |
| LightGBMLarge | 0.75 | 2.789 |
| RandomForestEntr | 0.667 | 1.652 |
| RandomForestGini | 0.667 | 1.693 |
| NeuralNetFastAI | 0.5 | 1.439 |
| ExtraTreesEntr | 0.417 | 1.83 |
| ExtraTreesGini | 0.417 | 1.595 |
Search B — hyperparameter optimization. Random search, num_trials=20, time_limit=300 s,
over LightGBM:
| hyperparameter | range |
|---|---|
learning_rate |
Real(0.01, 0.2), log scale |
num_leaves |
Int(4, 32) |
min_data_in_leaf |
Int(2, 20) |
feature_fraction |
Real(0.5, 1.0) |
Ranges are deliberately narrow because 23 genuinely independent objects cannot support a deep tree.
Selected: WeightedEnsemble_L2, validation balanced accuracy 0.833.
| model | score_val | fit_time |
|---|---|---|
| LightGBM/T9 | 0.833 | 0.841 |
| LightGBM/T8 | 0.833 | 0.835 |
| LightGBM/T5 | 0.833 | 0.844 |
| LightGBM/T1 | 0.833 | 1.122 |
| LightGBM/T13 | 0.833 | 1.251 |
| WeightedEnsemble_L2 | 0.833 | 1.128 |
| LightGBM/T15 | 0.75 | 0.818 |
| LightGBM/T16 | 0.75 | 0.879 |
| LightGBM/T14 | 0.75 | 0.961 |
| LightGBM/T20 | 0.75 | 0.881 |
| LightGBM/T7 | 0.75 | 0.9 |
| LightGBM/T3 | 0.75 | 0.843 |
| LightGBM/T19 | 0.75 | 0.837 |
| LightGBM/T6 | 0.75 | 0.806 |
| LightGBM/T4 | 0.75 | 0.911 |
| LightGBM/T2 | 0.75 | 0.851 |
| LightGBM/T17 | 0.75 | 0.914 |
| LightGBM/T18 | 0.75 | 0.815 |
| LightGBM/T10 | 0.75 | 0.863 |
| LightGBM/T12 | 0.75 | 1.088 |
| LightGBM/T11 | 0.75 | 1.037 |
Selected configuration
portfolio, model WeightedEnsemble_L2. Selected on the cross-validation mean below, not the 5-object
validation score, under a rule fixed before the numbers were seen: prefer the tuned search only if it beats the
portfolio's CV mean by more than 0.10; otherwise keep the simpler portfolio configuration.
Hyperparameters of the selected model:
learning_rate:0.05extra_trees:Trueseed:0
Metrics
All metrics are unitless fractions in [0, 1].
Object-level 5-fold cross-validation over the 23 measured training objects. Folds are drawn over objects; all synthetic descendants of a held-out object — including rows whose second parent is held out — are removed from that fold's training data, and each fold is scored on held-out measured objects only. Both configurations were evaluated on identical object groups.
| configuration | ('accuracy', 'mean') | ('accuracy', 'std') | ('balanced accuracy', 'mean') | ('balanced accuracy', 'std') |
|---|---|---|---|---|
| portfolio | 0.83 | 0.172 | 0.75 | 0.25 |
| tuned | 0.74 | 0.082 | 0.717 | 0.126 |
Per fold:
| configuration | fold | held-out objects | balanced accuracy |
|---|---|---|---|
| portfolio | 1 | 5 | 0.5 |
| portfolio | 2 | 5 | 1 |
| portfolio | 3 | 5 | 0.75 |
| portfolio | 4 | 4 | 0.5 |
| portfolio | 5 | 4 | 1 |
| tuned | 1 | 5 | 0.75 |
| tuned | 2 | 5 | 0.75 |
| tuned | 3 | 5 | 0.5 |
| tuned | 4 | 4 | 0.833 |
| tuned | 5 | 4 | 0.75 |
Selected configuration: balanced accuracy 0.750 ± 0.250 (mean ± s.d. across folds), accuracy 0.830. This is the headline figure. Because folds share objects indirectly through the augmentation lineage, read the standard deviation as a stability estimate rather than a textbook standard error. The CV mean also served as the selection criterion between two candidates, which makes it slightly optimistic.
Held-out test set (6 measured objects), used once:
| Accuracy | Balanced accuracy | Precision (extrudable) | Recall (extrudable) | F1 (extrudable) | |
|---|---|---|---|---|---|
| Selected model (portfolio) | 0.667 | 0.667 | 0.6 | 1 | 0.75 |
| Training-majority baseline | 0.5 | 0.5 | 0.5 | 1 | 0.667 |
Test accuracy 66.7% (4/6 objects), 95% Clopper–Pearson interval 22.3% to 95.7%. With 6 objects, one error moves accuracy by about 17 percentage points, so the interval — not the point estimate — is the honest summary.
Limitations and ethical notes
- Tiny, non-random source. 34 objects from one person's desk, over-representing stationery and small hardware. No furniture, textiles, or organic shapes. The model cannot be said to generalize to parts in general.
- Single-annotator label.
extrudableis a documented ±1 mm judgement made by one person with no independent check. A good score means the model recovered that person's rule, not that it learned extrusion physics. - Model selection is not identifiable at this sample size. Several families tie exactly on the 5-object validation set, and the hyperparameter search produced few distinct scores across its trials. Treat the selected model as a reasonable choice, not as the best one.
- Effective training size is ~23 objects, not 423 rows. The synthetic rows are echoes, so a high training score is expected and uninformative.
- Thin categorical coverage.
ceramic,cork,rubber, andsiliconeeach appear about once, so predictions for those materials rest on almost no evidence. - The realistic harm is misplaced confidence. A model that looks accurate on six objects could be confidently wrong about a real user's part, wasting filament at best and producing a part that fails in use at worst. Any downstream use should treat the output as a hint a human checks, never as a gate.
No personal data is involved: the dataset contains measurements of inanimate objects only.
License
CC-BY-4.0, matching the source dataset. Attribution to Serena Sun for the dataset and to YOUR NAME for the model.
Hardware and compute budget
- Hardware: Google Colab CPU runtime (no GPU).
- Search A: 300 s. Search B: 300 s. Cross-validation: 2 configurations × 5 folds × 90 s.
- Total fitting budget: about 1500 s (25 minutes) of wall-clock compute, excluding installs and downloads.
AI usage disclosure
Generative AI (Claude, Anthropic) was used as a coding assistant to adapt the course's AutoML notebook to this dataset, in particular the leakage audit, the weighted-ensemble check, the object-level cross-validation, and the prose of this card. Every cell was executed and checked by me, and the conclusions about model selection are my own reading of the outputs. No data was generated by AI; the dataset is a classmate's hand-measured work, used unchanged.
How to use
import zipfile, huggingface_hub
from autogluon.tabular import TabularPredictor
path = huggingface_hub.hf_hub_download(
repo_id="yennik16/2026-24679-extrudability-autogluon-classifier", filename="autogluon_predictor_dir.zip", repo_type="model"
)
with zipfile.ZipFile(path) as zf:
zf.extractall("predictor_dir")
predictor = TabularPredictor.load("predictor_dir")
predictor.predict(your_dataframe) # columns: length_mm, width_mm, height_mm, wall_thickness_mm, n_through_holes, n_straight_edges, aspect_ratio, flatness, footprint_mm2, hole_density, silhouette_class, material
Reload with the same library versions used above; AutoGluon artifacts are not guaranteed portable across versions.