基于Python的朴素贝叶斯分类器用于新语言

1 投票
3 回答
1329 浏览
提问于 2025-04-18 15:00

我并不是想自己从头开始做一个新的朴素贝叶斯分类器。市面上已经有很多现成的,比如scikit-learn就有朴素贝叶斯的实现,NLTK也有自己的NaiveBayesClassifier

我有超过1000个句子用于训练,还有300多个句子用于测试,都是我自己的语言(属于印度语言的一种)。我只需要选择一个已经实现的分类器(朴素贝叶斯),然后训练它并测试它的准确性。

问题是这些文本不是英文,而是用德文纳加里文(Devnagari unicode)写的。

我希望能得到一些建议,看看哪个分类器比较适合解决我目前遇到的主要问题,就是关于unicode的处理。

3 个回答

0

这个问题表述得很糟糕,但有可能它是关于语言识别而不是句子分类

如果真是这样的话,那么在你使用像朴素贝叶斯这样的分类器之前,还有很长的路要走。可以看看Damir Cavar的语言识别方法,他用Python实现了一个字符组的方法,链接在这里:Damir Cavar's LID

4

在scikit-learn中,朴素贝叶斯算法是通过数字向量来工作的。比如,我们可以通过某种向量化工具来获得这些数字向量。对于文本分类,我经常使用TfidfVectorizer这个工具:http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.html

在TfidfVectorizer的构造函数参数中,有一个叫做encoding的参数,默认值是'utf-8'。如果你要分析的是字节或文件,这个编码就会用来解码。

你可以使用这个参数来指定你自己的编码方式,另外你还可以定义自己的预处理函数和分析函数,这样也会很有用。

1

我更倾向于使用 scikit-learn 来构建一个语言识别系统,就像我之前做的那样,具体可以参考这个链接:https://github.com/alvations/bayesline

不过,使用简单的分类模块和unicode数据,完全可以用 NLTK 来构建一个语言识别系统。

