【翻译自 : How to Update Neural Network Models With More Data】
【说明:Jason Brownlee PhD大神的文章个人很喜欢,所以闲暇时间里会做一点翻译和学习实践的工作,这里是相应工作的实践记录,希望能帮到有需要的人!】
用于预测建模的深度学习神经网络模型可能需要更新。
这可能是因为自开发和部署模型以来数据已发生更改,或者可能是自开发模型以来已提供了附加标签数据的情况,并且预计这些附加数据将改善模型的性能。 。在为新数据更新神经网络模型时,特别是如果模型更新将自动执行(例如按定期时间表)时,使用多种不同方法进行实验和评估非常重要。有两种更新神经网络模型的方法,尽管两种主要方法涉及以现有模型为起点并对其进行重新训练,或者使现有模型保持不变并将现有模型的预测与新模型相结合。
在本教程中,您将发现如何响应新数据来更新深度学习神经网络模型。完成本教程后,您将知道:
当基础数据发生更改或新的标记数据可用时,可能需要更新神经网络模型。
如何仅使用新数据或旧数据与新数据的组合来更新经过训练的神经网络模型。
如何创建仅对新数据或旧数据和新数据的组合进行训练的现有模型和新模型的集合。
教程概述
本教程分为三个部分:他们是:
更新神经网络模型
重新训练更新策略
仅在新数据上更新模型
旧数据和新数据的更新模型
集成更新策略
仅在新数据上将模型与模型集成
将模型与新旧数据结合起来
更新神经网络模型
为预测建模项目选择和完成深度学习神经网络模型仅仅是个开始。然后,您可以开始使用模型对新数据进行预测。您可能遇到的一个可能的问题是,预测问题的性质可能会随着时间而改变。您可能会注意到以下事实,即预测的有效性可能会随着时间的流逝而开始下降。这可能是因为模型中做出和捕获的假设正在更改或不再成立。通常,这被称为“概念漂移”问题,其中变量的潜在概率分布以及变量之间的关系会随时间变化,这可能会对从数据构建的模型产生负面影响。
有关概念漂移的更多信息,请参见教程:
机器学习概念漂移的通俗介绍
概念漂移可能会在不同时间影响您的模型,并且具体取决于您要解决的预测问题以及为解决该问题而选择的模型。监视一段时间后模型的性能,并使用模型性能的明显下降作为触发来对模型进行更改,例如对新数据进行重新训练,可能会有所帮助。或者,您可能知道域中的数据变化频繁,因此需要定期(例如每周,每月或每年)更改模型。最后,您可能需要一段时间操作模型,并积累具有已知结果的其他数据,这些数据希望用于更新模型,以期改善预测性能。
重要的是,在响应问题更改或新数据的可用性时,您具有很大的灵活性。例如,您可以采用经过训练的神经网络模型,并使用新数据更新模型权重。或者,我们可能希望保持现有模型不变,并将其预测与适合新近可用数据的新模型结合起来。这些方法可能代表响应新数据而更新神经网络模型的两个通用主题,它们是:
重新训练更新策略。
集成更新策略。
重新训练更新策略
神经网络模型的一个优点是可以通过持续训练随时更新其权重。在响应基础数据的更改或新数据的可用性时,在更新神经网络模型时有几种不同的策略可供选择,例如:
继续仅在新数据上训练模型。
继续在旧数据和新数据上训练模型。
我们可能还会想象上述策略的各种变化,例如使用新数据的样本或新旧数据的样本而不是所有可用数据,以及对采样数据的基于实例的加权。我们可能还会考虑扩展模型,以冻结现有模型的各层(例如,使模型权重在训练期间无法更改),然后添加具有可更改模型权重的新层,将其嫁接到模型的扩展上以处理模型中的任何更改。数据。也许这是下一部分中再训练和整体方法的变体,我们现在将其保留。尽管如此,这是要考虑的两个主要策略。
让我们以一个可行的例子来具体说明这些方法。
仅在新数据上更新模型
我们只能在新数据上更新模型。这种方法的一个极端版本是不使用任何新数据,而只是在旧数据上重新训练模型。这可能与响应新数据时“不执行任何操作”相同。在另一个极端,模型只能适合新数据,而丢弃旧数据和旧模型。
忽略新数据,什么也不做。
根据新数据更新现有模型。
使新模型适合新数据,丢弃旧模型和数据。
在此示例中,我们将重点放在中间立场,但是对您的问题测试所有三种方法并查看哪种方法最有效可能会很有趣。首先,我们可以定义一个合成的二进制分类数据集并将其分成两半,然后将一部分用作“旧数据”,将另一部分用作“新数据”。
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1)
# record the number of input features in the data
n_features = X.shape[1]
# split into old and new data
X_old, X_new, y_old, y_new = train_test_split(X, y, test_size=0.50, random_state=1)
然后,我们可以定义一个多层感知器模型(MLP),并将其仅适合旧数据。
# define the model
model = Sequential()
model.add(Dense(20, kernel_initializer='he_normal', activation='relu', input_dim=n_features))
model.add(Dense(10, kernel_initializer='he_normal', activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# define the optimization algorithm
opt = SGD(learning_rate=0.01, momentum=0.9)
# compile the model
model.compile(optimizer=opt, loss='binary_crossentropy')
# fit the model on old data
model.fit(X_old, y_old, epochs=150, batch_size=32, verbose=0)
然后我们可以想象保存模型并使用一段时间。时间在流逝,我们希望根据可用的新数据对其进行更新。这将涉及使用比正常情况小的得多的学习率,以便我们不会冲走从旧数据中学到的权重。
注意:您将需要发现适合于您的模型和数据集的学习率,而不是简单地从头开始安装新模型,该学习率可以获得更好的性能。
# update model on new data only with a smaller learning rate
opt = SGD(learning_rate=0.001, momentum=0.9)
# compile the model
model.compile(optimizer=opt, loss='binary_crossentropy')
然后,我们只能以较小的学习率将模型拟合到新数据上。
model.compile(optimizer=opt, loss='binary_crossentropy')
# fit the model on new data
model.fit(X_new, y_new, epochs=100, batch_size=32, verbose=0)
结合在一起,下面列出了仅在新数据上更新神经网络模型的完整示例。
# update neural network with new data only
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import SGD
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1)
# record the number of input features in the data
n_features = X.shape[1]
# split into old and new data
X_old, X_new, y_old, y_new = train_test_split(X, y, test_size=0.50, random_state=1)
# define the model
model = Sequential()
model.add(Dense(20, kernel_initializer='he_normal', activation='relu', input_dim=n_features))
model.add(Dense(10, kernel_initializer='he_normal', activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# define the optimization algorithm
opt = SGD(learning_rate=0.01, momentum=0.9)
# compile the model
model.compile(optimizer=opt, loss='binary_crossentropy')
# fit the model on old data
model.fit(X_old, y_old, epochs=150, batch_size=32, verbose=0)
# save model...
# load model...
# update model on new data only with a smaller learning rate
opt = SGD(learning_rate=0.001, momentum=0.9)
# compile the model
model.compile(optimizer=opt, loss='binary_crossentropy')
# fit the model on new data
model.fit(X_new, y_new, epochs=100, batch_size=32, verbose=0)
接下来,让我们看看根据新旧数据更新模型。
旧数据和新数据的更新模型
我们可以结合新旧数据来更新模型。这种方法的一个极端版本是丢弃模型,并简单地将新模型适合所有新旧数据。 一个不太极端的版本是将现有模型用作起点,并根据合并的数据集对其进行更新。
同样,最好同时测试这两种策略并查看对您的数据集有效的方法。在这种情况下,我们将专注于不太极端的更新策略。综合数据集和模型可以像以前一样适合旧数据集。
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1)
# record the number of input features in the data
n_features = X.shape[1]
# split into old and new data
X_old, X_new, y_old, y_new = train_test_split(X, y, test_size=0.50, random_state=1)
# define the model
model = Sequential()
model.add(Dense(20, kernel_initializer='he_normal', activation='relu', input_dim=n_features))
model.add(Dense(10, kernel_initializer='he_normal', activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# define the optimization algorithm
opt = SGD(learning_rate=0.01, momentum=0.9)
# compile the model
model.compile(optimizer=opt, loss='binary_crossentropy')
# fit the model on old data
model.fit(X_old, y_old, epochs=150, batch_size=32, verbose=0)
新数据可用,我们希望结合新旧数据对模型进行更新。
首先,我们必须使用较小的学习率,以尝试将当前权重用作搜索的起点。
注意:您将需要发现适合于您的模型和数据集的学习率,而不是简单地从头开始安装新模型,该学习率可以获得更好的性能。
# update model with a smaller learning rate
opt = SGD(learning_rate=0.001, momentum=0.9)
# compile the model
model.compile(optimizer=opt, loss='binary_crossentropy')
然后,我们可以创建一个由新旧数据组成的复合数据集。
# create a composite dataset of old and new data
X_both, y_both = vstack((X_old, X_new)), hstack((y_old, y_new))
最后,我们可以在此复合数据集上更新模型。
# fit the model on new data
model.fit(X_both, y_both, epochs=100, batch_size=32, verbose=0)
结合在一起,下面列出了在旧数据和新数据上更新神经网络模型的完整示例。
# update neural network with both old and new data
from numpy import vstack
from numpy import hstack
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import SGD
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1)
# record the number of input features in the data
n_features = X.shape[1]
# split into old and new data
X_old, X_new, y_old, y_new = train_test_split(X, y, test_size=0.50, random_state=1)
# define the model
model = Sequential()
model.add(Dense(20, kernel_initializer='he_normal', activation='relu', input_dim=n_features))
model.add(Dense(10, kernel_initializer='he_normal', activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# define the optimization algorithm
opt = SGD(learning_rate=0.01, momentum=0.9)
# compile the model
model.compile(optimizer=opt, loss='binary_crossentropy')
# fit the model on old data
model.fit(X_old, y_old, epochs=150, batch_size=32, verbose=0)
# save model...
# load model...
# update model with a smaller learning rate
opt = SGD(learning_rate=0.001, momentum=0.9)
# compile the model
model.compile(optimizer=opt, loss='binary_crossentropy')
# create a composite dataset of old and new data
X_both, y_both = vstack((X_old, X_new)), hstack((y_old, y_new))
# fit the model on new data
model.fit(X_both, y_both, epochs=100, batch_size=32, verbose=0)
接下来,让我们看看如何使用集成模型来响应新数据。
集成更新策略
集成是由多个其他模型组成的预测模型。有多种不同类型的集成模型,尽管也许最简单的方法是对来自多个不同模型的预测求平均。
有关深度学习神经网络的集成算法的更多信息,请参见教程:
深度学习神经网络的集成学习方法
在响应基础数据的更改或新数据的可用性时,我们可以将集成模型用作策略。与上一节中的方法类似,我们可以考虑将集成学习算法的两种方法作为响应新数据的策略;他们是:
现有模型和新模型的集合仅适用于新数据。
现有模型和新模型的集合适合于新旧数据。
同样,我们可能会考虑这些方法的变体,例如旧数据和新数据的样本,以及集成中包含的一个以上现有模型或其他模型。尽管如此,这是要考虑的两个主要策略。让我们以一个可行的例子来具体说明这些方法。
仅在新数据上将模型与模型集成
我们可以创建现有模型的集合,而新模型仅适用于新数据。期望与单独使用旧模型或新模型相比,集成预测的性能更好或更稳定(方差更低)。在采用集成之前,应先对您的数据集进行检查。首先,我们可以准备数据集并拟合旧模型,就像在前面的部分中所做的那样。
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1)
# record the number of input features in the data
n_features = X.shape[1]
# split into old and new data
X_old, X_new, y_old, y_new = train_test_split(X, y, test_size=0.50, random_state=1)
# define the old model
old_model = Sequential()
old_model.add(Dense(20, kernel_initializer='he_normal', activation='relu', input_dim=n_features))
old_model.add(Dense(10, kernel_initializer='he_normal', activation='relu'))
old_model.add(Dense(1, activation='sigmoid'))
# define the optimization algorithm
opt = SGD(learning_rate=0.01, momentum=0.9)
# compile the model
old_model.compile(optimizer=opt, loss='binary_crossentropy')
# fit the model on old data
old_model.fit(X_old, y_old, epochs=150, batch_size=32, verbose=0)
一段时间过去了,新数据可用了。
然后,我们可以在新数据上拟合新模型,自然地发现仅在新数据集上运行良好或最佳的模型和配置。
在这种情况下,我们将仅使用与旧模型相同的模型架构和配置。
# define the new model
new_model = Sequential()
new_model.add(Dense(20, kernel_initializer='he_normal', activation='relu', input_dim=n_features))
new_model.add(Dense(10, kernel_initializer='he_normal', activation='relu'))
new_model.add(Dense(1, activation='sigmoid'))
# define the optimization algorithm
opt = SGD(learning_rate=0.01, momentum=0.9)
# compile the model
new_model.compile(optimizer=opt, loss='binary_crossentropy')
然后,我们可以将此新模型仅适用于新数据。
# fit the model on old data
new_model.fit(X_new, y_new, epochs=150, batch_size=32, verbose=0)
现在我们有了两个模型,我们可以对每个模型进行预测,并将预测的平均值计算为“整体预测”。
# make predictions with both models
yhat1 = old_model.predict(X_new)
yhat2 = new_model.predict(X_new)
# combine predictions into single array
combined = hstack((yhat1, yhat2))
# calculate outcome as mean of predictions
yhat = mean(combined, axis=-1)
综上所述,下面列出了使用现有模型的集成和仅适用于新数据的新模型进行更新的完整示例。
# ensemble old neural network with new model fit on new data only
from numpy import hstack
from numpy import mean
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import SGD
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1)
# record the number of input features in the data
n_features = X.shape[1]
# split into old and new data
X_old, X_new, y_old, y_new = train_test_split(X, y, test_size=0.50, random_state=1)
# define the old model
old_model = Sequential()
old_model.add(Dense(20, kernel_initializer='he_normal', activation='relu', input_dim=n_features))
old_model.add(Dense(10, kernel_initializer='he_normal', activation='relu'))
old_model.add(Dense(1, activation='sigmoid'))
# define the optimization algorithm
opt = SGD(learning_rate=0.01, momentum=0.9)
# compile the model
old_model.compile(optimizer=opt, loss='binary_crossentropy')
# fit the model on old data
old_model.fit(X_old, y_old, epochs=150, batch_size=32, verbose=0)
# save model...
# load model...
# define the new model
new_model = Sequential()
new_model.add(Dense(20, kernel_initializer='he_normal', activation='relu', input_dim=n_features))
new_model.add(Dense(10, kernel_initializer='he_normal', activation='relu'))
new_model.add(Dense(1, activation='sigmoid'))
# define the optimization algorithm
opt = SGD(learning_rate=0.01, momentum=0.9)
# compile the model
new_model.compile(optimizer=opt, loss='binary_crossentropy')
# fit the model on old data
new_model.fit(X_new, y_new, epochs=150, batch_size=32, verbose=0)
# make predictions with both models
yhat1 = old_model.predict(X_new)
yhat2 = new_model.predict(X_new)
# combine predictions into single array
combined = hstack((yhat1, yhat2))
# calculate outcome as mean of predictions
yhat = mean(combined, axis=-1)
将模型与新旧数据结合起来
我们可以创建一个既有模型又可以同时适合新旧数据的新模型的集合。期望与单独使用旧模型或新模型相比,集成预测的性能更好或更稳定(方差更低)。 在采用集成之前,应先对您的数据集进行检查。首先,我们可以准备数据集并拟合旧模型,就像在前面的部分中所做的那样。
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1)
# record the number of input features in the data
n_features = X.shape[1]
# split into old and new data
X_old, X_new, y_old, y_new = train_test_split(X, y, test_size=0.50, random_state=1)
# define the old model
old_model = Sequential()
old_model.add(Dense(20, kernel_initializer='he_normal', activation='relu', input_dim=n_features))
old_model.add(Dense(10, kernel_initializer='he_normal', activation='relu'))
old_model.add(Dense(1, activation='sigmoid'))
# define the optimization algorithm
opt = SGD(learning_rate=0.01, momentum=0.9)
# compile the model
old_model.compile(optimizer=opt, loss='binary_crossentropy')
# fit the model on old data
old_model.fit(X_old, y_old, epochs=150, batch_size=32, verbose=0)
一段时间过去了,新数据可用了。然后,我们可以在新旧数据的组合上拟合新模型,从而自然地发现仅在新数据集上运行良好或最佳的模型和配置。在这种情况下,我们将仅使用与旧模型相同的模型架构和配置。
# define the new model
new_model = Sequential()
new_model.add(Dense(20, kernel_initializer='he_normal', activation='relu', input_dim=n_features))
new_model.add(Dense(10, kernel_initializer='he_normal', activation='relu'))
new_model.add(Dense(1, activation='sigmoid'))
# define the optimization algorithm
opt = SGD(learning_rate=0.01, momentum=0.9)
# compile the model
new_model.compile(optimizer=opt, loss='binary_crossentropy')
我们可以根据新旧数据创建一个复合数据集,然后在该数据集上拟合新模型。
# create a composite dataset of old and new data
X_both, y_both = vstack((X_old, X_new)), hstack((y_old, y_new))
# fit the model on old data
new_model.fit(X_both, y_both, epochs=150, batch_size=32, verbose=0)
最后,我们可以将两个模型一起使用来进行整体预测。
# make predictions with both models
yhat1 = old_model.predict(X_new)
yhat2 = new_model.predict(X_new)
# combine predictions into single array
combined = hstack((yhat1, yhat2))
# calculate outcome as mean of predictions
yhat = mean(combined, axis=-1)
结合在一起,下面列出了使用现有模型和适合于新旧数据的新模型进行集成的完整示例。
# ensemble old neural network with new model fit on old and new data
from numpy import hstack
from numpy import vstack
from numpy import mean
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import SGD
# define dataset
X, y = make_classification(n_samples=1000, n_features=20, n_informative=15, n_redundant=5, random_state=1)
# record the number of input features in the data
n_features = X.shape[1]
# split into old and new data
X_old, X_new, y_old, y_new = train_test_split(X, y, test_size=0.50, random_state=1)
# define the old model
old_model = Sequential()
old_model.add(Dense(20, kernel_initializer='he_normal', activation='relu', input_dim=n_features))
old_model.add(Dense(10, kernel_initializer='he_normal', activation='relu'))
old_model.add(Dense(1, activation='sigmoid'))
# define the optimization algorithm
opt = SGD(learning_rate=0.01, momentum=0.9)
# compile the model
old_model.compile(optimizer=opt, loss='binary_crossentropy')
# fit the model on old data
old_model.fit(X_old, y_old, epochs=150, batch_size=32, verbose=0)
# save model...
# load model...
# define the new model
new_model = Sequential()
new_model.add(Dense(20, kernel_initializer='he_normal', activation='relu', input_dim=n_features))
new_model.add(Dense(10, kernel_initializer='he_normal', activation='relu'))
new_model.add(Dense(1, activation='sigmoid'))
# define the optimization algorithm
opt = SGD(learning_rate=0.01, momentum=0.9)
# compile the model
new_model.compile(optimizer=opt, loss='binary_crossentropy')
# create a composite dataset of old and new data
X_both, y_both = vstack((X_old, X_new)), hstack((y_old, y_new))
# fit the model on old data
new_model.fit(X_both, y_both, epochs=150, batch_size=32, verbose=0)
# make predictions with both models
yhat1 = old_model.predict(X_new)
yhat2 = new_model.predict(X_new)
# combine predictions into single array
combined = hstack((yhat1, yhat2))
# calculate outcome as mean of predictions
yhat = mean(combined, axis=-1)
进一步阅读
如果您想更深入,本节提供了有关该主题的更多资源。