降维技术是数据预处理中的一个重要环节,其目的是减少数据集中的特征数量,以提高模型的泛化能力并减少过拟合的风险。过拟合是指模型在训练数据上表现过于优秀,但在未见过的真实世界数据上表现不佳的现象。降维可以通过两种方式实现:特征选择和特征提取。特征选择是通过排除不太有用的特征来减少数据的维度,而特征提取则是将数据转换到更低的维度。
特征选择与特征提取
在特征选择中,有几种方法可以帮助识别并排除不重要的特征,例如递归特征消除、遗传特征选择和顺序前向选择。而在特征提取中,可以使用自编码器、主成分分析(PCA)和线性判别分析(LDA)等技术来降低数据的维度。
自编码器的工作原理
自编码器是一种无监督的人工神经网络,它通过将数据压缩到更低的维度(瓶颈层或编码层),然后解码数据以重建原始输入。瓶颈层(或编码层)保存了输入数据的压缩表示。在自编码器中,输出单元的数量必须等于输入单元的数量,因为试图重建输入数据。自编码器通常由编码器和解码器组成。编码器将提供的数据编码到更低的维度,即瓶颈层的大小,而解码器将压缩的数据解码回其原始形式。
编码器层中的神经元数量会随着层的深入而减少,而解码器层中的神经元数量则会随着层的深入而增加。在以下示例中,编码器和解码器各使用了三层。编码器分别在每层包含32、16和7个单元,而解码器则分别包含7、16和32个单元。瓶颈层/瓶颈层中的神经元数量必须小于数据中的特征数量。
在将数据输入自编码器之前,必须使用MinMaxScaler将数据缩放到0和1之间,因为将在输出层使用sigmoid激活函数,该函数输出0和1之间的值。
自编码器的类型
使用的自编码器是深度自编码器,其中编码器和解码器是对称的。自编码器的编码器和解码器不必是对称的,也可以是非对称的。可用的自编码器类型包括深度自编码器、稀疏自编码器、不完整自编码器、变分自编码器和LSTM自编码器。
自编码器的超参数
自编码器的超参数包括瓶颈层中的单元数量/代码大小、输入和输出大小(即数据中的特征数量)、每层的神经元或节点数量、编码器和解码器的层数、激活函数和优化函数。
import math
import pandas as pd
import tensorflow as tf
import kerastuner.tuners as kt
import matplotlib.pyplot as plt
from tensorflow.keras import Model
from tensorflow.keras import Sequential
from sklearn.preprocessing import StandardScaler
from tensorflow.keras.layers import Dense, Dropout
from sklearn.model_selection import train_test_split
from tensorflow.keras.losses import MeanSquaredLogarithmicError
TRAIN_DATA_PATH = '/content/sample_data/california_housing_train.csv'
TEST_DATA_PATH = '/content/sample_data/california_housing_test.csv'
TARGET_NAME = 'median_house_value'
train_data = pd.read_csv(TRAIN_DATA_PATH)
test_data = pd.read_csv(TEST_DATA_PATH)
x_train, y_train = train_data.drop(TARGET_NAME, axis=1), train_data[TARGET_NAME]
x_test, y_test = test_data.drop(TARGET_NAME, axis=1), test_data[TARGET_NAME]
def scale_datasets(x_train, x_test):
standard_scaler = MinMaxScaler()
x_train_scaled = pd.DataFrame(standard_scaler.fit_transform(x_train), columns=x_train.columns)
x_test_scaled = pd.DataFrame(standard_scaler.transform(x_test), columns=x_test.columns)
return x_train_scaled, x_test_scaled
x_train_scaled, x_test_scaled = scale_datasets(x_train, x_test)
class AutoEncoders(Model):
def __init__(self, output_units):
super().__init__()
self.encoder = Sequential([
Dense(32, activation="relu"),
Dense(16, activation="relu"),
Dense(7, activation="relu")
])
self.decoder = Sequential([
Dense(16, activation="relu"),
Dense(32, activation="relu"),
Dense(output_units, activation="sigmoid")
])
def call(self, inputs):
encoded = self.encoder(inputs)
decoded = self.decoder(encoded)
return decoded
auto_encoder = AutoEncoders(len(x_train_scaled.columns))
auto_encoder.compile(loss='mae', metrics=['mae'], optimizer='adam')
history = auto_encoder.fit(x_train_scaled, x_train_scaled, epochs=15, batch_size=32, validation_data=(x_test_scaled, x_test_scaled))
encoder_layer = auto_encoder.get_layer('sequential')
reduced_df = pd.DataFrame(encoder_layer.predict(x_train_scaled))
reduced_df = reduced_df.add_prefix('feature_')