Como criar e utilizar um modelo de Machine Learning de forma prática
Neste artigo descrevo, de maneira bem simples, uma das formas de disponibilizar um modelo de Machine Learning para utilização prática.
Se você está iniciando na área de Ciência de Dados venha comigo e vamos fazer isso juntos.
Neste exemplo vamos trabalhar com um problema de regressão linear simples aplicado ao conjunto de dados Weather Conditions in World War Two:
Este conjunto de dados (dataset) está disponível no site da comunidade Kaggle e contém resumos meteorológicos diários de várias estações ao redor do mundo no período de 1940 a 1945.
Nosso objetivo será bem simples. Vamos desenvolver um modelo para prever a temperatura máxima informando apenas a temperatura mínima.
Para desenvolver esse modelo eu optei pelo software Spyder da plataforma Anaconda. Maiores informações sobre essa plataforma podem ser encontradas em:
Como primeiro passo vamos importar as bibliotecas a serem utilizadas no Python:
import pandas as pd import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression from sklearn.metrics import r2_score from joblib import dump import seaborn as sns import warnings
warnings.filterwarnings('ignore')
Bibliotecas como Pandas, Matplotlib, Numpy, Sklearn e Seaborn são muito utilizadas por Cientistas de Dados. Maiores informações sobre cada uma delas podem ser encontradas em:
Na sequencia vamos carregar o dataset disponibilizado em um dataframe do Pandas. Eu optei por baixar o arquivo .CSV do site do Kaggle e trabalhá-lo localmente no Spyder.
Há 31 atributos (colunas) disponíveis neste dataset mas, neste exemplo, vamos trabalhar somente com dois deles: MinTemp , MaxTemp.
Para isso executaremos o seguinte comando para realizar a importação do arquivo CVS para um objeto dataframe do Pandas em memória:
df_weather=pd.read_csv(r'Summary_of_Weather.csv', sep=',', usecols=['MaxTemp', 'MinTemp'])
Após essa importação podemos verificar as dimensões do dataframe com a aplicação do comando abaixo:
print("Dimensões do dataframe:")
print (df_weather.shape)
Como resultado teremos:
Dimensões do dataframe:
(119040, 2)
Como podemos observar, temos 119 mil instancias e 2 atributos neste dataframe.
Podemos agora realizar uma pequena análise exploratória nesses dados.
Vamos iniciar verificando os tipos desses dados com o comando abaixo:
print("Tipos dos dados:")
df_weather.info()
Como resultado veremos que ambos os atributos são do tipo ponto flutuante (float):
Tipos dos dados: <class 'pandas.core.frame.DataFrame'> RangeIndex: 119040 entries, 0 to 119039 Data columns (total 2 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 MaxTemp 119040 non-null float64 1 MinTemp 119040 non-null float64 dtypes: float64(2)
memory usage: 1.8 MB
Também podemos visualizar as primeiras instâncias deste dataframe com o comando:
print("Primeiras instâncias:")
print(df_weather.head())
Como resultado teremos:
Primeiras instâncias: MaxTemp MinTemp 0 25.555556 22.222222 1 28.888889 21.666667 2 26.111111 22.222222 3 26.666667 22.222222
4 26.666667 21.666667
Para o nosso modelo de regressão, esses atributos com dados quantitativos contínuos já estão no tipo correto e não necessitam de nenhuma transformação.
Outra verificação importante é se há dados faltantes no dataframe, pois caso ocorram podem comprometer a qualidade dos resultados do nosso modelo. Em casos assim o ideal é tratá-los com alguma técnica antes de dar continuidade. Exemplos de técnicas simples são a substituição dos dados faltantes pela média ou mediana dos dados.
Podemos verificar a presença de dados faltantes com a utilização do comando:
print("Atributos com dados faltantes:") nans = df_weather.isna().sum()
print(nans[nans > 0])
Como resultado teremos:
Atributos com dados faltantes:
Series([], dtype: int64)
Ou seja, em nosso dataframe não há atributos com dados faltantes. Então sigamos em frente.
Também é interessante verificarmos a correlação entre esses atributos. Para isso utilizaremos a correlação de Pearson que mede a associação linear entre variáveis contínuas.
Dessa forma saberemos o valor que indica o quanto a relação entre os nossos atributos pode ser descrita por uma reta. Para isso executaremos o seguinte comando:
print ("Gráfico de correlação:") plt.figure(figsize=(6,5)) df_corr_ = df_weather.corr(method='pearson') ax_ = sns.heatmap(df_corr_, annot=True) bottom, top = ax_.get_ylim() ax_.set_ylim(bottom + 0.5, top - 0.5)
plt.show()
E como resultado teremos uma forte correlação positiva de 0.88 entre os dois atributos do nosso dataframe:
Outra verificação importante a ser feita é como os dados estão distribuídos. Para isso, utilizaremos um gráfico de dispersão através do seguinte comando:
print ("Gráfico de dispersão:") plt.figure(figsize=(4, 4), dpi=100) plt.scatter(df_weather['MinTemp'], df_weather['MaxTemp'], color='gray') plt.xlabel("MinTemp") plt.ylabel("MaxTemp")
plt.show()
Como resultado podemos observar que há uma forte dependência positiva de Y (temperatura máxima) em relação a X (temperatura mínima). Isso nos indica que, quanto maior a temperatura mínima (eixo X) também maior será a temperatura máxima (eixo Y):
Após essa simplificada análise exploratória dos dados partiremos para a próxima fase que compõe a definição e treinamento do algoritmo de Machine Learning que realizará nossas previsões.
Para tanto precisaremos separar nosso dataframe em duas variáveis distintas: uma preditora e uma resposta. A variável preditora conterá os dados independentes a partir dos quais o modelo treinará suas previsões. E a variável resposta conterá os dados dependentes que, após o treinamento, serão utilizados pelo modelo como critério de comparação para mensurar os acertos e erros em suas previsões.
Neste exemplo estamos trabalhando com aprendizagem supervisionada porque o conjunto de dados que recebemos para análise já veio rotulado, ou seja, para cada instância do atributo X (independente) o atributo y (dependente) já veio preenchido com um valor histórico.
A separação do nosso dataframe em variáveis preditora e resposta será realizada através do seguinte comando:
X=df_weather['MinTemp'].values.reshape(-1, 1) #variável preditora
y=df_weather['MaxTemp'].values.reshape(-1, 1) #variável resposta
Podemos confirmar que, após essa separação, nossos dados continuam com a mesma dimensão total:
print("Dimensões de X e y:")
print("X:", X.shape, " y:", y.shape)
Como resultado teremos:
Dimensões de X e y:
X: (119040, 1) y: (119040, 1)
Dessa forma podemos dividir nosso conjunto de dados em treino e teste reservando 70% dos dados para treino e 30% para teste com o seguinte comando:
X_treinamento, X_teste, y_treinamento, y_teste = train_test_split(X, y, test_size=0.3)
Após essa divisão podemos verificar como ficaram as dimensões:
print("Dimensões de X e y para treino e teste:") print("X_treinamento:", X_treinamento.shape, " X_teste:", X_teste.shape)
print("y_treinamento:", y_treinamento.shape, " y_teste:", y_teste.shape)
Como resultado teremos:
Dimensões de X e y para treino e teste: X_treinamento: (83328, 1) X_teste: (35712, 1)
y_treinamento: (83328, 1) y_teste: (35712, 1)
Estamos trabalhando com um problema de regressão linear. Isto posto, dentre os vários algoritmos disponíveis para resolver problemas deste tipo, eu escolhi o LinearRegression da biblioteca Scikit-Learn.
Com os comandos abaixo criaremos uma instância do algoritmo de regressão na variável regressor e treinaremos o algoritmo com os dados de treino que extraímos do nosso dataframe:
regressor = LinearRegression()
modelo = regressor.fit (X_treinamento, y_treinamento)
Depois de treinado podemos utilizar o modelo para realizar previsões sobre nossos dados de teste (X_teste) com o seguinte comando:
previsao = modelo.predict(X_teste)
Há diversas maneiras para mensurarmos a qualidade do nosso modelo. No caso de modelos de regressão linear, uma delas é o coeficiente de determinação R2. Este coeficiente mede os erros cometidos pelo modelo sobre os dados de teste e compara com os erros ocorridos caso tivéssemos utilizado uma média comum para estimar o resultado.
Dessa forma, quanto mais próximo de 1 (ou 100%) for o valor do R2 melhor será o nosso modelo. Para maiores informações sobre essa métrica de qualidade assista:
Podemos apurar o coeficiente R2 do nosso modelo, já com uma formatação de percentual, através do seguinte comando:
R_2 = r2_score(y_teste, previsao) #realiza o cálculo do R2
print ("Coeficiente R2 (%):", R_2.round(4) * 100)
O resultado em torno de 77% (Coeficiente R2 (%): 77.23) mostra que esse modelo retorna resultados 77% melhores do que se fizéssemos a utilização de uma simples média dos valores para gerar nossas previsões:
Coeficiente R2 (%): 77.23
Podemos demonstrar graficamente o comportamento das previsões do nosso modelo sobre os dados originais com o seguinte gráfico de dispersão:
print ("Gráfico de dispersão:") plt.figure(figsize=(4, 4), dpi=100) plt.scatter(X_treinamento, y_treinamento, color='gray') plt.plot(X_teste, previsao, color='red') plt.xlabel("MinTemp") plt.ylabel("MaxTemp")
plt.show()
Neste gráfico os pontos cinza são os dados originais do nosso conjunto de dados e a reta em vermelho demonstra as previsões realizadas pelo modelo:
Ao chegarmos neste ponto é necessário verificar se o resultado da métrica de qualidade foi satisfatório para a solução do problema ou se será necessário melhorar o modelo. Se a opção for por melhorar o modelo algumas alternativas podem ser consideradas tais como: utilizar outro algoritmo de Machine Learning, incluir novos atributos para utilização, mudar a forma como os dados faltantes foram tratados, buscar mais dados para aumentar o conjunto, etc.
Neste exemplo vamos considerar que o resultado foi satisfatório e que esse modelo deve ser implantado e disponibilizado para utilização. Para isso precisaremos exportar o modelo para um arquivo armazenado no disco. Podemos realizar esse procedimento com a biblioteca JobLib através do comando:
dump(modelo, 'previsor.pkl')
Este comando criará na mesma pasta do arquivo em Pyhon um novo arquivo cujo nome escolhido foi previsor.pkl. Mais informações sobre essa biblioteca podem ser encontradas em:
Partiremos agora para o VSCode onde criaremos a interface para implantação do modelo.
Nossa interface será uma aplicação web simples desenvolvida com o framework Flask. Este framework simples e poderoso possibilitará a utilização do nosso modelo de Machine Learning através de um formulário web. Mais informações sobre o framework Flask podem ser encontradas em:
A estrutura desse aplicação web será a seguinte:
Site: - app.py - previsor.pkl
- templates\index.html
No arquivo app.py definiremos o comportamento da nossa aplicação web. O primeiro passo será realizar a importação das bibliotecas Python que iremos utilizar:
import numpy as np from flask import Flask, request, render_template
from joblib import load
Agora instanciaremos a nossa aplicação Flask e importaremos o modelo de Machine Learning do disco para a memória:
app = Flask(__name__)
modelo = load('previsor.pkl')
Criaremos dois endpoints para nossa aplicação:
- Um / (raiz) apontando para a página index.html:
@app.route("/") def index():
return render_template('index.html')
- Um /model/ para tratar a requisição via post do formulário web, armazenar o valor requisitado em uma variável (X_preditor) e submeter essa variável ao nosso modelo de previsão. O resultado será renderizado na própria página index.html:
@app.route('/model/', methods=['GET', 'POST']) def model(): y_predict = 0 try: if request.method == 'POST': preditor = request.form.get("preditor") X_preditor = np.array([[preditor]]).astype(np.float64) y_predict = modelo.predict(X_preditor) y_predict = np.round(y_predict, 2) except Exception as e: y_predict = 'Predict fail' return render_template('index.html', predict=y_predict) if __name__ == "__main__":
app.run(debug=False)
A página index.html contém um formulário web com um campo texto para digitação do valor para a variável preditora: Temperatura mínima. E um label para a exibição da variável resposta: Temperatura máxima.
<!DOCTYPE html> <html> <head> </head> <body class="body"> <div> <header> </header> <div> <font>Temperatura Mínima (degrees Celsius):</font> <br> <form action="/model/" method=post enctype=multipart/form-data> <input type="text" name="preditor"> <input type=submit value=Predict></input> </form> <br> <font>Temperatura Máxima (degrees Celsius): {{ predict }}</font> </div> </div> </body>
</html>
Para rodar a aplicação basta abrir um novo Terminal no próprio VSCode e digitar o comando:
python app.py
Como resultado será exibido um link para acesso local (http://127.0.0.1:5000/). Basta segurar a tecla Ctrl e clicar sobre o link:
Será então aberto o navegador com o seguinte formulário:
Ao digitar um valor de temperatura mínima e clicar no botão Predict o modelo de Machine Learning será acionado e realizará a previsão da temperatura Máxima com base no treinamento ao qual foi submetido:
Em nosso exemplo para a temperatura mínima de 12 graus Celsius o modelo retornou a temperatura máxima de 21,73 graus Celsius
Isso conclui o objetivo desse artigo de tentar mostrar, de forma bastante simples e prática, todo o fluxo para disponibilizar um modelo de Machine Learning para utilização.
Passamos por todas as principais fases do processo, desde a coleta dos dados e treinamento do modelo até o desenvolvimento de uma aplicação web para sua disponibilização.
E aí? O que achou? Quaisquer dúvidas ou comentários serão muito bem-vindos. Esse projeto está disponível no meu GitHub:
Product Manager | Product Owner | Customer Experience | Gestão de Produtos | Metodologias Ágeis | Roadmap de Produtos | Análise de Mercado | Lançamento de Produtos | Go-to-Market | KPIs | QA
3 aMuito didático. Parabéns!
GESTÃO DE PESSOAS | GESTÃO DE PROJETOS | ESPECIALISTA DE TI | ANALISTA DE NEGÓCIOS | DATA DRIVEN | SFC | SFPC | PSPO | MASTER BLACK BELT LEAN SIX SIGMA
3 aÉ um TCC
Full Stack Developer | JS TS | C# .NET | React Native
3 aParabéns Francisco!!!