StratifiedKFold vs StratifiedShuffleSplit vs StratifiedKFold + Shuffle

Posted

技术标签:

【中文标题】StratifiedKFold vs StratifiedShuffleSplit vs StratifiedKFold + Shuffle【英文标题】: 【发布时间】:2016-10-04 18:20:54 【问题描述】:

StratifiedKFold、StratifiedShuffleSplit、StratifiedKFold + Shuffle 有什么区别? 我应该什么时候使用每一个?当我获得更好的准确度分数时? 为什么我没有得到类似的结果? 我已经把我的代码和结果。我正在使用朴素贝叶斯和 10x10 交叉验证。

   #######SKF FOR LOOP########
from sklearn.cross_validation import StratifiedKFold
for i in range(10):
    skf = StratifiedKFold(y, n_folds=10, shuffle=True)
    scoresSKF2 = cross_validation.cross_val_score(clf, x, y , cv=skf)
    print(scoresSKF2)
    print("Accuracy SKF_NB: %0.2f (*/- %0.2f)" % (scoresSKF2.mean(), scoresSKF2.std()* 2))
    print("") 

    [ 0.1750503   0.16834532  0.16417051  0.18205424  0.1625758   0.1750939
      0.15495808  0.1712963   0.17096494  0.16918166]
    Accuracy SKF_NB: 0.17 (*/- 0.01)

    [ 0.16297787  0.17956835  0.17309908  0.17686093  0.17239388  0.16093615
     0.16970223  0.16956019  0.15473776  0.17208358]
   Accuracy SKF_NB: 0.17 (*/- 0.01)

    [ 0.17102616  0.16719424  0.1733871   0.16560877  0.166041    0.16122508
     0.16767852  0.17042824  0.18719212  0.1677307 ]
    Accuracy SKF_NB: 0.17 (*/- 0.01)

    [ 0.17275079  0.16633094  0.16906682  0.17570687  0.17210511  0.15515747
     0.16594391  0.18113426  0.16285135  0.1746953 ]
    Accuracy SKF_NB: 0.17 (*/- 0.01)

   [ 0.1764875   0.17035971  0.16186636  0.1644547   0.16632977  0.16469229
     0.17635155  0.17158565  0.17849899  0.17005223]
    Accuracy SKF_NB: 0.17 (*/- 0.01)

   [ 0.16815177  0.16863309  0.17309908  0.17368725  0.17152758  0.16093615
     0.17143683  0.17158565  0.16574906  0.16511898]
    Accuracy SKF_NB: 0.17 (*/- 0.01)

   [ 0.16786433  0.16690647  0.17309908  0.17022504  0.17066128  0.16613695
     0.17259324  0.17737269  0.16256158  0.17643645]
    Accuracy SKF_NB: 0.17 (*/- 0.01)

    [ 0.16297787  0.16402878  0.17684332  0.16791691  0.16950621  0.1716267
      0.18328997  0.16984954  0.15792524  0.17701683]
    Accuracy SKF_NB: 0.17 (*/- 0.01)

   [ 0.16958896  0.16633094  0.17165899  0.17080208  0.16026567  0.17538284
     0.17490604  0.16840278  0.17502173  0.16511898]
    Accuracy SKF_NB: 0.17 (*/- 0.01)

    [ 0.17275079  0.15625899  0.17713134  0.16762839  0.18278949  0.16729269
     0.16449841  0.17303241  0.16111272  0.1610563 ]
    Accuracy SKF_NB: 0.17 (*/- 0.02)


  #####StratifiedKFold + Shuffle######
  from sklearn.utils import shuffle
  for i in range(10):
      X, y = shuffle(x, y, random_state=i)
      skf = StratifiedKFold(y, 10)
      scoresSKF2 = cross_validation.cross_val_score(clf, X, y , cv=skf)
      print(scoresSKF2)
      print("Accuracy SKF_NB: %0.2f (*/- %0.2f)" % (scoresSKF2.mean(), scoresSKF2.std()* 2))
      print("")

   [ 0.16700201  0.15913669  0.16359447  0.17772649  0.17297141  0.16931523
    0.17172593  0.18576389  0.17125471  0.16134649]
    Accuracy SKF_NB: 0.17 (*/- 0.02)

    [ 0.02874389  0.02705036  0.02592166  0.02740912  0.02714409  0.02687085
     0.02891009  0.02922454  0.0260794   0.02814858]
    Accuracy SKF_NB: 0.03 (*/- 0.00)

    [ 0.0221328   0.02848921  0.02361751  0.02942874  0.02598903  0.02947125
     0.02804279  0.02719907  0.02376123  0.02205456]
    Accuracy SKF_NB: 0.03 (*/- 0.01)

   [ 0.02788158  0.02848921  0.03081797  0.03289094  0.02829916  0.03293846
     0.02862099  0.02633102  0.03245436  0.02843877]
    Accuracy SKF_NB: 0.03 (*/- 0.00)

    [ 0.02874389  0.0247482   0.02448157  0.02625505  0.02483396  0.02860445
     0.02948829  0.02604167  0.02665894  0.0275682 ]
    Accuracy SKF_NB: 0.03 (*/- 0.00)

    [ 0.0221328   0.02705036  0.02476959  0.02510098  0.02454519  0.02687085
      0.02254987  0.02199074  0.02492031  0.02524666]
    Accuracy SKF_NB: 0.02 (*/- 0.00)

    [ 0.02615694  0.03079137  0.02102535  0.03029429  0.02252382  0.02889338
       0.02197167  0.02604167  0.02752825  0.02843877]
    Accuracy SKF_NB: 0.03 (*/- 0.01)

    [ 0.02673182  0.02676259  0.03197005  0.03115984  0.02512273  0.03236059
      0.02688638  0.02372685  0.03216459  0.02698781]
     Accuracy SKF_NB: 0.03 (*/- 0.01)

    [ 0.0258695   0.02964029  0.03081797  0.02740912  0.02916546  0.02976018
      0.02717548  0.02922454  0.02694871  0.0275682 ]
    Accuracy SKF_NB: 0.03 (*/- 0.00)

    [ 0.03506755  0.0247482   0.02592166  0.02740912  0.02772163  0.02773765
      0.02948829  0.0234375   0.03332367  0.02118398]
    Accuracy SKF_NB: 0.03 (*/- 0.01)


    ######StratifiedShuffleSplit##########
   from sklearn.cross_validation import StratifiedShuffleSplit
   for i in range(10):
       sss = StratifiedShuffleSplit(y, 10, test_size=0.1, random_state=0)
       scoresSSS = cross_validation.cross_val_score(clf, x, y , cv=sss)
       print(scoresSSS)
       print("Accuracy SKF_NB: %0.2f (*/- %0.2f)" % (scoresSSS.mean(), scoresSSS.std()* 2))
       print("")
    [ 0.02743286  0.02858793  0.02512273  0.02281259  0.02541149  0.02743286
      0.02570026  0.02454519  0.02570026  0.02858793]
     Accuracy SKF_NB: 0.03 (*/- 0.00)

    [ 0.02743286  0.02858793  0.02512273  0.02281259  0.02541149  0.02743286
      0.02570026  0.02454519  0.02570026  0.02858793]
    Accuracy SKF_NB: 0.03 (*/- 0.00)

    [ 0.02743286  0.02858793  0.02512273  0.02281259  0.02541149  0.02743286
      0.02570026  0.02454519  0.02570026  0.02858793]
    Accuracy SKF_NB: 0.03 (*/- 0.00)

    [ 0.02743286  0.02858793  0.02512273  0.02281259  0.02541149  0.02743286
      0.02570026  0.02454519  0.02570026  0.02858793]
    Accuracy SKF_NB: 0.03 (*/- 0.00)

    [ 0.02743286  0.02858793  0.02512273  0.02281259  0.02541149  0.02743286
      0.02570026  0.02454519  0.02570026  0.02858793]
    Accuracy SKF_NB: 0.03 (*/- 0.00)

    [ 0.02743286  0.02858793  0.02512273  0.02281259  0.02541149  0.02743286
      0.02570026  0.02454519  0.02570026  0.02858793]
     Accuracy SKF_NB: 0.03 (*/- 0.00)

     [ 0.02743286  0.02858793  0.02512273  0.02281259  0.02541149  0.02743286
       0.02570026  0.02454519  0.02570026  0.02858793]
      Accuracy SKF_NB: 0.03 (*/- 0.00)

     [ 0.02743286  0.02858793  0.02512273  0.02281259  0.02541149  0.02743286
       0.02570026  0.02454519  0.02570026  0.02858793]
     Accuracy SKF_NB: 0.03 (*/- 0.00)

     [ 0.02743286  0.02858793  0.02512273  0.02281259  0.02541149  0.02743286
       0.02570026  0.02454519  0.02570026  0.02858793]
     Accuracy SKF_NB: 0.03 (*/- 0.00)

    [ 0.02743286  0.02858793  0.02512273  0.02281259  0.02541149  0.02743286
      0.02570026  0.02454519  0.02570026  0.02858793]
    Accuracy SKF_NB: 0.03 (*/- 0.00)

