前回エンドポイント作るまではできたけどそこからどうやってそのエンドポイントを使ったらいいかわからず1日うーーーんってやってたらできたので記事にしてみました。
できたもの
作ったものはすごくシンプルでこのフォームに好きな数字を入れて送信ボタンを押下したら
ハマったとこ
このページ自体はflaskを使っていて
フォーム作ったりフォームの内容をPOSTして〜ってところは
色々調べていたらできたのですがハマったのは
どうやったら予測消費電力が返って来るか、というところ
読解力が乏しいので色んな記事やら読んでも理解できず......
AWSのブログにlambdaにこうやったら使えるよっていうのが
書いてあったのでそれを使ってみることに...
import boto3
sagemaker = boto3.client('sagemaker-runtime')
result = sagemaker.invoke_endpoint(
EndpointName='test',
Body=pre_data
)
でもデータの形をどうすればいいかわからず(モデル作成はcsvファイルでやってました)
配列を渡したり適当にオブジェクトにしたりcsvに変換してs3に落としてみたり....色々やっていたのですがずっとエラーが出っ放しでした。
特に出てたエラーが
Received client error (400) from model with message "unable to evaluate payload provided". See https://us-east-1.console.aws.amazon.com/cloudwatch/~~~ (Service: AmazonSageMakerRuntime; Status Code: 424; Error Code: ModelError; Request ID: null)
全然意味がわかんないしCloudWatch見ても訳がわからん状態でした。
色々調べてたらsagemaker.invoke_endpoint
の引数にContentType='text/csv'
って入れたらいいよってここに書いてあったので入れたけど結局データの形をどうしたらいいかわからずまたエラー
Invalid type for parameter Body, value: [12, 0, 12, 12.0, 0], type: <class 'list'>, valid types: <class 'bytes'>, <class 'bytearray'>, file-like object
エラーを読んでみるとfile-like object
にしろって書いてある...
でもfile-like objectが何かわからないで調べていたら
ファイルオブジェクトには実際には 3 種類あります: 生の バイナリーファイル、バッファされた バイナリーファイル、そして テキストファイル です。
ってここにありました。
テキストファイルってことは、モデル作るときcsvだったしカンマ区切りか!って思ってカンマ区切りでデータを送ったら
from flask import Flask, render_template, request, redirect
import json
import boto3
app = Flask(__name__)
@app.route('/')
def index():
return render_template('/sagemaker.html')
@app.route('/predict', methods=['POST'])
def predict():
if request.method == 'POST':
month = request.form['month']
week = request.form['week']
time = request.form['time']
temp = request.form['temp']
weather = request.form['weather']
pre_data_str = month + "," + week + "," + time + "," + temp + "," + weather
sagemaker = boto3.client('sagemaker-runtime', region_name='us-east-1')
result = sagemaker.invoke_endpoint(
ContentType='text/csv',
EndpointName='test',
Body=pre_data_str
)
result_body = json.load(result['Body'])
pre = int(float(result_body['predictions'][0]['score']))
return render_template('/predict.html', predict=pre)
else:
return redirect('/')
if __name__ == '__main__':
app.run(port=8000, debug=True)
いけました!
わからんすぎて本当に投げそうになったけど最後まで頑張ってよかったです。
これを次はlambdaで使ってみて、その後カスタムでやってみようと思います。