将 PySpark 管道保存到 PMML 并使用 Flask 进行部署(应要求在应用程序中出现错误)
Save PySpark Pipeline to PMML and Deploy It Using Flask (ERROR in app upon request)
我一直在尝试寻找一种方法来将训练有素的 PySpark 管道部署为 API,最终我将 Flask 和 PMML 作为可能的解决方案。
据我所知,PMML 文件的生成工作正常:我使用 ParamGridBuilder 训练管道,获得最佳模型,并将其输出为 .pmml 文件。
但是,当我将生成的文件加载到 Flask 中时出现了问题。我能够得到 API 运行 就好了;但是,当我向它发送请求时,我并没有得到预期的结果(文本中包含的情绪),而是出现以下错误。
[2020-03-02 17:05:15,831] ERROR in app: Exception on /sentiment_analysis [GET]
Traceback (most recent call last):
File "/home/users/anaconda3/lib/python3.6/site-packages/flask/app.py", line 2446, in wsgi_app
response = self.full_dispatch_request()
File "/home/users/anaconda3/lib/python3.6/site-packages/flask/app.py", line 1951, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/users/anaconda3/lib/python3.6/site-packages/flask/app.py", line 1820, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/users/anaconda3/lib/python3.6/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/users/anaconda3/lib/python3.6/site-packages/flask/app.py", line 1949, in full_dispatch_request
rv = self.dispatch_request()
File "/home/users/anaconda3/lib/python3.6/site-packages/flask/app.py", line 1935, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/users/sentiment_analysis.py", line 59, in hello_world
resultado = evaluator.evaluate(df)
File "/home/users/.local/lib/python3.6/site-packages/jpmml_evaluator/__init__.py", line 80, in evaluate
javaArguments = self.backend.dict2map(arguments)
File "/home/users/.local/lib/python3.6/site-packages/jpmml_evaluator/pyjnius.py", line 31, in dict2map
raise ValueError()
ValueError
127.0.0.1 - - [02/Mar/2020 17:05:15] "GET /sentiment_analysis?text=test HTTP/1.1" 500 -
以下是涉及的软件和软件包的版本:
- Python 3.6.4
- Spark 2.4.4
- pyspark2pmml 0.5.1
- jpmml_evaluator 0.2.3
- 烧瓶 1.1.1
- pyspark 2.4.4
此外,下面是我用来将模型加载到 Flask 中的 Python 代码。
from flask import Flask, request
import pandas as pd
from jpmml_evaluator import make_evaluator, pyjnius
app = Flask('sentiment_analysis')
@app.route("/sentiment_analysis")
def hello_world():
text = request.args.get('text')
pyjnius.jnius_configure_classpath()
backend = pyjnius.PyJNIusBackend()
evaluator = make_evaluator(backend, "test.pmml") \
.verify()
df = pd.DataFrame(columns=["TWEET"], data=[[text]])
result = evaluator.evaluate(df)
sentiment = result.collect()[0]['prediction']
if int(sentiment) == 0:
sentiment = 'negative'
else:
sentiment = 'positive'
return 'The sentiment is: ' + sentiment, 200
app.run(host='0.0.0.0', port=5001)
有人知道这里出了什么问题吗?
您的参数 DataFrame
包含复杂的列类型;您选择的 Java 后端 (PyJNIus) 不知道如何将此 Python 值映射到 Java 值。
如果您想继续使用自己动手的 Flask API 方式,可以尝试以下方法:
- 更新
jpmml_evaluator
包到最新。 0.2.3之后新增了数值转换。较新的包版本应该会准确地告诉您有问题的列类型是什么。查看jpmml_evaluator.pyjnius.dict2map
方法的源代码。
- 选择不同的 Java 后端。具体来说,尝试用 Py4J 替换 PyJNIus。
- 在您的 Python 代码中用更简单的内容替换复杂的列类型。
综合考虑,使用 Openscoring REST Web 服务为 PySpark 模型提供服务会更好。有一个关于 deploying Apache Spark ML pipeline models as a REST web service 的最新教程。
我一直在尝试寻找一种方法来将训练有素的 PySpark 管道部署为 API,最终我将 Flask 和 PMML 作为可能的解决方案。
据我所知,PMML 文件的生成工作正常:我使用 ParamGridBuilder 训练管道,获得最佳模型,并将其输出为 .pmml 文件。
但是,当我将生成的文件加载到 Flask 中时出现了问题。我能够得到 API 运行 就好了;但是,当我向它发送请求时,我并没有得到预期的结果(文本中包含的情绪),而是出现以下错误。
[2020-03-02 17:05:15,831] ERROR in app: Exception on /sentiment_analysis [GET]
Traceback (most recent call last):
File "/home/users/anaconda3/lib/python3.6/site-packages/flask/app.py", line 2446, in wsgi_app
response = self.full_dispatch_request()
File "/home/users/anaconda3/lib/python3.6/site-packages/flask/app.py", line 1951, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/users/anaconda3/lib/python3.6/site-packages/flask/app.py", line 1820, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/users/anaconda3/lib/python3.6/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/users/anaconda3/lib/python3.6/site-packages/flask/app.py", line 1949, in full_dispatch_request
rv = self.dispatch_request()
File "/home/users/anaconda3/lib/python3.6/site-packages/flask/app.py", line 1935, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/users/sentiment_analysis.py", line 59, in hello_world
resultado = evaluator.evaluate(df)
File "/home/users/.local/lib/python3.6/site-packages/jpmml_evaluator/__init__.py", line 80, in evaluate
javaArguments = self.backend.dict2map(arguments)
File "/home/users/.local/lib/python3.6/site-packages/jpmml_evaluator/pyjnius.py", line 31, in dict2map
raise ValueError()
ValueError
127.0.0.1 - - [02/Mar/2020 17:05:15] "GET /sentiment_analysis?text=test HTTP/1.1" 500 -
以下是涉及的软件和软件包的版本:
- Python 3.6.4
- Spark 2.4.4
- pyspark2pmml 0.5.1
- jpmml_evaluator 0.2.3
- 烧瓶 1.1.1
- pyspark 2.4.4
此外,下面是我用来将模型加载到 Flask 中的 Python 代码。
from flask import Flask, request
import pandas as pd
from jpmml_evaluator import make_evaluator, pyjnius
app = Flask('sentiment_analysis')
@app.route("/sentiment_analysis")
def hello_world():
text = request.args.get('text')
pyjnius.jnius_configure_classpath()
backend = pyjnius.PyJNIusBackend()
evaluator = make_evaluator(backend, "test.pmml") \
.verify()
df = pd.DataFrame(columns=["TWEET"], data=[[text]])
result = evaluator.evaluate(df)
sentiment = result.collect()[0]['prediction']
if int(sentiment) == 0:
sentiment = 'negative'
else:
sentiment = 'positive'
return 'The sentiment is: ' + sentiment, 200
app.run(host='0.0.0.0', port=5001)
有人知道这里出了什么问题吗?
您的参数 DataFrame
包含复杂的列类型;您选择的 Java 后端 (PyJNIus) 不知道如何将此 Python 值映射到 Java 值。
如果您想继续使用自己动手的 Flask API 方式,可以尝试以下方法:
- 更新
jpmml_evaluator
包到最新。 0.2.3之后新增了数值转换。较新的包版本应该会准确地告诉您有问题的列类型是什么。查看jpmml_evaluator.pyjnius.dict2map
方法的源代码。 - 选择不同的 Java 后端。具体来说,尝试用 Py4J 替换 PyJNIus。
- 在您的 Python 代码中用更简单的内容替换复杂的列类型。
综合考虑,使用 Openscoring REST Web 服务为 PySpark 模型提供服务会更好。有一个关于 deploying Apache Spark ML pipeline models as a REST web service 的最新教程。