tensorflow 用于聚类的二值数据降维的自动编码器

woobm2wo  于 2023-03-19  发布在  其他
关注(0)|答案(2)|浏览(138)

给定一个二进制数据集(来源于是/否调查问卷回答),旨在用于后续的无监督聚类分析,具有显著的多共线性,约50,000个观察值共包含31个特征(subjects),在执行聚类分析之前降低输入数据的维度似乎是明智的。我尝试使用自动编码器来进行此操作,但令人惊讶的是,聚类(通过k-中心线推导,选择k-中心线的原因是基础数据的标称性质以及与例如k-均值相比在离群值/噪声方面更大的稳定性)在使用MCA时实际上更独特且更清楚地区分,在k = 5时具有明确的最大轮廓系数。
鉴于前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')
sqxo8psd

sqxo8psd1#

因此,多重共线性的问题在于,除了无法进行有意义的推断之外,它还会阻碍收敛速度,这意味着,在所有条件相同的情况下,如果数据高度多重共线性,则需要更多的数据才能实现收敛。
根据你的目标(纯预测与推理),你可能希望正交化(参见herehere)你的输入,然后将残差馈送到你的自动编码器,或者你可能希望选择一个更合理的激活函数或使用稀疏的自动编码器。
也就是说,如果你的目标是做出好的预测,而不一定关心推理,我建议你先尝试最后两个步骤:
1.更改瓶颈处的激活功能(使用Sigmoid?)。
1.使用稀疏自动编码器参见here,here和here

wh6knrhe

wh6knrhe2#

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

相关问题