我已经构建了一个增量学习模型,但不确定它是否正确。我有两组训练数据,第一组包含20000行,第二组包含10000行,两者都有两个列:描述和ID…在离线学习的情况下,我的模型运行良好,能够为给定的描述正确分类ID…datafile_train是第一组训练数据,datafile_train1是第二组训练数据。我使用SGDClassifier和partial_fit方法进行增量学习
1) Countvectorizer、tfidf和partial_fit
vectorizer = CountVectorizer()tfidf_transformer = TfidfTransformer()X_train = vectorizer.fit_transform(datafile_train.loc[:,'description'])X_train_tfidf = tfidf_transformer.fit_transform(X_train)clf = linear_model.SGDClassifier(penalty='l2',loss='hinge')prd=clf.partial_fit(X_train_tfidf, datafile_train.loc[:,'taxonomy_id'],classes=np.unique(datafile_train.loc[:,'taxonomy_id']))
之后,我将分类器序列化并再次反序列化以用于下一次partial_fit进行增量学习
2) 分类器的序列化和反序列化
def store(prd): import pickle filename = "incremental" f = open(filename, 'wb') pickle.dump(prd, f) f.close()store(prd)def train_data(): import pickle f = open('incremental', 'rb') classifier = pickle.load(f) f.close() return classifier clfp=train_data()
3) 再次对新数据使用Countvectorizer、tfidf和partial_fit
vectorizer = CountVectorizer()tfidf_transformer = TfidfTransformer()X_train1 = vectorizer.fit_transform(datafile_train1.loc[:,'description'])X_train_tfidf1 = tfidf_transformer.fit_transform(X_train1)prd1=clfp.partial_fit(X_train_tfidf1, datafile_train1.loc[:,'taxonomy_id'])# 这里的clfp是之前训练过的数据,已经反序列化
我按照这种方式构建了模型,但当我检查第一个训练数据的序列化文件大小时,它是5 MB,当我使用这个模型来训练新数据时,如您在第二个partial_fit中看到的,我使用了clfp(大小为5 MB),在训练新数据后,当我为第二个partial_fit序列化训练文件时,它也显示只有5 MB大小,因为我在之前训练的数据上训练了新数据,所以它应该得到更新。这是否是实现增量/在线学习的正确方法?请帮助我,我是机器学习的新手,所以如果您能用代码解释会更好
并且抛出了这个错误
ValueError: Number of features 125897 does not match previous data 124454.
****编辑(使用Hashingvectorizer)
hashing = HashingVectorizer()X_train_hashing=hashing.fit_transform(datafile_train.loc[:,'description'])clf = linear_model.SGDClassifier(penalty='l2',loss='hinge')prd=clf.partial_fit(X_train_hashing, datafile_train.loc[:,'taxonomy_id'],classes=np.unique(datafile_train.loc[:,'taxonomy_id']))def store(prd): import pickle filename = "inc" f = open(filename, 'wb') pickle.dump(prd, f) f.close()store(prd)def train_data(): import pickle f = open('inc', 'rb') classifier = pickle.load(f) f.close() return classifier clfp=train_data()
现在我使用clfp训练模型进行下一次partial_fit
X_train_hashing1=hashing.transform(datafile_train1.loc[:,'description'])prd1=clfp.partial_fit(X_train_hashing1, datafile_train1.loc[:,'taxonomy_id'])def store(prd1): import pickle timestr = time.strftime("%Y%m%d-%H%M%S") filename = "Train-" + timestr +".pickle" f = open(filename, 'wb') pickle.dump(prd1, f) f.close()store(prd1)
在这一次编辑中,没有出现任何错误,但两个序列化文件的大小都是25.2 MB,但第二个序列化文件的大小应该大于第一个序列化文件,因为我在新数据上使用了第一个训练模型
回答:
我认为保存的模型大小不应该增加很多,或者可能根本不会增加。
模型不会存储发送到partial_fit()
的整个新数据,只会根据这些数据更新其属性。这些属性一旦根据它们的类型(如float32, float64
等)分配了存储空间,无论它们的值如何,都会占据相同的空间。
在SGDClassifier中会发生变化的显著属性包括:
coef_ : 数组,形状为(1, n_features) 如果n_classes == 2 否则为(n_classes, n_features) 分配给特征的权重。
intercept_ : 数组,形状为(1,) 如果n_classes == 2 否则为(n_classes,) 决策函数中的常数项。
所以当您初始化模型时,这些属性要么未分配,要么全部初始化为0。一旦您将第一组数据传递给partial_fit()
,这些值会根据数据更新,试图最小化预测的损失。
当您传递新数据时,这些值再次更新,但它们仍然占据与其类型(如float32, float64
等)指定的相同存储空间。
所以这就是保存的模型大小没有变化的原因。