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