commit 30f5c76e2b5c531d9041ca702a1c2c1cc591c068 Author: mrdiro Date: Sat May 10 15:08:59 2025 -0500 first commit diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6eb9c96 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Dairo Carrasquilla + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..cdf4af9 --- /dev/null +++ b/README.md @@ -0,0 +1,69 @@ +# 🎰 Baloto AI - Lottery Prediction System + +`Baloto AI` es un sistema de predicción de números de lotería basado en redes neuronales. Usa modelos LSTM con múltiples salidas para intentar predecir combinaciones ganadoras de un archivo histórico de resultados. + +⚠️ Este proyecto **no garantiza resultados reales ni premios**, pero es una excelente herramienta de aprendizaje sobre redes neuronales, modelos multi-salida y entrenamiento de modelos con Keras/TensorFlow. + +--- + +## 🚀 Getting Started + +### 📁 Requisitos + +* Python 3.8+ +* TensorFlow 2.x +* NumPy +* [art](https://pypi.org/project/art/) (para generar banners ASCII) + +### 📦 Instalación + +```bash +pip install -r requirements.txt +``` + +### 📄 Formato del archivo `data.txt` + +Debes tener un archivo llamado `data.txt` en el mismo directorio, con este formato: + +``` +5,12,18,23,35,4 +8,10,14,21,39,12 +... +``` + +* Las primeras 5 columnas son los números principales. +* La sexta columna es el número **bonus**. + +--- + +## ⚙️ Ejecución + +```bash +python baloto_ai.py +``` + +El script: + +1. Limpia la consola. +2. Muestra una pantalla de bienvenida. +3. Carga y valida los datos. +4. Construye y entrena un modelo LSTM multi-output. +5. Muestra una barra de progreso animada por época. +6. Genera una predicción de una nueva combinación de números. + +--- + +## 📌 Disclaimer + +Este proyecto es **puramente educativo** y no tiene ninguna capacidad mágica para adivinar resultados de lotería reales. + +* No está afiliado a ningún sistema de lotería oficial. +* No garantiza ningún tipo de premio. +* Usar esto para apuestas reales es bajo tu **propio riesgo** (y probablemente mala idea). + +--- + +## 🤖 Créditos + +Desarrollado por Dairo Carrasquilla. +Inspirado en la idea absurda pero divertida de predecir el azar con redes neuronales. diff --git a/baloto_ai.py b/baloto_ai.py new file mode 100644 index 0000000..746ef16 --- /dev/null +++ b/baloto_ai.py @@ -0,0 +1,152 @@ +from tensorflow import keras +from keras import layers +from art import text2art +import tensorflow as tf +import numpy as np +import shutil +import socket +import sys + +# Bloquear el acceso a Internet +socket.socket = lambda *args, **kwargs: (_ for _ in ()).throw(Exception("Internet access is disabled")) + +# === Callback Personalizado para Salida Estilizada de Entrenamiento === +class CustomTrainingCallback(tf.keras.callbacks.Callback): + def __init__(self): + super().__init__() + self.total_epochs = None + self.bar_length = 40 + + def on_train_begin(self, logs=None): + self.total_epochs = self.params['epochs'] + print("\033[1;36m" + "=" * 60 + "\033[0m") + print("\033[1;35mTraining Progress:\033[0m") + + def on_epoch_end(self, epoch, logs=None): + current = epoch + 1 + percent = current / self.total_epochs + filled_len = int(self.bar_length * percent) + bar = '█' * filled_len + '·' * (self.bar_length - filled_len) + sys.stdout.write(f"\r\033[1;34m[Epoch {current}/{self.total_epochs}] [{bar}] {percent*100:.1f}%\033[0m") + sys.stdout.flush() + + if current == self.total_epochs: + print("\n\033[1;36m" + "=" * 60 + "\033[0m\n") + + +# === Funciones de Interfaz === +def print_banner(): + print("\033[1;34m" + text2art("Baloto AI", font="block")) + print("\033[1;33m" + "Lottery Prediction Artificial Intelligence".center(60) + "\033[0m") + print("\033[1;36m" + "=" * 60 + "\033[0m") + +def print_status(message): + print(f"\033[1;34m[•]\033[0m \033[1;37m{message}\033[0m") + +def print_intro(): + print_banner() + print_status("Starting LotteryAI Prediction System...") + print("\033[1;36m" + "=" * 60 + "\033[0m") + +# === Funciones de Entrenamiento === +def load_data(): + print_status("Loading training data...") + if not tf.io.gfile.exists('data.txt'): + raise FileNotFoundError("data.txt not found") + + data = np.genfromtxt('data.txt', delimiter=',', dtype=int) + if data.shape[1] != 6: + raise ValueError("Each row in data.txt must have exactly 6 numbers (5 regular + 1 bonus)") + + regular_numbers = data[:, :5] + bonus_numbers = data[:, 5] + + train_size = int(0.8 * len(data)) + + x_train = regular_numbers[:train_size] + y_train_main = [regular_numbers[:train_size][:, i] for i in range(5)] + y_train_bonus = bonus_numbers[:train_size] + + x_val = regular_numbers[train_size:] + y_val_main = [regular_numbers[train_size:][:, i] for i in range(5)] + y_val_bonus = bonus_numbers[train_size:] + + return (x_train, y_train_main, y_train_bonus), (x_val, y_val_main, y_val_bonus) + +def create_model(): + print_status("Building neural network model...") + input_layer = layers.Input(shape=(5,)) + x = layers.Embedding(input_dim=44, output_dim=32)(input_layer) + x = layers.LSTM(64)(x) + + output_main = [layers.Dense(44, activation='softmax', name=f'main_output_{i}')(x) for i in range(5)] + output_bonus = layers.Dense(44, activation='softmax', name='bonus_output')(x) + + model = keras.Model(inputs=input_layer, outputs=output_main + [output_bonus]) + + loss_dict = {f'main_output_{i}': 'sparse_categorical_crossentropy' for i in range(5)} + loss_dict['bonus_output'] = 'sparse_categorical_crossentropy' + + metrics_dict = {f'main_output_{i}': 'accuracy' for i in range(5)} + metrics_dict['bonus_output'] = 'accuracy' + + model.compile( + optimizer='adam', + loss=loss_dict, + metrics=metrics_dict + ) + return model + +def train_model(model, x_train, y_train_main, y_train_bonus, x_val, y_val_main, y_val_bonus): + print_status("Training model (100 epochs)...\n") + train_targets = {f'main_output_{i}': y_train_main[i] for i in range(5)} + train_targets['bonus_output'] = y_train_bonus + + val_targets = {f'main_output_{i}': y_val_main[i] for i in range(5)} + val_targets['bonus_output'] = y_val_bonus + + callback = CustomTrainingCallback() + + return model.fit( + x_train, train_targets, + validation_data=(x_val, val_targets), + epochs=100, + verbose=0, # Desactiva la salida estándar + callbacks=[callback] + ) + +def predict_numbers(model, x_val): + predictions = model.predict(x_val) + pred_main = np.array([np.argmax(p, axis=1) for p in predictions[:-1]]).T + pred_bonus = np.argmax(predictions[-1], axis=1) + return pred_main, pred_bonus + +def print_results(pred_main, pred_bonus): + print_status("Generating predictions...") + print("\033[1;36m" + "=" * 60 + "\033[0m") + print("\033[1;32m" + "🎯 PREDICTED NUMBERS 🎯".center(60) + "\033[0m") + print("\033[1;36m" + "-" * 60 + "\033[0m") + if pred_main.shape[0] > 0: + main_nums = ', '.join(map(str, np.sort(pred_main[0]))) + print(f"\033[1;33mMain Numbers:\033[0m \033[1;37m{main_nums}\033[0m") + print(f"\033[1;33mBonus Number:\033[0m \033[1;37m{pred_bonus[0]}\033[0m") + else: + print("\033[1;31mNo predictions available\033[0m") + print("\033[1;36m" + "=" * 60 + "\033[0m") + +# === Ejecución Principal === +def main(): + print("\x1b[H\x1b[2J\x1b[3J") # Limpia la consola + print_intro() + try: + (x_train, y_train_main, y_train_bonus), (x_val, y_val_main, y_val_bonus) = load_data() + model = create_model() + train_model(model, x_train, y_train_main, y_train_bonus, x_val, y_val_main, y_val_bonus) + pred_main, pred_bonus = predict_numbers(model, x_val) + print_results(pred_main, pred_bonus) + except Exception as e: + print("\033[1;31m[!] Error:\033[0m", str(e)) + sys.exit(1) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/data.txt b/data.txt new file mode 100644 index 0000000..cf687ec --- /dev/null +++ b/data.txt @@ -0,0 +1,12 @@ +10,12,24,32,37,12 +3,21,31,33,40,14 +5,12,17,19,22,16 +6,23,32,34,4,14 +1,15,2,23,31,1 +1,16,18,2,25,15 +4,5,19,28,43,5 +2,9,22,23,25,5 +11,26,31,35,43,6 +24,34,35,36,4,5 +5,11,18,31,32,9 +18,32,34,36,38,13 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..6926cd5 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +tensorflow>=2.10 +numpy>=1.22 +art>=5.9