Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prior and liklihood model transforms #159

Open
cscherrer opened this issue Aug 7, 2020 · 5 comments
Open

prior and liklihood model transforms #159

cscherrer opened this issue Aug 7, 2020 · 5 comments

Comments

@cscherrer
Copy link
Owner

Say you have a Soss model like

m = @model X,numGroups begin
    numFeatures = size(X,2)
    β ~ Normal() |> iid(numFeatures, numGroups)
    p = softmax.(eachrow(X*β))
    y ~ For(eachindex(p)) do j
            Categorical(p[j])
        end
end

What would you expect prior(m, :y) and likelihood(m, :y) to look like?

We haven't implemented likelihood yet, but for prior we currently get

julia> Soss.prior(m, :y)
@model (X, numGroups) begin
        numFeatures = size(X, 2)
        β ~ Normal() |> iid(numFeatures, numGroups)
        p = softmax.(eachrow(X * β))
    end

Intuitively, I think I'd want this to only include dependencies of β (so no p). It also feels wrong for the prior to include X. But the only way I see to get rid of it is to return a function "on the side" that's something like

deps(nt) = (numFeatures = size(nt.X, 2), )

The I'm trying to be so careful here is that we need to be able to do this sort of thing programmatically, e.g. only "knowing" that a given model turns an X into a y, so we can easily swap it out for another one.

Any thoughts?

@millerjoey @DilumAluthge

@DilumAluthge
Copy link
Collaborator

How about storing the numFeatures as part of the model itself, instead of reading it from X?

So, if the full model is:

m = @model X,numFeatures,numGroups begin
    @assert numFeatures == size(X,2)
    β ~ Normal() |> iid(numFeatures, numGroups)
    p = softmax.(eachrow(X*β))
    y ~ For(eachindex(p)) do j
            Categorical(p[j])
        end
end

Then I would expect the prior to be:

@model numFeatures,numGroups begin
    β ~ Normal() |> iid(numFeatures, numGroups)
end

And the likelihood will be:

@model X,numFeatures,numGroups begin
    @assert numFeatures == size(X,2)
    p = softmax.(eachrow(X*β))
    y ~ For(eachindex(p)) do j
            Categorical(p[j])
        end
end

It definitely would seem weird if the prior included X or p.

@cscherrer
Copy link
Owner Author

Models written like this are certainly easier to deal with. We can always put more responsibility on the users if we don't see a nice way for Soss to manage this sort of thing. So it's a sensible fallback.

Ideally, I'd love to have it so users don't have to worry about this, and Soss will "do the right thing".

@DilumAluthge
Copy link
Collaborator

Hmmm. If we don't have the user specify the number of features, then unfortunately the prior will depend on X, right?

@DilumAluthge
Copy link
Collaborator

Or, at least the prior will depend on size(X, 2).

@millerjoey
Copy link
Collaborator

Intuitively, I think I'd want this to only include dependencies of β (so no p). It also feels wrong for the prior to include X.

Are we happy with the behavior of before()? Maybe we need a better language to distinguish assignments from stochastic statements to relate it better to the more loaded terms like prior and likelihood.

prior(m::Model, xs...) = before(m, xs..., inclusive = true, strict = true, other_distinguishing_keywords...)

Also does

julia> Soss.before(m, , inclusive = true, strict = true)
@model (X, numGroups) begin
        numFeatures = size(X, 2)
        β ~ Normal() |> iid(numFeatures, numGroups)
    end

miss the point? Defaulting prior so it includes the named argument (like how we've discussed you prefer). This gets around the issue of Soss inferring how far "before" to go.

Can you elaborate on how we might do this:

The I'm trying to be so careful here is that we need to be able to do this sort of thing programmatically, e.g. only "knowing" that a given model turns an X into a y, so we can easily swap it out for another one.

It seems interesting but I'm not sure I'm visualizing it right.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants