当对数据进行缩放时,为什么训练数据集使用“fit”和“transform”,而测试数据集只使用“transform”?

40

当缩放数据时,为什么训练数据集使用“fit”和“transform”,而测试数据集只使用“transform”?

SAMPLE_COUNT = 5000
TEST_COUNT = 20000
seed(0)
sample = list()
test_sample = list()
for index, line in enumerate(open('covtype.data','rb')):
    if index < SAMPLE_COUNT:
        sample.append(line)
    else:
        r = randint(0,index)
        if r < SAMPLE_COUNT:
            sample[r] = line
        else:
            k = randint(0,index)
            if k < TEST_COUNT:
                if len(test_sample) < TEST_COUNT:
                    test_sample.append(line)
                else:
                    test_sample[k] = line
from sklearn.preprocessing import StandardScaler
for n, line in enumerate(sample):
sample[n] = map(float, line.strip().split(','))
y = np.array(sample)[:,-1]
scaling = StandardScaler()

X = scaling.fit_transform(np.array(sample)[:,:-1]) ##here use fit and transform

for n,line in enumerate(test_sample):
test_sample[n] = map(float,line.strip().split(','))
yt = np.array(test_sample)[:,-1]

Xt = scaling.transform(np.array(test_sample)[:,:-1])##why here only use transform

正如注释所说,为什么Xt只使用transform而不是fit?

作为注释所说,为什么Xt只使用transform而不是fit?

(更通俗易懂的翻译)
8个回答

45

我们在训练数据上使用 fit_transform() 方法,以便学习缩放参数并同时对训练数据进行缩放。

我们只需要在测试数据上使用 transform() 方法,因为我们使用在训练数据上学习到的缩放参数来对测试数据进行缩放。

这是一种标准的缩放流程。您总是要在训练数据上学习缩放参数,然后将它们应用于测试数据。这里有一篇文章非常好地解释了这个过程:https://sebastianraschka.com/faq/docs/scale-training-test.html


在R语言中,scale函数用于转换未分割的数据集,然后将数据集分为训练集和测试集。如果Python的“transform”按照您所说的方式执行,则结果可能不同。 - littlely
即使阅读了Sebastian Raschka的文章后,我仍不清楚为什么我们不应该在测试集上拟合比例估计器。对于监督模型(如回归器或分类器),在测试集上进行拟合会导致过度拟合数据。然而,我不明白使用缩放时为什么会出现这种现象。如果训练集和测试集中的数据遵循相同的分布,则认为在总数据上拟合比例估计器应使它更准确(更低偏差)并且更精确(方差更小),因为它会使用比训练集更多的数据。 - Tanguy

18
我们有两个数据集:训练数据集和测试数据集。假设我们只有2个特征:“x1”和“x2”。
现在考虑一个非常假设性的例子:
训练数据中的一个样本具有值:“x1”=100和“x2”=200. 当进行缩放时,“x1”获得0.1的值,“x2”也获得0.1的值。对于此样本,响应变量值为100。这些计算是根据训练数据的平均值和标准差而计算的。
测试数据中的一个样本具有值:“x1”=50和“x2”=100。根据测试数据值进行缩放时,“x1”=0.1,“x2”=0.1。这意味着我们的函数将对该样本预测响应变量值为100。但这是错误的。它不应该是100。它应该预测另外一些东西,因为上述2个样本的特征非缩放值是不同的,因此指向不同的响应值。只有当我们根据训练数据进行缩放时,才能知道正确的预测值,因为那些是我们的线性回归函数所学习的值。
我尝试在下面解释这个逻辑的直觉:在应用线性回归并拟合线性回归函数之前,我们决定对训练数据集中的特征进行缩放。当我们缩放训练数据集的特征时,所有“x1”特征都会根据其“x1”特征值相对于不同样本的均值和标准差进行调整。对于“x2”特征也是同样的情况。
这意味着每个特征已基于仅训练数据而转换为一个新数值。就像每个特征都被赋予了一个相对位置。相对于仅针对训练数据的平均值和标准差。因此,每个样本的新“x1”和“x2”值仅取决于训练数据的平均值和标准差。
现在,在拟合线性回归函数时,它会基于训练数据集的缩放特征来学习参数(即,学习预测响应值)。这意味着它正在学习基于训练数据集中不同样本的“x1”和“x2”的特定均值和标准差进行预测。因此,预测值的值取决于:
*学习到的参数。反过来又取决于 *训练数据的特征值(已经被缩放)。由于缩放,训练数据的特征取决于 * 训练数据的平均值和标准差。如果我们现在将standardscaler()应用于测试数据,测试数据的'x1'和'x2'将具有自己的平均值和标准差。这意味着两个特征的新值将只相对于测试数据中的数据,并且与训练数据没有任何联系。这就像它们被减去和除以随机值一样,现在得到了新的值,这些值不传达它们与训练数据的关系。

