Ich versuche, eine DST für die probablistische Programmierung von Jared Tobin blog post inspiriert zu implementieren.Modellierung Beobachtung für probabilistische Programmiersprache mit freien Monaden
Ein freies Monade für eine DST die Bernoulli und Beta-Verteilung einschließlich könnte wie folgt aussehen:
data ModelF r =
BernoulliF Double (Bool -> r)
| BetaF Double Double (Double -> r)
deriving (Functor)
type Model = Free ModelF
bernoulli :: Double -> Model Bool
bernoulli p = liftF (BernoulliF p id)
beta :: Double -> Double -> Model Double
beta a b = liftF (BetaF a b id)
ich es verlängern möchten Beobachtung auf Ausschüttungen zu unterstützen. Das heißt: erzwinge einen bestimmten Rückgabewert.
Erster Versuch war die Funktors zu verlängern:
data ModelF r =
BernoulliF Double (Bool -> r)
| BetaF Double Double (Double -> r)
| ObsF (ModelF r) r
deriving (Functor)
Diese Problematik ist jedoch, da es für eine rekursive Verschachtelung von ObsF
ermöglicht.
Eine Lösung wäre, den freien Monade in eine andere freie Monade heben einen beobachteten Wert darstellt:
data ObsModelF r =
PureF (Model r)
| ObsF (Model r) r
deriving (Functor)
observe :: Model r -> r -> Free ObsModelF r
observe model o = liftF (ObsF model o)
Die Syntax ich nach obwohl bin ist:
let dist = do
p <- beta 1 1
observe (bernoulli p) True
Dies ist unvereinbar mit ObsModelF
seit beta 1 1
sollte auch in ObsModelF
gehoben werden. Dies erfordert zwei separate Konstruktoren: einen für Verteilungen ohne Beobachtung und einen mit einer Beobachtung. Ist es möglich, diese Komplexität in der Sommerzeit zu vermeiden?
Ein dritter Versuch. Diesmal wickle ich den Verteilungsfunktor (ModelF
) in den Beobachtungsfunktor ein, den ich dann anhebe (ObsModelF
). ich einige Art Fehler ich allerdings recht nicht verstehen (die Kommentare sehen):
data ModelF r =
BernoulliF Double (Bool -> r)
| BetaF Double Double (Double -> r)
deriving (Functor)
data ObsModelF r =
PureF (ModelF r)
| ObsF (ModelF r) r
deriving (Functor)
type ObsModel = Free ObsModelF
bernoulli :: Double -> ObsModel Bool
bernoulli p = liftF . PureF $ BernoulliF p id
beta :: Double -> Double -> ObsModel Double
beta a b = liftF . PureF $ BetaF a b id
observe :: ObsModel r -> r -> ObsModel r
observe f o = liftF $ case f of
(Free f') -> case f' of
(PureF f'') -> ObsF f'' o -----| Couldn't match expected type ‘Free ObsModelF r’
(ObsF f'' o') -> ObsF f'' o --| with actual type ‘r’
toSampler :: (RandomGen g) => ObsModel r -> State g r
toSampler = iterM $ \case
ObsF a o -> case a of
BernoulliF p f -> return o >>= f -----| Couldn't match type ‘StateT g Data.Functor.Identity.Identity r’
BetaF a b f -> return o >>= f --| with ‘Bool’
PureF a -> case a of
BernoulliF p f -> MWC.bernoulli p >>= f
BetaF a b f -> MWC.beta a b >>= f
ich einen sehr einfachen Interpreter enthalten haben (toSampler
). Derzeit ignoriert es die Verteilung vollständig und bildet nur den Beobachtungswert ab. Bitte beachten Sie, dass dies nicht das beabsichtigte Verhalten beim Konditionieren einer Distribution ist. Es wird nur gezeigt, wie der Interpreter die freie Struktur durchqueren würde.
Ich bin nicht sicher über die Semantik, die Sie vom Typ 'ObsModelF' erwarten. Könnten Sie einen Dolmetscher schreiben? Was ist falsch daran, 'beta 1 1' mit' PureF' oder einer 'lift'-ähnlichen Funktion zu verpacken? –
Ich möchte eine willkürliche Verteilung beobachten. Wenn ich alle Distributionen mit 'Pure' (sowohl mit Bernoulli als auch mit Beta) aufheben würde, müsste ich Bernoulli auspacken, um es wieder mit' ObsF' zu heben. Es scheint wie eine Menge Operationen für eine einfache Aufgabe. Was ich erreichen möchte, ist, einen 'ModelF r'-Rückgabewert zu fixieren, indem man es als beobachtet' markiert '. Ich kann versuchen, mehr im Fragekörper auszuarbeiten. – tmpethick
Vom Lesen des Blogposts und von einigem mehr Materialien habe ich eine Idee von, was es bedeutet zu "beobachten", aber ich kann das nicht mit deinem Typ im Moment folglich vereinbaren Warum habe ich darum gebeten, einen Dolmetscher zu haben? Darüber hinaus kann das Wrapping/Entpacken normalerweise ziemlich einfach vom Sprachbenutzer ausgeblendet werden, aber es ist einfacher, einen geeigneten Weg zu finden, um die API zu bereinigen, wenn es zuerst eine funktionierende Implementierung gibt. –