【问题讨论】:

你能告诉我们你的输出吗?您是运行一次并比较准确度得分,还是运行多次并比较每次的平均准确度得分? 好吧,我已经添加了输出。我正在运行 10x10 交叉验证并比较平均准确度分数。 【参考方案1】:

很难说哪个更好。选择应该更多地与您的建模策略和目标有关,但是社区中强烈倾向于使用 K 折交叉验证来进行模型选择和性能估计。我将尝试让您对指导您选择抽样技术的两个主要概念有一些直觉:分层交叉验证/随机拆分

另外请记住,您可以将这些采样技术用于两个截然不同的目标:模型选择和性能估计。

分层通过保持数据集标签/目标之间的平衡或比率来工作。因此,如果您的整个数据集有两个标签(例如正面和负面)并且这些标签的比率为 30/70,并且您分成 10 个子样本,则每个分层子样本应保持相同的比率。推理:由于机器学习模型的性能通常对样本平衡非常敏感,因此使用此策略通常会使模型对于子样本更加稳定。

拆分与随机拆分。拆分只是拆分,通常是为了拥有单独的训练和测试子样本。但是将第一个 X% 用于子样本,将剩余的 X% 用于另一个子样本可能不是一个好主意,因为它会引入非常高的偏差。通过引入子采样的随机性,随机分割发挥作用。

