O SVM usando o scikit learn é executado infinitamente e nunca conclui a execução


76

Estou tentando executar o SVR usando o scikit learn (python) em um conjunto de dados de treinamento com 595605 linhas e 5 colunas (recursos) e o conjunto de dados de teste com 397070 linhas. Os dados foram pré-processados ​​e regularizados.

Consigo executar os exemplos de teste com êxito, mas ao executar usando meu conjunto de dados e deixá-lo em execução por mais de uma hora, ainda não pude ver nenhuma saída ou término do programa. Eu tentei executar usando um IDE diferente e até mesmo do terminal, mas esse não parece ser o problema. Eu também tentei alterar o valor do parâmetro 'C' de 1 para 1e3.

Estou enfrentando problemas semelhantes com todas as implementações svm usando o scikit.

Não estou esperando o suficiente para concluir? Quanto tempo essa execução deve levar?

Pela minha experiência, não deve demorar alguns minutos.

Aqui está a configuração do meu sistema: Ubuntu 14.04, 8GB de RAM, muita memória livre, processador de quarta geração i7


Você poderia fornecer o código? Além disso, o treinamento ou o teste levam muito tempo? Que tal conjuntos de dados menores de treinamento / teste?
ffriend

Estou apenas lendo dados de um arquivo csv em um dataframe do pandas e passando-os para a função de aprendizado do scikit. Isso é tudo! Fornecer código não seria realmente ajudar aqui
tejaskhot

6
A implementação SVM do sklearn implica pelo menos três etapas: 1) criar um objeto SVR, 2) ajustar um modelo, 3) prever valor. O primeiro passo descreve o kernel em uso, o que ajuda a entender muito melhor os processos internos. O segundo e o terceiro passos são bem diferentes, e precisamos saber pelo menos qual deles leva tanto tempo. Se estiver treinando, pode ser bom, porque o aprendizado às vezes é lento. Se estiver testando, provavelmente há um erro, porque o teste no SVM é realmente rápido. Além disso, pode ser a leitura de CSV que leva tanto tempo e nem SVM. Portanto, todos esses detalhes podem ser importantes.
ffriend

Estou enfrentando o mesmo problema também através do svm, mas alguém pode me dizer quanto tempo vai demorar após a normalização?
Kashyap kitchlu

Respostas:


70

SVMs kernelizados requerem o cálculo de uma função de distância entre cada ponto do conjunto de dados, que é o custo dominante de . O armazenamento das distâncias é um fardo para a memória, portanto elas são recalculadas em tempo real. Felizmente, apenas os pontos mais próximos do limite de decisão são necessários na maioria das vezes. As distâncias frequentemente calculadas são armazenadas em um cache. Se o cache estiver sendo debulhado, o tempo de execução aumentará para .O ( n características × n 3 observações )O(nfeatures×nobservations2)O(nfeatures×nobservations3)

Você pode aumentar esse cache chamando o SVR como

model = SVR(cache_size=7000)

Em geral, isso não vai funcionar. Mas tudo não está perdido. Você pode subamostrar os dados e usar o restante como um conjunto de validação ou escolher um modelo diferente. Acima da faixa de 200.000 observações, é aconselhável escolher alunos lineares.

O SVM do kernel pode ser aproximado, aproximando a matriz do kernel e alimentando-o com um SVM linear. Isso permite que você alterne entre precisão e desempenho em tempo linear.

Um meio popular de conseguir isso é usar cerca de 100 centros de cluster encontrados por kmeans / kmeans ++ como base da função do seu kernel. Os novos recursos derivados são então alimentados em um modelo linear. Isso funciona muito bem na prática. Ferramentas como sophia-ml e vowpal wabbit são como o Google, Yahoo e Microsoft fazem isso. Entrada / saída se torna o custo dominante para alunos lineares simples.

Na abundância de dados, os modelos não paramétricos têm o mesmo desempenho na maioria dos problemas. As exceções são entradas estruturadas, como texto, imagens, séries temporais, áudio.

Leitura adicional


16

O SVM resolve um problema de otimização de ordem quadrática.

