Amanhã vai chover?
Kelvin L

Kelvin L @godkelvin

About: https://github.com/godkelvin

Location:
Brasil, Espírito Santo
Joined:
Feb 28, 2025

Amanhã vai chover?

Publish Date: Feb 28
24 3

Sabemos que o termo "Inteligência Artificial" se popularizou nos últimos anos,

MAS

É apenas um nome bonitinho para o que Turing e Arthur Samuel construíam já na década de 40 e 50: Machine Learning.

Hoje vamos aprender a como treinar um algoritmo utilizando a biblioteca Scikit-Learn do Python.

Veremos o KNN (K-Nearest Neighbors).

KNN

O KNN é um algoritmo de aprendizado supervisionado usado para classificação e regressão.

A ideia central do KNN é classificar um dado novo com base na proximidade dos dados já conhecidos.

Por exemplo, se queremos classificar a bolinha de cor verde pertencente a classe azul ou vermelha, verificamos quantas bolinhas de cada classe estão próximas dela e com base na quantidade de vizinhos, classificamos a bolinha verde (No exemplo, a bolinha verde irá ser classificada como azul).
Image description

Essa quantidade de vizinhos para a classificação é denominada K.

Objetivo

Aprender a estrutura básica de treinamento de um algoritmo utilizando a biblioteca Scikit-Learn.

Como faremos isso?

Treinando o algoritmo KNN.

Base de dados Utilizada

Vamos utilizar uma base de dados que contém amostras de 10 anos de estações meteorológicas da Austrália.

Disponível em: https://www.kaggle.com/datasets/jsphyg/weather-dataset-rattle-package/discussion/485344

Tarefa de predição

Classificar se no dia após a observação irá chover, tendo como variável alvo RainTomorrow.

Uma olhadinha na base de dados

O dataset contém 145.460 registros.

É dividido em 23 colunas (características).

Bizoiando as primeiras linhas do dataset:

import pandas as pd
dataframe = pd.read_csv("weatherAUS.csv")
dataframe.head()
Enter fullscreen mode Exit fullscreen mode

Image description

Image description

Vamos ver a proporção de cada classe, importante para identificar se o nosso dataset está desbalanceado.

columns = dataframe.columns.tolist()

for col in columns:
  #Com o normalize = True, irá retornar em percentual (E para ficar legível, multiplicamos por 100)
  proportion = dataframe[col].value_counts(normalize=True) * 100
  print(proportion)
  print("-----------")
Enter fullscreen mode Exit fullscreen mode

Image description

Image description

Onde há valores nulos?

Isso é importante para o tratamento de dados posteriormente.

print(dataframe.isnull().sum())
Enter fullscreen mode Exit fullscreen mode

Image description

Ou seja, muitas colunas com gráficos nulos!
Vamos tratar!

POXA KELVIN, MAS PORQUE TEM VALORES NULOS???

Porque equipamentos falham, internet cai, em algumas regiões não tem o equipamento adequado etc etc.

Ou seja, é de responsabilidade SUA lidar com esses problemas.

Transformação e tratamento de dados

import pandas as pd
import numpy as np
from sklearn.preprocessing import LabelEncoder
# https://www.kaggle.com/datasets/jsphyg/weather-dataset-rattle-package
# dataframe = pd.read_csv("weatherAUS.csv")

# Alterando as variáveis No e Yes para inteiro (0 e 1)
dataframe["RainToday"] = dataframe["RainToday"].map({"No": 0, "Yes": 1})

# Tratando as datas
dataframe["Date"] = pd.to_datetime(dataframe["Date"])
dataframe["Year"] = dataframe["Date"].dt.year
dataframe["Month"] = dataframe["Date"].dt.month
dataframe["Day"] = dataframe["Date"].dt.day
dataframe.drop(columns=["Date"], inplace=True)

#Capturando somente as variaveis numericas, visto que, as categoricas não fazem sentido tirar a média
numeric_columns = dataframe.select_dtypes(include=[np.number]).columns.tolist()
columns_with_nulls_numeric = dataframe[numeric_columns].columns[dataframe[numeric_columns].isnull().any()].to_list()
for column in columns_with_nulls_numeric:
  location_month_mean_value = dataframe.groupby(["Location", "Month"])[column].transform("mean")
  dataframe[column] = dataframe[column].fillna(location_month_mean_value)


