在sklearn中copy = False做什么

时间:2017-11-25 01:34:32

标签: python scikit-learn

在scikitlearn中PCA function的文档中,默认情况下copy参数为True

文件说明了这个论点:
If False, data passed to fit are overwritten and running fit(X).transform(X) will not yield the expected results, use fit_transform(X) instead.

我不确定这是什么意思,因为该函数将如何覆盖输入X?当你调用.fit(X)时,该函数应该只是计算PCA向量并更新PCA对象的内部状态,对吧? 因此,即使您将副本设置为False.fit(X)函数仍应按照文档中的说明返回对象self,那么fit(X).transform(X)是否仍然可以正常工作?

那么当这个参数设置为False时会复制什么?

此外,我何时才想将其设置为False

编辑: 我将fit和transform函数一起分开运行并获得了不同的结果,即使copy参数对于两者都是相同的。

from sklearn.decomposition import PCA
import numpy as np

X = np.arange(20).reshape((5,4))

print("Separate")
XT = X.copy()
pcaT = PCA(n_components=2, copy=True)
print("Original: ", XT)
results = pcaT.fit(XT).transform(XT)
print("New: ", XT)
print("Results: ", results)

print("\nCombined")
XF = X.copy()
pcaF = PCA(n_components=2, copy=True) 
print("Original: ", XF)
results = pcaF.fit_transform(XF)
print("New: ", XF)
print("Results: ", results)

########## Results
Separate
Original:  [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]
 [16 17 18 19]]
New:  [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]
 [16 17 18 19]]
Results:  [[  1.60000000e+01  -2.66453526e-15]
 [  8.00000000e+00  -1.33226763e-15]
 [  0.00000000e+00   0.00000000e+00]
 [ -8.00000000e+00   1.33226763e-15]
 [ -1.60000000e+01   2.66453526e-15]]

Combined
Original:  [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]
 [16 17 18 19]]
New:  [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]
 [16 17 18 19]]
Results:  [[  1.60000000e+01   1.44100598e-15]
 [  8.00000000e+00  -4.80335326e-16]
 [ -0.00000000e+00   0.00000000e+00]
 [ -8.00000000e+00   4.80335326e-16]
 [ -1.60000000e+01   9.60670651e-16]]

1 个答案:

答案 0 :(得分:4)

在您的示例中,copy的值最终会被忽略,如下所述。但是如果你把它设置为False会发生什么:

X = np.arange(20).reshape((5,4)).astype(np.float64)
print(X)
pca = PCA(n_components=2, copy=False).fit(X)
print(X)

这会打印原始X

[[  0.   1.   2.   3.]
 [  4.   5.   6.   7.]
 [  8.   9.  10.  11.]
 [ 12.  13.  14.  15.]
 [ 16.  17.  18.  19.]]

然后显示X被fit方法突变。

[[-8. -8. -8. -8.]
 [-4. -4. -4. -4.]
 [ 0.  0.  0.  0.]
 [ 4.  4.  4.  4.]
 [ 8.  8.  8.  8.]]

罪魁祸首是this lineX -= self.mean_,其中augmented assignment mutates the array

如果设置copy = True,这是默认值,则X不会发生变异。

即使copy = False

,有时也会进行复制

为什么copy没有对您的示例产生影响? PCA.fit方法对copy的值唯一做的就是将它传递给实用函数check_array,它被调用以确保数据矩阵的数据类型为float32或float64。如果数据类型不是其中之一,则会发生类型转换,并且无论如何都会创建副本(在您的示例中,存在从int到float的转换)。这就是为什么在我上面的例子中我将X作为一个浮点数组。

fit().transform()fit_transform()

之间的微小差异

您还问过为什么fit(X).transform(X)fit_transform(X)会返回略有不同的结果。这与copy参数无关。差异在于双精度算术的误差范围内。它来自以下内容:

  • fit执行SVD为X = U @ S @ V.T(其中@表示矩阵乘法)并将V存储在components_属性中。
  • transform将数据乘以V
  • fit_transform执行与fit相同的SVD,然后返回U @ S

数学上,U @ SX @ V相同,因为V是正交矩阵。但是浮点运算的误差导致了微小的差异。

fit_transform执行U @ S代替X @ V是有道理的;这是一个更简单,更准确的乘法,因为S是对角线。 fit不相同的原因是只存储了V,并且在任何情况下它都不知道它获得的参数与模型到达的{{1}相同}。