如何实现ZCA美白?python
我正在尝试实现ZCA美白,并找到了一些相关文章,但它们有点让人困惑。。有人能帮我照盏灯吗 任何提示或帮助都将不胜感激 以下是我读到的文章: 我尝试了几件事,但大多数我都不明白,我被锁在了某个台阶上。 现在我有了这个基础来重新开始:如何实现ZCA美白?python,python,pca,correlated,image-preprocessing,Python,Pca,Correlated,Image Preprocessing,我正在尝试实现ZCA美白,并找到了一些相关文章,但它们有点让人困惑。。有人能帮我照盏灯吗 任何提示或帮助都将不胜感激 以下是我读到的文章: 我尝试了几件事,但大多数我都不明白,我被锁在了某个台阶上。 现在我有了这个基础来重新开始: dtype = np.float32 data = np.loadtxt("../inputData/train.csv", dtype=dtype, delimiter=',', skiprows=1) img = ((data[1,1:]).reshape((
dtype = np.float32
data = np.loadtxt("../inputData/train.csv", dtype=dtype, delimiter=',', skiprows=1)
img = ((data[1,1:]).reshape((28,28)).astype('uint8')*255)
您的数据是否存储在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美白应用于训练集:
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教程。它们有很好的解释,也有一些MATLAB上的编程练习,但是,在MATLAB上找到的几乎所有函数都在Numpy上同名。我希望这可以提供一些见解。这里是一个用于生成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
希望有帮助
关于为什么的答案不正确的详细信息:正如在“s”中所指出的,ZCA美白函数包含一个小但关键的错误:应该删除np.diag。Numpy返回S
作为一个m x 1向量,而不是一个m x m矩阵(这在其他svd实现中很常见,例如Matlab)。因此,ZCAMatrix
变量变为一个mx1向量,而不是一个mxm矩阵(当输入为mxn时)。(此外,Andfoy答案中的协方差矩阵仅在X预先居中时有效,即平均值为0)
ZCA的其他参考资料:您可以在Python中看到斯坦福UFLDL ZCA美白练习的完整答案 尽管两个答案都提到了,但似乎没有一个答案使用了其中所述的步骤
因此,我认为根据教程提供一个简单实现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)
关于这背后的数学问题,我参考了交叉验证。我可能晚了一点才开始讨论,但最近我在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实现但找不到的人来说,它可能还是有用的。这适用于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
def展平矩阵(矩阵):
向量=矩阵。展平(order='F')
矢量=矢量。重塑(1,透镜(矢量))
返回向量
def zca_增白(输入):
sigma=np.dot(inputs,inputs.T)/inputs.shape[1]#相关矩阵
U、 S,V=np.linalg.svd(sigma)#奇异值分解
ε=0.1#白化常数,防止被零除
ZCAMatrix=np.dot(np.dot(U,np.diag(1.0/np.sqrt(np.diag(S)+epsilon)),U.T)#ZCA白化矩阵
返回np.dot(ZCAMatrix,输入)#数据白化
def全局对比度标准化(X,比例=1,减去平均值=True,使用标准值=True,
sqrt_偏差=10,最小除数=1e-8):
"""
__作者(David Warde Farley)
__版权所有\=“版权所有2012,蒙特利尔大学”
__信用证[大卫·沃德·法利]
__许可证\=“3-条款BSD”
__电子邮件\ \“wardefar@iro"
__维护人员\=“David Warde Farley”
[1]A.Coates,H.Lee和A.Ng.“单层结构的分析”
无监督特征学习中的网络”,美国统计局,2011年第14期。
http://www.stanford.edu/~acoates/papers/coatesleeng\u aistats\u 2011.pdf
"""
断言X.ndim==2,“X.ndim必须为2”
比例=浮动(比例)
断言比例>=最小除数
平均值=X.平均值(轴=1)
如果减去平均值:
X=X-平均值[:,np.newaxis]
其他:
X=X.copy()
如果使用标准:
ddof=1
如果X.shape[1]==1:
ddof=0
规范化器=np.sqrt(sqrt_偏差+X.var(轴=1,ddof=ddof))/标度
其他:
标准化器=np.sqrt(sqrt_偏差+(X**2).sum(轴=1))/标度
规格化器[规格化器<最小除数]=1。
X/=normalizers[:,np.newaxis]#不复制。
返回X
def ZeroCenter(数据):
数据=数据-np.平均值(数据,轴=0)
返回数据
def Zerocenter_ZCA_美白_全局_对比度_规格化(数据):
numpy_data=np.数组(数据).重塑(48,48)
数据2=零中心(numpy_数据)
数据3=zca_增白(展平矩阵(数据2))。重塑(48,48)
数据4=全局对比度标准化(数据3)
数据5=np.rot90(数据4,3)
返回数据5
例如,从该图像:
返回:
代码如下:
,需要将fer2013.csv文件放在同一个目录中()实际上data=np.loadtxt(“../inputData/train.csv”,dtype=dtype,delimiter=”,“,skiprows=1)每行有一个黑/白像素向量(0-255),img只是一个图像,我将其重新塑造为28,28。如果我想对整个“数据”对象进行ZCA,我应该怎么做?非常感谢你,福伊!如果您的数据已经由一个m x 784矩阵表示,您应该调用zca_(数据)。它是手写数字的MNIST数据集吗?是的!来自Kaggle竞赛:)我想知道如何才能从图像回到csv。例如,我可以创建ZCA的csv。有bu吗