scikit-learn/scikit-learn — pull request #1147 by kuantkid (2012-09-14 06:13:45+00:00)
Title: FIX for issue #884 and improve contingency matrix built efficiency

I think(I am not so sure) that the log operation breaks for ```log(a/b)```, as the division/multiplication will have possible loss of precision, and ```log(a/b)``` should be written as ```log(a) - log(b)```.

For example in issue #776:
1.``normalized_mutual_info_score([1, 1, 1, 1, 1, 1, 1], [0, 1, 2, 3, 4, 5, 6])`` Will be zero
2. ```for i in np.logspace(1, 4, 4):
print normalized_mutual_info_score(np.ones(i, dtype=np.int), np.arange(i, dtype=np.int))```
Will be all zero

Another is to use ```coo_matrix``` to accelerate the built of the contigency matrix, A quick test is shown below.

Using coo_matrix
coo_matrix is similar to matlab's ```accumarray```, and I think it is more efficient to calculate :-).
```%timeit contingency = contingency_matrix(random_integers(1,10000,(1,1000000))[0],random_integers(1,10000,(1,1000000))[0])
1 loops, best of 3: 604 ms per loop```
Using original python dict
```%timeit contingency = contingency_matrix(random_integers(1,10000,(1,1000000))[0],random_integers(1,10000,(1,1000000))[0])
1 loops, best of 3: 1.84 s per loop```

Further issue is that when using dict, ```contingency = contingency_matrix(random_integers(1,10000,(1,1000000)),random_integers(1,10000,(1,1000000)))``` such code will fail as the ndarray not hashable, a check for the input string should be made.

One thing remaining is that, the contigency_matrix is usually (if not all the time) is sparse, so use sparse operation should further accelearte expecially calculate the ```x * log(x)``` with dealing the ```0log0``` case as we can get out the non-zero items with no cost than dense matrix. But currently I put a ```todense()``` for the contingency matrix. I will further fix it if decided to use coo_matrix :-)