🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Keras

Kerasは、TheanoやTensorFlow/CNTK対応のラッパーライブラリです。DeepLearningの数学的部分を短いコードでネットワークとして表現することが可能。DeepLearningの最新手法を迅速に試すことができます。

Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

Heroku

HerokuはHeroku社が開発と運営を行っているPaaSの名称です。RubyやNode.js、Python、そしてJVMベース(Java、Scala、Clojureなど)の複数のプログラミング言語をサポートしている。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

3538閲覧

flask+keras+tensorflowのwebアプリをherokuにデプロイした際に出たエラー、R14 - Memory Quota Exceededが解決できない。

salmon_0511

総合スコア16

Keras

Kerasは、TheanoやTensorFlow/CNTK対応のラッパーライブラリです。DeepLearningの数学的部分を短いコードでネットワークとして表現することが可能。DeepLearningの最新手法を迅速に試すことができます。

Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

Heroku

HerokuはHeroku社が開発と運営を行っているPaaSの名称です。RubyやNode.js、Python、そしてJVMベース(Java、Scala、Clojureなど)の複数のプログラミング言語をサポートしている。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2019/10/11 04:23

編集2019/10/12 08:31

flask+keras+tensorflowのwebアプリをherokuにデプロイした際に、「R14 - Memory Quota Exceeded」エラーしたため、その解決方法を教えていただきたく、質問しました。

前提・実現したいこと

flask+keras+tensorflowで学習済みモデルをload_moduleし、アップロードした画像の判別をするwebアプリを実装していました。

webアプリ:https://tongue-classify.herokuapp.com

ローカル環境ならびにデプロイしたアプリはPC上では正常に作動しました。が、スマホで作動させた場合に下記のようなR14エラーが発生してしまいます。

R14エラーがdynoメモリ不足によって起こると知ったため、何らかの方法でメモリ使用量を削減し、herokuの無料プラン内で作動させたいと思いました。

発生している問題・エラーメッセージ

$ heroku logs --tail 2019-10-10T10:07:32.591876+00:00 heroku[web.1]: Process running mem=534M(104.3%) 2019-10-10T10:07:32.593706+00:00 heroku[web.1]: Error R14 (Memory quota exceeded) 2019-10-10T10:08:36.672094+00:00 heroku[web.1]: source=web.1 dyno=heroku.148920410.8ea5bc70-23aa-4b88-99c4-f7fd91b197a9 sample#load_avg_1m=0.34 2019-10-10T10:08:36.688775+00:00 heroku[web.1]: source=web.1 dyno=heroku.148920410.8ea5bc70-23aa-4b88-99c4-f7fd91b197a9 sample#memory_total=509.29MB sample#memory_rss=479.70MB sample#memory_cache=0.05MB sample#memory_swap=29.54MB sample#memory_pgpgin=323173pages sample#memory_pgpgout=204444pages sample#memory_quota=512.00MB 2019-10-10T10:08:42.477268+00:00 heroku[router]: at=info method=POST path="/predict" host=tongue-classify.herokuapp.com request_id=b05077d4-d660-49af-82db-9e84bffe02dd fwd="125.200.127.226" dyno=web.1 connect=0ms service=2820ms status=500 bytes=455 protocol=https

該当のソースコード

python

1import os 2from flask import Flask, flash, request, redirect, url_for, render_template 3from werkzeug.utils import secure_filename 4 5from keras.models import Sequential, load_model 6import keras, sys 7import numpy as np 8from PIL import Image 9import keras.backend as K 10import tensorflow as tf 11 12 13config = tf.ConfigProto() 14config.gpu_options.allow_growth = True 15sess = tf.Session(config=config) 16K.set_session(sess) 17 18 19class_1 = "1です。" 20class_content_1 = "舌苔はほとんどついておらず、かなり綺麗な状態かと思われます。" 21classes_solution_1 = "これまでと同様に、口腔ケアを頑張っていきましょう。注意点として、舌磨きのやりすぎは舌を傷つけるだけでなく舌苔の付着量増加にもつながるため、1日1回を限度に優しく行うようにしましょう。" 22 23class_2 = "2です。" 24class_content_2 = "舌の汚れはあまり気にする必要はないでしょう。" 25classes_solution_2 = "舌苔は口臭の原因にもなるため、ああああああああああああああああああああああああああああああああああああああああああああああああああああ。" 26 27class_3 = "3です。" 28class_content_3 = "舌に汚れが若干多くついているかもしれません。舌苔(舌の汚れ)は口臭の原因にもなるため、普段の歯磨きに加え、舌を掃除することが望ましいでしょう。" 29classes_solution_3 = "舌苔の掃除法としてはガーゼや舌ブラシを用いて、舌の表面を奥から手前に優しくこするようにして行ってください。1日1回を限度に行いましょう。" 30 31classes = [class_1,class_2,class_3] 32classes_content = [class_content_1, class_content_2, class_content_3] 33classes_solution = [classes_solution_1, classes_solution_2, classes_solution_3] 34 35num_classes = len(classes) 36image_size = 50 37 38UPLOAD_FOLDER = './uploads' 39ALLOWED_EXTENSIOS = set(['png', 'jpg', 'gif']) 40 41app = Flask(__name__) 42app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER 43 44 45 46model = load_model('./tongue_cnn_aug.h5') 47graph = tf.get_default_graph() 48 49 50 51def allowed_file(filename): 52 #もし.が含まれたる かつ もし拡張子前の.で区切り、拡張子小文字小文字であれば true 53 return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIOS 54 55# @app.route('/', methods=['GET', 'POST']) 56@app.route('/') 57def upload_file(): 58 return render_template('test.html') 59 60@app.route('/predict',methods=['GET', 'POST']) 61def predict_file(): 62 global graph 63 with graph.as_default(): 64 if request.method == 'POST': 65 if 'file' not in request.files: 66 flash('ファイルがありません') 67 return redirect(request.url) 68 file = request.files['file'] #ここがよくワカンねぇな 69 # if user does not selectfile, browser also 70 #submit an empty part without filename 71 if file.filename == '': 72 flash('ファイルがありません') 73 return redirect(request.url) 74 if file and allowed_file(file.filename): 75 filename = secure_filename(file.filename) 76 file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) 77 filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) 78 79 image = Image.open(filepath) 80 image = image.convert('RGB') 81 image = image.resize((image_size, image_size)) 82 data = np.asarray(image) 83 X = [] 84 X.append(data) 85 X = np.array(X) 86 87 #model = load_model('./tongue_cnn_aug.h5') 88 89 result = model.predict([X])[0] 90 predicted = result.argmax() 91 percentage = int(result[predicted] * 100) 92 #K.clear_session() 93 result_title = "" 94 result_content="" 95 result_solution="" 96 97 98 # return render_template('predict.html', result = classes[predicted], result_content = classes_content[predicted], result_solution = classes_solution[predicted], result_title="解析結果") 99 return render_template('predict.html', result = classes[predicted], result_content = classes_content[predicted], result_solution = classes_solution[predicted], result_title="解析結果",img_name=file.filename) 100 101from flask import send_from_directory 102 103@app.route('/uploads/<filename>') 104def uploaded_file(filename): 105 return send_from_directory(app.config['UPLOAD_FOLDER'], filename) 106 107

