Nos últimos anos a indústria de seguros tem buscado maneiras de aprimorar seus modelos usando Machine Learning. Uma delas é utilizar dados que vão além de um formulário preenchido pelo segurado para determinar o risco de acidentes.

Um dos métodos utilizados é usar dados comportamentais do motorista, obtidos através de rastreamento via GPS. Desta maneira acredita-se ser possível capturar informações e padrões de perfil que vão além dos métodos tradicionais.

O que torna um motorista diferente do outro? Identificar o motorista que está conduzindo um veículo durante uma viagem é o primeiro passo para conseguirmos um bom modelo.

Índice

Descrição da Competição

A seguradora AXA decidiu disponibilizar viagens anônimas de aproximadamente 2700 motoristas. Para cada motorista são 200 viagens, sendo que algumas delas não são do motorista em questão, e a tarefa era criar um modelo que identificasse quais eram as viagens atribuídas a este motorista incorretamente.

Para evitar o vazamento de informações, os dados foram centralizados e rotacionados de maneira aleatória, além de ter alguns trechos das viagens removidos do início e do fim.

Dados

No total foram disponibilizadas 200 viagens de 2736 motoristas. Dentro da pasta de cada motorista havia uma quantidade aleatória de viagens falsamente atribuídas ao motorista em questão. Uma informação importante é que tínhamos a garantia que a maioria das viagens pertencia verdadeiramente ao motorista.

Cada viagem era descrita em um arquivo CSV com um valor numérico para a posição x e y, que seria a distância da origem, em metros, e cada linha correspondia a 1 segundo de viagem.

Métrica

A métrica utilizada para avaliação foi a área sob a curva ROC, abreviada por AUC.

Features

Os atributos que utilizei se baseiam principalmente nas três primeiras derivadas do deslocamento: velocidade, aceleração e arrancada. Outras derivadas acabavam por prejudicar a performance.

Frequências - FFT

Procurei extrair frequências, tanto dos dados originais brutos, quanto das derivadas. Fiz isto com a função FFT (Fast Fourier Transform) disponível no Numpy. Dividi o intervalo de frequências por 20, e o valor dos atributos era a soma das frequências do respectivo intervalo.

Neste caso eu extraí as frequências isoladas para cada componente (x e y). Talvez obter as frequências usando a velocidade e aceleração, considerando os dois componentes juntos, seja melhor, mas não testei esta hipótese.

O AUC máximo que consegui, usando frequências das três derivadas, foi 0,7058, com uma regressão logística sem otimização de parâmetros. Apesar de não ter testado, acredito que otimizando os parâmetros do modelo para cada motorista este número poderia ser aumentado até um máximo de 0,73.

Histogramas

Esta é a transformação que encontrei em todos os trabalhos acadêmicos que li sobre o assunto. Consiste em fazer um histograma dos atributos. Neste caso, ganhamos um novo parâmetro, o tamanho dos intervalos.

A melhor maneira que encontrei foi dividir a magnitude da velocidade em 50 intervalos, e a aceleração, em 10.

Dois detalhes que melhoraram a performance: utilizar o atributo “density” da função do Numpy, que calcula a função densidade da probabilidade, e normalizar os resultados para que sua soma fosse 1.

Valores em Porcentagens

Outra sugestão bastante frequente era utilizar o valor dos atributos em determinadas porcentagens. Isso ajuda a descobrir quão extremos são os valores dos mesmos.

Um exemplo pode facilitar o entendimento: no caso da velocidade, para obter o valor presente no percentil 5%, ordenei os valores de maneira crescente e localizei o ponto da lista que representava a fronteira dos primeiros 5% dos dados ordenados.

Se tivermos uma lista com 100 valores de velocidade ordenados, com um índice que vai de 1 a 100, o valor presente na posição 5 seria o desejado. O valor presente na posição 50, por exemplo, seria a mediana.

Isso é importante porque diferencia motoristas que possuem um perfil mais rápido ou mais lento.

Eu utilizei os percentis 5% a 95%, em intervalos de 5%.

Viagens Repetidas

Uma abordagem que foi importante para que os melhores colocados subissem na tabela foi criar um algoritmo para encontrar viagens similares. Era notável que alguns trechos, apesar de possuírem um ângulo diferente com relação à origem, se tratavam do mesmo caminho.

Eu fiz um algoritmo simples, baseado na velocidade do motorista durante a viagem mas, apesar de ter encontrado algumas viagens similares, acabava prejudicando a pontuação.

Os algoritmos que tiveram sucesso eram mais complexos, e em alguns casos envolviam a transformação das variáveis, redução de dimensões, e limites para determinar a similaridade. Dentre todos, dois métodos pareceram essenciais:

Ramer–Douglas–Peucker: como cada viagem tinha uma duração diferente, este método foi utilizado para reduzir, e igualar, o número de pontos.

Dynamic Time Warping: este método foi utilizado para comparar os trechos e determinar a similaridade entre eles.

Amostragem

Como não era possível saber realmente quais eram as viagens de cada motorista. Ou seja, existiam viagens marcadas como positivas, quando na realidade eram negativas, havia a oportunidade de se decidir a melhor maneira de fazer a amostragem dos dados.

Aleatória

Num primeiro momento, com métodos não supervisionados, usei apenas as 200 viagens de cada motorista. Uma sugestão no fórum da competição foi usar as 200 viagens de um motorista como exemplos positivos e usar viagens de outros motoristas como exemplos negativos.

