使用 train_test_split 拆分数据时与之后加载 csv 文件的精度不同
Posted
技术标签:
【中文标题】使用 train_test_split 拆分数据时与之后加载 csv 文件的精度不同【英文标题】:Different accuracy when splitting data with train_test_split than loading csv file afterwards 【发布时间】:2021-01-28 18:55:28 【问题描述】:我已经建立了一个模型来预测客户是企业客户还是私人客户。在训练模型后,我预测了我没有用于训练的 1000 个数据集的类别。此预测将保存在 csv 文件中。 现在我有两种不同的行为:
-
在程序中拆分样本数据
当我使用train, sample = train_test_split(train, test_size=1000, random_state=seed)
创建样本时,预测会在训练期间获得相同的准确度(与验证值相同)。
-
提前拆分样本数据,然后加载
但是当我在学习之前手动拆分数据时,通过获取原始 csv 文件的 1000 个数据集并将其复制到一个新的示例 csv 文件中,我在学习后进行预测之前正在加载该文件,我得到了一个更糟糕的结果(例如 76 % 而不是 90%)。 这种行为在我看来没有意义,因为原始数据(用于训练的 csv 文件)也被提前打乱了,因此我应该得到相同的结果。 以下是上述案例区分的相关代码:
1。在程序中拆分样本数据
拆分
def getPreProcessedDatasetsWithSamples(filepath, batch_size):
path = filepath
data = __getPreprocessedDataFromPath(path)
train, test = train_test_split(data, test_size=0.2, random_state=42)
train, val = train_test_split(train, test_size=0.2, random_state=42)
train, sample = train_test_split(train, test_size=1000, random_state=seed)
train_ds = __df_to_dataset(train, shuffle=False, batch_size=batch_size)
val_ds = __df_to_dataset(val, shuffle=False, batch_size=batch_size)
test_ds = __df_to_dataset(test, shuffle=False, batch_size=batch_size)
sample_ds = __df_to_dataset(sample, shuffle=False, batch_size=batch_size)
return (train_ds, val_ds, test_ds, sample, sample_ds)
使用样本进行预测,sample_ds
def savePredictionWithSampleToFileKeras(model, outputName, sample, sample_ds):
predictions = model.predict(sample_ds)
loss, accuracy = model.evaluate(sample_ds)
print("Accuracy of sample", accuracy)
sample['prediction'] = predictions
sample.to_csv("./saved_samples/" + outputName + ".csv")
样本准确率:90%
2。提前拆分样本数据,然后加载
通过加载 csv 文件进行预测
def savePredictionToFileKeras(model, sampleFilePath, outputName, batch_size):
sample_ds = preprocessing.getPreProcessedSampleDataSets(sampleFilePath, batch_size)
sample = preprocessing.getPreProcessedSampleDataFrames(sampleFilePath)
predictions = model.predict(sample_ds)
loss, accuracy = model.evaluate(sample_ds)
print("Accuracy of sample", accuracy)
sample['prediction'] = predictions
sample.to_csv("./saved_samples/" + outputName + ".csv")
样本准确率:77%
编辑
观察:当我将整个数据加载为样本数据时,我得到的值与预期的验证值相同(大约 90%),但是当我只是随机化同一个文件的行顺序时,我得到一个值82%。据我了解,准确性应该是相同的,因为文件是相等的。
一些附加信息: 我已将实现从顺序更改为功能 API。我在预处理中使用嵌入(我也尝试过 One-Hot-Encoding 没有成功)。
【问题讨论】:
你尝试过 K 折交叉验证吗? 还没有,因为我不认为交叉验证可以解释不同的行为。此外,在链接 random_state 以及测试集和训练集的分布时,结果没有差异。所以我认为简历不会帮助我找到问题的答案。 【参考方案1】:上述两种方法都不能预测正确的准确性。仅当您的数据平衡时,准确性才是很好的衡量标准。对于不平衡的数据,它不是很好的衡量标准,它不会总是正确的。每次更改精度都会发生变化。 您应该首先使用 K 折交叉验证,以便所有数据点都将用于训练模型。如果您的数据集不平衡,您可以尝试不同的平衡技术,例如对训练数据进行过采样或欠采样并验证模型。
【讨论】:
感谢您的回答!你怎么理解不平衡?例如,我的数据包含 60% 的 A 类和 40% 的 B 类,您认为这是不平衡的吗? 问题是我无法理解为什么只有手动加载数据的准确性发生变化(以更糟糕的方式),而不是train_test_split
的数据?例如,每次我在训练/验证/测试集上使用不同的分布时,我都会得到相同的结果,例如90%。所以这就是为什么我认为不需要使用 CV 的原因,因为准确度总是一样的,不管我使用哪种训练/验证/测试分布。我试图通过手动加载数据来理解为什么不是这种情况。【参考方案2】:
最后我发现了问题:我正在使用 Tokenizer 预处理 NAME 和 STREET 列,我将每个单词转换为一个值,该值指示单词出现的频率。在我使用train_test_split
的情况下,我使用所有数据的相同整体单词来转换单词,但是当我之后加载示例数据集时,我只使用示例数据集中出现的单词。例如,“family”这个词可能是总体上最常用的词,但在样本数据集中只是第三个,因此编码将是完全错误的。
在对所有数据使用相同的分词器实例后,我对所有数据都获得了相同的高精度。
【讨论】:
以上是关于使用 train_test_split 拆分数据时与之后加载 csv 文件的精度不同的主要内容,如果未能解决你的问题,请参考以下文章
何时使用 scikit learn 的 train_test_split
我们如何将显式测试数据和训练数据提供给 SVM,而不是使用 train_test_split 函数?
python - 如何在没有python中的train_test_split函数的情况下将数据中的固定行数拆分为Xtest、Xtrain、Ytrain和Ytest