对数正态分布和测井变量之间的差异,拟合正态

机器算法验证 r 正态分布 混合模式 对数正态分布
2022-03-22 17:13:23

背景:我有一组双峰数据,所以我使用 R 中的 mixtools 包来拟合双峰正态分布。看起来法线似乎不太适合,并且考虑到我拥有的其他类似数据集(不是双峰的)并且是对数正态分布的,我认为对数正态可能更有意义。但是,mixtools 没有办法拟合双峰对数正态分布,所以我取了数据的对数并重新拟合。这张图片在下面,它符合我的要求。

确实,这是一个软件问题(不知道哪个包可以明确适合双峰对数正态),但这让我想到了我经常想知道的事情:将正态分布拟合到记录的数据相当于拟合对数正态分布到原始数据?我怀疑不是,但我不确定为什么?(忽略零或负数据的情况。假设所有数据都是相当大的正数,但有偏差)。还知道您当然需要进行反向转换才能获得原始值估计。

我试图用一些玩具数据对此进行测试,并意识到我什至不知道为什么与对数正态分布相关的均值对数不是当你取对数正态分布的平均值时得到的结果。因此,当涉及到对数法线的参数时,我的理解可能已经被打破了。

library(fitdistrplus)

set.seed(1)
test <- rnorm(1000, mean=100)
test[test<=0] <- NA #Unnecessary since no values <= 0, but just to prove
test<-na.omit(test)

log.test <- log10(test)
mean(log.test)
sd(log.test)
#1.999926 is mean for log.test
#0.004496153 is sd for log.test

fitdist(log.test, dist="lnorm", method="mle")
#However, "meanlog" is 0.693107737 and "sdlog" is 0.002247176
#The means are so different, not sure why?

在此处输入图像描述

2个回答

参考

xlogN(μ,σ2)ifp(x)=1x2πσe(log(x)μ)22σ2,x>0

在哪里

E[x]=eμ+12σ2.

注意

ylogN(m,v2)log(y)N(m,v2),

根据此问答

回答

将正态分布拟合到记录数据是否等同于将对数正态分布拟合到原始数据?

理论上?在大多数情况下是的(参见上面的逻辑等价)。我发现明确使用对数正态分布有用的唯一案例是污染数据的案例研究。在这种情况下,重要的是根据污染浓度对工作日和周末进行不同的建模(μ1>μ2在先前的*中),但具有两个对数正态分布的预期值,没有限制(我必须允许eμ1+12σ12eμ2+12σ22)。每次测量是在哪一天进行的都是未知的,因此必须推断出单独的参数。

您当然可以争辩说,这可以在不调用对数正态分布的情况下完成,但这是我们决定使用的并且它有效。

我试图用一些玩具数据对此进行测试,并意识到我什至不知道为什么与对数正态分布相关的均值对数不是当你取对数正态分布的平均值时得到的结果。

其原因只是我们在支撑上的距离概念的结果。自从log是单调递增函数,对数变换变量保持顺序。例如,对数正态分布的中位数就是eμ,对数中位数的指数(因为正态分布的平均值也是它的中位数)。

但是,那log函数只保留顺序,而不是距离函数本身。均值与距离有关:均值只是在欧几里得意义上最接近所有其他点的点,当点按其概率加权时。所有对数值都被压缩到0以不均匀的方式(即,较大的值被压缩得更多)。事实上,对数正态分布的均值的对数高于对数值的均值(即μ) 经过σ

log(eμ+12σ2)=μ+12σ2>μ.
也就是说,对数的平均值被压缩为分布分布的函数(即,涉及σ) 由于log函数以不均匀的方式压缩距离。


*附带说明,这些先验中的人为约束往往不如其他用于推断/分离分布的方法。

我想补充一下,您正确理解对数转换和均值之间的关系。

lnorm使用自然对数,而不是以 10 为底。此外,在fitdist通话中,您正在尝试将对数正态分布拟合到已经对数转换的数据(请参见下面的正确代码)。

library(fitdistrplus)

set.seed(1)
test <- rnorm(1000, mean=100)
test[test<=0] <- NA #Unnecessary since no values <= 0, but just to prove
test<-na.omit(test)

log.test <- log(test)
mean(log.test)
sd(log.test)
#4.605 is mean for log.test
#0.01035277 is sd for log.test

fitdist(test, dist="lnorm", method="mle")
# "meanlog" is 4.6050002, "sdlog" is 0.0103476
fitdist(log.test, dist="norm", method="mle")
# "meanlog" is 4.6050002, "sdlog" is 0.0103476