Predición de choiva
- Duración:
- 50 min
- Agrupamento:
- 2
Obxectivo: Buscarás, descargarás e prepararás datos meteorolóxicos para adestrar unha rede neuronal con Keras que predirá se choverá ou non en función de variables como temperatura, humidade, vento e presión atmosférica.
A predición de choiva é un reto moi útil e aplicable á vida real. Hai datasets dispoñibles que conteñen datos meteorolóxicos históricos, como temperatura, humidade, presión atmosférica e velocidade do vento, que poden ser usados para prever se vai chover ou non.
Dataset recomendado: Podes atopar datos meteorolóxicos en este repositorio , ideais para practicar e afondar no deep learning.
Pasos do reto:
✅ Buscar e descargar os datos desde a web.
✅ Subilos a Google Colab e cargalos con Pandas.
✅ Depuralos eliminando valores nulos e normalizando as variables.
✅ Deseñar unha rede neuronal con Keras para predicir se choverá ou non.
✅ Visualizar os resultados con gráficos de perda e precisión.
✅ Probar o modelo con datos novos para ver se acerta na predición.
Lembra: A IA está para axudarche, pregúntalle!
Paso 1: Buscar e descargar os datos
Os datos meteorolóxicos están dispoñibles en Kaggle e inclúen rexistros históricos de distintas variables. Propóñoche un en concreto, pero podes adaptalo a calquera!
- Entra na páxina e descarga o arquivo WeatherTypeClassification.csv .
- Gárdao no ordenador e revisa os datos cun editor de texto ou folla de cálculo para entender as variables dispoñibles.
Temperature (numeric: A temperatura en graos Celsius, variando desde frío extremo a calor extrema.
Humidity (numeric): A porcentaxe de humidade, incluíndo valores por riba de 100% para presentar outliers.
Wind Speed (numeric): A velocidade de vento en quilómetros por hora, cunha gama que inclúe unrealistically valores altos.
Precipitation (%) (numeric): A porcentaxe de precipitación, incluíndo outlier valores.
Cloud Cover (categorical): A descrición de cuberta da nube.
Atmospheric Pressure (numeric): A presión atmosférica en hPa, cubrindo unha gama ancha.
UV Index (numeric): O índice de UV, indicando a forza de ultraviolet radiación.
Season (categorical): A estación durante o cal o dato foi gravado.
Visibility (km) (numeric): A visibilidade en kilómetros, incluíndo moi abaixo ou valores moi altos.
Location (categorical): O tipo de localización onde o dato foi gravado.
Weather Type (categorical): Clasificación, indicando o tipo de tempo.
Paso 2: Cargar os datos en Colab e depuralos
Podes recuperar o programa para depurar os datos que usaches para Scikit-learn ou usar este código:
Para subir a colab o arquivo e visualizar as primeiras filas:
import pandas as pd
from google.colab import files
# Cargar o arquivo CSV en Colab
print("Sube o teu arquivo CSV:")
datos = files.upload()
# Obter o nome do primeiro arquivo subido
nome_arquivo = list(datos.keys())[0]
# Ler o arquivo CSV sen depender dun nome fixo
df = pd.read_csv(nome_arquivo)
# Visualizar as primeiras filas dos datos
print(f"Arquivo cargado correctamente: {nome_arquivo}")
df.head()
Limpeza de datos: Revisar se hai valores nulos. Convertir a variable de choiva (Precipitation (%)) a valores binarios (1 se chove, 0 se non). Normalizar as características (para que todos os valores teñan o mesmo rango).
# Comprobar valores nulos
print(df.isnull().sum())
# Seleccionar características relevantes
X = df[['Temperature', 'Humidity', 'Wind Speed', 'Atmospheric Pressure']]
y = df['Precipitation (%)']
# Normalizar os datos
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
X = scaler.fit_transform(X)
# Normalizar tamén y para mellorar estabilidade do modelo
y = scaler.fit_transform(y.values.reshape(-1, 1))
# Visualizar as primeiras filas dos datos
print(f"Arquivo revisado correctamente: {nome_arquivo}")
df.head()
Paso 3: Construír a rede neuronal con Keras
Axustando o modelo para que prediga valores continuos (% de choiva) en vez de unha clasificación binaria (0 ou 1).
Define o modelo con este código:
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Input
# Crear o modelo
modelo = Sequential([
Input(shape=(X.shape[1],)), # Cantidade de características como entrada
Dense(32, activation='relu'), # Primeira capa oculta con 32 neuronas
Dense(16, activation='relu'), # Segunda capa oculta con 16 neuronas
Dense(1, activation='linear') # Capa de saída con activación lineal para valores continuos
])
# Compilar o modelo con función de perda axeitada para regresión
modelo.compile(optimizer='adam', loss='mean_squared_error', metrics=['mean_absolute_error'])
# Mostrar resumo do modelo
modelo.summary()
PREGUNTAS:
- Investiga que significa cada columna e fila da táboa resultante de modelo.summary()
- Por que usamos mean-absolute_error como métrica e non accuracy?
Paso 4: Adestramento do modelo
Pasamos a adestrar o modelo co código:
from sklearn.model_selection import train_test_split
# Dividir en datos de adestramento e validación
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
# Adestramento
historial = modelo.fit(
X_train, y_train,
epochs=10,
batch_size=32,
validation_data=(X_val, y_val)
)
PREGUNTA: Averigüa que significa X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
Paso 5: Visualización do adestramento
Agora graficamos a perda e o erro medio na precición(xa non usamos accuraty porque non é clasificación binaria):
import matplotlib.pyplot as plt
plt.figure(figsize=(12, 4))
# Gráfica da perda
plt.subplot(1, 2, 1)
plt.plot(historial.history['loss'], label='Perda no Adestramento')
plt.plot(historial.history['val_loss'], label='Perda na Validación')
plt.xlabel('Época')
plt.ylabel('Perda')
plt.title('Progreso da Perda')
plt.legend()
# Gráfica do erro absoluto medio
plt.subplot(1, 2, 2)
plt.plot(historial.history['mean_absolute_error'], label='Erro Absoluto Medio no Adestramento')
plt.plot(historial.history['val_mean_absolute_error'], label='Erro Absoluto Medio na Validación')
plt.xlabel('Época')
plt.ylabel('Erro Absoluto Medio')
plt.title('Progreso do Erro Absoluto Medio')
plt.legend()
plt.tight_layout()
plt.show()
PREGUNTA:Explica as gráficas obtidas
Paso 6: Predición con datos novos
Agora o modelo pode predicir a probabilidade estimada de choiva en % a partir das condicións meteorolóxicas do día.
Proba con novos datos:
import numpy as np
from sklearn.preprocessing import MinMaxScaler
# Crear o modelo (asegúrate de que xa o tes adestrado e cargado)
# modelo = ... # O modelo xa debe estar definido e adestrado
# Crear o escalador e axustalo cos datos de adestramento
scaler = MinMaxScaler()
X = scaler.fit_transform(df[['Temperature', 'Humidity', 'Wind Speed', 'Atmospheric Pressure']])
# Características dun novo día (modificable)
novo_dia = np.array([[15, 80, 5, 1012]]) # Temperatura, Humidade, Vento, Presión
# Convertir `novo_dia` nun DataFrame para manter os nomes das características
novo_dia_df = pd.DataFrame(novo_dia, columns=['Temperature', 'Humidity', 'Wind Speed', 'Atmospheric Pressure'])
# Aplicar a transformación de escalado correctamente
novo_dia_scaled = scaler.transform(novo_dia_df)
# Predicir a Probabilidade esperada de choiva
prediccion = modelo.predict(novo_dia_scaled)
print(f"Probabilidade estimada de choiva: {prediccion[0][0]*100:.2f} %")
PREGUNTA: Cambia o programa para que:
- che vaia pedinto Temperatura(ºC), Humidade (%), Velocidade do vento (km/h) e Presión atmosférica (milibares)
- Realice peticións dinámicas con while:True
Código Python: Programa para depurar datos dun arquivo .csv
# Importar librerías necesarias
import pandas as pd
# Función para analizar, limpar, preprocesar e modificar datos de forma educativa
def analizar_limpar_e_modificar_datos():
print("Benvido/a! Este programa axudarache a analizar, limpar e preparar os teus datos para proxectos de IA.")
print("Explicaremos cada paso para que comprendas por que é necesario realizar este proceso.")
# Paso 1: Subir o arquivo CSV
from google.colab import files
print("\nPor favor, sube o arquivo CSV cos datos que desexas analizar e limpar:")
uploaded = files.upload()
nome_arquivo = list(uploaded.keys())[0]
datos = pd.read_csv(nome_arquivo)
print(f"\nArquivo '{nome_arquivo}' cargado correctamente!")
print("\nVisualizando as primeiras filas dos datos:")
print(datos.head())
# Paso 2: Seleccionar columnas para analizar e limpar
print("\nColumnas dispoñibles no arquivo:")
print(list(datos.columns))
print("\nSelecciona as columnas que queres analizar e limpar. Introduce os nomes separados por comas.")
columnas_seleccionadas = input("Introduce os nomes das columnas (exemplo: 'Column1,Column2'): ").split(',')
# Limpar espazos ao redor dos nomes das columnas
columnas_seleccionadas = [col.strip() for col in columnas_seleccionadas]
print(f"\nSeleccionaches estas columnas: {columnas_seleccionadas}")
# Comprobar que as columnas existen
for columna in columnas_seleccionadas:
if columna not in datos.columns:
print(f"\nErro: A columna '{columna}' non existe no arquivo. Revise os nomes.")
return
# Paso 3: Cambiar nomes das columnas seleccionadas
print("\nQueres cambiar o nome dalgunha das columnas seleccionadas?")
print("1 - Si, quero cambiar os nomes.")
print("2 - Non, quero manter os nomes actuais.")
cambiar_nomes = input("Introduce o número correspondente á túa elección: ")
if cambiar_nomes == "1":
novos_nomes = {}
for columna in columnas_seleccionadas:
novo_nome = input(f"Introduce o novo nome para a columna '{columna}': ")
novos_nomes[columna] = novo_nome
datos.rename(columns=novos_nomes, inplace=True)
columnas_seleccionadas = [novos_nomes[col] for col in columnas_seleccionadas]
print(f"\nOs nomes das columnas foron actualizados: {novos_nomes}")
else:
print("\nManteranse os nomes orixinais das columnas seleccionadas.")
# Crear un DataFrame para traballar con só as columnas seleccionadas
datos_seleccionados = datos[columnas_seleccionadas].copy()
# Paso 4: Analizar e modificar valores en cada columna
print("\nAgora imos analizar os valores nas columnas seleccionadas.")
filas_a_eliminar = []
for columna in columnas_seleccionadas:
print(f"\nAnalizando a columna: '{columna}'")
tipos_detectados = datos_seleccionados[columna].apply(type).unique()
print(f"- Tipos de datos detectados: {[tipo.__name__ for tipo in tipos_detectados]}")
# Preguntar ao usuario que tipo de dato debería ter a columna
print("\nQue tipo de dato debería ter esta columna?")
print("1 - bool (True/False)")
print("2 - int (Números enteiros)")
print("3 - float (Números decimais)")
print("4 - str (Texto)")
tipo_dato_esperado = input("Introduce o número correspondente ao tipo de dato esperado: ")
tipo_actual = None
if pd.api.types.is_bool_dtype(datos_seleccionados[columna]):
tipo_actual = "1"
elif pd.api.types.is_integer_dtype(datos_seleccionados[columna]):
tipo_actual = "2"
elif pd.api.types.is_float_dtype(datos_seleccionados[columna]):
tipo_actual = "3"
elif pd.api.types.is_string_dtype(datos_seleccionados[columna]):
tipo_actual = "4"
if tipo_dato_esperado == tipo_actual:
print(f"- A columna '{columna}' xa está no formato esperado. Non require cambios.")
else:
# Convertir a columna ao tipo especificado
try:
if tipo_dato_esperado == "1":
datos_seleccionados[columna] = datos_seleccionados[columna].astype(bool)
elif tipo_dato_esperado == "2":
datos_seleccionados[columna] = datos_seleccionados[columna].astype(int)
elif tipo_dato_esperado == "3":
datos_seleccionados[columna] = datos_seleccionados[columna].astype(float)
elif tipo_dato_esperado == "4":
datos_seleccionados[columna] = datos_seleccionados[columna].astype(str)
print(f"- A columna '{columna}' foi convertida ao formato esperado.")
except ValueError as e:
print(f"\nErro ao converter os datos: {e}. Revisando os valores...")
# Preguntar ao usuario se quere cambiar os valores das categorías detectadas
categorias = datos_seleccionados[columna].unique()
print(f"- A columna '{columna}' ten {len(categorias)} categorías: {categorias}")
print("\nQueres cambiar os valores das categorías?")
print("1 - Si, quero cambiar os nomes/valores das categorías.")
print("2 - Non, quero manter os valores actuais.")
cambio_categoria = input("Introduce o número da túa elección: ")
if cambio_categoria == "1":
conversion = {}
for categoria in categorias:
print(f"Para a categoría '{categoria}', introduce o valor co que a queres substituír:")
novo_valor = input("Novo valor: ")
conversion[categoria] = novo_valor
print(f"Mapa de conversión para '{columna}': {conversion}")
datos_seleccionados[columna] = datos_seleccionados[columna].map(conversion)
# Validación de valores inexistentes ou problemáticos
print("- Comprobando valores inexistentes ou problemáticos na columna...")
for i, valor in enumerate(datos_seleccionados[columna]):
if pd.isnull(valor): # Valor inexistente ou NaN
print(f"Fila {i+1}: O valor está baleiro ou inexistente.")
decision = input("Queres eliminar esta fila? (Si/Non): ").strip().lower()
if decision == "si":
filas_a_eliminar.append(i)
# Eliminar filas erróneas segundo decisións do usuario
print("\nEliminando filas problemáticas segundo as túas decisións...")
datos_limpados = datos_seleccionados.drop(filas_a_eliminar, axis=0)
print(f"Filas eliminadas: {len(filas_a_eliminar)}")
# Paso 5: Gardar o arquivo limpo
print("\nGardando o arquivo limpo e completamente preprocesado...")
nome_saida = input("Introduce o nome do arquivo de saída (por exemplo, 'datos_limpados.csv'): ")
datos_limpados.to_csv(nome_saida, index=False)
print(f"\nArquivo limpo gardado como '{nome_saida}'. Contén os datos seleccionados e correctamente limpos.")
# Ofrecer ao usuario descargar o arquivo
print("\nDescargando o arquivo...")
files.download(nome_saida)
# Executar o programa educativo
analizar_limpar_e_modificar_datos()
Paso 3: Explicación da táboa de parámetros da rede
PREGUNTA 1-
A táboa mostra a estrutura da túa rede neuronal construída con Keras usando un modelo secuencial.
Aquí está a interpretación dos campos:
- Layer (type) → Indica as capas do modelo e o seu tipo.
- Output Shape → Indica a forma da saída de cada capa. Por exemplo, (None, 32) significa que cada entrada pasará por 32 neuronas.
- Param # → Cantidade de parámetros (pesos e sesgos) que a capa ten que axustar durante o adestramento.
Descomposición da rede:
- Primeira capa (dense) → Ten 32 neuronas e 160 parámetros (incluíndo pesos e sesgos).
- Segunda capa (dense_1) → Ten 16 neuronas e 528 parámetros.
- Terceira capa (dense_2) → Ten 1 neurona, que produce a saída final, e 17 parámetros.
Detalles globais:
- Total params: 705 parámetros axustables en todo o modelo.
- Trainable params: 705 parámetros serán optimizados durante o adestramento.
- Non-trainable params: 0, porque todas as capas teñen parámetros que se adestran.
Que significa para o teu modelo?Ten capas densas, o que significa que cada neurona está conectada con todas as da capa anterior. A última capa predice un valor único, perfecto para problemas de regresión ou clasificación binaria. Cantos máis parámetros, máis capacidade de aprendizaxe, pero tamén maior risco de sobreaxuste se non se regulariza correctamente.
PREGUNTA 2-
Por que este cambio? 'mean_absolute_error' mide canto se afasta a predición do valor real, útil para regresión. 'accuracy' só serve para clasificación binaria ou multicategoría, pero non para predicións numéricas como a cantidade de choiva.
Diferentes funcións de perda para diferentes problemas:
binary_crossentropy → Para clasificación binaria (exemplo: choiva vs. non choiva).
mean_squared_error → Para regresión (exemplo: cantidade de choiva en %).
Accuracy (Precisión) - Representa cantas predicións foron correctas comparadas coas etiquetas reais. Útil só en clasificación, cando hai categorías claramente definidas (exemplo: chove ou non chove). Se a saída é un número continuo, accuracy non ten sentido, porque non hai unha resposta "correcta exacta". No teu caso: O modelo está predicindo % de choiva, polo que accuracy non é útil. A métrica axeitada é mean_absolute_error, que indica o erro medio en % das predicións comparado cos valores reais.z
Paso 4: Adestramento
PREGUNTA-X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
Esta liña de código está dividindo os datos en grupos de adestramento e validación, para ensinar á rede neuronal e comprobar que realmente aprende ben.
Que significa cada parte?
- train_test_split(X, y, test_size=0.2, random_state=42) → Toma os datos e divídeos en dúas partes: unha para adestrar o modelo e outra para validalo.
- X_train → Datos de entrada para adestramento.
- X_val → Datos de entrada para validación (ver se o modelo aprendeu correctamente).
- y_train → Resultados reais para adestramento (o que o modelo debe aprender a prever).
- y_val → Resultados reais para validación.
Que significa test_size=0.2? Indica que o 20% dos datos se reservarán para validación e o 80% será usado para adestramento. Se puxésemos test_size=0.3, estaríamos usando o 30% dos datos para validación e o 70% para adestramento.
Que significa random_state=42? Asegura que a división de datos sexa sempre a mesma cada vez que se executa o código. Se non o puxésemos, a separación sería diferente cada vez que se corre o programa. O número 42 é só un valor arbitrario (podería ser calquera número).
Este código permite que o modelo aprenda con parte dos datos e logo comproba se realmente sabe predicir correctamente con datos que nunca viu antes, os de validación.
Paso 5: Visualizando adestramento
PREGUNTA-
A partir dos datos das gráficas, pódese concluír que o adestramento do modelo está a mellorar tanto a perda como o erro absoluto medio ao longo das épocas.
Primeira gráfica: "Progreso da Perda"
Representa canto erro total ten o modelo ao predecir. A perda no adestramento (liña azul) diminúe progresivamente, o que indica que o modelo está aprendendo. A perda na validación (liña laranxa) tamén diminúe, aínda que cunha curva menos pronunciada.
Conclusión: O modelo está mellorando, pero habería que revisar se a perda chega a un nivel estable ou se existe risco de sobreaxuste.
Segunda gráfica: "Progreso do Erro Absoluto Medio"
Indica canto se afasta a predición do valor real en promedio. No adestramento, o erro absoluto medio comeza en aproximadamente 0.170 e vai reducindo ata 0.140 ao final da última época. O erro absoluto medio na validación tamén diminúe, pasando de 0.155 a 0.142.
Conclusión: O modelo mellora a súa capacidade de predición, pero a diferenza entre adestramento e validación suxire que pode necesitar máis datos ou melloras para evitar un posible sobreaxuste.
O modelo está aprendendo de forma efectiva, reducindo o erro en cada época, pero sería útil monitorizar máis épocas para comprobar que a precisión se estabiliza correctamente.
Paso 6:Predición novos datos
import numpy as np
from sklearn.preprocessing import MinMaxScaler
# Crear o escalador e axustalo cos datos de adestramento
df_subset = df[['Temperature', 'Humidity', 'Wind Speed', 'Atmospheric Pressure']].sample(500, random_state=42)
scaler = MinMaxScaler()
scaler.fit(df_subset) # Axustar o escalador con datos representativos
# Bucle para pedir datos dinámicamente
while True:
try:
# Solicitar datos ao usuario
temperatura = float(input("Introduce a temperatura (ºC): "))
humidade = float(input("Introduce a humidade (%): "))
vento = float(input("Introduce a velocidade do vento (km/h): "))
presion = float(input("Introduce a presión atmosférica (milibares): "))
# Crear un array cos valores introducidos
novo_dia = np.array([[temperatura, humidade, vento, presion]])
# Convertir `novo_dia` nun DataFrame para manter os nomes das características
novo_dia_df = pd.DataFrame(novo_dia, columns=['Temperature', 'Humidity', 'Wind Speed', 'Atmospheric Pressure'])
# Aplicar a transformación de escalado correctamente
novo_dia_scaled = scaler.transform(novo_dia_df)
# Predicir a cantidade esperada de choiva
prediccion = modelo.predict(novo_dia_scaled)
print(f"Probabilidade estimada de choiva: {prediccion[0][0]*100:.2f} %")
# Preguntar se o usuario quere repetir ou saír
continuar = input("Queres probar outro día? (s/n): ").strip().lower()
if continuar != 's':
print("Saíndo do programa...")
break
except ValueError:
print("⚠️ Erro: Introduce valores numéricos correctamente.")
Programa completo
Código Python: Predictor de choiva
#Paso 1
import pandas as pd
from google.colab import files
# Cargar o arquivo CSV en Colab
print("Sube o teu arquivo CSV:")
datos = files.upload()
# Obter o nome do primeiro arquivo subido
nome_arquivo = list(datos.keys())[0]
# Ler o arquivo CSV sen depender dun nome fixo
df = pd.read_csv(nome_arquivo)
# Visualizar as primeiras filas dos datos
print(f"Arquivo cargado correctamente: {nome_arquivo}")
df.head()
#Paso 2
# Comprobar valores nulos
print(df.isnull().sum())
# Seleccionar características relevantes
X = df[['Temperature', 'Humidity', 'Wind Speed', 'Atmospheric Pressure']]
y = df['Precipitation (%)']
# Normalizar os datos
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
X = scaler.fit_transform(X)
# Normalizar tamén y para mellorar estabilidade do modelo
y = scaler.fit_transform(y.values.reshape(-1, 1))
# Visualizar as primeiras filas dos datos
print(f"Arquivo revisado correctamente: {nome_arquivo}")
df.head()
#Paso 3
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Input
# Crear o modelo
modelo = Sequential([
Input(shape=(X.shape[1],)), # Cantidade de características como entrada
Dense(32, activation='relu'), # Primeira capa oculta con 32 neuronas
Dense(16, activation='relu'), # Segunda capa oculta con 16 neuronas
Dense(1, activation='linear') # Capa de saída con activación lineal para valores continuos
])
# Compilar o modelo con función de perda axeitada para regresión
modelo.compile(optimizer='adam', loss='mean_squared_error', metrics=['mean_absolute_error'])
# Mostrar resumo do modelo
modelo.summary()
#Paso 4
from sklearn.model_selection import train_test_split
# Dividir en datos de adestramento e validación
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
# Adestramento
historial = modelo.fit(
X_train, y_train,
epochs=10,
batch_size=32,
validation_data=(X_val, y_val)
)
#Paso 5
import matplotlib.pyplot as plt
plt.figure(figsize=(12, 4))
plt.ion() #Engadimos isto para que non interfiran as gráficas coa introdución de datos
# Gráfica da perda
plt.subplot(1, 2, 1)
plt.plot(historial.history['loss'], label='Perda no Adestramento')
plt.plot(historial.history['val_loss'], label='Perda na Validación')
plt.xlabel('Época')
plt.ylabel('Perda')
plt.title('Progreso da Perda')
plt.legend()
# Gráfica do erro absoluto medio
plt.subplot(1, 2, 2)
plt.plot(historial.history['mean_absolute_error'], label='Erro Absoluto Medio no Adestramento')
plt.plot(historial.history['val_mean_absolute_error'], label='Erro Absoluto Medio na Validación')
plt.xlabel('Época')
plt.ylabel('Erro Absoluto Medio')
plt.title('Progreso do Erro Absoluto Medio')
plt.legend()
plt.tight_layout()
plt.show()
#Paso 6
import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
# Crear o escalador e axustalo cos datos de adestramento
df_subset = df[['Temperature', 'Humidity', 'Wind Speed', 'Atmospheric Pressure']].sample(500, random_state=42)
scaler = MinMaxScaler()
scaler.fit(df_subset) # Axustar o escalador con datos representativos
# Bucle para pedir datos dinámicamente
while True:
try:
# Solicitar datos ao usuario
temperatura = float(input("Introduce a temperatura (ºC): "))
humidade = float(input("Introduce a humidade (%): "))
vento = float(input("Introduce a velocidade do vento (km/h): "))
presion = float(input("Introduce a presión atmosférica (milibares): "))
# Crear un array cos valores introducidos
novo_dia = np.array([[temperatura, humidade, vento, presion]])
# Convertir `novo_dia` nun DataFrame para manter os nomes das características
novo_dia_df = pd.DataFrame(novo_dia, columns=['Temperature', 'Humidity', 'Wind Speed', 'Atmospheric Pressure'])
# Aplicar a transformación de escalado correctamente
novo_dia_scaled = scaler.transform(novo_dia_df)
# Predicir a cantidade esperada de choiva
prediccion = modelo.predict(novo_dia_scaled)
print(f"Probabilidade estimada de choiva: {prediccion[0][0]*100:.2f} %")
# Preguntar se o usuario quere repetir ou saír
continuar = input("Queres probar outro día? (s/n): ").strip().lower()
if continuar != 's':
print("Saíndo do programa...")
break
except ValueError:
print("⚠️ Erro: Introduce valores numéricos correctamente.")