Por que recebo uma árvore de decisão com 100% de precisão?

38

Estou obtendo uma precisão de 100% para minha árvore de decisão. O que estou fazendo errado?

Este é o meu código:

import pandas as pd
import json
import numpy as np
import sklearn
import matplotlib.pyplot as plt


data = np.loadtxt("/Users/Nadjla/Downloads/allInteractionsnum.csv", delimiter=',')


x = data[0:14]
y = data[-1]


from sklearn.cross_validation import train_test_split

x_train = x[0:2635]
x_test = x[0:658]
y_train = y[0:2635]
y_test = y[0:658]


from sklearn.tree import DecisionTreeClassifier
tree = DecisionTreeClassifier()
tree.fit(x_train.astype(int), y_train.astype(int))


from sklearn.metrics import accuracy_score

y_predicted = tree.predict(x_test.astype(int))
accuracy_score(y_test.astype(int), y_predicted)
Nadjla
fonte
4
Por que você acha que está fazendo algo errado? Talvez os seus dados são tais que você pode conseguir uma classicação perfeito ...
Knarpie
64
Aliás, +1 para se perguntar se algo está errado com 100% de precisão. Muitas pessoas simplesmente acham que o modelo delas é ótimo ...
S. Kolassa - Restabelece Monica
1
No R, existe um pacote (cursor) para dividir automaticamente um conjunto de dados em dois grupos, um para dados de treinamento e outro para dados de teste. Eu chamo o processo como partição de dados. Acredito que exista um pacote semelhante no Python para obter uma partição de dados também.
Anastasiya-Romanova秀
Útil leitura de fundo: Problemas comuns no ML
SMCI
3
@ Anastasiya-Romanova 秀 Praticamente todas as bibliotecas ML sérias contêm essa funcionalidade, incluindo a usada pelo OP (o OP importou a funcionalidade relevante e simplesmente não a utilizou por algum motivo).
Konrad Rudolph

Respostas:

79

Sua amostra de teste é um subconjunto da sua amostra de treinamento:

x_train = x[0:2635]
x_test = x[0:658]
y_train = y[0:2635]
y_test = y[0:658]

Isso significa que você avalia seu modelo em uma parte dos dados de treinamento, ou seja, está fazendo uma avaliação dentro da amostra. A precisão dentro da amostra é um indicador notoriamente ruim da precisão fora da amostra, e maximizar a precisão dentro da amostra pode levar ao excesso de ajuste. Portanto, deve-se sempre avaliar um modelo em uma amostra de validação verdadeira que seja completamente independente dos dados de treinamento.

Verifique se seu treinamento e seus dados de teste são disjuntos, por exemplo,

x_train = x[659:2635]
x_test = x[0:658]
y_train = y[659:2635]
y_test = y[0:658]
S. Kolassa - Restabelecer Monica
fonte
2
Seria melhor usar sklearn.model_selection.train_test_splitcomo Juan Ignacio Gil sugere, pois isso também embaralha os conjuntos e evita preocupações se o conjunto de dados não for aleatório no pedido. Também é mais claro porque mostra a intenção e lida automaticamente com alterações no tamanho do conjunto de dados.
Jack Aidley
1
@ JackAidley: Eu concordo (e votei na resposta de Juan há alguns dias). Melhor ainda seria tornar a divisão determinística para depuração, definindo a semente do número aleatório .
S. Kolassa - Restabelece Monica 26/03
@StephanKolassa Olá, estive aprimorando o conjunto de dados Iris e, depois de usá-lo GridSearchCVcom dados de treinamento, para testar a precisão, recebo 100% KNeighborsClassifier. Eu usei test_train_splitpara dividir o conjunto de dados. O que eu poderia ter feito de errado aqui?
Sndn
19

Você está obtendo 100% de precisão porque está usando uma parte dos dados de treinamento para testes. No momento do treinamento, a árvore de decisão adquiriu conhecimento sobre esses dados e, agora, se você fornecer os mesmos dados para prever, obterá exatamente o mesmo valor. É por isso que a árvore de decisão produz resultados sempre corretos.

Para qualquer problema de aprendizado de máquina, o conjunto de dados de treinamento e teste deve ser separado. A precisão do modelo pode ser determinada apenas quando examinamos como ele está prevendo valores desconhecidos.

Sanjay Chandlekar
fonte
17

Como outros usuários disseram, você está usando como conjunto de teste um subconjunto do conjunto de trens, e uma árvore de decisão é muito propensa a sobreajuste.

Você quase teve quando importou

from sklearn.cross_validation import train_test_split

Mas então você não usa a função Você deveria ter feito:

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.33)

obter conjuntos aleatórios de trem e teste

Juan Ignacio Gil
fonte
2

Conforme apontado por @Stephan Kolassa e @Sanjay Chandlekar, isso se deve ao fato de sua amostra de teste ser um subconjunto da sua amostra de treinamento.

No entanto, para a seleção dessas amostras, a amostragem aleatória seria mais apropriada para garantir que ambas as amostras sejam representativas. Dependendo da sua estrutura de dados, você também pode considerar amostragem aleatória estratificada.

Não sou fluente em Python, mas qualquer software estatístico deve permitir amostragem aleatória; algumas dicas também estão disponíveis no SO .

nghauran
fonte
0

Só quero enfatizar a intuição do motivo pelo qual você precisa dividir o treinamento e testar as amostras explicitamente.

nnn1n=2

Isso é chamado de ajuste excessivo, porque é improvável que esse processo de divisão preveja pontos de dados relevantes para o seu problema, mas que você ainda não observou .

Obviamente, o objetivo principal da construção dessas plataformas de previsão é criar ferramentas que possam ser aplicadas a dados nunca antes vistos; dividir os dados que temos em amostras de treinamento e teste é uma tentativa de simular essa auto-cegueira e policiar nossos modelos de sobreajuste da maneira acima.

MichaelChirico
fonte
0

Você não precisa de 100% de precisão para obter o ajuste excessivo. Com baldes suficientes, você pode obter resultados irreprodutíveis (algo que pareceria terrível fora da amostra).

Veja este artigo extraído do Lancet, descrevendo o método de cortar uma amostra em baldes muito finos. De Munchausen Estatística Grade É também a base para o desenho animado XKCD Significativo

Atingir 100% de precisão está a um pequeno passo de encontrar um classificador que funcione enganosamente bem.

NBF
fonte