google-meridian 1.3.1__py3-none-any.whl → 1.4.0__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.
Files changed (74) hide show
  1. {google_meridian-1.3.1.dist-info → google_meridian-1.4.0.dist-info}/METADATA +13 -9
  2. google_meridian-1.4.0.dist-info/RECORD +108 -0
  3. {google_meridian-1.3.1.dist-info → google_meridian-1.4.0.dist-info}/top_level.txt +1 -0
  4. meridian/analysis/__init__.py +1 -2
  5. meridian/analysis/analyzer.py +0 -1
  6. meridian/analysis/optimizer.py +5 -3
  7. meridian/analysis/review/checks.py +81 -30
  8. meridian/analysis/review/constants.py +4 -0
  9. meridian/analysis/review/results.py +40 -9
  10. meridian/analysis/summarizer.py +8 -3
  11. meridian/analysis/test_utils.py +934 -485
  12. meridian/analysis/visualizer.py +11 -7
  13. meridian/backend/__init__.py +53 -5
  14. meridian/backend/test_utils.py +72 -0
  15. meridian/constants.py +2 -0
  16. meridian/data/load.py +2 -0
  17. meridian/data/test_utils.py +82 -10
  18. meridian/model/__init__.py +2 -0
  19. meridian/model/context.py +925 -0
  20. meridian/model/eda/__init__.py +0 -1
  21. meridian/model/eda/constants.py +13 -2
  22. meridian/model/eda/eda_engine.py +299 -37
  23. meridian/model/eda/eda_outcome.py +21 -1
  24. meridian/model/equations.py +418 -0
  25. meridian/model/knots.py +75 -47
  26. meridian/model/model.py +93 -792
  27. meridian/{analysis/templates → templates}/card.html.jinja +1 -1
  28. meridian/{analysis/templates → templates}/chart.html.jinja +1 -1
  29. meridian/{analysis/templates → templates}/chips.html.jinja +1 -1
  30. meridian/{analysis → templates}/formatter.py +12 -1
  31. meridian/templates/formatter_test.py +216 -0
  32. meridian/{analysis/templates → templates}/insights.html.jinja +1 -1
  33. meridian/{analysis/templates → templates}/stats.html.jinja +1 -1
  34. meridian/{analysis/templates → templates}/style.css +1 -1
  35. meridian/{analysis/templates → templates}/style.scss +1 -1
  36. meridian/{analysis/templates → templates}/summary.html.jinja +4 -2
  37. meridian/{analysis/templates → templates}/table.html.jinja +1 -1
  38. meridian/version.py +1 -1
  39. scenarioplanner/__init__.py +42 -0
  40. scenarioplanner/converters/__init__.py +25 -0
  41. scenarioplanner/converters/dataframe/__init__.py +28 -0
  42. scenarioplanner/converters/dataframe/budget_opt_converters.py +383 -0
  43. scenarioplanner/converters/dataframe/common.py +71 -0
  44. scenarioplanner/converters/dataframe/constants.py +137 -0
  45. scenarioplanner/converters/dataframe/converter.py +42 -0
  46. scenarioplanner/converters/dataframe/dataframe_model_converter.py +70 -0
  47. scenarioplanner/converters/dataframe/marketing_analyses_converters.py +543 -0
  48. scenarioplanner/converters/dataframe/rf_opt_converters.py +314 -0
  49. scenarioplanner/converters/mmm.py +743 -0
  50. scenarioplanner/converters/mmm_converter.py +58 -0
  51. scenarioplanner/converters/sheets.py +156 -0
  52. scenarioplanner/converters/test_data.py +714 -0
  53. scenarioplanner/linkingapi/__init__.py +47 -0
  54. scenarioplanner/linkingapi/constants.py +27 -0
  55. scenarioplanner/linkingapi/url_generator.py +131 -0
  56. scenarioplanner/mmm_ui_proto_generator.py +354 -0
  57. schema/__init__.py +15 -0
  58. schema/mmm_proto_generator.py +71 -0
  59. schema/model_consumer.py +133 -0
  60. schema/processors/__init__.py +77 -0
  61. schema/processors/budget_optimization_processor.py +832 -0
  62. schema/processors/common.py +64 -0
  63. schema/processors/marketing_processor.py +1136 -0
  64. schema/processors/model_fit_processor.py +367 -0
  65. schema/processors/model_kernel_processor.py +117 -0
  66. schema/processors/model_processor.py +412 -0
  67. schema/processors/reach_frequency_optimization_processor.py +584 -0
  68. schema/test_data.py +380 -0
  69. schema/utils/__init__.py +1 -0
  70. schema/utils/date_range_bucketing.py +117 -0
  71. google_meridian-1.3.1.dist-info/RECORD +0 -76
  72. meridian/model/eda/meridian_eda.py +0 -220
  73. {google_meridian-1.3.1.dist-info → google_meridian-1.4.0.dist-info}/WHEEL +0 -0
  74. {google_meridian-1.3.1.dist-info → google_meridian-1.4.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,133 @@
1
+ # Copyright 2025 The Meridian Authors.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Consumes a trained Meridian model and produces an `Mmm` proto.
16
+
17
+ The `Mmm` proto contains parts collected from the core model as well as
18
+ analysis results from trained model processors.
19
+ """
20
+
21
+ from collections.abc import Mapping, Sequence
22
+ import functools
23
+ import inspect
24
+ from typing import Any, Generic, TypeAlias, TypeVar
25
+
26
+ from meridian.model import model
27
+ from mmm.v1 import mmm_pb2 as mmm_pb
28
+ from schema.processors import model_kernel_processor
29
+ from schema.processors import model_processor
30
+
31
+
32
+ __all__ = [
33
+ "ModelConsumer",
34
+ ]
35
+
36
+
37
+ SpecType: TypeAlias = type[model_processor.Spec]
38
+ ProcType = TypeVar("ProcType", bound=type[model_processor.ModelProcessor])
39
+
40
+
41
+ class ModelConsumer(Generic[ProcType]):
42
+ """Consumes a trained Meridian model and produces an `Mmm` proto.
43
+
44
+ Attributes:
45
+ model_processors: A preset list of model processor types.
46
+ """
47
+
48
+ def __init__(
49
+ self,
50
+ model_processors_classes: Sequence[ProcType],
51
+ ):
52
+ self._model_processors_classes = model_processors_classes
53
+
54
+ @functools.cached_property
55
+ def specs_to_processors_classes(
56
+ self,
57
+ ) -> dict[SpecType, ProcType]:
58
+ """Returns a mapping of spec types to their corresponding processor types.
59
+
60
+ Raises:
61
+ ValueError: If multiple model processors are found for the same spec type.
62
+ """
63
+ specs_to_processors_classes = {}
64
+ for processor_class in self._model_processors_classes:
65
+ if (
66
+ specs_to_processors_classes.get(processor_class.spec_type())
67
+ is not None
68
+ ):
69
+ raise ValueError(
70
+ "Multiple model processors found for spec type:"
71
+ f" {processor_class.spec_type()}"
72
+ )
73
+ specs_to_processors_classes[processor_class.spec_type()] = processor_class
74
+ return specs_to_processors_classes
75
+
76
+ def __call__(
77
+ self,
78
+ mmm: model.Meridian,
79
+ specs: Sequence[model_processor.Spec],
80
+ model_id: str = "",
81
+ ) -> mmm_pb.Mmm:
82
+ """Produces an `Mmm` schema for the model along with its analyses results.
83
+
84
+ Args:
85
+ mmm: A trained Meridian model. A trained model has its posterior
86
+ distributions already sampled.
87
+ specs: A sequence of specs that specify the analyses to run on the model.
88
+ Specs of the same type will be grouped together and executed together by
89
+ the corresponding model processor.
90
+ model_id: An optional model identifier.
91
+
92
+ Returns:
93
+ A proto containing the model kernel at rest and its analysis results.
94
+ """
95
+
96
+ # Group specs by their type.
97
+ specs_by_type = {}
98
+ for spec in specs:
99
+ specs_by_type.setdefault(spec.__class__, []).append(spec)
100
+
101
+ tmodel = model_processor.TrainedModel(mmm)
102
+ processor_params = {
103
+ "trained_model": tmodel,
104
+ }
105
+
106
+ output = mmm_pb.Mmm()
107
+ # Attach the model kernel to the Mmm proto.
108
+ model_kernel_processor.ModelKernelProcessor(mmm, model_id)(output)
109
+
110
+ # Perform analysis or optimization.
111
+ for spec_type, specs in specs_by_type.items():
112
+ processor_type = self.specs_to_processors_classes[spec_type]
113
+ processor = _create_processor(processor_type, processor_params)
114
+ # Attach the output of the processor to the output proto.
115
+ processor(specs, output)
116
+
117
+ return output
118
+
119
+
120
+ def _create_processor(
121
+ processor_type: ProcType,
122
+ processor_params: Mapping[str, Any],
123
+ ) -> model_processor.ModelProcessor:
124
+ """Creates a processor of the given type with a subset of the given params."""
125
+ # Clone the given parameters dict first.
126
+ params = dict(processor_params)
127
+ # Remove any parameters that are not in the processor's constructor signature.
128
+ sig = inspect.signature(processor_type.__init__)
129
+ if not any(p.kind == p.VAR_KEYWORD for p in sig.parameters.values()):
130
+ for missing in params.keys() - sig.parameters.keys():
131
+ del params[missing]
132
+ # Finally, construct the concrete processor.
133
+ return processor_type(**params)
@@ -0,0 +1,77 @@
1
+ # Copyright 2025 The Meridian Authors.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Meridian Model Processor Library.
16
+
17
+ This package provides a collection of processors designed to operate on trained
18
+ Meridian models. These processors facilitate various post-training tasks,
19
+ including model analysis, insight generation, and budget optimization.
20
+
21
+ The processors are built upon a common framework defined in the
22
+ `model_processor` module, which establishes the base classes and interfaces for
23
+ builtin processors in this package, as well as for creating custom processors.
24
+ Each processor typically takes a trained Meridian model object and additional
25
+ specifications as input, producing structured output, in protobuf format.
26
+
27
+ These structured outputs can then be used to generate insights, visualizations,
28
+ and other artifacts that help users understand and optimize their marketing
29
+ strategy. For instance, the `schema.converters` package provides tools to
30
+ flatten these outputs into tabular Google Sheets tables suitable for a Meridian
31
+ Looker Studio dashboard's data sources.
32
+
33
+ Available Processor Modules:
34
+
35
+ - `model_processor`: Defines the abstract base classes `ModelProcessor` and
36
+ `ModelProcessorSpec`, which serve as the foundation for all processors
37
+ in this package.
38
+ - `model_kernel_processor`: A processor to extract and serialize the core
39
+ components and parameters of the trained Meridian model.
40
+ - `model_fit_processor`: Generates various goodness-of-fit statistics and
41
+ diagnostic metrics for the trained model.
42
+ - `marketing_processor`: Performs marketing mix analysis, including
43
+ contribution analysis, response curves, and ROI calculations.
44
+ - `budget_optimization_processor`: Provides tools for optimizing marketing
45
+ budgets based on the model's predictions to achieve specific goals.
46
+ - `reach_frequency_processor`: Analyzes and optimizes based on reach and
47
+ frequency metrics, if applicable to the model structure.
48
+
49
+ Each processor defines its own spec language. For instance, the budget
50
+ optimization processor would take a `BudgetOptimizationSpec` object as input,
51
+ which defines the constraints and parameters of the optimization problem a
52
+ user wants to explore.
53
+
54
+ A trained Meridian model is generally a requisite input for all processors.
55
+ Generally, a `model_processor.TrainedModel` wrapper object is passed to each
56
+ processor, along with its processor-specific spec. For example:
57
+
58
+ ```python
59
+ # Assuming 'trained_model' is a loaded Meridian model object
60
+ processor = model_fit_processor.ModelFitProcessor(trained_model)
61
+ result = processor([model_fit_processor.ModelFitSpec()])
62
+
63
+ # `result` is a structured `ModelFit` proto that describes the model's goodness
64
+ # of fit analysis.
65
+ ```
66
+
67
+ For more details on these processors' sub-API, please refer to the documentation
68
+ of the individual modules.
69
+ """
70
+
71
+ from schema.processors import budget_optimization_processor
72
+ from schema.processors import common
73
+ from schema.processors import marketing_processor
74
+ from schema.processors import model_fit_processor
75
+ from schema.processors import model_kernel_processor
76
+ from schema.processors import model_processor
77
+ from schema.processors import reach_frequency_optimization_processor