Reputation: 725
I just deployed a Plotly dash app on Heroku. The whole app is working perfectly fine on my local machine but some figures stop showing after I deployed it on the web. Can anyone tell me why is this happening?
This is how the app looks like on the web -
But working fine on my machine -
Some figures are working fine locally as well as on the web -
The code I am using to plot the figure that is not showing-
controls = dbc.Card(
[
# html.H4("Model Input"),
dbc.CardHeader(
"Model Input",
className="bg-primary text-white",
),
html.Br(style={"margin-bottom": "20px"}),
dbc.FormGroup(
[
dbc.Label("Month", size="md"),
dcc.Dropdown(
id="month-selector",
options=[{"label": col, "value": col} for col in month_cols],
value="Month__Sep",
),
],
),
dbc.FormGroup(
[
dbc.Label("Visitor Type", size="md"),
dcc.Dropdown(
id="visitor-type-selector",
options=[{"label": col, "value": col} for col in visitor_type_cols],
value="VisitorType__New_Visitor",
),
],
),
dbc.FormGroup(
[
dbc.Label("Page Value", size="md"),
# dbc.Input(
# id="page-value-input",
# value="37",
# type="text", # passing numbers causing unexpected behaviour
# debounce=True,
# ),
dcc.Slider(
id="page-value-input",
min=0,
max=300,
step=1,
value=10,
marks={
0: "0",
30: "30",
90: "90",
150: "150",
210: "210",
300: "300",
},
),
# dbc.FormText("Enter a value between $0 to $300.", color="secondary"),
],
),
dbc.FormGroup(
[
dbc.Label("Exit Rate", size="md"),
# dbc.Input(
# id="exit-rate-input",
# value="0.03",
# type="text", # passing numbers causing unexpected behaviour
# debounce=True,
# ),
dcc.Slider(
id="exit-rate-input",
min=0.0,
max=1.0,
step=0.01,
value=0.05,
marks={
0: "0",
0.1: "0.1",
0.3: "0.3",
0.5: "0.5",
0.7: "0.7",
0.9: "0.9",
1: "1",
},
),
# dbc.FormText("Enter a value between 0 and 1"),
]
),
dbc.FormGroup(
[
dbc.Label("Bounce Rate", size="md"),
# dbc.Input(
# id="bounce-rate-input",
# value="0",
# type="text", # passing numbers causing unexpected behaviour
# debounce=True,
# ),
dcc.Slider(
id="bounce-rate-input",
min=0.0,
max=1.0,
step=0.01,
value=0.0,
marks={
0: "0",
0.1: "0.1",
0.3: "0.3",
0.5: "0.5",
0.7: "0.7",
0.9: "0.9",
1: "1",
},
),
# dbc.FormText("Enter a value between 0 and 1")
],
),
dbc.FormGroup(
[
dbc.Label("Product Related", size="md"),
# dbc.Input(
# id="product-related-input", value="34", type="text", debounce=True
# ),
dcc.Slider(
id="product-related-input",
min=0,
max=200,
step=1,
value=18,
marks={
0: "0",
30: "30",
60: "60",
90: "90",
150: "150",
200: "200",
},
),
# dbc.FormText(
# "Number of times user visited product related section (0-200).",
# color="secondary",
# ),
],
),
dbc.FormGroup(
[
dbc.Label("Product Related Duration", size="md"),
# dbc.Input(
# id="product-related-duration-input",
# value="80",
# type="text",
# debounce=True,
# ),
dcc.Slider(
id="product-related-duration-input",
min=0,
max=100,
step=1,
value=55,
marks={
0: "0",
10: "10",
20: "20",
30: "30",
60: "60",
100: "100",
},
),
# dbc.FormText(
# "Total Time spent in product related section (0-100 min.)"
# ),
],
),
],
body=True,
# color="primary",
# inverse=True,
)
# Dash app for predicting customer purchasing intention
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.MATERIA])
server = app.server
app.layout = dbc.Container(
[
### first row
html.Br(),
dbc.Row(
[
dbc.Col(
html.H1(
"Online Shoppers Purchasing Intension Prediction",
className="text-center text-primary mb-4",
),
)
],
# style={"margin": "20px"},
),
html.Br(),
### second row
dbc.Row(
[
dbc.Col(
[
html.H4("By Bhola Prasad"),
html.Div(
[
html.Div(
[
html.A(
"Website",
href="https://www.lifewithdata.com/",
target="_blank",
)
]
),
html.Div(
[
html.A(
"LinkedIn",
href="https://www.linkedin.com/in/bhola-prasad-0065834b/",
target="_blank",
)
]
),
html.Div(
[
html.A(
"GitHub",
href="https://github.com/bprasad26/predict-online-shoppers-purchasing-intention",
target="_blank",
)
]
),
]
)
# dcc.Markdown(
# "##### Website - [Life With Data](https://www.lifewithdata.com/)",
# className="mb-4",
# ),
],
)
],
justify="start",
),
html.Br(style={"margin-bottom": "50px"}),
### Third row
dbc.Row(
[
dbc.Col(controls, md=4),
dbc.Col(
[class_output_card, dcc.Graph(id="shap-waterfall-plot")],
md=8,
),
],
# align="center",
),
### Fourth Row
html.Br(style={"margin-bottom": "50px"}),
dbc.Row([dbc.Col(decision_tree_card)]),
### Fifth Row
html.Br(style={"margin-bottom": "50px"}),
dbc.Row(
[dbc.Col(permutation_imp_card, md=5), dbc.Col(feature_imp_card, md=5)],
justify="between",
), # 'start', 'center', 'end', 'around' and 'between'.
],
fluid=True,
)
@app.callback(
Output("shap-waterfall-plot", "figure"),
[
Input("page-value-input", "value"),
Input("exit-rate-input", "value"),
Input("product-related-input", "value"),
Input("product-related-duration-input", "value"),
Input("bounce-rate-input", "value"),
Input("visitor-type-selector", "value"),
Input("month-selector", "value"),
],
)
def shap_waterfall_plot(
PageValues,
ExitRates,
ProductRelated,
ProductRelated_Duration,
BounceRates,
VisitorType,
Month,
):
# load model
model_path = os.path.join(os.getcwd(), "models", "rf_rnd_search1.joblib")
model = joblib.load(open(model_path, "rb"))
visitor_type_index = np.where(X_train_sel.columns == VisitorType)[0][0]
month_index = np.where(X_train_sel.columns == Month)[0][0]
x = np.zeros(len(X_train_sel.columns))
x[0] = float(PageValues)
x[1] = float(ExitRates)
x[2] = float(ProductRelated)
x[3] = float(ProductRelated_Duration)
x[4] = float(BounceRates)
x[visitor_type_index] = 1
x[month_index] = 1
x_series = pd.Series(x, index=cols_to_use)
# create a tree explainer object
explainer = shap.TreeExplainer(model)
# calculate shap values
shap_values = explainer.shap_values(x_series)
fill_color = ["#ff0051" if val >= 0 else "#008bfb" for val in shap_values[1]]
fig = go.Figure()
fig.add_trace(
go.Bar(
x=shap_values[1],
y=cols_to_use,
text=np.round(shap_values[1], 3),
orientation="h",
marker_color=fill_color,
)
)
fig.update_traces(textposition="outside")
fig.update_layout(
yaxis=dict(autorange="reversed"),
xaxis=dict(
title=f"""P(Buy= {np.round(model.predict_proba([x_series])[0][1],2)})
E(Buy= {np.round(explainer.expected_value[1],3)})"""
),
height=600,
template="simple_white",
)
return fig
if __name__ == "__main__":
app.run_server()
The app can be seen on this link - https://customer-purchase-prediction.herokuapp.com/
For reproducing the plots, all the data sets and models can be found in this Github repo - https://github.com/bprasad26/predict-online-shoppers-purchasing-intention
Upvotes: 4
Views: 699
Reputation: 1803
The graphs are not loaded because of following issues.
Steps
Create a runtime.txt file in the root folder add python-3.8.10
Install all the necessary binaries for the Dash Application
heroku buildpacks:add --index 1 heroku/python heroku buildpacks:add --index 2 https://github.com/weibeld/heroku-buildpack-graphviz.git
Remove both numpy and shap version from the requirements file so it will install the latest version and fix the dependency issues with shap
numpy
shap
heroku logs --tail
output streams of all of its running processes, helps in debugging.
Check out the dashboard https://machine-learning-customer.herokuapp.com/
Upvotes: 4