2016-08-05 64 views
0

我正在训练做python的MNIST的PCA重建,并将它们与我在maltab中的(旧)重建进行比较,我偶然发现我的重建不同意。经过一番调试,我决定打印每个主要组件的独特特征,以显示它们是否相同,并且我发现我的惊讶发现它们是而不是相同。我打印所有组件的总和,并得到不同的数字。我做了MATLAB中的以下内容:为什么Scipy和MATLAB的主成分值不一致?

[coeff, ~, ~, ~, ~, mu] = pca(X_train); 
U = coeff(:,1:K) 
U_fingerprint = sum(U(:)) 
%print 31.0244 

和在Python/SciPy的:

pca = pca.fit(X_train) 
U = pca.components_ 
print 'U_fingerprint', np.sum(U) 
# prints 12.814 

为什么在TWI PCA不是计算相同的值?


我所有的尝试和解决这个问题:

我发现,这是因为当我重建我的MNIST图像的方式,蟒蛇重建那里受到了很多非常非常接近他们的原始图像。我在Python中遇到了0.0221556788645的错误,而在MATLAB中我得到了尺寸为29.07578的错误。为了找出差异来自哪里,我决定手指打印数据集(也许它们是以不同方式归一化的)。所以,我有两个独立的副本MNIST数据集(即是通过把我的255标准化),并得到了指纹(汇总数据集中的所有号码):

print np.sum(x_train) # from keras 
print np.sum(X_train)+np.sum(X_cv) # from TensorFlow 
6.14628e+06 
6146269.1585420668 

这是(基本上)相同的(一个来自副本张量流MNIST,另一个来自Keras MNIST,注意MNIST训练数据集有大约1000个训练集,所以你需要追加缺少的训练集)。令我惊讶的是,我的MATLAB数据有相同指纹:

data_fingerprint = sum(X_train(:)) 
% prints data_fingerprint = 6.1463e+06 

意味着数据集正是相同。好,所以规范化数据不是问题。

在我的MATLAB脚本其实我手工计算重建如下:

U = coeff(:,1:K) 
X_tilde_train = (U * U' * X_train); 
train_error_PCA = (1/N_train)*norm(X_tilde_train - X_train ,'fro')^2 
%train_error_PCA = 29.0759 

,所以我想是因为我用的是接口蟒蛇可能是问题了用于计算重建为:

pca = PCA(n_components=k) 
pca = pca.fit(X_train) 
X_pca = pca.transform(X_train) # M_train x K 
#print 'X_pca' , X_pca.shape 
X_reconstruct = pca.inverse_transform(X_pca) 
print 'tensorflow error: ',(1.0/X_train.shape[0])*LA.norm(X_reconstruct_tf - X_train) 
print 'keras error: ',(1.0/x_train.shape[0])*LA.norm(X_reconstruct_keras - x_train) 
#tensorflow error: 0.0221556788645 
#keras error: 0.0212030354818 

这导致不同的误差值0.022 vs 29.07,令人震惊的差异!

因此,我决定在我的Python脚本代码,精确重建式:

pca = PCA(n_components=k) 
pca = pca.fit(X_train) 
U = pca.components_ 
print 'U_fingerprint', np.sum(U) 
X_my_reconstruct = np.dot( U.T , np.dot(U, X_train.T)) 
print 'U error: ',(1.0/X_train.shape[0])*LA.norm(X_reconstruct_tf - X_train) 
# U error: 0.0221556788645 

想不到,它通过使用该接口具有相同的错误作为我MNIST误差计算。因此,得出结论我不认为我有我的PCA的误解。

所有这些都导致我检查主要组件的实际位置以及令我惊讶的scipy和MATLAB的PCA值有不同的指纹。

有谁知道为什么或什么事情发生?


沃伦建议,在PCA分量(特征向量)可能有不同的标志。在幅度将所有组件做一个指纹后只有我发现它们具有相同的指纹:

[coeff, ~, ~, ~, ~, mu] = pca(X_train); 
K=12; 
U = coeff(:,1:K) 
U_fingerprint = sumabs(U(:)) 
% U_fingerprint = 190.8430 

和蟒蛇:

k=12 
pca = PCA(n_components=k) 
pca = pca.fit(X_train) 
print 'U_fingerprint', np.sum(np.absolute(U)) 
# U_fingerprint 190.843 

这意味着差必须因(pca)U矢量的不同符号。我觉得这很令人惊讶,我认为这应该会有很大的变化,我甚至没有考虑到它会产生很大的变化。我猜我错了?

+0

两个版本有多少个组件会返回?比较文件,这可能是一个可能解释观察到的行为的差异点。 – rubenvb

+0

@rubenvb他们都是12(显然是相同的,否则这将是愚蠢的错误,我将在明天早上提供github代码以供人们判断脚本)。 –

+0

在MATLAB变量是列市长和在python行市长。确保你没有计算转置矩阵中的PCA。 –

回答

2

我不知道这是否是问题,但肯定可以。主分量向量就像特征向量:如果将向量乘以-1,它仍然是一个有效的PCA向量。由matlab计算的一些矢量可能与python中计算的矢量的符号不同。这将导致非常不同的总和。

例如,MATLAB文档有这个例子:

coeff = pca(ingredients) 

coeff = 

    -0.0678 -0.6460 0.5673 0.5062 
    -0.6785 -0.0200 -0.5440 0.4933 
    0.0290 0.7553 0.4036 0.5156 
    0.7309 -0.1085 -0.4684 0.4844 

我有自己的python PCA代码,并用相同的输入作为在MATLAB中,它产生此系数数组:

[[ 0.0678 0.646 -0.5673 0.5062] 
[ 0.6785 0.02 0.544 0.4933] 
[-0.029 -0.7553 -0.4036 0.5156] 
[-0.7309 0.1085 0.4684 0.4844]] 

因此,不要简单地对系数数组进行求和,而应该对系数的绝对值求和。或者,在求和之前确保所有矢量具有相同的符号约定。例如,可以通过将每列乘以该列中第一个元素的符号(假设它们都不为零)来实现。

+0

好像两个主要组件矩阵(特征向量)具有相同的指纹,现在我按照您的建议计算了绝对值的新指纹。这是否意味着重建计算错误,因为特征向量的符号不一致? –

+0

这个标志不应该有所作为,因为重建是通过X_reconstruct = U * U.T * X来完成的,它可以消除符号。 –

+1

如果仔细查看我的代码,可以注意到我计算的是规范2的损失,但是然后将它平方根(或者我猜测更精确地不是平方),另一个计算平方误差,但是我平方误差。其中考虑到了差异。感谢您的帮助! :d –

相关问题