試したこと

Qiita--KerasでGPUメモリの使用量を抑える方法

を参考にkerasのメモリを制限しようと試みたものの、エラーは消えませんでした。

###追記

メモリの使用量

Line # Mem usage Increment Line Contents ================================================ 51 332.6 MiB 332.6 MiB @app.route('/') 52 @profile 53 def upload_file(): 54 332.8 MiB 0.2 MiB return render_template('test.html') 127.0.0.1 - - [12/Oct/2019 17:15:04] "GET / HTTP/1.1" 200 - I1012 17:15:04.182286 123145472167936 _internal.py:122] 127.0.0.1 - - [12/Oct/2019 17:15:04] "GET / HTTP/1.1" 200 - Filename: /Users/yuya/PycharmProjects/tongue/predict_web.py Line # Mem usage Increment Line Contents ================================================ 58 332.8 MiB 332.8 MiB @app.route('/predict',methods=['GET', 'POST']) 59 @profile 60 def predict_file(): 61 global graph 62 332.8 MiB 0.0 MiB with graph.as_default(): 63 332.8 MiB 0.0 MiB if request.method == 'POST': 64 332.8 MiB 0.0 MiB if 'file' not in request.files: 65 flash('ファイルがありません') 66 return redirect(request.url) 67 332.8 MiB 0.0 MiB file = request.files['file'] #ここがよくワカンねぇな 68 # if user does not selectfile, browser also 69 #submit an empty part without filename 70 332.8 MiB 0.0 MiB if file.filename == '': 71 flash('ファイルがありません') 72 return redirect(request.url) 73 332.8 MiB 0.0 MiB if file and allowed_file(file.filename): 74 332.8 MiB 0.0 MiB filename = secure_filename(file.filename) 75 332.8 MiB 0.0 MiB file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) 76 332.8 MiB 0.0 MiB filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) 77 78 333.2 MiB 0.4 MiB image = Image.open(filepath) 79 337.9 MiB 4.7 MiB image = image.convert('RGB') 80 337.9 MiB 0.0 MiB image = image.resize((image_size, image_size)) 81 337.9 MiB 0.0 MiB data = np.asarray(image) 82 337.9 MiB 0.0 MiB X = [] 83 337.9 MiB 0.0 MiB X.append(data) 84 337.9 MiB 0.0 MiB X = np.array(X) 85 86 #model = load_model('./tongue_cnn_aug.h5') 87 88 341.7 MiB 3.8 MiB result = model.predict([X])[0] 89 341.7 MiB 0.0 MiB predicted = result.argmax() 90 341.7 MiB 0.0 MiB percentage = int(result[predicted] * 100) 91 #K.clear_session() 92 341.7 MiB 0.0 MiB result_title = "" 93 341.7 MiB 0.0 MiB result_content="" 94 341.7 MiB 0.0 MiB result_solution="" 95 96 97 # return render_template('predict.html', result = classes[predicted], result_content = classes_content[predicted], result_solution = classes_solution[predicted], result_title="解析結果") 98 341.8 MiB 0.1 MiB return render_template('predict.html', result = classes[predicted], result_content = classes_content[predicted], result_solution = classes_solution[predicted], result_title="解析結果",img_name=file.filename)

学習済みモデルがどれぐらいメモリを使用しているのかの確認方法が調べても分かりませんでしたので、memory_profilerを使って各行のメモリ使用量を確認してみました。

load_moduleした学習モデル「tongue_cnn_aug.h5」のメモリ使用料の確認方法も教えていただけたらと思います。

訂正依頼でgpuについての言及がありましたが、gpuと当プログラムの関係はなかったものの、もしかしたらメモリが減るのでは?と思い試してみました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

quickquip

2019/10/11 04:30 編集

そもそもモデルが使用するメモリはどのぐらいなのでしょう。 試したこと のところに書いてある記事はGPUの話ですが、質問と関係がありますか?
guest

回答1

0

自己解決

モデルのサイズを小さくしたところ、デプロイすることができました。

投稿2019/11/01 09:00

salmon_0511

総合スコア16

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問