Não tenho nada a acrescentar que não tenha sido dito aqui. Eu só quero postar um link na página sklearn sobre SVC, que esclarece o que está acontecendo:

A implementação é baseada em libsvm. A complexidade do tempo de ajuste é mais do que quadrática com o número de amostras, o que dificulta o dimensionamento do conjunto de dados com mais de duas mil e cem amostras.

Se você não deseja usar kernels, e um SVM linear é suficiente, existe o LinearSVR, que é muito mais rápido porque usa uma abordagem de otimização em regressões lineares. Porém, você terá que normalizar seus dados, caso ainda não o esteja fazendo, porque aplica regularização ao coeficiente de interceptação, o que provavelmente não é o que você deseja. Isso significa que, se a média dos seus dados estiver longe de zero, não será possível resolvê-los satisfatoriamente.

O que você também pode usar é a descida estocástica do gradiente para resolver o problema de otimização. O Sklearn possui o SGDRegressor . Você precisa usar loss='epsilon_insensitive'para obter resultados semelhantes ao SVM linear. Veja a documentação. Eu usaria apenas a descida gradiente como último recurso, porque isso implica em muitos ajustes dos hiperparâmetros, a fim de evitar ficar preso nos mínimos locais. Use LinearSVRse puder.


Eu tinha um conjunto de dados com muitas linhas. O SVC começou a demorar muito para mim cerca de 150 mil linhas de dados. Usei sua sugestão com o LinearSVR e um milhão de linhas leva apenas alguns minutos. O PS também descobriu que o classificador LogisticRegression produz resultados semelhantes aos do LinearSVR (no meu caso) e é ainda mais rápido.
Jeffery_the_wind

8

Você incluiu a escala na sua etapa de pré-processamento? Eu tive esse problema ao executar meu SVM. Meu conjunto de dados é de ~ 780.000 amostras (linha) com 20 recursos (col). Meu conjunto de treinamento é de ~ 235k amostras. Acontece que eu esqueci de dimensionar meus dados! Se for esse o caso, tente adicionar este bit ao seu código:

dimensionar dados para [-1,1]; aumentar a velocidade SVM:

sklearn.preprocessing import MinMaxScaler
scaling = MinMaxScaler (range_range = (- 1,1)). fit (X_train)
X_train = scaling.transform (X_train)
X_test = scaling.transform (X_test)


2
Alguém pode explicar por que isso acelera o ajuste do SVM?
Lppier 10/05/19

1
Existe uma razão pela qual você escolheu o MinMaxScaler em vez de qualquer outro? StandardScaler, por exemplo?
Raspi

@ IPpp: essencialmente, você está reduzindo o espaço limite possível para cada opção de uma maneira que reduz o nível de esforço da sua máquina.
ike

7

Com um conjunto de dados tão grande, acho que seria melhor usar uma rede neural, aprendizado profundo, floresta aleatória (eles são surpreendentemente bons) etc.

Como mencionado nas respostas anteriores, o tempo gasto é proporcional à terceira potência do número de amostras de treinamento. Até o tempo de previsão é polinomial em termos de número de vetores de teste.

Se você realmente deve usar o SVM, recomendo usar a GPU para acelerar ou reduzir o tamanho do conjunto de dados de treinamento. Tente com uma amostra (talvez 10.000 linhas) dos dados primeiro para verificar se não há problema com o formato ou a distribuição dos dados.

Como mencionado em outras respostas, os kernels lineares são mais rápidos.


3

Recentemente, encontrei um problema semelhante porque esqueci de dimensionar recursos no meu conjunto de dados, que antes era usado para treinar o tipo de modelo de conjunto. A falta de escala dos dados pode ser o provável culpado, conforme apontado por Shelby Matlock. Você pode experimentar diferentes dimensionadores disponíveis no sklearn, como o RobustScaler :

from sklearn.preprocessing import RobustScaler scaler = RobustScaler() X = scaler.fit_transfrom(X)

O X agora está transformado / dimensionado e pronto para ser alimentado no modelo desejado.


2

