赞
踩
【翻译自: Autoencoder Feature Extraction for Regression】
【说明:Jason Brownlee PhD大神的文章个人很喜欢,所以闲暇时间里会做一点翻译和学习实践的工作,这里是相应工作的实践记录,希望能帮到有需要的人!】
自动编码器是一种神经网络,可用于学习原始数据的压缩表示。自动编码器由编码器和解码器子模型组成。编码器压缩输入,而解码器尝试根据编码器提供的压缩版本重新创建输入。训练后,将保存编码器模型,并丢弃解码器。然后,编码器可用作数据准备技术,对原始数据执行特征提取,以用于训练不同的机器学习模型。
在本教程中,您将发现如何开发和评估用于回归预测的自动编码器,完成本教程后,您将知道:
- 自动编码器是一种神经网络模型,可用于学习原始数据的压缩表示。
- 如何在训练数据集上训练自动编码器模型,并仅保存模型的编码器部分。
- 训练机器学习模型时如何使用编码器作为数据准备步骤。
本教程分为三个部分: 他们是:
- 用于特征提取的自动编码器
- 回归自动编码器
- 自动编码器作为数据准备
自动编码器是一种神经网络模型,旨在学习输入的压缩表示形式。它们是一种无监督的学习方法,尽管从技术上讲,它们是使用有监督的学习方法(称为自我监督)进行训练的。 通常将它们作为尝试重新创建输入的更广泛模型的一部分进行培训。
例如:X = model.predict(X)
自动编码器模型的设计通过将体系结构限制在模型中点的瓶颈处来故意使此挑战变得困难,从该瓶颈执行输入数据的重构。自动编码器的类型很多,其用途各不相同,但也许更常见的用途是作为学习型或自动特征提取模型。在这种情况下,一旦模型适合,就可以放弃模型的重建方面,可以使用直至瓶颈的模型。 模型在瓶颈处的输出是固定长度的向量,该向量提供输入数据的压缩表示。
然后,可以将来自域的输入数据提供给模型,并且可以将瓶颈处的模型输出用作监督学习模型中的特征向量,以进行可视化,或更普遍地用于降维。接下来,让我们探讨如何针对回归预测建模问题开发用于特征提取的自动编码器。
在本节中,我们将开发一种自动编码器,以学习回归预测建模问题的输入特征的压缩表示。首先,让我们定义一个回归预测建模问题。
我们将使用make_regression()scikit-learn函数来定义具有100个输入要素(列)和1,000个示例(行)的综合回归任务。 重要的是,我们将以大多数输入变量都是冗余的(100个中的90个或90%)的方式定义问题,以便以后自动编码器可以学习有用的压缩表示形式。
下面的示例定义了数据集并总结了其形状。
- # synthetic regression dataset
- from sklearn.datasets import make_regression
- # define dataset
- X, y = make_regression(n_samples=1000, n_features=100, n_informative=10, noise=0.1, random_state=1)
- # summarize the dataset
- print(X.shape, y.shape)
运行示例将定义数据集并打印数组的形状,从而确认行数和列数。
(1000, 100) (1000,)
接下来,我们将开发一个多层感知器(MLP)自动编码器模型。该模型将采用所有输入列,然后输出相同的值。它将学习准确地重新创建输入模式。自动编码器由两部分组成:编码器和解码器。编码器学习如何解释输入并将其压缩为瓶颈层定义的内部表示。解码器获取编码器的输出(瓶颈层),并尝试重新创建输入。一旦对自动编码器进行了训练,解码将被丢弃,我们仅保留编码器并将其用于将输入示例压缩为瓶颈层输出的矢量。在第一个自动编码器中,我们将完全不压缩输入,而将使用与输入大小相同的瓶颈层。这应该是一个容易解决的问题,该模型将几乎完美地学习并旨在确认我们的模型已正确实现。
我们将使用功能性API定义模型。如果这是您的新手,我建议您学习本教程:
如何使用Keras功能API进行深度学习
在定义和拟合模型之前,我们将数据分为训练集和测试集,并通过将值归一化为0-1范围来缩放输入数据,这是MLP的一种良好做法。
- # split into train test sets
- X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)
- # scale data
- t = MinMaxScaler()
- t.fit(X_train)
- X_train = t.transform(X_train)
- X_test = t.transform(X_test)
我们将定义编码器具有一个隐藏层,该隐藏层具有与批处理归一化和ReLU激活的输入数据相同数量的节点。随后是瓶颈层,该瓶颈层的节点数与输入数据中的列数相同,例如 没有压缩。
- # define encoder
- visible = Input(shape=(n_inputs,))
- e = Dense(n_inputs*2)(visible)
- e = BatchNormalization()(e)
- e = ReLU()(e)
- # define bottleneck
- n_bottleneck = n_inputs
- bottleneck = Dense(n_bottleneck)(e)
解码器将以相同的结构定义。它将具有一层具有批处理归一化和ReLU激活的隐藏层。 输出层将具有与输入数据中的列数相同的节点数,并将使用线性激活函数输出数值。
- # define decoder
- d = Dense(n_inputs*2)(bottleneck)
- d = BatchNormalization()(d)
- d = ReLU()(d)
- # output layer
- output = Dense(n_inputs, activation='linear')(d)
- # define autoencoder model
- model = Model(inputs=visible, outputs=output)
- # compile autoencoder model
- model.compile(optimizer='adam', loss='mse')
考虑到重构是多输出回归问题的一种,该模型将使用高效的亚当版随机梯度下降法进行拟合,并最小化均方误差。
- # compile autoencoder model
- model.compile(optimizer='adam', loss='mse')
我们可以在自动编码器模型中绘制图层,以了解数据如何流过模型。
- # plot the autoencoder
- plot_model(model, 'autoencoder.png', show_shapes=True)
下图显示了自动编码器的图。
接下来,我们可以训练模型以重现输入,并在保持测试集上跟踪模型的性能。 该模型经过了400个时期的训练,批次大小为16个示例。
- # fit the autoencoder model to reconstruct input
- history = model.fit(X_train, X_train, epochs=400, batch_size=16, verbose=2, validation_data=(X_test,X_test))
训练后,我们可以绘制火车和测试集的学习曲线,以确认模型很好地学习了重建问题。
- # plot loss
- pyplot.plot(history.history['loss'], label='train')
- pyplot.plot(history.history['val_loss'], label='test')
- pyplot.legend()
- pyplot.show()
最后,如果需要,我们可以保存编码器模型供以后使用。
- # define an encoder model (without the decoder)
- encoder = Model(inputs=visible, outputs=bottleneck)
- plot_model(encoder, 'encoder.png', show_shapes=True)
- # save the encoder to file
- encoder.save('encoder.h5')
作为保存编码器的一部分,我们还将绘制模型以获取瓶颈层输出形状的感觉,例如 100个元素的向量。下面提供了该图的示例。
综上所述,下面列出了一个自动编码器的完整示例,该示例可用于重构回归数据集的输入数据,而无需在瓶颈层进行任何压缩。
- # train autoencoder for regression with no compression in the bottleneck layer
- from sklearn.datasets import make_regression
- from sklearn.preprocessing import MinMaxScaler
- from sklearn.model_selection import train_test_split
- from tensorflow.keras.models import Model
- from tensorflow.keras.layers import Input
- from tensorflow.keras.layers import Dense
- from tensorflow.keras.layers import ReLU
- from tensorflow.keras.layers import BatchNormalization
- from tensorflow.keras.utils import plot_model
- from matplotlib import pyplot
- # define dataset
- X, y = make_regression(n_samples=1000, n_features=100, n_informative=10, noise=0.1, random_state=1)
- # number of input columns
- n_inputs = X.shape[1]
- # split into train test sets
- X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)
- # scale data
- t = MinMaxScaler()
- t.fit(X_train)
- X_train = t.transform(X_train)
- X_test = t.transform(X_test)
- # define encoder
- visible = Input(shape=(n_inputs,))
- e = Dense(n_inputs*2)(visible)
- e = BatchNormalization()(e)
- e = ReLU()(e)
- # define bottleneck
- n_bottleneck = n_inputs
- bottleneck = Dense(n_bottleneck)(e)
- # define decoder
- d = Dense(n_inputs*2)(bottleneck)
- d = BatchNormalization()(d)
- d = ReLU()(d)
- # output layer
- output = Dense(n_inputs, activation='linear')(d)
- # define autoencoder model
- model = Model(inputs=visible, outputs=output)
- # compile autoencoder model
- model.compile(optimizer='adam', loss='mse')
- # plot the autoencoder
- plot_model(model, 'autoencoder.png', show_shapes=True)
- # fit the autoencoder model to reconstruct input
- history = model.fit(X_train, X_train, epochs=400, batch_size=16, verbose=2, validation_data=(X_test,X_test))
- # plot loss
- pyplot.plot(history.history['loss'], label='train')
- pyplot.plot(history.history['val_loss'], label='test')
- pyplot.legend()
- pyplot.show()
- # define an encoder model (without the decoder)
- encoder = Model(inputs=visible, outputs=bottleneck)
- plot_model(encoder, 'encoder.png', show_shapes=True)
- # save the encoder to file
- encoder.save('encoder.h5')

