Skip to content

Commit 8611c5b

Browse files
committed
[Reliability Bayesian pymc-devs#474] added cost function plot and varied priors.
Signed-off-by: Nathaniel <[email protected]>
1 parent 71e4a35 commit 8611c5b

File tree

2 files changed

+675
-481
lines changed

2 files changed

+675
-481
lines changed

examples/case_studies/reliability_and_calibrated_prediction.ipynb

+624-471
Large diffs are not rendered by default.

examples/case_studies/reliability_and_calibrated_prediction.myst.md

+51-10
Original file line numberDiff line numberDiff line change
@@ -881,14 +881,17 @@ y = item_period_max["t"].values
881881
censored = ~item_period_max["failed"].values.astype(bool)
882882
883883
884-
priors = {"beta": [100, 15_000], "alpha": [2, 0.5, 0.02, 8]}
885-
priors_informative = {"beta": [9500, 12_000], "alpha": [2, 0.5, 0.02, 3]}
884+
priors = {"beta": [100, 15_000], "alpha": [4, 1, 0.02, 8]}
885+
priors_informative = {"beta": [10_000, 500], "alpha": [2, 0.5, 0.02, 3]}
886886
887887
888-
def make_model(p):
888+
def make_model(p, info=False):
889889
with pm.Model() as model:
890890
891-
beta = pm.Uniform("beta", p["beta"][0], p["beta"][1])
891+
if info:
892+
beta = pm.Normal("beta", p["beta"][0], p["beta"][1])
893+
else:
894+
beta = pm.Uniform("beta", p["beta"][0], p["beta"][1])
892895
alpha = pm.TruncatedNormal(
893896
"alpha", p["alpha"][0], p["alpha"][1], lower=p["alpha"][2], upper=p["alpha"][3]
894897
)
@@ -903,7 +906,7 @@ def make_model(p):
903906
904907
905908
idata, model = make_model(priors)
906-
idata_informative, model = make_model(priors_informative)
909+
idata_informative, model = make_model(priors_informative, info=True)
907910
```
908911

909912
```{code-cell} ipython3
@@ -914,10 +917,18 @@ idata
914917
az.plot_trace(idata, kind="rank_vlines");
915918
```
916919

920+
```{code-cell} ipython3
921+
az.plot_trace(idata_informative, kind="rank_vlines");
922+
```
923+
917924
```{code-cell} ipython3
918925
az.summary(idata)
919926
```
920927

928+
```{code-cell} ipython3
929+
az.summary(idata_informative)
930+
```
931+
921932
```{code-cell} ipython3
922933
joint_draws = az.extract_dataset(idata, group="posterior", num_samples=1000)[
923934
["alpha", "beta"]
@@ -1004,8 +1015,12 @@ ax1.hist(
10041015
)
10051016
ax1.set_title("Distribution of 10% failure Time", fontsize=20)
10061017
ax1.legend()
1007-
ax2.hist(hist_data["p05"], bins=30, ec="black", color="cyan", alpha=0.4, label="Uninformative")
1008-
ax2.hist(hist_data_info["p05"], bins=30, ec="black", color="pink", alpha=0.4, label="Informative")
1018+
ax2.hist(
1019+
hist_data["p05"], bins=30, ec="black", color="cyan", alpha=0.4, label="Uninformative Prior"
1020+
)
1021+
ax2.hist(
1022+
hist_data_info["p05"], bins=30, ec="black", color="pink", alpha=0.4, label="Informative Prior"
1023+
)
10091024
ax2.legend()
10101025
ax2.set_title("Distribution of 5% failure Time", fontsize=20)
10111026
wbf = WeibullFitter().fit(item_period_bearing_cage["t"] + 1e-25, item_period_bearing_cage["failed"])
@@ -1068,12 +1083,18 @@ output_df
10681083
```
10691084

10701085
```{code-cell} ipython3
1086+
def cost_func(failures, power):
1087+
### Imagined cost function for failing item e.g. refunds required
1088+
return -np.power(failures, power)
1089+
1090+
10711091
mosaic = """AAAA
1072-
BBBB"""
1092+
BBCC"""
10731093
fig, axs = plt.subplot_mosaic(mosaic=mosaic, figsize=(20, 12))
10741094
axs = [axs[k] for k in axs.keys()]
10751095
ax = axs[0]
10761096
ax1 = axs[1]
1097+
ax2 = axs[2]
10771098
10781099
ax.scatter(
10791100
output_df["alpha"],
@@ -1112,10 +1133,30 @@ ax1.hist(
11121133
output_df["expected"], ec="black", color="pink", label="Expected Count of Failures", bins=20
11131134
)
11141135
ax1.set_title("Uncertainty in the Posterior Prediction Interval of Failure Counts", fontsize=20)
1115-
ax1.legend();
1136+
ax1.legend()
1137+
1138+
ax2.set_title("Expected Costs Distribution(s) \nbased on implied Failure counts", fontsize=20)
1139+
ax2.hist(
1140+
cost_func(output_df["expected"], 2.3),
1141+
label="Cost(failures,2)",
1142+
color="royalblue",
1143+
alpha=0.3,
1144+
ec="black",
1145+
bins=20,
1146+
)
1147+
ax2.hist(
1148+
cost_func(output_df["expected"], 2),
1149+
label="Cost(failures,2.3)",
1150+
color="red",
1151+
alpha=0.5,
1152+
ec="black",
1153+
bins=20,
1154+
)
1155+
ax2.set_xlabel("$ cost")
1156+
ax2.legend()
11161157
```
11171158

1118-
The choice of model in such cases is crucial. The decision about which failure profile is apt has to be informed by a subject matter expert because extrapolation from such sparse data is always risky. An understanding of the uncertainty is crucial if real costs attach to the failures and the subject matter expert is usually better placed to tell if you 2 or 7 failures can be expected within 600 hours of service.
1159+
The choice of model in such cases is crucial. The decision about which failure profile is apt has to be informed by a subject matter expert because extrapolation from such sparse data is always risky. An understanding of the uncertainty is crucial if real costs attach to the failures and the subject matter expert is usually better placed to tell if you 2 or 7 failures can be plausibly expected within 600 hours of service.
11191160

11201161
# Conclusion
11211162

0 commit comments

Comments
 (0)