我想澄清一件事。我知道以下命令将在(loc, loc+scale)之间生成一个均匀分布的随机变量
from scipy.stats import uniformC =uniform.rvs(loc=0,scale=4)print(C)
假设我想在使用RandomizedSearchCV算法的逻辑回归中使用这个分布,如下所示:
parameters =dict(C =uniform(loc=0,scale=4),penalty=['l2', 'l1'])from sklearn.model_selection import RandomizedSearchCVclf = RandomizedSearchCV(logreg, parameters, random_state=0)search = clf.fit(iris.data, iris.target)print(search.best_params_)
但我不明白一件事:RandomizedSearchCV类似于网格搜索,只是它尝试在给定尝试次数(n_iter
)下随机选择组合数量,但这里C
是一个对象,它不是数组或类似的东西,我甚至无法打印它的值,所以我如何理解这段代码?它是如何生成随机数的?没有rvs的指示?
回答:
根据文档中关于param_distributions
参数(这里是parameters
)的说明:
包含参数名称(
str
)作为键和要尝试的分布或参数列表的字典。分布必须提供rvs
方法用于抽样(如scipy.stats.distributions中的那些)。如果给定一个列表,则会均匀抽样。
因此,在每次迭代中发生的事情是:
- 根据
[0, 4]
中的均匀分布抽取C
的值 - 在
l1
和l2
之间均匀抽取penalty
的值(即每种情况有50%的概率) - 使用这些抽取的值运行交叉验证并存储结果
使用文档中的示例(与您的问题中的参数几乎相同):
from sklearn.datasets import load_irisfrom sklearn.linear_model import LogisticRegressionfrom sklearn.model_selection import RandomizedSearchCVfrom scipy.stats import uniformiris = load_iris()logistic = LogisticRegression(solver='saga', tol=1e-2, max_iter=200, random_state=0)distributions = dict(C=uniform(loc=0, scale=4), penalty=['l2', 'l1'])clf = RandomizedSearchCV(logistic, distributions, random_state=0)search = clf.fit(iris.data, iris.target)
我们得到
search.best_params_# {'C': 2.195254015709299, 'penalty': 'l1'}
我们可以进一步了解所有(10个)使用的组合及其表现:
从中可以清楚地看出,尝试的所有C
值确实都在[0, 4]
范围内,如所要求的。此外,由于有多种组合达到了最佳得分0.98,scikit-learn使用cv_results_
中返回的第一个组合。
仔细观察,我们发现只有4次试验使用了l1
惩罚(而不是我们可能期望的10次中的50%,即5次),但这在小型随机样本(这里只有10个)中是可以预期的。