import os
import json
import numpy as np
import pandas as pd
from prophet import Prophet
from prophet.serialize import model_to_json
from ibm_watson_machine_learning import APIClient
# setting env variable because of, INFO:numexpr.utils:Note: NumExpr detected 16 cores but "NUMEXPR_MAX_THREADS" not set
os.environ["NUMEXPR_MAX_THREADS"] = "8"
# setup your wml credentials
wml_credentials = {
"token": os.environ["USER_ACCESS_TOKEN"],
"instance_id" : "openshift",
"url": "",
"version": "4.0"
}
client = APIClient(wml_credentials)
SPACE_ID = "04e8a238-2da0-47be-a48f-894bd8f9c5cb"
client.set.default_space(SPACE_ID)
'SUCCESS'
# import logging
# logging.basicConfig()
# logging.getLogger().setLevel(logging.WARN)
! wget --quiet https://raw.githubusercontent.com/facebook/prophet/main/examples/example_wp_log_peyton_manning.csv
df = pd.read_csv("example_wp_log_peyton_manning.csv")
df
ds | y | |
---|---|---|
0 | 2007-12-10 | 9.590761 |
1 | 2007-12-11 | 8.519590 |
2 | 2007-12-12 | 8.183677 |
3 | 2007-12-13 | 8.072467 |
4 | 2007-12-14 | 7.893572 |
... | ... | ... |
2900 | 2016-01-16 | 7.817223 |
2901 | 2016-01-17 | 9.273878 |
2902 | 2016-01-18 | 10.333775 |
2903 | 2016-01-19 | 9.125871 |
2904 | 2016-01-20 | 8.891374 |
2905 rows × 2 columns
m = Prophet(daily_seasonality=True)
m.fit(df)
future = m.make_future_dataframe(periods=365)
future.tail()
ds | |
---|---|
3265 | 2017-01-15 |
3266 | 2017-01-16 |
3267 | 2017-01-17 |
3268 | 2017-01-18 |
3269 | 2017-01-19 |
forecast = m.predict(future)
forecast[["ds", "yhat", "yhat_lower", "yhat_upper"]].tail()
ds | yhat | yhat_lower | yhat_upper | |
---|---|---|---|---|
3265 | 2017-01-15 | 8.210927 | 7.470130 | 8.968077 |
3266 | 2017-01-16 | 8.535940 | 7.830036 | 9.213891 |
3267 | 2017-01-17 | 8.323352 | 7.627969 | 9.046245 |
3268 | 2017-01-18 | 8.156000 | 7.353956 | 8.950303 |
3269 | 2017-01-19 | 8.167942 | 7.450133 | 8.930495 |
fig1 = m.plot(forecast)
fig2 = m.plot_components(forecast)
with open("prophet-model.json", "w") as f:
json.dump(model_to_json(m), f)
There are many ways of persisting the serialized json model such as, but not limited to, saving the json output to,
serialized_model = model_to_json(m)
Using WML API to create a custom environment. You can also create and deploy a custom environment using the user interface (refer to blog post).
ENV_NAME = "Prophet Custom Env"
config_yaml = """
channels:
- conda-forge
dependencies:
- prophet
"""
with open("config.yaml", "w", encoding="utf-8") as f:
f.write(config_yaml)
meta_props = {
client.package_extensions.ConfigurationMetaNames.NAME: ENV_NAME,
client.package_extensions.ConfigurationMetaNames.TYPE: "conda_yml"
}
package_ext_details = client.package_extensions.store(meta_props=meta_props, file_path="config.yaml")
package_ext_uid = client.package_extensions.get_uid(package_ext_details)
meta_props = {
client.software_specifications.ConfigurationMetaNames.NAME: ENV_NAME,
client.software_specifications.ConfigurationMetaNames.BASE_SOFTWARE_SPECIFICATION: {"guid": client.software_specifications.get_uid_by_name("default_py3.8")},
}
software_spec_details = client.software_specifications.store(meta_props=meta_props)
software_spec_uid = client.software_specifications.get_uid(software_spec_details)
client.software_specifications.add_package_extension(software_spec_uid, package_ext_uid)
software_spec_details = client.software_specifications.get_details(software_spec_uid)
software_spec_uid = client.software_specifications.get_uid(software_spec_details)
Creating package extensions SUCCESS SUCCESS
FUNCTION_NAME = "Prophet Model"
FUNCTION_DEPLOYMENT_NAME = "Prophet Model Deployment"
# function to be deployed
def func():
# inference function that will be called
def score(payload):
# import the necessary packages
import numpy as np
import pandas as pd
from prophet import Prophet
from prophet.serialize import model_from_json
# read serialized json model from payload
serialized_model = payload["input_data"][0]["serialized_model"]
# load model from serialized json
m = model_from_json(serialized_model)
# data from payload
data = payload["input_data"][0]["values"]
# prepare predict dataframe
df = pd.DataFrame({"ds": pd.to_datetime(np.array(data).flatten(), unit="ns")})
forecast = m.predict(df)
forecast["ds"] = forecast["ds"].values.astype(np.int64) // 10 ** 9
return {"predictions": [{
"fields": forecast.columns.tolist(),
"values": forecast.values.tolist()
}]}
return score
payload = {
"input_data": [{
"serialized_model": serialized_model,
"values": future.values.tolist()
}]
}
function_result = func()(payload)["predictions"][0]
forecast = pd.DataFrame(function_result["values"], columns=function_result["fields"])
forecast.head()
ds | trend | yhat_lower | yhat_upper | trend_lower | trend_upper | additive_terms | additive_terms_lower | additive_terms_upper | daily | ... | weekly | weekly_lower | weekly_upper | yearly | yearly_lower | yearly_upper | multiplicative_terms | multiplicative_terms_lower | multiplicative_terms_upper | yhat | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1.197245e+09 | 9.264771 | 8.251444 | 9.506362 | 9.264771 | 9.264771 | -0.424653 | -0.424653 | -0.424653 | -1.227689 | ... | 0.352289 | 0.352289 | 0.352289 | 0.450747 | 0.450747 | 0.450747 | 0.0 | 0.0 | 0.0 | 8.840118 |
1 | 1.197331e+09 | 9.263239 | 7.983581 | 9.228102 | 9.263239 | 9.263239 | -0.674560 | -0.674560 | -0.674560 | -1.227689 | ... | 0.119623 | 0.119623 | 0.119623 | 0.433506 | 0.433506 | 0.433506 | 0.0 | 0.0 | 0.0 | 8.588679 |
2 | 1.197418e+09 | 9.261708 | 7.779824 | 9.029851 | 9.261708 | 9.261708 | -0.877153 | -0.877153 | -0.877153 | -1.227689 | ... | -0.066665 | -0.066665 | -0.066665 | 0.417201 | 0.417201 | 0.417201 | 0.0 | 0.0 | 0.0 | 8.384555 |
3 | 1.197504e+09 | 9.260176 | 7.729681 | 8.978530 | 9.260176 | 9.260176 | -0.897682 | -0.897682 | -0.897682 | -1.227689 | ... | -0.072267 | -0.072267 | -0.072267 | 0.402274 | 0.402274 | 0.402274 | 0.0 | 0.0 | 0.0 | 8.362494 |
4 | 1.197590e+09 | 9.258645 | 7.715851 | 8.922145 | 9.258645 | 9.258645 | -0.908126 | -0.908126 | -0.908126 | -1.227689 | ... | -0.069569 | -0.069569 | -0.069569 | 0.389132 | 0.389132 | 0.389132 | 0.0 | 0.0 | 0.0 | 8.350519 |
5 rows × 22 columns
meta_props = {
client.repository.FunctionMetaNames.NAME: FUNCTION_NAME,
client.repository.FunctionMetaNames.SOFTWARE_SPEC_UID: software_spec_uid, # client.software_specifications.get_id_by_name(ENV_NAME)
}
function_details = client.repository.store_function(meta_props=meta_props, function=func)
meta_props = {
client.deployments.ConfigurationMetaNames.NAME: FUNCTION_DEPLOYMENT_NAME,
client.deployments.ConfigurationMetaNames.ONLINE: {}
}
function_uid = client.repository.get_function_uid(function_details)
function_deployment_details = client.deployments.create(function_uid, meta_props=meta_props)
function_deployment_uid = client.deployments.get_uid(function_deployment_details)
####################################################################################### Synchronous deployment creation for uid: 'd0feeae9-d1d0-45aa-8494-ccc709ae48a3' started ####################################################################################### initializing Note: online_url is deprecated and will be removed in a future release. Use serving_urls instead. ..................................................................... ready ------------------------------------------------------------------------------------------------ Successfully finished deployment creation, deployment_uid='ef957cd3-6fc1-4406-b360-b22c7fe5ceaf' ------------------------------------------------------------------------------------------------
The below output should be the same as the earlier Prophet model.
payload = {
"input_data": [{
"serialized_model": serialized_model,
"values": future.values.tolist() # feel free to change to your desired forecast horizon
}]
}
function_result = client.deployments.score(function_deployment_uid, payload)["predictions"][0]
forecast = pd.DataFrame(function_result["values"], columns=function_result["fields"])
forecast["ds"] = pd.to_datetime(forecast["ds"], unit="s")
forecast.head()
ds | trend | yhat_lower | yhat_upper | trend_lower | trend_upper | additive_terms | additive_terms_lower | additive_terms_upper | daily | ... | weekly | weekly_lower | weekly_upper | yearly | yearly_lower | yearly_upper | multiplicative_terms | multiplicative_terms_lower | multiplicative_terms_upper | yhat | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2007-12-10 | 9.264771 | 8.171276 | 9.404913 | 9.264771 | 9.264771 | -0.424653 | -0.424653 | -0.424653 | -1.227689 | ... | 0.352289 | 0.352289 | 0.352289 | 0.450747 | 0.450747 | 0.450747 | 0.0 | 0.0 | 0.0 | 8.840118 |
1 | 2007-12-11 | 9.263239 | 8.015035 | 9.206857 | 9.263239 | 9.263239 | -0.674560 | -0.674560 | -0.674560 | -1.227689 | ... | 0.119623 | 0.119623 | 0.119623 | 0.433506 | 0.433506 | 0.433506 | 0.0 | 0.0 | 0.0 | 8.588679 |
2 | 2007-12-12 | 9.261708 | 7.771087 | 9.021837 | 9.261708 | 9.261708 | -0.877153 | -0.877153 | -0.877153 | -1.227689 | ... | -0.066665 | -0.066665 | -0.066665 | 0.417201 | 0.417201 | 0.417201 | 0.0 | 0.0 | 0.0 | 8.384555 |
3 | 2007-12-13 | 9.260176 | 7.727514 | 8.951958 | 9.260176 | 9.260176 | -0.897682 | -0.897682 | -0.897682 | -1.227689 | ... | -0.072267 | -0.072267 | -0.072267 | 0.402274 | 0.402274 | 0.402274 | 0.0 | 0.0 | 0.0 | 8.362494 |
4 | 2007-12-14 | 9.258645 | 7.712199 | 9.012810 | 9.258645 | 9.258645 | -0.908126 | -0.908126 | -0.908126 | -1.227689 | ... | -0.069569 | -0.069569 | -0.069569 | 0.389132 | 0.389132 | 0.389132 | 0.0 | 0.0 | 0.0 | 8.350519 |
5 rows × 22 columns
fig1 = m.plot(forecast)
fig2 = m.plot_components(forecast)
# Clean up everything
# import requests
# response = requests.get(client.service_instance._href_definitions.get_pkg_extns_href(), params=client._params(), headers=client._get_headers(), verify=False)
# for x in response.json()["resources"]:
# client.package_extensions.delete(x["metadata"]["asset_id"])
# for x in client.software_specifications.get_details()["resources"]:
# if x["entity"]["software_specification"]["type"] == "derived":
# client.software_specifications.delete(x["metadata"]["asset_id"])
# for function in client.deployments.get_details()["resources"]: client.deployments.delete(function["metadata"]["id"])
# for function in client.repository.get_function_details()["resources"]: client.repository.delete(function["metadata"]["id"])