エンティティリンキングシステム「BLINK」の使用環境構築メモ

# BLINKとは？
- リポジトリ：https://github.com/facebookresearch/BLINK
- [エンティティリンキング](https://qiita.com/izuna385/items/9d658620b9b96b0b4ec9#エンティティリンキング-とは)を行うためのシステム
- 高速だが精度に劣るバイエンコーダというモデルと、精度は高いが速度は遅いクロスエンコーダというモデルの2つ（両方ともBERTを使用）を組み合わせてエンティティリンキングを行う
- エンティティリンキングの手がかりとして、エンティティを説明するディスクリプション（＋エンティティ名）と文章中のエンティティメンション（＋その周囲の文脈）しか使わないことが特徴
- 詳しくは、右の論文を参照：[Scalable Zero-shot Entity Linking with Dense Entity Retrieval](https://arxiv.org/pdf/1911.03814.pdf)
# 環境
- OS：Linux 4.18.0-240.1.1.el8_3.x86_64
    - pyenvインストール済み
- GPU：GeForce RTX 3090×2
- `cat /proc/driver/nvidia/version`
    - NVRM version: NVIDIA UNIX x86_64 Kernel Module  460.27.04  Fri Dec 11 23:35:05 UTC 2020
    - GCC version:  gcc バージョン 8.3.1 20191121 (Red Hat 8.3.1-5) (GCC) 
- `/usr/local/cuda/bin/nvcc --version`
    -  ```
       nvcc: NVIDIA (R) Cuda compiler driver
       Copyright (c) 2005-2020 NVIDIA Corporation
       Built on Tue_Sep_15_19:10:02_PDT_2020
       Cuda compilation tools, release 11.1, V11.1.74
       Build cuda_11.1.TC455_06.29069683_0
       ```
# やったこと
1. [pyenvでanaconda (Python3系) をインストール - Qiita](https://qiita.com/hollycats/items/4fb0f1e3a77593aa8929)を参考に、pyenvでanaconda3-5.3.1をインストール
1. [元のリポジトリのREADME](https://github.com/facebookresearch/BLINK#use-blink)を見て、使用の準備をする
    - `conda activate`コマンドが使えない場合は、表示されたエラーメッセージ通りにコマンドを実行する
        - 自分の場合は`echo ". /home/<ユーザ名>/.pyenv/versions/anaconda3-5.3.1/etc/profile.d/conda.sh" >> ~/.bashrc`を実行
1. `python blink/main_dense.py -i`を実行してモジュールが見つからないと怒られたので、[ModuleNotFoundError/ No module named 'blink' · Issue #18 · facebookresearch/BLINK](https://github.com/facebookresearch/BLINK/issues/18)を参考に`PYTHONPATH=. python blink/main_dense.py -i`を実行した
1. インストールされているPyTorchのバージョンが搭載されているGPUに対応していない（？）と怒られた。`torch.cuda.get_arch_list() = ['sm_37', 'sm_50', 'sm_60', 'sm_70', 'sm_75']`と`torch.version.cuda = 10.2`という状況で、以下がエラー文
    ```bash
    UserWarning: 
    GeForce RTX 3090 with CUDA capability sm_86 is not compatible with the current PyTorch installation.
    The current PyTorch install supports CUDA capabilities sm_37 sm_50 sm_60 sm_70 sm_75.
    If you want to use the GeForce RTX 3090 GPU with PyTorch, please check the instructions at https://pytorch.org/get-started/locally/

      warnings.warn(incompatible_device_warn.format(device_name, capability, " ".join(arch_list), device_name))
    ...
    RuntimeError: CUDA error: no kernel image is available for execution on the device
    ```
4. 「torch 1.6.0 sm_86」などで検索してヒットした以下のページを参考に、[PyTorchの公式サイト](https://pytorch.org/get-started/previous-versions/)を見て`pip install torch==1.7.0+cu110 torchvision==0.8.0+cu110 torchaudio==0.7.0 -f https://download.pytorch.org/whl/torch_stable.html`を実行した
    - **[GeForce RTX 3080 with CUDA capability sm_86 is not compatible with the current PyTorch installation.](https://github.com/pytorch/pytorch/issues/45028)**
    - [NVIDIA GeForce RTX 3090 with CUDA capability sm_86 is not compatible with the current PyTorch instal](https://discuss.pytorch.org/t/nvidia-geforce-rtx-3090-with-cuda-capability-sm-86-is-not-compatible-with-the-current-pytorch-installation/141940)
    - [RTX3090+cuda10.2の環境でPyTorchが動作しない](https://teratail.com/questions/358588)
6. torchvision==0.8.0+cu110を満たすバージョンが見つからないと怒られたので、`pip install torch==1.7.0+cu110 torchvision==0.8.0 torchaudio==0.7.0 -f https://download.pytorch.org/whl/torch_stable.html`を実行した
7. 再度`PYTHONPATH=. python blink/main_dense.py -i`を実行したら、以下のエラーが出た
    ```py
    AttributeError: 'KeyedVectors' object has no attribute 'key_to_index'
    ```
8. 「'KeyedVectors' object has no attribute 'key_to_index' blink」で検索してヒットした['KeyedVectors' object has no attribute 'key_to_index' · Issue #81 · facebookresearch/BLINK](https://github.com/facebookresearch/BLINK/issues/81)を参考に、`pip install gensim==3.5.0`を実行した
9. 再度`PYTHONPATH=. python blink/main_dense.py -i`を実行して、無事BLINKがインタラクティブモードで動くことを確認
10. バイエンコーダのためにFAISS indexerを使いたい場合は、`PYTHONPATH=. python blink/build_faiss_index.py --output_path models/faiss_flat_index.pkl --save_index`を実行してインデックスをビルドする
    - [元のリポジトリのREADME](https://github.com/facebookresearch/BLINK#2-download-the-blink-models)に書いてあるコマンドに`--save_index`オプションを加えないと、ビルドしたFAISS indexが保存されない
    - ビルドが終わったら、元のREADMEを参考に`PYTHONPATH=. python blink/main_dense.py -i --faiss_index flat --index_path models/faiss_flat_index.pkl`を実行すると、FAISS indexerを使用した状態でBLINKが動く
# プログラムから呼び出す編
- [やったこと](#やったこと)内の使用環境構築が終わっていることを前提とする
1. BLINKディレクトリの1つ上に移動して、`pip install -e ./BLINK`を実行
    - [元のリポジトリのREADME](https://github.com/facebookresearch/BLINK#4-use-blink-in-your-codebase)に載っているpip installコマンドはエラーが出たため、以下のページを参考にした
        - [ERROR/ setup.py is not a valid editable requirement. It should either be a path to a local project o](https://github.com/napalm-automation-community/napalm-s350/issues/5)
        - [conda環境でpython setup.py installが上手くいかないときの解決法 - Qiita](https://qiita.com/3000manJPY/items/babb8f5c6415ee23e580)
2. BLINKディレクトリ内に、[元のリポジトリのREADME](https://github.com/facebookresearch/BLINK#4-use-blink-in-your-codebase)に載っているサンプルコードと同じ内容のPythonファイルを作成
3. 上のファイル内の`"models/"`を`"./models/"`に変更
4. カレントディレクトリがBLINKディレクトリであることを確認し、`python blink_test.py`を実行する
5. 上のコードを実行すると、終了までに5分ほどかかった
    - デバッガで確認してみると、`predictions`変数に各メンションに対するリンキング結果が格納されていることが分かる

以上