Primeira vez aqui? Seja bem vindo e cheque o FAQ!
x

Um exercício de Machine Learning usando a base Adult income do Kaggle.

0 votos
18 visitas
perguntada Nov 6 em Matemática por Fábio Springer (11 pontos)  

Base disponível em: Adult income

Compartilhe

1 Resposta

0 votos
respondida Nov 6 por Fábio Springer (11 pontos)  
editado Nov 6 por Fábio Springer

O objetivo desse exercício é limpar a base, disponível em https://www.kaggle.com/anirudhraj/adult-salary-predictor , criar uma classe que separa indivíduos que ganham mais e 50k dólares. As variáveis da base não são numéricas e não existe a classe objetivo já definia, logo nosso primeiro desafio é organizar a base. Em seguida vamos usar o modelo básico de regressão logística e avaliar o modelo.
A descrição traduzida da base é:
"O conjunto de dados contém 16 colunas
Renda
- A renda é dividida em duas classes: <= 50K e> 50K
Número de atributos: 14
- Estes são os dados demográficos e outros recursos para descrever uma pessoa"

Vamos optar por uma abordagem simples que expõe a facilidade de implementar rapidamente modelos simplórios em python. A base foi dívida no formato \(\frac{2}{3}\) e \(\frac{1}{3}\) visto que é uma boa regra de bolso para qualquer análise inicial.

import numpy as np 
import pandas as pd 
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split 
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
from sklearn import metrics
import statsmodels.api as sm

reg = LogisticRegression() 