Em geral esta foi uma abordagem bastante positiva. Dentre as maneiras de fazê-la estavam:

  • Escolher, aleatoriamente, uma quantidade N de motoristas e tratar todas as viagens deles como negativas.
  • Escolher, aleatoriamente, uma quantidade V de viagens de N motoristas diferentes, para usar como negativas.

A abordagem que me serviu melhor foi baseada na segunda opção: selecionar um pequeno número de viagens de vários motoristas diferentes.

Amostra por similaridade

Outra alternativa que testei foi selecionar amostras negativas de motoristas que eram mais similares ou diferentes das amostras positivas, de acordo com uma medida como distância euclidiana.

Criei atributos como a média de velocidade, distância percorrida, e duração das viagens para cada motorista e determinei quais eram os mais parecidos, e quais eram os mais diferentes do motorista em questão.

Apesar da abordagem utilizando os motoristas “mais diferentes” mostrar uma melhora durante a validação cruzada, ela não melhorou a pontuação no test set. A razão que atribuo a isto é o fato dos dados da validação conterem viagens que são falsas, mas estão marcadas como verdadeiras, enquanto que no test set temos a realidade absoluta.

Reforçando as previsões

Procurei reforçar as previsões do modelo treinando mais de uma vez, mas agora usando as previsões do modelo anterior no lugar da variável dependente original, da seguinte maneira:

No primeiro passe fiz o procedimento normal, usando as viagens do motorista como positivas, e outras aleatoriamente selecionadas de outros motoristas como negativas para obter previsões.

Nos próximos passes eu utilizei as previsões do modelo anterior como variável dependente. Isso melhorou bastante na validação cruzada, mas apresentou uma melhora muito pequena nos dados de validação do Kaggle.

Modelos e Métodos

Clustering

Num primeiro momento decidi agrupar as viagens de acordo com características similares. Essa ideia foi baseada na suposição que, como a maioria das viagens pertencia ao motorista, seria possível separar as viagens em dois clusters, e aquele que tivesse a minoria das viagens seria o “negativo”.

Outra ideia era aumentar o número de clusters, já que existiam diferenças das viagens entre si, mesmo pertencentes ao mesmo motorista.

De qualquer maneira, estas ideias se mostraram inúteis, com AUC próximo de 0,5.

Outra maneira não supervisionada que tentei foi calcular a similaridade de cosseno entre a média dos atributos das viagens e cada uma delas. Neste caso a “probabilidade” de uma viagem pertencer ao motorista seria um menos este valor. O que também se mostrou inútil.

Regressão Logística

O meu modelo com maior sucesso foi a regressão logística. Isso me surpreendeu, já que o sucesso descrito por vários participantes no fórum envolvia boosted trees.

Utilizei cerca de 1000 exemplos, 200 positivos e 800 negativos. Um detalhe importante foi ativar a opção “class_weight=auto”. Esta opção atribui uma penalidade diferente aos exemplos, de acordo com a distribuição das classes. Neste caso, um erro ou acerto na classe positiva valia mais do que o mesmo na classe negativa. Desta maneira, apesar de termos mais exemplos positivos, a penalização por erros era equilibrada.

Treinei uma regressão para cada motorista, personalizando a penalidade de regularização (L1 ou L2) e o coeficiente da mesma. Cada modelo fazia a validação cruzada de valores para este coeficiente utilizando os dois tipos de regularização, e no fim selecionava o tipo de regularização e o coeficiente que apresentasse a melhor AUC.

O melhor modelo individual atingiu a AUC de 0,86.

Random Forests/Boosted Trees

De acordo com os fóruns, o modelo mais utilizado foi Gradient Boosted Trees. Basicamente ele consiste em treinar uma sequência de decision trees pouco complexas, atribuindo um peso maior a exemplos que foram classificados incorretamente pelas árvores anteriores. A probabilidade de um exemplo específico é uma combinação linear das previsões de cada árvore.

No meu caso as tentativas de utilizar este modelo não foram bem sucedidas. Dois motivos podem ter contribuído:

  • Por desconfiança da validação, eu acabei não dando muita atenção à otimização dos parâmetros dele para conseguir uma boa AUC.
  • O processo de validação cruzada para encontrar bons parâmetros ia demorar muito, e testes preliminares não haviam apresentado bons resultados.

De qualquer maneira treinei um modelo de Random Forests, com os parâmetros padrões, para utilizar num ensemble. Ele sozinho possuía AUC de 0,847.

Ensemble

Próximo do fim da competição decidi partir para a forma mais “fácil” de se melhorar a pontuação: ensembles.

Para uma parte do ensemble treinei os seguintes modelos:

  • Regressão Logística apenas com regularização L1
  • Regressão Logística apenas com regularização L2
  • SVM RBF
  • SVM Linear
  • Random Forests

Apesar do SVM não oferecer probabilidades, acreditei que ele seria uma boa contribuição para o ensemble, o que se mostrou verdadeiro.

A média simples da previsão destes modelos produziu uma AUC de 0,8825.

Por fim, juntei estes com todos os outros que já havia produzido desde o início da competição, para uma AUC final de 0,8915. Isto me garantiu uma colocação entre as 15% melhores soluções da competição.

Métodos das soluções vencedoras

As soluções vencedoras usaram 400 exemplos para cada motorista, selecionando viagens aleatórias de outros motoristas como exemplos negativos.

O modelo mais comum foi Gradient Boosted Trees. Além disso, algoritmos complexos para encontrar viagens similares e atribui-las diretamente ao motorista conquistaram os pontos finais necessários para se posicionar entre as 10 melhores soluções.

Seja o primeiro a saber das novidades em Machine Learning. Me siga no LinkedIn.