12

我试图实现ZCA 美白并找到了一些文章来做,但它们有点令人困惑.. 有人可以为我发光吗?

任何提示或帮助表示赞赏!

这是我读过的文章:

http://courses.media.mit.edu/2010fall/mas622j/whiten.pdf http://bbabenko.tumblr.com/post/86756017649/learning-low-level-vision-feautres-in-10-lines-of

我尝试了几件事,但其中大多数我不明白,我在某个步骤被锁定了。现在我有这个作为重新开始的基础:

dtype = np.float32
data = np.loadtxt("../inputData/train.csv", dtype=dtype, delimiter=',', skiprows=1)
img = ((data[1,1:]).reshape((28,28)).astype('uint8')*255)
4

5 回答 5

16

这是一个用于生成 ZCA 白化矩阵的 python 函数:

def zca_whitening_matrix(X):
    """
    Function to compute ZCA whitening matrix (aka Mahalanobis whitening).
    INPUT:  X: [M x N] matrix.
        Rows: Variables
        Columns: Observations
    OUTPUT: ZCAMatrix: [M x M] matrix
    """
    # Covariance matrix [column-wise variables]: Sigma = (X-mu)' * (X-mu) / N
    sigma = np.cov(X, rowvar=True) # [M x M]
    # Singular Value Decomposition. X = U * np.diag(S) * V
    U,S,V = np.linalg.svd(sigma)
        # U: [M x M] eigenvectors of sigma.
        # S: [M x 1] eigenvalues of sigma.
        # V: [M x M] transpose of U
    # Whitening constant: prevents division by zero
    epsilon = 1e-5
    # ZCA Whitening matrix: U * Lambda * U'
    ZCAMatrix = np.dot(U, np.dot(np.diag(1.0/np.sqrt(S + epsilon)), U.T)) # [M x M]
    return ZCAMatrix

以及一个使用示例:

X = np.array([[0, 2, 2], [1, 1, 0], [2, 0, 1], [1, 3, 5], [10, 10, 10] ]) # Input: X [5 x 3] matrix
ZCAMatrix = zca_whitening_matrix(X) # get ZCAMatrix
ZCAMatrix # [5 x 5] matrix
xZCAMatrix = np.dot(ZCAMatrix, X) # project X onto the ZCAMatrix
xZCAMatrix # [5 x 3] matrix

希望能帮助到你!

为什么Edgar Andrés Margffoy Tuay的答案不正确的详细信息:正如RM评论中所指出的,Edgar Andrés Margffoy Tuay的 ZCA 美白功能包含一个小但至关重要的错误:np.diag(S)应该删除。Numpy 返回S为 amx 1 向量而不是 amxm 矩阵(这在其他 svd 实现中很常见,例如 Matlab)。因此,ZCAMatrix变量变为 amx 1 向量,而不是应有的 amxm 矩阵(当输入为 mxn 时)。(此外,Andfoy 的答案中的协方差矩阵仅在 X 预先居中时才有效,即均值为 0)。

ZCA 的其他参考资料:您可以在 Python 中查看斯坦福 UFLDL ZCA 美白练习的完整答案

于 2016-07-26T13:07:35.223 回答
12

您的数据是否存储在 mxn 矩阵中?其中 m 是数据的维度,n 是案例总数?如果不是这种情况,您应该调整数据的大小。例如,如果您的图像大小为 28x28,而您只有一张图像,那么您应该有一个 1x784 的矢量。你可以使用这个功能:

import numpy as np

def flatten_matrix(matrix):
    vector = matrix.flatten(1)
    vector = vector.reshape(1, len(vector))
    return vector

然后,您将 ZCA Whitening 应用到您的训练集,使用:

def zca_whitening(inputs):
    sigma = np.dot(inputs, inputs.T)/inputs.shape[1] #Correlation matrix
    U,S,V = np.linalg.svd(sigma) #Singular Value Decomposition
    epsilon = 0.1                #Whitening constant, it prevents division by zero
    ZCAMatrix = np.dot(np.dot(U, np.diag(1.0/np.sqrt(np.diag(S) + epsilon))), U.T)                     #ZCA Whitening matrix
    return np.dot(ZCAMatrix, inputs)   #Data whitening

保存矩阵很重要,ZCAMatrix如果要在训练神经网络后进行预测,则应将测试用例相乘。

最后,我邀请您参加http://ufldl.stanford.edu/wiki/index.php/UFLDL_Tutorialhttp://ufldl.stanford.edu/tutorial/上的斯坦福 UFLDL 教程。他们有很好的解释和一些关于 MATLAB 的编程练习,然而,几乎所有在 MATLAB 上找到的函数都在 Numpy 上同名。我希望这可以提供一个见解。

于 2015-07-21T01:34:27.320 回答
3

