我的矢量V为256位。对于矢量中的每个位置,我想根据高斯分布计算密度:
V[0] -> p(V[0])
V[1] -> p(V[1])
...
V[255] -> p(V[255])
之后我想将所有概率相乘:
p(V[0]) * p(V[1]) * ... * p(V[255])
我的实现中这个方法的问题是每个概率都很高(大约400左右),所以我不能把所有东西都加在一起。
解决方法是获取每个Gaussian的日志,然后将所有Gaussian加在一起:
V[0] -> log(p(V[0]))
V[1] -> log(p(V[1]))
...
V[255] -> log(p(V[255]))
log(p(V[0])) + log(p(V[1])) + ... + log(p(V[255]))
但是当我尝试这样做时,当高斯结果为零时我得到一个错误。
考虑到这一点,log(0)
问题是否有解决方法?是log(0)
的准确代表取代0
吗?
所以,对于记录,如果我尝试普通方法(乘法),我得到的错误就是这个:
iex(6)> Naive.CLI.main(["~/data/usps.csv", "~/indices/17.csv"])
** (ArithmeticError) bad argument in arithmetic expression
:erlang.*(417.62100246853674, 6.504406716503509e307)
根据我的理解,数字对于乘法生效来说太高了。
这就是我所做的(我认为应该是正确的想法):
def gaussian(vector, mean, variance) do
vector
|> Enum.zip(mean)
|> Enum.zip(variance)
|> Enum.map(fn {{e, m}, v} -> {e, m, v} end)
|> Enum.map(fn {e, m, v} -> calculate(e, m, v) end)
|> Enum.map(fn e ->
if e == 0.0 do
0.0
else
:math.log10(e)
end
end)
end
defp calculate(elem, mean, variance) do
(1/:math.sqrt(2*:math.pi*variance)) *
:math.exp(-0.5*(((elem - mean)*(elem - mean)) / variance))
end
基本上如果高斯结果为零,我也会返回零。