さくらVPS（GPU無し）でBERTを動かしてみた

# はじめに
こちらの記事
[BERTについて解説！日本語モデルを使って予測をしてみようー！](https://toukei-lab.com/bert)
の通りにしますと、Google colaboratory上で簡単にBERTが体験できます。

これを、Google colaboratory上ではなく、安いサーバー上で公開利用できないかと考え、さくらVPS1G (月額800円)で動かしてみました。

ポイントは、Google colaboratoryでは使えるGPUが、さくらVPSでは使えないので、CPU版のライブラリのインストールが必要だということです。

# 導入環境
さくらVPS　
メモリ 1GB、ストレージSSD 50 GB、CPU 2コア (月額800円)
標準インストール CentOS8 x86_64

# 導入
まずは、次の記事を参考にさせていただき、「anaconda」ユーザーを作成して、機械学習用の環境「ml_env」を作成しました。記事ではCentos7.7で構築されていますが、CentOS8でも全く問題はありませんでした。
[【第一回】CentOSにPythonの機械学習開発環境を構築する（Anacondaインストール編） - Qiita](https://qiita.com/yasushi-jp/items/7cef8447062fb7dd200c)

上の記事に引き続いて、「anaconda」ユーザーで機械学習用環境「ml_env」をアクティブにしまして、この環境にBERTを導入します。

###CPU版のTransformersのインストール###

```
pip install transformers[tf-cpu]
```

※このインストールでTensorFlowも同時にインストールされます。[参考](https://huggingface.co/transformers/installation.html)

###CPU版のTorchのインストール###

```
pip install torch==1.7.0+cpu torchvision==0.8.1+cpu torchaudio===0.7.0 -f https://download.pytorch.org/whl/torch_stable.html
```

※ Anacondaでインストール`conda install pytorch`としますと、`Illegal instruction (core dumped)`のようなエラーがでました。GPU関連のエラーのようなので、上記のようなCPU版をインストールしました。このコマンドは、[https://pytorch.org/get-started/locally/](https://pytorch.org/get-started/locally/) の「START LOCALLY」で
![pytorch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566826/db48b60d-1be1-90a7-7821-acbf4c241781.png)
のように選択して生成されたものです。CUDAをNoneとして、GUP無しとしています。

これで必要なライブラリはインストールできました。

###BERT日本語Pretrainedモデルのダウンロード###
続いて、京都大学の[黒橋・河原・村脇研究室](http://nlp.ist.i.kyoto-u.ac.jp/index.php?BERT%E6%97%A5%E6%9C%AC%E8%AA%9EPretrained%E3%83%A2%E3%83%87%E3%83%AB)が公開されています、BERT日本語Pretrainedモデルをダウンロードします。

現在、anacondaユーザーで`/home/anaconda/` にいるとしまして、日本語モデルを格納するディレクトリ`/home/anaconda/bert/japan_test`を作成しまして、移動します。


```
mkdir bert
cd bert
mkdir japan_test
cd japan_test
```

続いて、ダウンロード、解凍、ダウンロードファイルの削除をします。

```
curl -OL http://nlp.ist.i.kyoto-u.ac.jp/nl-resource/JapaneseBertPretrainedModel/Japanese_L-12_H-768_A-12_E-30_BPE.zip
unzip Japanese_L-12_H-768_A-12_E-30_BPE.zip
rm -rf Japanese_L-12_H-768_A-12_E-30_BPE.zip
```

これで、` /home/anaconda/bert/japan_test/apanese_L-12_H-768_A-12_E-30_BPE`にモデルが設置できました。

作成したディレクトリから出ます。

```
cd ../..
```
ここ` /home/anaconda/`に、BERTテスト用の、Pythonプラグラムのファイル` bert_test.py`を置きます。

```bert_test.py
from transformers import BertTokenizer, BertForMaskedLM, BertConfig
import torch
import numpy as np

config = BertConfig.from_json_file('/home/anaconda/bert/japan_test/Japanese_L-12_H-768_A-12_E-30_BPE/bert_config.json')
model = BertForMaskedLM.from_pretrained('/home/anaconda/bert/japan_test/Japanese_L-12_H-768_A-12_E-30_BPE/pytorch_model.bin', config=config)
bert_tokenizer = BertTokenizer('/home/anaconda/bert/japan_test/Japanese_L-12_H-768_A-12_E-30_BPE/vocab.txt',
 do_lower_case=False, do_basic_tokenize=False)

tokenized_text = ['[CLS]', 'むかし', '浦島', 'という', '漁師', 'が', '住んで', 'いました', '。'
, 'ある', '日', '、', '[MASK]', 'が', '浜', 'を', '歩いて', 'いると', '[SEP]']
masked_index = 12

tokens=bert_tokenizer.convert_tokens_to_ids(tokenized_text)
tokens_tensor=torch.tensor([tokens])

model.eval()
with torch.no_grad():
  outputs = model(tokens_tensor)
  predictions = outputs[0]
_,predicted_indexes=torch.topk(predictions[0,masked_index],k=10)
predicted_tokens = bert_tokenizer.convert_ids_to_tokens(predicted_indexes.tolist())
print(predicted_tokens)
```

このプログラムは、

```
['[CLS]', 'むかし', '浦島', 'という', '漁師', 'が', '住んで', 'いました', '。', 'ある', '日', '、', '[MASK]', 'が', '浜', 'を', '歩いて', 'いると', '[SEP]']
```

の` [MASK]` に入る単語を予測します。

```
python bert_test.py
```

で実行しますと、

```
['漁師', '[UNK]', '男', '人々', '人', '若者', '女', '役人', '少年', '魚']
```

という、それっぽい結果が得られました。これでBERTを動かすことに成功しました。

# その他

このBERTの解析結果を、Webアプリケーションで使いたいと考え、FlaskでローカルなWebサーバーを立てましまして、Flask上でBERTのモデルをデーモン化（常駐化）させてみました。そしてApacheでWebサーバーを立てまして、APIとして公開しました。つまり外部からApacheのAPIにアクセスしますとそのAPIプログラムが、Flask上のBERTにアクセスしまして、BERTの解析結果を得る、という流れを作ってみました。