在训练测试拆分之前或之后处理

Posted

技术标签:

【中文标题】在训练测试拆分之前或之后处理【英文标题】:processing before or after train test split 【发布时间】:2020-01-01 17:40:06 【问题描述】:

我正在使用这篇优秀的文章来学习机器学习。

https://stackabuse.com/python-for-nlp-multi-label-text-classification-with-keras/

作者将X和y数据拆分后进行了token化。

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.20, random_state=42
)

tokenizer = Tokenizer(num_words=5000)
tokenizer.fit_on_texts(X_train)

X_train = tokenizer.texts_to_sequences(X_train)
X_test = tokenizer.texts_to_sequences(X_test)

vocab_size = len(tokenizer.word_index) + 1

maxlen = 200

X_train = pad_sequences(X_train, padding="post", maxlen=maxlen)
X_test = pad_sequences(X_test, padding="post", maxlen=maxlen)

如果我在使用 train_test_split 类之前对其进行标记,我可以节省几行代码。

tokenizer = Tokenizer(num_words=5000)
tokenizer.fit_on_texts(X)

X_t = tokenizer.texts_to_sequences(X)
vocab_size = len(tokenizer.word_index) + 1
maxlen = 200

X = pad_sequences(X_t, padding="post", maxlen=maxlen)

我只是想确认我的方法是正确的,我不希望脚本后面有任何意外。

【问题讨论】:

不是编程问题,因此这里可以说是题外话;更适合Cross Validated ML 预处理的简单黄金法则是在模型拟合的整个流程中将您的测试数据视为不可用。请参阅here 的讨论(尽管上下文略有不同)。 【参考方案1】:

这两种方法都可以在实践中发挥作用。但是在训练集上拟合标记器并将其应用于训练集和测试集比拟合整个数据集要好。实际上,使用第一种方法,您正在模仿这样一个事实,即在部署模型后的某个时间点会出现模型看不见的单词。因此,您的模型评估将更接近生产环境中发生的情况。

【讨论】:

【参考方案2】:

为了补充 Simons 的帖子,我想说在拆分之前甚至禁止标记化。

该算法将使用来自标记器的数据进行学习,这严格用于测试算法。这是训练集和测试集之间的主要方法。

【讨论】:

【参考方案3】:

同意@desertnaut 的评论,即该问题更适合“Cross Validated”,您将在那里得到更好的回复。不过我还是想说一下。

TL;DR:不要这样做,交叉污染你的训练和测试集通常不是一个好主意。这样做在统计上是不正确的。

Tokenizer.fit_to_texts(dictionary) 进行单词索引,即它将您的任何单词序列转换为数字(向量表示),因此训练集和测试集之间的词汇差异可能不是 null set,即如果仅使用训练数据,则Tokenizer 对象构建的单词索引器中不存在test 中的某些单词。如果您只在训练集上训练您的分词器,这可能会导致某些测试集生成不同的向量。

由于学习问题中的测试集应该是隐藏的,因此在模型的任何训练过程中使用它在统计上都是不正确的。

【讨论】:

以上是关于在训练测试拆分之前或之后处理的主要内容,如果未能解决你的问题,请参考以下文章

机器学习项目:在探索性数据分析之前或之后拆分训练/测试集?

特征选择应该在训练测试拆分之前还是之后完成?

训练/测试拆分之前或之后的欠采样

在生成文档术语矩阵之前或之后拆分为测试和训练集?

Scikit-Learn One-hot-encode 在训练/测试拆分之前或之后

在训练之前执行图形切割或作为基于像素的分类的后处理