Isso faz sentido. IIUC, a velocidade de execução das operações do vetor de suporte é limitada pelo número de amostras, não pela dimensionalidade. Em outras palavras, é limitado pelo tempo da CPU e não pela RAM. Não sei exatamente quanto tempo isso deve levar, mas estou executando alguns benchmarks para descobrir.


1

Deixe-o funcionar durante a noite ou melhor por 24 horas. Qual é a sua utilização de CPU? Se nenhum dos núcleos estiver funcionando a 100%, você terá um problema. Provavelmente com memória. Você verificou se o seu conjunto de dados se encaixa em 8 GB? Você já experimentou o SGDClassifier? É um dos mais rápidos lá. Vale a pena tentar primeiro, esperando que seja concluído em mais ou menos uma hora.


SGDClassifiernão suporta kernels. Se o OP quiser SVM linear, recomendo que tente primeiro LinearSVR. É muito mais rápido do que SVRporque resolve o problema usando uma biblioteca de regressão linear e o mínimo global é garantido (diferente da descida do gradiente).
Ricardo Cruz

Aprecie seu comentário. Você poderia explicar por que o suporte ao kernel é um problema?
Diego

Da documentação , a The loss function to be used. Defaults to ‘hinge’, which gives a linear SVM.mesma coisa para SGDRegressor. SGDRegressoré equivalente a usar SVR(kernel='linear'). Se é isso que o OP quer, isso é ótimo. Fiquei com a impressão de que ele queria usar o SVM com um kernel. Se não for esse o caso, eu recomendaria que ele tentasse primeiro LinearSVR.
Ricardo Cruz

1

Tente normalizar os dados para [-1,1]. Eu enfrentei um problema semelhante e, após a normalização, tudo funcionou bem. Você pode normalizar dados facilmente usando:

from sklearn import preprocessing X_train = preprocessing.scale(X_train) X_test = preprocessing.scale(X_test)


@ Archie Esta é uma resposta para uma pergunta, não uma pergunta.
timleathart

1

Eu encontrei esse problema e, cache_sizecomo outros sugerem, não ajuda em nada. Você pode ver esta postagem e esta como o principal colaborador sugerido que você deve alterar o código manualmente.

Como você sabe, SVCe SVRsão problemas de otimização e eles param quando a margem de erro é tão pouco onde a otimização é fútil. Portanto, há outro parâmetro neles, max_iteronde você pode definir quantas iterações devem fazer.

Eu usei sklearnem python e e1071em R e R é muito mais rápido chegar ao resultado sem definir o max_itere sklearnleva 2-4 vezes mais. A única maneira de reduzir o tempo de computação do python era usando max_iter. É em relação à complexidade do modelo, o número de recursos, grãos e hiperparâmetros, mas para pequenas dataset eu usei por cerca de 4000 datapoint e max_iterfoi 10000os resultados não foram diferentes em tudo e foi aceitável.


0

Acabei de ter um problema semelhante com um conjunto de dados que contém apenas 115 elementos e apenas um único recurso (dados de companhias aéreas internacionais). A solução foi dimensionar os dados. O que eu perdi nas respostas até agora foi o uso de um Pipeline:

from sklearn.svm import SVR
from sklearn.preprocessing import StandardScaler, MinMaxScaler

model = Pipeline([('scaler', StandardScaler()),
                  ('svr', SVR(kernel='linear'))])

Você pode treinar modelcomo um modelo usual de classificação / regressão e avaliá-lo da mesma maneira. Nada muda, apenas a definição do modelo.


O que é Pipeline? Você não está importando.
Bram Vanroy 26/01

0

Você precisa dimensionar seus dados. A escala normalizará seus pontos de dados para -1 a 1, o que ajudará a uma convergência mais rápida.

Tente usar o seguinte código:

# X is your numpy data array.

from sklearn import preprocessing

X = preprocessing.scale(X)

bem-vindo ao Data Science SE! Você poderia explicar como sua sugestão ajudará a OP? O que você está sugerindo é uma escala de uma matriz. Não está claro como isso pode ou não afetar o algoritmo SVR no scikit learn.
Stereo
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.