许多火花核密度估计器的并行计算和推断

时间:2019-04-04 16:59:37

标签: pyspark

我想做

  1. 通过pyspark内核密度估计进行分段或分组
  2. 将生成的密度估计量加入另一个数据框并进行推断

例如,假设我有一个看起来像这样的数据框:

data=[{'id':1, 'samples':[3,56,40]},
      {'id':2, 'samples':[-3,80,45,45,2]}]

此数据是从

之类的东西生成的
df.groupBy('id').agg(F.collect_list('sample').alias('samples'))

df大的地方。然后想象一下我还有另一个很大的数据框,数据如下:

data2 = [{'id':1, 'val': 10},
         {'id':1, 'val': 39},
         {'id':2, 'val': 5}]

相对于上面得到的两个密度估计量,我想获得这三个值10、39、5的概率。

例如,将执行此操作的Python程序为

import scipy.stats

data_to_define_pdfs=[{'id':1, 'samples':[3,56,40]},
                     {'id':2, 'samples':[-3,80,45,45,2]}]
kdes = {}
for row in data_to_define_pdfs:
    kdes[row['id']] = scipy.stats.gaussian_kde(row['samples'])

inferrence_data = [
    {'id': 1, 'val': 10},
    {'id': 1, 'val': 39},
    {'id': 2, 'val': 5}]

for row in inferrence_data:
    kde = kdes[row['id']]
    row['prob'] = kde.pdf(x=row['val'])[0]

import pprint
pprint.pprint(inferrence_data)

将会输出

[{'id': 1, 'prob': 0.008817584549791962, 'val': 10},
 {'id': 1, 'prob': 0.012149240532443975, 'val': 39},
 {'id': 2, 'prob': 0.008013522166302479, 'val': 5}]

2 个答案:

答案 0 :(得分:0)

我有一个解决方案,我将所有样本与数据进行推理,因为它可能会复制很多样本,所以它不是最佳选择,并且我为要应用的数据中的每一行重新生成python scipy kde对象kde-但它是一个开始,我可以想象做一些更聪明的事情:

data_to_define_pdfs_flat = []
for row in data:
    for sample in row['samples']:
        data_to_define_pdfs_flat.append({'id':row['id'], 'sample': sample})

df_sample = spark.createDataFrame(data=data_to_define_pdfs_flat,
                                  schema=T.StructType([T.StructField('id', T.IntegerType(), False),
                                                       T.StructField('sample', T.FloatType(), False)]))
df_samples = df_sample.groupBy('id').agg(F.collect_list('sample').alias('samples'))

df_infer = spark.createDataFrame(data=data2,
                                 schema=T.StructType([T.StructField('id', T.IntegerType(), False),
                                                      T.StructField('val', T.FloatType(), False)]))

df_infer2 = df_infer.join(df_samples, on='id')


def do_inference(df):
    def f(samples, val):
        kde = scipy.stats.gaussian_kde(samples)
        return float(kde.pdf(val)[0])

    udf_f = F.udf(f, T.FloatType())
    return df.withColumn('prob', udf_f(F.col('samples'), F.col('val')))


df_infer2 = do_inference(df=df_infer2)
df_samples.show()
df_infer2.show()

答案 1 :(得分:0)

如果您可以在本地存储KDE的所有样本,那么我有一个pandas数据框解决方案-至少在此玩具示例中。由于使用内存的方式,使熊猫数据框的内容大规模地工作似乎总是很困难。

在此解决方案中,kde都是在主节点上形成的,并被运送到所有任务节点-每个kde都是该id的所有样本数据的函数,因此我必须对构成{ {1}}:

df_samples