if __name__ == 'main':

    # Carregar os dados 
    salary = pd.read_csv("C:\\Users\\fabio\\OneDrive\\Documentos\\UNB\\computacao\\archive\\adult.csv")
    # Verificar os dados
    salary.info()
    # vamos agora remover espaços nos nomes das colunas
    salary.rename(columns={'capital-gain': 'capital gain', 'capital-loss': 'capital loss', 'native-country': 'country','hours-per-week': 'hours per week','marital-status': 'marital'}, inplace=True)
    salary.columns
    # Agora vamso remover caracteres especiais e substituir por NaN, o padrão para indicar dados faltantes em Python
    salary['country'] = salary['country'].replace('?',np.nan)
    salary['workclass'] = salary['workclass'].replace('?',np.nan)
    salary['occupation'] = salary['occupation'].replace('?',np.nan)
    # Vamos excluir linhas com dados faltantes
    salary.dropna(how= 'any')
    # Agora vamos criar nossa classe de interesse, 1 se renda > 50k e 0 se < 50k
    salary['income'] = salary['income'].map({'<=50K': 0, '>50K': 1}).astype(int)
    # Agora vamos transformar nossas variaveis categoricas em numericas
    salary['gender'] = salary['gender'].map({'Male': 0, 'Female': 1}).astype(int)
    salary['race'] = salary['race'].map({'Black': 0, 'Asian-Pac-Islander': 1,'Other': 2, 'White': 3, 'Amer-Indian-Eskimo': 4}).astype(int)
    salary['marital'] = salary['marital'].map({'Married-spouse-absent': 0, 'Widowed': 1, 'Married-civ-spouse': 2, 'Separated': 3, 'Divorced': 4,'Never-married': 5, 'Married-AF-spouse': 6}).astype(int)
    salary['workclass'] = salary['workclass'].map({'Self-emp-inc': 0, 'State-gov': 1,'Federal-gov': 2, 'Without-pay': 3, 'Local-gov': 4,'Private': 5, 'Self-emp-not-inc': 6}).astype(int)
    salary['education'] = salary['education'].map({'Some-college': 0, 'Preschool': 1, '5th-6th': 2, 'HS-grad': 3, 'Masters': 4, '12th': 5, '7th-8th': 6, 'Prof-school': 7,'1st-4th': 8, 'Assoc-acdm': 9, 'Doctorate': 10, '11th': 11,'Bachelors': 12, '10th': 13,'Assoc-voc': 14,'9th': 15}).astype(int)
    salary['occupation'] = salary['occupation'].map({ 'Farming-fishing': 1, 'Tech-support': 2, 'Adm-clerical': 3, 'Handlers-cleaners': 4, 'Prof-specialty': 5,'Machine-op-inspct': 6, 'Exec-managerial': 7,'Priv-house-serv': 8,'Craft-repair': 9,'Sales': 10, 'Transport-moving': 11, 'Armed-Forces': 12, 'Other-service': 13,'Protective-     serv':14}).astype(int)
    salary['relationship'] = salary['relationship'].map({'Not-in-family': 0, 'Wife': 1, 'Other-relative': 2, 'Unmarried': 3,'Husband': 4,'Own-child': 5}).astype(int)

    # Em features nos concatenamos a relacao educacao, race... usando np.c do numpy
    salary_features = pd.DataFrame(np.c_[salary['relationship'], salary['education'], salary['race'],salary['occupation'],salary['gender'],salary['marital'],salary['workclass']], columns = ['relationship','education','race','occupation','gender','marital','workclass'])
    # Objetivo   = variavel de interesse
    salary_Objetivo = pd.DataFrame(salary.income)

    # Vamos agora dividir a base de dados e implmentar o modelo de regressao, perceba dividimos com 33% para teste e 77% para treinar o algoritimo 
    features_train, features_test, Objetivo_train, Objetivo_test = train_test_split(salary_features, salary_Objetivo, test_size=0.33, random_state=42)

    # Agora vamos treinar o nosso modelo 
    reg.fit(features_train, Objetivo_train)
     #Hora de fazer a previsao 
    Objetivo_pred = reg.predict(features_test)

    # Vereificar a acuracia
    print("Acurácia:" , metrics.accuracy_score(Objetivo_test, Objetivo_pred)

E obtemos aproximadamente 70% de acurácia. O resultado é ótimo considerando que não tratamos a base de dados com mais profundidade, removendo ruídos da base, nem avaliamos regularizar o modelo. Nesse caso não existe grande variância no valor numérico das variáveis então é possível que regularizar o modelo não cause muito impacto, a grande melhoria em termos de previsão seria implementar outros algoritmos mais complexos e comparar com o modelo logístico

comentou Nov 6 por Pedro Watuhã (1 ponto)  
Acredito que o resultado obtido a partir do modelo seja de fato muito bom, mas acredito que alguma melhoria na apresentação e nos resultados sejam possíveis. Primeiramente, tive alguma dificuldade para obter a base do Kaggle, pois há diversas bases com o nome de Adult Income, acho que colocar o link aqui possa ajudar futuramente (Solucionado).
- Quanto ao código, ele não é executado porque o if __name__ == "__main__" está redigido de forma equivocada e quando o executei, obtive um erro de que "Cannot convert non-finite values (NA or inf) to integer".
- Quanto à exibição, acho que não foram exploradas muitas estatísticas descritivas como gráficos e relacionados para justificar uma parte da alocação dessas variáveis sob o modelo explicativo final.
-Quanto ao resultado, acredito que o modelo de regressão logística possa apresentar o melhor resultado para essa operação. Todavia, acho que seria muito pertinente complementar a análise a utilização de um modelo probit ou de uma rede neural para classificação para perceber o quão melhor pode ser o modelo logit. Além disso, acho que seria curioso comparar a distribuição dos resultados esperados em comparação aos reais para podermos observar onde estão os erros do modelo.
comentou Nov 8 por Fábio Springer (11 pontos)  
Ótimas colocações. Em primeiro lugar aqui o código rodou direitinho, talvez no processo de copiar e color pro Prorum tenha ocorrido algum problema de formatação. Não fiz a parte de estatísticas descritivas pois tive alguns problemas com o Prorum e não consegui postar imagens de forma adequada. A credito que a escolha do algoritmo é um problema menor. Via de regra quando se fala de salários o objetivo é tentar prever dado as features o valor do salário e não suas classes. Fiz uso do algoritmo de classificação porque a pessoa que postou a base sugere fazer uso de um KNN que eu não considero um algoritmo tão bom quanto a regressão logistica para essa situação.
...