Python:计算 tf-idf 中两列之间的余弦相似度时出现内存错误 Pandas
Python: MemoryError when computing tf-idf cosine similarity between two columns in Pandas
我正在尝试计算 Pandas 数据帧中两列之间的 tf-idf 向量余弦相似度。一列包含搜索查询,另一列包含产品标题。余弦相似度值旨在作为搜索 engine/ranking 机器学习算法的 "feature"。
我在 iPython 笔记本上执行此操作,但不幸的是 运行 遇到了 MemoryErrors,经过几个小时的挖掘我不确定为什么。
我的设置:
- 联想 E560 笔记本电脑
- 酷睿 i7-6500U @ 2.50 GHz
- 16 GB 内存
- Windows 10
- 使用 anaconda 3.5 内核对所有库进行全新更新
我已经根据类似的 Whosebug 问题在一个小型玩具数据集上测试了我的 code/goal:
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from scipy import spatial
clf = TfidfVectorizer()
a = ['hello world', 'my name is', 'what is your name?', 'max cosine sim']
b = ['my name is', 'hello world', 'my name is what?', 'max cosine sim']
df = pd.DataFrame(data={'a':a, 'b':b})
clf.fit(df['a'] + " " + df['b'])
tfidf_a = clf.transform(df['a']).todense()
tfidf_b = clf.transform(df['b']).todense()
row_similarities = [1 - spatial.distance.cosine(tfidf_a[x],tfidf_b[x]) for x in range(len(tfidf_a)) ]
df['tfidf_cosine_similarity'] = row_similarities
print(df)
这给出了以下(好!)输出:
a b tfidf_cosine_similarity
0 hello world my name is 0.000000
1 my name is hello world 0.000000
2 what is your name? my name is what? 0.725628
3 max cosine sim max cosine sim 1.000000
但是,当我尝试将相同的方法应用于尺寸为 186,154 x 5 的数据框 (df_all_export)(其中 5 列中的 2 列是查询 (search_term) 和文档 (product_title) 这样:
clf.fit(df_all_export['search_term'] + " " + df_all_export['product_title'])
tfidf_a = clf.transform(df_all_export['search_term']).todense()
tfidf_b = clf.transform(df_all_export['product_title']).todense()
row_similarities = [1 - spatial.distance.cosine(tfidf_a[x],tfidf_b[x]) for x in range(len(tfidf_a)) ]
df_all_export['tfidf_cosine_similarity'] = row_similarities
df_all_export.head()
我明白了……(这里没有给出完整的错误,但你明白了):
MemoryError Traceback (most recent call last)
<ipython-input-27-8308fcfa8f9f> in <module>()
12 clf.fit(df_all_export['search_term'] + " " + df_all_export['product_title'])
13
---> 14 tfidf_a = clf.transform(df_all_export['search_term']).todense()
15 tfidf_b = clf.transform(df_all_export['product_title']).todense()
16
完全迷失在这一点上,但我担心解决方案会非常简单和优雅:)
提前致谢!
您仍然可以使用 sklearn.metrics.pairwise 方法处理稀疏矩阵/数组:
# I've executed your example up to (including):
# ...
clf.fit(df['a'] + " " + df['b'])
A = clf.transform(df['a'])
B = clf.transform(df['b'])
from sklearn.metrics.pairwise import *
paired_cosine_distances
将显示您的字符串有多远或有多不同(比较两列中的值 "row-by-row")
0
- 表示完全匹配
In [136]: paired_cosine_distances(A, B)
Out[136]: array([ 1. , 1. , 0.27437247, 0. ])
cosine_similarity
将第 a
列的第一个字符串与第 b
列中的所有字符串进行比较(第 1 行 );列 a
的第二个字符串以及列 b
中的所有字符串(行 2)等等...
In [137]: cosine_similarity(A, B)
Out[137]:
array([[ 0. , 1. , 0. , 0. ],
[ 1. , 0. , 0.74162106, 0. ],
[ 0.43929881, 0. , 0.72562753, 0. ],
[ 0. , 0. , 0. , 1. ]])
In [141]: A
Out[141]:
<4x10 sparse matrix of type '<class 'numpy.float64'>'
with 12 stored elements in Compressed Sparse Row format>
In [142]: B
Out[142]:
<4x10 sparse matrix of type '<class 'numpy.float64'>'
with 12 stored elements in Compressed Sparse Row format>
注意:所有计算都是使用 sparsed 矩阵进行的 - 我们没有在内存中解压缩它们!
在 MaxU 上面发布的友好帮助和解决方案的帮助下,我在这里展示了完成我试图实现的任务的完整代码。除了 MemoryError
之外,当我尝试一些 "hacky" 解决方法时,tt 还避开了出现在余弦相似度计算中的奇怪 nans。
请注意以下代码是部分片段,因为已经在完整代码中构造了尺寸为 186,134 x 5
的大型数据框 df_all_export
。
我希望这对尝试使用 tf-idf 向量计算搜索查询和匹配文档之间的余弦相似度的其他人有所帮助。对于这样一个常见的"problem",我努力寻找一个使用 SKLearn 和 Pandas.
实现的清晰解决方案
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import paired_cosine_distances as pcd
clf = TfidfVectorizer()
clf.fit(df_all_export['search_term'] + " " + df_all_export['product_title'])
A = clf.transform(df_all_export['search_term'])
B = clf.transform(df_all_export['product_title'])
cosine = 1 - pcd(A, B)
df_all_export['tfidf_cosine'] = cosine
我正在尝试计算 Pandas 数据帧中两列之间的 tf-idf 向量余弦相似度。一列包含搜索查询,另一列包含产品标题。余弦相似度值旨在作为搜索 engine/ranking 机器学习算法的 "feature"。
我在 iPython 笔记本上执行此操作,但不幸的是 运行 遇到了 MemoryErrors,经过几个小时的挖掘我不确定为什么。
我的设置:
- 联想 E560 笔记本电脑
- 酷睿 i7-6500U @ 2.50 GHz
- 16 GB 内存
- Windows 10
- 使用 anaconda 3.5 内核对所有库进行全新更新
我已经根据类似的 Whosebug 问题在一个小型玩具数据集上测试了我的 code/goal:
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from scipy import spatial
clf = TfidfVectorizer()
a = ['hello world', 'my name is', 'what is your name?', 'max cosine sim']
b = ['my name is', 'hello world', 'my name is what?', 'max cosine sim']
df = pd.DataFrame(data={'a':a, 'b':b})
clf.fit(df['a'] + " " + df['b'])
tfidf_a = clf.transform(df['a']).todense()
tfidf_b = clf.transform(df['b']).todense()
row_similarities = [1 - spatial.distance.cosine(tfidf_a[x],tfidf_b[x]) for x in range(len(tfidf_a)) ]
df['tfidf_cosine_similarity'] = row_similarities
print(df)
这给出了以下(好!)输出:
a b tfidf_cosine_similarity
0 hello world my name is 0.000000
1 my name is hello world 0.000000
2 what is your name? my name is what? 0.725628
3 max cosine sim max cosine sim 1.000000
但是,当我尝试将相同的方法应用于尺寸为 186,154 x 5 的数据框 (df_all_export)(其中 5 列中的 2 列是查询 (search_term) 和文档 (product_title) 这样:
clf.fit(df_all_export['search_term'] + " " + df_all_export['product_title'])
tfidf_a = clf.transform(df_all_export['search_term']).todense()
tfidf_b = clf.transform(df_all_export['product_title']).todense()
row_similarities = [1 - spatial.distance.cosine(tfidf_a[x],tfidf_b[x]) for x in range(len(tfidf_a)) ]
df_all_export['tfidf_cosine_similarity'] = row_similarities
df_all_export.head()
我明白了……(这里没有给出完整的错误,但你明白了):
MemoryError Traceback (most recent call last)
<ipython-input-27-8308fcfa8f9f> in <module>()
12 clf.fit(df_all_export['search_term'] + " " + df_all_export['product_title'])
13
---> 14 tfidf_a = clf.transform(df_all_export['search_term']).todense()
15 tfidf_b = clf.transform(df_all_export['product_title']).todense()
16
完全迷失在这一点上,但我担心解决方案会非常简单和优雅:)
提前致谢!
您仍然可以使用 sklearn.metrics.pairwise 方法处理稀疏矩阵/数组:
# I've executed your example up to (including):
# ...
clf.fit(df['a'] + " " + df['b'])
A = clf.transform(df['a'])
B = clf.transform(df['b'])
from sklearn.metrics.pairwise import *
paired_cosine_distances
将显示您的字符串有多远或有多不同(比较两列中的值 "row-by-row")
0
- 表示完全匹配
In [136]: paired_cosine_distances(A, B)
Out[136]: array([ 1. , 1. , 0.27437247, 0. ])
cosine_similarity
将第 a
列的第一个字符串与第 b
列中的所有字符串进行比较(第 1 行 );列 a
的第二个字符串以及列 b
中的所有字符串(行 2)等等...
In [137]: cosine_similarity(A, B)
Out[137]:
array([[ 0. , 1. , 0. , 0. ],
[ 1. , 0. , 0.74162106, 0. ],
[ 0.43929881, 0. , 0.72562753, 0. ],
[ 0. , 0. , 0. , 1. ]])
In [141]: A
Out[141]:
<4x10 sparse matrix of type '<class 'numpy.float64'>'
with 12 stored elements in Compressed Sparse Row format>
In [142]: B
Out[142]:
<4x10 sparse matrix of type '<class 'numpy.float64'>'
with 12 stored elements in Compressed Sparse Row format>
注意:所有计算都是使用 sparsed 矩阵进行的 - 我们没有在内存中解压缩它们!
在 MaxU 上面发布的友好帮助和解决方案的帮助下,我在这里展示了完成我试图实现的任务的完整代码。除了 MemoryError
之外,当我尝试一些 "hacky" 解决方法时,tt 还避开了出现在余弦相似度计算中的奇怪 nans。
请注意以下代码是部分片段,因为已经在完整代码中构造了尺寸为 186,134 x 5
的大型数据框 df_all_export
。
我希望这对尝试使用 tf-idf 向量计算搜索查询和匹配文档之间的余弦相似度的其他人有所帮助。对于这样一个常见的"problem",我努力寻找一个使用 SKLearn 和 Pandas.
实现的清晰解决方案import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import paired_cosine_distances as pcd
clf = TfidfVectorizer()
clf.fit(df_all_export['search_term'] + " " + df_all_export['product_title'])
A = clf.transform(df_all_export['search_term'])
B = clf.transform(df_all_export['product_title'])
cosine = 1 - pcd(A, B)
df_all_export['tfidf_cosine'] = cosine