Scikit-Learn RandomizedSearchCV 不适用于 MultinomialNB 中的 class_prior

Scikit-Learn RandomizedSearchCV not working for class_prior in MultinomialNB

我正在尝试对 MultinomialNB (1) 进行随机参数优化。现在我的参数有 3 个而不是一个值,因为它是 'class_prior' 而我有 3 个 类。

from sklearn.naive_bayes import MultinomialNB
from sklearn.grid_search import RandomizedSearchCV
from scipy.stats import uniform

tuned_parameters = {'class_prior': [uniform.rvs(0,3), uniform.rvs(0,3), 
uniform.rvs(0,3)]}
clf = RandomizedSearchCV(MultinomialNB(), tuned_parameters, cv=3, 
scoring='f1_micro', n_iter=10)

但是错误日志看起来像:

...
File "/home/mark/Virtualenvs/python3env2/lib/python3.5/site-
packages/sklearn/naive_bayes.py", line 607, in fit
self._update_class_log_prior(class_prior=class_prior)
File "/home/mark/Virtualenvs/python3env2/lib/python3.5/site-
packages/sklearn/naive_bayes.py", line 455, in _update_class_log_prior
if len(class_prior) != n_classes:
TypeError: object of type 'numpy.float64' has no len()

还尝试删除 .rvs -->

TypeError: object of type 'rv_frozen' has no len()

是否无法随机搜索具有 3 个分量的变量,即 3 class_priors?

(1) http://scikit-learn.org/stable/modules/grid_search.html

是的,这是可能的。这样做:

tuned_parameters = {'class_prior': [[uniform.rvs(0,3), uniform.rvs(0,3), 
uniform.rvs(0,3)]]}

请注意值周围的额外方括号。 原因是要由 RandomizedSearchCV(或 GridSearchCV)调整的参数应该包装在一个列表中,每次都会尝试其中的一个元素。将保留产生最高分数(或在丢失的情况下最低)的元素组合。

例如,请参阅此用于 SVC 参数调整的简单代码:

parameters = {'kernel':['linear', 'rbf'], 'C':[1, 10]}

这将扩展为总共 4 个值的排列,如下所示:

Option1:- 'kernel':'linear', 'C':1
Option2:- 'kernel':'linear', 'C':10
Option3:- 'kernel':'rbf', 'C':1
Option4:- 'kernel':'rbf', 'C':10

这意味着估计器将拟合 4 次(每次使用上面的不同选项),然后保留最佳估计器。

在你的例子中,根据documentation of MultinomialNB class_prior是类的概率数组。

所以理想情况下应该扩展成这样:

选项 1:'class_prior':[uniform.rvs(0,3),uniform.rvs(0,3),uniform.rvs(0,3)]

但在 RandomizedSearhCV 中(没有关于 class_prior 类型的信息),它将被扩展为:

Option1: 'class_prior': uniform.rvs(0,3)
Option2: 'class_prior': uniform.rvs(0,3)
Option3: 'class_prior': uniform.rvs(0,3)

然后将其呈现给 MultinomialNB,并且由于 uniform.rvs() 的输出是浮点数而不是列表,因此它不会有 len(),因此不会有错误。

为此,您需要使用双方括号,以便正确展开如下所示:

Option1: 'class_prior': [uniform.rvs(0,3), uniform.rvs(0,3), uniform.rvs(0,3)]

但是现在也有问题。由于扩展结果只有一个选项,所以显然无论分数是多少都会被选中(因为我们没有其他选择)。

此外,RandomizedSearchCV 会抛出错误,因为您指定了 n_iter=10 并且选择的数量应该多于此(在我们的例子中,它是一个选择)。

所以你需要像这样改变你的tuned_parameters

tuned_parameters = {'class_prior': [[uniform.rvs(0,3), uniform.rvs(0,3), uniform.rvs(0,3)],
                                    [uniform.rvs(0,3), uniform.rvs(0,3), uniform.rvs(0,3)], 
                                    [uniform.rvs(0,3), uniform.rvs(0,3), uniform.rvs(0,3)],
                                    [uniform.rvs(0,3), uniform.rvs(0,3), uniform.rvs(0,3)],
                                    [uniform.rvs(0,3), uniform.rvs(0,3), uniform.rvs(0,3)],
                                    ...
                                    ...
                                    ... ]}

至少n_iter次。