Skip to content

Commit af127c9

Browse files
committed
Add tests
1 parent f48842a commit af127c9

File tree

11 files changed

+212
-0
lines changed

11 files changed

+212
-0
lines changed

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ numpy
44
scikit-learn>0.20.0
55
tqdm
66
git+https://github.com/beringresearch/annoy.git#egg=annoy
7+
pytest

setup.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,7 @@
1717
'annoy',
1818
'tqdm'
1919
],
20+
extras_require={
21+
'tests': ['pytest']
22+
},
2023
zip_safe=False)

tests/conftest.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import pytest
2+
from keras import backend as K
3+
4+
5+
@pytest.fixture(autouse=True)
6+
def clear_session_after_test():
7+
"""Test wrapper to clean up after TensorFlow and CNTK tests.
8+
9+
This wrapper runs for all the tests in the keras test suite.
10+
"""
11+
yield
12+
if K.backend() == 'tensorflow' or K.backend() == 'cntk':
13+
K.clear_session()

tests/data/.test-annoy-index.index

105 KB
Binary file not shown.

tests/data/test_knn.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
from ivis.data.knn import build_annoy_index, extract_knn
2+
3+
from annoy import AnnoyIndex
4+
import numpy as np
5+
from scipy.sparse import csr_matrix
6+
from sklearn import datasets
7+
import tempfile
8+
import pytest
9+
import os
10+
11+
12+
@pytest.fixture(scope='function')
13+
def annoy_index_file():
14+
_, filepath = tempfile.mkstemp('.index')
15+
yield filepath
16+
os.remove(filepath)
17+
18+
def test_build_sparse_annoy_index(annoy_index_file):
19+
data = np.random.choice([0, 1], size=(10, 5))
20+
sparse_data = csr_matrix(data)
21+
22+
index = build_annoy_index(sparse_data, annoy_index_file)
23+
assert os.path.exists(annoy_index_file)
24+
25+
loaded_index = AnnoyIndex(5)
26+
loaded_index.load(annoy_index_file)
27+
28+
assert index.f == loaded_index.f == 5
29+
assert index.get_n_items() == loaded_index.get_n_items() == 10
30+
assert index.get_nns_by_item(0, 5) == loaded_index.get_nns_by_item(0, 5)
31+
32+
33+
def test_dense_annoy_index(annoy_index_file):
34+
data = np.random.choice([0, 1], size=(10, 5))
35+
index = build_annoy_index(data, annoy_index_file)
36+
assert os.path.exists(annoy_index_file)
37+
38+
loaded_index = AnnoyIndex(5)
39+
loaded_index.load(annoy_index_file)
40+
41+
assert index.f == loaded_index.f == 5
42+
assert index.get_n_items() == loaded_index.get_n_items() == 10
43+
assert index.get_nns_by_item(0, 5) == loaded_index.get_nns_by_item(0, 5)
44+
45+
def test_knn_retrieval():
46+
annoy_index_filepath = 'tests/data/.test-annoy-index.index'
47+
expected_neighbour_list = np.load('tests/data/test_knn_k4.npy')
48+
49+
iris = datasets.load_iris()
50+
X = iris.data
51+
52+
k = 4
53+
search_k = -1
54+
neighbour_list = extract_knn(X, annoy_index_filepath, k=k, search_k=search_k)
55+
56+
assert np.all(expected_neighbour_list == neighbour_list)

tests/data/test_knn_k4.npy

4.81 KB
Binary file not shown.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from ivis.data.triplet_generators import generate_knn_triplets_from_neighbour_list
2+
from sklearn import datasets
3+
4+
import numpy as np
5+
6+
def test_generate_knn_triplets_from_neighbour_list():
7+
neighbour_list = np.load('tests/data/test_knn_k4.npy')
8+
9+
iris = datasets.load_iris()
10+
X = iris.data
11+
batch_size = 32
12+
13+
data_generator = generate_knn_triplets_from_neighbour_list(X, neighbour_list, batch_size=batch_size)
14+
15+
# Run generator thorugh one iteration of dataset and into the next
16+
for i in range((X.shape[0] // batch_size) + 2):
17+
batch = next(data_generator)
18+
19+
# Check that everything is the expected shape
20+
assert isinstance(batch, tuple)
21+
assert len(batch) == 2
22+
23+
assert len(batch[0]) == 3
24+
assert len(batch[1]) == batch_size
25+
assert batch[0][0].shape == (batch_size, X.shape[-1])
26+
27+

tests/integration/test_iris.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from ivis import Ivis
2+
from sklearn import datasets
3+
import numpy as np
4+
5+
6+
def test_iris_embedding():
7+
iris = datasets.load_iris()
8+
x = iris.data
9+
y = iris.target
10+
11+
val_x = x
12+
val_y = y
13+
14+
ivis_iris = Ivis(n_epochs_without_progress=5)
15+
ivis_iris.k = 15
16+
ivis_iris.batch_size = 16
17+
18+
y_pred_iris = ivis_iris.fit_transform(x)

tests/nn/test_losses.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from ivis.nn import losses
2+
from ivis.nn.losses import triplet_loss, get_loss_functions
3+
4+
from keras import backend as K
5+
import numpy as np
6+
import tensorflow as tf
7+
8+
9+
def test_loss_function_call():
10+
margin = 2
11+
12+
loss_dict = get_loss_functions(margin=margin)
13+
14+
for loss_name in loss_dict.keys():
15+
loss_function = triplet_loss(distance=loss_name, margin=margin)
16+
assert loss_function.__name__ == loss_name
17+

tests/nn/test_network.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from ivis.nn.network import get_base_networks, base_network, build_network
2+
3+
import keras
4+
from keras.models import Model, Sequential
5+
from keras.layers import Dense
6+
import numpy as np
7+
8+
def test_base_networks():
9+
network_names = get_base_networks()
10+
input_shape = (4,)
11+
12+
for name in network_names:
13+
model = base_network(name, input_shape)
14+
assert isinstance(model, Model)
15+
16+
def test_build_network():
17+
18+
X = np.zeros(shape=(10, 5))
19+
embedding_dims = 3
20+
21+
base_model = Sequential()
22+
base_model.add(Dense(8, input_shape=(X.shape[-1],)))
23+
24+
model = build_network(base_model, embedding_dims=embedding_dims, embedding_l2=0.1)
25+
encoder = model.layers[3]
26+
27+
assert model.layers[3].output_shape == (None, 3)
28+
assert np.all(base_model.get_weights()[0] == encoder.get_weights()[0])
29+
assert np.all([isinstance(layer, keras.layers.InputLayer) for layer in model.layers[:3]])
30+
31+
assert encoder.output_shape == (None, embedding_dims)
32+

0 commit comments

Comments
 (0)