【发布时间】:2020-02-03 15:18:00
【问题描述】:
我有一个机器学习问题,我正在计算 pandas 数据框文本列与字典值的 bigram Jaccard 相似度。目前我将它们存储为列表,然后将它们转换为列。事实证明,这在生产中非常缓慢。有没有更有效的方法?
以下是我目前正在遵循的步骤: 对于dict中的每个键: 1. 获取 pandas 列和 dict[key] 的二元组 2.计算Jaccard相似度 3.追加到一个空列表 4.将列表存储在数据框中 5. 将列表转换为列
from itertools import tee, islice
def count_ngrams(lst, n):
tlst = lst
while True:
a, b = tee(tlst)
l = tuple(islice(a, n))
if len(l) == n:
yield l
next(b)
tlst = b
else:
break
def n_gram_jaccard_similarity(str1, str2,n):
a = set(count_ngrams(str1.split(),n))
b = set(count_ngrams(str2.split(),n))
intersection = a.intersection(b)
union = a.union(b)
try:
return len(intersection) / float(len(union))
except:
return np.nan
def jc_list(sample_dict,row,n):
sim_list = []
for key in sample_dict:
sim_list.append(n_gram_jaccard_similarity(sample_dict[key],row["text"],n))
return str(sim_list)
使用上述函数构建二元Jaccard相似度特征如下:
df["bigram_jaccard_similarity"]=df.apply(lambda row: jc_list(sample_dict,row,2),axis=1)
df["bigram_jaccard_similarity"] = df["bigram_jaccard_similarity"].map(lambda x:[float(i) for i in [a for a in [s.replace(',','').replace(']', '').replace('[','') for s in x.split()] if a!='']])
df[[i for i in sample_dict]] = pd.DataFrame(df["bigram_jaccard_similarity"].values.tolist(), index= df.index)
示例输入:
df = pd.DataFrame(columns=["id","text"],index=None)
df.loc[0] = ["1","this is a sample text"]
import collections
sample_dict = collections.defaultdict()
sample_dict["r1"] = "this is sample 1"
sample_dict["r2"] = "is sample"
sample_dict["r3"] = "sample text 2"
预期输出:
【问题讨论】:
-
你能分享一些数据和想要的输出吗?感觉就像您基本上可以使用 scikit-learns jaccard-similarity 而不是真正使用 pandas。除了每行应用很慢 :) Vectorize!
-
@Quickbeam2k1 :我已经添加了示例输入和输出。你能提供一个矢量化的例子吗?
标签: python pandas dataframe machine-learning feature-extraction