Spark中具有固定向量的数据帧行的点积

Posted

技术标签:

【中文标题】Spark中具有固定向量的数据帧行的点积【英文标题】:Dot Products of Rows of a Dataframe with a Fixed Vector in Spark 【发布时间】:2019-07-30 20:26:25 【问题描述】:

我在 Spark 中有一个包含 m 行和 n 列的数据框 (df1)。我有另一个具有 1 行和 n 列的数据框(df2)。如何有效地计算 df1 的每一行与 df2 的单行的点积?

【问题讨论】:

【参考方案1】:

我们可以使用 VectorAssembler 来做点积。

    创建示例 DataFrame:
from pyspark.ml.linalg import Vectors, DenseVector
from pyspark.sql import functions as F
from pyspark.ml.feature import VectorAssembler
from pyspark.sql.types import *

v = [('a', 1,2,3),
    ('b', 4,5,6),
    ('c', 9,8,7)]
df1 = spark.createDataFrame(v, ['id', 'v1', 'v2', 'v3'])
df2 = spark.createDataFrame([('d',3,2,1)], ['id', 'v1', 'v2', 'v3'])
df1.show()
df2.show()

它们看起来像这样:

+---+---+---+---+
| id| v1| v2| v3|
+---+---+---+---+
|  a|  1|  2|  3|
|  b|  4|  5|  6|
|  c|  9|  8|  7|
+---+---+---+---+

+---+---+---+---+
| id| v1| v2| v3|
+---+---+---+---+
|  d|  3|  2|  1|
+---+---+---+---+

    使用VectorAssembler 将列转换为Vector
vecAssembler = VectorAssembler(inputCols=["v1", "v2", "v3"], outputCol="values")
dfv1 = vecAssembler.transform(df1) 
dfv2 = vecAssembler.transform(df2)
dfv1.show()
dfv2.show()

现在它们看起来像这样:

+---+---+---+---+-------------+
| id| v1| v2| v3|       values|
+---+---+---+---+-------------+
|  a|  1|  2|  3|[1.0,2.0,3.0]|
|  b|  4|  5|  6|[4.0,5.0,6.0]|
|  c|  9|  8|  7|[9.0,8.0,7.0]|
+---+---+---+---+-------------+

+---+---+---+---+-------------+
| id| v1| v2| v3|       values|
+---+---+---+---+-------------+
|  d|  3|  2|  1|[3.0,2.0,1.0]|
+---+---+---+---+-------------+

    定义一个udf 来做点积
# Get the fixed vector from DataFrame dfv2
vm = Vectors.dense(dfv2.take(1)[0]['values'])

dot_prod_udf = F.udf(lambda v: float(v.dot(vm)), FloatType())
dfv1 = dfv1.withColumn('dot_prod', dot_prod_udf('values'))

dfv1.show()

最终结果是:

+---+---+---+---+-------------+--------+
| id| v1| v2| v3|       values|dot_prod|
+---+---+---+---+-------------+--------+
|  a|  1|  2|  3|[1.0,2.0,3.0]|    10.0|
|  b|  4|  5|  6|[4.0,5.0,6.0]|    28.0|
|  c|  9|  8|  7|[9.0,8.0,7.0]|    50.0|
+---+---+---+---+-------------+--------+

【讨论】:

【参考方案2】:

您可以简单地用第一个数据框形成一个矩阵,用第二个数据框形成另一个矩阵,然后将它们相乘。这是要使用的代码 sn-p(这里我使用的是块矩阵,因为我假设您的数据帧不能存储在本地机器中)


v = [('a', [1,2,3]),
    ('b', [4,5,6]),
    ('c', [9,8,7])]
df1 = spark.createDataFrame(v, ['id', 'vec'])
df2 = spark.createDataFrame([('d',[3,2,1])], ['id', 'vec'])

m1 = matdf1.toBlockMatrix(100,100)
m2 = matdf2.toBlockMatrix(100,100)

m1.multiply(m2.transpose())

【讨论】:

以上是关于Spark中具有固定向量的数据帧行的点积的主要内容,如果未能解决你的问题,请参考以下文章

向量与 SIMD 的点积

向量点积和叉积(向量积)

计算机图形学-向量向量加减法向量的点积(乘)向量的叉积(乘)

二维图形变换

LookAt Matrix 实现中的点积

向量的点积和叉积