如何使用SOM算法进行分类预测?

3

我希望看到 SOM 算法是否可用于分类预测。我曾经编写了以下代码,但是发现分类结果与正确的结果相差甚远。例如,在测试数据集中,我得到了比训练目标变量中的3个值更多的值。我该如何创建一个能够与训练目标变量保持一致的预测模型?

library(kohonen)
    library(HDclassif)
    data(wine)
    set.seed(7)

    training <- sample(nrow(wine), 120)
    Xtraining <- scale(wine[training, ])
    Xtest <- scale(wine[-training, ],
                   center = attr(Xtraining, "scaled:center"),
                   scale = attr(Xtraining, "scaled:scale"))

    som.wine <- som(Xtraining, grid = somgrid(5, 5, "hexagonal"))


som.prediction$pred <- predict(som.wine, newdata = Xtest,
                          trainX = Xtraining,
                          trainY = factor(Xtraining$class))

结果如下:

$unit.classif

 [1]  7  7  1  7  1 11  6  2  2  7  7 12 11 11 12  2  7  7  7  1  2  7  2 16 20 24 25 16 13 17 23 22
[33] 24 18  8 22 17 16 22 18 22 22 18 23 22 18 18 13 10 14 15  4  4 14 14 15 15  4
1个回答

2
这可能有所帮助:
  • SOM是一种无监督分类算法,因此您不应该期望它在包含分类器标签的数据集上进行训练(如果这样做,它将需要此信息才能工作,并且在没有标记的数据集上无用)
  • 想法是它将会“转换”输入数字向量为网络单元编号(尝试使用1每3网格重新运行代码,您将得到预期的输出)
  • 然后,您需要将这些网络单元编号转换回您正在寻找的类别(这是您的代码中缺失的关键部分)

下面的可重现示例将输出经典分类错误。它包括原始帖子中缺失的“转换回”部分的一个实现选项。

虽然对于这个特定的数据集,模型很快就会过度拟合:3个单位可以得到最好的结果。

#Set and scale a training set (-1 to drop the classes)
data(wine)
set.seed(7)
training <- sample(nrow(wine), 120)
Xtraining <- scale(wine[training, -1])

#Scale a test set (-1 to drop the classes)
Xtest <- scale(wine[-training, -1],
               center = attr(Xtraining, "scaled:center"),
               scale = attr(Xtraining, "scaled:scale"))

#Set 2D grid resolution
#WARNING: it overfits pretty quickly
#Errors are 36% for 1 unit, 63% for 2, 93% for 3, 89% for 4
som_grid <- somgrid(xdim = 1, ydim=3, topo="hexagonal")

#Create a trained model
som_model <- som(Xtraining, som_grid)

#Make a prediction on test data
som.prediction <- predict(som_model, newdata = Xtest)

#Put together original classes and SOM classifications
error.df <- data.frame(real = wine[-training, 1],
                       predicted = som.prediction$unit.classif)

#Return the category number that has the strongest association with the unit
#number (0 stands for ambiguous)
switch <- sapply(unique(som_model$unit.classif), function(x, df){
  cat <- as.numeric(names(which.max(table(
    error.df[error.df$predicted==x,1]))))
  if(length(cat)<1){
    cat <- 0
  }
  return(c(x, cat))
}, df = data.frame(real = wine[training, 1], predicted = som_model$unit.classif))

#Translate units numbers into classes
error.df$corrected <- apply(error.df, MARGIN = 1, function(x, switch){
  cat <- switch[2, which(switch[1,] == x["predicted"])]
  if(length(cat)<1){
    cat <- 0
  }
  return(cat)
}, switch = switch)

#Compute a classification error
sum(error.df$corrected == error.df$real)/length(error.df$real)

感谢@Kevin Dallaporta提供的代码示例。我有两个问题,首先我使用了trainY = factor(Xtraining$class),但是在你的预测函数中我没有看到它。其次,我该如何将类别预测结果附加到测试数据集上? - mql4beginner
很高兴它有所帮助!似乎在kohonen的V2.X版本中存在trainY = factor参数,但在V3.X中消失了。我不知道它应该做什么,但是无论有没有它,返回值都是相同的,并且在2017年3月的文档中没有任何痕迹。在我提供的代码中,预测结果在error.df$corrected中,因此您可以使用以下内容将其附加到测试中:test$predicted <- error.df$corrected - user5730831

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接