Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #630 +/- ##
==========================================
+ Coverage 86.86% 87.03% +0.17%
==========================================
Files 41 42 +1
Lines 4409 5061 +652
==========================================
+ Hits 3830 4405 +575
- Misses 579 656 +77
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
pvk-developer
left a comment
There was a problem hiding this comment.
When fitting I also see the steps (they come from TabDDPM), if verbose is set to False do we need to display them?
|
During fit there is a point where |
I lean towards keeping it as faithful to the original implementation as possible. Sometimes |
|
|
||
| LOGGER = logging.getLogger(__name__) | ||
| _MODEL_KWARGS = None | ||
| _MODALITY_FLAG = 'multi_table' |
There was a problem hiding this comment.
You could remove this line since this is already set in the MultiTableBaselineSynthesizer:
SDGym/sdgym/synthesizers/base.py
Line 142 in 410fef0
There was a problem hiding this comment.
This is looking good!
I’m still reviewing the logic and checking that it aligns with their implementation. In the meantime, I’m thinking about two things:
- For the structure, we could either:
- Define a clavaddpm folder where we keep files such as pipeline_modules.py and preprocess_utils.py, along with our SDGym logic.
- Keep everything in one file, but be more explicit about what comes from their implementation versus what we added. It could look something like:
######################### SDGym extra logic #########################
def get_group_data_dict(np_data, group_id_attrs=[0]):
"""Grouping dictionary from pipeline_utils.py."""
group_data_dict = {}
data_len = len(np_data)
for i in range(data_len):
row_id = tuple(np_data[i, group_id_attrs])
if row_id not in group_data_dict:
group_data_dict[row_id] = []
group_data_dict[row_id].append(np_data[i])
return group_data_dict
######################## From preprocess_utils.py ###################
def get_domain(df, id_cols, discrete_cols):
"""Build the ``{col: {'size', 'type'}}`` domain of a table from preprocess_utils.py."""
domain = {}
for col in df.columns:
if col in discrete_cols:
domain[col] = {'size': len(df[col].unique()), 'type': 'discrete'}
elif col not in id_cols:
domain[col] = {'size': len(df[col].unique()), 'type': 'continuous'}
return domain
.
.
.
######################## From pipeline_modules.py ###################
.
.
.
- Would it be possible to have an integration test that runs the SDGym ClavaDDPM implementation against their original implementation and checks that the results are the same or similar? It would be nice to have, although I’m not sure how feasible it is. It might require adding their repo as a test dependency.
|
|
||
|
|
||
| def match_tables(A, B, n_clusters=25, unique_matching=True, batch_size=100): | ||
| """Nearest-neighbour match of every row of ``A`` to a row of ``B``. |
There was a problem hiding this comment.
We could add from pipeline_utils.py
| batch_size=100, | ||
| no_matching=False, | ||
| ): | ||
| """Reconcile a child generated once per parent into a single table.""" |
There was a problem hiding this comment.
Maybe also add from pipeline_utils.py
| meta = metadata if isinstance(metadata, dict) else metadata.to_dict() | ||
|
|
||
| self._table_names = list(meta['tables']) | ||
| self._primary_key = {} |
| self.matching_batch_size = matching_batch_size | ||
| self.unique_matching = unique_matching | ||
| self.no_matching = no_matching | ||
| self.max_categories = max_categories |
There was a problem hiding this comment.
This seems to never be used, should we get rid of it?
| chosen, chosen_distance = int(candidate), float(distance) | ||
| break | ||
| if chosen is None: | ||
| chosen = next(j for j in range(len(B)) if j not in used) |
There was a problem hiding this comment.
Should we also update chosen_distance here?
|
|
||
| Mirrors ``GaussianMultinomialDiffusion._sample`` but takes explicit | ||
| per-row labels instead of drawing them from the empirical distribution. | ||
| Similar to the original classifier-guided ``conditional_sample`` implemtation. |
There was a problem hiding this comment.
| Similar to the original classifier-guided ``conditional_sample`` implemtation. | |
| Similar to the original classifier-guided ``conditional_sample`` implementation. |
| encoder's fitted range get fresh values: numeric ids continue after the | ||
| largest original id, other ids become new ``'{column}_{code}'`` strings. |
There was a problem hiding this comment.
Do we need to handle the numerical case here?
In l875 and l883 we're skipping the encoder for numerical ids
| parent_num_cols.append((col_index, col)) | ||
|
|
||
| parent_primary_key_index = original_parent_cols.index(parent_primary_key) | ||
| foreing_key_index = original_child_cols.index(foreign_key) |
There was a problem hiding this comment.
| foreing_key_index = original_child_cols.index(foreign_key) | |
| foreign_key_index = original_child_cols.index(foreign_key) |
| parent_scale * cat_one_hot[:, joint_cat_matrix_p_index:] | ||
| ) | ||
|
|
||
| # Perform quantile normalization using QuantileTransformer |
There was a problem hiding this comment.
We removed num_quantile because it was not used?
https://github.com/weipang142857/ClavaDDPM/blob/fa6ef4d7c6d2c584b45a398c4471bb51e0bb5e17/pipeline_modules.py#L243
Maybe we should update the comment
| num_clusters = min(num_clusters, len(cluster_data)) | ||
|
|
||
| init_param = 'k-means++' | ||
| if SKLEARN_VERSION.release[:2] < (1, 1): |
There was a problem hiding this comment.
n_init='auto' is also impacted by the sklearn version. It was introduced in scikit-learn 1.2:
https://scikit-learn.org/stable/whats_new/v1.2.html
At some point maybe we could just bump the minimum version for sklearn
original implementation is https://github.com/weipang142857/ClavaDDPM
The important class to review is
ClavaDDPMandClavaDDPMSynthesizeras these are the wrappers I wrote. I've written other code pieces, if it's taken from the source code directly, I mention "from" in the docstrings.