ctdGAN 0.3.1__py3-none-any.whl
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.
- ctdGAN/Tools.py +175 -0
- ctdGAN/__init__.py +3 -0
- ctdGAN/ctdgan.py +756 -0
- ctdGAN/ctdgan_cluster.py +165 -0
- ctdGAN/ctdgan_clusterer.py +527 -0
- ctdGAN/ctdgan_datasampler.py +175 -0
- ctdGAN/ctdgan_datatransformer.py +384 -0
- ctdGAN/ctdgan_networks.py +246 -0
- ctdGAN/main.py +34 -0
- ctdgan-0.3.1.dist-info/METADATA +23 -0
- ctdgan-0.3.1.dist-info/RECORD +14 -0
- ctdgan-0.3.1.dist-info/WHEEL +5 -0
- ctdgan-0.3.1.dist-info/licenses/LICENSE +13 -0
- ctdgan-0.3.1.dist-info/top_level.txt +1 -0
ctdGAN/Tools.py
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import random
|
|
2
|
+
import numpy as np
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from scipy.stats import chi2_contingency
|
|
5
|
+
import torch
|
|
6
|
+
|
|
7
|
+
import gc
|
|
8
|
+
import contextlib
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def set_random_states(manual_seed):
|
|
12
|
+
"""Initializes the random number generators of NumPy, PyTorch, and PyTorch CUDA by passing the input seed.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
manual_seed: An integer to be passed to the random number generators.
|
|
16
|
+
"""
|
|
17
|
+
np.random.seed(manual_seed)
|
|
18
|
+
|
|
19
|
+
if manual_seed is None:
|
|
20
|
+
torch.manual_seed(0)
|
|
21
|
+
torch.cuda.manual_seed(0)
|
|
22
|
+
else:
|
|
23
|
+
torch.manual_seed(manual_seed)
|
|
24
|
+
torch.cuda.manual_seed(manual_seed)
|
|
25
|
+
|
|
26
|
+
torch.backends.cudnn.deterministic = True
|
|
27
|
+
torch.backends.cudnn.benchmark = False
|
|
28
|
+
|
|
29
|
+
def get_random_states():
|
|
30
|
+
"""Retrieves the current states of randomness of NumPy, PyTorch, and PyTorch CUDA.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
Three states of randomness for NumPy, PyTorch, and PyTorch CUDA respectively.
|
|
34
|
+
"""
|
|
35
|
+
np_random_state = np.random.get_state()
|
|
36
|
+
torch_random_state = torch.random.get_rng_state()
|
|
37
|
+
if torch.cuda.is_available():
|
|
38
|
+
cuda_random_state = torch.cuda.random.get_rng_state()
|
|
39
|
+
else:
|
|
40
|
+
cuda_random_state = None
|
|
41
|
+
|
|
42
|
+
return np_random_state, torch_random_state, cuda_random_state
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def reset_random_states(np_random_state, torch_random_state, cuda_random_state):
|
|
46
|
+
"""Sets the current states of randomness of NumPy, PyTorch, and PyTorch CUDA.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
np_random_state: The state at which the NumPy random generator will be set.
|
|
50
|
+
torch_random_state: The state at which the PyTorch random generator will be set.
|
|
51
|
+
cuda_random_state: The state at which the PyTorch CUDA random generator will be set.
|
|
52
|
+
"""
|
|
53
|
+
np.random.set_state(np_random_state)
|
|
54
|
+
torch.random.set_rng_state(torch_random_state)
|
|
55
|
+
|
|
56
|
+
if torch.cuda.is_available():
|
|
57
|
+
torch.cuda.random.set_rng_state(cuda_random_state)
|
|
58
|
+
torch.cuda.empty_cache()
|
|
59
|
+
|
|
60
|
+
gc.collect()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def relabel_clusters(labels):
|
|
64
|
+
"""
|
|
65
|
+
Relabel cluster IDs so they become consecutive integers starting from 0.
|
|
66
|
+
|
|
67
|
+
Example:
|
|
68
|
+
[0,0,0,0,2,2,2] -> [0,0,0,0,1,1,1]
|
|
69
|
+
"""
|
|
70
|
+
mapping = {}
|
|
71
|
+
new_labels = []
|
|
72
|
+
next_label = 0
|
|
73
|
+
|
|
74
|
+
for label in labels:
|
|
75
|
+
if label not in mapping:
|
|
76
|
+
mapping[label] = next_label
|
|
77
|
+
next_label += 1
|
|
78
|
+
new_labels.append(mapping[label])
|
|
79
|
+
|
|
80
|
+
return new_labels
|
|
81
|
+
|
|
82
|
+
@contextlib.contextmanager
|
|
83
|
+
def ct_set_random_states(seed, set_model_random_state):
|
|
84
|
+
"""Context manager for managing the random state.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
seed (int or tuple):
|
|
88
|
+
The random seed or a tuple of (numpy.random.RandomState, torch.Generator).
|
|
89
|
+
set_model_random_state (function):
|
|
90
|
+
Function to set the random state on the model.
|
|
91
|
+
"""
|
|
92
|
+
original_np_state = np.random.get_state()
|
|
93
|
+
original_torch_state = torch.get_rng_state()
|
|
94
|
+
|
|
95
|
+
random_np_state, random_torch_state = seed
|
|
96
|
+
|
|
97
|
+
np.random.set_state(random_np_state.get_state())
|
|
98
|
+
torch.set_rng_state(random_torch_state.get_state())
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
yield
|
|
102
|
+
finally:
|
|
103
|
+
current_np_state = np.random.RandomState()
|
|
104
|
+
current_np_state.set_state(np.random.get_state())
|
|
105
|
+
current_torch_state = torch.Generator()
|
|
106
|
+
current_torch_state.set_state(torch.get_rng_state())
|
|
107
|
+
set_model_random_state((current_np_state, current_torch_state))
|
|
108
|
+
|
|
109
|
+
np.random.set_state(original_np_state)
|
|
110
|
+
torch.set_rng_state(original_torch_state)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def random_state(function):
|
|
114
|
+
"""Set the random state before calling the function.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
function (Callable): The function to wrap around.
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
def wrapper(self, *args, **kwargs):
|
|
121
|
+
if self.random_states is None:
|
|
122
|
+
return function(self, *args, **kwargs)
|
|
123
|
+
|
|
124
|
+
else:
|
|
125
|
+
with ct_set_random_states(self.random_states, self.set_random_state):
|
|
126
|
+
return function(self, *args, **kwargs)
|
|
127
|
+
|
|
128
|
+
return wrapper
|
|
129
|
+
|
|
130
|
+
def cramers_v(x, y):
|
|
131
|
+
confusion_matrix = pd.crosstab(x, y)
|
|
132
|
+
chi2 = chi2_contingency(confusion_matrix)[0]
|
|
133
|
+
n = confusion_matrix.sum().sum()
|
|
134
|
+
r, k = confusion_matrix.shape
|
|
135
|
+
return np.sqrt(chi2 / (n * (min(k - 1, r - 1) + 1e-8)))
|
|
136
|
+
|
|
137
|
+
def correlation_ratio(categories, measurements):
|
|
138
|
+
categories = pd.Categorical(categories)
|
|
139
|
+
groups = [measurements[categories == cat] for cat in categories.categories]
|
|
140
|
+
|
|
141
|
+
grand_mean = np.mean(measurements)
|
|
142
|
+
|
|
143
|
+
ss_between = sum(len(g) * (np.mean(g) - grand_mean) ** 2 for g in groups)
|
|
144
|
+
ss_total = sum((measurements - grand_mean)**2)
|
|
145
|
+
|
|
146
|
+
return np.sqrt(ss_between / (ss_total + 1e-8))
|
|
147
|
+
|
|
148
|
+
def compute_mixed_matrix(df, cat_cols):
|
|
149
|
+
cols = df.columns
|
|
150
|
+
mat = pd.DataFrame(np.zeros((len(cols), len(cols))), index=cols, columns=cols)
|
|
151
|
+
|
|
152
|
+
num_cols = [c for c in cols if c not in cat_cols]
|
|
153
|
+
|
|
154
|
+
for i, col1 in enumerate(cols):
|
|
155
|
+
for j, col2 in enumerate(cols):
|
|
156
|
+
|
|
157
|
+
if col1 == col2:
|
|
158
|
+
mat.loc[col1, col2] = 1.0
|
|
159
|
+
|
|
160
|
+
elif col1 in num_cols and col2 in num_cols:
|
|
161
|
+
mat.loc[col1, col2] = df[col1].corr(df[col2])
|
|
162
|
+
|
|
163
|
+
elif col1 in cat_cols and col2 in cat_cols:
|
|
164
|
+
mat.loc[col1, col2] = cramers_v(df[col1], df[col2])
|
|
165
|
+
|
|
166
|
+
else:
|
|
167
|
+
# numeric-categorical
|
|
168
|
+
if col1 in cat_cols:
|
|
169
|
+
cat, num = col1, col2
|
|
170
|
+
else:
|
|
171
|
+
cat, num = col2, col1
|
|
172
|
+
|
|
173
|
+
mat.loc[col1, col2] = correlation_ratio(df[cat], df[num])
|
|
174
|
+
|
|
175
|
+
return mat
|
ctdGAN/__init__.py
ADDED