为什么我在 tensorboard t-sne 中可视化的 cnn 图像特征是随机的?
why is my visualization of cnn image features in tensorboard t-sne RANDOM?
我有一个卷积神经网络 (VGG16),它在 26 张图像的分类任务上表现良好 类。现在我想在张量板上使用 t-SNE 可视化数据分布。我删除了 CNN 的最后一层,因此输出是 4096 个特征。
因为分类工作正常(~90% val_accuracy),我希望在 t-SNE 中看到类似模式的东西。但无论我做什么,分布都保持 随机 (-> 数据在 circle/sphere 中对齐,类 是杂乱无章的)。我做错什么了吗?我是否误解了 t-SNE 或 tensorboard?这是我第一次使用它。
这是我获取功能的代码:
import tensorflow as tf
from tensorflow.keras import Model
import os
import numpy as np
from tensorboard.plugins import projector
def get_image_features(data_dir, model, layername='fc2'): # fc2 = last vgg dense layer
out = model.get_layer(layername).output
feature_model = Model(model.input, out) # the model, see summary() below
dataGen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1. / model.input.shape[2])
test_batches = dataGen.flow_from_directory(data_dir, target_size=model.input.shape[1:3], class_mode='categorical',
batch_size=50, shuffle=False)
features = feature_model.predict(test_batches)
return features
def create_projector(self, features, metadata_path):
import tensorflow.compat.v1 as tf # tf v1 needed
tf.disable_v2_behavior()
if type(features) is str:
features = np.loadtxt(features)
data_dir_list = os.listdir(self.test_data_dir)
data_dir_list.sort()
img_data = []
for dataset in data_dir_list:
img_list = os.listdir(os.path.join(self.test_data_dir, dataset))
img_list.sort()
for img in img_list:
input_img = cv2.imread(os.path.join(self.test_data_dir, dataset, img))
input_img_resize = cv2.resize(input_img, (112, 112))
img_data.append(input_img_resize)
img_data = np.array(img_data)
features_var = tf.Variable(features, name='features')
with tf.Session() as sess:
saver = tf.train.Saver([features_var])
sess.run(features_var.initializer)
saver.save(sess, os.path.join(self.log_dir, 'images_4_classes.ckpt'))
config = projector.ProjectorConfig()
embedding = config.embeddings.add()
embedding.tensor_name = features_var.name
embedding.metadata_path = metadata_path
projector.visualize_embeddings(tf.summary.FileWriter(self.log_dir), config)
编辑:
当我取消选中“spherize data”时,它不再是一个球体,但 类 的分布似乎仍然是完全随机的。
顺便说一句:PCA 工作正常并显示某种模式
这是 feature_model.summary():
Layer (type) Output Shape Param #
=================================================================
block1_conv1_input (InputLay [(None, 224, 224, 3)] 0
_________________________________________________________________
block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
_________________________________________________________________
block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
_________________________________________________________________
block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
_________________________________________________________________
block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
_________________________________________________________________
block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
_________________________________________________________________
block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
_________________________________________________________________
block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
_________________________________________________________________
block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
_________________________________________________________________
block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
_________________________________________________________________
block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
_________________________________________________________________
block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
_________________________________________________________________
flatten (Flatten) (None, 25088) 0
_________________________________________________________________
fc1 (Dense) (None, 4096) 102764544
_________________________________________________________________
fc2 (Dense) (None, 4096) 16781312
=================================================================
几周后,我不再尝试使用 tensorboard。我将输出层中的特征数量减少到 256、128、64,我之前使用 PCA 和 Truncated SDV 减少了特征,但没有任何改变。
现在我使用 sklearn.manifold.TSNE 并使用 plotly 可视化输出。这也很简单,工作正常,我可以看到适当的模式,而张量板中的 t-SNE 仍然产生随机分布。
所以我猜 tensorboard 中的算法太多了 类。或者我在准备数据时犯了一个错误并且没有注意到(但是为什么 PCA 起作用?)
如果有人知道问题出在哪里,我仍然很好奇。但如果其他人遇到同样的问题,我建议您使用 sklearn 进行尝试。
我有一个卷积神经网络 (VGG16),它在 26 张图像的分类任务上表现良好 类。现在我想在张量板上使用 t-SNE 可视化数据分布。我删除了 CNN 的最后一层,因此输出是 4096 个特征。 因为分类工作正常(~90% val_accuracy),我希望在 t-SNE 中看到类似模式的东西。但无论我做什么,分布都保持 随机 (-> 数据在 circle/sphere 中对齐,类 是杂乱无章的)。我做错什么了吗?我是否误解了 t-SNE 或 tensorboard?这是我第一次使用它。
这是我获取功能的代码:
import tensorflow as tf
from tensorflow.keras import Model
import os
import numpy as np
from tensorboard.plugins import projector
def get_image_features(data_dir, model, layername='fc2'): # fc2 = last vgg dense layer
out = model.get_layer(layername).output
feature_model = Model(model.input, out) # the model, see summary() below
dataGen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1. / model.input.shape[2])
test_batches = dataGen.flow_from_directory(data_dir, target_size=model.input.shape[1:3], class_mode='categorical',
batch_size=50, shuffle=False)
features = feature_model.predict(test_batches)
return features
def create_projector(self, features, metadata_path):
import tensorflow.compat.v1 as tf # tf v1 needed
tf.disable_v2_behavior()
if type(features) is str:
features = np.loadtxt(features)
data_dir_list = os.listdir(self.test_data_dir)
data_dir_list.sort()
img_data = []
for dataset in data_dir_list:
img_list = os.listdir(os.path.join(self.test_data_dir, dataset))
img_list.sort()
for img in img_list:
input_img = cv2.imread(os.path.join(self.test_data_dir, dataset, img))
input_img_resize = cv2.resize(input_img, (112, 112))
img_data.append(input_img_resize)
img_data = np.array(img_data)
features_var = tf.Variable(features, name='features')
with tf.Session() as sess:
saver = tf.train.Saver([features_var])
sess.run(features_var.initializer)
saver.save(sess, os.path.join(self.log_dir, 'images_4_classes.ckpt'))
config = projector.ProjectorConfig()
embedding = config.embeddings.add()
embedding.tensor_name = features_var.name
embedding.metadata_path = metadata_path
projector.visualize_embeddings(tf.summary.FileWriter(self.log_dir), config)
编辑: 当我取消选中“spherize data”时,它不再是一个球体,但 类 的分布似乎仍然是完全随机的。 顺便说一句:PCA 工作正常并显示某种模式
这是 feature_model.summary():
Layer (type) Output Shape Param #
=================================================================
block1_conv1_input (InputLay [(None, 224, 224, 3)] 0
_________________________________________________________________
block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
_________________________________________________________________
block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
_________________________________________________________________
block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
_________________________________________________________________
block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
_________________________________________________________________
block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
_________________________________________________________________
block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
_________________________________________________________________
block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
_________________________________________________________________
block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
_________________________________________________________________
block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
_________________________________________________________________
block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
_________________________________________________________________
block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
_________________________________________________________________
flatten (Flatten) (None, 25088) 0
_________________________________________________________________
fc1 (Dense) (None, 4096) 102764544
_________________________________________________________________
fc2 (Dense) (None, 4096) 16781312
=================================================================
几周后,我不再尝试使用 tensorboard。我将输出层中的特征数量减少到 256、128、64,我之前使用 PCA 和 Truncated SDV 减少了特征,但没有任何改变。
现在我使用 sklearn.manifold.TSNE 并使用 plotly 可视化输出。这也很简单,工作正常,我可以看到适当的模式,而张量板中的 t-SNE 仍然产生随机分布。 所以我猜 tensorboard 中的算法太多了 类。或者我在准备数据时犯了一个错误并且没有注意到(但是为什么 PCA 起作用?)
如果有人知道问题出在哪里,我仍然很好奇。但如果其他人遇到同样的问题,我建议您使用 sklearn 进行尝试。