我正在尝试使用 sklearn 在 MNIST 分类任务上训练 KNN 模型。当我尝试使用 sklearn 的 GridSearchCV 或 RandomizedSearchCV 类调整参数时,我的代码执行时间非常长。
作为实验,我使用 KNeighborsClassifier() 和默认参数创建了一个 KNN 模型,并将这些相同的参数传递给 GridSearchCV。 Afaik,这应该意味着 GridSearchCV 只有一组参数,因此实际上不应该执行“搜索”。然后,我在训练数据上调用了两者的 .fit() 方法并计时了它们的执行时间(参见下面的代码)。 KNN 模型的 .fit() 方法运行时间约为 11 秒,而 GridSearchCV 模型运行时间超过 20 分钟。
我知道 GridSearchCV 应该花费稍长的时间,因为它正在执行 5 倍交叉验证,但执行时间的差异似乎太大,无法用它来解释。
我是否对 GridSearchCV 调用执行了某些操作,导致它需要很长时间才能执行?我可以做些什么来加速它吗?
import sklearn
import time
# importing models
from sklearn.model_selection import StratifiedShuffleSplit
from sklearn.model_selection import GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
# Importing data
from sklearn.datasets import fetch_openml
mnist = fetch_openml(name='mnist_784')
print("data loaded")
# splitting the data into stratified train & test sets
X, y = mnist.data, mnist.target # mnist mj.data.shape is (n_samples, n_features)
sss = StratifiedShuffleSplit(n_splits = 1, test_size = 0.2, random_state = 0)
for train_index, test_index in sss.split(X,y):
X_train, y_train = X[train_index], y[train_index]
X_test, y_test = X[test_index], y[test_index]
print("data split")
# Data has no missing values and is preprocessed, so no cleaing needed.
# using a KNN model, as recommended
knn = KNeighborsClassifier()
print("model created")
print("training model")
start = time.time()
knn.fit(X_train, y_train)
end = time.time()
print(f"Execution time for knn paramSearch was: {end-start}")
# Parameter tuning.
# starting by performing a broad-range search on n_neighbours to work out the
# rough scale the parameter should be on
print("beginning param tuning")
params = {'n_neighbors':[5],
'weights':['uniform'],
'leaf_size':[30]
}
paramSearch = GridSearchCV(
estimator = knn,
param_grid = params,
cv=5,
n_jobs = -1)
start = time.time()
paramSearch.fit(X_train, y_train)
end = time.time()
print(f"Execution time for knn paramSearch was: {end-start}")
对于普通 KNN,成本高昂的过程是“预测”,而不是拟合:拟合只是保存数据的副本,然后预测必须完成查找最近邻居的工作。 因此,由于您的搜索涉及对每个测试折叠进行评分,因此这将比仅仅拟合花费更多的时间。 更好的比较是让您在非搜索部分的训练集上进行预测。 但是,sklearn 确实对
algorithm
参数有不同的选项,其目的是通过构建搜索结构来牺牲一些预测复杂性以增加训练时间,从而在预测时需要更少的比较。 使用默认的
algorithm='auto'
,您可能正在构建一棵球树,因此第一段的效果不会那么深刻。 我怀疑这仍然是问题所在:现在训练时间将不可忽略,但搜索中的评分部分花费了大部分时间。