Spaces:
Sleeping
Sleeping
Dacho688 commited on
Commit ·
a2d5210
0
Parent(s):
Initial commit
Browse files- .gitattributes +2 -0
- .gitignore +4 -0
- Dockerfile +7 -0
- README.md +11 -0
- __pycache__/app.cpython-312.pyc +0 -0
- app/__pycache__/forecast.cpython-312.pyc +0 -0
- app/app.py +65 -0
- app/forecast.py +9 -0
- docker-compose.yaml +7 -0
- requirements.txt +25 -0
- sample_ts.csv +121 -0
- sample_ts.xlsx +0 -0
.gitattributes
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Auto detect text files and perform LF normalization
|
| 2 |
+
* text=auto
|
.gitignore
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.env
|
| 2 |
+
.vscode/
|
| 3 |
+
.venv/
|
| 4 |
+
.__pycache__/
|
Dockerfile
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Dockerfile
|
| 2 |
+
FROM python:3.12-slim
|
| 3 |
+
WORKDIR /app
|
| 4 |
+
COPY requirements.txt .
|
| 5 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 6 |
+
COPY ./app .
|
| 7 |
+
CMD ["bokeh", "serve", "--port", "7860", "--allow-websocket-origin=*", "app.py"]
|
README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Auto Forecast Tool
|
| 3 |
+
emoji: 📈
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: gray
|
| 6 |
+
sdk: docker
|
| 7 |
+
app_port: 7860
|
| 8 |
+
pinned: false
|
| 9 |
+
---
|
| 10 |
+
The above yaml frontmatter is required to configure huggingface space.
|
| 11 |
+
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
__pycache__/app.cpython-312.pyc
ADDED
|
Binary file (806 Bytes). View file
|
|
|
app/__pycache__/forecast.cpython-312.pyc
ADDED
|
Binary file (815 Bytes). View file
|
|
|
app/app.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from bokeh.io import curdoc
|
| 2 |
+
from bokeh.models import FileInput, Div, ColumnDataSource, DataTable, TableColumn, TextInput, NumericInput,Button
|
| 3 |
+
from bokeh.layouts import column,row
|
| 4 |
+
from bokeh.plotting import figure
|
| 5 |
+
import base64
|
| 6 |
+
import io
|
| 7 |
+
import pandas as pd
|
| 8 |
+
import forecast
|
| 9 |
+
|
| 10 |
+
#Initialize an empty data source, table, and figure
|
| 11 |
+
source = ColumnDataSource(data={})
|
| 12 |
+
columns = [] # Initially empty, will be built on upload
|
| 13 |
+
data_table = DataTable(source=source, columns=columns, width=300, height=400)
|
| 14 |
+
table_title = Div(text="""<h2>Data Table</h2>""", width=300)
|
| 15 |
+
fig = figure(title = "Auto Forecast Plot",width=1500,height=800)
|
| 16 |
+
fig.title.text_font_style = 'bold'
|
| 17 |
+
fig.title.text_color = 'black'
|
| 18 |
+
fig.title.text_font_size = '14pt'
|
| 19 |
+
fig.title.align = 'center'
|
| 20 |
+
#Create bokeh objects
|
| 21 |
+
title = Div(text="""
|
| 22 |
+
<div style="text-align: center; width: 100%;">
|
| 23 |
+
<h1>Auto Forecast Tool</h1>
|
| 24 |
+
</div>
|
| 25 |
+
""", width=1800,align='center',sizing_mode='stretch_width')
|
| 26 |
+
status_msg = Div(text = "<b>STATUS:</b> Ready")
|
| 27 |
+
file_input = FileInput(accept=".csv",title="Upload Time Series Data as CSV")
|
| 28 |
+
seasonality = NumericInput(value=1,title="Number of periods in season? Enter 1 if no seasonality.", mode='int')
|
| 29 |
+
n_ahead = NumericInput(value=12,title="Number of periods to forecast?", mode='int')
|
| 30 |
+
column_name = TextInput(title="Column name to forecast?")
|
| 31 |
+
forecast = Button(label="Auto Forecast")
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def update_status():
|
| 35 |
+
#Update status
|
| 36 |
+
status_msg.text = "<b>STATUS:</b> Running......"
|
| 37 |
+
curdoc().add_next_tick_callback(upload_callback)
|
| 38 |
+
|
| 39 |
+
def upload_callback():
|
| 40 |
+
# Decode upload, save to memory, and read in as df
|
| 41 |
+
decoded = base64.b64decode(file_input.value)
|
| 42 |
+
file = io.BytesIO(decoded)
|
| 43 |
+
df = pd.read_csv(file)
|
| 44 |
+
|
| 45 |
+
# Make forecasts and append to df
|
| 46 |
+
forecasts = forecast.forecast(df,column_name.value,seasonality.value,n_ahead.value)
|
| 47 |
+
new_data = pd.DataFrame()
|
| 48 |
+
new_data['Forecasts'] = forecasts
|
| 49 |
+
df = pd.concat([df, new_data], ignore_index=True).reset_index()
|
| 50 |
+
|
| 51 |
+
#Update the data source
|
| 52 |
+
source.data = df.to_dict('list')
|
| 53 |
+
#Update the columns based on the new file's headers
|
| 54 |
+
data_table.columns = [TableColumn(field=col, title=col) for col in df.columns]
|
| 55 |
+
|
| 56 |
+
#Update figure with all data
|
| 57 |
+
fig.line(x='index',y= 'Sales',source=source,line_width=2)
|
| 58 |
+
fig.line(x='index',y= 'Forecasts',source=source,line_width=2,line_color='Red')
|
| 59 |
+
#Update status
|
| 60 |
+
status_msg.text = "<b>STATUS:</b> Complete!"
|
| 61 |
+
|
| 62 |
+
forecast.on_click(update_status)
|
| 63 |
+
|
| 64 |
+
layout = column(row(title, align='center'),row(column(status_msg,file_input, seasonality, n_ahead, column_name,forecast, table_title, data_table),fig),sizing_mode='stretch_both')
|
| 65 |
+
curdoc().add_root(layout)
|
app/forecast.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pmdarima import auto_arima
|
| 2 |
+
import pandas as pd
|
| 3 |
+
|
| 4 |
+
def forecast(df, column_name: str, seasonality: int, ahead: int):
|
| 5 |
+
data = df[column_name]
|
| 6 |
+
oos = round(len(data) * .1)
|
| 7 |
+
model = auto_arima(data,m = seasonality, max_order = 10, information_criterion = 'oob', stepwise = False, out_of_sample_size = oos, scoring = 'mse')
|
| 8 |
+
forecasts = model.predict(ahead,return_conf_int = False)
|
| 9 |
+
return forecasts
|
docker-compose.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
services:
|
| 2 |
+
app:
|
| 3 |
+
build: .
|
| 4 |
+
container_name: AutoForecast
|
| 5 |
+
restart: unless-stopped
|
| 6 |
+
ports:
|
| 7 |
+
- "7860:7860"
|
requirements.txt
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
bokeh==3.9.0
|
| 2 |
+
contourpy==1.3.3
|
| 3 |
+
Cython==3.2.4
|
| 4 |
+
Jinja2==3.1.6
|
| 5 |
+
joblib==1.5.3
|
| 6 |
+
MarkupSafe==3.0.3
|
| 7 |
+
narwhals==2.18.1
|
| 8 |
+
numpy==2.4.4
|
| 9 |
+
packaging==26.0
|
| 10 |
+
pandas==3.0.2
|
| 11 |
+
patsy==1.0.2
|
| 12 |
+
pillow==12.2.0
|
| 13 |
+
pmdarima==2.1.1
|
| 14 |
+
python-dateutil==2.9.0.post0
|
| 15 |
+
PyYAML==6.0.3
|
| 16 |
+
scikit-learn==1.8.0
|
| 17 |
+
scipy==1.17.1
|
| 18 |
+
setuptools==82.0.1
|
| 19 |
+
six==1.17.0
|
| 20 |
+
statsmodels==0.14.6
|
| 21 |
+
threadpoolctl==3.6.0
|
| 22 |
+
tornado==6.5.5
|
| 23 |
+
tzdata==2026.1
|
| 24 |
+
urllib3==2.6.3
|
| 25 |
+
xyzservices==2026.3.0
|
sample_ts.csv
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Sales
|
| 2 |
+
25.43
|
| 3 |
+
25.40261631
|
| 4 |
+
25.25921236
|
| 5 |
+
25.37212214
|
| 6 |
+
25.59537742
|
| 7 |
+
25.71449737
|
| 8 |
+
25.83492987
|
| 9 |
+
26.06598132
|
| 10 |
+
26.24807293
|
| 11 |
+
26.29073998
|
| 12 |
+
26.47911422
|
| 13 |
+
26.64143188
|
| 14 |
+
26.54648005
|
| 15 |
+
26.20449163
|
| 16 |
+
26.15804831
|
| 17 |
+
26.34006063
|
| 18 |
+
26.65306602
|
| 19 |
+
26.67016132
|
| 20 |
+
26.86504956
|
| 21 |
+
26.45487684
|
| 22 |
+
26.28864757
|
| 23 |
+
26.24155545
|
| 24 |
+
25.98584189
|
| 25 |
+
26.19768115
|
| 26 |
+
25.99336282
|
| 27 |
+
25.7098198
|
| 28 |
+
25.40067164
|
| 29 |
+
25.49413624
|
| 30 |
+
25.86170657
|
| 31 |
+
25.57582803
|
| 32 |
+
25.45306549
|
| 33 |
+
25.19219256
|
| 34 |
+
25.69617506
|
| 35 |
+
25.74281787
|
| 36 |
+
25.76476699
|
| 37 |
+
26.10184043
|
| 38 |
+
26.17668546
|
| 39 |
+
25.96149588
|
| 40 |
+
25.96916466
|
| 41 |
+
26.34714157
|
| 42 |
+
26.71505289
|
| 43 |
+
27.21283004
|
| 44 |
+
27.59688634
|
| 45 |
+
27.18419775
|
| 46 |
+
27.42551023
|
| 47 |
+
27.9160403
|
| 48 |
+
28.14207525
|
| 49 |
+
28.25457145
|
| 50 |
+
28.4948408
|
| 51 |
+
28.53134638
|
| 52 |
+
27.99483363
|
| 53 |
+
28.19582371
|
| 54 |
+
28.03514658
|
| 55 |
+
27.94852817
|
| 56 |
+
27.70558018
|
| 57 |
+
28.21989493
|
| 58 |
+
28.22234232
|
| 59 |
+
28.11163131
|
| 60 |
+
28.39043792
|
| 61 |
+
28.76427468
|
| 62 |
+
28.77743576
|
| 63 |
+
28.81627813
|
| 64 |
+
28.90543479
|
| 65 |
+
28.96039756
|
| 66 |
+
29.27505977
|
| 67 |
+
29.53442255
|
| 68 |
+
29.47826423
|
| 69 |
+
30.24456748
|
| 70 |
+
30.28091309
|
| 71 |
+
29.35889895
|
| 72 |
+
29.61603448
|
| 73 |
+
29.62164427
|
| 74 |
+
29.20166099
|
| 75 |
+
28.98293796
|
| 76 |
+
29.52118563
|
| 77 |
+
28.8210753
|
| 78 |
+
28.86790893
|
| 79 |
+
29.52749068
|
| 80 |
+
29.27976979
|
| 81 |
+
29.14817396
|
| 82 |
+
28.815914
|
| 83 |
+
28.54500723
|
| 84 |
+
28.07540091
|
| 85 |
+
28.05535895
|
| 86 |
+
27.82826507
|
| 87 |
+
28.07305168
|
| 88 |
+
28.28592037
|
| 89 |
+
28.31924593
|
| 90 |
+
28.16129611
|
| 91 |
+
27.98713574
|
| 92 |
+
28.46008467
|
| 93 |
+
27.97933622
|
| 94 |
+
28.10981219
|
| 95 |
+
28.14902559
|
| 96 |
+
28.2020732
|
| 97 |
+
28.36939803
|
| 98 |
+
28.1405316
|
| 99 |
+
28.43986795
|
| 100 |
+
28.24326799
|
| 101 |
+
27.83816661
|
| 102 |
+
28.07991496
|
| 103 |
+
28.26620122
|
| 104 |
+
28.6233578
|
| 105 |
+
28.64521264
|
| 106 |
+
28.28176018
|
| 107 |
+
28.65605903
|
| 108 |
+
28.46357256
|
| 109 |
+
28.62236099
|
| 110 |
+
28.97059124
|
| 111 |
+
28.43462732
|
| 112 |
+
28.29492653
|
| 113 |
+
28.49375449
|
| 114 |
+
28.6629355
|
| 115 |
+
28.25693418
|
| 116 |
+
28.19665076
|
| 117 |
+
28.09894706
|
| 118 |
+
28.29157087
|
| 119 |
+
28.16400833
|
| 120 |
+
28.49138934
|
| 121 |
+
28.82024867
|
sample_ts.xlsx
ADDED
|
Binary file (11.7 kB). View file
|
|
|