# Unpooled Accelerated Failure Time Model

**URL:** https://discourse.pymc.io/t/unpooled-accelerated-failure-time-model/16135
**Category:** version agnostic
**Created:** [November 19, 2024, 4:46am UTC](https://discourse.pymc.io/t/unpooled-accelerated-failure-time-model/16135 "2024-11-19T04:46:37Z")
**Posts on this page:** 4
**Page:** 2

<div class="post-metadata">

### Author: ![buckeye17](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/buckeye17/32/8206_2.png) [@buckeye17](https://discourse.pymc.io/u/buckeye17)
#### Post date: [November 23, 2024, 4:58am UTC](https://discourse.pymc.io/t/unpooled-accelerated-failure-time-model/16135/21 "2024-11-23T04:58:22Z")

</div>

Well, I spoke too soon. I assumed that if the sampler started then the model was valid. It turns out that the above model only produces an error once the sampler finishes running. Here’s the error message:

```auto
ValueError: conflicting sizes for dimension 'groups_flat': length 1354 on the data but length 3770 on coordinate 'groups_flat'

```

---

<div class="post-metadata">

### Author: ![ricardoV94](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/ricardov94/32/5775_2.png) [@ricardoV94](https://discourse.pymc.io/u/ricardoV94)
#### Post date: [November 24, 2024, 3:27pm UTC](https://discourse.pymc.io/t/unpooled-accelerated-failure-time-model/16135/22 "2024-11-24T15:27:05Z")

</div>

instead of doing shape.eval(), do eval().shape. The first can hide shape errors, the second won’t

---

<div class="post-metadata">

### Author: ![buckeye17](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/buckeye17/32/8206_2.png) [@buckeye17](https://discourse.pymc.io/u/buckeye17)
#### Post date: [November 25, 2024, 4:07pm UTC](https://discourse.pymc.io/t/unpooled-accelerated-failure-time-model/16135/23 "2024-11-25T16:07:04Z")

</div>

The models defined above will yield `(3770, 3770)` for `reg[:, group_idx].eval().shape` and yield `(3770, 5)` for `aft_model["reg"].eval().shape`. I don’t understand why they produce different results. Again `(3770, 5)` makes sense to me, so it seems `reg[:, group_idx].eval().shape` is not a helpful evaluation.

I’m happy to say that I figured out how to fix the latest error. I verified that the model is now able to do all forms of prior & posterior MCMC sampling. The fix came by splitting the `groups_flat` dimension into two dimensions named `groups_cens_flat` & `groups_uncens_flat`.

Here’s the final model:

````py
intervals = np.arange(12)
n_groups = 5
unique_groups = list(range(n_groups))
group_values = np.random.randint(n_groups, size=retention_df.shape[0])
group_idx = pd.Categorical(group_values, categories=unique_groups).codes
cens = [i for i, x in enumerate(retention_df.left) if x == 0.0]
uncens = [i for i, x in enumerate(retention_df.left) if x == 1.0]
coords = {
    "intervals": intervals,
    "groups": unique_groups,
    "groups_cens_flat": group_values[cens],
    "groups_uncens_flat": group_values[uncens],
    "preds": [
        "sentiment",
        "intention",
        "Male",
        "Low",
        "Medium",
        "Finance",
        "Health",
        "Law",
        "Public/Government",
        "Sales/Marketing",
    ],
}

X = retention_df[
    [
        "sentiment",
        "intention",
        "Male",
        "Low",
        "Medium",
        "Finance",
        "Health",
        "Law",
        "Public/Government",
        "Sales/Marketing",
    ]
].copy()
y = retention_df["month"].values

def weibull_lccdf(x, alpha, beta):
    """Log complementary cdf of Weibull distribution."""
    return -((x / beta) ** alpha)

with pm.Model(coords=coords, check_bounds=False) as aft_model:
    X_data = pm.MutableData("X_data_obs", X)
    beta = pm.Normal("beta", 0.0, 1, dims="preds")
    mu = pm.Normal("mu", 0, 1, dims="groups")
    s = pm.HalfNormal("s", 5.0, dims="groups")
    eta = pm.Deterministic("eta", pm.math.dot(beta, X_data.T))
    reg = pm.Deterministic("reg", pt.exp(-(mu[None, :] + eta[:, None]) / s[None, :]))
    y_obs = pm.Weibull(
        "y_obs",
        beta=reg[uncens, group_idx[uncens]],
        alpha=s[group_idx[uncens]],
        observed=y[uncens],
        dims="groups_uncens_flat"
    )
    y_cens = pm.Potential(
        "y_cens",
        weibull_lccdf(y[cens], alpha=s[group_idx[cens]], beta=reg[cens, group_idx[cens]]),
        dims="groups_cens_flat"
    )
    
    idata = pm.sample_prior_predictive()
    idata.extend(pm.sample())
    idata.extend(pm.sample_posterior_predictive(idata))
    ```
````

---

<div class="post-metadata">

### Author: ![ricardoV94](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/ricardov94/32/5775_2.png) [@ricardoV94](https://discourse.pymc.io/u/ricardoV94)
#### Post date: [November 25, 2024, 4:53pm UTC](https://discourse.pymc.io/t/unpooled-accelerated-failure-time-model/16135/24 "2024-11-25T16:53:04Z")

</div>

> [@buckeye17](#):
>
> I don’t understand why they produce different results

PyTensor assumes you have a valid shape graph, and gives you an output based on that assumption. In you case you had something invalid.

[https://pytensor.readthedocs.io/en/latest/tutorial/shape\_info.html#problems-with-shape-inference](https://pytensor.readthedocs.io/en/latest/tutorial/shape_info.html#problems-with-shape-inference)

[Previous page](https://discourse.pymc.io/t/unpooled-accelerated-failure-time-model/16135.md?page=1)
