Predição de paciente com Diabetes — Machine Learning

Ferdinando de Melo
5 min readAug 6, 2021

--

Este artigo tem como foco mostrar como é simples criar um modelo para predição de categorias, neste caso, usando dados de pacientes com diabetes.

Escolha da matéria

Para criação desse projeto, foi utilizado utilizado dados de um conjunto do Kaggle (https://www.kaggle.com/houcembenmansour/predict-diabetes-based-on-diagnostic-measures) que disponibiliza informação de alguns pacientes que foram diagnosticados com Diabetes e outras informações como pressão arterial, idade, peso, etc.

Essas informações serão usadas para descoberta da nossa variável alvo que é o objetivo do nosso modelo, diagnosticar o sujeito com ou sem Diabetes. Lembrando que esse modelo foi utilizado somente para fins educacionais, se você apresenta algum sintoma de doença, consulte seu médico!

Capturando os dados

Essa base de dados, por ser uma base simples e limpa, facilitou bastante o nosso trabalho. Ela foi importada para o Pandas, tirado o índice de identificação do paciente e os dados foram traduzidos para a a natureza correta:

# Importação da base de dados
df = pd.read_csv('diabetes.csv')
# Retirada do índice de identificação do paciente
df.drop("patient_number", axis=1, inplace=True)
# Troca de tipos das variáveis para demonstração
df['diabetes'] = df['diabetes'].apply(lambda x: 0 if x == 'No diabetes' else 1)
df['gender'] = df['gender'].apply(lambda x: 0 if x == 'female' else 1).astype('int')
df['waist_hip_ratio'] = df['waist_hip_ratio'].apply(lambda x : str(x).replace(",",".")).astype('float')
df['chol_hdl_ratio'] = df['chol_hdl_ratio'].apply(lambda x : str(x).replace(",",".")).astype('float')
df['bmi'] = df['bmi'].apply(lambda x : str(x).replace(",",".")).astype('float')

Para auxiliar na análise dos dados, foi utilizado a ferramenta “pandas_profilling” que demonstra em uma página HTML o resumo dos dados em questão. E como dito anteriormente, não temos nenhum dado faltando ou nulo em nossa base:

Validação dos dados

O “pandas_profilling” também nos auxilia demonstrando a correlação dos dados, assim podemos identificar os as variáveis que mais impactam a nossa variável alvo.

Grau de correlação Pearson’s Metrics

Analisando o quadro acima, podemos entender que alguns dados são menos importantes para o diagnóstico, como o gênero do paciente. Mas em compensação há outros dados que tem forte correlação com a nossa variável alvo, como o nível de glicose no sangue. Portanto, podemos retirar essas variáveis menos importantes para construção do nosso modelo.

df.drop("hip", axis=1, inplace=True)
df.drop("height", axis=1, inplace=True)
df.drop("waist_hip_ratio", axis=1, inplace=True)
df.drop("gender", axis=1, inplace=True)
df.drop("chol_hdl_ratio", axis=1, inplace=True)

Os nomes das colunas foram traduzidas para um melhor entendimento do leitor nativo do Português.

# Renomeando as colunas para português 
df.rename(columns=
{"cholesterol": "colesterol_ruim","hdl_chol": "colesterol_bom","age": "idade","weight": "peso","bmi":"imc","systolic_bp": "pressão_sistolica","diastolic_bp": "pressão_diastolica","waist": "cintura"},
inplace=True)

Criando o modelo

Para a separação dos dados, foram utilizadas as bibliotecas “janitor” e “sklearn”

import janitor as jn
from sklearn.model_selection import train_test_split
X,y = jn.get_features_targets(df, target_columns = "diabetes")
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state =0)

Na seleção do modelo, foram utilizados os modelos da biblioteca “sklearn” que dão suporte a predição de duas categorias e o “XGBoost”. Verifiquei qual deles dariam uma melhor resposta baseado em sua curva ROC e o desvio padrão.

