Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 带Sklearn的组/簇K倍CV_Python_Scikit Learn_Cross Validation - Fatal编程技术网

Python 带Sklearn的组/簇K倍CV

Python 带Sklearn的组/簇K倍CV,python,scikit-learn,cross-validation,Python,Scikit Learn,Cross Validation,我需要对一些模型进行K倍CV,但我需要确保验证(测试)数据集按组和t年数聚集在一起GroupKFold已关闭,但它仍会拆分验证集(请参见第二个折叠) 例如,如果我有一组从2000年到2008年的数据,我想把它分成3组。合适的组合为:验证:2000-2002年,培训:2003-2008年;V:2003-2005,T:2000-2002和2006-2008;和V:2006-2008,T:2000-2005) 在验证集按t年进行聚类的情况下,是否有方法使用K倍CV对数据进行分组和聚类 from skl

我需要对一些模型进行K倍CV,但我需要确保验证(测试)数据集按组和
t
年数聚集在一起
GroupKFold
已关闭,但它仍会拆分验证集(请参见第二个折叠)

例如,如果我有一组从2000年到2008年的数据,我想把它分成3组。合适的组合为:验证:2000-2002年,培训:2003-2008年;V:2003-2005,T:2000-2002和2006-2008;和V:2006-2008,T:2000-2005)

在验证集按
t
年进行聚类的情况下,是否有方法使用K倍CV对数据进行分组和聚类

from sklearn.model_selection import GroupKFold

X = [0.1, 0.2, 2.2, 2.4, 2.3, 4.55, 5.8, 8.8, 9, 10, 0.1, 0.2, 2.2]
y = ["a", "b", "b", "b", "c", "c", "c", "d", "d", "d", "a", "b", "b"]
groups = [1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4]

gkf = GroupKFold(n_splits=2)
for train_index, test_index in gkf.split(X, y, groups=groups):
    print("Train:", train_index, "Validation:",test_index)
输出:

Train: [ 0  1  2  3  4  5 10 11 12] Validation: [6 7 8 9]
Train: [3 4 5 6 7 8 9] Validation: [ 0  1  2 10 11 12]
Train: [ 0  1  2  6  7  8  9 10 11 12] Validation: [3 4 5]
n_splits= 3
train_idx: [ 4  5  6  7  8  9 10 11 12 13 14 15 16 17] test_idx: [0 1 2 3]
train_idx: [ 0  1  2  3 10 11 12 13 14 15 16 17] test_idx: [4 5 6 7 8 9]
train_idx: [0 1 2 3 4 5 6 7 8 9] test_idx: [10 11 12 13 14 15 16 17]
n_splits= 3
train_idx: [ 6  7  8  9 10 11 12] test_idx: [0 1 2 3 4 5]
train_idx: [ 0  1  2 10 11 12] test_idx: [3 4 5 6 7 8 9]
train_idx: [0 1 2 3 4 5] test_idx: [ 6  7  8  9 10 11 12]
预期产出(假设每组2年):


尽管如此,测试和训练子集不是连续的,可以选择更多的年份进行分组。

我希望我正确地理解了您的意思

scikits
model_selection
中的方法可能有助于:

假设将组标签0指定给2000-2002年的所有数据点,将标签1指定给2003-2005年的所有数据点,将标签2指定给2006-2008年的数据点。 然后可以使用以下方法创建训练和测试拆分,其中三个测试拆分是从三个组中的一个组创建的:

from sklearn.model_selection import LeaveOneGroupOut
import numpy as np
groups=[1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,3]
X=np.random.random(len(groups))
y=np.random.randint(0,4,len(groups))

logo = LeaveOneGroupOut()
print("n_splits=", logo.get_n_splits(X,y,groups))
for train_index, test_index in logo.split(X, y, groups):
    print("train_idx:", train_index, "test_idx:", test_index)
输出:

Train: [ 0  1  2  3  4  5 10 11 12] Validation: [6 7 8 9]
Train: [3 4 5 6 7 8 9] Validation: [ 0  1  2 10 11 12]
Train: [ 0  1  2  6  7  8  9 10 11 12] Validation: [3 4 5]
n_splits= 3
train_idx: [ 4  5  6  7  8  9 10 11 12 13 14 15 16 17] test_idx: [0 1 2 3]
train_idx: [ 0  1  2  3 10 11 12 13 14 15 16 17] test_idx: [4 5 6 7 8 9]
train_idx: [0 1 2 3 4 5 6 7 8 9] test_idx: [10 11 12 13 14 15 16 17]
n_splits= 3
train_idx: [ 6  7  8  9 10 11 12] test_idx: [0 1 2 3 4 5]
train_idx: [ 0  1  2 10 11 12] test_idx: [3 4 5 6 7 8 9]
train_idx: [0 1 2 3 4 5] test_idx: [ 6  7  8  9 10 11 12]

