Skip to content

Commit d5c5742

Browse files
authored
Merge pull request #1 from davidprueser/mpe
made return values from mpe and _mpe consistent
2 parents af02a13 + 6a1e095 commit d5c5742

7 files changed

Lines changed: 51 additions & 42 deletions

File tree

doc/source/mlflow_integration.rst

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,17 @@ MLFlow Integration
44
JPTs can be integrated with MLFlow to manage the full model lifecycle.
55
Among other things Hyperparameters and the model itself can be logged using a python wrapper.
66

7-
A full tutorial is be found here
7+
In order to integrate JPTs with MLFlow, MLFlow needs to be installed. This can be done by either installing the
8+
``pyjpt`` package with MLFlow being added as an extra requirement
9+
10+
.. code:: bash
11+
12+
$ pip install pyjpt[mlflow]
13+
14+
or by installing the MLFlow package manually.
15+
16+
17+
A full tutorial on the MLFlow integration can be found here
818

919
.. toctree::
1020

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,5 @@ def requirements():
114114
long_description=__description__,
115115
package_data={'jpt': ['.version']},
116116
include_package_data=True,
117+
extras_require={'mlflow': ['mlflow >= 2.5.0']}
117118
)

src/jpt/distributions/univariate/integer.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -250,20 +250,19 @@ def _variance(self) -> float:
250250
e = self._expectation()
251251
return sum((v - e) ** 2 * p for v, p in zip(self.values.values(), self.probabilities))
252252

253-
def mpe(self) -> (float, Set[int]):
254-
p_max, lbls = self._mpe()
255-
return p_max, self.value2label(lbls)
253+
def mpe(self) -> (Set[int], float):
254+
lbls, p_max = self._mpe()
255+
return self.value2label(lbls), p_max
256256

257-
def _mpe(self) -> (float, Set[int]):
257+
def _mpe(self) -> (Set[int], float):
258258
p_max = max(self.probabilities)
259259
return (
260-
p_max,
261260
{
262261
l for l, p in zip(
263262
self.values.values(),
264263
self.probabilities
265264
) if p == p_max
266-
}
265+
}, p_max
267266
)
268267

269268
mode = mpe

src/jpt/distributions/univariate/multinomial.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ def _sample_one(self) -> Symbol:
279279
@deprecated('Expectation is undefined in symbolic domains. Use Multinomial._mode() instead.')
280280
def _expectation(self) -> Set[int]:
281281
'''Returns the value with the highest probability for this variable'''
282-
return self._mpe()[1]
282+
return self._mpe()[0]
283283

284284
@deprecated('Expectation is undefined in symbolic domains. Use Multinomial._mode() instead.')
285285
def expectation(self) -> Set[Symbol]:
@@ -291,25 +291,24 @@ def expectation(self) -> Set[Symbol]:
291291
self._expectation()
292292
)
293293

294-
def mpe(self) -> Tuple[float, Set[Symbol]]:
295-
p_max, values = self._mpe()
296-
return p_max, self.value2label(values)
294+
def mpe(self) -> Tuple[Set[Symbol], float]:
295+
values, p_max = self._mpe()
296+
return self.value2label(values), p_max
297297

298-
def _mpe(self) -> Tuple[float, Set[int]]:
298+
def _mpe(self) -> Tuple[Set[int], float]:
299299
"""
300300
Calculate the most probable configuration of this distribution in value space.
301301
302-
:return: The likelihood of the mpe as float and the mpe itself as Set
302+
:return: The likelihood of the mpe itself as Set and the likelihood of the mpe as float
303303
"""
304304
_max = max(self.probabilities)
305305
return (
306-
_max,
307306
set(
308307
[label for label, p in zip(
309308
self.values.values(),
310309
self.probabilities
311310
) if p == _max]
312-
)
311+
), _max
313312
)
314313

315314
mode = mpe

src/jpt/distributions/univariate/numeric.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from ...base.functions import __module__
2121
except ModuleNotFoundError:
2222
import pyximport
23+
2324
pyximport.install()
2425
finally:
2526
from ...base.intervals import R, ContinuousSet, RealSet, NumberSet
@@ -112,10 +113,10 @@ def label2value(
112113
@classmethod
113114
def equiv(cls, other):
114115
return (
115-
issubclass(other, Numeric) and
116-
cls.__name__ == other.__name__ and
117-
cls.values == other.values and
118-
cls.labels == other.labels
116+
issubclass(other, Numeric) and
117+
cls.__name__ == other.__name__ and
118+
cls.values == other.values and
119+
cls.labels == other.labels
119120
)
120121

121122
@property
@@ -175,18 +176,17 @@ def is_dirac_impulse(self) -> bool:
175176
"""Checks if this distribution is a dirac impulse."""
176177
return len(self._quantile.cdf.intervals) == 2
177178

178-
def mpe(self) -> (float, RealSet):
179+
def mpe(self) -> (RealSet, float):
179180
return self._mpe(self.value2label)
180181

181-
def _mpe(self, value_transform: Optional[Callable] = None) -> (float, NumberSet):
182+
def _mpe(self, value_transform: Optional[Callable] = None) -> (NumberSet, float):
182183
"""
183184
Calculate the most probable configuration of this quantile distribution.
184-
:return: The likelihood of the mpe as float and the mpe itself as RealSet
185+
:return: The mpe itself as RealSet and the likelihood of the mpe as float
185186
"""
186187
value_transform = ifnone(value_transform, lambda _: _)
187188
_max = max(f.value for f in self.pdf.functions)
188189
return (
189-
_max,
190190
value_transform(
191191
RealSet(
192192
[
@@ -196,7 +196,7 @@ def _mpe(self, value_transform: Optional[Callable] = None) -> (float, NumberSet)
196196
if function.value == _max
197197
]
198198
).simplify()
199-
)
199+
), _max
200200
)
201201

