如何在 python 3 中对大量文本进行分类?
Posted
技术标签:
【中文标题】如何在 python 3 中对大量文本进行分类?【英文标题】:How to classify a very large amount of text in python 3? 【发布时间】:2019-09-18 13:26:56 【问题描述】:我必须对超过 10,000 个类别的大量文本进行分类。我需要专家建议,因为我还是一名学生。
我的数据是按类别分类的商业产品的描述和标题。例如,标题为“大而好的键盘”的键盘属于办公室 > 计算机 > 键盘类别。
现在,我使用“from sklearn.feature_extraction.text import TfidfVectorizer”来表示我的文本数据。但是矩阵在内存中太大了。 对于表示大量数据,您有什么技巧吗?
我正在考虑使用 word-2-vec 来表示数据,然后使用神经网络进行分类。
但我需要你的建议才能走上正确的道路!!
谢谢
【问题讨论】:
您的问题到底是什么?您是否尝试过为您的数据拟合分类器,您是否说它“太大”,因为它花费了太多时间? 另外,tfidf 向量化然后应用 word2vec 没有多大意义……你想达到什么目的? 我的数据是商业产品的描述和标题。我的目标是产品类别。例如,键盘的描述为“大键盘”,它被归类为办公室> 计算机> 键盘。目前我在我的数据上使用“from sklearn.feature_extraction.text import TfidfVectorizer”,但矩阵在内存中非常大。是否有另一种表示文本数据的解决方案?感谢您的帮助 【参考方案1】:如果您想减小 Tfidf 矢量化的大小,我看到了两个选项。
假设你有以下数据:
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.decomposition import TruncatedSVD
X = ["When I wake up in the morning I always eat apples",
"What do you eat in the morning",
"Usually I only drink coffee",
"How awful, I really cannot stand coffee"]
当应用 Tfidf 变换时,你会得到一个形状为 (4,21) 的矩阵:
vectorizer = TfidfVectorizer()
vectorized_X = vectorizer.fit_transform(X)
vectorized_X.shape
>>> (4,21)
现在让我们假设 21 列太多了,我们想减少它。
选项 1
您可以使用降维。执行 Tfidf 后最自然的方法是使用截断的 SVD。这将对您的 tfidf 矢量化执行线性降维。它的好处是您可以指定要保留的新组件的数量:
svd = TruncatedSVD(n_components=2)
reduced_X = svd.fit_transform(vectorized_X)
reduced_X.shape
>>> (4,2)
选项 2
Tfidf 允许您指定要在矢量化中保留多少字。然后,它返回仅对词频最高的词执行的向量化。
vectorizer_reduction = TfidfVectorizer(max_features = 5)
vectorized_reduced_X = vectorizer_reduction.fit_transform(X)
vectorized_reduced_X.shape
>>> (4,5)
如果我可以在两者之间进行选择,我会选择选项 1,因为它首先考虑所有信息然后对其进行总结,而 选项 2 只是丢弃从一开始就提供信息。但我也希望 选项 1 需要更长的时间......所以也许最佳解决方案可能是两者的混合(首先应用限制性 Tfidf,然后应用 SVD)?
【讨论】:
两种方法的混合在我看来是一个不错的选择。我将测试以获得速度和良好预测率之间的最佳比率。感谢您清晰准确的回答! 我也想到了另一种解决方案,就是使用word-2-vec。使用库“gensim”(radimrehurek.com/gensim/models/word2vec.html),看起来很容易。根据文档,可以在不将整体加载到内存的情况下完成文本矢量化。你觉得这个选项怎么样? @ToniGarcia 如果你想使用 word2vec,下一个问题是:你打算用它做什么?这会将您的每个句子转换为矩阵,最好使用神经网络处理。如果这是你想走的路,那很好。这与将文本转换为 tfidf 完全不同。 我真正的问题是用无法存储在内存中的数据来训练分类器。我尝试使用 word-2-vec 将句子转换为矩阵,然后训练分类器。但这需要太多时间。所以我在 sklearn 上使用 partial_fit 训练了一个 SGD。我会用我的代码写一个关于这个的答案。 我已经在上面写了答案。【参考方案2】:我找到了一种无需将所有数据都存储在内存中即可训练分类器的解决方案。
假设您有 2 个数据集用于训练 1 分类器。
#Data 1
X1_text = ["When I wake up in the morning I always eat apples",
"What do you eat in the morning"]
y1 = [1,1] #target 1
#Data 2
X2_text = ["Usually I only drink coffee",
"How awful, I really cannot stand coffee"]
y2 = [2,2] #target 2
我们使用散列来向量化数据
from sklearn.feature_extraction.text import HashingVectorizer
vectorizer = HashingVectorizer(decode_error='ignore', n_features=2 ** 18)
X1 = vectorizer.transform(X1_text)
X2 = vectorizer.transform(X2_text)
我们将使用 partial_fit 分两步训练 SGDClassifier。 https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.SGDClassifier.html
from sklearn.linear_model.stochastic_gradient import SGDClassifier
clf = SGDClassifier()
第一步,对 X1 / y1 使用 partial_fit。参数类必须包含所有可能的类来预测。这里是 1 和 2 。 注意:如果你有,例如,所有目标的变量类,你可以使用 classes = np.unique(classes)。请参阅文档。
clf.partial_fit(X1, y1, classes = [1,2])
第二步,用其他数据重新训练分类器。不要使用属性类。
clf.partial_fit(X2, y2)
【讨论】:
以上是关于如何在 python 3 中对大量文本进行分类?的主要内容,如果未能解决你的问题,请参考以下文章