
转移学习是一种在训练大型机器学习或深度学习模型时节省精力的方法。它有助于避免重复的过程,从数据中学习特征。在计算机视觉中使用了各种预训练的模型来促进转移学习。在这篇文章中,我们将学习如何在时间序列预测问题中利用转移学习,特别是当我们使用深度学习模型(如LSTM)进行预测时。我们将为一个时间序列预测任务建立一个模型,并将其作为一个预训练的模型用于不同但类似的时间序列预测应用中,而无需花费大量精力进行训练。
目录
- 什么是迁移学习?
- 建立用于时间序列预测的转移学习模型
- 使用预训练的时间序列预测模型
- 摘要
什么是迁移学习?
迁移学习是使用现成的或为类似任务训练的不同模型的预训练权重的技术之一,并在我们的任务中使用它来产生有效的结果。TensorFlow框架提供了各种转移学习模型,但有更多适合图像分类的模型。
因此,本文包括了一个如何对时间序列数据实现迁移学习技术的案例研究,其中,首先为一些数据建立一个模型,还有一个为同类数据开发的相应模型,并用于获得预测。
建立转移学习模型
因此,在本文的案例研究中,我们使用了时间序列数据,以便使用时间序列预测技术来预测家庭用电量。
最初获得的数据是文本(txt)文件的形式,这些数据使用pandas框架进行适当的预处理,以获得逗号分隔值(CSV)文件形式的文本(txt)文件,同时使用parse_date() 函数获得适合时间序列预测的数据。接下来的步骤如下所示。
df = pd.read_csv('/content/drive/MyDrive/Colab notebooks/Transfer learning with time series data/household_power_consumption.txt', sep=';',
parse_dates={'dt' : ['Date', 'Time']}, infer_datetime_format=True,
low_memory=False, na_values=['nan','?'], index_col='dt')
一旦完成了适当的预处理,使用pandas的head()函数对最初的t个观测数据进行可视化处理,如下图所示。
df.head()

因此,一旦数据被可视化,就用scikit-learn模型将数据分成训练和测试,并将20%的可用数据留作验证。以下是相同的步骤。
main,val=train_test_split(df,test_size=0.2)
这里的 "主 "数据被用来建立第一个LSTM模型。使用主数据集,数据被可视化为趋势和季节性的存在,其中某些特征被按月重新取样于各种综合参数,如总和和平均值。
如下图所示,名为GlobalActivePower的特征被重新采样为总和和平均值,以可视化分布。
main.Global_active_power.resample('D').sum().plot(title='Resampling for sum')
plt.tight_layout()
plt.show()
main.Global_active_power.resample('D').mean().plot(title='Resampling for mean', color='red')
plt.tight_layout()
plt.show()

以类似的方式,数据集的任何特征都可以进行相应的重采样,以检查各种聚合函数的分布。甚至某些特征也可以对时间序列数据的各种频率参数进行重采样。下面是一个每月对其中一个特征进行重采样并将其可视化的示例代码。
main['Voltage'].resample('M').mean().plot(kind='bar', color='red')
plt.xticks(rotation=60)
plt.ylabel('Voltage')
plt.title('Voltage per quarter (summed over quarter)')
plt.show()

