使用PassiveAggressiveClassifier的partial_fit在Scikit中进行增量学习

时间:2015-06-11 09:03:30

标签: machine-learning scikit-learn

我正尝试在下面的脚本中使用PassiveAggressiveClassifier TfidVectorizer技术训练partial_fit

代码已更新:

a, ta = [], []
r, tr = [], []
g = []

vect = HashingVectorizer(ngram_range=(1,4))
model = PassiveAggressiveClassifier()
with open('files', 'rb') as f:
    for line in f:
        line = line.strip()
        with open('gau-' + line + '.csv', 'rb') as csvfile:
            reader = csv.DictReader(csvfile)
            for row in reader:
                res = row['gau']
                g.append(res)

        cls = np.unique(g)
        print(len(cls))

        with open('gau-' + line + '.csv', 'rb') as csvfile:
            reader = csv.DictReader(csvfile)
            i = 0
            j = True
            for row in reader:
                arr = row['text']
                res = row['gau']
                a.append(arr)
                if(len(res) > 0):
                    r.append(int(res))
                i = i + 1

                if i % 400 == 0:
                    training_set = vect.fit_transform(a)
                    print(training_set.shape)
                    training_result = np.array(r)
                    model = model.partial_fit(
                        training_set, training_result, classes=cls)
                    a, r, i = [], [], 0

        print(model)
        testing_set = vect.transform(ta)
        testing_result = np.array(tr)
        predicted = model.predict(testing_set)

        print "Result to be predicted: "+testing_result
        print "Prediction: "+predicted

有多个CSV文件,每个文件包含4k-5k记录,我试图使用partial_fit函数一次装入400条记录。当我运行此代码时,我遇到了以下错误:

Result to be predicted: 1742
Prediction: 2617

如何解决此问题?我的CSV文件中的记录长度可变。

更新

TfidVectorizer替换HashingVectorizer,我成功创建了我的模型,但现在在对我的测试数据执行预测时,生成的预测都是错误的。 我的训练数据包含数百万行csv文件,每行包含最多4k-5k字的文本。

那么我的方法是否有任何问题,即这些算法可以与我的数据一起使用吗?

4 个答案:

答案 0 :(得分:1)

  

我尝试使用TfidVectorizer和partial_fit技术训练PassiveAggressiveClassifier并使用以下脚本:

您不能,因为TfidfVectorizer不适用于在线学习。你想要HashingVectorizer

至于你的代码到底发生了什么,问题出在这里:

training_set = vect.fit_transform(a)
print(training_set.shape)
training_result = np.array(r)
model = model.partial_fit(training_set, training_result, classes=cls)

您正在每一步重新安装TF-IDF对象。因此,没有什么可以阻止你在一次迭代中使用字典大小而在下一次迭代时使用另一次迭代,这正是你得到的错误。

如果你坚持使用TF-IDF,你可以尝试一些事情:

  1. 追加零/修剪fit_transform返回的向量,使其成为第一个的长度:不太可能正常工作;

  2. 使用初始数据集(最好是大数据集)在TF-IDF对象上调用fit,然后在其他数据集上调用transform。这可能会更好,但我仍然建议HashingVectorizer

答案 1 :(得分:1)

这是我从你的问题中理解的。

1)您需要应用部分拟合模型进行在线培训。

2)你的特征空间太大了。

如果我做对了,那我就遇到了同样的问题。如果您使用HashingVectorizer,则很有可能发生密钥冲突。

HashingVectorizer doc

  

还有一些缺点(vs使用带有一个的CountVectorizer   内存词汇表:没有办法计算逆   变换(从特征索引到字符串特征名称)可以是   在尝试内省哪些功能最重要时会出现问题   到一个模型。可能存在冲突:可以映射到不同的令牌   相同的特征索引。但是在实践中,这很少是一个问题   n_features足够大(例如2 ** 18用于文本分类   问题)。没有IDF加权,因为这会渲染变压器   stageful。

如果密钥发生碰撞,则可能会降低准确性。

在我的在线培训中,首先我用这样的partial_fit训练了分类器。

classifier = MultinomialNB(alpha=alpha_optimized).partial_fit(X_train_tfidf,y_train,classes=np.array([0,1]))

第二天,我加载第一天训练集的腌制分类器count_vect和tfidf。然后我只对count_vet和tfidf应用了变换。它工作了

X_train_counts = count_vect.transform(x_train)
X_train_tfidf = tfidf.transform(X_train_counts)
pf_classifier.partial_fit(X_train_tfidf,y_train)

如有任何疑问,请回复。

答案 2 :(得分:0)

作为一种解决方案,我会说使用HashingVectorizer可以满足您的需求,因为您可以设置构造函数中的功能数量。

您可能更喜欢使用TfidfVectorizer,也许它更适合您的情况。我给出了答案,直到某人给出了对你更有用的东西。

希望会有。别忘了接受你选择的那个

答案 3 :(得分:0)

对于那些HashingVectorizer无法满足他们需求的人,请在我对这个相关问题here的回答中查看可能的替代方案。它基本上是TfidfVectorizer和CountVectorizer的partial_fit的自定义实现。

有关此处具体讨论的两条评论:

  • OP的问题要求每次调用partial_fit后输出向量的维度都相同。通常,预期实现partial_fit的每个Scikit-Learn估计器都能够在调用partial_fit之后在管道中工作,因此对于矢量化器,这意味着不会更改输出维度,因为管道中的其他估计器可能不一定能够处理改变。我认为这就是为什么partial_fit还没有在Scikit-Learn中为这些矢量化器实现(参见讨论on an active PR),因为partial_fit可能会更新肯定会改变输出维度的词汇。

  • 因此,我的答案(TfidfVectorizer的partial_fit方法)提出的解决方案只能解决OP需求的第一部分,即增量学习。为了解决第二部分,可以将输出序列用零填充到预定矢量中。这并不理想,因为当词汇量超过这个限制时会失败。