朴素贝叶斯的特征选择
feature selection for Naive Bayes
我用朴素贝叶斯做了分类。目标是通过文本预测 4 个因素。数据如下所示:
'data.frame': 387 obs. of 2 variables:
$ reviewText: chr "I love this. I have a D800. I am mention my camera to make sure that you understand that this product is not ju"| __truncated__ "I hate buying larger gig memory cards - because there's always that greater risk of losing the photos, and/or r"| __truncated__ "These chromebooks are really a pretty nice idea -- Almost no maintaince (no maintaince?), no moving parts, smal"| __truncated__ "Purchased, as this drive allows a much speedier read/write and is just below a full SSD (they need to drop the "| __truncated__ ...
$ pragmatic : Factor w/ 4 levels "-1","0","1","9": 4 4 4 3 3 4 3 3 3...
我用caret
包做了分类。分类代码如下所示:
sms_corpus <- Corpus(VectorSource(sms_raw$text))
sms_corpus_clean <- sms_corpus %>%
tm_map(content_transformer(tolower)) %>%
tm_map(removeNumbers) %>%
tm_map(removeWords, stopwords(kind="en")) %>%
tm_map(removePunctuation) %>%
tm_map(stripWhitespace)
sms_dtm <- DocumentTermMatrix(sms_corpus_clean)
train_index <- createDataPartition(sms_raw$type, p=0.5, list=FALSE)
sms_raw_train <- sms_raw[train_index,]
sms_raw_test <- sms_raw[-train_index,]
sms_corpus_clean_train <- sms_corpus_clean[train_index]
sms_corpus_clean_test <- sms_corpus_clean[-train_index]
sms_dtm_train <- sms_dtm[train_index,]
sms_dtm_test <- sms_dtm[-train_index,]
sms_dict <- findFreqTerms(sms_dtm_train, lowfreq= 5)
sms_train <- DocumentTermMatrix(sms_corpus_clean_train, list(dictionary=sms_dict))
sms_test <- DocumentTermMatrix(sms_corpus_clean_test, list(dictionary=sms_dict))
convert_counts <- function(x) {
x <- ifelse(x > 0, 1, 0)
x <- factor(x, levels = c(0, 1), labels = c("Absent", "Present"))
}
sms_train <- sms_train %>% apply(MARGIN=2, FUN=convert_counts)
sms_test <- sms_test %>% apply(MARGIN=2, FUN=convert_counts)
ctrl <- trainControl(method="cv", 10)
set.seed(8)
sms_model1 <- train(sms_train, sms_raw_train$type, method="nb",
trControl=ctrl)
sms_predict1 <- predict(sms_model1, sms_test)
cm1 <- confusionMatrix(sms_predict1, sms_raw_test$type)
当我以这种方式使用这个模型时,这意味着我同时对所有 4 个变量进行预测,我得到一个较低的 Accuracy:0.5469
,混淆矩阵看起来像这样。
Reference
Prediction -1 0 1 9
-1 0 0 1 0
0 0 0 0 0
1 9 5 33 25
9 11 3 33 72
当我分别对所有 4 个变量进行预测时,我得到了更好的结果。分类代码与上面相同,但我使用 df$sensorial <- as.factor(df$sensorial == 9)
而不是 df$sensorial <- factor(df$sensorial)
。对于其他变量,我使用 1
、-1
或 0
而不是 9
。如果我这样做,我会得到 9
的 Accuracy: 0.772
,-1
的 Accuracy:0.829
,0
的 Accuracy:0.9016
和1
的 Accuracy:0.7959
。此外,结果要好得多。所以一定和特征selection有关。不同结果的原因可能是不同值的特征通常相同。因此,一个可能的解决方案可能是赋予那些仅在存在特定值而不存在其他值时才发生的特征更重要。有没有办法以这种方式 select 特征,以便如果我同时对所有 4 个变量进行预测,模型会更好?像加权术语文档矩阵之类的东西?
编辑:
我像 Cihan Ceyhan 所说的那样计算了四个值的权重:
prop.table(table(sms_raw_train$type))
-1 0 1 9
0.025773196 0.005154639 0.180412371 0.788659794
modelweights <- ifelse(sms_raw_train$type == -1,
(1/table(sms_raw_train$type)[1]) * 0.25,
ifelse(sms_raw_train$type == 0,
(1/table(sms_raw_train$type)[2]) * 0.25,
ifelse(sms_raw_train$type == 1,
(1/table(sms_raw_train$type)[3]) * 0.25,
ifelse(sms_raw_train$type == 9,
(1/table(sms_raw_train$type)[4]) * 0.25,9))))
但结果并没有更好Accuracy:0.5677
Reference
Prediction -1 0 1 9
-1 1 0 1 1
0 1 0 1 0
1 11 3 32 20
9 7 5 33 76
因此,也许最好分别计算每个值的结果,然后像发布的第二个解决方案那样将结果相加。
准确性是此处使用的误导性指标。在您发布的多标签混淆矩阵中,如果您只查看标签 -1
与 others
,则准确率约为 89%。因为您只预测 -1
一次,并且将 -1
错误分类为 others
20 次 (9+11)。对于所有其他情况,您 class 正确验证 -1
与 others
问题,因此 170/191=89%
准确。但这当然并不意味着该模型按预期工作;它只是在几乎所有情况下打印 others
。这种机制也是您在单个标签 classifications 中看到更高准确度数字的原因。
请参阅 here,了解 class 不平衡问题的概述,以及缓解该问题的可能方法。
另外这个thread跟你的case很相关,建议你看看
我用朴素贝叶斯做了分类。目标是通过文本预测 4 个因素。数据如下所示:
'data.frame': 387 obs. of 2 variables:
$ reviewText: chr "I love this. I have a D800. I am mention my camera to make sure that you understand that this product is not ju"| __truncated__ "I hate buying larger gig memory cards - because there's always that greater risk of losing the photos, and/or r"| __truncated__ "These chromebooks are really a pretty nice idea -- Almost no maintaince (no maintaince?), no moving parts, smal"| __truncated__ "Purchased, as this drive allows a much speedier read/write and is just below a full SSD (they need to drop the "| __truncated__ ...
$ pragmatic : Factor w/ 4 levels "-1","0","1","9": 4 4 4 3 3 4 3 3 3...
我用caret
包做了分类。分类代码如下所示:
sms_corpus <- Corpus(VectorSource(sms_raw$text))
sms_corpus_clean <- sms_corpus %>%
tm_map(content_transformer(tolower)) %>%
tm_map(removeNumbers) %>%
tm_map(removeWords, stopwords(kind="en")) %>%
tm_map(removePunctuation) %>%
tm_map(stripWhitespace)
sms_dtm <- DocumentTermMatrix(sms_corpus_clean)
train_index <- createDataPartition(sms_raw$type, p=0.5, list=FALSE)
sms_raw_train <- sms_raw[train_index,]
sms_raw_test <- sms_raw[-train_index,]
sms_corpus_clean_train <- sms_corpus_clean[train_index]
sms_corpus_clean_test <- sms_corpus_clean[-train_index]
sms_dtm_train <- sms_dtm[train_index,]
sms_dtm_test <- sms_dtm[-train_index,]
sms_dict <- findFreqTerms(sms_dtm_train, lowfreq= 5)
sms_train <- DocumentTermMatrix(sms_corpus_clean_train, list(dictionary=sms_dict))
sms_test <- DocumentTermMatrix(sms_corpus_clean_test, list(dictionary=sms_dict))
convert_counts <- function(x) {
x <- ifelse(x > 0, 1, 0)
x <- factor(x, levels = c(0, 1), labels = c("Absent", "Present"))
}
sms_train <- sms_train %>% apply(MARGIN=2, FUN=convert_counts)
sms_test <- sms_test %>% apply(MARGIN=2, FUN=convert_counts)
ctrl <- trainControl(method="cv", 10)
set.seed(8)
sms_model1 <- train(sms_train, sms_raw_train$type, method="nb",
trControl=ctrl)
sms_predict1 <- predict(sms_model1, sms_test)
cm1 <- confusionMatrix(sms_predict1, sms_raw_test$type)
当我以这种方式使用这个模型时,这意味着我同时对所有 4 个变量进行预测,我得到一个较低的 Accuracy:0.5469
,混淆矩阵看起来像这样。
Reference
Prediction -1 0 1 9
-1 0 0 1 0
0 0 0 0 0
1 9 5 33 25
9 11 3 33 72
当我分别对所有 4 个变量进行预测时,我得到了更好的结果。分类代码与上面相同,但我使用 df$sensorial <- as.factor(df$sensorial == 9)
而不是 df$sensorial <- factor(df$sensorial)
。对于其他变量,我使用 1
、-1
或 0
而不是 9
。如果我这样做,我会得到 9
的 Accuracy: 0.772
,-1
的 Accuracy:0.829
,0
的 Accuracy:0.9016
和1
的 Accuracy:0.7959
。此外,结果要好得多。所以一定和特征selection有关。不同结果的原因可能是不同值的特征通常相同。因此,一个可能的解决方案可能是赋予那些仅在存在特定值而不存在其他值时才发生的特征更重要。有没有办法以这种方式 select 特征,以便如果我同时对所有 4 个变量进行预测,模型会更好?像加权术语文档矩阵之类的东西?
编辑:
我像 Cihan Ceyhan 所说的那样计算了四个值的权重:
prop.table(table(sms_raw_train$type))
-1 0 1 9
0.025773196 0.005154639 0.180412371 0.788659794
modelweights <- ifelse(sms_raw_train$type == -1,
(1/table(sms_raw_train$type)[1]) * 0.25,
ifelse(sms_raw_train$type == 0,
(1/table(sms_raw_train$type)[2]) * 0.25,
ifelse(sms_raw_train$type == 1,
(1/table(sms_raw_train$type)[3]) * 0.25,
ifelse(sms_raw_train$type == 9,
(1/table(sms_raw_train$type)[4]) * 0.25,9))))
但结果并没有更好Accuracy:0.5677
Reference
Prediction -1 0 1 9
-1 1 0 1 1
0 1 0 1 0
1 11 3 32 20
9 7 5 33 76
因此,也许最好分别计算每个值的结果,然后像发布的第二个解决方案那样将结果相加。
准确性是此处使用的误导性指标。在您发布的多标签混淆矩阵中,如果您只查看标签 -1
与 others
,则准确率约为 89%。因为您只预测 -1
一次,并且将 -1
错误分类为 others
20 次 (9+11)。对于所有其他情况,您 class 正确验证 -1
与 others
问题,因此 170/191=89%
准确。但这当然并不意味着该模型按预期工作;它只是在几乎所有情况下打印 others
。这种机制也是您在单个标签 classifications 中看到更高准确度数字的原因。
请参阅 here,了解 class 不平衡问题的概述,以及缓解该问题的可能方法。
另外这个thread跟你的case很相关,建议你看看