|
11 | 11 | from sklearn.utils.testing import assert_array_almost_equal |
12 | 12 | from sklearn.utils.testing import assert_less |
13 | 13 | from sklearn.utils.testing import assert_raises_regexp |
| 14 | +from sklearn.utils.testing import assert_in |
14 | 15 | from sklearn.utils import check_random_state |
15 | 16 | from sklearn.manifold.t_sne import _joint_probabilities |
16 | 17 | from sklearn.manifold.t_sne import _joint_probabilities_nn |
@@ -560,3 +561,67 @@ def test_index_offset(): |
560 | 561 | # Make sure translating between 1D and N-D indices are preserved |
561 | 562 | assert_equal(_barnes_hut_tsne.test_index2offset(), 1) |
562 | 563 | assert_equal(_barnes_hut_tsne.test_index_offset(), 1) |
| 564 | + |
| 565 | + |
| 566 | +def test_n_iter_without_progress(): |
| 567 | + # Make sure that the parameter n_iter_without_progress is used correctly |
| 568 | + random_state = check_random_state(0) |
| 569 | + X = random_state.randn(100, 2) |
| 570 | + tsne = TSNE(n_iter_without_progress=2, verbose=2, |
| 571 | + random_state=0, method='exact') |
| 572 | + |
| 573 | + old_stdout = sys.stdout |
| 574 | + sys.stdout = StringIO() |
| 575 | + try: |
| 576 | + tsne.fit_transform(X) |
| 577 | + finally: |
| 578 | + out = sys.stdout.getvalue() |
| 579 | + sys.stdout.close() |
| 580 | + sys.stdout = old_stdout |
| 581 | + |
| 582 | + # The output needs to contain the value of n_iter_without_progress |
| 583 | + assert_in("did not make any progress during the " |
| 584 | + "last 2 episodes. Finished.", out) |
| 585 | + |
| 586 | + |
| 587 | +def test_min_grad_norm(): |
| 588 | + # Make sure that the parameter min_grad_norm is used correctly |
| 589 | + random_state = check_random_state(0) |
| 590 | + X = random_state.randn(100, 2) |
| 591 | + min_grad_norm = 0.002 |
| 592 | + tsne = TSNE(min_grad_norm=min_grad_norm, verbose=2, |
| 593 | + random_state=0, method='exact') |
| 594 | + |
| 595 | + old_stdout = sys.stdout |
| 596 | + sys.stdout = StringIO() |
| 597 | + try: |
| 598 | + tsne.fit_transform(X) |
| 599 | + finally: |
| 600 | + out = sys.stdout.getvalue() |
| 601 | + sys.stdout.close() |
| 602 | + sys.stdout = old_stdout |
| 603 | + |
| 604 | + lines_out = out.split('\n') |
| 605 | + |
| 606 | + # extract the gradient norm from the verbose output |
| 607 | + gradient_norm_values = [] |
| 608 | + for line in lines_out: |
| 609 | + # When the computation is Finished just an old gradient norm value |
| 610 | + # is repeated that we do not need to store |
| 611 | + if 'Finished' in line: |
| 612 | + break |
| 613 | + |
| 614 | + start_grad_norm = line.find('gradient norm') |
| 615 | + if start_grad_norm >= 0: |
| 616 | + line = line[start_grad_norm:] |
| 617 | + line = line.replace('gradient norm = ', '') |
| 618 | + gradient_norm_values.append(float(line)) |
| 619 | + |
| 620 | + # Compute how often the gradient norm is smaller than min_grad_norm |
| 621 | + gradient_norm_values = np.array(gradient_norm_values) |
| 622 | + n_smaller_gradient_norms = \ |
| 623 | + len(gradient_norm_values[gradient_norm_values <= min_grad_norm]) |
| 624 | + |
| 625 | + # The gradient norm can be smaller than min_grad_norm at most once, |
| 626 | + # because in the moment it becomes smaller the optimization stops |
| 627 | + assert_less_equal(n_smaller_gradient_norms, 1) |
0 commit comments