在 50 个变量 x 100k 行数据集上优化 K-最近邻算法
Posted
技术标签:
【中文标题】在 50 个变量 x 100k 行数据集上优化 K-最近邻算法【英文标题】:Optimize K-Nearest Neighbors Algorithm on 50 variables x 100k row dataset 【发布时间】:2020-01-24 16:31:51 【问题描述】:我想优化一段代码,它可以帮助我计算给定数据集中每个项目的最近邻居(包含 10 万行)。该数据集包含 50 个可变列,有助于描述每个行项,并且大多数单元格包含介于 0 - 1 之间的概率值。
问题:我是python的新手,但想知道是否有更高级的用户可以在下面的代码中推荐任何更好的结构,这将有助于我加快计算速度。目前,该程序需要很长时间才能完成。提前致谢!
import math
import numpy as np
import pandas as pd
from scipy.spatial import distance
from sklearn.neighbors import KNeighborsRegressor
df_set = pd.read_excel('input.xlsx', skiprows=0)
distance_columns = ["var_1",
......,
......,
......,
"var_50"]
def euclidean_distance(row):
inner_value = 0
for k in distance_columns:
inner_value += (row[k] - selected_row[k]) ** 2
return math.sqrt(inner_value)
knn_name_list = []
for i in range(len(df_set.index)):
numeric = df_set[distance_columns]
normalized = (numeric - numeric.mean()) / numeric.std()
normalized.fillna(0, inplace=True)
selected_normalized = normalized[df_set["Filename"] == df_set["Filename"][i]]
euclidean_distances = normalized.apply(lambda row: distance.euclidean(row, selected_normalized), axis=1)
distance_frame = pd.DataFrame(data="dist": euclidean_distances, "idx": euclidean_distances.index)
distance_frame.sort_values("dist", inplace=True)
second_smallest = distance_frame.iloc[1]["idx"]
most_similar_to_selected = df_set.loc[int(second_smallest)]["Filename"]
knn_name_list.append(most_similar_to_selected)
print(knn_name_list)
df_set['top_neighbor'] = np.array(knn_name_list)
df_set.to_csv('output.csv', encoding='utf-8', sep=',', index=False)
【问题讨论】:
您是否已对瓶颈所在的位置进行过任何测量?这可以像通过打印带有一些标签的time.perf_counter()
的输出来测量时间一样简单,以查看性能下降的位置。这可能只是库函数,在这一点上测量性能变得有点棘手,但这些简单的测试可能会导致令人惊讶的结果和简单的修复以提高性能。
很棒的建议,我今天会尝试这样做,如果我有任何新见解,我会更新我的帖子。谢谢@Etienne!
我猜你不想正确使用软件包(sklearn、scipy 等)?
不,也请推荐带有包的答案。我将测试这两种方法的速度。
【参考方案1】:
我建议使用NearestNeighbors。 (将 n_jobs 设置为 -1 以使用所有处理器)
import numpy as np
from sklearn.neighbors import NearestNeighbors
from sklearn.preprocessing import normalize
#Loading data
df_set = ...
#Selecting numerical data
numeric = df_set[distance_columns]
#normelizing
normalized = normalize(numeric, norm='l1', axis=1, copy=True, return_norm=False)
#Initializing NearestNeighbors
neigh = NearestNeighbors(n_neighbors=5, metric='euclidean', n_jobs=-1)
#Fitting with normilized data
neigh.fit(normalized)
...
second_smallest = ...
#Getting Most similar to your selected data
most_similar_to_selected = neigh.kneighbors(second_smallest)
【讨论】:
关于如何将 for 循环集成到您的答案中的任何想法?循环遍历数据集中的每一行并为数据集中的每个项目重新计算最近邻是很重要的。 您可以使用 kneighbors_graph 方法做到这一点:scikit-learn.org/stable/modules/generated/…【参考方案2】:为了给您提供@Amine 方法的另一个想法,您还可以将PCA Transformation
包含在其中(https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html)。
这将像这样工作:
import numpy as np
from sklearn.neighbors import NearestNeighbors
from sklearn.preprocessing import normalize
from sklearn.decomposition import PCA
#Loading data
df_set = ...
#Selecting numerical data
numeric = df_set[distance_columns]
#normelizing
normalized = normalize(numeric, norm='l1', axis=1, copy=True, return_norm=False)
#reduce number of compononents (here to 25)
pca = PCA(n_components=25)
pca.fit(normalized)
pcanormalized = pca.fit_transform(normalized)
#Initializing NearestNeighbors
neigh = NearestNeighbors(n_neighbors=5, metric='euclidean', n_jobs=-1)
#Fitting with normilized data
neigh.fit(pcanormalized)
...
second_smallest = ...
#Getting Most similar to your selected data
most_similar_to_selected = neigh.kneighbors(second_smallest)
【讨论】:
感谢您的回答。我还将尝试执行此代码以查看速度。关于如何将 for 循环(考虑到我的问题中描述的数据集中的每个项目)集成到您的答案中的任何想法?以上是关于在 50 个变量 x 100k 行数据集上优化 K-最近邻算法的主要内容,如果未能解决你的问题,请参考以下文章