运行示例符合模型,并报告沿途训练和测试集上的损失。
注意:如果在创建模型图时遇到问题,可以注释掉导入并调用plot_model()函数。
注意:由于算法或评估程序的随机性,或者数值精度的差异,您的结果可能会有所不同。 考虑运行该示例几次并比较平均结果。
在这种情况下,我们看到损失变低了,但并没有达到零(正如我们可能预期的那样),而瓶颈层没有压缩。 也许需要进一步调整模型架构或学习超参数。
- Epoch 393/400
- 42/42 - 0s - loss: 0.0025 - val_loss: 0.0024
- Epoch 394/400
- 42/42 - 0s - loss: 0.0025 - val_loss: 0.0021
- Epoch 395/400
- 42/42 - 0s - loss: 0.0023 - val_loss: 0.0021
- Epoch 396/400
- 42/42 - 0s - loss: 0.0025 - val_loss: 0.0023
- Epoch 397/400
- 42/42 - 0s - loss: 0.0024 - val_loss: 0.0022
- Epoch 398/400
- 42/42 - 0s - loss: 0.0025 - val_loss: 0.0021
- Epoch 399/400
- 42/42 - 0s - loss: 0.0026 - val_loss: 0.0022
- Epoch 400/400
- 42/42 - 0s - loss: 0.0025 - val_loss: 0.0024