其实不需要对NLTK的代码做什么特别的修改,它们可以直接使用。(这可能对你有帮助,关于如何在NLTK中构建分类器,可以参考这个链接:nltk NaiveBayesClassifier用于情感分析的训练

现在为了证明使用NLTK和unicode数据进行语言识别是完全可行的,下面会展示一些内容。

首先,在进行语言识别时,使用unicode字符特征和字节码在特征提取上有一点小区别:

from nltk.corpus import indian

# NLTK reads the corpus as bytecodes.
hindi = " ".join(indian.words('hindi.pos'))
bangla = " ".join(indian.words('bangla.pos'))
marathi = " ".join(indian.words('marathi.pos'))
telugu = " ".join(indian.words('telugu.pos'))

# Prints out first 10 bytes (including spaces).
print 'hindi:', hindi[:10]
print 'bangla:', bangla[:10]
print 'marathi:', marathi[:10]
print 'telugu:', telugu[:10]
print

# Converts bytecodes to utf8.
hindi = hindi.decode('utf8')
bangla = bangla.decode('utf8')
marathi = marathi.decode('utf8')
telugu = telugu.decode('utf8')

# Prints out first 10 unicode char (including spaces).
print 'hindi:', hindi[:10]
print 'bangla:', bangla[:10]
print 'marathi:', marathi[:10]
print 'telugu:', telugu[:10]
print

[输出]:

hindi: पूर
bangla: মহি
marathi: '' सन
telugu: 4 . ఆడ

hindi: पूर्ण प्रत
bangla: মহিষের সন্
marathi: '' सनातनवा
telugu: 4 . ఆడిట్ 

现在你看到了使用字节码和unicode的区别,我们来训练一个标记器。

from nltk import NaiveBayesClassifier as nbc

# Allocate some sort of labels for the data.
training = [(hindi, 'hi'), (bangla, 'ba'), (marathi, 'ma'), (telugu, 'te')]
# This is how you can extract ngrams
print ngrams(telugu[:10], 2)
print
print ngrams(hindi[:10], 3)
print

vocabulary = set(chain(*[ngrams(txt, 2) for txt,tag in training]))

feature_set = [({i:(i in ngrams(sentence, 2)) for i in vocabulary},tag) for sentence, tag in training]

classifer = nbc.train(feature_set)

test1 = u'पूर्ण प्रत' # hindi
test2 = u'মহিষের সন্' # bangla
test3 = u'सनातनवा' # marathi
test4 = u'ఆడిట్ ' # telugu

for testdoc in [test1, test2, test3, test4]:
    featurized_test_sent =  {i:(i in ngrams(testdoc,2)) for i in vocabulary}
    print "test sent:", testdoc
    print "tag:", classifer.classify(featurized_test_sent)
    print

[输出]:

[(u'4', u' '), (u' ', u'.'), (u'.', u' '), (u' ', u'\u0c06'), (u'\u0c06', u'\u0c21'), (u'\u0c21', u'\u0c3f'), (u'\u0c3f', u'\u0c1f'), (u'\u0c1f', u'\u0c4d'), (u'\u0c4d', u' ')]

[(u'\u092a', u'\u0942', u'\u0930'), (u'\u0942', u'\u0930', u'\u094d'), (u'\u0930', u'\u094d', u'\u0923'), (u'\u094d', u'\u0923', u' '), (u'\u0923', u' ', u'\u092a'), (u' ', u'\u092a', u'\u094d'), (u'\u092a', u'\u094d', u'\u0930'), (u'\u094d', u'\u0930', u'\u0924')]

test sent: पूर्ण प्रत
tag: hi

test sent: মহিষের সন্
tag: ba

test sent: सनातनवा
tag: ma

test sent: ఆడిట్ 
tag: te

以下是完整的代码:

# -*- coding: utf-8 -*-

from itertools import chain
from nltk.corpus import indian
from nltk.util import ngrams
from nltk import NaiveBayesClassifier as nbc


# NLTK reads the corpus as bytecodes.
hindi = " ".join(indian.words('hindi.pos'))
bangla = " ".join(indian.words('bangla.pos'))
marathi = " ".join(indian.words('marathi.pos'))
telugu = " ".join(indian.words('telugu.pos'))

# Prints out first 10 bytes (including spaces).
print 'hindi:', hindi[:10]
print 'bangla:', bangla[:10]
print 'marathi:', marathi[:10]
print 'telugu:', telugu[:10]
print

# Converts bytecodes to utf8.
hindi = hindi.decode('utf8')
bangla = bangla.decode('utf8')
marathi = marathi.decode('utf8')
telugu = telugu.decode('utf8')

# Prints out first 10 unicode char (including spaces).
print 'hindi:', hindi[:10]
print 'bangla:', bangla[:10]
print 'marathi:', marathi[:10]
print 'telugu:', telugu[:10]
print

# Allocate some sort of labels for the data.
training = [(hindi, 'hi'), (bangla, 'ba'), (marathi, 'ma'), (telugu, 'te')]
# This is how you can extract ngrams
print ngrams(telugu[:10], 2)
print
print ngrams(hindi[:10], 3)
print

vocabulary = set(chain(*[ngrams(txt, 2) for txt,tag in training]))

feature_set = [({i:(i in ngrams(sentence, 2)) for i in vocabulary},tag) for sentence, tag in training]

classifer = nbc.train(feature_set)

test1 = u'पूर्ण प्रत' # hindi
test2 = u'মহিষের সন্' # bangla
test3 = u'सनातनवा' # marathi
test4 = u'ఆడిట్ ' # telugu

for testdoc in [test1, test2, test3, test4]:
    featurized_test_sent =  {i:(i in ngrams(testdoc,2)) for i in vocabulary}
    print "test sent:", testdoc
    print "tag:", classifer.classify(featurized_test_sent)
    print

撰写回答