Skip to content

Commit 4c40692

Browse files
committed
Merge branch 'develop' into main
2 parents a4f459a + c9ad457 commit 4c40692

File tree

23 files changed

+1777
-67
lines changed

23 files changed

+1777
-67
lines changed

README.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ For complete Documentation with tutorials visit []
6969
* [TabNet: Attentive Interpretable Tabular Learning](https://arxiv.org/abs/1908.07442) is another model coming out of Google Research which uses Sparse Attention in multiple steps of decision making to model the output.
7070
* [Mixture Density Networks](https://publications.aston.ac.uk/id/eprint/373/1/NCRG_94_004.pdf) is a regression model which uses gaussian components to approximate the target function and provide a probabilistic prediction out of the box.
7171
* [AutoInt: Automatic Feature Interaction Learning via Self-Attentive Neural Networks](https://arxiv.org/abs/1810.11921) is a model which tries to learn interactions between the features in an automated way and create a better representation and then use this representation in downstream task
72+
* [TabTransformer](https://arxiv.org/abs/2012.06678) is an adaptation of the Transformer model for Tabular Data which creates contextual representations for categorical features.
7273

7374
To implement new models, see the [How to implement new models tutorial](https://github.com/manujosephv/pytorch_tabular/blob/main/docs/04-Implementing%20New%20Architectures.ipynb). It covers basic as well as advanced architectures.
7475

@@ -112,9 +113,9 @@ loaded_model = TabularModel.load_from_checkpoint("examples/basic")
112113
```
113114
## Blogs
114115

115-
[PyTorch Tabular – A Framework for Deep Learning for Tabular Data](https://deep-and-shallow.com/2021/01/27/pytorch-tabular-a-framework-for-deep-learning-for-tabular-data/)
116-
[Neural Oblivious Decision Ensembles(NODE) – A State-of-the-Art Deep Learning Algorithm for Tabular Data](https://deep-and-shallow.com/2021/02/25/neural-oblivious-decision-ensemblesnode-a-state-of-the-art-deep-learning-algorithm-for-tabular-data/)
117-
[Mixture Density Networks: Probabilistic Regression for Uncertainty Estimation](https://deep-and-shallow.com/2021/03/20/mixture-density-networks-probabilistic-regression-for-uncertainty-estimation/)
116+
- [PyTorch Tabular – A Framework for Deep Learning for Tabular Data](https://deep-and-shallow.com/2021/01/27/pytorch-tabular-a-framework-for-deep-learning-for-tabular-data/)
117+
- [Neural Oblivious Decision Ensembles(NODE) – A State-of-the-Art Deep Learning Algorithm for Tabular Data](https://deep-and-shallow.com/2021/02/25/neural-oblivious-decision-ensemblesnode-a-state-of-the-art-deep-learning-algorithm-for-tabular-data/)
118+
- [Mixture Density Networks: Probabilistic Regression for Uncertainty Estimation](https://deep-and-shallow.com/2021/03/20/mixture-density-networks-probabilistic-regression-for-uncertainty-estimation/)
118119

119120
## Future Roadmap(Contributions are Welcome)
120121

@@ -124,8 +125,15 @@ loaded_model = TabularModel.load_from_checkpoint("examples/basic")
124125
4. Add Fourier Encoding for cyclic time variables
125126
5. Integrate Optuna Hyperparameter Tuning
126127
6. Add Text and Image Modalities for mixed modal problems
127-
7. Integrate Wide and Deep model
128-
8. Integrate TabTransformer
128+
7. Add Variable Importance
129+
8. Integrate SHAP for interpretability
130+
131+
**DL Models**
132+
133+
9. [DNF-Net: A Neural Architecture for Tabular Data](https://www.semanticscholar.org/paper/DNF-Net%3A-A-Neural-Architecture-for-Tabular-Data-Abutbul-Elidan/99c49f3a917815eed2144bfb5d064623ff09ade5)
134+
10. [Attention augmented differentiable forest for tabular data](https://www.semanticscholar.org/paper/Attention-augmented-differentiable-forest-for-data-Chen/57990b40affc5f34f4029dab39bc78e44e7d3b10)
135+
11. [XBNet : An Extremely Boosted Neural Network](https://arxiv.org/abs/2106.05239v2)
136+
12. [Revisiting Deep Learning Models for Tabular Data](https://arxiv.org/abs/2106.11959)
129137
## Citation
130138
If you use PyTorch Tabular for a scientific publication, we would appreciate citations to the published software and the following paper:
131139

examples/to_test_classification.py

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from pytorch_tabular.models.tab_transformer.config import TabTransformerConfig
2+
from pytorch_tabular.models.ft_transformer.config import FTTransformerConfig
13
import torch
24
import numpy as np
35
from torch.functional import norm
@@ -88,7 +90,7 @@
8890
continuous_feature_transform=None,#"quantile_normal",
8991
normalize_continuous_features=False,
9092
)
91-
model_config = CategoryEmbeddingModelConfig(task="classification", metrics=["f1","accuracy"], metrics_params=[{"num_classes":num_classes},{}])
93+
# model_config = CategoryEmbeddingModelConfig(task="classification", metrics=["f1","accuracy"], metrics_params=[{"num_classes":num_classes},{}])
9294
# model_config = NodeConfig(
9395
# task="classification",
9496
# depth=4,
@@ -97,7 +99,25 @@
9799
# metrics=["f1", "accuracy"],
98100
# metrics_params=[{"num_classes": num_classes, "average": "macro"}, {}],
99101
# )
100-
trainer_config = TrainerConfig(gpus=-1, auto_select_gpus=True, fast_dev_run=False, max_epochs=5, batch_size=1024)
102+
model_config = TabTransformerConfig(
103+
task="classification",
104+
metrics=["f1", "accuracy"],
105+
share_embedding = True,
106+
share_embedding_strategy="add",
107+
shared_embedding_fraction=0.25,
108+
metrics_params=[{"num_classes": num_classes, "average": "macro"}, {}],
109+
)
110+
# model_config = FTTransformerConfig(
111+
# task="classification",
112+
# metrics=["f1", "accuracy"],
113+
# # embedding_initialization=None,
114+
# embedding_bias=True,
115+
# share_embedding = True,
116+
# share_embedding_strategy="fraction",
117+
# shared_embedding_fraction=0.25,
118+
# metrics_params=[{"num_classes": num_classes, "average": "macro"}, {}],
119+
# )
120+
trainer_config = TrainerConfig(gpus=-1, auto_select_gpus=True, fast_dev_run=True, max_epochs=5, batch_size=512)
101121
experiment_config = ExperimentConfig(project_name="PyTorch Tabular Example",
102122
run_name="node_forest_cov",
103123
exp_watch="gradients",
@@ -127,11 +147,18 @@
127147
# loss=cust_loss,
128148
train_sampler=sampler)
129149

130-
result = tabular_model.evaluate(test)
131-
print(result)
132-
# test.drop(columns=target_name, inplace=True)
150+
from pytorch_tabular.categorical_encoders import CategoricalEmbeddingTransformer
151+
transformer = CategoricalEmbeddingTransformer(tabular_model)
152+
train_transform = transformer.fit_transform(train)
153+
# test_transform = transformer.transform(test)
154+
# ft = tabular_model.model.feature_importance()
155+
# result = tabular_model.evaluate(test)
156+
# print(result)
157+
# test.drop(columns=ta6rget_name, inplace=True)
133158
# pred_df = tabular_model.predict(test)
159+
# print(pred_df.head())
134160
# pred_df.to_csv("output/temp2.csv")
135161
# tabular_model.save_model("test_save")
136162
# new_model = TabularModel.load_from_checkpoint("test_save")
137-
# result = new_model.evaluate(test)
163+
# result = new_model.evaluate(test)
164+
# print(result)

pytorch_tabular/config/config.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -479,22 +479,22 @@ def read_from_yaml(filename: str = "config/optimizer_config.yml"):
479479
class ExperimentRunManager:
480480
def __init__(
481481
self,
482-
exp_version_manager: str = ".tmp/exp_version_manager.yml",
482+
exp_version_manager: str = ".pt_tmp/exp_version_manager.yml",
483483
) -> None:
484484
"""The manages the versions of the experiments based on the name. It is a simple dictionary(yaml) based lookup.
485485
Primary purpose is to avoid overwriting of saved models while runing the training without changing the experiment name.
486486
487487
Args:
488488
exp_version_manager (str, optional): The path of the yml file which acts as version control.
489-
Defaults to ".tmp/exp_version_manager.yml".
489+
Defaults to ".pt_tmp/exp_version_manager.yml".
490490
"""
491491
super().__init__()
492492
self._exp_version_manager = exp_version_manager
493493
if os.path.exists(exp_version_manager):
494494
self.exp_version_manager = OmegaConf.load(exp_version_manager)
495495
else:
496496
self.exp_version_manager = OmegaConf.create({})
497-
os.makedirs(".tmp", exist_ok=True)
497+
os.makedirs(".pt_tmp", exist_ok=True)
498498
with open(self._exp_version_manager, "w") as file:
499499
OmegaConf.save(config=self.exp_version_manager, f=file)
500500

pytorch_tabular/models/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
AutoIntMDNConfig
1313
)
1414
from .autoint import AutoIntConfig, AutoIntModel
15+
from .tab_transformer import TabTransformerConfig, TabTransformerModel
16+
from .ft_transformer import FTTransformerConfig, FTTransformerModel
1517
from .base_model import BaseModel
1618
from . import category_embedding, node, mixture_density, tabnet, autoint
1719

@@ -33,9 +35,14 @@
3335
"AutoIntMDNConfig",
3436
"AutoIntConfig",
3537
"AutoIntModel",
38+
"TabTransformerConfig",
39+
"TabTransformerModel",
40+
"FTTransformerConfig",
41+
"FTTransformerModel",
3642
"category_embedding",
3743
"node",
3844
"mixture_density",
3945
"tabnet",
4046
"autoint",
47+
"tab_transformer"
4148
]

pytorch_tabular/models/autoint/autoint.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,24 +46,24 @@ def _build_network(self):
4646
# Deep Layers
4747
_curr_units = self.hparams.embedding_dim
4848
if self.hparams.deep_layers:
49-
activation = getattr(nn, self.hparams.activation)
5049
# Linear Layers
5150
layers = []
5251
for units in self.hparams.layers.split("-"):
5352
layers.extend(
5453
_linear_dropout_bn(
55-
self.hparams,
54+
self.hparams.activation,
55+
self.hparams.initialization,
56+
self.hparams.use_batch_norm,
5657
_curr_units,
5758
int(units),
58-
activation,
5959
self.hparams.dropout,
6060
)
6161
)
6262
_curr_units = int(units)
6363
self.linear_layers = nn.Sequential(*layers)
6464
# Projection to Multi-Headed Attention Dims
6565
self.attn_proj = nn.Linear(_curr_units, self.hparams.attn_embed_dim)
66-
_initialize_layers(self.hparams, self.attn_proj)
66+
_initialize_layers(self.hparams.activation, self.hparams.initialization, self.attn_proj)
6767
# Multi-Headed Attention Layers
6868
self.self_attns = nn.ModuleList(
6969
[
@@ -152,7 +152,7 @@ def _build_network(self):
152152
self.output_layer = nn.Linear(
153153
self.backbone.output_dim, self.hparams.output_dim
154154
) # output_dim auto-calculated from other config
155-
_initialize_layers(self.hparams, self.output_layer)
155+
_initialize_layers(self.hparams.activation, self.hparams.initialization, self.output_layer)
156156

157157
def forward(self, x: Dict):
158158
x = self.backbone(x)
@@ -165,3 +165,9 @@ def forward(self, x: Dict):
165165
y_min, y_max = self.hparams.target_range[i]
166166
y_hat[:, i] = y_min + nn.Sigmoid()(y_hat[:, i]) * (y_max - y_min)
167167
return {"logits": y_hat, "backbone_features": x}
168+
169+
def extract_embedding(self):
170+
if len(self.hparams.categorical_cols) > 0:
171+
return self.backbone.cat_embedding_layers
172+
else:
173+
raise ValueError("Model has been trained with no categorical feature and therefore can't be used as a Categorical Encoder")

pytorch_tabular/models/base_model.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ def calculate_metrics(self, y, y_hat, tag):
121121
for metric, metric_str, metric_params in zip(
122122
self.metrics, self.hparams.metrics, self.hparams.metrics_params
123123
):
124-
if (self.hparams.task == "regression") and (self.hparams.output_dim > 1):
124+
if (self.hparams.task == "regression"):
125125
_metrics = []
126126
for i in range(self.hparams.output_dim):
127127
if (

pytorch_tabular/models/category_embedding/category_embedding_model.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ def __init__(self, config: DictConfig, **kwargs):
2424
self._build_network()
2525

2626
def _build_network(self):
27-
activation = getattr(nn, self.hparams.activation)
2827
# Linear Layers
2928
layers = []
3029
_curr_units = self.embedding_cat_dim + self.hparams.continuous_dim
@@ -33,10 +32,11 @@ def _build_network(self):
3332
for units in self.hparams.layers.split("-"):
3433
layers.extend(
3534
_linear_dropout_bn(
36-
self.hparams,
35+
self.hparams.activation,
36+
self.hparams.initialization,
37+
self.hparams.use_batch_norm,
3738
_curr_units,
3839
int(units),
39-
activation,
4040
self.hparams.dropout,
4141
)
4242
)
@@ -69,7 +69,7 @@ def _build_network(self):
6969
self.output_layer = nn.Linear(
7070
self.backbone.output_dim, self.hparams.output_dim
7171
) # output_dim auto-calculated from other config
72-
_initialize_layers(self.hparams, self.output_layer)
72+
_initialize_layers(self.hparams.activation, self.hparams.initialization, self.output_layer)
7373

7474
def unpack_input(self, x: Dict):
7575
continuous_data, categorical_data = x["continuous"], x["categorical"]

0 commit comments

Comments
 (0)