如何使用 spark 朴素贝叶斯分类器对 IDF 进行文本分类?
How to use spark Naive Bayes classifier for text classification with IDF?
我想使用 tf-idf 将文本文档转换为特征向量,然后训练朴素贝叶斯算法对其进行分类。
我可以轻松加载没有标签的文本文件,并使用 HashingTF() 将其转换为向量,然后使用 IDF() 根据单词的重要性对单词进行加权。但是,如果我这样做,我就摆脱了标签,即使顺序相同,似乎也无法将标签与矢量重新组合。
另一方面,我可以在每个单独的文档上调用 HashingTF() 并保留标签,但是我无法在其上调用 IDF(),因为它需要整个文档语料库(标签会挡路)。
朴素贝叶斯的 spark 文档只有一个示例,其中的点已经被标记和矢量化,因此没有太大帮助。
我也看过这个指南:http://help.mortardata.com/technologies/spark/train_a_machine_learning_model
但在这里他只对没有 idf 的每个文档应用哈希函数。
所以我的问题是,是否有一种方法不仅可以对朴素贝叶斯分类器使用 idf 的词进行矢量化,还可以对词进行加权?主要问题似乎是 sparks 坚持只接受 labeledPoints 的 rdds 作为 NaiveBayes 的输入。
def parseLine(line):
label = row[1] # the label is the 2nd element of each row
features = row[3] # the text is the 4th element of each row
features = tokenize(features)
features = hashingTF.transform(features)
return LabeledPoint(label, features)
labeledData = data1.map(parseLine)
标准 PySpark 方法(拆分 -> 转换 -> 压缩)似乎工作得很好:
from pyspark.mllib.feature import HashingTF, IDF
from pyspark.mllib.regression import LabeledPoint
from pyspark.mllib.classification import NaiveBayes
training_raw = sc.parallelize([
{"text": "foo foo foo bar bar protein", "label": 1.0},
{"text": "foo bar dna for bar", "label": 0.0},
{"text": "foo bar foo dna foo", "label": 0.0},
{"text": "bar foo protein foo ", "label": 1.0}])
# Split data into labels and features, transform
# preservesPartitioning is not really required
# since map without partitioner shouldn't trigger repartitiong
labels = training_raw.map(
lambda doc: doc["label"], # Standard Python dict access
preservesPartitioning=True # This is obsolete.
)
tf = HashingTF(numFeatures=100).transform( ## Use much larger number in practice
training_raw.map(lambda doc: doc["text"].split(),
preservesPartitioning=True))
idf = IDF().fit(tf)
tfidf = idf.transform(tf)
# Combine using zip
training = labels.zip(tfidf).map(lambda x: LabeledPoint(x[0], x[1]))
# Train and check
model = NaiveBayes.train(training)
labels_and_preds = labels.zip(model.predict(tfidf)).map(
lambda x: {"actual": x[0], "predicted": float(x[1])})
要获取一些统计信息,您可以使用 MulticlassMetrics
:
from pyspark.mllib.evaluation import MulticlassMetrics
from operator import itemgetter
metrics = MulticlassMetrics(
labels_and_preds.map(itemgetter("actual", "predicted")))
metrics.confusionMatrix().toArray()
## array([[ 2., 0.],
## [ 0., 2.]])
相关
- Handling continuous data in Spark NaiveBayes
我想使用 tf-idf 将文本文档转换为特征向量,然后训练朴素贝叶斯算法对其进行分类。
我可以轻松加载没有标签的文本文件,并使用 HashingTF() 将其转换为向量,然后使用 IDF() 根据单词的重要性对单词进行加权。但是,如果我这样做,我就摆脱了标签,即使顺序相同,似乎也无法将标签与矢量重新组合。
另一方面,我可以在每个单独的文档上调用 HashingTF() 并保留标签,但是我无法在其上调用 IDF(),因为它需要整个文档语料库(标签会挡路)。
朴素贝叶斯的 spark 文档只有一个示例,其中的点已经被标记和矢量化,因此没有太大帮助。
我也看过这个指南:http://help.mortardata.com/technologies/spark/train_a_machine_learning_model 但在这里他只对没有 idf 的每个文档应用哈希函数。
所以我的问题是,是否有一种方法不仅可以对朴素贝叶斯分类器使用 idf 的词进行矢量化,还可以对词进行加权?主要问题似乎是 sparks 坚持只接受 labeledPoints 的 rdds 作为 NaiveBayes 的输入。
def parseLine(line):
label = row[1] # the label is the 2nd element of each row
features = row[3] # the text is the 4th element of each row
features = tokenize(features)
features = hashingTF.transform(features)
return LabeledPoint(label, features)
labeledData = data1.map(parseLine)
标准 PySpark 方法(拆分 -> 转换 -> 压缩)似乎工作得很好:
from pyspark.mllib.feature import HashingTF, IDF
from pyspark.mllib.regression import LabeledPoint
from pyspark.mllib.classification import NaiveBayes
training_raw = sc.parallelize([
{"text": "foo foo foo bar bar protein", "label": 1.0},
{"text": "foo bar dna for bar", "label": 0.0},
{"text": "foo bar foo dna foo", "label": 0.0},
{"text": "bar foo protein foo ", "label": 1.0}])
# Split data into labels and features, transform
# preservesPartitioning is not really required
# since map without partitioner shouldn't trigger repartitiong
labels = training_raw.map(
lambda doc: doc["label"], # Standard Python dict access
preservesPartitioning=True # This is obsolete.
)
tf = HashingTF(numFeatures=100).transform( ## Use much larger number in practice
training_raw.map(lambda doc: doc["text"].split(),
preservesPartitioning=True))
idf = IDF().fit(tf)
tfidf = idf.transform(tf)
# Combine using zip
training = labels.zip(tfidf).map(lambda x: LabeledPoint(x[0], x[1]))
# Train and check
model = NaiveBayes.train(training)
labels_and_preds = labels.zip(model.predict(tfidf)).map(
lambda x: {"actual": x[0], "predicted": float(x[1])})
要获取一些统计信息,您可以使用 MulticlassMetrics
:
from pyspark.mllib.evaluation import MulticlassMetrics
from operator import itemgetter
metrics = MulticlassMetrics(
labels_and_preds.map(itemgetter("actual", "predicted")))
metrics.confusionMatrix().toArray()
## array([[ 2., 0.],
## [ 0., 2.]])
相关
- Handling continuous data in Spark NaiveBayes