process-improve 0.9.76__tar.gz → 0.9.78__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {process_improve-0.9.76/process_improve.egg-info → process_improve-0.9.78}/PKG-INFO +3 -7
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/__init__.py +0 -2
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/datasets.py +1 -1
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/designs_factorial.py +1 -1
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/models.py +1 -1
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/plotting.py +1 -1
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/simulations.py +3 -3
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/structures.py +1 -1
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/multivariate/methods.py +1 -1
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/multivariate/plots.py +1 -1
- process_improve-0.9.78/process_improve/notebooks_examples/batch/batch_llm.py +245 -0
- process_improve-0.9.78/process_improve/notebooks_examples/batch/batch_llm_multivariate.py +202 -0
- process_improve-0.9.78/process_improve/notebooks_examples/batch/batch_music.py +186 -0
- process_improve-0.9.78/process_improve/notebooks_examples/experiments/case-studies.py +847 -0
- process_improve-0.9.78/process_improve/notebooks_examples/multivariate/pca_example.py +53 -0
- process_improve-0.9.78/process_improve/univariate/__init__.py +0 -0
- process_improve-0.9.78/process_improve/visualization/plots.py +19 -0
- {process_improve-0.9.76 → process_improve-0.9.78/process_improve.egg-info}/PKG-INFO +3 -7
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve.egg-info/SOURCES.txt +7 -1
- {process_improve-0.9.76 → process_improve-0.9.78}/pyproject.toml +2 -1
- {process_improve-0.9.76 → process_improve-0.9.78}/tests/test_multivariate.py +1 -1
- process_improve-0.9.76/setup.py +0 -50
- {process_improve-0.9.76 → process_improve-0.9.78}/LICENSE +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/MANIFEST.in +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/README.md +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/batch/__init__.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/batch/alignment_helpers.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/batch/data_input.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/batch/features.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/batch/plotting.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/batch/preprocessing.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/bivariate/__init__.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/bivariate/methods.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/batch/batch-fake-data.csv +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/batch/details.txt +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/batch/dryer.csv +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/batch/nylon.csv +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/experiments/test_doe1.csv +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/monitoring/batch-yield-and-purity.csv +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/monitoring/rubber-colour.csv +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/C.csv +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/Hotellings_T2_A3.csv +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/Hotellings_T2_A6.csv +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/LDPE.csv +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/P.csv +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/R.csv +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/T.csv +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/U.csv +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/W.csv +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/Yhat_A6.csv +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/kamyr.csv +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/tablet-spectra.csv +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/__init__.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/optimal.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/optimization.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/monitoring/__init__.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/monitoring/control_charts.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/monitoring/metrics.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/multivariate/__init__.py +0 -0
- {process_improve-0.9.76/process_improve/regression → process_improve-0.9.78/process_improve/notebooks_examples/batch}/__init__.py +0 -0
- {process_improve-0.9.76/process_improve/univariate → process_improve-0.9.78/process_improve/regression}/__init__.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/regression/methods.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/univariate/metrics.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve.egg-info/dependency_links.txt +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve.egg-info/requires.txt +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/process_improve.egg-info/top_level.txt +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/setup.cfg +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/tests/test_bivariate.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/tests/test_doe.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/tests/test_monitoring.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/tests/test_regression.py +0 -0
- {process_improve-0.9.76 → process_improve-0.9.78}/tests/test_univariate.py +0 -0
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: process-improve
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.78
|
|
4
4
|
Summary: Designed Experiments; Latent Variables (PCA, PLS, multivariate methods with missing data); Process Monitoring; Batch data analysis.
|
|
5
|
-
Home-page: https://github.com/kgdunn/process_improve
|
|
6
|
-
Author: Kevin Dunn
|
|
7
5
|
Author-email: Kevin Dunn <kgdunn@gmail.com>
|
|
6
|
+
License: MIT license
|
|
8
7
|
Project-URL: Homepage, https://github.com/kgdunn/process_improve
|
|
9
8
|
Project-URL: Repository, https://github.com/kgdunn/process_improve
|
|
10
9
|
Project-URL: Issues, https://github.com/kgdunn/process_improve/issues
|
|
11
10
|
Keywords: Designed Experiments,Latent Variables,PCA,PLS,Multivariate Data Analysis,Batch data analysis
|
|
12
|
-
Requires-Python: >=3.
|
|
11
|
+
Requires-Python: >=3.11
|
|
13
12
|
Description-Content-Type: text/markdown
|
|
14
13
|
License-File: LICENSE
|
|
15
14
|
Requires-Dist: bokeh>=3.6.3
|
|
@@ -26,9 +25,6 @@ Requires-Dist: scikit-learn>=1.6.1
|
|
|
26
25
|
Requires-Dist: seaborn>=0.13.2
|
|
27
26
|
Requires-Dist: statsmodels>=0.14.4
|
|
28
27
|
Requires-Dist: tqdm>=4.67.1
|
|
29
|
-
Dynamic: author
|
|
30
|
-
Dynamic: home-page
|
|
31
|
-
Dynamic: requires-python
|
|
32
28
|
|
|
33
29
|
# Process Improvement (using Data)
|
|
34
30
|
|
{process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/simulations.py
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# (c) Kevin Dunn, 2010-
|
|
1
|
+
# (c) Kevin Dunn, 2010-2025. MIT License. Based on own private work over the years.
|
|
2
2
|
|
|
3
3
|
import pandas as pd
|
|
4
4
|
from numpy.random import normal
|
|
@@ -30,7 +30,7 @@ def popcorn(t=120, T=None):
|
|
|
30
30
|
|
|
31
31
|
Source
|
|
32
32
|
------
|
|
33
|
-
Kevin Dunn, Process Improvement using Data, Chapter 5, 2010 to
|
|
33
|
+
Kevin Dunn, Process Improvement using Data, Chapter 5, 2010 to 2025,
|
|
34
34
|
https://learnche.org/pid
|
|
35
35
|
|
|
36
36
|
|
|
@@ -70,7 +70,7 @@ def grocery(p=3.46, h=150, P=None, H=None):
|
|
|
70
70
|
|
|
71
71
|
Source
|
|
72
72
|
------
|
|
73
|
-
Kevin Dunn, Process Improvement using Data, Chapter 5, 2010 to
|
|
73
|
+
Kevin Dunn, Process Improvement using Data, Chapter 5, 2010 to 2025,
|
|
74
74
|
https://learnche.org/pid
|
|
75
75
|
|
|
76
76
|
"""
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# ---
|
|
2
|
+
# jupyter:
|
|
3
|
+
# jupytext:
|
|
4
|
+
# cell_metadata_filter: -all
|
|
5
|
+
# custom_cell_magics: kql
|
|
6
|
+
# text_representation:
|
|
7
|
+
# extension: .py
|
|
8
|
+
# format_name: percent
|
|
9
|
+
# format_version: '1.3'
|
|
10
|
+
# jupytext_version: 1.11.2
|
|
11
|
+
# kernelspec:
|
|
12
|
+
# display_name: process-improve
|
|
13
|
+
# language: python
|
|
14
|
+
# name: python3
|
|
15
|
+
# ---
|
|
16
|
+
|
|
17
|
+
# %%
|
|
18
|
+
# !pip install git+https://github.com/amazon-science/chronos-forecasting.git
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# %%
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import os
|
|
25
|
+
import pathlib
|
|
26
|
+
import sys
|
|
27
|
+
|
|
28
|
+
import numpy as np
|
|
29
|
+
import pandas as pd
|
|
30
|
+
import plotly.graph_objects as go
|
|
31
|
+
import torch
|
|
32
|
+
from chronos import ChronosPipeline
|
|
33
|
+
|
|
34
|
+
# Some basic checks, and logging set up.
|
|
35
|
+
while not str(pathlib.Path.cwd().name).lower().startswith("process-improve"):
|
|
36
|
+
os.chdir(pathlib.Path.cwd().parents[0])
|
|
37
|
+
basecwd = pathlib.Path.cwd()
|
|
38
|
+
sys.path.insert(0, str(basecwd))
|
|
39
|
+
assert basecwd.exists()
|
|
40
|
+
|
|
41
|
+
import process_improve.datasets.batch as batch_ds
|
|
42
|
+
from process_improve.batch.data_input import melted_to_dict
|
|
43
|
+
from process_improve.batch.plotting import plot_all_batches_per_tag
|
|
44
|
+
|
|
45
|
+
pd.options.plotting.backend = "plotly"
|
|
46
|
+
pd.options.display.max_columns = 20
|
|
47
|
+
pd.options.display.width = 200
|
|
48
|
+
|
|
49
|
+
get_to_final_result = True
|
|
50
|
+
device_map = "cpu" # use "cpu" for CPU inference and "mps" for Apple Silicon; or "cuda"
|
|
51
|
+
|
|
52
|
+
# Ideally, use more than 1 tag to align on. These columns must exist in all data frames for all batches.
|
|
53
|
+
columns_to_import = ["AgitatorPower", "AgitatorTorque", "JacketTemperature", "DryerTemp"]
|
|
54
|
+
tag_to_plot = columns_to_import[3]
|
|
55
|
+
|
|
56
|
+
# %%
|
|
57
|
+
pipeline = ChronosPipeline.from_pretrained(
|
|
58
|
+
"amazon/chronos-t5-base",
|
|
59
|
+
device_map=device_map,
|
|
60
|
+
torch_dtype=torch.bfloat16,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
# %%
|
|
64
|
+
# Demo code from the repo itself, to validate that it works as expted
|
|
65
|
+
df = pd.read_csv(
|
|
66
|
+
"https://raw.githubusercontent.com/AileenNielsen/TimeSeriesAnalysisWithPython/master/data/AirPassengers.csv"
|
|
67
|
+
)
|
|
68
|
+
df["#Passengers"].plot()
|
|
69
|
+
context = torch.tensor(df["#Passengers"])
|
|
70
|
+
embeddings, tokenizer_state = pipeline.embed(context)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# context must be either a 1D tensor, a list of 1D tensors,
|
|
74
|
+
# or a left-padded 2D tensor with batch as the first dimension
|
|
75
|
+
prediction_length = 12
|
|
76
|
+
forecast = pipeline.predict(
|
|
77
|
+
context,
|
|
78
|
+
prediction_length=prediction_length,
|
|
79
|
+
num_samples=20,
|
|
80
|
+
temperature=1.0,
|
|
81
|
+
top_k=50,
|
|
82
|
+
top_p=1.0,
|
|
83
|
+
) # forecast shape: [num_series, num_samples, prediction_length]
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
# %%
|
|
87
|
+
# visualize the forecast
|
|
88
|
+
forecast_index = range(len(df), len(df) + prediction_length)
|
|
89
|
+
low, median, high = np.quantile(forecast[0].numpy(), [0.1, 0.5, 0.9], axis=0)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# %%
|
|
93
|
+
# Now our example starts. Settings for the batch case study
|
|
94
|
+
|
|
95
|
+
prediction_length = 35
|
|
96
|
+
num_samples = 20 # number or repeated predictions to make; we will average out over these
|
|
97
|
+
first_n_samples = 65
|
|
98
|
+
temperature = 1.0
|
|
99
|
+
top_k = 50
|
|
100
|
+
top_p = 1.0
|
|
101
|
+
|
|
102
|
+
# Import the data: a dictionary of dataframes
|
|
103
|
+
dryer_raw = (
|
|
104
|
+
pd.read_csv(pathlib.Path(batch_ds.__path__._recalculate()[0]) / "dryer.csv")
|
|
105
|
+
.rename({"ClockTime": "Pulse"}, axis=1)
|
|
106
|
+
.astype({"Pulse": "int"})
|
|
107
|
+
)
|
|
108
|
+
if not get_to_final_result:
|
|
109
|
+
dryer_raw[tag_to_plot].plot()
|
|
110
|
+
|
|
111
|
+
# %%
|
|
112
|
+
# Plot some data, to get an idea of what is present
|
|
113
|
+
plt = plot_all_batches_per_tag(
|
|
114
|
+
df_dict=melted_to_dict(dryer_raw, batch_id_col="batch_id"),
|
|
115
|
+
tag=tag_to_plot,
|
|
116
|
+
time_column="ClockTime",
|
|
117
|
+
x_axis_label="Time [hours]",
|
|
118
|
+
)
|
|
119
|
+
if not get_to_final_result:
|
|
120
|
+
plt.show()
|
|
121
|
+
|
|
122
|
+
# %%
|
|
123
|
+
training_batches = list(range(1, 11))
|
|
124
|
+
batch_dict = melted_to_dict(dryer_raw, batch_id_col="batch_id")
|
|
125
|
+
sequences = [batch_dict[k][tag_to_plot].to_list() for k in training_batches if tag_to_plot in batch_dict[k]]
|
|
126
|
+
training_sequence = pd.DataFrame(sequences).T
|
|
127
|
+
plt = training_sequence.plot(title="Training data")
|
|
128
|
+
if not get_to_final_result:
|
|
129
|
+
plt.show()
|
|
130
|
+
|
|
131
|
+
# %%
|
|
132
|
+
# Unravel all columnes, and make a single vector sequence
|
|
133
|
+
all_sequences = []
|
|
134
|
+
for k in training_batches:
|
|
135
|
+
all_sequences.extend(batch_dict[k][tag_to_plot].to_list())
|
|
136
|
+
training_sequence = pd.Series(all_sequences)
|
|
137
|
+
plt = training_sequence.plot(title="Unravelled training data")
|
|
138
|
+
if not get_to_final_result:
|
|
139
|
+
plt.show()
|
|
140
|
+
|
|
141
|
+
# %%
|
|
142
|
+
# Train the model with the tag from the training batches
|
|
143
|
+
context = torch.tensor(training_sequence)
|
|
144
|
+
|
|
145
|
+
forecast = pipeline.predict(
|
|
146
|
+
context,
|
|
147
|
+
prediction_length,
|
|
148
|
+
num_samples=num_samples,
|
|
149
|
+
temperature=temperature,
|
|
150
|
+
top_k=top_k,
|
|
151
|
+
top_p=top_p,
|
|
152
|
+
) # forecast shape: [num_series, num_samples, prediction_length]
|
|
153
|
+
|
|
154
|
+
# %%
|
|
155
|
+
# Testing data: the first 50 samples of the next 10 batches
|
|
156
|
+
|
|
157
|
+
testing_batches = [15]
|
|
158
|
+
batch_dict = melted_to_dict(dryer_raw, batch_id_col="batch_id")
|
|
159
|
+
sequences = []
|
|
160
|
+
for k in testing_batches:
|
|
161
|
+
if tag_to_plot in batch_dict[k]:
|
|
162
|
+
values = batch_dict[k][tag_to_plot].to_list()[0 : first_n_samples + prediction_length]
|
|
163
|
+
values[first_n_samples:] = [None] * prediction_length
|
|
164
|
+
sequences.append(values)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
testing_sequence = pd.DataFrame(sequences).T
|
|
168
|
+
if not get_to_final_result:
|
|
169
|
+
testing_sequence.plot(title="Testing data").show()
|
|
170
|
+
|
|
171
|
+
# %%
|
|
172
|
+
# Testing data:
|
|
173
|
+
for batch in testing_batches:
|
|
174
|
+
context = torch.tensor(
|
|
175
|
+
pd.concat([training_sequence, batch_dict[batch].iloc[0:first_n_samples][tag_to_plot]]).values
|
|
176
|
+
)
|
|
177
|
+
cast = pipeline.predict(
|
|
178
|
+
context,
|
|
179
|
+
prediction_length,
|
|
180
|
+
num_samples=num_samples,
|
|
181
|
+
temperature=temperature,
|
|
182
|
+
top_k=top_k,
|
|
183
|
+
top_p=top_p,
|
|
184
|
+
) # forecast shape: [num_series, num_samples, prediction_length]
|
|
185
|
+
lower, median, upper = np.quantile(cast[0].numpy(), [0.1, 0.5, 0.9], axis=0)
|
|
186
|
+
actual = batch_dict[batch][tag_to_plot]
|
|
187
|
+
forecast_index = actual.index[first_n_samples : (first_n_samples + prediction_length)]
|
|
188
|
+
fig = actual[0 : (first_n_samples + prediction_length)].plot(title="Actual and Forecast", height=1000)
|
|
189
|
+
fig.add_scatter(
|
|
190
|
+
x=forecast_index, y=actual[forecast_index], mode="lines", name="Actual", line=dict(width=3, color="blue")
|
|
191
|
+
)
|
|
192
|
+
fig.add_scatter(x=forecast_index, y=median, mode="lines", name="Forecast", line=dict(width=3, color="red"))
|
|
193
|
+
light_grey = "rgba(0, 0, 0, 0.1)"
|
|
194
|
+
for i in range(num_samples):
|
|
195
|
+
fig.add_scatter(
|
|
196
|
+
x=forecast_index,
|
|
197
|
+
y=cast[0].numpy()[i],
|
|
198
|
+
mode="lines",
|
|
199
|
+
legendgroup="i^th forecast",
|
|
200
|
+
name=f"Forecast {i+1}",
|
|
201
|
+
line=dict(color=light_grey),
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
fill_colour = "rgba(1, 0, 0, 0.2)"
|
|
205
|
+
fig.add_traces(
|
|
206
|
+
go.Scatter(
|
|
207
|
+
x=forecast_index,
|
|
208
|
+
y=upper,
|
|
209
|
+
line=dict(color=fill_colour),
|
|
210
|
+
mode="lines",
|
|
211
|
+
legendgroup="Bounds",
|
|
212
|
+
showlegend=False,
|
|
213
|
+
name="Bounds",
|
|
214
|
+
)
|
|
215
|
+
)
|
|
216
|
+
fig.add_traces(
|
|
217
|
+
go.Scatter(
|
|
218
|
+
x=forecast_index,
|
|
219
|
+
y=lower,
|
|
220
|
+
line=dict(color=fill_colour),
|
|
221
|
+
fill="tonexty", # fill in the range
|
|
222
|
+
fillcolor=fill_colour,
|
|
223
|
+
mode="lines",
|
|
224
|
+
legendgroup="Bounds",
|
|
225
|
+
name="Bounds",
|
|
226
|
+
)
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
fig.show()
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
# %%
|
|
233
|
+
|
|
234
|
+
# raw_sequences = [batch_dict[k][tag_to_plot] for k in training_batches if tag_to_plot in batch_dict[k]]
|
|
235
|
+
# embeddings = []
|
|
236
|
+
# for sequence in raw_sequences:
|
|
237
|
+
# a=2
|
|
238
|
+
# embeddings, tokenizer_state = pipeline.embed(torch.tensor(pd.DataFrame(sequence)))
|
|
239
|
+
# q=embeddings.numpy()
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
# sequences =
|
|
243
|
+
# training_sequence = pd.DataFrame(sequences).T
|
|
244
|
+
# plt = training_sequence.plot(title="Training data")
|
|
245
|
+
# if not get_to_final_resul
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# ---
|
|
2
|
+
# jupyter:
|
|
3
|
+
# jupytext:
|
|
4
|
+
# cell_metadata_filter: -all
|
|
5
|
+
# custom_cell_magics: kql
|
|
6
|
+
# text_representation:
|
|
7
|
+
# extension: .py
|
|
8
|
+
# format_name: percent
|
|
9
|
+
# format_version: '1.3'
|
|
10
|
+
# jupytext_version: 1.11.2
|
|
11
|
+
# kernelspec:
|
|
12
|
+
# display_name: process-improve
|
|
13
|
+
# language: python
|
|
14
|
+
# name: python3
|
|
15
|
+
# ---
|
|
16
|
+
|
|
17
|
+
# %%
|
|
18
|
+
# !pip install git+https://github.com/SalesforceAIResearch/uni2ts
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import os
|
|
24
|
+
import pathlib
|
|
25
|
+
import sys
|
|
26
|
+
|
|
27
|
+
import numpy as np
|
|
28
|
+
import pandas as pd
|
|
29
|
+
import torch
|
|
30
|
+
from datasets import load_dataset
|
|
31
|
+
from gluonts.dataset.pandas import PandasDataset
|
|
32
|
+
from huggingface_hub import hf_hub_download
|
|
33
|
+
from uni2ts.model.moirai import MoiraiForecast
|
|
34
|
+
|
|
35
|
+
# Some basic checks, and logging set up.
|
|
36
|
+
while not str(pathlib.Path.cwd().name).lower().startswith("process-improve"):
|
|
37
|
+
os.chdir(pathlib.Path.cwd().parents[0])
|
|
38
|
+
basecwd = pathlib.Path.cwd()
|
|
39
|
+
sys.path.insert(0, str(basecwd))
|
|
40
|
+
assert basecwd.exists()
|
|
41
|
+
|
|
42
|
+
import process_improve.datasets.batch as batch_ds
|
|
43
|
+
from process_improve.batch.data_input import melted_to_dict
|
|
44
|
+
from process_improve.batch.plotting import plot_all_batches_per_tag
|
|
45
|
+
|
|
46
|
+
pd.options.plotting.backend = "plotly"
|
|
47
|
+
pd.options.display.max_columns = 20
|
|
48
|
+
pd.options.display.width = 200
|
|
49
|
+
|
|
50
|
+
device_map = "cpu" # use "cpu" for CPU inference and "mps" for Apple Silicon; or "cuda"
|
|
51
|
+
|
|
52
|
+
# Ideally, use more than 1 tag to align on. These columns must exist in all data frames for all batches.
|
|
53
|
+
columns_to_import = ["AgitatorPower", "AgitatorTorque", "JacketTemperature", "DryerTemp"]
|
|
54
|
+
tag_to_plot = columns_to_import[3]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
TIME_COL = "Date"
|
|
58
|
+
TARGET = "visits"
|
|
59
|
+
DYNAMIC_COV = ["CPI", "Inflation_Rate", "GDP"]
|
|
60
|
+
SEAS_COV = [
|
|
61
|
+
"month_1",
|
|
62
|
+
"month_2",
|
|
63
|
+
"month_3",
|
|
64
|
+
"month_4",
|
|
65
|
+
"month_5",
|
|
66
|
+
"month_6",
|
|
67
|
+
"month_7",
|
|
68
|
+
"month_8",
|
|
69
|
+
"month_9",
|
|
70
|
+
"month_10",
|
|
71
|
+
"month_11",
|
|
72
|
+
"month_12",
|
|
73
|
+
]
|
|
74
|
+
FORECAST_HORIZON = 8 # months
|
|
75
|
+
FREQ = "M"
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# %%
|
|
79
|
+
def preprocess_dataset(dataframe: pd.DataFrame, dynamic_cov: list, time_col: str, target: str) -> pd.DataFrame:
|
|
80
|
+
"""
|
|
81
|
+
Receives the raw dataframe and create.
|
|
82
|
+
|
|
83
|
+
- unique id column
|
|
84
|
+
- make dynamic start dates for each series based on the first date where visits is different than 0
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
dataframe (pd.DataFrame): raw data
|
|
88
|
+
dynamic_cov (list): column names with dynamic cov
|
|
89
|
+
time_col (str): time column name
|
|
90
|
+
target (str): target name
|
|
91
|
+
Returns:
|
|
92
|
+
pd.DataFrame: cleaned data
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
# save dynamic cov for later
|
|
96
|
+
dynamic_cov_df = dataframe[dynamic_cov].reset_index().drop_duplicates()
|
|
97
|
+
|
|
98
|
+
# create target and unique id columns
|
|
99
|
+
dataframe = (
|
|
100
|
+
dataframe.loc[:, ~dataframe.columns.isin(dynamic_cov)]
|
|
101
|
+
.melt(ignore_index=False)
|
|
102
|
+
.reset_index()
|
|
103
|
+
.rename(columns={"variable": "unique_id", "value": target})
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
# crete dynamic start dates for each series
|
|
107
|
+
cleaned_df = []
|
|
108
|
+
for i in dataframe["unique_id"].unique():
|
|
109
|
+
temp = dataframe[dataframe["unique_id"] == i]
|
|
110
|
+
cleaned_df.append(temp[temp[time_col] >= min(temp[temp[target] > 0][time_col])])
|
|
111
|
+
cleaned_df = pd.concat(cleaned_df)
|
|
112
|
+
|
|
113
|
+
# join dynamic cov
|
|
114
|
+
cleaned_df = pd.merge(cleaned_df, dynamic_cov_df, on=[time_col], how="left")
|
|
115
|
+
|
|
116
|
+
return cleaned_df
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def moirai_forecast_to_pandas(forecast, test_df: pd.DataFrame, forecast_horizon: int, time_col: str) -> pd.DataFrame:
|
|
120
|
+
"""
|
|
121
|
+
Convert MOIRAI forecast into pandas dataframe.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
forecast: MOIRAI's forecast
|
|
125
|
+
test_df: dataframe with actuals
|
|
126
|
+
forecast_horizon: forecast horizon
|
|
127
|
+
time_col: date column
|
|
128
|
+
Returns:
|
|
129
|
+
pd.DataFrame: forecast in pandas format
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
d = {"unique_id": [], time_col: [], "forecast": [], "forecast_lower": [], "forecast_upper": []}
|
|
133
|
+
|
|
134
|
+
for ts in forecast:
|
|
135
|
+
for j in range(forecast_horizon):
|
|
136
|
+
d["unique_id"].append(ts.item_id)
|
|
137
|
+
d[time_col].append(test_df[test_df["unique_id"] == ts.item_id][time_col].tolist()[j])
|
|
138
|
+
|
|
139
|
+
temp = [sample[j] for sample in ts.samples]
|
|
140
|
+
|
|
141
|
+
d["forecast"].append(np.median(temp))
|
|
142
|
+
d["forecast_lower"].append(np.percentile(temp, 10))
|
|
143
|
+
d["forecast_upper"].append(np.percentile(temp, 90))
|
|
144
|
+
|
|
145
|
+
return pd.DataFrame(d)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
# load data and exogenous features
|
|
149
|
+
df = pd.DataFrame(load_dataset("zaai-ai/time_series_datasets", data_files={"train": "data.csv"})["train"]).drop(
|
|
150
|
+
columns=["Unnamed: 0"]
|
|
151
|
+
)
|
|
152
|
+
df[TIME_COL] = pd.to_datetime(df[TIME_COL])
|
|
153
|
+
|
|
154
|
+
# one hot encode month
|
|
155
|
+
df["month"] = df[TIME_COL].dt.month
|
|
156
|
+
df = pd.get_dummies(df, columns=["month"], dtype=int)
|
|
157
|
+
|
|
158
|
+
print(f"Distinct number of time series: {len(df['unique_id'].unique())}")
|
|
159
|
+
df.head()
|
|
160
|
+
|
|
161
|
+
# 8 months to test
|
|
162
|
+
train = df[df[TIME_COL] <= (max(df[TIME_COL]) - pd.DateOffset(months=FORECAST_HORIZON))]
|
|
163
|
+
test = df[df[TIME_COL] > (max(df[TIME_COL]) - pd.DateOffset(months=FORECAST_HORIZON))]
|
|
164
|
+
|
|
165
|
+
print(
|
|
166
|
+
f"Months for training: {len(train[TIME_COL].unique())} from {min(train[TIME_COL]).date()} to {max(train[TIME_COL]).date()}"
|
|
167
|
+
)
|
|
168
|
+
print(
|
|
169
|
+
f"Months for testing: {len(test[TIME_COL].unique())} from {min(test[TIME_COL]).date()} to {max(test[TIME_COL]).date()}"
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
# create GluonTS dataset from pandas
|
|
174
|
+
ds = PandasDataset.from_long_dataframe(
|
|
175
|
+
pd.concat([train, test[["unique_id", TIME_COL] + DYNAMIC_COV + SEAS_COV]]).set_index(
|
|
176
|
+
TIME_COL
|
|
177
|
+
), # concatenaation with test dynamic covaraiates
|
|
178
|
+
item_id="unique_id",
|
|
179
|
+
feat_dynamic_real=DYNAMIC_COV + SEAS_COV,
|
|
180
|
+
target=TARGET,
|
|
181
|
+
freq=FREQ,
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
# Prepare pre-trained model by downloading model weights from huggingface hub
|
|
186
|
+
model = MoiraiForecast.load_from_checkpoint(
|
|
187
|
+
checkpoint_path=hf_hub_download(repo_id="Salesforce/moirai-R-large", filename="model.ckpt"),
|
|
188
|
+
prediction_length=FORECAST_HORIZON,
|
|
189
|
+
context_length=24,
|
|
190
|
+
patch_size="auto",
|
|
191
|
+
num_samples=100,
|
|
192
|
+
target_dim=1,
|
|
193
|
+
feat_dynamic_real_dim=ds.num_feat_dynamic_real,
|
|
194
|
+
past_feat_dynamic_real_dim=ds.num_past_feat_dynamic_real,
|
|
195
|
+
map_location="cuda:0" if torch.cuda.is_available() else "cpu",
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
predictor = model.create_predictor(batch_size=32)
|
|
199
|
+
forecasts = predictor.predict(ds)
|
|
200
|
+
|
|
201
|
+
# convert forecast into pandas
|
|
202
|
+
forecast_df = moirai_forecast_to_pandas(forecasts, test, FORECAST_HORIZON, TIME_COL)
|