Estou tentando criar um SVM a partir de dados de treinamento em que um grupo é representado mais que o outro. No entanto, os grupos serão igualmente representados nos eventuais dados do teste. Portanto, eu gostaria de usar o class.weights
parâmetro da e1071
interface do pacote R libsvm
para equilibrar a influência dos dois grupos nos dados de treinamento.
Como não sabia exatamente como esses pesos deveriam ser especificados, configurei um pequeno teste:
- Gere alguns dados nulos (recursos aleatórios; proporção 2: 1 entre rótulos de grupos)
- Ajuste um svm com o
class.weights
conjunto de parâmetros. - Preveja vários novos conjuntos de dados nulos e analise as proporções da classe.
- Replicar todo o processo várias vezes para diferentes conjuntos de treinamento nulo.
Aqui está o código R que estou usando:
nullSVM <- function(n.var, n.obs) {
# Simulate null training data
vars = matrix(rnorm(n.var*n.obs), nrow=n.obs)
labels = rep(c('a', 'a', 'b'), length.out=n.obs)
data = data.frame(group=labels, vars)
# Fit SVM
fit = svm(group ~ ., data=data, class.weights=c(a=0.5, b=1))
# Calculate the average fraction of 'a' we would predict from null test data
mean(replicate(50, table(predict(fit, data.frame(matrix(rnorm(n.var*n.obs), nrow=n.obs))))[1])) / n.obs
}
library(e1071)
set.seed(12345)
mean(replicate(50, nullSVM(50, 300)))
De tudo isso, eu estava esperando uma saída ~ 0.5, no entanto, não foi isso que obtive:
> mean(replicate(50, nullSVM(50, 300)))
[1] 0.6429987
O class.weights
paramter está funcionando, espécie de , como o menor peso I a
, menor é representado nesta simulação (e se eu omitir class.weights
ele retorna próximo de 1) ... mas eu não entendo por que simplesmente usando pesos de 1: 2 ( para dados de treinamento que são 2: 1) não me leva até 50%.
Se estou entendendo mal os SVMs, alguém pode explicar esse ponto? (ou enviar algumas referências?)
Se estou fazendo errado, alguém pode me dizer a maneira correta de usar o class.weights
parâmetro?
Poderia ser um bug? (Acho que não, pois entendo que este software e a libsvm subjacente são bastante maduros)
fonte
Respostas:
Eu acho que pode depender dos valores de C e do número de padrões que você possui. O SVM tenta encontrar a margem máxima discriminante; portanto, se você tiver dados esparsos, é possível que o SVM encontre a solução de margem dura sem que nenhum dos multiplicadores Lagrange atinja seus limites superiores (nesse caso, a taxa de penalidades para cada classe é essencialmente irrelevante, pois as folgas são pequenas ou zero.Tente aumentar o número de padrões de treinamento e veja se isso tem algum efeito (pois isso torna menos provável que a solução de margem rígida possa ser encontrada dentro das restrições da caixa) .
Mais importante, os valores ótimos de C são dependentes dos dados; você não pode apenas configurá-los para alguns valores predeterminados, mas, em vez disso, otimizá-los, minimizando o erro de deixar um para fora ou algum limite de generalização. Se você tiver classes desequilibradas, poderá fixar a proporção dos valores para cada classe e otimizar a penalidade média sobre todos os padrões.
fonte
caret
pacote ou atune()
função incorporada para o ajuste de parâmetros do modelo, por isso gosto especialmente da sua segunda ideia de como lidar com isso na prática, ajustando o esquema de reamostragem para favorecer a classe minoritária. Muito apreciado.no treinamento, svm encontre vetores de suporte para criar um limite discriminativo e, quando houver vetores de suporte suficientes para todos os dados das classes, isso não será problema. na precisão dos resultados do conjunto de testes, você deve considerar a quantidade de dados de igualdade para todas as classes no mundo real e, para obter resultados reais, você deve manipular os dados e eles são considerados adequadamente na situação real.
fonte