202202
def _fit(
@@ -236,8 +236,8 @@ def _p(self, value: Union[numbers.Number, NumberSet]) -> numbers.Real:
236236
if probspace.isdisjoint(value):
237237
return 0
238238
probmass = (
239-
(self.cdf.eval(value.upper) if value.upper != np.PINF else 1.) -
240-
(self.cdf.eval(value.lower) if value.lower != np.NINF else 0.)
239+
(self.cdf.eval(value.upper) if value.upper != np.PINF else 1.) -
240+
(self.cdf.eval(value.lower) if value.lower != np.NINF else 0.)
241241
)
242242
if not probmass:
243243
return probspace in value
@@ -524,10 +524,10 @@ def _moment(
524524
# We have to "stretch" the pdf value over the interval in label space:
525525
function_value = function.value * interval.width / interval_.width
526526
result += (
527-
(
528-
pow(interval_.upper - center, order + 1)
529-
- pow(interval_.lower - center, order + 1)
530-
) * function_value / (order + 1)
527+
(
528+
pow(interval_.upper - center, order + 1)
529+
- pow(interval_.lower - center, order + 1)
530+
) * function_value / (order + 1)
531531
)
532532
return result
533533

src/jpt/trees.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ def conditional_leaf(self, evidence: VariableAssignment) -> 'Leaf':
616616

617617
return result
618618

619-
def mpe(self, minimal_distances: VariableMap) -> (float, VariableMap):
619+
def mpe(self, minimal_distances: VariableMap) -> (VariableMap, float):
620620
"""
621621
Calculate the most probable explanation of this leaf as a fully factorized distribution.
622622
:return: the likelihood of the maximum as a float and the configuration as a VariableMap
@@ -630,7 +630,7 @@ def mpe(self, minimal_distances: VariableMap) -> (float, VariableMap):
630630
for variable, distribution in self.distributions.items():
631631

632632
# calculate mpe of that distribution
633-
likelihood, explanation = distribution.mpe()
633+
explanation, likelihood = distribution.mpe()
634634

635635
# apply upper cap for infinities
636636
likelihood = minimal_distances[variable] if likelihood == float("inf") else likelihood
@@ -642,7 +642,7 @@ def mpe(self, minimal_distances: VariableMap) -> (float, VariableMap):
642642
maximum[variable] = explanation
643643

644644
# create mpe result
645-
return result_likelihood, LabelAssignment(maximum.items())
645+
return LabelAssignment(maximum.items()), result_likelihood
646646

647647
def number_of_parameters(self) -> int:
648648
"""
@@ -1235,13 +1235,13 @@ def mpe(
12351235
maxima = [leaf.mpe(self.minimal_distances) for leaf in conditional_jpt.leaves.values()]
12361236

12371237
# get the maximum of those maxima
1238-
highest_likelihood = max([m[0] for m in maxima])
1238+
highest_likelihood = max([m[1] for m in maxima])
12391239

12401240
# create a list for all possible maximal occurrences
12411241
results = []
12421242

12431243
# for every leaf and its mpe
1244-
for leaf, (likelihood, mpe) in zip(conditional_jpt.leaves.values(), maxima):
1244+
for leaf, (mpe, likelihood) in zip(conditional_jpt.leaves.values(), maxima):
12451245

12461246
if likelihood == highest_likelihood:
12471247
# append the argmax to the results

test/test_distributions.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,8 @@ def test_mpe(self):
169169
result_uniform = abc.mpe()
170170

171171
# Assert
172-
self.assertEqual((1 / 2, {'A'}), result_unique)
173-
self.assertEqual((1 / 3, {'A', 'B', 'C'}), result_uniform)
172+
self.assertEqual(({'A'}, 1 / 2), result_unique)
173+
self.assertEqual(({'A', 'B', 'C'}, 1 / 3), result_uniform)
174174

175175
def test_expectation(self):
176176
# Arrange
@@ -713,7 +713,7 @@ def test_mpe(self):
713713
)
714714

715715
# Act
716-
likelihood, mpe_state = dist.mpe()
716+
mpe_state, likelihood = dist.mpe()
717717

718718
# Assert
719719
self.assertEqual(
@@ -884,10 +884,10 @@ def test_mpe(self):
884884
biased_dice.set([0 / 6, 1 / 6, 2 / 6, 1 / 6, 1 / 6, 1 / 6])
885885

886886
# Act
887-
p_fair, fair_mpe = fair_dice.mpe()
888-
_p_fair, _fair_mpe = fair_dice._mpe()
889-
p_biased, biased_mpe = biased_dice.mpe()
890-
_p_biased, _biased_mpe = biased_dice._mpe()
887+
fair_mpe, p_fair = fair_dice.mpe()
888+
_fair_mpe, _p_fair = fair_dice._mpe()
889+
biased_mpe, p_biased = biased_dice.mpe()
890+
_biased_mpe, _p_biased = biased_dice._mpe()
891891

892892
# Assert
893893
self.assertEqual(set(range(1, 7)), fair_mpe)

0 commit comments

Comments
 (0)