创建了一条学习曲线图,表明该模型在重构输入时取得了很好的拟合,在整个训练过程中保持稳定,而不是过度拟合。
到现在为止还挺好。 我们知道如何开发无压缩的自动编码器。经过训练的编码器将保存到文件“ encoder.h5”中,我们以后可以加载和使用。接下来,让我们探讨如何使用训练有素的编码器模型。
在本节中,我们将使用自动编码器模型中训练有素的编码器模型来压缩输入数据并训练不同的预测模型。首先,让我们为该问题建立性能基准。 这很重要,因为如果压缩编码不能提高模型的性能,那么压缩编码不会为项目增加价值,因此不应使用。我们可以直接在训练数据集上训练支持向量回归(SVR)模型,并在保留测试集上评估模型的性能。优良作法是,在拟合和评估模型之前,我们将同时缩放输入变量和目标变量。
下面列出了完整的示例。
- # baseline in performance with support vector regression model
- from sklearn.datasets import make_regression
- from sklearn.preprocessing import MinMaxScaler
- from sklearn.model_selection import train_test_split
- from sklearn.svm import SVR
- from sklearn.metrics import mean_absolute_error
- # define dataset
- X, y = make_regression(n_samples=1000, n_features=100, n_informative=10, noise=0.1, random_state=1)
- # split into train test sets
- X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)
- # reshape target variables so that we can transform them
- y_train = y_train.reshape((len(y_train), 1))
- y_test = y_test.reshape((len(y_test), 1))
- # scale input data
- trans_in = MinMaxScaler()
- trans_in.fit(X_train)
- X_train = trans_in.transform(X_train)
- X_test = trans_in.transform(X_test)
- # scale output data
- trans_out = MinMaxScaler()
- trans_out.fit(y_train)
- y_train = trans_out.transform(y_train)
- y_test = trans_out.transform(y_test)
- # define model
- model = SVR()
- # fit model on the training dataset
- model.fit(X_train, y_train)
- # make prediction on test set
- yhat = model.predict(X_test)
- # invert transforms so we can calculate errors
- yhat = yhat.reshape((len(yhat), 1))
- yhat = trans_out.inverse_transform(yhat)
- y_test = trans_out.inverse_transform(y_test)
- # calculate error
- score = mean_absolute_error(y_test, yhat)
- print(score)