因此,正如我们前面所看到的,有各种特征必须在一个共同的尺度上进行标准化。因此,为了这个目的,我们使用了scikit learn模块的min-max scaler库,并为合适的模型拟合做了适当的预处理,如下所示。
from sklearn.preprocessing import MinMaxScaler
## If you would like to train based on the resampled data (over hour), then used below
values = df_resample.values
scaler = MinMaxScaler(feature_range=(0, 1))
scaled = scaler.fit_transform(values)
reframed = series_to_supervised(scaled, 1, 1)
# drop columns we don't want to predict
reframed.drop(reframed.columns[[8,9,10,11,12,13]], axis=1, inplace=True)
print(reframed.head())
现在,对标度值进行适当的预处理,将其分成训练和测试,以方便模型的建立。所涉及的步骤如下所示。
# split into train and test sets
values = reframed.values
n_train_time = 365*24
train = values[:n_train_time, :]
test = values[n_train_time:, :]
##test = values[n_train_time:n_test_time, :]
# split into input and outputs
train_X, train_y = train[:, :-1], train[:, -1]
test_X, test_y = test[:, :-1], test[:, -1]
# reshape input to be 3D [samples, timesteps, features]
train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
# We reshaped the input into the 3D format as expected by LSTMs, namely [samples, timesteps, features].
现在,由于数据分割成功,我们继续建立模型,建立一个循环神经网络。但首先,让我们导入必要的库,如下图所示。
import tensorflow as tf
import keras
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import Sequential
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.optimizers import SGD
from tensorflow.keras.callbacks import EarlyStopping
from keras.utils import np_utils
import itertools
from tensorflow.keras.layers import LSTM
from tensorflow.keras.layers import Conv1D
from tensorflow.keras.layers import MaxPooling1D
from tensorflow.keras.layers import Dropout
因此,现在模型已经建立,其层数如下图所示。
model = Sequential()
model.add(LSTM(100, input_shape=(train_X.shape[1], train_X.shape[2])))
model.add(Dropout(0.2))
model.add(Dense(1))
现在模型被适当地编译,如下图所示,用于评估模型的指标是均方根,因为它是评估时间序列数据的一个更相关的参数。所涉及的步骤如下所示。
model.compile(loss='mean_squared_error', optimizer='adam')
现在,该模型被拟合到如下所示的分割数据上。
history = model.fit(train_X, train_y, epochs=20, batch_size=70, validation_data=(test_X, test_y), verbose=2, shuffle=False)
现在使用这个模型,让我们尝试获得预测结果,由于这个模型是为均方误差而编制的,让我们仅以同样的理由来评估这个模型。对于时间序列数据,特别是为了获得预测,我们必须对目标变量进行一些预处理,同样的步骤如下所示。
# make a prediction
ypred = model.predict(test_X)
test_X = test_X.reshape((test_X.shape[0], 7))
# invert scaling for forecasted values
inv_ypred = np.concatenate((ypred, test_X[:, -6:]), axis=1)
inv_ypred = scaler.inverse_transform(inv_ypred)
inv_ypred = inv_ypred[:,0]
# invert scaling for actual values
test_y = test_y.reshape((len(test_y), 1))
inv_yact = np.concatenate((test_y, test_X[:, -6:]), axis=1)
inv_yact = scaler.inverse_transform(inv_yact)
inv_yact = inv_yact[:,0]
# calculate RMSE
rmse = np.sqrt(mean_squared_error(inv_yact, inv_ypred))
print('Test RMSE: %.3f' % rmse)
因此,对于开发的模型,我们得到的测试RMSE 为0.622,如下图所示。
使用预训练的时间序列预测模型
现在让我们把模型的权重和参数保存为h5 格式,如下图所示。
model.save('lstm_model_new.h5')
所以现在在一个类似数据的新实例中,保存的模型可以被加载到工作环境中,如下图所示。
from tensorflow.keras.models import load_model
loaded_model=load_model('/content/lstm_model_new.h5')
加载的模型的层数可以得到如下图所示。
loaded_model.layers

如果我们记得,我们保留了一部分数据用于验证。因此,为了创建新的模型,如上所述,对验证数据进行了适当的预处理,并以类似的方式,通过冻结某些层来建立一个顺序模型,以促进迁移学习。接下来的步骤如下所示。
# extract all the layers from base model except the last layer
for layer in loaded_model.layers[:-1]:
model1.add(layer)
# Freeze all the layers of base model
for layer in loaded_model.layers:
layer.trainable=False
# adding new layers
model1.add(Dense(50,input_dim=1))
model1.add(Dropout(0.1))
model1.add(Dense(1))
因此,一旦完成了必要层的冻结,就以类似的方式编译模型,并对分割的数据进行拟合。与预训练的模型类似,model1也被评估为均方根误差,该模型显示出优异的性能,产生的结果与预训练的模型几乎相同。
新模型的均方根值为0.621。
因此,这就是我们如何对时间序列数据实施迁移学习的方法,其中类似数据的预训练模型可以用来获得更容易的预测结果。
注意
时间序列数据是非常不确定的,并且拥有各种参数,如趋势和季节性。因此,最好的做法是先将系列数据可视化,然后使用为类似数据预训练的模型。
总结
转移学习是产生有效模型的技术之一,但基本事实是,随着数据的变化,要使用的预训练模型也不同,时间序列数据包括各种技术因素,如静止性、季节性和趋势,为正确的数据类型选择正确的预训练模型变得很重要。