编辑 我想我现在终于明白你想要什么了。对不起,我花了这么长时间

我不认为你想要的分割方法已经在sklearn中实现了。但是我们可以很容易地扩展BaseCrossValidator方法

import numpy as np
from sklearn.model_selection import BaseCrossValidator
from sklearn.utils.validation import check_array

class GroupOfGroups(BaseCrossValidator):
    def __init__(self, group_of_groups):
        """
        :param group_of_groups: list with length n_splits. Each entry in the list is a list with group ids from
 set(groups). In each of the n_splits splits, the groups given in the current group_of_groups sublist are used 
for validation.
        """
        self.group_of_groups = group_of_groups

    def get_n_splits(self, X=None, y=None, groups=None):
        return len(self.group_of_groups)

    def _iter_test_masks(self, X=None, y=None, groups=None):
        if groups is None:
            raise ValueError("The 'groups' parameter should not be None.")
        groups=check_array(groups, copy=True, ensure_2d=False, dtype=None)
        for g in self.group_of_groups:
            test_index = np.zeros(len(groups), dtype=np.bool)
            for g_id in g:
                test_index[groups == g_id] = True
            yield test_index
用法很简单。与前面一样,我们定义了
X,y
。此外,我们还定义了一个列表列表(组组列表),其中定义了在哪个测试折叠中应该一起使用哪些组。 因此
g_of_g=[[1,2],[2,3],[3,4]]
意味着第1组和第2组在第一次折叠中用作测试集,而其余的第3组和第4组用于训练。在折叠2中,来自组2和组3的数据用作测试集等

我对“GroupOfGroups”的命名不太满意,所以也许你能找到更好的名字

现在我们可以测试这个交叉验证程序:

X = [0.1, 0.2, 2.2, 2.4, 2.3, 4.55, 5.8, 8.8, 9, 10, 0.1, 0.2, 2.2]
y = ["a", "b", "b", "b", "c", "c", "c", "d", "d", "d", "a", "b", "b"]
groups = [1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4]
g_of_g = [[1,2],[2,3],[3,4]]
gg = GroupOfGroups(g_of_g)
print("n_splits=", gg.get_n_splits(X,y,groups))
for train_index, test_index in gg.split(X, y, groups):
    print("train_idx:", train_index, "test_idx:", test_index)
输出:

Train: [ 0  1  2  3  4  5 10 11 12] Validation: [6 7 8 9]
Train: [3 4 5 6 7 8 9] Validation: [ 0  1  2 10 11 12]
Train: [ 0  1  2  6  7  8  9 10 11 12] Validation: [3 4 5]
n_splits= 3
train_idx: [ 4  5  6  7  8  9 10 11 12 13 14 15 16 17] test_idx: [0 1 2 3]
train_idx: [ 0  1  2  3 10 11 12 13 14 15 16 17] test_idx: [4 5 6 7 8 9]
train_idx: [0 1 2 3 4 5 6 7 8 9] test_idx: [10 11 12 13 14 15 16 17]
n_splits= 3
train_idx: [ 6  7  8  9 10 11 12] test_idx: [0 1 2 3 4 5]
train_idx: [ 0  1  2 10 11 12] test_idx: [3 4 5 6 7 8 9]
train_idx: [0 1 2 3 4 5] test_idx: [ 6  7  8  9 10 11 12]

请记住,我没有包括很多检查,也没有做彻底的测试。因此,请仔细验证这是否适合您。

谢谢!这很接近,但我需要多个集群组,例如1&2或2&3。另一种选择是TimeSeriesSplit,但这基本上就是您所建议的。1和2在第二个训练集中聚集在一起,2和3在第一个训练集中聚集在一起。那么,何时需要在验证集中将1和2聚集在一起?您能提供初始示例的所需输出吗?test_idx仅包括一个组,其中我需要两个(或更多)组。我已经用期望的输出更新了我的问题;不过,简历不需要是连续的。就是这样!非常感谢。我看不出你的
列表与你期望的产出有什么关系,也看不到你期望的产出与你之前提到的2000年到2008年的9年有什么联系。也许是我,但我不太明白输入和输出是如何关联的,你的目标是什么。@Merlin1896在所需的输出中,我选择组1&2、2&3和3&4进行验证。然后我想用剩下的训练,所以第3组和第4组,第1组和第4组,以及第1组和第2组。在您的回答中,您只选择了一个组作为验证集,而我需要两个(或更大的数据集中的更多)。你的想法是对的,我只想选择聚集的组,比如两年。但是为什么索引6在测试集中出现了三次,而在训练集中却从来没有出现过?我猜这是打字错误?如果是,请查看我编辑的答案。