如何找到真实数据的概率分布和参数? (Python 3)

Posted

技术标签:

【中文标题】如何找到真实数据的概率分布和参数? (Python 3)【英文标题】:How to find probability distribution and parameters for real data? (Python 3) 【发布时间】:2016-09-26 01:12:21 【问题描述】:

我有一个来自sklearn 的数据集,我绘制了load_diabetes.target 数据的分布(即load_diabetes.data 用于预测的回归值)。

我使用它是因为它具有最少数量的回归变量/属性sklearn.datasets

使用 Python 3,我怎样才能得到最接近分布的分布类型和参数?

我所知道的 target 值都是正数和偏斜的(正偏斜/右偏斜)。 . . Python中有没有办法提供一些分布,然后得到最适合target数据/向量的方法?或者,根据给出的数据实际建议适合?这对于具有理论统计知识但很少有将其应用于“真实数据”经验的人来说将非常有用。

奖金 使用这种方法来确定“真实数据”的后验分布是否有意义?如果没有,为什么不呢?

from sklearn.datasets import load_diabetes
import matplotlib.pyplot as plt
import seaborn as sns; sns.set()
import pandas as pd

#Get Data
data = load_diabetes()
X, y_ = data.data, data.target

#Organize Data
SR_y = pd.Series(y_, name="y_ (Target Vector Distribution)")

#Plot Data
fig, ax = plt.subplots()
sns.distplot(SR_y, bins=25, color="g", ax=ax)
plt.show()

【问题讨论】:

您可以对数据进行几次拟合,然后选择产生最小拟合误差的那个。 你的图中的kde曲线是你想要的函数吗? @Philip;为此,您会从这里获取分布:docs.scipy.org/doc/scipy/reference/stats.html 吗?挑选和选择哪些最适合?如果不知道样本分布的参数,如何检验拟合? @ZichenWang 不一定。最终,我会寻找以下分布之一:pymc-devs.github.io/pymc3/api.html 具有特定参数和拟合误差 这个answer shows all the scipy.stats distributions available,也许你可以结合其中的一些来生成你想要的分布。 【参考方案1】:

使用这种方法

import scipy.stats as st
def get_best_distribution(data):
    dist_names = ["norm", "exponweib", "weibull_max", "weibull_min", "pareto", "genextreme"]
    dist_results = []
    params = 
    for dist_name in dist_names:
        dist = getattr(st, dist_name)
        param = dist.fit(data)

        params[dist_name] = param
        # Applying the Kolmogorov-Smirnov test
        D, p = st.kstest(data, dist_name, args=param)
        print("p value for "+dist_name+" = "+str(p))
        dist_results.append((dist_name, p))

    # select the best fitted distribution
    best_dist, best_p = (max(dist_results, key=lambda item: item[1]))
    # store the name of the best fit and its p value

    print("Best fitting distribution: "+str(best_dist))
    print("Best p value: "+ str(best_p))
    print("Parameters for the best fit: "+ str(params[best_dist]))

    return best_dist, best_p, params[best_dist]

【讨论】:

您能解释一下这种方法吗? 它是上面答案中代码的完整版本。他们为所有可能适合数据的分布创建了一个项目列表。然后他们使用 p 分数创建一个假设,以确定该分布与数据的匹配程度。具有最高 p 分数的内容被认为是最准确的。这是因为较高的 p 分数意味着假设最接近现实。 有没有办法让这段代码也尝试截断正态分布?我在数据集的列表中添加了“truncnorm”,但该函数始终返回 p 值 = 0。谢谢! 在这种方法中,您正在寻找最大 P 作为最佳方法。不应该是要选择的min(p)吗? 您好,感谢您采用这种方法。得到分布的参数后,如何从同一个分布中生成合成数据?有什么想法吗?【参考方案2】:

据我所知,没有自动获取样本分布类型和参数的方法(因为推断样本的分布本身就是一个统计问题)。

在我看来,你能做的最好的就是:

(对于每个属性)

尝试将每个属性拟合到一个相当大的可能分布列表 (例如,有关 Scipy 的示例,请参阅 Fitting empirical distribution to theoretical ones with Scipy (Python)?)

评估您的所有适合度并选择最佳的。这可以通过在您的样本和拟合的每个分布之间执行 Kolmogorov-Smirnov 测试来完成(您再次在 Scipy 中有一个实现),然后选择一个最小化 D 的测试统计量(也就是样本和拟合)。

奖励:这是有道理的 - 因为您将在每个变量上构建模型,同时为每个变量选择合适的模型 - 尽管您的预测的好坏取决于您的数据质量和您的分布用于拟合。毕竟,您正在构建模型。