我的讨论可能有点晚了,但我最近发现了这个线程,因为我在 TensorFlow 中努力实现 ZCA,因为我糟糕的 PC 处理器太慢而无法处理大量数据。

如果有人感兴趣,我已经对我在 TensorFlow 中的 ZCA 实现做了一个要点:

import tensorflow as tf

from keras.datasets import mnist

import numpy as np

tf.enable_eager_execution()

assert tf.executing_eagerly()


class ZCA(object):
    """
    Simple ZCA aka Mahalanobis transformation class made in TensorFlow.
    The code was largely ported from Keras ImageDataGenerator
    """

    def __init__(self, epsilon=1e-5, dtype='float64'):

        """epsilon is the normalization constant, dtype refers to the data type used in the computation.
         WARNING: the default precision is set to float64 as i have found that when computing the mean tensorflow'
         and numpy results can differ by a substantial amount.
         Usage: fit method computes the principal components and should be called first,
                compute method returns the actual transformed tensor
         NOTE : The input to both methods must be a 4D tensor.
        """

        assert dtype is 'float32' or 'float64', "precision must be float32 or float64"

        self.epsilon = epsilon
        self.dtype = dtype
        self.princ_comp = None
        self.mean = None

    def _featurewise_center(self, images_tensor):

        if self.mean is None:
            self.mean, _ = tf.nn.moments(images_tensor, axes=(0, 1, 2))
            broadcast_shape = [1, 1, 1]
            broadcast_shape[2] = images_tensor.shape[3]
            self.mean = tf.reshape(self.mean, broadcast_shape)

        norm_images = tf.subtract(images_tensor, self.mean)

        return norm_images

    def fit(self, images_tensor):

        assert images_tensor.shape[3], "The input should be a 4D tensor"

        if images_tensor.dtype is not self.dtype:  # numerical error for float32

            images_tensor = tf.cast(images_tensor, self.dtype)

        images_tensor = self._featurewise_center(images_tensor)

        flat = tf.reshape(images_tensor, (-1, np.prod(images_tensor.shape[1:].as_list())))
        sigma = tf.div(tf.matmul(tf.transpose(flat), flat), tf.cast(flat.shape[0], self.dtype))
        s, u, _ = tf.svd(sigma)
        s_inv = tf.div(tf.cast(1, self.dtype), (tf.sqrt(tf.add(s[tf.newaxis], self.epsilon))))
        self.princ_comp = tf.matmul(tf.multiply(u, s_inv), tf.transpose(u))

    def compute(self, images_tensor):

        assert images_tensor.shape[3], "The input should be a 4D tensor"

        assert self.princ_comp is not None, "Fit method should be called first"

        if images_tensor.dtype is not self.dtype:
            images_tensor = tf.cast(images_tensor, self.dtype)

        images_tensors = self._featurewise_center(images_tensor)

        flatx = tf.cast(tf.reshape(images_tensors, (-1, np.prod(images_tensors.shape[1:]))), self.dtype)
        whitex = tf.matmul(flatx, self.princ_comp)
        x = tf.reshape(whitex, images_tensors.shape)

        return x


def main():
    import matplotlib.pyplot as plt

    train_set, test_set = mnist.load_data()
    x_train, y_train = train_set

    zca1 = ZCA(epsilon=1e-5, dtype='float64')

    # input should be a 4D tensor

    x_train = x_train.reshape(*x_train.shape, 1)
    zca1.fit(x_train)
    x_train_transf = zca1.compute(x_train)

    # reshaping to 28*28 and casting to uint8 for plotting

    x_train_transf = tf.reshape(x_train_transf, x_train_transf.shape[0:3])


    fig, axes = plt.subplots(3, 3)

    for i, ax in enumerate(axes.flat):
        # Plot image.
        ax.imshow(x_train_transf[i],
                  cmap='binary'
                  )

        xlabel = "True: %d" % y_train[i]
        ax.set_xlabel(xlabel)
        ax.set_xticks([])
        ax.set_yticks([])

    plt.show()


if __name__ == '__main__':
main()

我知道这不是对原始问题的正确答案,但对于正在寻找 ZCA 的 GPU 实现但找不到的人来说,它仍然可能有用。

于 2018-04-29T11:39:46.353 回答
3

尽管两个答案都参考了UFLDL 教程,但似乎都没有使用其中描述的步骤。

因此,我认为根据教程提供一个简单实现 PCA/ZCA-whitening 的答案可能不是坏主意:

import numpy as np

# generate some random, 2D data
x = np.random.randn(1000, 2)
# and center it
x_c = x - np.mean(x, 0)

# compute the 2x2 covariance matrix
# (remember that covariance matrix is symmetric)
sigma = np.cov(x, rowvar=False)
# and extract eigenvalues and eigenvectors
# using the algorithm for symmetric matrices
l,u = np.linalg.eigh(sigma)
# NOTE that for symmetric matrices,
# eigenvalues and singular values are the same.
# u, l, _ = np.linalg.svd(sigma) should thus give equivalent results

