我正在尝试使用k-means聚类来对文本文档进行分类。是否可以将一组文档tfidf矢量化并执行计算,然后添加更多要分类的文档?
这就是我目前拥有的
true_k = 4
vectorizer = TfidfVectorizer(stop_words='english')
X = vectorizer.fit_transform(documents)
model = KMeans(n_clusters=true_k, init='k-means++', max_iter=100, n_init=1)
model.fit(X)
如何将更多文档添加到X?因为我想pickle X并保存它。
实际上这很简单(与公认的答案相反,这表明这很复杂——事实并非如此)。只需连接您的数据,并重用相同的矢量器(如果您创建新的矢量器,或按照已接受的答案中的建议重新装配旧的矢量器),它将更改其估计值,因此您将获得不同的特征空间,因此您必须将其设置为
true_k = 4
vectorizer = TfidfVectorizer(stop_words='english')
X = vectorizer.fit_transform(documents)
model = KMeans(n_clusters=true_k, init='k-means++', max_iter=100, n_init=1)
model.fit(X)
现在你可以获得新的数据、文档2,只需进行
X2 = vectorizer.transform(documents2)
X = np.vstack((X, X2))
model.fit(X) # optimally you would start from the previous solution, but sklearn does not yet support it
但是,请记住,这假设您的第一批文档已经代表了整个数据集。换句话说,您将限制自己使用第一个文档中的单词,并且不会重新修改idf规范化。实际上,您可以消除这两个限制,但您必须实现自己的在线tfidf矢量器,它可以更新其估计值。这并不难做到,但您必须(在每一批新文档之后)也更新以前的文档(因为idf部分会发生变化)。更简单的解决方案是只保留计数矢量器并更新它,独立计算"idf"部分并在顶部应用它(就在kmeans之前)。
问题是您的X
特征矩阵的形状为[n_docs, n_features
]。因此,如果使用新文档创建新特征矩阵,则必须确保新特征矩阵(X2
)具有与X
完全相同的特征。我无法想象一个可行的应用程序。
但是,如果您知道两者具有相同的特征空间,则可以使用scipy.sparse.vstack
将新文档附加到您的特征矩阵中:
from scipy.sparse import vstack
X = vstack((X, X2))
EDIT:为了确保X2
中的特征空间相同,可以在TfidfVectorizer
中使用vocabulary
关键字参数,例如:
vectorizer = TfidfVectorizer(stop_words='english')
vectorizer = vectorizer.fit(documents)
X = vectorizer.transform(documents)
# do whatever with X
new_vectorizer = TfidfVectorizer(stop_words='english', vocabulary=vectorizer.vocabulary_)
X2 = vectorizer.fit_transform(new_documents)
X = vstack((X, X2))
这意味着,除了保存X
之外,还需要存储vectorizer.vocabulary_
。