【讨论】:

如果您需要查看all the scipy.stats distributions,请查看here。 但是如何区分单模态分布和多模态分布呢?例如,在这里 (imgur.com/a/NZKxxRv),如果足够大胆的话,我可以看到 3 种正态分布模式或仅一种模式。 本文概述了如何使用 Fitter 库来自动识别 scipy 的哪些分布最适合数据towardsdatascience.com/…【参考方案3】:

您可以使用该代码来拟合(根据最大可能性)您的数据的不同分布:

import matplotlib.pyplot as plt
import scipy
import scipy.stats

dist_names = ['gamma', 'beta', 'rayleigh', 'norm', 'pareto']

for dist_name in dist_names:
    dist = getattr(scipy.stats, dist_name)
    param = dist.fit(y)
    # here's the parameters of your distribution, scale, location

你可以在此处查看有关如何使用获取的参数的示例 sn-p:Fitting empirical distribution to theoretical ones with Scipy (Python)?

然后,您可以选择具有最佳对数似然的分布(还有其他标准可以匹配“最佳”分布,例如贝叶斯后验概率、AIC、BIC 或 BICc 值,. ..)。

对于您的额外问题,我认为没有通用答案。如果你的数据集很重要,并且在与真实单词数据相同的条件下获得,你就可以做到。

【讨论】:

我实现了上面的代码,参数只显示了 3 个值。它们不应该等于 5 吗? 此外,在数据集不完整的情况下,使用期望最大化 (EM) 算法而不是传统的最大似然估计 (MLE) - 当存在一些未观察到或隐藏的变量时(它们被称为作为潜在变量)【参考方案4】:

此代码也有效:

import pandas as pd
import numpy as np
import scipy
from scipy import stats

#Please write below the name of the statistical distributions that you would like to check.
#Full list is here: https://docs.scipy.org/doc/scipy/reference/stats.html
dist_names = ['weibull_min','norm','weibull_max','beta',
              'invgauss','uniform','gamma','expon',   
              'lognorm','pearson3','triang']

#Read your data and set y_std to the column that you want to fit.
y_std=pd.read_csv('my_df.csv')
y_std=y_std['column_A']

#-------------------------------------------------
chi_square_statistics = []
size=len(y_std)

# 20 equi-distant bins of observed Data 
percentile_bins = np.linspace(0,100,20)
percentile_cutoffs = np.percentile(y_std, percentile_bins)
observed_frequency, bins = (np.histogram(y_std, bins=percentile_cutoffs))
cum_observed_frequency = np.cumsum(observed_frequency)

# Loop through candidate distributions
for distribution in dist_names:
    # Set up distribution and get fitted distribution parameters
    dist = getattr(scipy.stats, distribution)
    param = dist.fit(y_std)
    print("\n\n".format(dist, param))

    # Get expected counts in percentile bins
    # cdf of fitted sistrinution across bins
    cdf_fitted = dist.cdf(percentile_cutoffs, *param)
    expected_frequency = []
    for bin in range(len(percentile_bins)-1):
        expected_cdf_area = cdf_fitted[bin+1] - cdf_fitted[bin]
        expected_frequency.append(expected_cdf_area)

    # Chi-square Statistics
    expected_frequency = np.array(expected_frequency) * size
    cum_expected_frequency = np.cumsum(expected_frequency)
    ss = sum (((cum_expected_frequency - cum_observed_frequency) ** 2) / cum_observed_frequency)
    chi_square_statistics.append(ss)


#Sort by minimum ch-square statistics
results = pd.DataFrame()
results['Distribution'] = dist_names
results['chi_square'] = chi_square_statistics
results.sort_values(['chi_square'], inplace=True)


print ('\nDistributions listed by goodness of fit:')
print ('............................................')
print (results)

【讨论】:

【参考方案5】:

关于类似的问题 (see here),您可能会对 @Michel_Baudin 的回答解释感兴趣。他的代码评估了大约 40 个不同的可用 OpenTURNS 库,并根据 BIC 标准选择了最好的一个。看起来像这样:

import openturns as ot

sample = ot.Sample([[x] for x in your_data_list])
tested_factories = ot.DistributionFactory.GetContinuousUniVariateFactories()
best_model, best_bic = ot.FittingTest.BestModelBIC(sample, tested_factories)

【讨论】:

以上是关于如何找到真实数据的概率分布和参数? (Python 3)的主要内容,如果未能解决你的问题,请参考以下文章

异常检测统计学方法

GAN的数学原理

如何用matlab进行参数以及非参数概率密度估计

R图概率密度函数

2020-07-31

机器学习是否有可能从数据集中找到所有元素的概率分布?