探索没有TensorFlow API的纯Kotlin语言中的贝叶斯文本分类。
文本分类是自然语言处理中的一项重要任务,具有广泛的应用前景。我们将学习如何以非深度学习的方式使用该技术,而无需使用TensorFlow和神经网络。因为这个分类器将在Android应用程序中工作,所以需要用Kotlin或Java编写。
TensorFlow和TensorFlow Lite可以在Android上高效地工作(有时也能让人神往)。如果可以用Kotlin (Android原生语言)创建类似的算法,那么可以用任何编程语言(如C、c++甚至Swift (iOS原生语言))创建类似的算法。
有时候,在平台中本地编码的分类器可以比TensorFlow或其API执行得更好。此外,我们可以对它的工作和推理有更多的控制流。
我们将使用朴素贝叶斯文本分类器对Kotlin中的文本进行分类,该文本最终将在Android设备上运行。
说到朴素贝叶斯文本分类,Naive Bayes Classifiers - GeeksforGeeks
朴素贝叶斯文本分类利用贝叶斯定理的力量将文档(文本)分类为特定的类。
贝叶斯定理
如果我们根据文本分类的需要来计算这个等式,
我们代表我们的文档作为令牌x₁, x₂……xₙ和C是我们将计算的概率的类。分母被省略,并在这里看到它的解释(因为在两类(C₁和C₂)、P (x₁, x₂……xₙ)将保持不变,并充当一个正常化常数)
我们将计算两类的概率,即SPAM(C 1)和HAM(C 2)。具有较高概率的那个将是我们的输出。
对于每个类,我们都有一个词汇表或一组出现在spam或ham单词中的单词,它们将代表我们的类语料库。
让我们从Kotlin开始吧。
如果您以前喜欢Python !
首先,我们将分别定义包含 spam和ham单词的语料库positiveBagOfWords 和negativeBagOfWords。
class Vocabulary {
companion object {
val positiveBagOfWords = arrayOf( ... ) // Some words here
val negativeBagOfWords = arrayOf( ... ) // Some words here
}
}现在,我们创建一个名为Classifier的新类来处理分类任务。我们需要定义两个常量和一个方法,该方法从给定的文本片段中提取标记(通过删除不必要的单词、标点等)。
companion object {
val CLASS_POSITIVE = 0 // Spam
val CLASS_NEGATIVE = 1 // Ham
private val englishStopWords = arrayOf(
"i", "me", "my", "myself", "we", "our", "ours", "ourselves", "you", "your", "yours", "yourself", "yourselves",
"he", "him", "his", "himself", "she", "her", "hers", "herself", "it", "its", "itself", "they", "them", "their",
"theirs", "themselves", "what", "which", "who", "whom", "this", "that", "these", "those", "am", "is", "are", "was",
"were", "be", "been", "being", "have", "has", "had", "having", "do", "does", "did", "doing", "a", "an", "the",
"and", "but", "if", "or", "because", "as", "until", "while", "of", "at", "by", "for", "with", "about", "against",
"between", "into", "through", "during", "before", "after", "above", "below", "to", "from", "up", "down", "in",
"out", "on", "off", "over", "under", "again", "further", "then", "once", "here", "there", "when", "where", "why",
"how", "all", "any", "both", "each", "few", "more", "most", "other", "some", "such", "no",
"nor", "not", "only", "own", "same", "so", "than", "too", "very", "s", "t", "can", "will", "just", "don", "should",
"now" , "hello" , "hi" , "dear" , "respected" , "thank"
)
fun getTokens( text : String ) : Array<String> {
val tokens = text.toLowerCase().split( " " )
val filteredTokens = ArrayList<String>()
for ( i in 0 until tokens.count() ) {
if ( !tokens[i].trim().isBlank() ) {
filteredTokens.add( tokens[ i ] )
}
}
val stopWordRemovedTokens = tokens.map { Regex("[^a-zA-Z]").replace( it , "") }
as ArrayList<String>
stopWordRemovedTokens.removeAll {
englishStopWords.contains( it ) or it.trim().isBlank()
}
return stopWordRemovedTokens.distinct().toTypedArray()
}
}gettoken (document) =令牌。因此我们可以将一个文档D等一系列令牌x₁, x xₙ₂……。
找到的概率
首先,我们需要找到P(C)或类概率。 这只不过是两个语料库中有多少单词属于C类的概率。
private fun findClassProbability(classVocab1 : Array<String>, classVocab2 : Array<String> , classVocab : Array<String>) : Float{
val total_words = (classVocab1.count() + classVocab2.count()).toFloat()
val class_count = (classVocab.count()).toFloat()
return ( class_count / total_words )
}接下来,我们需要找到P(X | C)也就是X属于C类的概率。
在此之前,我们需要一种方法来找到给定 xᵢ 的P( xᵢ | C ),它是给定文档中的一个标记。 我们可以使用这种方法。
private fun findProbabilityGivenClass( x : String , classVocab : Array<String> ) : Float {
val x_count = classVocab.count { it.contains(x) or x.contains(it) }.toFloat()
val class_count = classVocab.count().toFloat()
return (( x_count / class_count ) + 1)
}其中class_vocab是一个语料库。它代表P中的C(xᵢ| C)。想知道1是从哪里来的吗?这是拉普拉斯平滑处理。如果在我们的语料库中不存在xᵢ时P(xᵢ| C)为0,那么我们所有的P(X | C)都可以变为0。添加1可以解决此问题。
现在,我们需要将所有P(xᵢ| C)相乘,最后将它乘以P(C),这是我们在下面方法中的类概率。
private fun findProbabilityGivenSample( document : String , classVocab : Array ) : Float {
val tokens = getTokens( document )
var probability_given_class = 1.0f
for ( token in tokens ) {
probability_given_class *= findProbabilityGivenClass( token , classVocab )
}
return probability_given_class * findClassProbability( positiveBagOfWords , negativeBagOfWords , classVocab )
}这是所有。现在我们需要检查哪个类有更高的可能性。
fun classifyText( text : String ) : Int {
val class_1_probability = findProbabilityGivenSample( text , positiveBagOfWords )
val class_2_probability = findProbabilityGivenSample( text , negativeBagOfWords )
if ( class_1_probability > class_2_probability ) {
return CLASS_POSITIVE
}
else if ( class_1_probability < class_2_probability ) {
return CLASS_NEGATIVE
}
}可以在此一眼看到完整的代码。https://gist.github.com/shubham0204/c19eb5694bf2c7be3901772726ac5c5e
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69918097/viewspace-3141089/ ,如需转载,请注明出处,否则将追究法律责任。