增量学习的目的是不将整个训练数据保存在内存中。因此,可以在整体上不适合内存的大数据集上进行学习。如果训练数据逐个可用,增量学习也很有用。
随机梯度下降 (SGD) 不会在内存中保留任何批次,除了它正在处理的批次。但是,这并不意味着它会立即忘记过去的补丁。批次用于计算梯度,用于更新模型系数。因此,尽管数据本身被丢弃,但批次中包含的信息仍保留在模型中。
由于梯度是使用最新批次更新的,因此新批次对模型当前训练状态的影响比旧批次更大。你可以说最近的批次在模型的记忆中更加生动,而它逐渐忘记了旧的批次。
这里有一个玩具例子来说明这个问题(代码在底部):
一个 SGD 分类器在前 100 个批次中使用三个类进行增量训练。在训练数据中不存在批次 100-200 第 3 类。很明显,分类器“忘记”了它之前学到的关于这个类的一切。您可以将这种效果标记为“灾难性遗忘”,或者您可能将其视为可取的“适应数据变化”;解释取决于用例。
所以,是的,SGD 确实似乎受到catastrophic forgetting 的影响。不过,我认为这没什么大不了的。只是在特定应用程序中设计训练策略时必须注意的事项。
import numpy as np
from sklearn.linear_model import SGDClassifier
from sklearn.datasets import make_blobs
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
np.random.seed(42)
n_features = 150
centers = np.concatenate([np.eye(3)*3, np.zeros((3, n_features-3))], axis=1)
x_test, y_test = make_blobs([100, 100, 100], centers=centers)
cla = SGDClassifier()
performance = []
def train_some_batches(n_samples_per_class):
for _ in range(100):
x_batch, y_batch = make_blobs(n_samples_per_class, centers=centers)
cla.partial_fit(x_batch, y_batch, classes=[0, 1, 2])
conf = confusion_matrix(y_test, cla.predict(x_test))
performance.append(np.diag(conf) / np.sum(conf, axis=1))
train_some_batches([50, 50, 50])
train_some_batches([50, 50, 0])
plt.plot(performance)
plt.legend(['class 1', 'class 2', 'class 3'])
plt.xlabel('training batches')
plt.ylabel('accuracy')
plt.show()