一类 SVM 总是返回 FALSE

Posted

技术标签:

【中文标题】一类 SVM 总是返回 FALSE【英文标题】:One class SVM always returns FALSE 【发布时间】:2022-01-05 02:39:18 【问题描述】:

我的机器学习课程中有一个关于异常/新奇检测的项目,并决定研究本文所述的一类 SVM 算法:http://research.microsoft.com/pubs/69731/tr-99-87.pdf。在 R 中的包 e1071 中有一个 svm 函数,它似乎支持一类分类。但是,当我尝试使用它时,预测器总是返回 false(即使在训练集上,这是最奇怪的事情)。这是我的代码:

library(e1071) # for svm classifier
library(IMIFA) # for USPS dataset
library(caret) # for confusion matrices

data(USPSdigits)

digits.train <- USPSdigits$train
digits.train <- digits.train[order(digits.train$V1), ]
digits.train$is.zero[digits.train$V1 == 0] <- "TRUE"
digits.train$is.zero[digits.train$V1 != 0] <- "FALSE"
digits.test <- USPSdigits$test
digits.test <- digits.test[order(digits.test$V1), ]
digits.test$is.zero[digits.test$V1 == 0] <- "TRUE"
digits.test$is.zero[digits.test$V1 != 0] <- "FALSE"

digits.train.features <- digits.train[digits.train$V1 == 0, -c(1, 258)]
digits.train.labels <- digits.train[digits.train$V1 == 0, 258]
digits.train.nu <- 0.5
digits.train.bandwith <- 0.5*256
digits.train.model <- svm(x = digits.train.features, type = 'one-classification', kernel = 'radial', nu = digits.train.nu, gamma = digits.train.bandwith)
digits.train.fitted <- predict(digits.train.model, digits.train.features)
digits.train.confusionMatrix <- table(Predicted = digits.train.fitted, Reference = digits.train.labels)
print(digits.train.confusionMatrix)

digits.test.features <- subset(digits.test, select = -c(is.zero, V1))
digits.test.labels <- digits.test$is.zero
digits.test.fitted <- predict(digits.train.model, digits.test.features)
digits.test.confusionMatrix <- table(Predicted = digits.test.fitted, Reference = digits.test.labels)
print(digits.test.confusionMatrix)

我的输出是:

> print(digits.train.confusionMatrix)
         Reference
Predicted TRUE
    FALSE 1194
> print(digits.test.confusionMatrix)
         Reference
Predicted FALSE TRUE
    FALSE  1648  359

我做错了什么?

【问题讨论】:

this post 对您有帮助吗? 我已经看过这篇文章,我的代码受到了它的启发,但是在这个更复杂的数据集上它似乎不起作用 【参考方案1】:

我创建了一个工作示例。将命名约定调整为您自己的。我使用了一个非常有表现力的命名约定来准确地展示我所做的事情。

仅对 1 个数字进行训练会导致许多列具有相同的值。这些在svm 中作为错误返回,应该被删除。 caret 中的函数nearZeroVar 是一个理想的函数。如果你曾经使用过 recipes 包,它被称为 step_nzv

library(e1071)
# library(caret) # caret used for nearZeroVar function.

# data steps like OP's
digits.train <- USPSdigits$train
digits.test <- USPSdigits$test

digits.train$is.zero[digits.train$V1 == 0] <- "TRUE"
digits.train$is.zero[digits.train$V1 != 0] <- "FALSE"


digits.test$is.zero[digits.test$V1 == 0] <- "TRUE"
digits.test$is.zero[digits.test$V1 != 0] <- "FALSE"


train_the_positives <- subset(digits.train, is.zero == "TRUE")

# get the columns with 99% of the same values
cols_to_remove <- caret::nearZeroVar(train_the_positives, freqCut = 99/1)

svm.model <- svm(train_the_positives[, -cols_to_remove],
                 type = 'one-classification',
                 nu = 0.10,
                 kernel = "radial")

# predictions on train_the_positives set
svm_predictions_on_train_the_positives <- predict(svm.model, train_the_positives[, -cols_to_remove])
table(Predicted = svm_predictions_on_train_the_positives,
      Reference = train_the_positives$is.zero)

         Reference
Predicted TRUE
    FALSE  121
    TRUE  1073

# predictions on full train set
svm_prediction_on_full_train_set <- predict(svm.model, digits.train[, -cols_to_remove])
table(Predicted = svm_prediction_on_full_train_set,
      Reference = digits.train$is.zero)

         Reference
Predicted FALSE TRUE
    FALSE  6069  121
    TRUE     28 1073


# predictions on test set
svm_prediction_on_test_set <- predict(svm.model, digits.test[, -cols_to_remove])
table(Predicted = svm_prediction_on_test_set,
      Reference = digits.test$is.zero)

         Reference
Predicted FALSE TRUE
    FALSE  1638   68
    TRUE     10  291

【讨论】:

天哪,它的工作原理很神奇!非常感谢 !!你知道错误可能来自哪里吗?是从数学方面还是从计算方面? @tudoroancea,我注意到当我运行你的 svm 时,它在运行时在计算中产生了错误,但仍然创建了一个模型。可能是由于一些固定变量。另外,请接受答案,因为这会将问题标记为已关闭。

以上是关于一类 SVM 总是返回 FALSE的主要内容,如果未能解决你的问题,请参考以下文章

为啥 WinAPI FormatMessage 失败,总是返回 false

具有布尔返回类型的飞镖未来方法总是返回 false

HttpClient IsComplete 总是返回 false

设置文件权限总是返回 FALSE

为啥 QFile::canReadLine() 总是返回 false?

为啥我的 Laravel 策略总是返回 false?