Ram*_*nda 5 python r weka confusion-matrix multilabel-classification
我正在对实际数据和分类器的预测数据进行多标签分类。实际数据由三个类(c1、c2 和 c3)组成,同样,预测数据也由三个类(c1、c2 和 c3)组成。数据如下
Actual_data Predicted_data
c1 c2 c3 c1 c2 c3
1 1 0 1 1 1
1 1 0 1 0 1
1 0 1 0 1 1
0 1 1 1 0 0
1 0 0 1 1 0
1 1 1 1 0 1
Run Code Online (Sandbox Code Playgroud)
在多标签分类中,一份文档可能属于多个类别。在上面的数据中,1代表文档属于特定类别,0代表文档不属于特定类别。
Actual_data 的第一行表示文档属于类 c1 和 c2,不属于类 c3。类似地,predicted_data 的第一行表示文档属于类 c1、c2 和 c3。
最初,我使用 R 编程来查找实际数据和预测数据之间的混淆矩阵。我将这些数据框保存在 y_actual 和 y_predict 中。
y_actual<-as.matrix(Actual_data)
y_predict<-as.matrix(Predicted_data)
xtab<-table(y_actual,y_predict)
Run Code Online (Sandbox Code Playgroud)
输出xtab是
y_predict
y_actual 0 1
0 1 5
1 5 7
Run Code Online (Sandbox Code Playgroud)
然后我使用 R 的插入符包创建了混淆矩阵,如下所示
library(caret)
confusionMatrix(xtab)
Confusion Matrix and Statistics
y_predict
y_actual 0 1
0 1 5
1 5 7
Accuracy : 0.4444
95% CI : (0.2153, 0.6924)
No Information Rate : 0.6667
P-Value [Acc > NIR] : 0.9856
Kappa : -0.25
Mcnemar's Test P-Value : 1.0000
Sensitivity : 0.16667
Specificity : 0.58333
Pos Pred Value : 0.16667
Neg Pred Value : 0.58333
Prevalence : 0.33333
Detection Rate : 0.05556
Detection Prevalence : 0.33333
Balanced Accuracy : 0.37500
'Positive' Class : 0
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我没有得到多标签混淆矩阵,而是得到了二进制标签混淆矩阵。我想要一个混淆矩阵,其中 y-实际和 y-预测中包含 c1,c2,c3,而不是 y-实际和 y-预测中的 0,1。
然后我在互联网上搜索,utiml包用于R中的多标签分类,但没有提供所需的输出。然后我尝试了python的scikit包进行多标签分类,代码如下。
import numpy as np
from sklearn.metrics import multilabel_confusion_matrix
y_actual = np.array([[1, 1, 0],
[1, 1, 0],
[1, 0, 1],
[0, 1, 1],
[1, 0, 0],
[1, 1, 1]])
y_predict = np.array([[1, 1, 1],
[1, 0, 1],
[0, 1, 1],
[1, 0, 0],
[1, 1, 0],
[1, 0, 1]])
matrix = multilabel_confusion_matrix(y_actual, y_predict)
print(matrix)
print(classification_report(y_actual,y_predict))
Run Code Online (Sandbox Code Playgroud)
程序的输出是
[[[0 1]
[1 4]]
[[0 2]
[3 1]]
[[1 2]
[1 2]]]
precision recall f1-score support
0 0.80 0.80 0.80 5
1 0.33 0.25 0.29 4
2 0.50 0.67 0.57 3
micro avg 0.58 0.58 0.58 12
macro avg 0.54 0.57 0.55 12
weighted avg 0.57 0.58 0.57 12
samples avg 0.53 0.61 0.54 12
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我也没有明智地获得输出标签。任何人都可以帮助我在任何平台(R编程、python或weka)中需要使用哪种包来获取上述实际数据和预测数据的多标签混淆矩阵。在输出中,y_actual 和 y_predict 的 c1、c2 和 c3 的混淆矩阵需要是 3*3 矩阵。
y_predict
y_actual c1 c2 c3
c1 4
c2 1
c3 2
Run Code Online (Sandbox Code Playgroud)
这里对角线元素表明它实际上属于 c1,并且分类器预测它属于 c1。c2 和 c3 也类似。我的问题是如何获取混淆矩阵的其他值,因为它是多标签分类。这个问题不是多类分类问题,而是多标签分类问题。
一种解决方案是改变数据的表示方式,使其符合混淆矩阵的内容caret或预期。sklearn如果您认为混淆矩阵中的每个单元代表一个离散类预测(即“对于这个类,我们预测这个,但我们实际上看到这个”),那么您可以看到没有办法实际构造这样的矩阵对于您的示例,其中类可以同时具有值。
考虑到这一点,在您的示例中,您实际上并没有三个独立的类别 - 您有 8 个。
这意味着对于每一行观察结果,给定存在的三个分类值,您的数据点可能会呈现:
none of the categories
only c1
c1&c2
c1&c3
only c2
c2&c3
only c3
all categories
Run Code Online (Sandbox Code Playgroud)
您需要做的就是向数据框中添加一个新列,重新编码您的三个现有目标列,以便新列采用 1 或 8 个值来指示这些组合中的每一个。
下面是一个解决方案的示例:
#Recreating your data
Actual_data <- cbind(c(1, 1, 1, 0, 1, 1),
c(1, 1, 0, 1, 0, 1),
c(0, 0, 1, 1, 0, 1)
)
colnames(Actual_data) <- c("c1", "c2", "c3")
Predicted_data <- cbind(c(1, 1, 0, 1, 1, 1),
c(1, 0, 1, 0, 1, 0),
c(1, 1, 1, 0, 0, 1)
)
colnames(Predicted_data) <- c("c1", "c2", "c3")
#To make it easy to recode everything, we can convert these two objects into dataframes:
Predicted_data <-as.data.frame(Predicted_data)
Actual_data <- as.data.frame(Actual_data)
#Next, we make a simple function that goes through each row and recodes the class
#combinations to a distinct category
set_class_combinations <- function(df){
df$target <- 0
for (i in nrow(df)){
df$target[df$c1 == 0 & df$c2 == 0 & df$c3 == 0] <- 1
df$target[df$c1 == 1 & df$c2 == 0 & df$c3 == 0] <- 2
df$target[df$c1 == 1 & df$c2 == 1 & df$c3 == 0] <- 3
df$target[df$c1 == 1 & df$c2 == 0 & df$c3 == 1] <- 4
df$target[df$c1 == 0 & df$c2 == 1 & df$c3 == 0] <- 5
df$target[df$c1 == 0 & df$c2 == 1 & df$c3 == 1] <- 6
df$target[df$c1 == 0 & df$c2 == 0 & df$c3 == 1] <- 7
df$target[df$c1 == 1 & df$c2 == 1 & df$c3 == 1] <- 8
}
return(df)
}
#With the function, we can add a new "target" column to our respective dataframes
Predicted_data <- set_class_combinations(Predicted_data)
Actual_data <- set_class_combinations(Actual_data)
#As your example does not include all available combinations, we just need to ensure that we
#account for this when we set the factor levels (1 through 8) and call the `confusionMatrix` function
cm <- confusionMatrix(factor(Predicted_data$target, levels = 1:8), factor(Actual_data$target, levels = 1:8))
print(cm)
Run Code Online (Sandbox Code Playgroud)