K 折交叉验证与随机拆分。 K 折叠包括创建 K 个子样本。因为您现在有更多的样本(而不是 2 个),您可以将其中一个子样本分开用于测试,其余子样本用于训练,对每个可能的测试/训练折叠组合执行此操作,并对结果进行平均。这称为交叉验证。做 K 折交叉验证就像做一个(非随机的)分裂 k 次,然后平均。小样本可能不会从 k 折交叉验证中受益,而大样本通常总是会从交叉验证中受益。随机分割是一种更有效(更快)的估计方式,但可能比 k 折交叉验证更容易出现抽样偏差。将分层和随机拆分相结合是一种尝试,试图建立一种有效且高效的抽样策略,以保持标签分布。

【讨论】:

感谢您的回答。我将使用分层交叉验证 + 随机分割或任何给我最佳准确性的方法。 @Rabbit 这个答案没有解决 StratifiedShuffleSplit,它似乎做了交叉验证(与 k 折不同)为每个 CV 批次重新采样。我不清楚为什么这会比 k-fold 更好或更差,我认为这是最初的问题?【参考方案2】:
    StratifiedKFold:在这里,我将两个数组打乱,但保留每一行的标签。 StratifiedKFOld + Shuffle:在这里,我在交叉验证之前对两个数组进行了洗牌。所以每一行不再链接到它的标签。这就是为什么与 1 相比准确性如此糟糕的原因。 StratifiedShuffleSplit:这里的准确性仍然很差,与 2 相同,因为数组已经被 2 洗牌,因此行和它们的标签之间不再存在链接。但是当我“独立”运行它时,准确度与 1 一样好。所以基本上 1 和 3 的效果相同。

【讨论】:

StratifiedKFOLD + Shuffle 不会将您的功能与其标签取消链接。就监督学习而言,任何与标签的脱节都没有意义。

以上是关于StratifiedKFold vs StratifiedShuffleSplit vs StratifiedKFold + Shuffle的主要内容,如果未能解决你的问题,请参考以下文章

GridSearchCV + StratifiedKfold 在 TFIDF 的情况下

异构 DataFrame 上的 StratifiedKfold

使用 StratifiedKFold 创建训练/测试/验证拆分

GridSearchCV 真的使用了 StratifiedKFold 吗?

xgboost.cv 给出 TypeError: 'StratifiedKFold' object is not iterable

scikit-learn 中的 StratifiedKFold 与 KFold