如何将文档拆分为训练集和测试集?

时间:2017-02-26 17:08:29

标签: machine-learning scikit-learn text-classification

我正在尝试建立一个分类模型。我在本地文件夹中有1000个文本文档。我想将它们分成训练集和测试集,分数比为70:30(70->训练和30->测试)这样做的更好的方法是什么?我正在使用python。

注意: - 为了更好地理解,请解释为什么应该遵循该方法。

谢谢

更新: - 经过几次投票回到这个问题。虽然我得到了近乎完美的答案,但我还想简要回答一下这个问题。

我想以编程方式分割训练集和测试集。首先要读取本地目录中的文件。其次,构建这些文件的列表并对其进行随机播放。第三,将它们分成训练集和测试集。

作为python的初学者和新手,我尝试了一些方法,使用内置的python关键字和函数只会失败。最后我有了接近它的想法。此外,交叉验证是建筑物一般分类模型的一个很好的选择。谢谢你的回答。

4 个答案:

答案 0 :(得分:6)

不确定完全你所追求的是什么,所以我会尽量全面。将有几个步骤:

  1. 获取文件列表
  2. 随机化文件
  3. 将文件拆分为培训和测试集
  4. 做事
  5. 1。获取文件列表

    我们假设您的文件都具有扩展名.data,并且它们都在文件夹/ml/data/中。我们想要做的是获取所有这些文件的列表。只需使用os模块即可完成此操作。我假设你没有子目录;如果有的话,这会改变。

    import os
    
    def get_file_list_from_dir(datadir):
        all_files = os.listdir(os.path.abspath(datadir))
        data_files = list(filter(lambda file: file.endswith('.data'), all_files))
        return data_files
    

    因此,如果我们要调用get_file_list_from_dir('/ml/data'),我们将返回该目录中所有.data个文件的列表(在shell中等效于glob /ml/data/*.data)。

    2。随机化文件

    我们不希望采样是可预测的,因为这被认为是训练ML分类器的一种不好的方法。

    from random import shuffle
    
    def randomize_files(file_list):
        shuffle(file_list)
    

    请注意random.shuffle执行就地改组,因此会修改现有列表。 (当然这个函数相当愚蠢,因为你只需要调用shuffle而不是randomize_files;你可以把它写成另一个函数来使它更有意义。)

    3。将文件拆分为培训和测试集

    我假设70:30比率而不是任何特定数量的文件。所以:

    from math import floor
    
    def get_training_and_testing_sets(file_list):
        split = 0.7
        split_index = floor(len(file_list) * split)
        training = file_list[:split_index]
        testing = file_list[split_index:]
        return training, testing
    

    4。做那件事

    这是您打开每个文件并进行培训和测试的步骤。我会留给你的!

    交叉验证

    出于好奇,您是否考虑过使用cross-validation?这是一种分割数据的方法,以便您使用每个文档进行培训和测试。您可以自定义每个“折叠”中用于培训的文档数量。如果你愿意,我可以更深入地了解这一点,但如果你不想这样做,我就不会这样做。

    编辑:好的,既然你要求我会再详细解释一下。

    所以我们有1000个文档的数据集。交叉验证的想法是,您可以使用所有进行培训和测试 - 只是不能立即进行。我们将数据集拆分为我们称之为“折叠”的数据集。折叠次数决定了在任何给定时间点训练和测试集的大小。

    假设我们想要一个10倍的交叉验证系统。这意味着训练和测试算法将运行十次。第一次将训练文件1-100并测试101-1000。第二轮将在101-200训练并在1-100和201-1000进行测试。

    如果我们做了一个40倍的CV系统,第一次折叠将在文件1-25上训练并在26-1000上进行测试,第二次折叠将在26-40上训练并在1-25和51上进行测试-1000,等等。

    为了实现这样的系统,我们仍然需要从上面做步骤(1)和(2),但步骤(3)会有所不同。我们可以将函数转换为generator - 一个我们可以像列表一样迭代的函数,而不是分成两组(一组用于训练,一组用于测试)。

    def cross_validate(data_files, folds):
        if len(data_files) % folds != 0:
            raise ValueError(
                "invalid number of folds ({}) for the number of "
                "documents ({})".format(folds, len(data_files))
            )
        fold_size = len(data_files) // folds
        for split_index in range(0, len(data_files), fold_size):
            training = data_files[split_index:split_index + fold_size]
            testing = data_files[:split_index] + data_files[split_index + fold_size:]
            yield training, testing
    

    最后的yield关键字是使其成为生成器的原因。要使用它,你会像这样使用它:

    def ml_function(datadir, num_folds):
        data_files = get_file_list_from_dir(datadir)
        randomize_files(data_files)
        for train_set, test_set in cross_validate(data_files, num_folds):
            do_ml_training(train_set)
            do_ml_testing(test_set)
    

    同样,由您来实现ML系统的实际功能。

    作为免责声明,我无论如何都不是专家,哈哈。但是,如果您对我在这里写的任何内容有任何疑问,请与我联系!

答案 1 :(得分:3)

如果你使用numpy,这很简单,首先加载文件并使它们成为一个numpy数组,然后:

import numpy as np

docs = np.array([
    'one', 'two', 'three', 'four', 'five',
    'six', 'seven', 'eight', 'nine', 'ten',
    ])

idx = np.hstack((np.ones(7), np.zeros(3))) # generate indices
np.random.shuffle(idx) # shuffle to make training data and test data random

train = docs[idx == 1]
test = docs[idx == 0]

print(train)
print(test)

结果:

['one' 'two' 'three' 'six' 'eight' 'nine' 'ten']
['four' 'five' 'seven']

答案 2 :(得分:1)

您可以使用sklearn提供的train_test_split方法。请参阅此处的文档:

http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html

答案 3 :(得分:0)

只需使用os.listdir()列出文件名。使用collections.shuffle()随机播放列表,然后training_files = filenames[:700]testing_files = filenames[700:]