【问题标题】:Uniformly distributed random variables in RandomSearchCV algorithmRandomSearchCV 算法中的均匀分布随机变量
【发布时间】:2020-10-08 19:12:57
【问题描述】:

我想澄清一件事。我知道以下命令将在(loc,loc+scale)之间生成一个均匀分布的随机变量

from scipy.stats import uniform
C =uniform.rvs(loc=0,scale=4)
print(C)

让我们假设我想在逻辑回归中使用这个分布,同时使用 RandomiizedSearchCV 算法,如下所示:

parameters =dict(C =uniform(loc=0,scale=4),penalty=['l2', 'l1'])
from sklearn.model_selection import RandomizedSearchCV
clf = RandomizedSearchCV(logreg, parameters, random_state=0)
search = clf.fit(iris.data, iris.target)
print(search.best_params_)

但我不明白一件事:RandomizedSearchCV 就像一个网格搜索,只是尝试选择具有给定试验量的组合的随机数(n_iter),但这里C 是一个对象,它不是数组或类似的东西,即使我无法打印它的值,那么我怎么能理解这段代码呢?它如何生成随机数?没有显示房车?

【问题讨论】:

    标签: machine-learning scikit-learn scipy


    【解决方案1】:

    根据documentationparam_distributions 参数(此处为parameters):

    以参数名称 (str) 作为键和分布或要尝试的参数列表的字典。发行版必须提供rvs 抽样方法(例如来自 scipy.stats.distributions 的抽样方法)。如果给定一个列表,则统一采样。

    所以,每次迭代发生的事情是:

    • 根据[0, 4] 中的均匀分布对C 的值进行采样
    • penalty 采样一个值,统一在l1l2 之间(即每个都有50% 的概率)
    • 使用这些采样值运行 CV 并存储结果

    使用documentation 中的示例(实际上与您问题中的参数相同):

    from sklearn.datasets import load_iris
    from sklearn.linear_model import LogisticRegression
    from sklearn.model_selection import RandomizedSearchCV
    from scipy.stats import uniform
    
    iris = 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) 种组合,以及它们的性能:

    import pandas as pd
    df = pd.DataFrame(search.cv_results_)
    print(df[['params','mean_test_score']])
    # result:
                                            params  mean_test_score
    0    {'C': 2.195254015709299, 'penalty': 'l1'}         0.980000
    1   {'C': 3.3770629943240693, 'penalty': 'l1'}         0.980000
    2   {'C': 2.1795327319875875, 'penalty': 'l1'}         0.980000
    3   {'C': 2.4942547871438894, 'penalty': 'l2'}         0.980000
    4     {'C': 1.75034884505077, 'penalty': 'l2'}         0.980000
    5  {'C': 0.22685190926977272, 'penalty': 'l2'}         0.966667
    6   {'C': 1.5337660753031108, 'penalty': 'l2'}         0.980000
    7   {'C': 3.2486749151019727, 'penalty': 'l2'}         0.980000
    8   {'C': 2.2721782443757292, 'penalty': 'l1'}         0.980000
    9     {'C': 3.34431505414951, 'penalty': 'l2'}         0.980000
    

    从那里很明显,C 的所有尝试值都在[0, 4] 中,按照要求。此外,由于有多个组合达到了 0.98 的最佳分数,因此 scikit-learn 使用 cv_results_ 返回的第一个组合。

    仔细观察,我们发现只有 4 次试验以 l1 惩罚(而不是 10 次中的 50%,即 5 次,正如我们预期的那样),但这对于小随机样本是可以预料的(这里只有 10 个)。

    【讨论】:

      【解决方案2】:

      您想为 C 使用多个值以供 RandomizedSearchCV 发现。 refit=True 和 return_train_score=True 允许您使用具有最佳模型拟合的 clf。

       X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.4,random_state=42)
      
       logreg=LogisticRegression(C=5,max_iter=10000)
       #https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html
       parameter_grid={'C':[uniform.rvs(loc=0,scale=4),3,4,10,100],'tol':[0.1,0.2,0.3,0.5,1,5,10,100]}  
      
       clf = RandomizedSearchCV(logreg, parameter_grid,
                           n_iter = 10,
                           scoring='accuracy',
                           cv=5,
                           refit=True, 
                           return_train_score = True,
                           random_state=0)
      
       search = clf.fit(X_train,y_train)
       predictions=clf.predict(X_test)
      
       print("Model accuracy {}%".format(accuracy_score(y_test,predictions)*100))
      
       cv_results_df = pd.DataFrame(clf.cv_results_)
      
       column = cv_results_df.loc[:, ['params']]
       print(column)
      
        # Extract and print the row that had the best mean test score
        best_row = cv_results_df[cv_results_df['rank_test_score'] == 1 ]
        print(best_row)
      
        #print(clf.cv_results_)
        #print(clf.best_index_) you can use with iloc to slice the best row
        print(clf.best_params_)
        print(clf.best_score_)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-08
        • 2021-12-28
        • 1970-01-01
        • 2020-04-04
        • 1970-01-01
        • 2011-03-02
        相关资源
        最近更新 更多