1.理解樸素貝葉斯
1)基本概念
-
依據(jù)概率原則進行分類。如天氣預(yù)測概率。
-
樸素貝葉斯(Naive Bayes, NB)適合場景:為估計一個結(jié)果的概率,從眾多屬性中提取的信息應(yīng)該被同時考慮。
-
很多算法忽略了弱影響的特征(若有大量弱影響的特征,它們組合在一起的影響可能會很大),但NB算法利用了所有可以獲得的證據(jù)來修正預(yù)測。
-
貝葉斯方法的基本概念:事件,試驗,概率,聯(lián)合概率,獨立事件,相關(guān)事件(建立預(yù)測模型的基礎(chǔ)),條件概率,先驗概率,似然概率,邊際似然概率,后驗概率,頻率表
-
條件概率公式(事件B已經(jīng)發(fā)生的條件下,事件A發(fā)生的概率):
image.png
-
后驗概率(如商業(yè)垃圾郵件過濾器:判斷viagra是垃圾郵件spam的概率):
image.png
2)樸素貝葉斯算法
- NB優(yōu)點:簡單快速有效;能處理噪音及缺失值數(shù)據(jù);訓(xùn)練集不限大??;容易獲得估計概率值。
- NB缺點:依賴同樣重要和獨立的特征(錯誤假設(shè));應(yīng)用在大量數(shù)值特征的數(shù)據(jù)集中不理想;概率估計值比預(yù)測的類更不可靠。
- “樸素”的含義:基于這樣一個假設(shè):數(shù)據(jù)集的所有特征都具有相同的重要性和獨立性,但在大多數(shù)實際應(yīng)用中,假設(shè)不成立。
- 樸素貝葉斯算法具通用性和準確性,在分類學(xué)習任務(wù)中很強大。
①樸素貝葉斯分類
假設(shè)有4個單詞的100封郵件的似然表來訓(xùn)練樸素貝葉斯算法(如下表),收到新郵件時(包含了單詞viagra和unsubscribe,但不包含money和groceries),通過計算后驗概率來判斷它是否為垃圾郵件。
image.png
原始的基于貝葉斯定理的后驗概率:
image.png
將4個單詞事件視為獨立事件(類條件獨立),可簡化公式:
image.png
計算垃圾郵件總似然為:
image.png
計算非垃圾郵件總似然為:
image.png
是垃圾郵件的概率為:
image.png
②拉普拉斯估計
對于類中一個或多個水平,如果一個時間從沒有發(fā)生過,那它出現(xiàn)的概率為0,從而導(dǎo)致后驗概率值也為0(抵消或否決了所有其他的證據(jù))。
比如,這次的新郵件中包含了前述的4個單詞,則計算垃圾郵件的似然:
image.png
該郵件是垃圾郵件的概率為:
image.png
拉普拉斯估計就是給頻率表中每個計數(shù)加上一個很小的數(shù)(一般設(shè)為1),保證每一類中每個特征發(fā)生的概率是非零的。
拉普拉斯估計后的垃圾郵件似然:
image.png
③數(shù)值型特征值離散化
前面的頻率表要求特征必須為分類變量,如果是數(shù)值變量,需要將數(shù)值離散化(分段),如根據(jù)時間尋找分割點。如果沒有明顯的分割點,也可利用分位數(shù)進行分段。
但將數(shù)值特征離散化總是會導(dǎo)致信息量的減少,因為特征的原始粒度減少為幾個數(shù)目較少的類別。分段太少會導(dǎo)致重要趨勢被掩蓋,分段太多會導(dǎo)致頻率表中的計數(shù)值很小,因此需要平衡分段數(shù)。
2.樸素貝斯分類應(yīng)用
示例:基于貝葉斯算法的手機垃圾短信過濾。
1)收集數(shù)據(jù)
數(shù)據(jù)下載sms_spam.csv
:
鏈接: https://pan.baidu.com/s/1fAufKXCSufwd8It_DHXyWQ 提取碼: vgyj
2)探索和準備數(shù)據(jù)
## Example: Filtering spam SMS messages ----
## Step 2: Exploring and preparing the data ----
# read the sms data into the sms data frame
sms_raw <- read.csv("sms_spam.csv", stringsAsFactors = FALSE)
# examine the structure of the sms data
str(sms_raw)
# convert spam/ham to factor.
sms_raw$type <- factor(sms_raw$type)
# examine the type variable more carefully
str(sms_raw$type)
table(sms_raw$type)
處理和分析文本數(shù)據(jù)
文本挖掘包tm創(chuàng)建語料庫(文本集合),inspect函數(shù)查看語料庫內(nèi)容,tm_map函數(shù)轉(zhuǎn)換tm語料庫(如去數(shù)字,變小寫等),stopwords函數(shù)去除填充詞(如to/and/or/but等)。
清理完后標記分解單詞形成的組,并創(chuàng)建稀疏矩陣。再進行訓(xùn)練集和測試集劃分,并利用詞云進行可視化文本數(shù)據(jù)。最后為高頻詞創(chuàng)建指示特征。
PS:運行過程中tm包的tolower參數(shù)一直報錯,未解決,因此本示例最終沒有用此參數(shù)。
# build a corpus using the text mining (tm) package
library(tm)
sms_corpus <- VCorpus(VectorSource(sms_raw$text))
# examine the sms corpus
print(sms_corpus)
inspect(sms_corpus[1:2])
as.character(sms_corpus[[1]])
lapply(sms_corpus[1:2], as.character)
# clean up the corpus using tm_map()
# sms_corpus_clean <- tm_map(sms_corpus, content_transformer(tolower)) #Error
sms_corpus_clean <- sms_corpus
# show the difference between sms_corpus and corpus_clean
as.character(sms_corpus[[1]])
as.character(sms_corpus_clean[[1]])
sms_corpus_clean <- tm_map(sms_corpus_clean, removeNumbers) # remove numbers
sms_corpus_clean <- tm_map(sms_corpus_clean, removeWords, stopwords()) # remove stop words
sms_corpus_clean <- tm_map(sms_corpus_clean, removePunctuation) # remove punctuation
# tip: create a custom function to replace (rather than remove) punctuation
removePunctuation("hello...world")
replacePunctuation <- function(x) { gsub("[[:punct:]]+", " ", x) }
replacePunctuation("hello...world")
# illustration of word stemming
library(SnowballC)
wordStem(c("learn", "learned", "learning", "learns"))
sms_corpus_clean <- tm_map(sms_corpus_clean, stemDocument)
sms_corpus_clean <- tm_map(sms_corpus_clean, stripWhitespace) # eliminate unneeded whitespace
# examine the final clean corpus
lapply(sms_corpus[1:3], as.character)
lapply(sms_corpus_clean[1:3], as.character)
# create a document-term sparse matrix
sms_dtm <- DocumentTermMatrix(sms_corpus_clean)
# alternative solution: create a document-term sparse matrix directly from the SMS corpus
sms_dtm2 <- DocumentTermMatrix(sms_corpus, control = list(
# tolower = TRUE, #注釋掉也報錯
removeNumbers = TRUE,
stopwords = TRUE,
removePunctuation = TRUE,
stemming = TRUE
))
# alternative solution: using custom stop words function ensures identical result
sms_dtm3 <- DocumentTermMatrix(sms_corpus, control = list(
# tolower = TRUE, #注釋掉也報錯
removeNumbers = TRUE,
stopwords = function(x) { removeWords(x, stopwords()) },
removePunctuation = TRUE,
stemming = TRUE
))
# compare the result
sms_dtm
sms_dtm2
sms_dtm3
# creating training and test datasets
sms_dtm_train <- sms_dtm[1:4169, ]
sms_dtm_test <- sms_dtm[4170:5558, ]
# also save the labels
sms_train_labels <- sms_raw[1:4169, ]$type
sms_test_labels <- sms_raw[4170:5558, ]$type
# check that the proportion of spam is similar
prop.table(table(sms_train_labels))
prop.table(table(sms_test_labels))
# word cloud visualization
library(wordcloud)
wordcloud(sms_corpus_clean, min.freq = 50, random.order = FALSE)
# subset the training data into spam and ham groups
spam <- subset(sms_raw, type == "spam")
ham <- subset(sms_raw, type == "ham")
wordcloud(spam$text, max.words = 40, scale = c(3, 0.5))
wordcloud(ham$text, max.words = 40, scale = c(3, 0.5))
sms_dtm_freq_train <- removeSparseTerms(sms_dtm_train, 0.999)
sms_dtm_freq_train
# indicator features for frequent words
findFreqTerms(sms_dtm_train, 5)
# save frequently-appearing terms to a character vector
sms_freq_words <- findFreqTerms(sms_dtm_train, 5)
str(sms_freq_words)
# create DTMs with only the frequent terms
sms_dtm_freq_train <- sms_dtm_train[ , sms_freq_words]
sms_dtm_freq_test <- sms_dtm_test[ , sms_freq_words]
# convert counts to a factor
convert_counts <- function(x) {
x <- ifelse(x > 0, "Yes", "No")
}
# apply() convert_counts() to columns of train/test data
sms_train <- apply(sms_dtm_freq_train, MARGIN = 2, convert_counts)
sms_test <- apply(sms_dtm_freq_test, MARGIN = 2, convert_counts)
得到的sms_train
和sms_test
的單詞稀疏矩陣如下表所示:
image.png
3)訓(xùn)練模型
上例已經(jīng)將原始短信轉(zhuǎn)換為可以用一個統(tǒng)計模型代表的形式,因此用NB算法根據(jù)單詞的存在與否來估計一條給定的短信是垃圾短信的概率。
使用e1071::naiveBays()
或klaR::NaiveBayes()
函數(shù)。
## Step 3: Training a model on the data ----
library(e1071)
sms_classifier <- naiveBayes(sms_train, sms_train_labels)
4)評估模型性能
基于測試集中的未知短信來檢驗分類器的預(yù)測值。比較預(yù)測值和真實值,仍然通過混淆矩陣來計算。
## Step 4: Evaluating model performance ----
sms_test_pred <- predict(sms_classifier, sms_test)
library(gmodels)
CrossTable(sms_test_pred, sms_test_labels,
prop.chisq = FALSE, prop.t = FALSE, prop.r = FALSE,
dnn = c('predicted', 'actual'))
image.png
沒怎么處理效果也比較好,所以NB是文本分類的一種標準算法。同樣地,假陰性問題帶來的代價較大(把正常短信過濾掉了),進一步提升模型性能試試。文章來源:http://www.zghlxwxcb.cn/news/detail-828629.html
5)提升模型性能
上面訓(xùn)練時,沒有設(shè)置拉普拉斯估計,此處設(shè)為1,性能有所提升。文章來源地址http://www.zghlxwxcb.cn/news/detail-828629.html
## Step 5: Improving model performance ----
sms_classifier2 <- naiveBayes(sms_train,
sms_train_labels,
laplace = 1) #拉普拉斯估計值
sms_test_pred2 <- predict(sms_classifier2, sms_test)
CrossTable(sms_test_pred2, sms_test_labels,
prop.chisq = FALSE, prop.t = FALSE, prop.r = FALSE,
dnn = c('predicted', 'actual'))
到了這里,關(guān)于機器學(xué)習之概率學(xué)習樸素貝葉斯(NB)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!