forked from jsyoon0823/INVASE
-
Notifications
You must be signed in to change notification settings - Fork 0
/
data_generation.py
163 lines (127 loc) · 4.41 KB
/
data_generation.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
"""Functions for synthetic data generation
Reference: Jinsung Yoon, James Jordon, Mihaela van der Schaar,
"IINVASE: Instance-wise Variable Selection using Neural Networks,"
International Conference on Learning Representations (ICLR), 2019.
Paper Link: https://openreview.net/forum?id=BJg_roAcK7
Contact: [email protected]
---------------------------------------------------
Generating 6 synthetic datasets
x ~ N(0,I) where d = 11 or 100
y = 1/(1+logit) where logit for each synthetic dataset is
- syn1: logit = exp(x1 * x2)
- syn2: logit = exp(x3^2 + x4^2 + x5^2 + x6^2 -4)
- syn3: logit = -10 sin(2 * x7) + 2|x8| + x9 + exp(-x10) - 2.4
- syn4: If x11 < 0, follows syn1, else if x11 >= 0, follows syn2
- syn5: If x11 < 0, follows syn1, else if x11 >= 0, follows syn3
- syn6: If x11 < 0, follows syn2, else if x11 >= 0, follows syn3
"""
# Necessary packages
import numpy as np
def generate_x (n, dim):
"""Generate the features (x).
Args:
- n: the number of samples
- dim: the number of features (feature dimensions)
Returns:
- x: (n x dim) data points sample from N(0, 1)
"""
x = np.random.randn(n, dim)
return x
def generate_y (x, data_type):
"""Generate corresponding label (y) given feature (x).
Args:
- x: features
- data_type: synthetic data type (syn1 to syn6)
Returns:
- y: corresponding labels
"""
# number of samples
n = x.shape[0]
# Logit computation
if data_type == 'syn1':
logit = np.exp(x[:, 0]*x[:, 1])
elif data_type == 'syn2':
logit = np.exp(np.sum(x[:, 2:6]**2, axis = 1) - 4.0)
elif data_type == 'syn3':
logit = np.exp(-10 * np.sin(0.2*x[:, 6]) + abs(x[:, 7]) + \
x[:, 8] + np.exp(-x[:, 9]) - 2.4)
elif data_type == 'syn4':
logit1 = np.exp(x[:, 0]*x[:, 1])
logit2 = np.exp(np.sum(x[:, 2:6]**2, axis = 1) - 4.0)
elif data_type == 'syn5':
logit1 = np.exp(x[:, 0]*x[:, 1])
logit2 = np.exp(-10 * np.sin(0.2*x[:, 6]) + abs(x[:, 7]) + \
x[:, 8] + np.exp(-x[:, 9]) - 2.4)
elif data_type == 'syn6':
logit1 = np.exp(np.sum(x[:,2:6]**2, axis = 1) - 4.0)
logit2 = np.exp(-10 * np.sin(0.2*x[:, 6]) + abs(x[:, 7]) + \
x[:, 8] + np.exp(-x[:, 9]) - 2.4)
# For syn4, syn5 and syn6 only
if data_type in ['syn4', 'syn5', 'syn6']:
# Based on X[:,10], combine two logits
idx1 = (x[:, 10]< 0)*1
idx2 = (x[:, 10]>=0)*1
logit = logit1 * idx1 + logit2 * idx2
# Compute P(Y=0|X)
prob_0 = np.reshape((logit / (1+logit)), [n, 1])
# Sampling process
y = np.zeros([n, 2])
y[:, 0] = np.reshape(np.random.binomial(1, prob_0), [n,])
y[:, 1] = 1-y[:, 0]
return y
def generate_ground_truth(x, data_type):
"""Generate ground truth feature importance corresponding to the data type
and feature.
Args:
- x: features
- data_type: synthetic data type (syn1 to syn6)
Returns:
- ground_truth: corresponding ground truth feature importance
"""
# Number of samples and features
n, d = x.shape
# Output initialization
ground_truth = np.zeros([n, d])
# For each data_type
if data_type == 'syn1':
ground_truth[:, :2] = 1
elif data_type == 'syn2':
ground_truth[:, 2:6] = 1
elif data_type == 'syn3':
ground_truth[:, 6:10] = 1
# Index for syn4, syn5 and syn6
if data_type in ['syn4', 'syn5', 'syn6']:
idx1 = np.where(x[:, 10]<0)[0]
idx2 = np.where(x[:, 10]>=0)[0]
ground_truth[:, 10] = 1
if data_type == 'syn4':
ground_truth[idx1, :2] = 1
ground_truth[idx2, 2:6] = 1
elif data_type == 'syn5':
ground_truth[idx1, :2] = 1
ground_truth[idx2, 6:10] = 1
elif data_type == 'syn6':
ground_truth[idx1, 2:6] = 1
ground_truth[idx2, 6:10] = 1
return ground_truth
def generate_dataset(n = 10000, dim = 11, data_type = 'syn1', seed = 0):
"""Generate dataset (x, y, ground_truth).
Args:
- n: the number of samples
- dim: the number of dimensions
- data_type: synthetic data type (syn1 to syn6)
- seed: random seed
Returns:
- x: features
- y: labels
- ground_truth: ground truth feature importance
"""
# Seed
np.random.seed(seed)
# x generation
x = generate_x(n, dim)
# y generation
y = generate_y(x, data_type)
# ground truth generation
ground_truth = generate_ground_truth(x, data_type)
return x, y, ground_truth