はじめに
この記事ではSageMakerはいじりません.SageMakerだけいじりたい人はクローンして次の記事から読んだらいいと思います.
企画倒れしました...
開発案件でSageMakerを味見する話があったのでやってみた記事(の前半)です.
※2022年11月25日現在の内容です.
『学習から行う』みたいな記事は見つけられたのですが,『推論だけやる』という記事は見つけられなかったので書いています.
よって,対象読者はこのあたりの条件を満たす人になるかと.
- 学習はローカル(というかAWS以外)でやる
- 推論のAPIを作りたい
- バックエンドのインフラはお任せにしたい(フロントエンドはさておき)
チュートリアル読めば書いてあったのかもしれない内容な気もしています.知りませんが.
誰かの技術ブログをサクッと再現できないたびに無力感を感じるので,タイトルに『雑魚のための』とつけました.
ソースコードはGithubにあげてあります.
また前提条件としてDocker,AWSのアカウント登録が済んでいることとしています.
間違ってもしないこと
- AWSでAPIのデバッグする
- APIに与えるパラメータだとか,内部でどう処理されるのかとかをエンドポイント作成しながらデバッグしてたら長時間かかった
- AWSでDcokerfileのデバッグをする
- エンドポイントを作成したらDockerfileが悪かったというパターンが超あった
知ってたらよかったこと
この辺りの要素を知っている人だとヌルヌルだったはずです.
コアプログラムとしてPython,仮想環境としてDocker,APIに関してはSwagger,インフラとしてAWSという感じですね.
- Python
- fastapi
- Docker
- Dockerfile
- Swagger
- Swagger UI
- AWS
- Amazon SageMaker
- Erastic Container Registry
やったこと
- Simpletransformersで文章分類器の作成
- FastAPIでAPI作成
- Amazon SageMakerでエンドポイント作成
3については規定の手続きになるので,1と2をどう組むかでアプリケーションを変えられますね.
ということで,1と2についてはこの記事で,3についてを次の記事で書いていきます.
(書いていたら長くなったので分けました.)
特にSimpletransformersは疲れたのでなんとなく割愛しています.
Simpletransformersで文章分類器の作成
Simpletransformers+Huggingfaceの学習済みモデルを使って文章分類器を作ります.
Simpletransformersはtransformersをラッパーしたライブラリで,超簡単にtransformerが使えます.
Huggingfaceは自然言語系のライブラリや誰かが学習させたモデルが使えます.
雑魚なのでありものを使います.
文章分類は,ツイッター文章の感情分類をします.
HuggingfaceよりCardiff大学の学習済みモデルを拝借します.
プログラムは書いてもらいました.
ソースコードはこちら
from scipy.special import softmax
from simpletransformers.classification import ClassificationModel
def transformation(inputs):
inputs = inputs["test_list"] if len(inputs["test_list"])>0 else [inputs["test_text"]]
model = ClassificationModel("roberta", "cardiffnlp/twitter-roberta-base-sentiment", use_cuda=False)
_, raw_pred = model.predict(inputs)
raw_pred = softmax(raw_pred, axis=1)
outputs = [{"positive": round(raw[0], 3), "neutral": round(raw[1], 3), "negative": round(raw[2], 3)} for raw in raw_pred]
return {"result": outputs}
inputs = {
test_text: "",
test_list: ["", ""]
}
print(transformation(inputs))
inputs
の中のtest_text
かtest_list
にstringを投げると推論してくれます.
※test_list
が優先されます.
このコアプログラムはここでデバッグしておきましょう.
出力がdictなのはSageMakerへの仕込みです.
つまづきポイントはこの通り.
-
ClassificationModel()
に与えるHuggingFaceのパスが間違っていないか - 関数への入力が間違っていないか
FasAPIでAPI作成
コーディング
この記事を参考にして作成しました.
pydanicの部分で参考にした記事があったのですがダチョウ並の脳なので忘れました.
ソースコードです(Gitにあがっています)
from fastapi import FastAPI
import uvicorn
from pydantic import BaseModel
from scipy.special import softmax
from simpletransformers.classification import ClassificationModel
app = FastAPI()
class Test(BaseModel):
test_text: str
test_list: list
@app.get("/ping")
def ping():
return {"Hello": "World"}
@app.post("/invocations")
def transformation(inputs: Test):
inputs = inputs.test_list if len(inputs.test_list)>0 else [inputs.test_text]
model = ClassificationModel("roberta", "cardiffnlp/twitter-roberta-base-sentiment", use_cuda=False)
_, raw_pred = model.predict(inputs)
raw_pred = softmax(raw_pred, axis=1)
outputs = [{"positive": round(raw[0], 3), "neutral": round(raw[1], 3), "negative": round(raw[2], 3)} for raw in raw_pred]
return {"result": outputs}
if __name__ == "__main__":
uvicorn.run(
"app:app",
host="0.0.0.0",
port=8080
)
役割としては,通信がうまく行っているかping()を飛ばして確認したあとに,transformation()で処理を行うという感じで使いました(本当の使い方が違ったらすいません).
さてさて,ここで大事なのはこれのデバッグってどこでやるの?という話ですよね.
実はFastAPIには自動ドキュメント作成機能があり,Swagger UIでブラウザを使ってAPIをテストすることができます(すごい).
Swagger UI
まずはuvicornを使ってAPIを起動してみます.
pythonのファイル名:FastAPIのインスタンス名
で起動できます.
例)hoge.pyの中でfuga = FastAPI()
としているならこんな感じです.
$ uvicorn hoge:fuga
app.pyの中でapp = FastAPI()としているのでこんな感じ↓で起動します.
$ uvicorn app:app
あるいはmainで呼び出すようにしているのでpythonコマンドでも起動できます.
$ cd src
$ python app.py
どちらにせよこんなのが出れば正解です.
INFO: Started server process [30238]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
※pythonで起動するとこっち↓がでるかと思います
INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
APIはhttp://127.0.0.1:8000
をたたけばいいそうです.
Swagger UIにはhttp://127.0.0.1:8000/docs
でアクセスできます.
※pythonで起動した場合はhttp://127.0.0.1:8000
→http://0.0.0.0:8080
で読み替えてください.
こんな画面が出てきます.
ここから先の操作は雑魚らしく野生の勘で進めました.
まずはGETから試してみましょう.
- GETのあたりをおもむろにポチる
- 右側のTry it outをポチる
- Executeをポチる
Code 200が返ってくれば正解です.
失敗すると400とか500が返ってきます.
POSTも試してみましょう.今度はTry it outを押すとRequest bodyがガッと開きますガッと.
せっかくなのでリクエストを編集してみます(画像小さい).
Request bodyの中をこんな感じに変えてみます.
コピペはこちらから
{
"test_text": "",
"test_list": [
"string", "string"
]
}
そんなこんなでExecuteすると,今回は結果出力までしばらく時間がかかります.
←こんなのがぐるぐるします.
ボトルネックはこの2つなので広い心で待ってあげましょう.
- HuggingFaceからモデルをダウンロードしてくる
- モデルを読み込んで推論する
こちらもうまくいくと200が返ってきて,失敗すると400とか500が返ってきます.
そして,terminal側にpythonのログが表示されます.
おもむろに失敗させてみました.
terminal側ではこんな感じでhogeってなんぞやと返ってきています.
Swagger UI側ではこんな感じでServerがおかしいぞと返ってきています.
そんなこんなでSwagger UIを使ってAPIの動作確認をすることができました.
Swagger UIとterminalの表示を駆使してデバッグをすることができます.
ここでしっかりとデバッグをしておきましょう.
おわりに
文章分類API自体はこれでオッケーです.
なにはともあれ無事にできてよかったです.
ありがとうHuggingFace,FastAPI,SwaggerUI.
終わりよければ全てよし.
いよいよ次はSageMakerでエンドポイントを作っていきます.
参考文献
順不同です.とりあえず読んだだろうというものを列挙してみました.
もっとあった気がするんですがマジで忘れましたすみません