scikit-learn 中 train_test_split() 的不稳定行为
Erratic behavior of train_test_split() in scikit-learn
Python 3.5(蟒蛇安装)
SciKit 0.17.1
我只是不明白为什么 train_test_split()
一直给我我认为不可靠的训练案例列表拆分。
这是一个例子。
我的列表 trnImgPaths
有 3 个 class,每个有 67 张图片(总共 201 张图片):
['/Caltech101/ferry/image_0001.jpg',
... thru ...
'/Caltech101/ferry/image_0067.jpg',
'/Caltech101/laptop/image_0001.jpg',
... thru ...
'/Caltech101/laptop/image_0067.jpg',
'/Caltech101/airplane/image_0001.jpg',
... thru ...
'/Caltech101/airplane/image_0067.jpg']
我的目标列表 trnImgTargets
在长度上与此完美匹配,classes 本身也与 trnImgPaths
.
完美匹配
In[148]: len(trnImgPaths)
Out[148]: 201
In[149]: len(trnImgTargets)
Out[149]: 201
如果我运行:
[trnImgs, testImgs, trnTargets, testTargets] = \
train_test_split(trnImgPaths, trnImgTargets, test_size=141, train_size=60, random_state=42)
或
[trnImgs, testImgs, trnTargets, testTargets] = \
train_test_split(trnImgPaths, trnImgTargets, test_size=0.7, train_size=0.3, random_state=42)
或
[trnImgs, testImgs, trnTargets, testTargets] = \
train_test_split(trnImgPaths, trnImgTargets, test_size=0.7, train_size=0.3)
尽管我最终得到:
In[150]: len(trnImgs)
Out[150]: 60
In[151]: len(testImgs)
Out[151]: 141
In[152]: len(trnTargets)
Out[152]: 60
In[153]: len(testTargets)
Out[153]: 141
我从来没有得到训练集 20 - 20 - 20 的完美分割。我可以通过手动检查和通过混淆矩阵进行健全性检查来判断。
下面分别是上面每个实验的结果:
[[19 0 0]
[ 0 21 0]
[ 0 0 20]]
[[19 0 0]
[ 0 21 0]
[ 0 0 20]]
[[16 0 0]
[ 0 22 0]
[ 0 0 22]]
我希望分裂是完美平衡的。任何想法为什么会这样?
它甚至看起来可能会先验地错误class验证一些案例,因为对于给定的 class.
永远不会有 n=22 个训练案例
简而言之:这是预期的行为。
随机拆分并不能保证 "balanced" 拆分。这就是 分层 拆分的目的(也是 implemented in sklearn)。
根据@lejlot 的评论,我设法锁定案例数量的方法是在 SKLearn 0.17 上使用 train_test_split
的新功能。现在有一个名为 stratify 的参数,我使用如下(这将强制拆分遵循标签列表中的标签数量):
[trnImgs, testImgs, trnTargets, testTargets] = \
train_test_split(trnImgPaths, trnImgTargets, test_size=0.7,
train_size=0.3, stratify=trnImgTargets)
现在,每次我 运行 我得到的脚本:
[[20 0 0]
[ 0 20 0]
[ 0 0 20]]
Python 3.5(蟒蛇安装) SciKit 0.17.1
我只是不明白为什么 train_test_split()
一直给我我认为不可靠的训练案例列表拆分。
这是一个例子。
我的列表 trnImgPaths
有 3 个 class,每个有 67 张图片(总共 201 张图片):
['/Caltech101/ferry/image_0001.jpg',
... thru ...
'/Caltech101/ferry/image_0067.jpg',
'/Caltech101/laptop/image_0001.jpg',
... thru ...
'/Caltech101/laptop/image_0067.jpg',
'/Caltech101/airplane/image_0001.jpg',
... thru ...
'/Caltech101/airplane/image_0067.jpg']
我的目标列表 trnImgTargets
在长度上与此完美匹配,classes 本身也与 trnImgPaths
.
In[148]: len(trnImgPaths)
Out[148]: 201
In[149]: len(trnImgTargets)
Out[149]: 201
如果我运行:
[trnImgs, testImgs, trnTargets, testTargets] = \
train_test_split(trnImgPaths, trnImgTargets, test_size=141, train_size=60, random_state=42)
或
[trnImgs, testImgs, trnTargets, testTargets] = \
train_test_split(trnImgPaths, trnImgTargets, test_size=0.7, train_size=0.3, random_state=42)
或
[trnImgs, testImgs, trnTargets, testTargets] = \
train_test_split(trnImgPaths, trnImgTargets, test_size=0.7, train_size=0.3)
尽管我最终得到:
In[150]: len(trnImgs)
Out[150]: 60
In[151]: len(testImgs)
Out[151]: 141
In[152]: len(trnTargets)
Out[152]: 60
In[153]: len(testTargets)
Out[153]: 141
我从来没有得到训练集 20 - 20 - 20 的完美分割。我可以通过手动检查和通过混淆矩阵进行健全性检查来判断。 下面分别是上面每个实验的结果:
[[19 0 0]
[ 0 21 0]
[ 0 0 20]]
[[19 0 0]
[ 0 21 0]
[ 0 0 20]]
[[16 0 0]
[ 0 22 0]
[ 0 0 22]]
我希望分裂是完美平衡的。任何想法为什么会这样?
它甚至看起来可能会先验地错误class验证一些案例,因为对于给定的 class.
永远不会有 n=22 个训练案例简而言之:这是预期的行为。
随机拆分并不能保证 "balanced" 拆分。这就是 分层 拆分的目的(也是 implemented in sklearn)。
根据@lejlot 的评论,我设法锁定案例数量的方法是在 SKLearn 0.17 上使用 train_test_split
的新功能。现在有一个名为 stratify 的参数,我使用如下(这将强制拆分遵循标签列表中的标签数量):
[trnImgs, testImgs, trnTargets, testTargets] = \
train_test_split(trnImgPaths, trnImgTargets, test_size=0.7,
train_size=0.3, stratify=trnImgTargets)
现在,每次我 运行 我得到的脚本:
[[20 0 0]
[ 0 20 0]
[ 0 0 20]]