【问题标题】:PCA on MNIST works but validation data performs really badMNIST 上的 PCA 有效,但验证数据的表现非常糟糕
【发布时间】:2020-08-09 19:48:34
【问题描述】:

我在 MNIST 上应用了 PCA,降维为 32。然后,为了测试它,我创建了一个简单的分类网络。训练准确率不错:96%,但另一方面,测试准确率是2%

那怎么了?

import tensorflow as tf
from tensorflow.keras.datasets import mnist
import tensorflow.keras.layers as layers
from tensorflow.keras.models import Sequential
import numpy as np

(x,y),(x2,y2) = mnist.load_data()

y = tf.keras.utils.to_categorical(y)  
y2 = tf.keras.utils.to_categorical(y2)  

def pca(x):
    x = np.reshape(x, (x.shape[0], 784)).astype("float32") / 255.
    mean = x.mean(axis=1)
    #print(mean)
    #print(mean[:,None])
    x -= mean[:,None]
    
    s, u, v = tf.linalg.svd(x)
    s = tf.linalg.diag(s)
    
    k = 32 # DIM_REDUCED
    pca = tf.matmul(u[:,0:k], s[0:k,0:k])
    
    #print(pca)
    #print(pca.shape)
    return pca

x = pca(x)
x2 = pca(x2)

## BUILD A SUPER SIMPLE CLASSIFIC. NET
model = Sequential()
model.add(layers.Dense(32, activation="relu", input_shape=(32,)))
model.add(layers.Dense(16, activation="relu"))
model.add(layers.Dense(10, activation="softmax"))

model.compile(loss = "categorical_crossentropy", optimizer = "adam", metrics = ["acc"])

model.fit(x,y, epochs = 5, verbose = 1, batch_size = 64, validation_data = (x2,y2))

输出

Epoch 5/5
60000/60000 [==============================] - 1s 23us/sample - loss: 0.1278 - acc: 0.9626 - val_loss: 11.0141 - val_acc: 0.0202

【问题讨论】:

    标签: python tensorflow machine-learning keras deep-learning


    【解决方案1】:

    首先,您为每组应用两个不同的“pca”。 train的特征向量和特征值可以与测试集不同。

    其次,您正在使用 SVD 获取主成分,但该成分不是您想要的结果。像投影矩阵一样使用主轴来获得更好/压缩的数据表示。

    import tensorflow as tf
    from tensorflow.keras.datasets import mnist
    import tensorflow.keras.layers as layers
    from tensorflow.keras.models import Sequential
    import numpy as np
    
    (x,y),(x2,y2) = mnist.load_data()
    
    y = tf.keras.utils.to_categorical(y)  
    y2 = tf.keras.utils.to_categorical(y2)  
    
    def pca(x):
        x = np.reshape(x, (x.shape[0], 784)).astype("float32") / 255.
        mean = x.mean(axis=0)
        #print(mean)
        #print(mean[:,None])
        x -= mean[None, :]
        
        s, u, v = tf.linalg.svd(x)
        s = tf.linalg.diag(s)
        
        k = 32 # DIM_REDUCED
        projM = v[:, 0:k] #tf.matmul(u[:,0:k], s[0:k,0:k])  
        return mean, projM
    
    def apply_pca(mean, projM, x):
        x = np.reshape(x, (x.shape[0], 784)).astype("float32") / 255.
        #print(mean)
        #print(mean[:,None])
        x -= mean[None, :]
    
        return tf.matmul(x, projM)
       
    mean, projM = pca(x) 
    
    x = apply_pca(mean, projM, x) 
    x2 = apply_pca(mean, projM, x2) 
    
    ## BUILD A SUPER SIMPLE CLASSIFIC. NET
    model = Sequential()
    model.add(layers.Dense(32, activation="relu", input_shape=(32,)))
    model.add(layers.Dense(16, activation="relu"))
    model.add(layers.Dense(10, activation="softmax"))
    
    model.compile(loss = "categorical_crossentropy", optimizer = "adam", metrics = ["acc"])
    
    model.fit(x,y, epochs = 5, verbose = 1, batch_size = 64, validation_data = (x2,y2))
    

    【讨论】:

    • 您的代码出现此错误:InvalidArgumentError: In[0] mismatch In[1] shape: 28 vs. 60000: [60000,28,28] [60000,32] 0 0 [Op:BatchMatMulV2] name: MatMul/
    • 行内原因:x = tf.matmul(x, projM)
    • 谢谢!我仍然想知道,当我们为变量分配新值时,为什么要将参数mean 传递给函数apply_pca?我想我们不需要通过它。
    • 我的错,我还看到您对每个样本进行平均。在任何情况下,您都应该对每个维度进行平均。在 MNIST 的情况下,您的平均向量应该是 28x28 (784)。我进行了一些更改以使其适合您。您在训练中执行的所有管道在测试中必须始终相同:相同的均值、相同的投影等。因此,我们使用向量 V 而不是 US。
    猜你喜欢
    • 1970-01-01
    • 2017-01-25
    • 2021-03-11
    • 1970-01-01
    • 2020-08-12
    • 2012-05-06
    • 2010-09-16
    • 1970-01-01
    • 2016-07-14
    相关资源
    最近更新 更多