# Quando uma location está completamente sem valores para determinada região, vamos tentar tirar a media do mes na respectiva
numeric_columns = dataframe.select_dtypes(include=[np.number]).columns.tolist()
columns_with_nulls_numeric = dataframe[numeric_columns].columns[dataframe[numeric_columns].isnull().any()].to_list()
for column in columns_with_nulls_numeric:
  mean_value_month = dataframe.groupby(["Month"])[column].transform("mean")
  dataframe[column] = dataframe[column].fillna(mean_value_month)

# Criando uma label (ID) para os valores em string
label_encoder = LabelEncoder()
dataframe["Location"] = label_encoder.fit_transform(dataframe["Location"])
dataframe["WindGustDir"] = label_encoder.fit_transform(dataframe["WindGustDir"])
dataframe["WindDir9am"] = label_encoder.fit_transform(dataframe["WindDir9am"])
dataframe["WindDir3pm"] = label_encoder.fit_transform(dataframe["WindDir3pm"])

# Dataframe depois dos devidos tratamentos
dataframe.head()
Enter fullscreen mode Exit fullscreen mode

Como podemos ver na etapa de transformação e tratamento, temos alguns pontos importantes dessa etapa:

1 - A variávell RainToday foi transformada para valores binários.

2 - A data estava em formato de String (2008-01-01) e para a mesma foram criadas as colunas de dia, mês e ano. Após essa transformação, o campo original de Date foi excluído.

3 - Para as colunas com valores nulos, vamos utilizar a estratégia de agrupar por Localização e mês e tirar a média para o registro faltante (Lembrando que, isso não é uma regra, é apenas uma forma de fazer).

4 - Caso uma localização inteira não tenha registro, foi utilizado a média global daquela característica.

5 - Para as variáveis categóricas, foi utilizado o LabelEnconder, que dá à elas um ID, visto que, o algorítmo que estamos trabalhando não aceita valores em strings. Por exemplo, direção do vendo NORTE assumiu o valor 1, direção do vento NORTE->SUL, assumiu o valor 2, e assim sucessivamente. Isso se deve ao fato do KNN não trabalharem com valores strings.

As seguintes caracteristicas categórias foram transformadas: Location, WindGustDir, WindDir9am e WindDir3pm.

Ainda há valores nulos?

print(dataframe.isnull().sum())
Enter fullscreen mode Exit fullscreen mode

Image description

Sim! E está justamente na variável que vamos prever (E EXCLUIR DO NOSSO DATASET!).

Não foi removida antes para não impactar nas médias globais.

O arroz e feijão do algoritmo

Divisão em conjuntos de treinamento e teste

from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier

# Cria um novo dataframe dropando a coluna alvo com valores  nulos
dataframe_cleaned = dataframe.dropna(subset=["RainTomorrow"]).copy()

# Coluna alvo, ou seja, o que quero identificar, convertida para 0 e 1
y = dataframe_cleaned["RainTomorrow"].map({"No": 0, "Yes": 1})

# Dropando a coluna alvo
dataframe_cleaned.drop(columns=["RainTomorrow"], inplace = True)
print(dataframe.shape)

X = dataframe_cleaned.values
Enter fullscreen mode Exit fullscreen mode

Após remoção dos registro nulos em RainTomorrow, temos um dataset com o tamanho de 142193

print(dataframe_cleaned.shape)
Enter fullscreen mode Exit fullscreen mode

Diferenças de grandeza

Como o KNN utiliza o cálculo de distância para classificar os dados, as características com diferença de grandeza devem ser normalizadas.

Ou seja, imagine que uma característica seja de 0, até 1 e outra sendo de 10, até 1000. Claramente temos uma diferença de grande e ambas devem ser transformadas.

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
X_train_knn, X_test_knn, y_train_knn, y_test_knn = train_test_split(X_scaled, y, test_size=0.25)

# Aqui ocorre o treinamento do algoritmo com o valor padrão de K = 5.
knn = KNeighborsClassifier()
knn.fit(X_train_knn, y_train_knn)

# Aqui, vamos prever a variável RainTomorrow
y_pred_knn = knn.predict(X_test_knn)
Enter fullscreen mode Exit fullscreen mode

LEMBRANDO QUE