from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVCtrain_test_split,
from sklearn.ensemble import RandomForestClassifier
from xgboost import XGBClassifier
from sklearn.model_selection import StratifiedKFold, cross_val_score, KFold
for model in [DummyClassifier, LogisticRegression, DecisionTreeClassifier, KNeighborsClassifier, GaussianNB, SVC, RandomForestClassifier, XGBClassifier]:
cls = model()
kfold = KFold(n_splits = 6, random_state = 0, shuffle=True)
s = cross_val_score(cls,X, y, scoring="roc_auc", cv=kfold)
print(f"{model.__name__} AUC: {s.mean():.3f} | STD: {s.std():.2f}")
Resultado AUC e STD de cada modelo testado

Com a saída do código acima, podemos verificar que para o nosso caso de estudo, os modelos mais aderentes são os XGBoost, RandomForest e o SupportVectorMachine, nessa ordem.

Escolhi 2 dos 3 melhores modelos, com base nos seus resultados para continuação do projeto: XGBoost e o RandomForest.

Modelo RandomForest

Para construção do RandomForest, utilizei a configuração abaixo, onde consegui os melhores resultados nos meus testes.

rdf = ensemble.RandomForestClassifier(random_state=0,n_estimators=200, max_features="auto")
rdf.fit(X_train, y_train)
score = rdf.score(X_test, y_test).item()
print("Random Forest")
print(f'Score: {score:.3f}')
precision = precision_score(y_test, rdf.predict(X_test)).item() *100
print(f'Precisão: {precision}%')
Resultado do modelo Random Forest

Com a matriz de decisão, fica mais fácil de verificar que o teste errou em poucos casos.

Matriz de confusão — Random Forest

Modelo XGBoost

Para a construção do modelo XGBoost, foi utilizada a configuração abaixo e como no modelo anterior, essa configuração foi a que demonstrou melhores resultados.

xgb = XGBClassifier(n_estimators = 20, learning_rate=0.1, n_jobs=5)
xgb.fit(X_train, y_train)
score = xgb.score(X_test, y_test).item()
print("XGBoost")
print(f'Score: {score:.3f}')
precision = precision_score(y_test, xgb.predict(X_test)).item() *100
print(f'Precisão: {precision:.2f}%')
Resultado do modelo XGBoost

Mesmo com uma precisão bem próxima ao do modelo Random Forest, com a base de teste, este modelo acertou 1 caso a mais que estaria com Diabetes.

Matriz de confusão — XGBoost

Teste dos modelos

Você pode testar os modelos construídos nesse artigo utilizando as funções “predict” de cada modelo, só é necessário passar um DataFrame com as variáveis utilizadas durante o treinamento do modelo. A resposta será um NumpyArray com o valor de cada categoria predita para o seu teste, ou seja, “1” para pacientes com possível quadro de Diabetes e “0” para pacientes sem o diagnóstico da doença.

Abaixo temos um exemplo de duas possíveis entradas para testar os modelos criados

# Teste com os dois modelos com entradas criadas pelo autordf_teste_modelo = pd.DataFrame.from_dict([{'colesterol_ruim':193, 'glucose':400, 'colesterol_bom':49, 'idade':19, 'peso':119, 'imc':22.5,'pressão_sistolica':118, 'pressão_diastolica':70, 'cintura':32},
{'colesterol_ruim':193, 'glucose':77, 'colesterol_bom':49, 'idade':19, 'peso':119, 'imc':22.5,'pressão_sistolica':118, 'pressão_diastolica':70, 'cintura':32}])
pred_test_xgb = xgb.predict(df_teste_modelo)
pred_test_rdf = rdf.predict(df_teste_modelo)
print(f"Resultado Teste RandomForest:{pred_test_rdf}")
print(f"Resultado Teste XGBoost:{pred_test_xgb}")
Resultados dos testes dos modelos

Conclusão

Com algumas (poucas) linhas de código e um conhecimento básico sobre os conceitos de criação de modelos matemáticos, você também consegue construir um modelo (neste caso dois) que pode ter uma precisão interessante para o seu objetivo.

Como para este estudo foi utilizado uma base pequena de dados, para um algo mais conclusivo e para um modelo passível de implantação em produção, seria necessário mais dados com uma maior variação para validação do modelo construído.

--

--

Ferdinando de Melo
Ferdinando de Melo

Written by Ferdinando de Melo

Python enthusiast and a data scientist lover

No responses yet