运行示例将SVR模型拟合到训练数据集上,并在测试集上对其进行评估。
注意:由于算法或评估程序的随机性,或者数值精度的差异,您的结果可能会有所不同。 考虑运行该示例几次并比较平均结果。
在这种情况下,我们可以看到该模型实现了约89的平均绝对误差(MAE)。我们希望并期望SVR模型适合输入的编码版本,以实现较低的误差,从而使编码被认为有用。
89.51082036130629
我们可以更新示例,以使用上一节中训练的编码器模型首先对数据进行编码。首先,我们可以从文件中加载经过训练的编码器模型。
- # load the model from file
- encoder = load_model('encoder.h5')
然后,我们可以使用编码器将原始输入数据(例如100列)转换为瓶颈向量(例如100个元素向量)。该过程可以应用于训练和测试数据集。
- # encode the train data
- X_train_encode = encoder.predict(X_train)
- # encode the test data
- X_test_encode = encoder.predict(X_test)
然后,我们可以像以前一样使用此编码数据来训练和评估SVR模型。
- # define model
- model = SVR()
- # fit model on the training dataset
- model.fit(X_train_encode, y_train)
- # make prediction on test set
- yhat = model.predict(X_test_encode)
完整实例如下:
- # support vector regression performance with encoded input
- from sklearn.datasets import make_regression
- from sklearn.preprocessing import MinMaxScaler
- from sklearn.model_selection import train_test_split
- from sklearn.svm import SVR
- from sklearn.metrics import mean_absolute_error
- from tensorflow.keras.models import load_model
- # define dataset
- X, y = make_regression(n_samples=1000, n_features=100, n_informative=10, noise=0.1, random_state=1)
- # split into train test sets
- X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)
- # reshape target variables so that we can transform them
- y_train = y_train.reshape((len(y_train), 1))
- y_test = y_test.reshape((len(y_test), 1))
- # scale input data
- trans_in = MinMaxScaler()
- trans_in.fit(X_train)
- X_train = trans_in.transform(X_train)
- X_test = trans_in.transform(X_test)
- # scale output data
- trans_out = MinMaxScaler()
- trans_out.fit(y_train)
- y_train = trans_out.transform(y_train)
- y_test = trans_out.transform(y_test)
- # load the model from file
- encoder = load_model('encoder.h5')
- # encode the train data
- X_train_encode = encoder.predict(X_train)
- # encode the test data
- X_test_encode = encoder.predict(X_test)
- # define model
- model = SVR()
- # fit model on the training dataset
- model.fit(X_train_encode, y_train)
- # make prediction on test set
- yhat = model.predict(X_test_encode)
- # invert transforms so we can calculate errors
- yhat = yhat.reshape((len(yhat), 1))
- yhat = trans_out.inverse_transform(yhat)
- y_test = trans_out.inverse_transform(y_test)
- # calculate error
- score = mean_absolute_error(y_test, yhat)
- print(score)

运行示例首先使用编码器对数据集进行编码,然后将SVR模型拟合到训练数据集上并在测试集上进行评估。
注意:由于算法或评估程序的随机性,或者数值精度的差异,您的结果可能会有所不同。 考虑运行该示例几次并比较平均结果。
在这种情况下,我们可以看到该模型实现了大约69的MAE。
这比在原始数据集上评估的同一模型更好的MAE,这表明编码对于我们选择的模型和测试工具很有帮助。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。