Skip to content

Commit 0bf74cb

Browse files
Merge pull request #9 from antoinedemathelin/master
fix: coral, kliep, GradientHandler
2 parents 5dd2483 + 66c055c commit 0bf74cb

File tree

8 files changed

+91
-10
lines changed

8 files changed

+91
-10
lines changed

adapt/feature_based/_coral.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,17 @@ def fit_embeddings(self, Xs, Xt):
196196

197197
self.Cs_ = self.lambda_ * cov_Xs + np.eye(Xs.shape[1])
198198
self.Ct_ = self.lambda_ * cov_Xt + np.eye(Xt.shape[1])
199-
Xs_emb = np.matmul(Xs, linalg.inv(linalg.sqrtm(self.Cs_)))
200-
Xs_emb = np.matmul(Xs_emb, linalg.sqrtm(self.Ct_))
199+
200+
Cs_sqrt_inv = linalg.inv(linalg.sqrtm(self.Cs_))
201+
Ct_sqrt = linalg.sqrtm(self.Ct_)
202+
203+
if np.iscomplexobj(Cs_sqrt_inv):
204+
Cs_sqrt_inv = Cs_sqrt_inv.real
205+
if np.iscomplexobj(Ct_sqrt):
206+
Ct_sqrt = Ct_sqrt.real
207+
208+
Xs_emb = np.matmul(Xs, Cs_sqrt_inv)
209+
Xs_emb = np.matmul(Xs_emb, Ct_sqrt)
201210

202211
if self.verbose:
203212
new_cov_Xs = np.cov(Xs_emb, rowvar=False)
@@ -280,8 +289,16 @@ def predict_features(self, X, domain="tgt"):
280289
if domain in ["tgt", "target"]:
281290
X_emb = X
282291
elif domain in ["src", "source"]:
283-
X_emb = np.matmul(X, linalg.inv(linalg.sqrtm(self.Cs_)))
284-
X_emb = np.matmul(X_emb, linalg.sqrtm(self.Ct_))
292+
Cs_sqrt_inv = linalg.inv(linalg.sqrtm(self.Cs_))
293+
Ct_sqrt = linalg.sqrtm(self.Ct_)
294+
295+
if np.iscomplexobj(Cs_sqrt_inv):
296+
Cs_sqrt_inv = Cs_sqrt_inv.real
297+
if np.iscomplexobj(Ct_sqrt):
298+
Ct_sqrt = Ct_sqrt.real
299+
300+
X_emb = np.matmul(X, Cs_sqrt_inv)
301+
X_emb = np.matmul(X_emb, Ct_sqrt)
285302
else:
286303
raise ValueError("`domain `argument "
287304
"should be `tgt` or `src`, "

adapt/feature_based/_mdd.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class MDD(BaseDeepFeature):
7373
task_ : tensorflow Model
7474
Principal task network.
7575
76-
task_adv_ : tensorflow Model
76+
discriminator_ : tensorflow Model
7777
Adversarial task network.
7878
7979
model_ : tensorflow Model

adapt/instance_based/_kliep.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,9 @@ def fit_estimator(self, X, y,
288288
else:
289289
if sample_weight is not None:
290290
sample_weight /= (sample_weight.sum() + EPS)
291+
if sample_weight.sum() <= 0:
292+
sample_weight = np.ones(len(sample_weight))
293+
sample_weight /= (sample_weight.sum() + EPS)
291294
bootstrap_index = np.random.choice(
292295
len(X), size=len(X), replace=True,
293296
p=sample_weight)
@@ -359,7 +362,7 @@ def _fit(self, Xs, Xt, sigma):
359362
alpha += b * ((((1-np.dot(np.transpose(b), alpha)) /
360363
(np.dot(np.transpose(b), b) + EPS))))
361364
alpha = np.maximum(0, alpha)
362-
alpha /= np.dot(np.transpose(b), alpha)
365+
alpha /= (np.dot(np.transpose(b), alpha) + EPS)
363366
objective = np.mean(np.log(np.dot(A, alpha) + EPS))
364367
k += 1
365368

@@ -389,7 +392,7 @@ def _cross_val_jscore(self, Xs, Xt, sigma, cv):
389392
centers,
390393
sigma),
391394
alphas
392-
)
395+
) + EPS
393396
))
394397
cv_scores.append(j_score)
395398
return cv_scores

