Minha primeira medalha no Kaggle com menos de 150 linhas de código

Fernando Marcos Wittmann
Data Science BR
Published in
3 min readJan 18, 2020

--

Após um mês insano, consegui ficar na colocação 46 contra 3616 times (top 1.3%) na primeira competição do Kaggle que ataquei seriamente, a Ashrae Energy Prediction. A mesma tinha 25 mil dólares em prêmios e infelizmente minha colocação ficou longe dos prêmios. Mas mesmo assim, me rendeu uma medalha de prata, o que ajuda no meu ranking da plataforma. A competição consistia em prever o consumo de energia de construções. Tentei criar modelos baseados no consumo individual de cada prédio, redes neurais e nenhum que treinei do zero se saiu muito bem. Por fim, apenas fazendo alguns testes com sugestões dadas pelos membros, consegui entrar no top 10 daquela época com o seguinte kernel:

A solução é extremamente simples e estarei detalhando neste post. Apesar de o kernel possuir em torno de 300 linhas, ao eliminar as tentativas que não funcionaram, a solução consiste em 132 linhas que compartilho no final deste post. De qualquer forma, o núcleo de minha solução consiste nas seguintes linhas:

## Main Function
if __name__=='__main__':

# 1. Reading Data
sub, subs = read_submissions()

# 2. Predicting
sub['meter_reading'] = predict(subs)

# 3. Leak correction
sub = leak_benchmark(sub)

# 4. Export Submission
export(sub)

Eu descrevi a solução nesta discussão: https://www.kaggle.com/c/ashrae-energy-prediction/discussion/123288. Segue a tradução da mesma:

Minha colocação foi graças à algumas experiências que fiz em paralelo ao tentar maximizar as dicas fornecidas em Kernels e discussões públicas.

A solução consiste em uma combinação de submissões públicas sem vazamento usando os coeficientes do Ridge CV. Minha pontuação pública ficou em torno de 0,939 com substituição de vazamento e 1,04 sem substituição de vazamento.

E algo curioso: o RidgeCV descobriu coeficientes negativos para algumas submissões, embora a soma de todos eles tenha sido próxima de 1 (como esperado):

## Ridge Coefficients
Sum of coefficients: 0.9994466580815099
half-half-drop-rows-stratify-weekday has weight 0.14
simple-data-cleanup-3-models has weight 0.26
ashrae-kfold-lightgbm-without-leak-1-08 has weight -0.23
another-1-08-lb-no-leak has weight -0.46
ashrae-kfold-lightgbm-without-building-id has weight 0.19
ashrae-energy-prediction-using-stratified-kfold has weight 0.52
ashrae-lightgbm-without-leak has weight -0.15
ashrae-stratified-kfold-lightgbm has weight 0.23
ashrae-2-lightgbm-without-leak-data has weight 0.50

Todos os créditos vão para os autores dos kernels públicos e a idéia de validação de vazamento do @yamsam . Minha contribuição foi a ideia de combiná-los usando o RidgeCV.

Em resumo

Para não tornar este post longo, em suma minha solução consistiu de combinar várias submissões públicas usando RidgeCV. É como se eu criasse um ensemble de outras submissões. Tal técnica também é conhecida por blending e é bastante comum nas competições. No entanto, algo diferente que havia nessa competição é que alguns dados que seriam resposta da competição vazaram e foram tornados públicos para todos os membros. E apesar da polêmica, o ranking final foi feito com base em apenas dados não vazados, portanto permaneceu justo para todos os membros. E passamos a ter à disposição uma nova carta na manga, que no meu caso se tornaram úteis como conjunto de validação para modelos públicos. Cruzei os dados do conjunto de teste com os vazados usando RidgeCV. O mesmo atribuiu um peso para cada submissão existente, e algo curioso que ocorreu foi que algumas submissões receberam pesos negativos. Isso é algo que nunca vemos em ensembles clássicos. Por exemplo, em random forest, a classificação final do conjunto de árvores de decisão é feita com base na maioria (major vote) ou pela média. Talvez em breve eu crie outros posts investigando tais propriedades combinando pesos negativos!

Mas somente funciona se houver vazamento de dados?

O vazamento facilitou para a criação um conjunto de validação usando uma parte do conjunto de testes público do kaggle. No entanto, tal estratégia pode ser útil mesmo sem dados vazados. Basta criar um stack dos modelos públicos. Segue a definição de Stacking da documentação do Sklearn:

Stacking é um método para combinar estimadores para reduzir seus vieses. Mais precisamente, as previsões de cada estimador individual são empilhadas e usados como entrada para um estimador final para calcular a previsão. Este estimador final é treinado através da validação cruzada.

Portanto, fazendo uso de validação cruzada, o modelo é selecionado a partir de predições dos dados de treinamento. Como desvantagem, neste caso precisaria recompilar os modelos públicos para obter tais predições de treinamento. Mas mesmo assim, é uma estratégia bastante robusta e factível!

Solução

--

--

Fernando Marcos Wittmann
Data Science BR

Head of Data Science @ Awari | Machine Learning Expert | E-Learning