###概要:
Anacondaを導入していない CentOS7 環境に、faissをインストールする方法のメモ。
Anacondaなら CentOS7 にも問題なくインストールできるかは、私は分かってはいないが… pipではスムーズにインストールできなかったので、インストール可能な手順を記録。
###背景:
CentOS7環境になぜかインストールできない!
世界的に見ると、同様の問題にぶち当たっている人は何名かはいるようなのですが、明確に"コレだぜ!"といった解決策を見出している情報もなく… 半日以上を費やしてしまった。
複数の CentOS7 環境で、同様にインストールができないことは確認しているので、CentOS7固有の問題かと思われ、手順を確立しておきたかった。
##最初は順調でした…
FaissというFacebook社が公開している、類似性検索(およびクラスタリング)のための高速アルゴリズムを実装したライブラリです。
今、SentenceBERTでベクトル化した値から、SemanticSearchする仕組みを構築しようとしているのですが…
当初は単純に検索したいベクトルと、全検索対象のベクトルのCos類似度を算出・Sortして一番類似性の高いベクトルを取得するような実装でした。
しかしこのSemanticSearchの検索対象が大量になった場合に、算出コストがヤバいことになりそうな気配を感じていました。
ちょっと調べると、この問題に対し、ベクトルをIndex化して(?)低コスト(短時間で)で算出することができる「Faiss」というライブラリが見つかりました。
早速、Google Colab上で試してみました!
!pip3 install faiss-cpu
import numpy as np
import faiss
d = max([len(v) for v in sentence_vectors])
index = faiss.IndexFlatL2(d)
index.add(np.array(sentence_vectors).astype('float32'))
closest_n = 1
D, I = index.search(np.array(query_embeddings).astype('float32'), closest_n)
###楽勝〜!!
まだ検索対象のベクトルが少数(100以下)のテストなので、劇的な変化は感じませんが…
実際に検索時間は短縮し、類似性検索もCos類似度での抽出結果とも差はないので、実際の仕組みに組み込んでみようと取り組み始めました。
##さて… 本題のCentOS7のサーバーにインストールしましょう!! 当然楽勝でしょう?!
Colabと同様に pip でインストール。
Faiss は Anaconda でのインストールが主流のようですが、私は Anaconda は使っていないので pip です。
pip の場合は faiss-cpu / faiss-gpu というモジュール名を指定するようですよね… cpu・gpuを切り替える場合は、uninstallして再度どちらかでインストールし直すみたいです。
https://pypi.org/project/faiss-cpu/
https://pypi.org/project/faiss-gpu/
###しか〜し! エラーが出てる! なぜ?!
$ sudo pip3 install faiss-cpu
Collecting faiss-cpu
Downloading https://files.pythonhosted.org/packages/8b/3e/d64ff22504a70fb15457de8fb2f5fd84e35448fdcd9958880ae8d0438a82/faiss-cpu-1.6.4.post2.tar.gz
Building wheels for collected packages: faiss-cpu
Running setup.py bdist_wheel for faiss-cpu ... error
Complete output from command /usr/bin/python3 -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-i9sic395/faiss-cpu/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" bdist_wheel -d /tmp/tmp2c2gltlxpip-wheel- --python-tag cp36:
running bdist_wheel
running build
running build_py
running build_ext
building 'faiss._swigfaiss' extension
swigging faiss/faiss/python/swigfaiss.i to faiss/faiss/python/swigfaiss_wrap.cpp
swig -python -c++ -Doverride= -I/usr/local/include -Ifaiss -DSWIGWORDSIZE64 -o faiss/faiss/python/swigfaiss_wrap.cpp faiss/faiss/python/swigfaiss.i
unable to execute 'swig': No such file or directory
error: command 'swig' failed with exit status 1
----------------------------------------
Failed building wheel for faiss-cpu
Running setup.py clean for faiss-cpu
Failed to build faiss-cpu
Installing collected packages: faiss-cpu
Running setup.py install for faiss-cpu ... error
Complete output from command /usr/bin/python3 -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-i9sic395/faiss-cpu/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-q0l4dufw-record/install-record.txt --single-version-externally-managed --compile:
running install
running build
running build_py
running build_ext
building 'faiss._swigfaiss' extension
swigging faiss/faiss/python/swigfaiss.i to faiss/faiss/python/swigfaiss_wrap.cpp
swig -python -c++ -Doverride= -I/usr/local/include -Ifaiss -DSWIGWORDSIZE64 -o faiss/faiss/python/swigfaiss_wrap.cpp faiss/faiss/python/swigfaiss.i
unable to execute 'swig': No such file or directory
error: command 'swig' failed with exit status 1
----------------------------------------
Command "/usr/bin/python3 -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-i9sic395/faiss-cpu/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-q0l4dufw-record/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-build-i9sic395/faiss-cpu/
ちなみに、ローカルの Mac で試してみました。Colabだけでうまく行く方法だったのかも?!
いえいえ、ローカルのMacでも何の問題もなく faiss-cpu でインストールが完了します… これはヤバイ匂いがする!
###迷宮に迷い込みました…
いろいろWeb上で調べてみたのですが、決定打となる対策は見当たりません…
その中でも、faiss-centos という私の現在の悩み事のタネのワードが組み合わされた代物が見つかりました。
これはイケるでしょ!!
ここは気合で! ほれ!!
$ sudo pip3 install faiss-centos
WARNING: Running pip install with root privileges is generally not a good idea. Try `pip3 install --user` instead.
Collecting faiss-centos
Could not find a version that satisfies the requirement faiss-centos (from versions: )
No matching distribution found for faiss-centos
##が〜ん…
さらにいろいろWebを彷徨うものの、以下のように解決したんだかどうだか… いまいちわからん。
https://github.com/facebookresearch/faiss/issues/866
###その後も、いろいろやりました!
その中でも、faiss-centos は wheel ではなくて egg なので、pip のバージョンを8に落として試すとか…
egg ファイルを unzip で伸張してみるとか…
openblas-serial や gmp-devel をインストールしてみるとか…
しかしこちらの苦悩などお構いなしに、_swigfaiss が見つからんとか、何かが足りん!だとか無理難題を言ってきます。 疲れたぁ…
ちょっと一休み… というか別のことをして気を紛らわせたり、お茶を飲んだり、ボーっとしたり…
##あれ〜!?
さて、一休みもしたし、脳みその疲れも取れたし、もうすっかり夜になってるし!
再度 CentOS7 のサーバーにログインして…
$ python3
Python 3.6.8 (default, Apr 2 2020, 13:34:55)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import faiss
>>>
###エラーが出てない!!
休憩前は、エラーだったのに… とうとう私の元にも7人のコビトさん達がやってきてくれたのかぁ??
だって… pipでインストールされた形跡もない!? どゆこと??
$ pip3 freeze | grep faiss
$
なので目的のフォルダーに移動し、もう一度… エラーだ。
またルートに戻って、もう一度… イケる! 何の違い??
なにやら、「 https://pypi.org/project/faiss-centos/ 」からダウンロードした、faiss_centos-1.5.2-py3.6.egg をunzip した、faiss/ フォルダを直下にして、import するとOKのようなのです。
一筋の光が…
だとしたら… この faiss/ フォルダを、site-packages/ にコピーしたら???
##結論
その後、追加でインストールが必要なライブラリなどを特定し、CentOS7でも faiss をインストールできる手順を特定しました。
分かってしまえば、コレだけでしたぁ…
$ wget https://files.pythonhosted.org/packages/f6/8b/ab69a201ea1b8be759ba16f172f92d1fb935a8f4a94f02fe52c7d8ec579f/faiss_centos-1.5.2-py3.6.egg
$ unzip faiss_centos-1.5.2-py3.6.egg
$ sudo cp -r ./faiss /usr/local/lib/python3.6/site-packages
(もしくは… $ sudo cp -r ./faiss /usr/lib/python3.6/site-packages 環境に合わせて…)
$ sudo yum install openblas-serial
$ sudo yum install gmp gmp-devel
$ python3
Python 3.6.8 (default, Apr 2 2020, 13:34:55)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import faiss
>>>
もし、同じような問題にぶち当たっている人がいたら、参考にしてもらえると嬉しいですね。