Para fins de aprendizado, vamos utilizar ao longo do código os valores padrões da biblioteca scikit-learn (Ou seja, não vamos mexer nos hiperparâmetros).

Como avaliamos o nosso algoritmo? Métricas!

Lembrando que 25% do dataset de tamanho 142.193 equivale a 35.549 registros.

from sklearn.metrics import accuracy_score, confusion_matrix, precision_score, recall_score

acc_knn = accuracy_score(y_test_knn, y_pred_knn) * 100
confusion_m_knn = confusion_matrix(y_test_knn, y_pred_knn)
precision_knn = precision_score(y_test_knn, y_pred_knn) * 100
recall_knn = recall_score(y_test_knn, y_pred_knn) * 100

print("-> Resultados do KNN:")
print("Acurácia: %.2f%%\nPrecisão: %.2f%%\nRecall: %.2f%%" %(acc_knn, precision_knn, recall_knn))

print("Matriz de confusão:\n\tVerdadeiro Positivo: \t%i\tFalso Negativo: \t%i\n\tFalso Positivo: \t%i\tVerdadeiro Negativo: \t%i" 
      %(confusion_m_knn[0][0], confusion_m_knn[0][1], confusion_m_knn[1][0], confusion_m_knn[1][1]))
Enter fullscreen mode Exit fullscreen mode

Image description

Poderia escrever um artigo inteiro apenas sobre as métricas, mas no momento vamos nos contentar em apenas entende-las:

Acurácia: A proporção de previsões corretas (verdadeiros positivos + verdadeiros negativos) em relação ao total de registros.

Precisão: A precisão é a proporção de previsões corretas entre todas as previsões positivas feitas pelo modelo.

Exemplo: Se o modelo prevê que irá chover em 100 dias e, desses 100 dias, 70 realmente choveu (VP) e 30 não choveu (FP), então a precisão seria de 70%.

Recall: É proporção de previsões corretas para a classe positiva (RainTomorrow = Yes) entre todas as instâncias realmente positivas no conjunto de dados.

Exemplo: Se realmente choveu em 100 dias e o modelo previu corretamente que chovia em 80 desses dias (VP), mas errou em 20 dias (FN), então o recall seria de 80%.

Conclusão

Eai? Nosso algoritmo está bom? Está ruim? Já podemos nos candidatar para a pessoa da previsão do tempo do jornal local?

A resposta é: DEPENDE!

O quão aceitável é uma acurácia de 83%? Para uma pessoa que vai passar o dia inteiro no PC, pouco importa!

Mas para o agricultor que pode perder um dia inteiro de trabalho, importa muito!

(Isso vale para as demais métricas!)

Faça você mesmo!

Para fins de aprendizado, recomendo que vocês mexam nos valores de K, utilizem outros meios de transformação, faça outro tipo de tratamento para os valores nulos!

Novamente, isso foi apenas um ponta pé inicial para mostrar à vocês que machine learning pode ser divertido e fácil!

Eai, amanhã vai chover?

Comments 3 total

  • Thiago David
    Thiago DavidFeb 28, 2025

    incredible, i love it! nice article.

  • Ernane Ferreira
    Ernane FerreiraFeb 28, 2025

    Que bacana! Achei muito interessante. Obrigado por compartilhar!

  • Lillian Queen
    Lillian QueenMar 1, 2025

    FINALLY I GOT MY LOST BITCOIN BACK ALL THANKS TO // THE HACK ANGELS RECOVERY EXPERT

    I am out here to spread this good news to the entire world on how THE HACK ANGELS RECOVERY EXPERT and his terams help me in recovering my lost Bitcoin. I never thought I could get scammed of my Bitcoin , I never knew these investments were fake. I was depressed and in anger but all thanks to THE HACK ANGELS RECOVERY EXPERT for the help and professional service offered to me in my time of need. I invested $1.3 million in a cryptocurrency platform and found out it was a scam and I had no idea how to get my money back until I contacted THE HACK ANGELS RECOVERY EXPERT To anyone out there seeking to recover any lost bitcoin from cryptocurrency forms of online scams or wallet hackers , I recommend THE HACK ANGELS RECOVERY EXPERT they specialize in recovery of lost funds. CONTACT DETAILS;

    WhatsApp +1(520)200-2320 or shoot them an email at support@thehackangels.com They also have a great website at thehackangels.com
    Image description

Add comment