Pyspark 多个spark核密度估计的并行计算与推理
我想做Pyspark 多个spark核密度估计的并行计算与推理,pyspark,Pyspark,我想做 分段或分组Pypark核密度估计 将得到的密度估计器连接到另一个数据帧并进行推断 例如,假设我有一个如下所示的数据帧: 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很大。然后想象我有另一个大数据帧,比如: d
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}]
我有一个解决方案,我将所有样本与用于推断的数据连接起来,这不是最优的,因为我可能会复制很多样本,我正在为我应用kde的数据中的每一行重新生成python scipy 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()
我有一个解决方案,我将所有样本与用于推断的数据连接起来,这不是最优的,因为我可能会复制很多样本,我正在为我应用kde的数据中的每一行重新生成python scipy 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()
如果您可以在本地存储KDE的所有样本,我有一个熊猫数据帧解决方案——至少在这个玩具示例中是这样。由于熊猫数据帧是如何使用内存的,所以它似乎总是很难大规模工作 在这个解决方案中,kde都在主节点上形成,并发送到所有任务节点-每个kde都是该id的所有样本数据的函数,因此我必须对生成
df_样本的数据进行子样本
:
def do_inference_pd(df_infer, df_samples):
rows = df_samples.collect()
kdes = {}
for row in rows:
row = row.asDict(True)
kdes[row['id']] = scipy.stats.gaussian_kde(np.array(row['samples']))
def kde_prob(pdf):
kde = kdes[pdf.id[0]]
x = pdf.val
return pdf.assign(prob=kde(x))
df_infer_prob = df_infer.withColumn('prob', F.lit(0.0))
sch_str = df_infer2.schema.simpleString()
f = F.pandas_udf(f=kde_prob, returnType=sch_str, functionType=F.PandasUDFType.GROUPED_MAP)
df_infer_prob = df_infer_prob.groupBy('id').apply(f)
return df_infer_prob
df_infer_prob = do_inference_pd(df_infer=df_infer, df_samples=df_samples)
如果您可以在本地存储KDE的所有样本,我有一个熊猫数据帧解决方案——至少在这个玩具示例中是这样。由于熊猫数据帧是如何使用内存的,所以它似乎总是很难大规模工作 在这个解决方案中,kde都在主节点上形成,并发送到所有任务节点-每个kde都是该id的所有样本数据的函数,因此我必须对生成
df_样本的数据进行子样本
:
def do_inference_pd(df_infer, df_samples):
rows = df_samples.collect()
kdes = {}
for row in rows:
row = row.asDict(True)
kdes[row['id']] = scipy.stats.gaussian_kde(np.array(row['samples']))
def kde_prob(pdf):
kde = kdes[pdf.id[0]]
x = pdf.val
return pdf.assign(prob=kde(x))
df_infer_prob = df_infer.withColumn('prob', F.lit(0.0))
sch_str = df_infer2.schema.simpleString()
f = F.pandas_udf(f=kde_prob, returnType=sch_str, functionType=F.PandasUDFType.GROUPED_MAP)
df_infer_prob = df_infer_prob.groupBy('id').apply(f)
return df_infer_prob
df_infer_prob = do_inference_pd(df_infer=df_infer, df_samples=df_samples)
如果您还包含了所需的输出,并对其计算方式进行了明确的解释,这将非常有用。感谢您的关注!我添加了一个例子。你有没有找到其他选择?如果你也包含了所需的输出,并解释了它是如何计算的,那会很有帮助。谢谢你的关注!我加了一个例子,你有没有其他选择?