Q1) ストキャスティクスに対するすべての引数の意味は、ここに文書化されています。deterministic への引数は同じで、追加の引数はここに記載されています。
Q2) 動作の違いは、実際にswitchpoint.logp
関数を実行して Python に変換property
するPyMC 内にいくつかの魔法がありswitchpoint.random
、この処理を受けず、関数として保持されることです。
実際に何が起こっているのか知りたい場合は、関連するソースの一部を次に示します。
def get_logp(self):
if self.verbose > 1:
print '\t' + self.__name__ + ': log-probability accessed.'
logp = self._logp.get()
if self.verbose > 1:
print '\t' + self.__name__ + ': Returning log-probability ', logp
try:
logp = float(logp)
except:
raise TypeError, self.__name__ + ': computed log-probability ' + str(logp) + ' cannot be cast to float'
if logp != logp:
raise ValueError, self.__name__ + ': computed log-probability is NaN'
# Check if the value is smaller than a double precision infinity:
if logp <= d_neg_inf:
if self.verbose > 0:
raise ZeroProbability, self.errmsg + ": %s" %self._parents.value
else:
raise ZeroProbability, self.errmsg
return logp
def set_logp(self,value):
raise AttributeError, 'Potential '+self.__name__+'\'s log-probability cannot be set.'
logp = property(fget = get_logp, fset=set_logp, doc="Self's log-probability value conditional on parents.")
logp
関数の間に a と呼ばれるものへの変換など、他にもいくつかのことが行われていますLazyFunction
が、それが基本的な考え方です。
Q3)stochastic
デコレータには、コードのイントロスペクションを使用してrandom
サブlogp
関数が内部で定義されているかどうかを判断するいくつかの (より多くの) 魔法がありswitchpoint
ます。そうである場合は、logp
サブ関数を使用して計算logp
し、そうでない場合は、それ自体を使用しswitchpoint
ます。そのソースコードはここにあります:
# This gets used by stochastic to check for long-format logp and random:
if probe:
# Define global tracing function (I assume this is for debugging??)
# No, it's to get out the logp and random functions, if they're in there.
def probeFunc(frame, event, arg):
if event == 'return':
locals = frame.f_locals
kwds.update(dict((k,locals.get(k)) for k in keys))
sys.settrace(None)
return probeFunc
sys.settrace(probeFunc)
# Get the functions logp and random (complete interface).
# Disable special methods to prevent the formation of a hurricane of Deterministics
cur_status = check_special_methods()
disable_special_methods()
try:
__func__()
except:
if 'logp' in keys:
kwds['logp']=__func__
else:
kwds['eval'] =__func__
# Reenable special methods.
if cur_status:
enable_special_methods()
for key in keys:
if not kwds.has_key(key):
kwds[key] = None
for key in ['logp', 'eval']:
if key in keys:
if kwds[key] is None:
kwds[key] = __func__
繰り返しになりますが、さらにいくつかのことが行われており、かなり複雑ですが、それが基本的な考え方です。