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.
Files changed (72) hide show
  1. {process_improve-0.9.76/process_improve.egg-info → process_improve-0.9.78}/PKG-INFO +3 -7
  2. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/__init__.py +0 -2
  3. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/datasets.py +1 -1
  4. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/designs_factorial.py +1 -1
  5. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/models.py +1 -1
  6. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/plotting.py +1 -1
  7. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/simulations.py +3 -3
  8. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/structures.py +1 -1
  9. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/multivariate/methods.py +1 -1
  10. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/multivariate/plots.py +1 -1
  11. process_improve-0.9.78/process_improve/notebooks_examples/batch/batch_llm.py +245 -0
  12. process_improve-0.9.78/process_improve/notebooks_examples/batch/batch_llm_multivariate.py +202 -0
  13. process_improve-0.9.78/process_improve/notebooks_examples/batch/batch_music.py +186 -0
  14. process_improve-0.9.78/process_improve/notebooks_examples/experiments/case-studies.py +847 -0
  15. process_improve-0.9.78/process_improve/notebooks_examples/multivariate/pca_example.py +53 -0
  16. process_improve-0.9.78/process_improve/univariate/__init__.py +0 -0
  17. process_improve-0.9.78/process_improve/visualization/plots.py +19 -0
  18. {process_improve-0.9.76 → process_improve-0.9.78/process_improve.egg-info}/PKG-INFO +3 -7
  19. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve.egg-info/SOURCES.txt +7 -1
  20. {process_improve-0.9.76 → process_improve-0.9.78}/pyproject.toml +2 -1
  21. {process_improve-0.9.76 → process_improve-0.9.78}/tests/test_multivariate.py +1 -1
  22. process_improve-0.9.76/setup.py +0 -50
  23. {process_improve-0.9.76 → process_improve-0.9.78}/LICENSE +0 -0
  24. {process_improve-0.9.76 → process_improve-0.9.78}/MANIFEST.in +0 -0
  25. {process_improve-0.9.76 → process_improve-0.9.78}/README.md +0 -0
  26. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/batch/__init__.py +0 -0
  27. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/batch/alignment_helpers.py +0 -0
  28. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/batch/data_input.py +0 -0
  29. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/batch/features.py +0 -0
  30. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/batch/plotting.py +0 -0
  31. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/batch/preprocessing.py +0 -0
  32. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/bivariate/__init__.py +0 -0
  33. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/bivariate/methods.py +0 -0
  34. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/batch/batch-fake-data.csv +0 -0
  35. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/batch/details.txt +0 -0
  36. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/batch/dryer.csv +0 -0
  37. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/batch/nylon.csv +0 -0
  38. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/experiments/test_doe1.csv +0 -0
  39. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/monitoring/batch-yield-and-purity.csv +0 -0
  40. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/monitoring/rubber-colour.csv +0 -0
  41. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/C.csv +0 -0
  42. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/Hotellings_T2_A3.csv +0 -0
  43. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/Hotellings_T2_A6.csv +0 -0
  44. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/LDPE.csv +0 -0
  45. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/P.csv +0 -0
  46. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/R.csv +0 -0
  47. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/T.csv +0 -0
  48. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/U.csv +0 -0
  49. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/W.csv +0 -0
  50. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/LDPE/Yhat_A6.csv +0 -0
  51. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/kamyr.csv +0 -0
  52. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/datasets/multivariate/tablet-spectra.csv +0 -0
  53. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/__init__.py +0 -0
  54. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/optimal.py +0 -0
  55. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/experiments/optimization.py +0 -0
  56. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/monitoring/__init__.py +0 -0
  57. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/monitoring/control_charts.py +0 -0
  58. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/monitoring/metrics.py +0 -0
  59. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/multivariate/__init__.py +0 -0
  60. {process_improve-0.9.76/process_improve/regression → process_improve-0.9.78/process_improve/notebooks_examples/batch}/__init__.py +0 -0
  61. {process_improve-0.9.76/process_improve/univariate → process_improve-0.9.78/process_improve/regression}/__init__.py +0 -0
  62. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/regression/methods.py +0 -0
  63. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve/univariate/metrics.py +0 -0
  64. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve.egg-info/dependency_links.txt +0 -0
  65. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve.egg-info/requires.txt +0 -0
  66. {process_improve-0.9.76 → process_improve-0.9.78}/process_improve.egg-info/top_level.txt +0 -0
  67. {process_improve-0.9.76 → process_improve-0.9.78}/setup.cfg +0 -0
  68. {process_improve-0.9.76 → process_improve-0.9.78}/tests/test_bivariate.py +0 -0
  69. {process_improve-0.9.76 → process_improve-0.9.78}/tests/test_doe.py +0 -0
  70. {process_improve-0.9.76 → process_improve-0.9.78}/tests/test_monitoring.py +0 -0
  71. {process_improve-0.9.76 → process_improve-0.9.78}/tests/test_regression.py +0 -0
  72. {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.76
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.8
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
 
@@ -1,3 +1 @@
1
1
  """(c) Kevin Dunn, 2010-2025. MIT License."""
2
-
3
- __version__ = "0.9.76"
@@ -1,4 +1,4 @@
1
- # (c) Kevin Dunn, 2010-2024. MIT License. Based on own private work over the years.
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
 
@@ -1,4 +1,4 @@
1
- # (c) Kevin Dunn, 2010-2024. MIT License.
1
+ # (c) Kevin Dunn, 2010-2025. MIT License.
2
2
 
3
3
  """Various factorial designs"""
4
4
 
@@ -1,4 +1,4 @@
1
- # (c) Kevin Dunn, 2010-2024. MIT License. Based on own private work over the years.
1
+ # (c) Kevin Dunn, 2010-2025. MIT License. Based on own private work over the years.
2
2
 
3
3
  import warnings
4
4
  from collections import defaultdict
@@ -1,4 +1,4 @@
1
- # (c) Kevin Dunn, 2010-2024. MIT License.
1
+ # (c) Kevin Dunn, 2010-2025. MIT License.
2
2
  import webbrowser
3
3
 
4
4
  import numpy as np
@@ -1,4 +1,4 @@
1
- # (c) Kevin Dunn, 2010-2024. MIT License. Based on own private work over the years.
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 2024,
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 2024,
73
+ Kevin Dunn, Process Improvement using Data, Chapter 5, 2010 to 2025,
74
74
  https://learnche.org/pid
75
75
 
76
76
  """
@@ -1,4 +1,4 @@
1
- # (c) Kevin Dunn, 2010-2024. MIT License. Based on own private work over the years.
1
+ # (c) Kevin Dunn, 2010-2025. MIT License. Based on own private work over the years.
2
2
 
3
3
  import itertools
4
4
  from collections import defaultdict
@@ -1,4 +1,4 @@
1
- # (c) Kevin Dunn, 2010-2024. MIT License. Based on own private work over the years.
1
+ # (c) Kevin Dunn, 2010-2025. MIT License. Based on own private work over the years.
2
2
  from __future__ import annotations
3
3
 
4
4
  import time
@@ -1,4 +1,4 @@
1
- # (c) Kevin Dunn, 2010-2024. MIT License. Based on own private work over the years.
1
+ # (c) Kevin Dunn, 2010-2025. MIT License. Based on own private work over the years.
2
2
 
3
3
  # Built-in libraries
4
4
  from __future__ import annotations
@@ -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)