使用 PCA 减少 CNN 训练集中的维数
Using PCA to Reduce # Dimensions in Training Set for CNN
简短版本: 我在使用 PCA 减少训练数据的维数时遇到困难。训练数据是为 2D CNN 构建的,它将图形图像分为三个 类。
模型的目的
我是主成分分析的新手。我有一个 2D 卷积神经网络,可将图形图像(36 x 36 像素)分类为三个 类 之一,例如:
改进模型
我意识到大部分像素都是白色的,所以 CNN 非常低效并且需要很长时间来训练。我开始意识到降维技术并尝试使用 PCA。我将我的一张训练图像转换为灰度图像并可视化了“特征图”(如左图所示)。然后我从特征图(如右图所示)重建了原件。
X=grayscale
pca_oliv = PCA(n_components = 36)
X_proj = pca_oliv.fit_transform(X)
print(np.cumsum(pca_oliv.explained_variance_ratio_))
plt.imshow(np.reshape(pca_oliv.components_, (36,36)), cmap=plt.cm.bone, interpolation='nearest')
问题
但我知道它可以做得更好。 这是 n=36 维度。通过绘制解释的方差,我找到了 3 个维度的肘部。这意味着 36 个维度中只有 3 个维度,我可以保留 91.7% 的方差。
但如果我将 pca_oliv = PCA(n_components = 36)
更改为 pca_oliv = PCA(n_components = 3)
,一切都会变得混乱:ValueError: cannot reshape array of size 108 into shape (36,36)
。为什么?我做错了什么?
MWE
pip install tensorflow
pip install numpy
pip install matplotlib
"""# Import Libraries"""
# Import Libraries
import tensorflow as tf
from tensorflow import keras
from keras.models import Sequential
from keras.layers import Dense, Flatten, Conv2D, MaxPooling2D, Dropout
from tensorflow.keras import layers
from tensorflow.keras.utils import to_categorical
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')
"""# Load Dataset"""
import pathlib
dataset_url = "*/TrainingSet.tar.gz"
data_dir = tf.keras.utils.get_file(origin = dataset_url,
fname = "TrainingSet",
untar = True)
data_dir = pathlib.Path(data_dir)
"""# Display # Images to check"""
print(list(data_dir.glob('*/*.png')))
image_count = len(list(data_dir.glob('*/*.png')))
print(image_count)
"""# Display sample image"""
pip install sklearn
import numpy as np
import os
import PIL
import PIL.Image
import tensorflow as tf
import tensorflow_datasets as tfds
from sklearn.decomposition import PCA
graphs = list(data_dir.glob('*/*.png'))
PIL.Image.open(str(graphs[6]))
"""# Define Image Dimensions & Batch Size"""
batch_size = 32
img_height = 36
img_width = 36
"""# Create Training & Validation Sets (80%, 20%)"""
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="training",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="validation",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
"""# Define 3 Classes"""
class_names = ['Cubic Sinusoidal', 'Linear Sinusoidal', 'Quadratic Sinusoidal']
print(class_names)
"""# Supervised Learning (9 Samples from the Training Set)"""
!pip install skimage
from skimage import data
from skimage.color import rgb2gray
import matplotlib.pyplot as plt
subGraphs = []
plt.figure(figsize=(10, 10))
for images, labels in train_ds.take(1):
for i in range(9):
ax = plt.subplot(3, 3, i + 1)
plt.imshow(images[i].numpy().astype("uint8"))
subGraphs.append(images[i].numpy().astype("uint8"))
plt.title(class_names[labels[i]])
plt.axis("off")
subGraphs = np.array(subGraphs)
print(subGraphs.shape)
grayscale = rgb2gray(subGraphs[1])
print(grayscale.shape)
X=grayscale
pca_oliv = PCA(n_components = 36)
X_proj = pca_oliv.fit_transform(X)
print(np.cumsum(pca_oliv.explained_variance_ratio_))
plt.plot(np.cumsum(pca_oliv.explained_variance_ratio_))
plt.imshow(np.reshape(pca_oliv.components_, (36,36)), cmap=plt.cm.bone, interpolation='nearest')
X_inv_proj = pca_oliv.inverse_transform(X_proj)
X_proj_img = np.reshape(X_inv_proj,(1,36,36))
plt.imshow(X_proj_img[0], cmap=plt.cm.bone, interpolation='nearest')
作为参考,这是我的 Jupyter Notebook:PCA+CNN。如果有人能提供帮助,那就太好了。
PCA
用于同时减少维数,确保此较低维表示涵盖最大可能的变化。现在,想一想,您最初有多少维度。因为,我看到你使用了 (36, 36)
灰度图像。在这里,每个像素都是您的原始特征。您再次拍摄了 9 张图像以在其上应用 PCA
。
在这种情况下,您的 number of examples
小于 number of original features
,即 9 < 36*36
,因此,您需要不超过 9
个主要组件来涵盖完整方差。但是,如果您的示例数量大于特征数量 (36*36 = 1296)
,那么您将能够采用 n_components
更大的值。看到这里,sklearn.decomposition.PCA and Why are there only n−1 principal components for n data if the number of dimensions is ≥n?
但无论如何,我不会深入了解 PCA
,而是描述您需要在代码中更改的内容。
grayscale = rgb2gray(subGraphs)
print(grayscale.shape)
grayscale = grayscale.reshape((grayscale.shape[0], grayscale.shape[1] * grayscale.shape[2]))
print(grayscale.shape)
因为 PCA
期望输入形状为 (number of examples, number of features)
因此,您必须在第一维中保留 number of examples
,第二维将是所有像素值(原始特征)。如果您使用了彩色图像,那么您需要将所有通道的特征包含在同一个第二维中,有点像:
color_img = color_img.reshape((color_img.shape[0], color_img.shape[1] * color_img.shape[2] * color_img.shape[3]))
print(color_img.shape)
现在可以申请了PCA
:
X=grayscale
pca_oliv = PCA(n_components = 9)
X_proj = pca_oliv.fit_transform(X)
print(np.cumsum(pca_oliv.explained_variance_ratio_))
plt.plot(np.cumsum(pca_oliv.explained_variance_ratio_))
请注意,您将无法设置 n_components
超过 9
,因为您只使用了 9 张图片。如果你看到 X_proj
的形状,你会发现它的形状是 (9, 9)
。第一个 9
是示例的数量,第二个 9
是每个示例以较低维度 space 表示,其中 space 具有 9
维度(n_components
).
最后,进行逆变换以恢复原始维度,(这只是为了说明目的,您将使用 X_proj
训练您的模型,因为它是较低维度的表示):
X_inv_proj = pca_oliv.inverse_transform(X_proj)
print(X_inv_proj.shape)
for index in range(len(X_inv_proj)): # 9
X_proj_img = np.reshape(X_inv_proj[index],(36,36))
plt.imshow(X_proj_img, cmap=plt.cm.bone, interpolation='nearest')
plt.show()
同样,X_proj
包含您的 9
示例的低维表示(9
维)。因为它不是图像,所以你不需要重塑它。您可以直接使用它来训练您的模型,就好像这些 9
个特征代表了您原来的 36*36
个特征。
这里请注意,逆变换并不总是无损变换。在这里,在您的情况下,我们采用了 9
个主要组件(在这种情况下是最大可能采用的)。所以,本质上我们在得到 PCA
的同时采用了 100%
变化,所以,当我们应用逆变换时,它会给我们变化的 100%
,即它会恢复原始数据.但是如果我们把n_components
取到某个较低的值,那么逆变换就不能完全恢复原来的信息,虽然X_inv_proj
的形状不会改变,但是它的信息会hold不会是原始数据的完整信息。
简短版本: 我在使用 PCA 减少训练数据的维数时遇到困难。训练数据是为 2D CNN 构建的,它将图形图像分为三个 类。
模型的目的
我是主成分分析的新手。我有一个 2D 卷积神经网络,可将图形图像(36 x 36 像素)分类为三个 类 之一,例如:
改进模型
我意识到大部分像素都是白色的,所以 CNN 非常低效并且需要很长时间来训练。我开始意识到降维技术并尝试使用 PCA。我将我的一张训练图像转换为灰度图像并可视化了“特征图”(如左图所示)。然后我从特征图(如右图所示)重建了原件。
X=grayscale
pca_oliv = PCA(n_components = 36)
X_proj = pca_oliv.fit_transform(X)
print(np.cumsum(pca_oliv.explained_variance_ratio_))
plt.imshow(np.reshape(pca_oliv.components_, (36,36)), cmap=plt.cm.bone, interpolation='nearest')
问题
但我知道它可以做得更好。 这是 n=36 维度。通过绘制解释的方差,我找到了 3 个维度的肘部。这意味着 36 个维度中只有 3 个维度,我可以保留 91.7% 的方差。
但如果我将 pca_oliv = PCA(n_components = 36)
更改为 pca_oliv = PCA(n_components = 3)
,一切都会变得混乱:ValueError: cannot reshape array of size 108 into shape (36,36)
。为什么?我做错了什么?
MWE
pip install tensorflow
pip install numpy
pip install matplotlib
"""# Import Libraries"""
# Import Libraries
import tensorflow as tf
from tensorflow import keras
from keras.models import Sequential
from keras.layers import Dense, Flatten, Conv2D, MaxPooling2D, Dropout
from tensorflow.keras import layers
from tensorflow.keras.utils import to_categorical
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')
"""# Load Dataset"""
import pathlib
dataset_url = "*/TrainingSet.tar.gz"
data_dir = tf.keras.utils.get_file(origin = dataset_url,
fname = "TrainingSet",
untar = True)
data_dir = pathlib.Path(data_dir)
"""# Display # Images to check"""
print(list(data_dir.glob('*/*.png')))
image_count = len(list(data_dir.glob('*/*.png')))
print(image_count)
"""# Display sample image"""
pip install sklearn
import numpy as np
import os
import PIL
import PIL.Image
import tensorflow as tf
import tensorflow_datasets as tfds
from sklearn.decomposition import PCA
graphs = list(data_dir.glob('*/*.png'))
PIL.Image.open(str(graphs[6]))
"""# Define Image Dimensions & Batch Size"""
batch_size = 32
img_height = 36
img_width = 36
"""# Create Training & Validation Sets (80%, 20%)"""
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="training",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="validation",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
"""# Define 3 Classes"""
class_names = ['Cubic Sinusoidal', 'Linear Sinusoidal', 'Quadratic Sinusoidal']
print(class_names)
"""# Supervised Learning (9 Samples from the Training Set)"""
!pip install skimage
from skimage import data
from skimage.color import rgb2gray
import matplotlib.pyplot as plt
subGraphs = []
plt.figure(figsize=(10, 10))
for images, labels in train_ds.take(1):
for i in range(9):
ax = plt.subplot(3, 3, i + 1)
plt.imshow(images[i].numpy().astype("uint8"))
subGraphs.append(images[i].numpy().astype("uint8"))
plt.title(class_names[labels[i]])
plt.axis("off")
subGraphs = np.array(subGraphs)
print(subGraphs.shape)
grayscale = rgb2gray(subGraphs[1])
print(grayscale.shape)
X=grayscale
pca_oliv = PCA(n_components = 36)
X_proj = pca_oliv.fit_transform(X)
print(np.cumsum(pca_oliv.explained_variance_ratio_))
plt.plot(np.cumsum(pca_oliv.explained_variance_ratio_))
plt.imshow(np.reshape(pca_oliv.components_, (36,36)), cmap=plt.cm.bone, interpolation='nearest')
X_inv_proj = pca_oliv.inverse_transform(X_proj)
X_proj_img = np.reshape(X_inv_proj,(1,36,36))
plt.imshow(X_proj_img[0], cmap=plt.cm.bone, interpolation='nearest')
作为参考,这是我的 Jupyter Notebook:PCA+CNN。如果有人能提供帮助,那就太好了。
PCA
用于同时减少维数,确保此较低维表示涵盖最大可能的变化。现在,想一想,您最初有多少维度。因为,我看到你使用了 (36, 36)
灰度图像。在这里,每个像素都是您的原始特征。您再次拍摄了 9 张图像以在其上应用 PCA
。
在这种情况下,您的 number of examples
小于 number of original features
,即 9 < 36*36
,因此,您需要不超过 9
个主要组件来涵盖完整方差。但是,如果您的示例数量大于特征数量 (36*36 = 1296)
,那么您将能够采用 n_components
更大的值。看到这里,sklearn.decomposition.PCA and Why are there only n−1 principal components for n data if the number of dimensions is ≥n?
但无论如何,我不会深入了解 PCA
,而是描述您需要在代码中更改的内容。
grayscale = rgb2gray(subGraphs)
print(grayscale.shape)
grayscale = grayscale.reshape((grayscale.shape[0], grayscale.shape[1] * grayscale.shape[2]))
print(grayscale.shape)
因为 PCA
期望输入形状为 (number of examples, number of features)
因此,您必须在第一维中保留 number of examples
,第二维将是所有像素值(原始特征)。如果您使用了彩色图像,那么您需要将所有通道的特征包含在同一个第二维中,有点像:
color_img = color_img.reshape((color_img.shape[0], color_img.shape[1] * color_img.shape[2] * color_img.shape[3]))
print(color_img.shape)
现在可以申请了PCA
:
X=grayscale
pca_oliv = PCA(n_components = 9)
X_proj = pca_oliv.fit_transform(X)
print(np.cumsum(pca_oliv.explained_variance_ratio_))
plt.plot(np.cumsum(pca_oliv.explained_variance_ratio_))
请注意,您将无法设置 n_components
超过 9
,因为您只使用了 9 张图片。如果你看到 X_proj
的形状,你会发现它的形状是 (9, 9)
。第一个 9
是示例的数量,第二个 9
是每个示例以较低维度 space 表示,其中 space 具有 9
维度(n_components
).
最后,进行逆变换以恢复原始维度,(这只是为了说明目的,您将使用 X_proj
训练您的模型,因为它是较低维度的表示):
X_inv_proj = pca_oliv.inverse_transform(X_proj)
print(X_inv_proj.shape)
for index in range(len(X_inv_proj)): # 9
X_proj_img = np.reshape(X_inv_proj[index],(36,36))
plt.imshow(X_proj_img, cmap=plt.cm.bone, interpolation='nearest')
plt.show()
同样,X_proj
包含您的 9
示例的低维表示(9
维)。因为它不是图像,所以你不需要重塑它。您可以直接使用它来训练您的模型,就好像这些 9
个特征代表了您原来的 36*36
个特征。
这里请注意,逆变换并不总是无损变换。在这里,在您的情况下,我们采用了 9
个主要组件(在这种情况下是最大可能采用的)。所以,本质上我们在得到 PCA
的同时采用了 100%
变化,所以,当我们应用逆变换时,它会给我们变化的 100%
,即它会恢复原始数据.但是如果我们把n_components
取到某个较低的值,那么逆变换就不能完全恢复原来的信息,虽然X_inv_proj
的形状不会改变,但是它的信息会hold不会是原始数据的完整信息。