条件付けと推論¶
条件付き化¶
conditionalization() は同時状態を核にします。
concat_start_index は、新しい codomain の先頭になる codomain 因子の
1 始まりの位置です。それより前の因子が domain になります。codomain の和が 0 の
スライスは 0 のままで、is_markov() はその行を
許容します。受け手は状態である必要があります。
import numpy as np
from fxtensor_salmon import FXTensor
location_labels = ["Urban", "Rural"]
season_labels = ["Spring", "Summer", "Other"]
weather_labels = ["Sunny", "Rainy"]
joint = FXTensor(
[[], [location_labels, season_labels, weather_labels]],
data=np.array(
[
[[0.08, 0.04], [0.12, 0.04], [0.08, 0.04]],
[[0.06, 0.12], [0.12, 0.12], [0.06, 0.12]],
]
),
)
cond_tensor = joint.conditionalization(concat_start_index=3)
assert cond_tensor.labels == ([location_labels, season_labels], [weather_labels])
assert cond_tensor.is_markov()
assert np.allclose(
cond_tensor.data,
[
[[2 / 3, 1 / 3], [0.75, 0.25], [2 / 3, 1 / 3]],
[[1 / 3, 2 / 3], [0.50, 0.50], [1 / 3, 2 / 3]],
],
)
joint_state = FXTensor([[], [2, 2]], data=np.array([[0.1, 0.2], [0.0, 0.0]]))
kernel = joint_state.conditionalization(2)
assert kernel.profile == [[2], [2]]
assert kernel.is_markov()
assert np.allclose(kernel.data, [[1 / 3, 2 / 3], [0.0, 0.0]])
not_a_state = FXTensor([[2], [2]], data=np.eye(2))
try:
not_a_state.conditionalization(1)
except ValueError:
pass
else:
raise AssertionError("conditionalization requires a state")
核の条件付け¶
conditional() は、核 f: A → X ⊗ Y に対する
同じ分割です。結果の domain は A ⊗ X です。状態に対しては
conditionalization と一致します。
import numpy as np
from fxtensor_salmon import FXTensor
location_labels = ["Urban", "Rural"]
season_labels = ["Spring", "Summer", "Other"]
weather_labels = ["Sunny", "Rainy"]
joint = FXTensor(
[[], [location_labels, season_labels, weather_labels]],
data=np.array(
[
[[0.08, 0.04], [0.12, 0.04], [0.08, 0.04]],
[[0.06, 0.12], [0.12, 0.12], [0.06, 0.12]],
]
),
)
cond_tensor = joint.conditionalization(concat_start_index=3)
assert cond_tensor.labels == ([location_labels, season_labels], [weather_labels])
assert cond_tensor.is_markov()
assert np.allclose(
cond_tensor.data,
[
[[2 / 3, 1 / 3], [0.75, 0.25], [2 / 3, 1 / 3]],
[[1 / 3, 2 / 3], [0.50, 0.50], [1 / 3, 2 / 3]],
],
)
joint_state = FXTensor([[], [2, 2]], data=np.array([[0.1, 0.2], [0.0, 0.0]]))
kernel = joint_state.conditionalization(2)
assert kernel.profile == [[2], [2]]
assert kernel.is_markov()
assert np.allclose(kernel.data, [[1 / 3, 2 / 3], [0.0, 0.0]])
not_a_state = FXTensor([[2], [2]], data=np.eye(2))
try:
not_a_state.conditionalization(1)
except ValueError:
pass
else:
raise AssertionError("conditionalization requires a state")
ベイズ反転¶
事前状態 p: I → X と核 f: X → Y に対し、
bayesian_inversion() は次の f†: Y → X を
返します。
f†(x|y) = p(x) f(y|x) / Σ_x' p(x') f(y|x')
証拠が 0 の行は 0 のままです。X のラベルは、f がラベル付きなら f から、
そうでなければ事前状態から取ります。このメソッドが返すテンソルでは、有限の等式
p ; copy ; (id ⊗ f) = p ; f ; copy ; (f† ⊗ id) が成り立ちます。
ベイズ反転: p ; copy ; (id ⊗ f) = p ; f ; copy ; (f† ⊗ id)。¶
import numpy as np
from fxtensor_salmon import FXTensor
health = ["Sick", "Healthy"]
result = ["Positive", "Negative"]
prior = FXTensor([[], [health]], data=np.array([0.01, 0.99]))
test = FXTensor([[health], [result]], data=np.array([[0.9, 0.1], [0.05, 0.95]]))
posterior = test.bayesian_inversion(prior)
assert posterior.labels == ([result], [health])
assert np.isclose(posterior.data[0, 0], 2 / 13)
x = prior.labels[1]
y = test.labels[1]
forward = prior.composition(FXTensor.copy_tensor(x)).composition(
FXTensor.identity_tensor(x).tensor_product(test)
)
backward = prior.composition(test).composition(FXTensor.copy_tensor(y)).composition(
posterior.tensor_product(FXTensor.identity_tensor(y))
)
assert forward == backward
point = FXTensor([[], [2]], data=np.array([1.0, 0.0]))
kernel = FXTensor([[2], [2]], data=np.array([[0.0, 1.0], [0.3, 0.7]]))
inverted = kernel.bayesian_inversion(point)
assert np.allclose(inverted.data[0], [0.0, 0.0])
assert np.allclose(inverted.data[1], [1.0, 0.0])
台とほとんど確実な等価¶
support() は、同じプロファイルとラベルを持つ
0/1 テンソルです。FXTensor._ATOL 以内の成分は 0 とみなします。
almost_surely_equal() は、事前状態が正である
点で、同じプロファイルの2つのテンソルが一致するかを見ます。ラベルは比べません。
事前状態は、codomain が domain と一致する状態である必要があります。
is_absolutely_continuous() は、other が 0 の
場所で self も 0 かを見ます。核では入力ごとに確認します。プロファイルは
一致している必要があり、ラベルは比べません。
ほとんど確実な等価: p ; copy ; (id ⊗ f) = p ; copy ; (id ⊗ g)。¶
import numpy as np
from fxtensor_salmon import FXTensor
prior = FXTensor([[], [["x0", "x1", "x2"]]], data=np.array([0.4, 0.6, 0.0]))
f = FXTensor(
[[["x0", "x1", "x2"]], [["y0", "y1"]]],
data=np.array([[0.2, 0.8], [0.5, 0.5], [1.0, 0.0]]),
)
g = FXTensor(
[[["x0", "x1", "x2"]], [["y0", "y1"]]],
data=np.array([[0.2, 0.8], [0.5, 0.5], [0.3, 0.7]]),
)
assert np.array_equal(prior.support().data, [1.0, 1.0, 0.0])
assert f.almost_surely_equal(g, prior)
assert not f.almost_surely_equal(g, FXTensor([[], [3]], data=np.array([0.2, 0.2, 0.6])))
assert f.is_absolutely_continuous(g)
assert not g.is_absolutely_continuous(f)
relabeled = FXTensor([[["a", "b", "c"]], [["p", "q"]]], data=np.array(f.data))
assert f.almost_surely_equal(relabeled, prior)