python - 计算熊猫数据框的余弦距离
问题描述
我有一个形状(70000 x 10)的熊猫数据框(比如df)。数据框头部如下图所示:
0_x 1_x 2_x ... 7_x 8_x 9_x
userid ...
1000010249674395648 0.000007 0.999936 0.000007 ... 0.000007 0.000007 0.000007
1000282310388932608 0.000060 0.816790 0.000060 ... 0.000060 0.000060 0.000060
1000290654755450880 0.000050 0.000050 0.000050 ... 0.000050 0.191159 0.000050
1000304603840241665 0.993157 0.006766 0.000010 ... 0.000010 0.000010 0.000010
1000600081165438977 0.000064 0.970428 0.000064 ... 0.000064 0.000064 0.000064
我想找到用户 ID 之间的成对余弦距离。例如:
余弦距离(1000010249674395648,1000282310388932608)= 0.9758776214797362
我使用了这里提到的以下方法,但是由于 CPU 内存有限,在计算余弦距离时都会抛出内存错误:
scikit-learn 的 cosine_similarity:
from sklearn.metrics.pairwise import cosine_similarity cosine_sim = cosine_similarity(df)
网上找到的更快的矢量化解决方案:
def get_cosine_sim_df(df): topic_vectors = df.values norm_topic_vectors = topic_vectors / np.linalg.norm(topic_vectors, axis=-1)[:, np.newaxis] cosine_sim = np.dot(norm_topic_vectors, norm_topic_vectors.T) cosine_sim_df = pd.DataFrame(data = cosine_sim, index=df.index, columns=df.index) return cosine_sim_df cosine_sim = get_cosine_sim_df(df)
系统硬件概述:
Model Name: MacBook Pro
Model Identifier: MacBookPro11,4
Processor Name: Quad-Core Intel Core i7
Processor Speed: 2.2 GHz
Number of Processors: 1
Total Number of Cores: 4
L2 Cache (per Core): 256 KB
L3 Cache: 6 MB
Hyper-Threading Technology: Enabled
Memory: 16 GB
我正在寻找一种有效的方法和更快的方法来计算 CPU 内存限制内的成对余弦距离,类似于 pyspark 数据帧或 pandas 批处理技术,而不是一次处理所有数据帧。
任何建议/方法表示赞赏。
仅供参考 - 我正在使用 Python 3.7
解决方案
我正在使用 spark 2.4 和 python 3.7
# build spark session
from pyspark.sql import SparkSession
spark = SparkSession.builder \
.master("local") \
.appName("cos_sim") \
.config("spark.some.config.option", "some-value") \
.getOrCreate()
将您的 pandas df 转换为 spark df
# Pandas to Spark
df = spark_session.createDataFrame(pand_df)
我生成了一些随机数据,而不是
import random
import pandas as pd
from pyspark.sql.functions import monotonically_increasing_id
def generate_random_data(num_usrs = 20, num_cols = 10):
cols = [str(i)+"_x" for i in range(num_cols)]
usrsdata = [ [random.random() for i in range(num_cols)] for i in range(num_usrs)]
# return pd.DataFrame(usrsdata, columns = cols)
return spark.createDataFrame(data = usrsdata, schema = cols)
df = generate_random_data()
df = df.withColumn("uid", monotonically_increasing_id())
df.limit(5).toPandas() # just for nice display of df (df not actually changed)
将 df 的列转换为特征向量
from pyspark.ml.feature import VectorAssembler
assembler = VectorAssembler(inputCols=df.columns, outputCol="features")
assembled = assembler.transform(df).select(['uid', 'features'])
assembled.limit(2).toPandas()
标准化
from pyspark.ml.feature import Normalizer
normalizer = Normalizer(inputCol="features", outputCol="norm")
data = normalizer.transform(assembled)
data.limit(2).toPandas()
计算成对余弦相似度
from pyspark.mllib.linalg.distributed import IndexedRow, IndexedRowMatrix
mat = IndexedRowMatrix(data.select("uid", "norm").rdd\
.map(lambda row: IndexedRow(row.uid, row.norm.toArray()))).toBlockMatrix()
dot = mat.multiply(mat.transpose())
dot.toLocalMatrix().toArray()[:2] # displaying first 2 users only
推荐阅读
- android - startactivty 意图不适用于错误 SurfaceFlinger:重复图层名称
- php - 创建没有 eval 的动态 if 语句
- twilio - 如何使用 Twilio 号码在 Zoiper 中发送/接收短信?
- c# - 如何访问模板生成的元素 wpf
- javascript - 为什么我制作的这个命令历史不起作用?
- javascript - jQuery 文件已保存但在浏览器中未更改
- azure-devops - 如何在 Azure DevOps 分析中为 Sprint 和董事会计算特定指标
- java - 如何使用一个表中的数据作为参考来使用 Firebase 获取另一个表中的另一个数据?
- python - 如何在链接验证后重定向用户以在 aws cognito 中拥有自定义 UI?
- scala - 在 k 折验证中的每次迭代/折中获取单个模型分数