Как осуществить отбеливание ZCA? питон

Я пытаюсь осуществить отбеливание 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)

5 ответов

Вот функция python для генерации отбеливающей матрицы 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

И пример использования:

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, функция отбеливания ZCA Edgar Andrés Margffoy Tuay содержит небольшую, но важную ошибку: np.diag(S) должны быть удалены. Numpy возвращается S как вектор a m x 1, а не как матрица amxm (как обычно в других реализациях svd, например, Matlab). Следовательно ZCAMatrix переменная становится вектором a m x 1, а не матрицей amxm, как это и должно быть (когда вводом является mxn). (Кроме того, ковариационная матрица в ответе Андфоя действительна, только если X предварительно центрирован, то есть означает 0).

Другие ссылки на ZCA: Вы можете увидеть полный ответ в Python на упражнение по отбеливанию ZCA в Стэнфорде UFLDL здесь.

Ваши данные хранятся в матрице 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 матрица, вы должны умножить свои тестовые случаи, если вы хотите предсказать после обучения нейронной сети.

Наконец, я приглашаю вас принять участие в учебниках по Стэнфордскому UFLDL по адресу http://ufldl.stanford.edu/wiki/index.php/UFLDL_Tutorial или http://ufldl.stanford.edu/tutorial/. Они имеют довольно хорошие объяснения, а также некоторые упражнения по программированию в MATLAB, однако почти все функции, найденные в MATLAB, имеют одинаковые имена в Numpy. Я надеюсь, что это может дать представление.

Возможно, я немного опоздал к обсуждению, но недавно нашел эту тему, пытаясь реализовать ZCA в TensorFlow, потому что мой плохой процессор на ПК был слишком медленным для обработки большого объема данных.

Если кому-то интересно, я сделал суть моей реализации ZCA в 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 __name__ == '__main__':
main()

Я знаю, что это неправильный ответ на первоначальный вопрос, но все же он может быть полезен для всех, кто ищет реализацию ZCA для GPU, но не может ее найти.

Хотя оба ответа относятся к учебнику по UFLDL, ни один из них, похоже, не использует шаги, описанные в нем.

Поэтому я подумал, что неплохо было бы просто дать ответ, который просто реализует отбеливание PCA/ZCA в соответствии с руководством:

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)

Я предполагаю, что вы можете обернуть это в функцию самостоятельно...

Альтернативная реализация, которая иногда может быть более эффективной (и должна иметь лучшую стабильность по сравнению с тем, что я помню из моего математического курса по математике), будет:

_,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)

За математикой, стоящей за этим, я ссылаюсь на этот превосходный ответ из перекрестной проверки.

Это работает с массивом 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-expression-recognition-challenge/data)

Другие вопросы по тегам