scikit-learnをインストールした

MacOSX(10.7.5)でInstalling scikit-learnを見ながらpip installしたらあっさり成功したので喜んでいたのだが、いざ使ってみるとsoを読もうとしてATLで始まるシンボルを見つけられずにエラーになる。

import sklearnが成功しただけで満足して、ちゃんと「nosetests sklearn --exe」しなかったのがいけない。動的に読み込まれるものがちゃんと動くかどうかテストすることが必要だった。

今回の問題は、振る舞いとしてはこれと同じ:python - scikit-learn fails to load - Stack Overflow

from .cd_fast import sparse_std
ImportError: sklearn/linear_model/cd_fast.so: undefined symbol: ATL_dcopy

で、こちらではワークアラウンドスクリプトが紹介されている。Linking problem with atlas on OS X · Issue #1247 · scikit-learn/scikit-learn

このスクリプトは「-L/opt/local/libが付いているコマンドを、全部-L/opt/local/libを削って再実行」というもの。しかし、あれはportでいれて、これはpipで入れて、それはソースからワークアラウンドスクリプト噛ませて入れて、というのはなるべくしたくないなぁ。

MacPortで入っているATLASが悪さをしている風だったので、まずMacPortをバッサリ削除して、そこからport install py27-scikit-learnで入れたらどうなるかを確認してみた。テストでATLAS系の問題が引っかからなくなった。めでたしめでたし。

でもテストは1個エラーになる。

======================================================================
ERROR: sklearn.cluster.bicluster.tests.test_utils.test_get_submatrix
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/sklearn/cluster/bicluster/tests/test_utils.py", line 43, in test_get_submatrix
    assert_true(np.all(X != -1))
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/case.py", line 422, in assertTrue
    if not expr:
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/sparse/base.py", line 183, in __bool__
    raise ValueError("The truth value of an array with more than one "
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all().

----------------------------------------------------------------------
def test_get_submatrix():
    data = np.arange(20).reshape(5, 4)
    rows = [True, True, False, False, True]
    cols = [False, False, True, True]
    for X in (data, csr_matrix(data)):
        submatrix = get_submatrix(rows, cols, X)
        if issparse(submatrix):
            submatrix = submatrix.todense()
        assert_array_equal(submatrix, [[2, 3],
                                       [6, 7],
                                       [18, 19]])
        submatrix[:] = -1
        assert_true(np.all(X != -1))

これcsr_matrix(data)がsparse matrixを返して、X != -1でブロードキャストされてboolのsparse matrixになって、 *それがnp.allに渡されてもなぜかboolではなくsparse matrixが返る* という現象なのでsparse matrixのバグかnp.allの設計がイケてないのかじゃないかと疑っているが、まあ続きは今度気が向いたら追いかける。