web-dev-qa-db-fra.com

Comment mettre en œuvre le blanchiment ZCA? Python

J'essaie de mettre en œuvre ZCA blanchissant et j'ai trouvé des articles pour le faire, mais ils sont un peu déroutants .. quelqu'un peut-il éclairer une lumière pour moi?

Toute astuce ou aide est appréciée!

Voici les articles que j'ai lus:

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

J'ai essayé plusieurs choses mais la plupart d'entre elles je ne comprenais pas et je me suis retrouvé bloqué à un moment donné. En ce moment j'ai ceci comme base pour recommencer:

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

Voici une fonction python permettant de générer la matrice de blanchiment ZCA:

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

Et un exemple d'utilisation:

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

J'espère que ça aide!

Les détails de la raison pour laquelle la réponse de Edgar Andrés Margffoy Tuay _ n'est pas correcte : Comme indiqué dans RM : commentaire , Edgar Andrés Margffoy Tuay } La fonction de blanchiment ZCA contient une petite erreur cruciale: la np.diag(S) doit être supprimée. Numpy renvoie S sous la forme d'un vecteur m x 1 et non d'une matrice m x m (comme dans d'autres implémentations de svd, par exemple Matlab). Par conséquent, la variable ZCAMatrix devient un vecteur m x 1 et non une matrice m x m comme il se doit (lorsque l'entrée est m x n). (En outre, la matrice de covariance dans la réponse d'Andfoy n'est valide que si X est pré-centré, c'est-à-dire signifie 0).

Autres références pour ZCA : Vous pouvez voir la réponse complète, en Python, à l’exercice de blanchiment ZCA de Stanford UFLDL (ici) .

11
Pascal Timshel

Vos données sont-elles stockées dans une matrice mxn? Où m est la dimension des données et n le nombre total d'observations? Si ce n'est pas le cas, vous devriez redimensionner vos données. Par exemple, si vos images ont une taille de 28x28 et que vous n’avez qu’une image, vous devriez avoir un vecteur 1x784. Vous pouvez utiliser cette fonction:

import numpy as np

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

Ensuite, vous appliquez ZCA Whitening à votre ensemble d’entraînement à l’aide de:

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

Il est important de sauvegarder la matrice ZCAMatrix, vous devez multiplier vos cas de test si vous souhaitez prédire après la formation de Neural Net.

Enfin, je vous invite à suivre les didacticiels Stanford UFLDL à http://ufldl.stanford.edu/wiki/index.php/UFLDL_Tutorial ou http://ufldl.stanford.edu/tutorial/ . Ils ont d'excellentes explications et quelques exercices de programmation sur MATLAB. Cependant, presque toutes les fonctions présentes sur MATLAB sont sur Numpy du même nom. J'espère que cela peut donner un aperçu.

Je suis peut-être un peu en retard à la discussion, mais j’ai trouvé ce fil récemment alors que j’avais du mal à mettre en œuvre ZCA dans TensorFlow, car mon processeur médiocre était trop lent pour traiter de gros volumes de données.

Si quelqu'un est intéressé, j'ai fait un Gist de ma mise en œuvre de la ZCA dans TensorFlow:

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 __== '__main__':
main()

Je sais que cette réponse à la question initiale n’est pas appropriée, mais elle peut néanmoins être utile à quiconque recherche une implémentation ZU sur GPU mais n’en trouve pas.

2
Samuele Cornell

Bien que les deux réponses fassent référence au UFLDL tutorial , aucune d’entre elles ne semble suivre les étapes décrites.

Par conséquent, j’ai pensé que ce n’était peut-être pas une mauvaise idée de fournir une réponse qui implémenterait simplement le blanchiment PCA/ZCA conformément au tutoriel:

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)

Je suppose que vous pouvez envelopper une fonction par vous-même ...

Une implémentation alternative, qui pourrait parfois être plus efficace (et devrait avoir une meilleure stabilité d'après ce que je me souviens de mon cours de mathématiques numériques), serait:

_,s,v = np.linalg.svd(x_c)
x_rot = np.dot(x_c, v.T)
x_white = x_rot / s * np.sqrt(len(x_c) - 1)
x_zca = np.dot(x_white, v)

Pour les mathématiques derrière cela, je me réfère à cette excellente réponse de croix validée.

0
Mr Tsjolder

Cela fonctionne avec un tableau de 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

par exemple à partir de cette image:

 enter image description here

résultats:

 enter image description here

Voici le code:

https://Gist.github.com/m-alcu/45f4a083cb5e388d2ed26ace4392ed66 , doit placer le fichier fer2013.csv dans le même répertoire (/ https://www.kaggle.com/c/challenges-in- représentation-apprentissage-expression-faciale-reconnaissance-défi/données )