google-meridian 1.3.0__py3-none-any.whl → 1.3.2__py3-none-any.whl
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.
- google_meridian-1.3.2.dist-info/METADATA +209 -0
- google_meridian-1.3.2.dist-info/RECORD +76 -0
- {google_meridian-1.3.0.dist-info → google_meridian-1.3.2.dist-info}/top_level.txt +1 -0
- meridian/analysis/__init__.py +1 -2
- meridian/analysis/analyzer.py +0 -1
- meridian/analysis/optimizer.py +5 -3
- meridian/analysis/review/checks.py +81 -30
- meridian/analysis/review/constants.py +4 -0
- meridian/analysis/review/results.py +40 -9
- meridian/analysis/summarizer.py +1 -1
- meridian/analysis/visualizer.py +1 -1
- meridian/backend/__init__.py +229 -24
- meridian/backend/test_utils.py +194 -0
- meridian/constants.py +1 -0
- meridian/data/load.py +2 -0
- meridian/model/eda/__init__.py +0 -1
- meridian/model/eda/constants.py +12 -2
- meridian/model/eda/eda_engine.py +353 -45
- meridian/model/eda/eda_outcome.py +21 -1
- meridian/model/knots.py +17 -0
- meridian/model/model_test_data.py +15 -0
- meridian/{analysis/templates → templates}/card.html.jinja +1 -1
- meridian/{analysis/templates → templates}/chart.html.jinja +1 -1
- meridian/{analysis/templates → templates}/chips.html.jinja +1 -1
- meridian/{analysis → templates}/formatter.py +12 -1
- meridian/templates/formatter_test.py +216 -0
- meridian/{analysis/templates → templates}/insights.html.jinja +1 -1
- meridian/{analysis/templates → templates}/stats.html.jinja +1 -1
- meridian/{analysis/templates → templates}/style.css +1 -1
- meridian/{analysis/templates → templates}/style.scss +1 -1
- meridian/{analysis/templates → templates}/summary.html.jinja +4 -2
- meridian/{analysis/templates → templates}/table.html.jinja +1 -1
- meridian/version.py +1 -1
- schema/__init__.py +30 -0
- schema/serde/__init__.py +26 -0
- schema/serde/constants.py +48 -0
- schema/serde/distribution.py +515 -0
- schema/serde/eda_spec.py +192 -0
- schema/serde/function_registry.py +143 -0
- schema/serde/hyperparameters.py +363 -0
- schema/serde/inference_data.py +105 -0
- schema/serde/marketing_data.py +1321 -0
- schema/serde/meridian_serde.py +413 -0
- schema/serde/serde.py +47 -0
- schema/serde/test_data.py +4608 -0
- schema/utils/__init__.py +17 -0
- schema/utils/time_record.py +156 -0
- google_meridian-1.3.0.dist-info/METADATA +0 -409
- google_meridian-1.3.0.dist-info/RECORD +0 -62
- meridian/model/eda/meridian_eda.py +0 -220
- {google_meridian-1.3.0.dist-info → google_meridian-1.3.2.dist-info}/WHEEL +0 -0
- {google_meridian-1.3.0.dist-info → google_meridian-1.3.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: google-meridian
|
|
3
|
+
Version: 1.3.2
|
|
4
|
+
Summary: Google's open source mixed marketing model library, helps you understand your return on investment and direct your ad spend with confidence.
|
|
5
|
+
Author-email: The Meridian Authors <no-reply@google.com>
|
|
6
|
+
Project-URL: homepage, https://github.com/google/meridian
|
|
7
|
+
Project-URL: repository, https://github.com/google/meridian
|
|
8
|
+
Project-URL: changelog, https://github.com/google/meridian/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: documentation, https://developers.google.com/meridian
|
|
10
|
+
Keywords: mmm
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Topic :: Other/Nonlisted Topic
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: arviz
|
|
19
|
+
Requires-Dist: altair>=5
|
|
20
|
+
Requires-Dist: immutabledict
|
|
21
|
+
Requires-Dist: joblib
|
|
22
|
+
Requires-Dist: natsort<8,>=7.1.1
|
|
23
|
+
Requires-Dist: numpy<3,>=2.0.2
|
|
24
|
+
Requires-Dist: pandas<3,>=2.2.2
|
|
25
|
+
Requires-Dist: patsy<1,>=0.5.3
|
|
26
|
+
Requires-Dist: scipy<2,>=1.13.1
|
|
27
|
+
Requires-Dist: statsmodels>=0.14.5
|
|
28
|
+
Requires-Dist: tensorflow<2.21,>=2.18
|
|
29
|
+
Requires-Dist: tensorflow-probability<0.26,>=0.25
|
|
30
|
+
Requires-Dist: tf-keras<2.21,>=2.18
|
|
31
|
+
Requires-Dist: xarray
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-xdist; extra == "dev"
|
|
35
|
+
Requires-Dist: pylint>=2.6.0; extra == "dev"
|
|
36
|
+
Requires-Dist: pyink; extra == "dev"
|
|
37
|
+
Provides-Extra: colab
|
|
38
|
+
Requires-Dist: psutil; extra == "colab"
|
|
39
|
+
Requires-Dist: python-calamine; extra == "colab"
|
|
40
|
+
Provides-Extra: and-cuda
|
|
41
|
+
Requires-Dist: tensorflow[and-cuda]<2.21,>=2.18; extra == "and-cuda"
|
|
42
|
+
Provides-Extra: mlflow
|
|
43
|
+
Requires-Dist: mlflow; extra == "mlflow"
|
|
44
|
+
Provides-Extra: jax
|
|
45
|
+
Requires-Dist: jax==0.5.3; extra == "jax"
|
|
46
|
+
Requires-Dist: jaxlib==0.5.3; extra == "jax"
|
|
47
|
+
Requires-Dist: tensorflow-probability[substrates-jax]==0.25.0; extra == "jax"
|
|
48
|
+
Provides-Extra: schema
|
|
49
|
+
Requires-Dist: mmm-proto-schema; extra == "schema"
|
|
50
|
+
Requires-Dist: semver; extra == "schema"
|
|
51
|
+
Dynamic: license-file
|
|
52
|
+
|
|
53
|
+
# About Meridian
|
|
54
|
+
|
|
55
|
+
Marketing mix modeling (MMM) is a statistical analysis technique that measures
|
|
56
|
+
the impact of marketing campaigns and activities to guide budget planning
|
|
57
|
+
decisions and improve overall media effectiveness. MMM uses aggregated data to
|
|
58
|
+
measure impact across marketing channels and account for non-marketing factors
|
|
59
|
+
that impact sales and other key performance indicators (KPIs). MMM is
|
|
60
|
+
privacy-safe and does not use any cookie or user-level information.
|
|
61
|
+
|
|
62
|
+
Meridian is an MMM framework that enables advertisers to set up and run their
|
|
63
|
+
own in-house models. Meridian helps you answer key questions such as:
|
|
64
|
+
|
|
65
|
+
* How did the marketing channels drive my revenue or other KPI?
|
|
66
|
+
* What was my marketing return on investment (ROI)?
|
|
67
|
+
* How do I optimize my marketing budget allocation for the future?
|
|
68
|
+
|
|
69
|
+
Meridian is a highly customizable modeling framework that is based on
|
|
70
|
+
[Bayesian causal inference](https://developers.google.com/meridian/docs/causal-inference/bayesian-inference).
|
|
71
|
+
It is capable of handling large scale geo-level data, which is encouraged if
|
|
72
|
+
available, but it can also be used for national-level modeling. Meridian
|
|
73
|
+
provides clear insights and visualizations to inform business decisions around
|
|
74
|
+
marketing budget and planning. Additionally, Meridian provides methodologies to
|
|
75
|
+
support calibration of MMM with experiments and other prior information, and to
|
|
76
|
+
optimize target ad frequency by utilizing reach and frequency data.
|
|
77
|
+
|
|
78
|
+
If you are using LightweightMMM, see the
|
|
79
|
+
[migration guide](https://developers.google.com/meridian/docs/migrate) to help
|
|
80
|
+
you understand the differences between these MMM projects.
|
|
81
|
+
|
|
82
|
+
## Install Meridian
|
|
83
|
+
|
|
84
|
+
Python 3.11 or 3.12 is required to use Meridian. We also recommend using a
|
|
85
|
+
minimum of 1 GPU.
|
|
86
|
+
|
|
87
|
+
Note: This project has been tested on T4 GPU using 16 GB of RAM.
|
|
88
|
+
|
|
89
|
+
To install Meridian, run the following command to automatically install the
|
|
90
|
+
latest release from PyPI.
|
|
91
|
+
|
|
92
|
+
* For Linux-GPU users:
|
|
93
|
+
|
|
94
|
+
Note: CUDA toolchain and a compatible GPU device is necessary for
|
|
95
|
+
`[and-cuda]` extra to activate.
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
$ pip install --upgrade google-meridian[and-cuda]
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
* For macOS and general CPU users:
|
|
102
|
+
|
|
103
|
+
Note: There is no official GPU support for macOS.
|
|
104
|
+
|
|
105
|
+
```sh
|
|
106
|
+
$ pip install --upgrade google-meridian
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Alternatively, run the following command to install the most recent, unreleased
|
|
110
|
+
version from GitHub.
|
|
111
|
+
|
|
112
|
+
* For GPU users:
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
$ pip install --upgrade "google-meridian[and-cuda] @ git+https://github.com/google/meridian.git"
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
* For CPU users:
|
|
119
|
+
|
|
120
|
+
```sh
|
|
121
|
+
$ pip install --upgrade git+https://github.com/google/meridian.git
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
We recommend to install Meridian in a fresh
|
|
125
|
+
[virtual environment](https://virtualenv.pypa.io/en/latest/user_guide.html#quick-start)
|
|
126
|
+
to make sure that correct versions of all the dependencies are installed, as
|
|
127
|
+
defined in [pyproject.toml](https://github.com/google/meridian/blob/main/pyproject.toml).
|
|
128
|
+
|
|
129
|
+
## How to use the Meridian library
|
|
130
|
+
|
|
131
|
+
To get started with Meridian, you can run the code programmatically using sample
|
|
132
|
+
data with the [Getting Started Colab][3].
|
|
133
|
+
|
|
134
|
+
The Meridian model uses a holistic MCMC sampling approach called
|
|
135
|
+
[No U Turn Sampler (NUTS)](https://www.tensorflow.org/probability/api_docs/python/tfp/experimental/mcmc/NoUTurnSampler)
|
|
136
|
+
which can be compute intensive. To help with this, GPU support has been
|
|
137
|
+
developed across the library (out-of-the-box) using tensors. We recommend
|
|
138
|
+
running your Meridian model on GPUs to get real time optimization results and
|
|
139
|
+
significantly reduce training time.
|
|
140
|
+
|
|
141
|
+
## Meridian Documentation & Tutorials
|
|
142
|
+
|
|
143
|
+
The following documentation, colab, and video resources will help you get
|
|
144
|
+
started quickly with using Meridian:
|
|
145
|
+
|
|
146
|
+
| Resource | Description |
|
|
147
|
+
| --------------------------- | ---------------------------------------------- |
|
|
148
|
+
| [Meridian documentation][1] | Main landing page for Meridian documentation. |
|
|
149
|
+
| [Meridian basics][2] | Learn about Meridian features, methodologies, and the model math. |
|
|
150
|
+
| [Getting started colab][3] | Install and quickly learn how to use Meridian with this colab tutorial using sample data. |
|
|
151
|
+
| [User guide][4] | A detailed walk-through of how to use Meridian and generating visualizations using your own data. |
|
|
152
|
+
| [Pre-modeling][5] | Prepare and analyze your data before modeling. |
|
|
153
|
+
| [Modeling][6] | Modeling guidance for model refinement and edge cases. |
|
|
154
|
+
| [Post-modeling][7] | Post-modeling guidance for model fit, visualizations, optimizations, refreshing the model, and debugging. |
|
|
155
|
+
| [Migrate from LMMM][8] | Learn about the differences between Meridian and LightweightMMM as you consider migrating. |
|
|
156
|
+
| [API Reference][9] | API reference documentation for the Meridian package. |
|
|
157
|
+
| [Reference list][10] | White papers and other referenced material. |
|
|
158
|
+
|
|
159
|
+
[1]: https://developers.google.com/meridian
|
|
160
|
+
[2]: https://developers.google.com/meridian/docs/basics/meridian-introduction
|
|
161
|
+
[3]: https://developers.google.com/meridian/notebook/meridian-getting-started
|
|
162
|
+
[4]: https://developers.google.com/meridian/docs/user-guide/installing
|
|
163
|
+
[5]: https://developers.google.com/meridian/docs/pre-modeling/collect-data
|
|
164
|
+
[6]: https://developers.google.com/meridian/docs/advanced-modeling/control-variables
|
|
165
|
+
[7]: https://developers.google.com/meridian/docs/post-modeling/model-fit
|
|
166
|
+
[8]: https://developers.google.com/meridian/docs/migrate
|
|
167
|
+
[9]: https://developers.google.com/meridian/reference/api/meridian
|
|
168
|
+
[10]: https://developers.google.com/meridian/docs/reference-list
|
|
169
|
+
|
|
170
|
+
## Support
|
|
171
|
+
|
|
172
|
+
**Questions about methodology**: Please see the [Modeling](https://developers.google.com/meridian/docs/basics/meridian-introduction) tab in the technical documentation.
|
|
173
|
+
|
|
174
|
+
**Issues installing or using Meridian**: Feel free to post questions in the
|
|
175
|
+
[Discussions](https://github.com/google/meridian/discussions) or [Issues](https://github.com/google/meridian/issues) tabs of the Meridian GitHub repository. The Meridian team responds to
|
|
176
|
+
these questions weekly in batches, so please be patient and don't reach out
|
|
177
|
+
directly to your Google Account teams.
|
|
178
|
+
|
|
179
|
+
**Bug reports**: Please post bug reports to the [Issues](https://github.com/google/meridian/issues)
|
|
180
|
+
tab of the Meridian GitHub repository. We also encourage the community to share
|
|
181
|
+
tips and advice with each other on the [Issues](https://github.com/google/meridian/issues)
|
|
182
|
+
tab. When our team addresses or resolves a new bug, we will notify you through
|
|
183
|
+
the comments on the issue.
|
|
184
|
+
|
|
185
|
+
**Feature requests**: Please post these to the [Discussions](https://github.com/google/meridian/discussions)
|
|
186
|
+
tab of the Meridian GitHub repository. We have an internal roadmap for Meridian
|
|
187
|
+
development, but would love your inputs for new feature requests so that we can
|
|
188
|
+
prioritize them based on the roadmap.
|
|
189
|
+
|
|
190
|
+
**Pull requests**: These are appreciated but are very difficult for us to merge
|
|
191
|
+
because the code in this repository is linked to Google internal systems and has
|
|
192
|
+
to pass internal review. If you submit a pull request and we believe that we can
|
|
193
|
+
incorporate a change in the base code, we will reach out to you directly about
|
|
194
|
+
this.
|
|
195
|
+
|
|
196
|
+
## Citing Meridian
|
|
197
|
+
|
|
198
|
+
To cite this repository:
|
|
199
|
+
|
|
200
|
+
<!-- mdlint off(SNIPPET_INVALID_LANGUAGE) -->
|
|
201
|
+
```BibTeX
|
|
202
|
+
@software{meridian_github,
|
|
203
|
+
author = {Google Meridian Marketing Mix Modeling Team},
|
|
204
|
+
title = {Meridian: Marketing Mix Modeling},
|
|
205
|
+
url = {https://github.com/google/meridian},
|
|
206
|
+
version = {1.3.2},
|
|
207
|
+
year = {2025},
|
|
208
|
+
}
|
|
209
|
+
```
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
google_meridian-1.3.2.dist-info/licenses/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
|
2
|
+
meridian/__init__.py,sha256=0fOT5oNZF7-pbiWWGUefV-ysafttieG079m1ijMFQO8,861
|
|
3
|
+
meridian/constants.py,sha256=idvYuDmoULgHvVG5kGJb2j2VAdBF6BeOwDfKLP14-Fo,20322
|
|
4
|
+
meridian/version.py,sha256=eMNUh0AywCHr0ZyrDyJchcddVsAyWWKKHuXI0VxLScE,644
|
|
5
|
+
meridian/analysis/__init__.py,sha256=AM7xpqoeC-mmY4tPIyHisjQ2MICI7v3jSri--DhDqXA,874
|
|
6
|
+
meridian/analysis/analyzer.py,sha256=qGKYoEpWC6pDf2sDrwLhpa2putDnpUzbBpuNqL1lGi4,219910
|
|
7
|
+
meridian/analysis/optimizer.py,sha256=6OqJg8T09g4GqJc6_DnYDJsBAlY4ToUb3MRtS0EH4Nc,126316
|
|
8
|
+
meridian/analysis/summarizer.py,sha256=pah0osYYJFQTf2Fn7-nnvxlBupf9cfaKW87bcqRO1A4,19036
|
|
9
|
+
meridian/analysis/summary_text.py,sha256=I_smDkZJYp2j77ea-9AIbgeraDa7-qUYyb-IthP2qO4,12438
|
|
10
|
+
meridian/analysis/test_utils.py,sha256=aZq88pxtpMHwhcpfYz8nHhR0Alhi_OvgS9qBR4LBgO0,78346
|
|
11
|
+
meridian/analysis/visualizer.py,sha256=_z5vSnXyv3Zx4tmKLyevnMolzLzUzNFcNInOipEmMok,94092
|
|
12
|
+
meridian/analysis/review/__init__.py,sha256=cF24EbhiVSs-tvtRf59uVin39tu6aCTTCaeEdv6ISZ8,804
|
|
13
|
+
meridian/analysis/review/checks.py,sha256=QEUVwC8L9Pif3y0B_OVAUpZeN6EnFGKH2oXA_dsdgbc,26893
|
|
14
|
+
meridian/analysis/review/configs.py,sha256=5JJ8v6n22GNBmE78xNX6jwdjkZz2qar4Q9YTcVqzcoI,3653
|
|
15
|
+
meridian/analysis/review/constants.py,sha256=9tnnc_vAaJi9mnZ0GrRr86RsVq5fyhBaEtIvOLNmn8A,1498
|
|
16
|
+
meridian/analysis/review/results.py,sha256=ZZiAdFrqySzcbjrCEacBLQS_ddiklZ34yD1BWns5SYI,17418
|
|
17
|
+
meridian/analysis/review/reviewer.py,sha256=BcfmqHjp-30iZBlrzWfXDN1IJU-UIjINxZ7lsrj5Mts,6675
|
|
18
|
+
meridian/backend/__init__.py,sha256=i2XOZnIPo3xAKpMGT39-4CVnVdf4cJyO0jB9FEE4zlQ,41337
|
|
19
|
+
meridian/backend/config.py,sha256=B9VQnhBfg9RW04GNbt7F5uCugByenoJzt-keFLLYEp8,3561
|
|
20
|
+
meridian/backend/test_utils.py,sha256=oJNosF_x_BzNuia8LzLFb_YfjGWHRCzR5FXNN5KQ8sw,13738
|
|
21
|
+
meridian/data/__init__.py,sha256=StIe-wfYnnbfUbKtZHwnAQcRQUS8XCZk_PCaEzw90Ww,929
|
|
22
|
+
meridian/data/arg_builder.py,sha256=Kqlt88bOqFj6D3xNwvWo4MBwNwcDFHzd-wMfEOmLoPU,3741
|
|
23
|
+
meridian/data/data_frame_input_data_builder.py,sha256=_hexZMFAuAowgo6FaOGElHSFHqhGnHQwEEBcwnT3zUE,27295
|
|
24
|
+
meridian/data/input_data.py,sha256=Qlxm4El6h1SRPsWDqZoKkOcMtrjiRWr3z8sU2mtghRA,43151
|
|
25
|
+
meridian/data/input_data_builder.py,sha256=tbZjVXPDfmtndVyJA0fmzGzZwZb0RCEjXOTXb-ga8Nc,25648
|
|
26
|
+
meridian/data/load.py,sha256=ETX8Z62Gk6JcxFxvyB4XQhpNcRSqBRIO4_sTAN58mCY,40172
|
|
27
|
+
meridian/data/nd_array_input_data_builder.py,sha256=lfpmnENGuSGKyUd7bDGAwoLqHqteOKmHdKl0VI2wCQA,16341
|
|
28
|
+
meridian/data/test_utils.py,sha256=mw-QPTP15oXf32I7cxMe8iSFBLB3seqEiITZMTz_Eg8,59838
|
|
29
|
+
meridian/data/time_coordinates.py,sha256=C5A5fscSLjPH6G9YT8OspgIlCrkMY7y8dMFEt3tNSnE,9874
|
|
30
|
+
meridian/mlflow/__init__.py,sha256=elwXUqPQYi7VF9PYjelU1tydfcUrmtuoq6eJCOnV9bk,693
|
|
31
|
+
meridian/mlflow/autolog.py,sha256=SZsrynLjozcyrAFCNWiqchSa2yOszVnwFBGz23BmWUU,6379
|
|
32
|
+
meridian/model/__init__.py,sha256=mhF5VkRxvwamRa_0AihgbFuXLMueRCK-Je_ZZvU5IFw,1013
|
|
33
|
+
meridian/model/adstock_hill.py,sha256=HoRKjyL03pCTBz6Utof9wEvlQCFM43BvrEW_oupj7NU,17688
|
|
34
|
+
meridian/model/knots.py,sha256=B78oTQ97Zd0aON4CnhMPqJZ4eamy6d-esKMWqoDf9uQ,27273
|
|
35
|
+
meridian/model/media.py,sha256=skjy4Vd8LfDQWlqR_2lJ1qbG9UcS1dow5W45BAu4qk8,14599
|
|
36
|
+
meridian/model/model.py,sha256=jMtfl7woWtJ8M8AX42QeZ5hUS8hlhPdZ-9OU8KahjKA,68984
|
|
37
|
+
meridian/model/model_test_data.py,sha256=XGBz8RGdCsjAUOmgxX3CfWSj-_hdq2Lc8saFCqmImwM,23901
|
|
38
|
+
meridian/model/posterior_sampler.py,sha256=f3MayglIgBeBjWeXJU_RgT9cCugcjJ3aEjHqaWPsTbg,26806
|
|
39
|
+
meridian/model/prior_distribution.py,sha256=ZArW4uXIPPQL6hRWiGZUzcHktbkjE_vOklvlbp9LR64,57662
|
|
40
|
+
meridian/model/prior_sampler.py,sha256=iLvCefhA4WY0ENcnLK9471WUZPPyzQ1je58MRjxKv74,25460
|
|
41
|
+
meridian/model/spec.py,sha256=VlK6WJiPo2lzOF0O2judtJ6O3uEw7wYL5AT8bioq4gE,19188
|
|
42
|
+
meridian/model/transformers.py,sha256=HxlVJitxP-wu-NOHU0tArFUZ4NAO3c7adAYj4Zvqnvo,8363
|
|
43
|
+
meridian/model/eda/__init__.py,sha256=bMj9kd2LWU_LQZAjQv54FFggzdv4CKRYblvc-0cHXc4,768
|
|
44
|
+
meridian/model/eda/constants.py,sha256=Kt8x8hvC2WkeEtW0Wmid8GkqZbh_p6NdiZ_A5V3qzwM,1031
|
|
45
|
+
meridian/model/eda/eda_engine.py,sha256=AxvKxdH8Q_TWlGZ58bWcfGMSgxkHZ2wrHloPuzS5C4Y,73324
|
|
46
|
+
meridian/model/eda/eda_outcome.py,sha256=cR9M49e6bDrBNxHOThW3aQlX5gZCOENC7GBljKQx7OY,6475
|
|
47
|
+
meridian/model/eda/eda_spec.py,sha256=diieYyZH0ee3ZLy0rGFMcWrrgiUrz2HctMwOrmtJR6w,2871
|
|
48
|
+
meridian/templates/card.html.jinja,sha256=gaQSHh8xN-LqHzI-xsHaORsaeOD7hnxkq-Fcw-ytZ8M,1284
|
|
49
|
+
meridian/templates/chart.html.jinja,sha256=j8rNLOfXxKx4f5TpP9_W8uCM8zKys8ga75jv-XCny2g,1086
|
|
50
|
+
meridian/templates/chips.html.jinja,sha256=IhPmAI7qZkXj5NeLUKVMCSKFzwv9yR8Qq140t36U10A,1030
|
|
51
|
+
meridian/templates/formatter.py,sha256=75KtZA2y6iyxpkVM3CLmpUtJ1-umBP9xXxdXkkSZcr8,7547
|
|
52
|
+
meridian/templates/formatter_test.py,sha256=nlefFTQaSArNyZWzGUuzCKtt3P3PJNZFmkGm0XMYwBY,8543
|
|
53
|
+
meridian/templates/insights.html.jinja,sha256=IRm49X49HZX-rc6z0uZmpsA_1JLD83UhI2BacOanHLY,606
|
|
54
|
+
meridian/templates/stats.html.jinja,sha256=JMRC_W2PyReU30ISOd8uv2ugDpYmSU3XtPk2OTsaQus,772
|
|
55
|
+
meridian/templates/style.css,sha256=O7YCKVqXgK4Ms3nnGmCVW4hILn4GCBRe4e15XJaP4ww,5492
|
|
56
|
+
meridian/templates/style.scss,sha256=he5jXpGatNfI6vtNbqdENapLiwIlXjqIBkKwxNVEvyw,5076
|
|
57
|
+
meridian/templates/summary.html.jinja,sha256=kR4nQc-oGBwXN6buKcf_wPaoWASomR4fT4gJ1iD9hYw,1775
|
|
58
|
+
meridian/templates/table.html.jinja,sha256=ibgnjdKCjS2qbq61lxqwtlb7JigDrc2m42RDdQvQnKQ,1176
|
|
59
|
+
schema/__init__.py,sha256=grEfsjrcPRzhd89ZXLggnBnrryl97bsayKWP1ue1ffE,1206
|
|
60
|
+
schema/serde/__init__.py,sha256=xyydIcWB5IUpcn3wu1m9HL1fK4gMWURbwTyRsQtolF0,975
|
|
61
|
+
schema/serde/constants.py,sha256=aYtD_RuA0GCkpC4TIQq3VjMqEc837Wn-TlJNm-yn_4Y,1842
|
|
62
|
+
schema/serde/distribution.py,sha256=jy3h6JD1TSs4gwociMis814sz_Fm2kFQ2UbkgjYJW9k,19347
|
|
63
|
+
schema/serde/eda_spec.py,sha256=uOqBeZpUU3Dzzc19rU1LjHWmUhRmVcx8oIZvZfVJHT8,7180
|
|
64
|
+
schema/serde/function_registry.py,sha256=GbgC5_9NDcA9Y7nqmdJ-4-LK5JPhhfI50Lmfy5ZBJOg,4858
|
|
65
|
+
schema/serde/hyperparameters.py,sha256=Igm-PZmIozrsKZH6c-XkrU_Nlf8OAuxpnJJfv7W1SfQ,13524
|
|
66
|
+
schema/serde/inference_data.py,sha256=DrwE9hU8LMrl0z8W_sUSIaPrRdym_lu0iOqpT4KZxsA,3623
|
|
67
|
+
schema/serde/marketing_data.py,sha256=yb-fRTe84Sjg7-v3wsvYRRXvrxLSFWSenO0_ikMvUpk,44845
|
|
68
|
+
schema/serde/meridian_serde.py,sha256=ZG05JaBG4LW8mhl-Cunje9Q6xyR4tyNTtLYedzMBYjA,15985
|
|
69
|
+
schema/serde/serde.py,sha256=8vUqhJxvZgX9UY3rXTyWJznRgapwDzzaHXDHwV_kKTA,1612
|
|
70
|
+
schema/serde/test_data.py,sha256=7hfEWyvZ9WcAkVAOXt6elX8stJlsfhfd-ASlHo9SRb8,107342
|
|
71
|
+
schema/utils/__init__.py,sha256=AkC4NMbmXC3PFBY9dFYxlf3qFsxt5OOBVdc9zmFXsC8,675
|
|
72
|
+
schema/utils/time_record.py,sha256=-KzHFjvSBUUXsfESPAfcJP_VFxaFLqj90Ac0kgKWfpI,4624
|
|
73
|
+
google_meridian-1.3.2.dist-info/METADATA,sha256=BHbc_4zpZ5EBv1urcvQR_brE9WEJaia4F1ZLYaA8sG0,9545
|
|
74
|
+
google_meridian-1.3.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
75
|
+
google_meridian-1.3.2.dist-info/top_level.txt,sha256=yWkWDLV_UUanhKmk_xNPiKNdPDl1oyU1sBYwEnhaSf4,16
|
|
76
|
+
google_meridian-1.3.2.dist-info/RECORD,,
|
meridian/analysis/__init__.py
CHANGED
|
@@ -15,9 +15,8 @@
|
|
|
15
15
|
"""Meridian analysis API for trained models."""
|
|
16
16
|
|
|
17
17
|
from meridian.analysis import analyzer
|
|
18
|
-
from meridian.analysis import formatter
|
|
19
18
|
from meridian.analysis import optimizer
|
|
20
19
|
from meridian.analysis import review
|
|
21
20
|
from meridian.analysis import summarizer
|
|
22
21
|
from meridian.analysis import visualizer
|
|
23
|
-
|
|
22
|
+
from meridian.templates import formatter
|
meridian/analysis/analyzer.py
CHANGED
|
@@ -53,7 +53,6 @@ def _validate_non_media_baseline_values_numbers(
|
|
|
53
53
|
)
|
|
54
54
|
|
|
55
55
|
|
|
56
|
-
# TODO: Refactor the related unit tests to be under DataTensors.
|
|
57
56
|
@dataclasses.dataclass
|
|
58
57
|
class DataTensors(backend.ExtensionType):
|
|
59
58
|
"""Container for data variable arguments of Analyzer methods.
|
meridian/analysis/optimizer.py
CHANGED
|
@@ -27,10 +27,10 @@ import jinja2
|
|
|
27
27
|
from meridian import backend
|
|
28
28
|
from meridian import constants as c
|
|
29
29
|
from meridian.analysis import analyzer as analyzer_module
|
|
30
|
-
from meridian.analysis import formatter
|
|
31
30
|
from meridian.analysis import summary_text
|
|
32
31
|
from meridian.data import time_coordinates as tc
|
|
33
32
|
from meridian.model import model
|
|
33
|
+
from meridian.templates import formatter
|
|
34
34
|
import numpy as np
|
|
35
35
|
import pandas as pd
|
|
36
36
|
import xarray as xr
|
|
@@ -1174,10 +1174,12 @@ class OptimizationResults:
|
|
|
1174
1174
|
diff = self.optimized_data.total_cpik - self.nonoptimized_data.total_cpik
|
|
1175
1175
|
non_optimized_performance_title = summary_text.NON_OPTIMIZED_CPIK_LABEL
|
|
1176
1176
|
non_optimized_performance_stat = (
|
|
1177
|
-
f'
|
|
1177
|
+
f'{currency}{self.nonoptimized_data.total_cpik:.2f}'
|
|
1178
1178
|
)
|
|
1179
1179
|
optimized_performance_title = summary_text.OPTIMIZED_CPIK_LABEL
|
|
1180
|
-
optimized_performance_stat =
|
|
1180
|
+
optimized_performance_stat = (
|
|
1181
|
+
f'{currency}{self.optimized_data.total_cpik:.2f}'
|
|
1182
|
+
)
|
|
1181
1183
|
optimized_performance_diff = formatter.compact_number(diff, 2, currency)
|
|
1182
1184
|
non_optimized_performance = formatter.StatsSpec(
|
|
1183
1185
|
title=non_optimized_performance_title,
|
|
@@ -28,6 +28,7 @@ from meridian.analysis.review import constants as review_constants
|
|
|
28
28
|
from meridian.analysis.review import results
|
|
29
29
|
from meridian.model import model
|
|
30
30
|
import numpy as np
|
|
31
|
+
import pandas as pd
|
|
31
32
|
|
|
32
33
|
ConfigType = TypeVar("ConfigType", bound=configs.BaseConfig)
|
|
33
34
|
ResultType = TypeVar("ResultType", bound=results.CheckResult)
|
|
@@ -207,6 +208,51 @@ class BayesianPPPCheck(
|
|
|
207
208
|
# ==============================================================================
|
|
208
209
|
# Check: Goodness of Fit
|
|
209
210
|
# ==============================================================================
|
|
211
|
+
def _set_details_from_gof_dataframe(
|
|
212
|
+
details: dict[str, float],
|
|
213
|
+
gof_df: pd.DataFrame,
|
|
214
|
+
geo_granularity: str,
|
|
215
|
+
suffix: str | None = None,
|
|
216
|
+
) -> None:
|
|
217
|
+
"""Sets the `details` variable of the GoodnessOfFitCheckResult.
|
|
218
|
+
|
|
219
|
+
This method takes a DataFrame containing goodness of fit metrics and pivots it
|
|
220
|
+
to a Series, which is then added to the `details` variable of the
|
|
221
|
+
`GoodnessOfFitCheckResult`.
|
|
222
|
+
|
|
223
|
+
Args:
|
|
224
|
+
details: A dictionary to store the goodness of fit metrics in.
|
|
225
|
+
gof_df: A DataFrame containing predictive accuracy of the whole data (if
|
|
226
|
+
holdout set is not used) of filtered to a single evaluation set ("all",
|
|
227
|
+
"train", or "test").
|
|
228
|
+
geo_granularity: The geo granularity of the data ("geo" or "national").
|
|
229
|
+
suffix: A suffix to add to the metric names (e.g., "all", "train", "test").
|
|
230
|
+
If None, the metrics are added without a suffix.
|
|
231
|
+
"""
|
|
232
|
+
gof_metrics_pivoted = gof_df.pivot(
|
|
233
|
+
index=constants.GEO_GRANULARITY,
|
|
234
|
+
columns=constants.METRIC,
|
|
235
|
+
values=constants.VALUE,
|
|
236
|
+
)
|
|
237
|
+
gof_metrics_series = gof_metrics_pivoted.loc[geo_granularity]
|
|
238
|
+
if suffix is not None:
|
|
239
|
+
details[f"{review_constants.R_SQUARED}_{suffix}"] = gof_metrics_series[
|
|
240
|
+
constants.R_SQUARED
|
|
241
|
+
]
|
|
242
|
+
details[f"{review_constants.MAPE}_{suffix}"] = gof_metrics_series[
|
|
243
|
+
constants.MAPE
|
|
244
|
+
]
|
|
245
|
+
details[f"{review_constants.WMAPE}_{suffix}"] = gof_metrics_series[
|
|
246
|
+
constants.WMAPE
|
|
247
|
+
]
|
|
248
|
+
else:
|
|
249
|
+
details[review_constants.R_SQUARED] = gof_metrics_series[
|
|
250
|
+
constants.R_SQUARED
|
|
251
|
+
]
|
|
252
|
+
details[review_constants.MAPE] = gof_metrics_series[constants.MAPE]
|
|
253
|
+
details[review_constants.WMAPE] = gof_metrics_series[constants.WMAPE]
|
|
254
|
+
|
|
255
|
+
|
|
210
256
|
class GoodnessOfFitCheck(
|
|
211
257
|
BaseCheck[configs.GoodnessOfFitConfig, results.GoodnessOfFitCheckResult]
|
|
212
258
|
):
|
|
@@ -221,38 +267,43 @@ class GoodnessOfFitCheck(
|
|
|
221
267
|
)
|
|
222
268
|
|
|
223
269
|
gof_metrics = gof_df[gof_df[constants.GEO_GRANULARITY] == geo_granularity]
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
case=results.GoodnessOfFitCases.PASS,
|
|
249
|
-
details=details,
|
|
250
|
-
)
|
|
251
|
-
else: # r_squared <= 0
|
|
252
|
-
return results.GoodnessOfFitCheckResult(
|
|
253
|
-
case=results.GoodnessOfFitCases.REVIEW,
|
|
270
|
+
is_holdout = constants.EVALUATION_SET_VAR in gof_df.columns
|
|
271
|
+
|
|
272
|
+
details = {}
|
|
273
|
+
case = results.GoodnessOfFitCases.PASS
|
|
274
|
+
|
|
275
|
+
if is_holdout:
|
|
276
|
+
for evaluation_set, suffix in [
|
|
277
|
+
(constants.ALL_DATA, review_constants.ALL_SUFFIX),
|
|
278
|
+
(constants.TRAIN, review_constants.TRAIN_SUFFIX),
|
|
279
|
+
(constants.TEST, review_constants.TEST_SUFFIX),
|
|
280
|
+
]:
|
|
281
|
+
set_metrics = gof_metrics[
|
|
282
|
+
gof_metrics[constants.EVALUATION_SET_VAR] == evaluation_set
|
|
283
|
+
]
|
|
284
|
+
_set_details_from_gof_dataframe(
|
|
285
|
+
details=details,
|
|
286
|
+
gof_df=set_metrics,
|
|
287
|
+
geo_granularity=geo_granularity,
|
|
288
|
+
suffix=suffix,
|
|
289
|
+
)
|
|
290
|
+
if details[f"{review_constants.R_SQUARED}_{suffix}"] <= 0:
|
|
291
|
+
case = results.GoodnessOfFitCases.REVIEW
|
|
292
|
+
else:
|
|
293
|
+
_set_details_from_gof_dataframe(
|
|
254
294
|
details=details,
|
|
295
|
+
gof_df=gof_metrics,
|
|
296
|
+
geo_granularity=geo_granularity,
|
|
297
|
+
suffix=None,
|
|
255
298
|
)
|
|
299
|
+
if details[review_constants.R_SQUARED] <= 0:
|
|
300
|
+
case = results.GoodnessOfFitCases.REVIEW
|
|
301
|
+
|
|
302
|
+
return results.GoodnessOfFitCheckResult(
|
|
303
|
+
case=case,
|
|
304
|
+
details=details,
|
|
305
|
+
is_holdout=is_holdout,
|
|
306
|
+
)
|
|
256
307
|
|
|
257
308
|
|
|
258
309
|
# ==============================================================================
|
|
@@ -32,6 +32,10 @@ NEGATIVE_BASELINE_PROB_REVIEW_THRESHOLD = (
|
|
|
32
32
|
R_SQUARED = "r_squared"
|
|
33
33
|
MAPE = "mape"
|
|
34
34
|
WMAPE = "wmape"
|
|
35
|
+
ALL_SUFFIX = "all"
|
|
36
|
+
TRAIN_SUFFIX = "train"
|
|
37
|
+
TEST_SUFFIX = "test"
|
|
38
|
+
EVALUATION_SET_SUFFIXES = (ALL_SUFFIX, TRAIN_SUFFIX, TEST_SUFFIX)
|
|
35
39
|
MEAN = "mean"
|
|
36
40
|
VARIANCE = "variance"
|
|
37
41
|
MEDIAN = "median"
|
|
@@ -319,18 +319,12 @@ class GoodnessOfFitCases(ModelCheckCase, enum.Enum):
|
|
|
319
319
|
|
|
320
320
|
PASS = (
|
|
321
321
|
Status.PASS,
|
|
322
|
-
|
|
323
|
-
"R-squared = {r_squared:.4f}, MAPE = {mape:.4f}, and wMAPE ="
|
|
324
|
-
" {wmape:.4f}."
|
|
325
|
-
),
|
|
322
|
+
"R-squared = {r_squared:.4f}, MAPE = {mape:.4f}, and wMAPE = {wmape:.4f}",
|
|
326
323
|
_GOODNESS_OF_FIT_PASS_RECOMMENDATION,
|
|
327
324
|
)
|
|
328
325
|
REVIEW = (
|
|
329
326
|
Status.REVIEW,
|
|
330
|
-
|
|
331
|
-
"R-squared = {r_squared:.4f}, MAPE = {mape:.4f}, and wMAPE ="
|
|
332
|
-
" {wmape:.4f}."
|
|
333
|
-
),
|
|
327
|
+
"R-squared = {r_squared:.4f}, MAPE = {mape:.4f}, and wMAPE = {wmape:.4f}",
|
|
334
328
|
_GOODNESS_OF_FIT_REVIEW_RECOMMENDATION,
|
|
335
329
|
)
|
|
336
330
|
|
|
@@ -348,9 +342,28 @@ class GoodnessOfFitCheckResult(CheckResult):
|
|
|
348
342
|
"""The immutable result of the Goodness of Fit Check."""
|
|
349
343
|
|
|
350
344
|
case: GoodnessOfFitCases
|
|
345
|
+
is_holdout: bool = False
|
|
351
346
|
|
|
352
347
|
def __post_init__(self):
|
|
353
|
-
if
|
|
348
|
+
if self.is_holdout:
|
|
349
|
+
required_keys = []
|
|
350
|
+
for suffix in [
|
|
351
|
+
constants.ALL_SUFFIX,
|
|
352
|
+
constants.TRAIN_SUFFIX,
|
|
353
|
+
constants.TEST_SUFFIX,
|
|
354
|
+
]:
|
|
355
|
+
required_keys.extend([
|
|
356
|
+
f"{constants.R_SQUARED}_{suffix}",
|
|
357
|
+
f"{constants.MAPE}_{suffix}",
|
|
358
|
+
f"{constants.WMAPE}_{suffix}",
|
|
359
|
+
])
|
|
360
|
+
if any(key not in self.details for key in required_keys):
|
|
361
|
+
raise ValueError(
|
|
362
|
+
"The message template is missing required formatting arguments for"
|
|
363
|
+
f" holdout case. Required keys: {required_keys}. Details:"
|
|
364
|
+
f" {self.details}."
|
|
365
|
+
)
|
|
366
|
+
elif any(
|
|
354
367
|
key not in self.details
|
|
355
368
|
for key in (
|
|
356
369
|
constants.R_SQUARED,
|
|
@@ -364,6 +377,24 @@ class GoodnessOfFitCheckResult(CheckResult):
|
|
|
364
377
|
f" {self.details}."
|
|
365
378
|
)
|
|
366
379
|
|
|
380
|
+
@property
|
|
381
|
+
def recommendation(self) -> str:
|
|
382
|
+
"""Returns the check result message."""
|
|
383
|
+
if self.is_holdout:
|
|
384
|
+
report_str = (
|
|
385
|
+
"R-squared = {r_squared_all:.4f} (All),"
|
|
386
|
+
" {r_squared_train:.4f} (Train), {r_squared_test:.4f} (Test); MAPE"
|
|
387
|
+
" = {mape_all:.4f} (All), {mape_train:.4f} (Train),"
|
|
388
|
+
" {mape_test:.4f} (Test); wMAPE = {wmape_all:.4f} (All),"
|
|
389
|
+
" {wmape_train:.4f} (Train), {wmape_test:.4f} (Test)".format(
|
|
390
|
+
**self.details
|
|
391
|
+
)
|
|
392
|
+
)
|
|
393
|
+
else:
|
|
394
|
+
report_str = self.case.message_template.format(**self.details)
|
|
395
|
+
|
|
396
|
+
return f"{report_str}. {self.case.recommendation}"
|
|
397
|
+
|
|
367
398
|
|
|
368
399
|
# ==============================================================================
|
|
369
400
|
# Check: ROI Consistency
|
meridian/analysis/summarizer.py
CHANGED
|
@@ -21,11 +21,11 @@ import os
|
|
|
21
21
|
import jinja2
|
|
22
22
|
from meridian import constants as c
|
|
23
23
|
from meridian.analysis import analyzer
|
|
24
|
-
from meridian.analysis import formatter
|
|
25
24
|
from meridian.analysis import summary_text
|
|
26
25
|
from meridian.analysis import visualizer
|
|
27
26
|
from meridian.data import time_coordinates as tc
|
|
28
27
|
from meridian.model import model
|
|
28
|
+
from meridian.templates import formatter
|
|
29
29
|
import pandas as pd
|
|
30
30
|
import xarray as xr
|
|
31
31
|
|
meridian/analysis/visualizer.py
CHANGED
|
@@ -22,9 +22,9 @@ import altair as alt
|
|
|
22
22
|
from meridian import backend
|
|
23
23
|
from meridian import constants as c
|
|
24
24
|
from meridian.analysis import analyzer
|
|
25
|
-
from meridian.analysis import formatter
|
|
26
25
|
from meridian.analysis import summary_text
|
|
27
26
|
from meridian.model import model
|
|
27
|
+
from meridian.templates import formatter
|
|
28
28
|
import numpy as np
|
|
29
29
|
import pandas as pd
|
|
30
30
|
import xarray as xr
|