|
66 | 66 | X = pd.DataFrame(X, columns=[f"feature_{i}" for i in range(n_features)]) |
67 | 67 | y = pd.Series(y, name="target") |
68 | 68 |
|
| 69 | +# %% [markdown] |
| 70 | +# |
| 71 | +# Let's recall what the expit function also called the sigmoid function is. |
| 72 | + |
| 73 | +# %% |
| 74 | +_, ax = plt.subplots() |
| 75 | +x = np.linspace(-10, 10, 100) |
| 76 | +ax.plot(x, expit(x)) |
| 77 | +_ = ax.set( |
| 78 | + title="Sigmoid/Expit function", |
| 79 | + xlabel="Linear predictor", |
| 80 | + ylabel="Probability", |
| 81 | +) |
| 82 | + |
| 83 | +# %% [markdown] |
| 84 | +# |
| 85 | +# The expit function allows to transform the linear predictor into probabilities between |
| 86 | +# 0 and 1. The role of the intercept is to shift the sigmoid function to the left or |
| 87 | +# right. |
| 88 | + |
69 | 89 | # %% [markdown] |
70 | 90 | # |
71 | 91 | # Let's look at the true target and especially the relative class frequencies and |
|
135 | 155 | # |
136 | 156 | # Write a small function that embeds the generative process that we defined above. This |
137 | 157 | # time only generate 10,000 samples, train a logistic regression model and check the |
138 | | -# learned model coefficients. |
| 158 | +# learned model coefficients. Make sure to pass the same true coefficients than in |
| 159 | +# the previous exercise. |
139 | 160 | # |
140 | 161 | # Do you recover the true model coefficients? If not, what is the reason? |
141 | 162 |
|
|
151 | 172 |
|
152 | 173 |
|
153 | 174 | # %% |
154 | | -def generate_imbalanced_dataset(n_samples=10_000, n_features=5, seed=0): |
| 175 | +def generate_imbalanced_dataset(true_coef, n_samples=10_000, seed=0): |
155 | 176 | rng = np.random.default_rng(seed) |
156 | 177 |
|
157 | | - true_coef = rng.normal(size=n_features) |
158 | | - X = rng.normal(size=(n_samples, n_features)) |
| 178 | + # we can sample a new design matrix but we need to keep the same true coefficients |
| 179 | + X = rng.normal(size=(n_samples, true_coef.shape[0])) |
159 | 180 | z = X @ true_coef |
160 | 181 | intercept = -4 |
161 | 182 | y = rng.binomial(n=1, p=expit(z + intercept)) |
162 | 183 |
|
163 | 184 | # create pandas data structures for convenience |
164 | | - X = pd.DataFrame(X, columns=[f"feature_{i}" for i in range(n_features)]) |
| 185 | + X = pd.DataFrame(X, columns=[f"feature_{i}" for i in range(X.shape[1])]) |
165 | 186 | y = pd.Series(y, name="target") |
166 | 187 |
|
167 | 188 | return X, y |
168 | 189 |
|
169 | 190 |
|
170 | | -X_exercise, y_exercise = generate_imbalanced_dataset(n_samples=10_000) |
| 191 | +X_exercise, y_exercise = generate_imbalanced_dataset(true_coef, n_samples=10_000) |
171 | 192 | model_exercise = LogisticRegression(penalty=None).fit(X_exercise, y_exercise) |
172 | 193 |
|
173 | 194 | comparison_coef_exercise = pd.DataFrame( |
@@ -448,7 +469,7 @@ def generate_imbalanced_dataset(n_samples=10_000, n_features=5, seed=0): |
448 | 469 | ) |
449 | 470 | ), |
450 | 471 | }, |
451 | | - index=np.hstack(["intercept", model.feature_names_in_]), |
| 472 | + index=np.hstack(["intercept", undersampling_model[-1].feature_names_in_]), |
452 | 473 | ) |
453 | 474 | ax = comparison_coef.plot.barh() |
454 | 475 | _ = ax.set( |
|
0 commit comments