我们知道,交叉验证需要对数据集进行分割。而如何对数据进行分割呢?本文主要的内容就是提供一个分割的思路。所使用的程序语言基于python!
第一步,我们需要提供数据。数据其实无需多么实际,一个好的方法能够是能够尽可能适用于各类数据的。为了便于演示,我们使用自制的整数来进行交叉验证。如下所示。
可以看出,这批数据共有95个样本。现在假设我们要把他分割成10份,训练集和验证集的比例为(9:1)。如果我们拿出了验证集,剩下的就是训练集了。因此首要目标应该是确定验证集,这样一来,剩下的就是训练集了。而要确定验证集,需要先确定分割后每份数据的大小。这一步可以通过公式:
其中,
这样一来,就得到了每一份的应有长度(由于
可以看出,我们成功的把数据分成了10份。现在,只需要一次选择第i个数组为验证集,而后剩下的就可以作为训练集了。这里的两行关键操作如下:
valid = [[divide[j] for j in i] for i in reindex]
train = [[divide[j] for j in range(sum(radio)) if j not in i] for i in reindex]
其中reindex是验证集的所有可能位置,在此处应该是[[0],[1],[2],...,[9]],而divide就是我们上图中的被分割过的数据了。通过这两部的嵌套列表操作,我们就能够得到训练集和验证集了。
验证集如下图所示(训练集数据量太大,不宜展示,可用代码自测)
另外,假如
同样是可行的,但是在如何生成reindex上就要动动脑筋,想想怎么做。
我这里使用了lambda 函数,以便针对不同比例测试集。具体的请看源代码。总之,得到的 reindex 应该如下:
同样的,针对每个验证集的给出的下标,挑选对应的数据即可。而剩下的按顺序形成对应的训练集。
由此得到的验证集如下图所示:
它应该是一个11长度的列表,每个元素是由两个ndarray类型的数组组成的列表。
最后,附上包装好的函数代码文件。
import numpy as np
def crossvolid(mat, radio = (9,2)):
long = len(mat)
#pdb.set_trace()
if len(radio) == 2:
flag = radio[1]
elif len(radio) == 3:
flag = sum(radio[1:])
if flag >= 4:
raise ValueError
index = list(range(sum(radio)))
for i in range(flag-1):
index.append(i)
if flag == 1:
fun = lambda index,i:[index[i]]
if flag == 2:
fun = lambda index,i:(index[i],index[i+1])
if flag == 3:
fun = lambda index,i:(index[i],index[i+1],index[i+2])
reindex = [fun(index,i) for i in range(len(index)) if i<len(index)-flag+1]
assert len(reindex) == sum(radio)
every = round(long/sum(radio)+0.5)
divide = []
for i in range(sum(radio)):
if i != sum(radio):
sub = mat[i*every:(i+1)*every]
divide.append(sub)
else:
sub = mat[i*every:]
divide.append(sub)
assert len(divide) == sum(radio)
valid = [[divide[j] for j in i] for i in reindex]
train = [[divide[j] for j in range(sum(radio)) if j not in i] for i in reindex]
return train,valid
if __name__== '__main__':
data = np.arange(1,96)
train,valid = crossvolid(data)