1
一开始有点难以理解,但经过几次重复阅读后开始有些意义了,所以感谢您的耐心解释 :-) - ChandanJha
有感觉,写得非常好...谢谢啊。 - AbtabM

7
任何对数据的处理都必须使用训练数据生成的参数进行。 fit() 方法创建了一个模型,从训练样本中提取各种参数以便后续进行必要的转换。而transform()则实际执行对数据的转换并返回标准化或缩放后的形式。fit_transform()只是执行fit()transform()操作的一种更快的方法。
重要的是,当你将数据集分成训练集和测试集时,你试图模拟真实世界应用场景。在实际情况下,你只有训练数据,并根据此开发出相应的模型,然后对类似数据的未知实例进行预测。
如果你使用fit_transform()转换整个数据集,然后再将其拆分为训练集和测试集,那么你违反了这种模拟方法,并且会按照未知示例的方法进行转换。这将不可避免地导致一种乐观的模型,因为你已经通过未知样本的指标来部分准备好了你的模型。
如果你将数据拆分为训练集和测试集,并使用fit_transform()对两者均进行转换,则也会造成错误,因为第一次对训练数据的转换仅使用训练集的指标,而第二次则仅使用测试集的指标。
正确的方法是仅使用训练数据训练任何转换器,并对测试数据进行转换。只有这样,你才能确保你得到的模型代表了一个真实世界的解决方案。
因此,无论你采用fit(train)然后transform(train)transform(test)的方式,还是fit_transform(train)然后transform(test)的方式,都没有关系。

1

fit()和transform()是用于处理数据集中缺失值的两种方法。可以通过计算数据的平均值或中位数来填充缺失值,并使用这些平均值或中位数填充空白处。 fit()用于计算平均值或中位数。 transform()用于使用计算出的平均值或中位数填充缺失值。 fit_tranform()将上述2个任务一次性执行。 对于训练数据,使用fit_transform()进行上述操作。当涉及到验证集时,只需要使用transform(),因为您不希望在处理验证集中的缺失值时更改处理方式,否则可能会使模型受到惊吓!因此,它可能无法按预期执行。


1
有两种方法: 第一种方法是使用fit和transform来缩放训练数据,只需转换测试数据 第二种方法是对整个数据集进行fit和transform:训练+测试
如果考虑模型在上线后如何处理缩放问题:当新数据到达时,新数据将像你的回测中看不见的测试数据一样被处理。
在第一种情况下,新数据只会被缩放转换,而你的模型回测缩放值保持不变。
但是在第二种情况下,当新数据到来时,你需要对整个数据集进行fit和transform,这意味着回测的缩放值将不再相同,然后你需要重新训练模型。如果这个任务可以快速完成,那么我想这是可以接受的,但第一种情况需要更少的工作...
如果训练和测试之间的缩放存在很大差异,则可能数据是非平稳的,ML可能不是一个好主意。

1

fit() 用于计算变换所需的参数,transform() 用于将数据缩放以转换为模型的标准格式。

fit_transform() 是两者的组合,可以更有效地完成上述工作。

由于 fit_transform() 已经计算和转换了训练数据,因此只剩下测试数据的转换。由于已经计算并存储了变换所需的参数,因此只需要使用 transform() 而不是 fit_transform() 来进行测试数据的转换。


0

fit_transform() - 学习缩放参数(训练数据)
transform() - 在这里应用学习到的缩放方法(测试数据)

ss = StandardScaler()
X_train = ss.fit_transform(X_train) #here we need to feed this to the model to learn so it will learn the parameter of scaling
X_test = ss.transform(X_test) #It will use the learn parameter to transform

0

我们使用fit()fit_transform()来学习(训练模型)训练数据集。 transform()可以用于已经训练好的模型对测试数据集进行操作。


我不是很清楚它们的机制是什么?我还看了一些模型,例如`h_class = SVC(kernel='rbf',C=1.0,gamma=0.7,random_state=101)`, h_class.fit(X_i, y_i), print h_class.support_,但为什么不这样写呢:a = h_class.fit(X_i, y_i), print a.support_ - littlely
fit() 方法不会创建(或返回)任何新对象。因此,像您所做的那样将其分配给 a 是没有用的。 - Vivek Kumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接