用朴素贝叶斯完成语种检测
我们试试用朴素贝叶斯完成一个语种检测的分类器,说起来,用朴素贝叶斯完成这个任务,其实准确度还不错。
机器学习的算法要取得好效果,离不开数据,咱们先拉点数据(twitter数据,包含English, French, German, Spanish, Italian 和 Dutch 6种语言)。
In [1]:
in_f = open('data.csv') lines = in_f.readlines() in_f.close() dataset = [(line.strip()[:-3], line.strip()[-2:]) for line in lines]
了解一下你的数据
In [2]:
dataset[:5]
Out[2]:
为了一会儿检测一下咱们的分类器效果怎么样,我们需要一份测试集。
所以把原数据集分成训练集的测试集,咱们用sklearn自带的分割函数。
In [3]:
# 完成训练集和测试集的切分 from sklearn.model_selection import train_test_split x, y = zip(*dataset) x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=1)
In [4]:
len(x_train)
Out[4]:
模型要有好效果,数据质量要保证。我们用正则表达式,去掉噪声数据:
In [5]:
import re def remove_noise(document): noise_pattern = re.compile("|".join(["httpS+", "@w+", "#w+"])) clean_text = re.sub(noise_pattern, "", document) #把所有指定的噪声串变成空(即直接删去噪声串) return clean_text.strip() remove_noise("Trump images are now more popular than cat gifs. @trump #trends http://www.trumptrends.html")
Out[5]:
下一步要做的就是在降噪数据上抽取出来有用的特征啦,我们抽取1-gram和2-gram的统计特征
In [6]:
from sklearn.feature_extraction.text import CountVectorizer vec = CountVectorizer( lowercase=True, # lowercase the text讲所有文本内容转为小写 analyzer='char_wb', # tokenise by character ngrams ngram_range=(1,2), # use ngrams of size 1 and 2(考虑一个到两个单词) max_features=1000, # keep the most common 1000 ngrams最多抽取1000个词作为特征 preprocessor=remove_noise #将上一个代码块中的函数传入进行预处理 ) vec.fit(x_train) def get_features(x): vec.transform(x)
先利用CountVectorizer来生成特征vec,然后再这个特征上将训练数据在分类器上做模型的拟合。
把分类器import进来并且训练
In [7]:
from sklearn.naive_bayes import MultinomialNB #采用多项式的朴素贝叶斯 classifier = MultinomialNB() classifier.fit(vec.transform(x_train), y_train)
Out[7]:
在测试集上看看我们的准确率如何:
In [8]:
classifier.score(vec.transform(XTest), yTest)
Out[8]:
能在1500句话上,训练得到准确率97.7%的分类器,效果还是不错的。
如果加大语料库,准确率会非常高。
规范化,写成一个class
In [9]:
import re from sklearn.feature_extraction.text import CountVectorizer from sklearn.model_selection import train_test_split from sklearn.naive_bayes import MultinomialNB class LanguageDetector(): def __init__(self, classifier=MultinomialNB()): self.classifier = classifier self.vectorizer = CountVectorizer(ngram_range=(1,2), max_features=1000, preprocessor=self._remove_noise) def _remove_noise(self, document): #去掉噪音 noise_pattern = re.compile("|".join(["httpS+", "@w+", "#w+"])) clean_text = re.sub(noise_pattern, "", document) return clean_text def features(self, X): #特征抽取 return self.vectorizer.transform(X) def fit(self, X, y): #模型拟合 self.vectorizer.fit(X) self.classifier.fit(self.features(X), y) def predict(self, x): #进行预测 return self.classifier.predict(self.features([x])) def score(self, X, y): #测试集上进行打分 return self.classifier.score(self.features(X), y)
In [10]:
in_f = open('data.csv') lines = in_f.readlines() in_f.close() dataset = [(line.strip()[:-3], line.strip()[-2:]) for line in lines] x, y = zip(*dataset) x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=1) language_detector = LanguageDetector() language_detector.fit(x_train, y_train) print(language_detector.predict('This is an English sentence')) print(language_detector.score(x_test, y_test))