adapt/utils.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ class GradientHandler(Layer):
364364
"""
365365
def __init__(self, lambda_init=1., name="g_handler"):
366366
super().__init__(name=name)
367+
self.lambda_init=lambda_init
367368
self.lambda_ = tf.Variable(lambda_init,
368369
trainable=False,
369370
dtype="float32")
@@ -384,6 +385,21 @@ def call(self, x):
384385
return _grad_handler(x, self.lambda_)
385386

386387

388+
def get_config(self):
389+
"""
390+
Return config dictionnary.
391+
392+
Returns
393+
-------
394+
dict
395+
"""
396+
config = super().get_config().copy()
397+
config.update({
398+
'lambda_init': self.lambda_init
399+
})
400+
return config
401+
402+
387403
def make_classification_da(n_samples=100,
388404
n_features=2,
389405
random_state=2):

src_docs/_templates/index.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,18 +135,18 @@ <h2> Examples </h2>
135135
<div class="three-cards">
136136
<div class="card h-100">
137137
<div class="card-body">
138-
<a href="{{ pathto("examples/Two_Moons") }}"><h4 class="card-title">Two Moons</h4></a>
138+
<a href="{{ pathto("examples/Two_moons") }}"><h4 class="card-title">Two Moons</h4></a>
139139
<p class="card-text">Here are some examples of domain adaptation methods applied on the Two Moons dataset.
140140
Please look at these examples to learn how to use the algorithms provided by the ADAPT package.
141141
</p>
142142
</div>
143143

144144
<div class="image">
145-
<a href="{{ pathto("examples/Two_Moons") }}">
145+
<a href="{{ pathto("examples/Two_moons") }}">
146146
<img src="_static/images/two_moons_setup.png" class="sk-index-img" alt="Two Moons">
147147
</a>
148148
</div>
149-
<a class="btn btn-below" role="button" href="{{ pathto("examples/Two_Moons") }}">See examples</a>
149+
<a class="btn btn-below" role="button" href="{{ pathto("examples/Two_moons") }}">See examples</a>
150150
</div>
151151
</div>
152152

tests/test_coral.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import numpy as np
66
from sklearn.linear_model import LogisticRegression
7+
from scipy import linalg
78
import tensorflow as tf
89
from tensorflow.keras import Sequential, Model
910
from tensorflow.keras.layers import Dense
@@ -62,6 +63,17 @@ def test_fit_coral():
6263
assert np.abs(model.estimator_.coef_[0][0] /
6364
model.estimator_.coef_[0][1] + 0.5) < 0.1
6465
assert (model.predict(Xt) == yt).sum() / len(Xt) >= 0.99
66+
67+
68+
def test_fit_coral_complex():
69+
np.random.seed(0)
70+
model = CORAL(LogisticRegression(), lambda_=10000.)
71+
Xs_ = np.random.randn(10, 100)
72+
Xt_ = np.random.randn(10, 100)
73+
model.fit(Xs_, ys[:10], Xt_)
74+
assert np.iscomplexobj(linalg.inv(linalg.sqrtm(model.Cs_)))
75+
assert np.iscomplexobj(linalg.sqrtm(model.Ct_))
76+
model.predict(Xs_, domain="src")
6577

6678

6779
def test_fit_deepcoral():

tests/test_kliep.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,21 @@
44

55
import numpy as np
66
from sklearn.linear_model import LinearRegression
7+
from sklearn.base import BaseEstimator
78

89
from adapt.instance_based import KLIEP
910

11+
12+
class DummyEstimator(BaseEstimator):
13+
14+
def __init__(self):
15+
pass
16+
17+
def fit(self, X, y):
18+
self.y = y
19+
return self
20+
21+
1022
np.random.seed(0)
1123
Xs = np.concatenate((
1224
np.random.randn(50)*0.1,
@@ -34,3 +46,21 @@ def test_fit():
3446
assert model.weights_[:50].sum() > 90
3547
assert model.weights_[50:].sum() < 0.5
3648
assert np.abs(model.predict(Xt) - yt).sum() < 20
49+
50+
51+
def test_fit_estimator_bootstrap_index():
52+
np.random.seed(0)
53+
ys_ = np.random.randn(100)
54+
model = KLIEP(DummyEstimator(),
55+
sigmas=[10, 100])
56+
model.fit_estimator(Xs, ys_, sample_weight=np.random.random(len(ys)))
57+
assert len(set(list(model.estimator_.y.ravel())) & set(list(ys_.ravel()))) > 33
58+
59+
60+
def test_fit_estimator_sample_weight_zeros():
61+
np.random.seed(0)
62+
ys_ = np.random.randn(100)
63+
model = KLIEP(DummyEstimator(),
64+
sigmas=[10, 100])
65+
model.fit_estimator(Xs, ys_, sample_weight=np.zeros(len(ys)))
66+
assert len(set(list(model.estimator_.y.ravel())) & set(list(ys_.ravel()))) > 33

tests/test_utils.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,9 @@ def test_gradienthandler(lambda_):
433433
gradient = tape.gradient(grad_handler(inputs),
434434
inputs)
435435
assert np.all(gradient == lambda_ * np.ones(3))
436+
config = grad_handler.get_config()
437+
assert config['lambda_init'] == lambda_
438+
436439

437440

438441
def test_make_classification_da():

0 commit comments

Comments
 (0)