# rotate the (centered) data to decorrelate it
x_rot = np.dot(x_c, u)
# check that the covariance is diagonal (indicating decorrelation)
np.allclose(np.cov(x_rot.T), np.diag(np.diag(np.cov(x_rot.T))))

# scale the data by eigenvalues to get unit variance
x_white = x_rot / np.sqrt(l)
# have the whitened data be closer to the original data
x_zca = np.dot(x_white, u.T)

我假设您可以自己将其包装在一个函数中...

为了完整性,不同的实现风格及其运行时(在 CIFAR10 的中心版本上评估):

x = np.random.randn(10_000, 3, 32, 32)
x_ = np.reshape(x, (len(x), -1))
x_c = x_ - np.mean(x_, axis=0)

def zca1(x):
    s, u = np.linalg.eigh(x.T @ x)
    scale = np.sqrt(len(x) / s)
    return (u * scale) @ u.T

def zca2(x):
    u, s, _ = np.linalg.svd(x.T @ x, hermitian=True)
    scale = np.sqrt(len(x) / s)
    return (u * scale) @ u.T

def zca3(x):
    _, s, v = np.linalg.svd(x, full_matrices=False)
    scale = np.sqrt(len(x)) / s
    return (v.T * scale) @ v


%timeit zca1(x_c)  
# 4.57 s ± 14.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit zca2(x_c)
# 4.62 s ± 22.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit zca3(x_c)
# 20.2 s ± 1.2 s per loop (mean ± std. dev. of 7 runs, 1 loop each)

对于这背后的数学,我参考了这个来自交叉验证的优秀答案。

于 2017-04-03T17:16:24.383 回答
0

这适用于 48x48 的数组:

def flatten_matrix(matrix):
    vector = matrix.flatten(order='F')
    vector = vector.reshape(1, len(vector))
    return vector

def zca_whitening(inputs): 
    sigma = np.dot(inputs, inputs.T)/inputs.shape[1] #Correlation matrix
    U,S,V = np.linalg.svd(sigma) #Singular Value Decomposition
    epsilon = 0.1                #Whitening constant, it prevents division by zero
    ZCAMatrix = np.dot(np.dot(U, np.diag(1.0/np.sqrt(np.diag(S) + epsilon))), U.T)  #ZCA Whitening matrix
    return np.dot(ZCAMatrix, inputs)   #Data whitening

def global_contrast_normalize(X, scale=1., subtract_mean=True, use_std=True,
                              sqrt_bias=10, min_divisor=1e-8):

    """
    __author__ = "David Warde-Farley"
    __copyright__ = "Copyright 2012, Universite de Montreal"
    __credits__ = ["David Warde-Farley"]
    __license__ = "3-clause BSD"
    __email__ = "wardefar@iro"
    __maintainer__ = "David Warde-Farley"
    .. [1] A. Coates, H. Lee and A. Ng. "An Analysis of Single-Layer
       Networks in Unsupervised Feature Learning". AISTATS 14, 2011.
       http://www.stanford.edu/~acoates/papers/coatesleeng_aistats_2011.pdf
    """
    assert X.ndim == 2, "X.ndim must be 2"
    scale = float(scale)
    assert scale >= min_divisor

    mean = X.mean(axis=1)
    if subtract_mean:
        X = X - mean[:, np.newaxis]  
    else:
        X = X.copy()
    if use_std:
        ddof = 1
        if X.shape[1] == 1:
            ddof = 0
        normalizers = np.sqrt(sqrt_bias + X.var(axis=1, ddof=ddof)) / scale
    else:
        normalizers = np.sqrt(sqrt_bias + (X ** 2).sum(axis=1)) / scale
    normalizers[normalizers < min_divisor] = 1.
    X /= normalizers[:, np.newaxis]  # Does not make a copy.
    return X

def ZeroCenter(data):
    data = data - np.mean(data,axis=0)
    return data

def Zerocenter_ZCA_whitening_Global_Contrast_Normalize(data):
    numpy_data = np.array(data).reshape(48,48)
    data2 = ZeroCenter(numpy_data)
    data3 = zca_whitening(flatten_matrix(data2)).reshape(48,48)
    data4 = global_contrast_normalize(data3)
    data5 = np.rot90(data4,3)
    return data5

例如从这张图片:

在此处输入图像描述

返回:

在此处输入图像描述

这是代码:

https://gist.github.com/m-alcu/45f4a083cb5e388d2ed26ace4392ed66,需要把fer2013.csv文件放在同一个目录下(https://www.kaggle.com/c/challenges-in-representation-learning-facial-表达识别挑战/数据

于 2018-05-06T07:54:46.493 回答