更新Python Pickle对象

5

我正在进行一个机器学习项目,为此我正在使用Python的pickle模块。

基本上,我正在解析一个庞大的数据集,这在一次执行中是不可能完成的,因此我需要保存分类器对象并在下一次执行中更新它。

所以我的问题是,当我再次运行程序并使用新的数据集时,已经创建的pickle对象是否会被修改(或更新)。如果没有,那么我如何在每次运行程序时更新相同的pickle对象。

save_classifier = open("naivebayes.pickle","wb")
pickle.dump(classifier,save_classifier)
save_classifier.close()

2
什么都不会自动发生。您下一次运行程序需要打开文件,将pickle加载回正常的Python对象中,修改该对象,然后再像上面那样保存它。 - Kirk Strauser
@KirkStrauser,这就是我所说的。我应该像现在这样保留我的代码,对吧?下一次运行时,已经创建的naivebayes.pickle会被更新,对吗? - arqam
分类器是否适应内存而不影响其他计算? - sobek
@sobek 我并不是一次性处理所有完整的数据集,所以才能够适应。我正在将数据集分成若干子集,然后训练分类器对象以修改它。 - arqam
@sobek 但是机器学习的基础不是我们创建一个经过充分训练并可在任何地方使用的分类器吗?我唯一看到的保存分类器对象并进行更新的方法就是使用pickle。如果您知道其他方法,请告诉我。 - arqam
显示剩余2条评论
1个回答

3
将您的分类器对象解封将重新创建与封装时相同状态的对象,这样您就可以继续使用来自数据集的新鲜数据进行更新。在程序运行结束时,再次对分类器进行封装并保存到文件中是个好主意。最好不要覆盖同一文件,而是保留备份(甚至更好地,一系列备份),以防万一出了问题。这样,您可以轻松回到已知良好状态的分类器
应该使用一个简单的程序和一个简单的对象进行封装和解封的实验,直到您完全自信掌握了所有原理。
下面是如何更新封装的分类器数据的草图。
import pickle
import os
from os.path import exists
# other imports required for nltk ...

picklename = "naivebayes.pickle"

# stuff to set up featuresets ...

featuresets = [(find_features(rev), category) for (rev, category) in documents]
numtrain = int(len(documents) * 90 / 100)
training_set = featuresets[:numtrain]
testing_set = featuresets[numtrain:]

# Load or create a classifier and apply training set to it
if exists(picklename):
    # Update existing classifier
    with open(picklename, "rb") as f:
        classifier = pickle.load(f)
    classifier.train(training_set)
else:
    # Create a brand new classifier    
    classifier = nltk.NaiveBayesClassifier.train(training_set)

# Create backup
if exists(picklename):
    backupname = picklename + '.bak'
    if exists(backupname):
        os.remove(backupname)
    os.rename(picklename, backupname)

# Save
with open(picklename, "wb") as f:
    pickle.dump(classifier, f)

第一次运行此程序将创建一个新的分类器,使用training_set中的数据进行训练,然后将分类器储存为“naivebayes.pickle”。每次运行此程序时,它都会加载旧的分类器并向其应用更多的训练数据。
另外,如果您正在使用Python 2,则应该使用更快的cPickle模块;您可以通过替换...(无法翻译完整内容,请提供完整文本)
import pickle 

使用

import cPickle as pickle

1
@Arqam:取决于您在保存分类器时是否指定不同的文件名。每次都使用相同的名称,它将在重写文件时有效地删除之前的版本。 - martineau
@PM2Ring但是如果我有很多文件,我只能加载一个文件,对吗?使用pickle.load()。那么我该如何使用为分类创建的所有这些文件呢? - arqam
@Arqam:通常情况下,您只需加载最新的pickle文件,即编号最大的文件。但是,如果您在训练过程中犯了错误,那么您可以告诉程序加载早期版本的文件。 - PM 2Ring
@PM2Ring,你能来聊天吗? - arqam
@PM2Ring 不,我只是通过执行 open(picklename,"ab") 得到了结果,所以我想 pickle 文件确实被更新了。当我使用上述命令时,pickle 文件的大小翻了一倍。 - arqam
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接