用于聚类的二进制数据集降维的自动编码器

问题描述 投票:0回答:3

给定一个旨在用于后续无监督聚类分析的二元数据集(来自是/否问卷回答),具有显着的多重共线性和总共 31 个特征,约 50,000 个观察(受试者),降低输入的维数似乎是明智的执行聚类分析之前的数据。我尝试为此使用自动编码器,但令人惊讶的是,集群(通过 k-medoids 派生,由于基础数据的标称性质以及与异常值/噪声相关的稳定性比例如 k-means 更高的稳定性而选择)实际上是使用 MCA 时更加明显和清晰,在 k = 5 时具有明显的最大 Silhouette 系数。

考虑到在我尝试自动编码器方法之前使用了具有前 5 个 PC 的 MCA(仅解释约 75% 的方差,通过碎石图选择),令我惊讶的是,自动编码器在提取有意义的特征方面做得更差相同的瓶颈维度。 当前自动编码器的问题,似乎是用于聚类的瓶颈层中的数据被扭曲了......

下面是我用来构建自动编码器的代码。会不会是超参数关了,或者整体架构的一些细节?随机搜索特定数量的层数、学习率、批量大小、层中的维度等没有产生任何实质性的结果。训练和验证数据集之间的损失相似,并且在大约 40 个时期后稳定在 0.15 左右。

我还尝试确定使用此类数据的研究,但没有发现任何有用的东西。

import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt


input_dim = 31
layer_1_dim = 18
layer_2_dim = 10
bottleneck_dim = 5
learning_rate = 0.001
epochs = 100
batch_size = 300


# split data into training and validation
training_n = int(data.shape[0] * 0.8)
train_data = data[:training_n, :]
val_data = data[training_n:, :]

# define autoencoder initializer
initializer = tf.keras.initializers.GlorotUniform()

# autoencoder layers
input_layer = Input(shape=(input_dim,))
layer = Dense(layer_1_dim, activation='relu')(input_layer)
layer = Dense(layer_2_dim, activation='relu', kernel_initializer=initializer)(layer)
layer = Dense(bottleneck_dim, activation='relu', kernel_initializer=initializer, name="bottleneck-output")(layer)
layer = Dense(layer_2_dim, activation='relu', kernel_initializer=initializer)(layer) 
layer = Dense(layer_1_dim, activation='relu', kernel_initializer=initializer)(layer)
output_layer = Dense(input_dim, activation='sigmoid', kernel_initializer=initializer)(layer)

# define and compile autoencoder model
autoencoder = Model(inputs=input_layer, outputs=output_layer)
optimizer = Adam(learning_rate=learning_rate)
autoencoder.compile(optimizer=optimizer, loss='binary_crossentropy')

# train the autoencoder model
history = autoencoder.fit(train_data, train_data, epochs=epochs, batch_size=batch_size, validation_data=(val_data, val_data))

# get bottleneck output
bottleneck_autoencoder = Model(inputs=autoencoder.input, outputs=autoencoder.get_layer('bottleneck-output').output)
bottleneck_output = bottleneck_autoencoder.predict(data)

# plot loss in traning and validation set
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Autoencoder loss (binary cross-entropy)')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Train', 'Validation'], loc='upper right')
plt.savefig('output/embedding.png')
python tensorflow keras artificial-intelligence cluster-analysis
3个回答
1
投票

如果您想要数据集的更好的低维表示,请使用 VAE 而不是常规自动编码器,它可以在 keras 中轻松完成(参见 https://keras.io/examples/generative/vae/

class Sampling(layers.Layer):
    """Uses (z_mean, z_log_var) to sample z, the vector encoding a digit."""

    def call(self, inputs):
        z_mean, z_log_var = inputs
        batch = tf.shape(z_mean)[0]
        dim = tf.shape(z_mean)[1]
        epsilon = tf.keras.backend.random_normal(shape=(batch, dim))
        return z_mean + tf.exp(0.5 * z_log_var) * epsilon

latent_dim = 2

encoder_inputs = keras.Input(shape=(28, 28, 1))
x = layers.Conv2D(32, 3, activation="relu", strides=2, padding="same")(encoder_inputs)
x = layers.Conv2D(64, 3, activation="relu", strides=2, padding="same")(x)
x = layers.Flatten()(x)
x = layers.Dense(16, activation="relu")(x)
z_mean = layers.Dense(latent_dim, name="z_mean")(x)
z_log_var = layers.Dense(latent_dim, name="z_log_var")(x)
z = Sampling()([z_mean, z_log_var])
encoder = keras.Model(encoder_inputs, [z_mean, z_log_var, z], name="encoder")
encoder.summary()

1
投票

由于这里的主要问题是多重共线性,您可以尝试使用考虑数据中非线性关系的降维方法。一个常见的例子是kernelPCA 然后你可以探索不同的核函数,我通常只用线性核就得到了有趣的结果。


1
投票

所以多重共线性的问题在于,除了不允许进行有意义的推理之外,它还会阻碍你的收敛速度。 这意味着,在一切都相同的情况下,如果您的数据是高度多重共线性的,您需要更多的数据才能实现收敛。

根据您的目标是什么(纯预测与推理),您可能想要正交化(参见此处此处)您的输入,然后将残差提供给您的自动编码器,或者您可能想要选择更明智的激活函数或使用稀疏自动编码器。

就是说,如果您的目标是做出好的预测并且不一定关心推理,我建议先尝试最后两个步骤:

  1. 在瓶颈处改变你的激活函数(使用 Sigmoid?)。
  2. 使用稀疏自动编码器见这里这里这里
© www.soinside.com 2019 - 2024. All rights reserved.