这是我的代码:
import numpy as np
from scipy.stats.kde import gaussian_kde
from scipy.stats import norm
from numpy import linspace,hstack
from pylab import plot,show,hist
import re
import json
attribute_file="path"
attribute_values = [line.rstrip('\n') for line in open(attribute_file)]
obs=[]
#Assume the list obs as loaded
obs=np.asarray(osservazioni)
obs=np.sort(obs,kind='mergesort')
x_min=osservazioni[0]
x_max=osservazioni[len(obs)-1]
# obtaining the pdf (my_pdf is a function!)
my_pdf = gaussian_kde(obs)
# plotting the result
x = linspace(0,x_max,1000)
plot(x,my_pdf(x),'r') # distribution function
hist(obs,normed=1,alpha=.3) # histogram
show()
new_values = np.asarray([-1, 0, 2, 3, 4, 5, 768])[:, np.newaxis]
for e in new_values:
print (str(e)+" - "+str(my_pdf(e)*100*2))
问题: obs数组包含所有obs的列表。 我需要为新值计算得分(在0和1之间)
[ - 1,0,2,3,4,500,768]
因此值-1必须具有离散分数,因为它不会出现在分布中,而是在观察中非常常见的1值旁边。
答案 0 :(得分:9)
原因是你的观察中有1个比768个多1个。因此,即使-1不完全为1,它也会得到一个很高的预测值,因为直方图在1处的值大于在768处的值。
直到乘法常数,预测公式为:
其中K是你的内核,D你的观察和你的bandwitdh。查看the doc for gaussian_kde
,我们发现,如果没有为bw_method
提供任何值,则会以某种方式估算,这不适合您。
因此,您可以尝试一些不同的值:带宽越大,考虑到远离新数据的点数越多,极限情况就是几乎恒定的预测函数。
另一方面,非常小的带宽只考虑了非常接近的点,这就是我想要的。
使用的代码:
import matplotlib.pyplot as plt
f, axarr = plt.subplots(2, 2, figsize=(10, 10))
for i, h in enumerate([0.01, 0.1, 1, 5]):
my_pdf = gaussian_kde(osservazioni, h)
axarr[i//2, i%2].plot(x, my_pdf(x), 'r') # distribution function
axarr[i//2, i%2].set_title("Bandwidth: {0}".format(h))
axarr[i//2, i%2].hist(osservazioni, normed=1, alpha=.3) # histogram
对于当前代码,对于x = -1,所有等于1的x_i的K((x-x_i)/ h)的值小于1,但是你加了很多这些值(你的观察中有921个,也有357个)
另一方面,对于x = 768,对于所有x_i,内核的值为1,即768,但是没有多少这样的点(准确地说是39)。因此,在这里,许多“小”术语比较少的较大术语产生更大的总和。
如果您不想要这种行为,可以减小高斯内核的大小:这样由于-1和1之间的距离而支付的惩罚(K(-2))将更高。但我认为这会超出你的观察范围。
确定新样本是否可接受(与经验分布相比)的公式更多是统计问题,您可以查看stats.stackexchange.com
您始终可以尝试使用较低的带宽值,这将为您提供预测功能。然后你可以将这个函数标准化,除以它的最大值。
之后,所有预测值将介于0和1之间:
maxDensityValue = np.max(my_pdf(x))
for e in new_values:
print("{0} {1}".format(e, my_pdf(e)/maxDensityValue))
答案 1 :(得分:1)
-1和0都非常接近于1,这种情况非常频繁,所以预计它们会有更高的值。 (这就是为什么0的值高于-1,即使它们都没有出现,0也接近1)。
您需要的是更小的带宽:请查看图表中的行以查看此信息 - 现在的数字根本不会显示为80因为它们接近1和2而获得了很多价值。
只需将标量设置为bandwidth_method即可实现此目的:
my_pdf = gaussian_kde(osservazioni, 0.1)
这可能不是你想要的确切标量,但尝试将0.1改为0.05甚至更低,看看你想要的是什么。
如果你想要一个介于0和1之间的值,你需要确保my_pdf()永远不会返回超过.005的值,因为你将它乘以200.
这就是我的意思:
for e in new_values:
print (str(e)+" - "+str(my_pdf(e)*100*2))
您输出的值是:
mypdf(e)*100*2 == mypdf(e)*200
#You want the max value to be 1 so
1 >= mypdf(e)*200
#Divide both sides by 200
0.005 >= mypdf(e)
所以mypdf()需要的最大值为0.005。 OR 您只需缩放数据即可。
对于最大值为1并保持与输入成比例,无论输入如何,您都需要先收集输出,然后根据最大值进行缩放。
示例:
orig_val=[] #Create intermediate list
for e in new_values:
orig_val += [my_pdf(e)*100*2] #Fill with the data
for i in range(len(new_values)):
print (str(new_values[i])+" - "+str(orig_val[i]/max(orig_val))) #Scale based on largest value
点击此处了解有关gaussian_kde的更多信息:scipy.stats.gaussian_kde