Novità

Intelligenza artificiale e lotto 🤖🎱📈📉🎯

Buongiorno lotto_tom75 una domanda, se io scelgo solo alcuni numeri e non tutti e 90, devo modificare qualche cosa nello script? Grazie

Codice:
# ==============================================================================
# SISTEMA PREDITTIVO LOTTO CON REINFORCEMENT LEARNING
# Autore: Modello Gemini di Google + Humano (tom) :) 
# Versione: 1.5 - Specialista di Gregge numerico
#
# DESCRIZIONE:
# Script specializzato per analizzare un gruppo ristretto di numeri ("gregge")
# e predire un ambo. Include checkpointing e ripresa del training.
#
# DISCLAIMER:
# Il gioco del Lotto è un processo casuale. Questo script è un esercizio
# accademico e non garantisce alcuna vincita. Giocare responsabilmente.
# ==============================================================================

import pandas as pd
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, BatchNormalization
from tensorflow.keras.optimizers import Adam
from collections import deque
import random
import os
import logging
from tqdm import tqdm
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics.pairwise import cosine_similarity

# --- Sopprimi i messaggi informativi di TensorFlow ---
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

# --- Setup del Logging ---
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# ==============================================================================
# ====> CONFIGURAZIONE DELLO STUDIO SUL GREGGE <====
# ==============================================================================

# 1. DEFINISCI IL TUO GREGGE DI NUMERI #es. c9 abs x s1 su TT e NZ unite by 8117

# GREGGE_SPECIALE = [
# 19.32.41.47.49.54.56.82.90         <-    METTI QUI il tuo GRUPPO BASE NUMERICO (ovviamente togli i # dei commenti per attivare questo pezzo di code)
# ]





# 2. DEFINISCI LA RUOTA DA ANALIZZARE (il "pascolo")
WHEEL_NAME_TO_ANALYZE = 'Napoli' # Esempio, cambiala con la tua scelta

# 3. IMPOSTA I PARAMETRI DI TRAINING
TOTAL_EPISODES = 1      # Imposta a 1 per il training notturno incrementale
BATCH_SIZE = 64         # Dimensione del batch, 64 è un buon compromesso
NUM_PREDICTED_AMBO = 2  # L'obiettivo è predire 2 numeri (un ambo)

# --- Costanti derivate dalla configurazione ---
NUM_GREGGE = len(GREGGE_SPECIALE)
STATE_WINDOW_SIZE = 50

# ==============================================================================

class LottoRLEnvironment:
    def __init__(self, data_features, data_actual_draws):
        self.features = data_features
        self.actual_draws = data_actual_draws
        self.n_steps = len(data_features)
        self.current_step = STATE_WINDOW_SIZE
    def reset(self):
        self.current_step = STATE_WINDOW_SIZE
        return self.features[self.current_step]
    def step(self, actions): # NOTA: Ora accetta più azioni (le 2 predizioni)
        self.current_step += 1
        done = self.current_step >= self.n_steps - 1
        
        predicted_numbers = [GREGGE_SPECIALE[a] for a in actions]
        actual_next_draw = self.actual_draws[self.current_step]
        
        # --- Nuova Reward Function per l'Ambo ---
        hits = sum(1 for num in predicted_numbers if num in actual_next_draw)
        
        if hits == 2:
            reward = 10.0  # Grande ricompensa per l'ambo secco!
        elif hits == 1:
            reward = 1.0   # Piccola ricompensa per un estratto
        else:
            reward = -0.1  # Piccola penalità
            
        next_state = self.features[self.current_step] if not done else None
        return next_state, reward, done

class DQNAgent:
    # ... (La classe DQNAgent rimane quasi identica, le modifiche sono nel flusso) ...
    def __init__(self, state_size, action_size, params):
        self.state_size = state_size
        self.action_size = action_size # Ora sarà 29
        self.memory = deque(maxlen=20000)
        self.gamma = params.get('gamma', 0.95)
        self.epsilon = params.get('epsilon', 1.0)
        self.epsilon_min = 0.01
        self.epsilon_decay = params.get('epsilon_decay', 0.999)
        self.learning_rate = params.get('learning_rate', 0.001)
        self.model = self._build_model()
        self.target_model = self._build_model()
        self.update_target_model()
    def _build_model(self):
        model = Sequential([
            Dense(128, input_dim=self.state_size, activation='relu'),
            BatchNormalization(), Dropout(0.3),
            Dense(128, activation='relu'),
            BatchNormalization(), Dropout(0.3),
            Dense(self.action_size, activation='linear') # Output di 29 neuroni
        ])
        model.compile(loss='mse', optimizer=Adam(learning_rate=self.learning_rate))
        return model
    def update_target_model(self):
        self.target_model.set_weights(self.model.get_weights())
    def remember(self, state, action, reward, next_state, done):
        # NOTA: Ora salviamo una singola azione scelta, non l'ambo
        self.memory.append((state, action, reward, next_state, done))
    def act(self, state, num_to_predict):
        if np.random.rand() <= self.epsilon:
            # Sceglie N azioni casuali e uniche
            return np.random.choice(self.action_size, num_to_predict, replace=False)
        
        # Sceglie le N migliori azioni
        act_values = self.model.predict(state, verbose=0)[0]
        return np.argsort(act_values)[-num_to_predict:][::-1] # Indici delle N migliori azioni
    def replay(self, batch_size):
        if len(self.memory) < batch_size: return
        minibatch = random.sample(self.memory, batch_size)
        
        # Il replay avviene su ogni singola azione/numero predetto
        for state, action, reward, next_state, done in minibatch:
            target = reward
            if not done:
                q_next = self.target_model.predict(next_state, verbose=0)[0]
                target = reward + self.gamma * np.amax(q_next)
            
            target_f = self.model.predict(state, verbose=0)
            target_f[0][action] = target
            
            self.model.fit(state, target_f, epochs=1, verbose=0)

        if self.epsilon > self.epsilon_min:
            self.epsilon *= self.epsilon_decay
    def save(self, name):
        self.model.save(name)
    def load(self, name):
        self.model.load_weights(name)
        self.update_target_model()

class LottoRLPredictor:
    def __init__(self, wheel_name):
        self.wheel_name = wheel_name
        self.df = None
        self.all_draws = []
        self.features = None
        self.agent = None
        self.scaler = MinMaxScaler()
        self.algorithms = {'DQN': {'agent': DQNAgent, 'params': {'learning_rate': 0.001, 'gamma': 0.95, 'epsilon_decay': 0.9995}}}
        self.best_algorithm_name = None
        self.best_params = None
        self.historical_accuracy_report = {}
        self.training_rewards = []

    def load_and_preprocess_data(self, file_path):
        logging.info(f"Caricamento dati da {file_path} per la ruota '{self.wheel_name}'...")
        try:
            df_temp = pd.read_csv(file_path, sep=';', header=None, skiprows=1, dtype=str, on_bad_lines='skip', encoding='utf-8')
            column_names = ['Num', 'Estrazione', 'Ruota', 'Numeri', 'Ritardo', 'Sortita', 'Estratti']
            num_cols_to_assign = min(len(column_names), df_temp.shape[1])
            self.df = df_temp.iloc[:, :num_cols_to_assign]
            self.df.columns = column_names[:num_cols_to_assign]
        except Exception as e:
            logging.error(f"Errore durante la lettura del CSV: {e}"); return

        self.df['Ruota'] = self.df['Ruota'].str.strip().str.title()
        self.wheel_name = self.wheel_name.strip().title()
        self.df = self.df[self.df['Ruota'] == self.wheel_name].copy()
        
        if self.df.empty:
            logging.error(f"Nessuna estrazione trovata per la ruota '{self.wheel_name}'."); self.df = None; return

        self.df['Data'] = pd.to_datetime(self.df['Estrazione'].str.split(' - ').str[1], format='%d/%m/%Y', errors='coerce')
        num_col = 'Estratti' if 'Estratti' in self.df.columns else 'Numeri'
        sep = ' ' if num_col == 'Estratti' else '.'
        
        self.df.dropna(subset=[num_col, 'Data'], inplace=True)
        self.df['Parsed_Numeri'] = self.df[num_col].astype(str).str.strip().str.split(sep).apply(lambda x: [int(n) for n in x if n.isdigit()])
        self.df.sort_values('Data', inplace=True); self.df.reset_index(drop=True, inplace=True)
        self.all_draws = self.df['Parsed_Numeri'].tolist()
        logging.info(f"Caricate {len(self.df)} estrazioni per la ruota '{self.wheel_name}'.")
        self._feature_engineering()

    def _feature_engineering(self):
        logging.info("Inizio Feature Engineering per il Gregge Speciale...")
        # Le features ora sono calcolate solo per i numeri del gregge
        delays = np.zeros((len(self.df), NUM_GREGGE), dtype=int)
        last_seen = {num: -1 for num in GREGGE_SPECIALE}

        for i, draw in enumerate(tqdm(self.all_draws, desc="Calcolo Features Gregge")):
            for idx, num in enumerate(GREGGE_SPECIALE):
                delays[i, idx] = i - last_seen[num] if last_seen[num] != -1 else i + 1
            for extracted_num in draw:
                if extracted_num in last_seen:
                    last_seen[extracted_num] = i
        
        delay_df = pd.DataFrame(delays)
        ma_delay_50 = delay_df.rolling(window=50).mean().fillna(0)
        self.features_df = pd.concat([delay_df.add_prefix('delay_'), ma_delay_50.add_prefix('ma_delay_50_')], axis=1)
        self.features = self.scaler.fit_transform(self.features_df)
        logging.info(f"Feature engineering completato. Shape: {self.features.shape}")

    def train_model(self, episodes, batch_size):
        if self.features is None: logging.error("Dati non caricati."); return
        
        state_size = self.features.shape[1]
        action_size = NUM_GREGGE # Azioni possibili = numero di pecore nel gregge
        
        self.agent = DQNAgent(state_size, action_size, self.algorithms['DQN']['params'])
        model_filename = f"gregge_model_{self.wheel_name.lower()}.h5"

        if os.path.exists(model_filename):
            logging.info(f"Trovato modello pre-esistente. Caricamento di '{model_filename}' per riprendere il training.")
            self.agent.load(model_filename)
        
        logging.info(f"Inizio training per {episodes} episodi...")
        env = LottoRLEnvironment(self.features, self.all_draws)
        
        for e in range(episodes):
            state = env.reset()
            state = np.reshape(state, [1, state_size])
            total_reward = 0
            pbar = tqdm(range(STATE_WINDOW_SIZE, env.n_steps - 1), desc=f"Episodio {e+1}/{episodes}", unit="estrazione")

            for _ in pbar:
                # L'agente sceglie le N migliori azioni (indici del gregge)
                actions = self.agent.act(state, NUM_PREDICTED_AMBO)
                
                # Passiamo le azioni all'ambiente e otteniamo un reward per la coppia
                next_state, reward, done = env.step(actions)
                total_reward += reward
                
                # Per l'apprendimento, salviamo ogni azione separatamente
                if not done:
                    next_state = np.reshape(next_state, [1, state_size])
                    # Semplificazione: diamo lo stesso reward a entrambe le azioni scelte
                    for action in actions:
                        self.agent.remember(state, action, reward, next_state, done)
                
                state = next_state
                if done: break
                
                # Il replay è stato semplificato per gestire azione singola
                if len(self.agent.memory) > batch_size:
                    self.agent.replay(batch_size)
                
                pbar.set_postfix({"Reward": f"{total_reward:.1f}", "Epsilon": f"{self.agent.epsilon:.3f}"})
            
            self.training_rewards.append(total_reward)
            self.agent.save(model_filename)
            logging.info(f"Fine Episodio {e+1}/{episodes} - Reward: {total_reward:.2f} - Modello salvato in '{model_filename}'")
        logging.info("Sessione di training completata.")

    def predict_next_extraction(self):
        if self.agent is None: logging.error("Modello non addestrato."); return None
        logging.info("Generazione predizione AMBO per il gregge...")
        last_state = np.reshape(self.features[-1], [1, self.features.shape[1]])
        
        # L'agente predice gli indici delle migliori N azioni
        predicted_indices = self.agent.act(last_state, NUM_PREDICTED_AMBO)
        
        # Mappiamo gli indici ai numeri reali del gregge
        predicted_numbers = [GREGGE_SPECIALE[i] for i in predicted_indices]
        
        return predicted_numbers
    
    def display_results(self, predictions):
        if not predictions: logging.warning("Nessuna predizione da mostrare."); return
        print(f"\n{'='*60}\nPREDIZIONE PROSSIMO AMBO - RUOTA [{self.wheel_name.upper()}]\n{'='*60}\n")
        print(f"Gruppo di Riferimento: {NUM_GREGGE} numeri")
        print(f"Ambo Predetto: {predictions[0]} - {predictions[1]}")
        print("-" * 30)

        plt.figure(figsize=(12, 6))
        plt.plot(self.training_rewards); plt.title(f'Reward Totale per Episodio (Gregge) - Ruota di {self.wheel_name}')
        plt.xlabel('Episodio'); plt.ylabel('Reward Totale Accumulato'); plt.grid(True); plt.tight_layout()
        plt.savefig(f'gregge_training_rewards_{self.wheel_name.lower()}.png')
        print(f"\nGrafico performance salvato come 'gregge_training_rewards_{self.wheel_name.lower()}.png'")
        plt.show()

# ==============================================================================
# --- FLUSSO DI ESECUZIONE PRINCIPALE ---
# ==============================================================================
if __name__ == '__main__':
    # Usa un nome file specifico per la ruota che stai analizzando
    # Esempio: "archivio_firenze_1000.csv"
    DATASET_FILE = 'archivio_ultime_820ca_sfaldamenti_su-NAPOLI.csv' # <--- METTI QUI IL NOME DEL TUO FILE CSV
    
    predictor = LottoRLPredictor(wheel_name=WHEEL_NAME_TO_ANALYZE)
    
    predictor.load_and_preprocess_data(DATASET_FILE)
    
    if predictor.df is not None and not predictor.df.empty:
        predictor.train_model(episodes=TOTAL_EPISODES, batch_size=BATCH_SIZE)
        
        final_predictions = predictor.predict_next_extraction()
        predictor.display_results(final_predictions)
    else:
        logging.error("Impossibile procedere: nessun dato valido caricato.")
 
Codice:
# ==============================================================================
# SISTEMA PREDITTIVO LOTTO CON REINFORCEMENT LEARNING
# Autore: Modello Gemini di Google + Humano (tom) :)
# Versione: 1.5 - Specialista di Gregge numerico
#
# DESCRIZIONE:
# Script specializzato per analizzare un gruppo ristretto di numeri ("gregge")
# e predire un ambo. Include checkpointing e ripresa del training.
#
# DISCLAIMER:
# Il gioco del Lotto è un processo casuale. Questo script è un esercizio
# accademico e non garantisce alcuna vincita. Giocare responsabilmente.
# ==============================================================================

import pandas as pd
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, BatchNormalization
from tensorflow.keras.optimizers import Adam
from collections import deque
import random
import os
import logging
from tqdm import tqdm
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics.pairwise import cosine_similarity

# --- Sopprimi i messaggi informativi di TensorFlow ---
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

# --- Setup del Logging ---
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# ==============================================================================
# ====> CONFIGURAZIONE DELLO STUDIO SUL GREGGE <====
# ==============================================================================

# 1. DEFINISCI IL TUO GREGGE DI NUMERI #es. c9 abs x s1 su TT e NZ unite by 8117

# GREGGE_SPECIALE = [
# 19.32.41.47.49.54.56.82.90         <-    METTI QUI il tuo GRUPPO BASE NUMERICO (ovviamente togli i # dei commenti per attivare questo pezzo di code)
# ]





# 2. DEFINISCI LA RUOTA DA ANALIZZARE (il "pascolo")
WHEEL_NAME_TO_ANALYZE = 'Napoli' # Esempio, cambiala con la tua scelta

# 3. IMPOSTA I PARAMETRI DI TRAINING
TOTAL_EPISODES = 1      # Imposta a 1 per il training notturno incrementale
BATCH_SIZE = 64         # Dimensione del batch, 64 è un buon compromesso
NUM_PREDICTED_AMBO = 2  # L'obiettivo è predire 2 numeri (un ambo)

# --- Costanti derivate dalla configurazione ---
NUM_GREGGE = len(GREGGE_SPECIALE)
STATE_WINDOW_SIZE = 50

# ==============================================================================

class LottoRLEnvironment:
    def __init__(self, data_features, data_actual_draws):
        self.features = data_features
        self.actual_draws = data_actual_draws
        self.n_steps = len(data_features)
        self.current_step = STATE_WINDOW_SIZE
    def reset(self):
        self.current_step = STATE_WINDOW_SIZE
        return self.features[self.current_step]
    def step(self, actions): # NOTA: Ora accetta più azioni (le 2 predizioni)
        self.current_step += 1
        done = self.current_step >= self.n_steps - 1
       
        predicted_numbers = [GREGGE_SPECIALE[a] for a in actions]
        actual_next_draw = self.actual_draws[self.current_step]
       
        # --- Nuova Reward Function per l'Ambo ---
        hits = sum(1 for num in predicted_numbers if num in actual_next_draw)
       
        if hits == 2:
            reward = 10.0  # Grande ricompensa per l'ambo secco!
        elif hits == 1:
            reward = 1.0   # Piccola ricompensa per un estratto
        else:
            reward = -0.1  # Piccola penalità
           
        next_state = self.features[self.current_step] if not done else None
        return next_state, reward, done

class DQNAgent:
    # ... (La classe DQNAgent rimane quasi identica, le modifiche sono nel flusso) ...
    def __init__(self, state_size, action_size, params):
        self.state_size = state_size
        self.action_size = action_size # Ora sarà 29
        self.memory = deque(maxlen=20000)
        self.gamma = params.get('gamma', 0.95)
        self.epsilon = params.get('epsilon', 1.0)
        self.epsilon_min = 0.01
        self.epsilon_decay = params.get('epsilon_decay', 0.999)
        self.learning_rate = params.get('learning_rate', 0.001)
        self.model = self._build_model()
        self.target_model = self._build_model()
        self.update_target_model()
    def _build_model(self):
        model = Sequential([
            Dense(128, input_dim=self.state_size, activation='relu'),
            BatchNormalization(), Dropout(0.3),
            Dense(128, activation='relu'),
            BatchNormalization(), Dropout(0.3),
            Dense(self.action_size, activation='linear') # Output di 29 neuroni
        ])
        model.compile(loss='mse', optimizer=Adam(learning_rate=self.learning_rate))
        return model
    def update_target_model(self):
        self.target_model.set_weights(self.model.get_weights())
    def remember(self, state, action, reward, next_state, done):
        # NOTA: Ora salviamo una singola azione scelta, non l'ambo
        self.memory.append((state, action, reward, next_state, done))
    def act(self, state, num_to_predict):
        if np.random.rand() <= self.epsilon:
            # Sceglie N azioni casuali e uniche
            return np.random.choice(self.action_size, num_to_predict, replace=False)
       
        # Sceglie le N migliori azioni
        act_values = self.model.predict(state, verbose=0)[0]
        return np.argsort(act_values)[-num_to_predict:][::-1] # Indici delle N migliori azioni
    def replay(self, batch_size):
        if len(self.memory) < batch_size: return
        minibatch = random.sample(self.memory, batch_size)
       
        # Il replay avviene su ogni singola azione/numero predetto
        for state, action, reward, next_state, done in minibatch:
            target = reward
            if not done:
                q_next = self.target_model.predict(next_state, verbose=0)[0]
                target = reward + self.gamma * np.amax(q_next)
           
            target_f = self.model.predict(state, verbose=0)
            target_f[0][action] = target
           
            self.model.fit(state, target_f, epochs=1, verbose=0)

        if self.epsilon > self.epsilon_min:
            self.epsilon *= self.epsilon_decay
    def save(self, name):
        self.model.save(name)
    def load(self, name):
        self.model.load_weights(name)
        self.update_target_model()

class LottoRLPredictor:
    def __init__(self, wheel_name):
        self.wheel_name = wheel_name
        self.df = None
        self.all_draws = []
        self.features = None
        self.agent = None
        self.scaler = MinMaxScaler()
        self.algorithms = {'DQN': {'agent': DQNAgent, 'params': {'learning_rate': 0.001, 'gamma': 0.95, 'epsilon_decay': 0.9995}}}
        self.best_algorithm_name = None
        self.best_params = None
        self.historical_accuracy_report = {}
        self.training_rewards = []

    def load_and_preprocess_data(self, file_path):
        logging.info(f"Caricamento dati da {file_path} per la ruota '{self.wheel_name}'...")
        try:
            df_temp = pd.read_csv(file_path, sep=';', header=None, skiprows=1, dtype=str, on_bad_lines='skip', encoding='utf-8')
            column_names = ['Num', 'Estrazione', 'Ruota', 'Numeri', 'Ritardo', 'Sortita', 'Estratti']
            num_cols_to_assign = min(len(column_names), df_temp.shape[1])
            self.df = df_temp.iloc[:, :num_cols_to_assign]
            self.df.columns = column_names[:num_cols_to_assign]
        except Exception as e:
            logging.error(f"Errore durante la lettura del CSV: {e}"); return

        self.df['Ruota'] = self.df['Ruota'].str.strip().str.title()
        self.wheel_name = self.wheel_name.strip().title()
        self.df = self.df[self.df['Ruota'] == self.wheel_name].copy()
       
        if self.df.empty:
            logging.error(f"Nessuna estrazione trovata per la ruota '{self.wheel_name}'."); self.df = None; return

        self.df['Data'] = pd.to_datetime(self.df['Estrazione'].str.split(' - ').str[1], format='%d/%m/%Y', errors='coerce')
        num_col = 'Estratti' if 'Estratti' in self.df.columns else 'Numeri'
        sep = ' ' if num_col == 'Estratti' else '.'
       
        self.df.dropna(subset=[num_col, 'Data'], inplace=True)
        self.df['Parsed_Numeri'] = self.df[num_col].astype(str).str.strip().str.split(sep).apply(lambda x: [int(n) for n in x if n.isdigit()])
        self.df.sort_values('Data', inplace=True); self.df.reset_index(drop=True, inplace=True)
        self.all_draws = self.df['Parsed_Numeri'].tolist()
        logging.info(f"Caricate {len(self.df)} estrazioni per la ruota '{self.wheel_name}'.")
        self._feature_engineering()

    def _feature_engineering(self):
        logging.info("Inizio Feature Engineering per il Gregge Speciale...")
        # Le features ora sono calcolate solo per i numeri del gregge
        delays = np.zeros((len(self.df), NUM_GREGGE), dtype=int)
        last_seen = {num: -1 for num in GREGGE_SPECIALE}

        for i, draw in enumerate(tqdm(self.all_draws, desc="Calcolo Features Gregge")):
            for idx, num in enumerate(GREGGE_SPECIALE):
                delays[i, idx] = i - last_seen[num] if last_seen[num] != -1 else i + 1
            for extracted_num in draw:
                if extracted_num in last_seen:
                    last_seen[extracted_num] = i
       
        delay_df = pd.DataFrame(delays)
        ma_delay_50 = delay_df.rolling(window=50).mean().fillna(0)
        self.features_df = pd.concat([delay_df.add_prefix('delay_'), ma_delay_50.add_prefix('ma_delay_50_')], axis=1)
        self.features = self.scaler.fit_transform(self.features_df)
        logging.info(f"Feature engineering completato. Shape: {self.features.shape}")

    def train_model(self, episodes, batch_size):
        if self.features is None: logging.error("Dati non caricati."); return
       
        state_size = self.features.shape[1]
        action_size = NUM_GREGGE # Azioni possibili = numero di pecore nel gregge
       
        self.agent = DQNAgent(state_size, action_size, self.algorithms['DQN']['params'])
        model_filename = f"gregge_model_{self.wheel_name.lower()}.h5"

        if os.path.exists(model_filename):
            logging.info(f"Trovato modello pre-esistente. Caricamento di '{model_filename}' per riprendere il training.")
            self.agent.load(model_filename)
       
        logging.info(f"Inizio training per {episodes} episodi...")
        env = LottoRLEnvironment(self.features, self.all_draws)
       
        for e in range(episodes):
            state = env.reset()
            state = np.reshape(state, [1, state_size])
            total_reward = 0
            pbar = tqdm(range(STATE_WINDOW_SIZE, env.n_steps - 1), desc=f"Episodio {e+1}/{episodes}", unit="estrazione")

            for _ in pbar:
                # L'agente sceglie le N migliori azioni (indici del gregge)
                actions = self.agent.act(state, NUM_PREDICTED_AMBO)
               
                # Passiamo le azioni all'ambiente e otteniamo un reward per la coppia
                next_state, reward, done = env.step(actions)
                total_reward += reward
               
                # Per l'apprendimento, salviamo ogni azione separatamente
                if not done:
                    next_state = np.reshape(next_state, [1, state_size])
                    # Semplificazione: diamo lo stesso reward a entrambe le azioni scelte
                    for action in actions:
                        self.agent.remember(state, action, reward, next_state, done)
               
                state = next_state
                if done: break
               
                # Il replay è stato semplificato per gestire azione singola
                if len(self.agent.memory) > batch_size:
                    self.agent.replay(batch_size)
               
                pbar.set_postfix({"Reward": f"{total_reward:.1f}", "Epsilon": f"{self.agent.epsilon:.3f}"})
           
            self.training_rewards.append(total_reward)
            self.agent.save(model_filename)
            logging.info(f"Fine Episodio {e+1}/{episodes} - Reward: {total_reward:.2f} - Modello salvato in '{model_filename}'")
        logging.info("Sessione di training completata.")

    def predict_next_extraction(self):
        if self.agent is None: logging.error("Modello non addestrato."); return None
        logging.info("Generazione predizione AMBO per il gregge...")
        last_state = np.reshape(self.features[-1], [1, self.features.shape[1]])
       
        # L'agente predice gli indici delle migliori N azioni
        predicted_indices = self.agent.act(last_state, NUM_PREDICTED_AMBO)
       
        # Mappiamo gli indici ai numeri reali del gregge
        predicted_numbers = [GREGGE_SPECIALE[i] for i in predicted_indices]
       
        return predicted_numbers
   
    def display_results(self, predictions):
        if not predictions: logging.warning("Nessuna predizione da mostrare."); return
        print(f"\n{'='*60}\nPREDIZIONE PROSSIMO AMBO - RUOTA [{self.wheel_name.upper()}]\n{'='*60}\n")
        print(f"Gruppo di Riferimento: {NUM_GREGGE} numeri")
        print(f"Ambo Predetto: {predictions[0]} - {predictions[1]}")
        print("-" * 30)

        plt.figure(figsize=(12, 6))
        plt.plot(self.training_rewards); plt.title(f'Reward Totale per Episodio (Gregge) - Ruota di {self.wheel_name}')
        plt.xlabel('Episodio'); plt.ylabel('Reward Totale Accumulato'); plt.grid(True); plt.tight_layout()
        plt.savefig(f'gregge_training_rewards_{self.wheel_name.lower()}.png')
        print(f"\nGrafico performance salvato come 'gregge_training_rewards_{self.wheel_name.lower()}.png'")
        plt.show()

# ==============================================================================
# --- FLUSSO DI ESECUZIONE PRINCIPALE ---
# ==============================================================================
if __name__ == '__main__':
    # Usa un nome file specifico per la ruota che stai analizzando
    # Esempio: "archivio_firenze_1000.csv"
    DATASET_FILE = 'archivio_ultime_820ca_sfaldamenti_su-NAPOLI.csv' # <--- METTI QUI IL NOME DEL TUO FILE CSV
   
    predictor = LottoRLPredictor(wheel_name=WHEEL_NAME_TO_ANALYZE)
   
    predictor.load_and_preprocess_data(DATASET_FILE)
   
    if predictor.df is not None and not predictor.df.empty:
        predictor.train_model(episodes=TOTAL_EPISODES, batch_size=BATCH_SIZE)
       
        final_predictions = predictor.predict_next_extraction()
        predictor.display_results(final_predictions)
    else:
        logging.error("Impossibile procedere: nessun dato valido caricato.")
Grazie lotto_tom75
 
Ho fatto una prova : Caricate 160 estrazioni e 1 solo episodio ma è lentissimo.
Lo so... 😑 Sul mio mini PC con GPU integrata molto scarsa e processore Celeron come ho scritto sopra ha impiegato ben 6 ore per analizzare anche se con successo.. solo le ultime 100 estrazioni su NA per un solo episodio. Quindi, a meno di non passare a GPU come quelle su colab o kaggle, se si vuole far girare script python di questo tipo su PC senza GPU performante bisogna pazientare... e molto.. 🙃🙂
 
Ultima modifica:
Codice:
# ==============================================================================
# SISTEMA PREDITTIVO LOTTO CON REINFORCEMENT LEARNING
# Autore: Modello Gemini di Google + Humano (tom) :)
# Versione: 1.5 - Specialista di Gregge numerico
#
# DESCRIZIONE:
# Script specializzato per analizzare un gruppo ristretto di numeri ("gregge")
# e predire un ambo. Include checkpointing e ripresa del training.
#
# DISCLAIMER:
# Il gioco del Lotto è un processo casuale. Questo script è un esercizio
# accademico e non garantisce alcuna vincita. Giocare responsabilmente.
# ==============================================================================

import pandas as pd
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, BatchNormalization
from tensorflow.keras.optimizers import Adam
from collections import deque
import random
import os
import logging
from tqdm import tqdm
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics.pairwise import cosine_similarity

# --- Sopprimi i messaggi informativi di TensorFlow ---
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

# --- Setup del Logging ---
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# ==============================================================================
# ====> CONFIGURAZIONE DELLO STUDIO SUL GREGGE <====
# ==============================================================================

# 1. DEFINISCI IL TUO GREGGE DI NUMERI #es. c9 abs x s1 su TT e NZ unite by 8117

# GREGGE_SPECIALE = [
# 19.32.41.47.49.54.56.82.90         <-    METTI QUI il tuo GRUPPO BASE NUMERICO (ovviamente togli i # dei commenti per attivare questo pezzo di code)
# ]





# 2. DEFINISCI LA RUOTA DA ANALIZZARE (il "pascolo")
WHEEL_NAME_TO_ANALYZE = 'Napoli' # Esempio, cambiala con la tua scelta

# 3. IMPOSTA I PARAMETRI DI TRAINING
TOTAL_EPISODES = 1      # Imposta a 1 per il training notturno incrementale
BATCH_SIZE = 64         # Dimensione del batch, 64 è un buon compromesso
NUM_PREDICTED_AMBO = 2  # L'obiettivo è predire 2 numeri (un ambo)

# --- Costanti derivate dalla configurazione ---
NUM_GREGGE = len(GREGGE_SPECIALE)
STATE_WINDOW_SIZE = 50

# ==============================================================================

class LottoRLEnvironment:
    def __init__(self, data_features, data_actual_draws):
        self.features = data_features
        self.actual_draws = data_actual_draws
        self.n_steps = len(data_features)
        self.current_step = STATE_WINDOW_SIZE
    def reset(self):
        self.current_step = STATE_WINDOW_SIZE
        return self.features[self.current_step]
    def step(self, actions): # NOTA: Ora accetta più azioni (le 2 predizioni)
        self.current_step += 1
        done = self.current_step >= self.n_steps - 1
     
        predicted_numbers = [GREGGE_SPECIALE[a] for a in actions]
        actual_next_draw = self.actual_draws[self.current_step]
     
        # --- Nuova Reward Function per l'Ambo ---
        hits = sum(1 for num in predicted_numbers if num in actual_next_draw)
     
        if hits == 2:
            reward = 10.0  # Grande ricompensa per l'ambo secco!
        elif hits == 1:
            reward = 1.0   # Piccola ricompensa per un estratto
        else:
            reward = -0.1  # Piccola penalità
         
        next_state = self.features[self.current_step] if not done else None
        return next_state, reward, done

class DQNAgent:
    # ... (La classe DQNAgent rimane quasi identica, le modifiche sono nel flusso) ...
    def __init__(self, state_size, action_size, params):
        self.state_size = state_size
        self.action_size = action_size # Ora sarà 29
        self.memory = deque(maxlen=20000)
        self.gamma = params.get('gamma', 0.95)
        self.epsilon = params.get('epsilon', 1.0)
        self.epsilon_min = 0.01
        self.epsilon_decay = params.get('epsilon_decay', 0.999)
        self.learning_rate = params.get('learning_rate', 0.001)
        self.model = self._build_model()
        self.target_model = self._build_model()
        self.update_target_model()
    def _build_model(self):
        model = Sequential([
            Dense(128, input_dim=self.state_size, activation='relu'),
            BatchNormalization(), Dropout(0.3),
            Dense(128, activation='relu'),
            BatchNormalization(), Dropout(0.3),
            Dense(self.action_size, activation='linear') # Output di 29 neuroni
        ])
        model.compile(loss='mse', optimizer=Adam(learning_rate=self.learning_rate))
        return model
    def update_target_model(self):
        self.target_model.set_weights(self.model.get_weights())
    def remember(self, state, action, reward, next_state, done):
        # NOTA: Ora salviamo una singola azione scelta, non l'ambo
        self.memory.append((state, action, reward, next_state, done))
    def act(self, state, num_to_predict):
        if np.random.rand() <= self.epsilon:
            # Sceglie N azioni casuali e uniche
            return np.random.choice(self.action_size, num_to_predict, replace=False)
     
        # Sceglie le N migliori azioni
        act_values = self.model.predict(state, verbose=0)[0]
        return np.argsort(act_values)[-num_to_predict:][::-1] # Indici delle N migliori azioni
    def replay(self, batch_size):
        if len(self.memory) < batch_size: return
        minibatch = random.sample(self.memory, batch_size)
     
        # Il replay avviene su ogni singola azione/numero predetto
        for state, action, reward, next_state, done in minibatch:
            target = reward
            if not done:
                q_next = self.target_model.predict(next_state, verbose=0)[0]
                target = reward + self.gamma * np.amax(q_next)
         
            target_f = self.model.predict(state, verbose=0)
            target_f[0][action] = target
         
            self.model.fit(state, target_f, epochs=1, verbose=0)

        if self.epsilon > self.epsilon_min:
            self.epsilon *= self.epsilon_decay
    def save(self, name):
        self.model.save(name)
    def load(self, name):
        self.model.load_weights(name)
        self.update_target_model()

class LottoRLPredictor:
    def __init__(self, wheel_name):
        self.wheel_name = wheel_name
        self.df = None
        self.all_draws = []
        self.features = None
        self.agent = None
        self.scaler = MinMaxScaler()
        self.algorithms = {'DQN': {'agent': DQNAgent, 'params': {'learning_rate': 0.001, 'gamma': 0.95, 'epsilon_decay': 0.9995}}}
        self.best_algorithm_name = None
        self.best_params = None
        self.historical_accuracy_report = {}
        self.training_rewards = []

    def load_and_preprocess_data(self, file_path):
        logging.info(f"Caricamento dati da {file_path} per la ruota '{self.wheel_name}'...")
        try:
            df_temp = pd.read_csv(file_path, sep=';', header=None, skiprows=1, dtype=str, on_bad_lines='skip', encoding='utf-8')
            column_names = ['Num', 'Estrazione', 'Ruota', 'Numeri', 'Ritardo', 'Sortita', 'Estratti']
            num_cols_to_assign = min(len(column_names), df_temp.shape[1])
            self.df = df_temp.iloc[:, :num_cols_to_assign]
            self.df.columns = column_names[:num_cols_to_assign]
        except Exception as e:
            logging.error(f"Errore durante la lettura del CSV: {e}"); return

        self.df['Ruota'] = self.df['Ruota'].str.strip().str.title()
        self.wheel_name = self.wheel_name.strip().title()
        self.df = self.df[self.df['Ruota'] == self.wheel_name].copy()
     
        if self.df.empty:
            logging.error(f"Nessuna estrazione trovata per la ruota '{self.wheel_name}'."); self.df = None; return

        self.df['Data'] = pd.to_datetime(self.df['Estrazione'].str.split(' - ').str[1], format='%d/%m/%Y', errors='coerce')
        num_col = 'Estratti' if 'Estratti' in self.df.columns else 'Numeri'
        sep = ' ' if num_col == 'Estratti' else '.'
     
        self.df.dropna(subset=[num_col, 'Data'], inplace=True)
        self.df['Parsed_Numeri'] = self.df[num_col].astype(str).str.strip().str.split(sep).apply(lambda x: [int(n) for n in x if n.isdigit()])
        self.df.sort_values('Data', inplace=True); self.df.reset_index(drop=True, inplace=True)
        self.all_draws = self.df['Parsed_Numeri'].tolist()
        logging.info(f"Caricate {len(self.df)} estrazioni per la ruota '{self.wheel_name}'.")
        self._feature_engineering()

    def _feature_engineering(self):
        logging.info("Inizio Feature Engineering per il Gregge Speciale...")
        # Le features ora sono calcolate solo per i numeri del gregge
        delays = np.zeros((len(self.df), NUM_GREGGE), dtype=int)
        last_seen = {num: -1 for num in GREGGE_SPECIALE}

        for i, draw in enumerate(tqdm(self.all_draws, desc="Calcolo Features Gregge")):
            for idx, num in enumerate(GREGGE_SPECIALE):
                delays[i, idx] = i - last_seen[num] if last_seen[num] != -1 else i + 1
            for extracted_num in draw:
                if extracted_num in last_seen:
                    last_seen[extracted_num] = i
     
        delay_df = pd.DataFrame(delays)
        ma_delay_50 = delay_df.rolling(window=50).mean().fillna(0)
        self.features_df = pd.concat([delay_df.add_prefix('delay_'), ma_delay_50.add_prefix('ma_delay_50_')], axis=1)
        self.features = self.scaler.fit_transform(self.features_df)
        logging.info(f"Feature engineering completato. Shape: {self.features.shape}")

    def train_model(self, episodes, batch_size):
        if self.features is None: logging.error("Dati non caricati."); return
     
        state_size = self.features.shape[1]
        action_size = NUM_GREGGE # Azioni possibili = numero di pecore nel gregge
     
        self.agent = DQNAgent(state_size, action_size, self.algorithms['DQN']['params'])
        model_filename = f"gregge_model_{self.wheel_name.lower()}.h5"

        if os.path.exists(model_filename):
            logging.info(f"Trovato modello pre-esistente. Caricamento di '{model_filename}' per riprendere il training.")
            self.agent.load(model_filename)
     
        logging.info(f"Inizio training per {episodes} episodi...")
        env = LottoRLEnvironment(self.features, self.all_draws)
     
        for e in range(episodes):
            state = env.reset()
            state = np.reshape(state, [1, state_size])
            total_reward = 0
            pbar = tqdm(range(STATE_WINDOW_SIZE, env.n_steps - 1), desc=f"Episodio {e+1}/{episodes}", unit="estrazione")

            for _ in pbar:
                # L'agente sceglie le N migliori azioni (indici del gregge)
                actions = self.agent.act(state, NUM_PREDICTED_AMBO)
             
                # Passiamo le azioni all'ambiente e otteniamo un reward per la coppia
                next_state, reward, done = env.step(actions)
                total_reward += reward
             
                # Per l'apprendimento, salviamo ogni azione separatamente
                if not done:
                    next_state = np.reshape(next_state, [1, state_size])
                    # Semplificazione: diamo lo stesso reward a entrambe le azioni scelte
                    for action in actions:
                        self.agent.remember(state, action, reward, next_state, done)
             
                state = next_state
                if done: break
             
                # Il replay è stato semplificato per gestire azione singola
                if len(self.agent.memory) > batch_size:
                    self.agent.replay(batch_size)
             
                pbar.set_postfix({"Reward": f"{total_reward:.1f}", "Epsilon": f"{self.agent.epsilon:.3f}"})
         
            self.training_rewards.append(total_reward)
            self.agent.save(model_filename)
            logging.info(f"Fine Episodio {e+1}/{episodes} - Reward: {total_reward:.2f} - Modello salvato in '{model_filename}'")
        logging.info("Sessione di training completata.")

    def predict_next_extraction(self):
        if self.agent is None: logging.error("Modello non addestrato."); return None
        logging.info("Generazione predizione AMBO per il gregge...")
        last_state = np.reshape(self.features[-1], [1, self.features.shape[1]])
     
        # L'agente predice gli indici delle migliori N azioni
        predicted_indices = self.agent.act(last_state, NUM_PREDICTED_AMBO)
     
        # Mappiamo gli indici ai numeri reali del gregge
        predicted_numbers = [GREGGE_SPECIALE[i] for i in predicted_indices]
     
        return predicted_numbers
 
    def display_results(self, predictions):
        if not predictions: logging.warning("Nessuna predizione da mostrare."); return
        print(f"\n{'='*60}\nPREDIZIONE PROSSIMO AMBO - RUOTA [{self.wheel_name.upper()}]\n{'='*60}\n")
        print(f"Gruppo di Riferimento: {NUM_GREGGE} numeri")
        print(f"Ambo Predetto: {predictions[0]} - {predictions[1]}")
        print("-" * 30)

        plt.figure(figsize=(12, 6))
        plt.plot(self.training_rewards); plt.title(f'Reward Totale per Episodio (Gregge) - Ruota di {self.wheel_name}')
        plt.xlabel('Episodio'); plt.ylabel('Reward Totale Accumulato'); plt.grid(True); plt.tight_layout()
        plt.savefig(f'gregge_training_rewards_{self.wheel_name.lower()}.png')
        print(f"\nGrafico performance salvato come 'gregge_training_rewards_{self.wheel_name.lower()}.png'")
        plt.show()

# ==============================================================================
# --- FLUSSO DI ESECUZIONE PRINCIPALE ---
# ==============================================================================
if __name__ == '__main__':
    # Usa un nome file specifico per la ruota che stai analizzando
    # Esempio: "archivio_firenze_1000.csv"
    DATASET_FILE = 'archivio_ultime_820ca_sfaldamenti_su-NAPOLI.csv' # <--- METTI QUI IL NOME DEL TUO FILE CSV
 
    predictor = LottoRLPredictor(wheel_name=WHEEL_NAME_TO_ANALYZE)
 
    predictor.load_and_preprocess_data(DATASET_FILE)
 
    if predictor.df is not None and not predictor.df.empty:
        predictor.train_model(episodes=TOTAL_EPISODES, batch_size=BATCH_SIZE)
     
        final_predictions = predictor.predict_next_extraction()
        predictor.display_results(final_predictions)
    else:
        logging.error("Impossibile procedere: nessun dato valido caricato.")


non riesco a farlo girare mi da errore sull' inserimento dei numeri . Potresti metter il formato del file csv ? Il mio è cosi :



fi tom tom.jpg
 
non riesco a farlo girare mi da errore sull' inserimento dei numeri . Potresti metter il formato del file csv ? Il mio è cosi :



Vedi l'allegato 2305363
Lotto_tom75 questo grafico come va interpretato ?Vedi l'allegato 2305385


come ho scritto qui https://forum.lottoced.com/threads/intelligenza-artificiale-e-lotto-🤖🎱📈📉🎯.2211449/post-2752119


# il formato del lotto deve essere questo qui sotto di esempio (ovvero quello che si ottiene da spaziometria sezione statistica veloce in basso a sx. Ovviamente si può anche usare un altro formato di dataset ma a patto di modificare anche il relativo codice di lettura dello stesso...)


# Num;Estrazione;Ruota;Numeri;Ritardo;Sortita;Estratti;
# 10581;10588 - 30/01/2025;Firenze;04.63.56.34.90;0;Cinquina;04 63 56 34 90 ;
# 10582;10589 - 31/01/2025;Firenze;38.51.15.50.56;0;Cinquina;38 51 15 50 56 ;
# 10583;10590 - 01/02/2025;Firenze;73.63.57.74.86;0;Cinquina;73 63 57 74 86 ;
# 10584;10591 - 04/02/2025;Firenze;20.33.60.73.87;0;Cinquina;20 33 60 73 87 ;
# 10585;10592 - 06/02/2025;Firenze;59.29.75.36.73;0;Cinquina;59 29 75 36 73 ;
# 10586;10593 - 07/02/2025;Firenze;01.31.73.34.37;0;Cinquina;01 31 73 34 37 ;
# 10587;10594 - 08/02/2025;Firenze;24.45.62.77.76;0;Cinquina;24 45 62 77 76 ;
# 10588;10595 - 11/02/2025;Firenze;04.57.11.79.12;0;Cinquina;04 57 11 79 12 ;
# 10589;10596 - 13/02/2025;Firenze;21.57.56.04.44;0;Cinquina;21 57 56 04 44 ;
# 10590;10597 - 14/02/2025;Firenze;21.87.82.53.31;0;Cinquina;21 87 82 53 31 ;
# 10591;10598 - 15/02/2025;Firenze;77.37.02.57.36;0;Cinquina;77 37 02 57 36 ;
# 10592;10599 - 18/02/2025;Firenze;11.68.62.04.21;0;Cinquina;11 68 62 04 21 ;
# 10593;10600 - 20/02/2025;Firenze;60.80.86.48.19;0;Cinquina;60 80 86 48 19 ;
# 10594;10601 - 21/02/2025;Firenze;54.01.37.47.04;0;Cinquina;54 01 37 47 04 ;
# 10595;10602 - 22/02/2025;Firenze;42.38.70.71.80;0;Cinquina;42 38 70 71 80 ;
....


e lo si ricava facendo così:



il grafico non c'è perchè come spiegato qui


è solo un punto essendo il periodo di addestramento solo 1

per ogni periodo di addestramento si crea un punto .. lungo l'asse x,y e se questi punti progressivi salgono... significa che il modello studia bene... se scendono che deve applicarsi di +...

Mi rendo conto che l'argomento è complesso.. l'unico consiglio che mi sento di darvi, se davvero volete impelagarvi nella sua comprensione e attuazione, è di cercare di capirlo dalle basi con l'aiuto dell'AI. Per chi invece è già addentro dell'argomento è ottimo domandare all'AI su colab google e su kaggle sempre di google. Specialmente se non si hanno GPU potenti a disposizione. Questi due servizi infatti le mettono disponibili gratuitamente per tutti gli interessati a tempo limitato rinnovabile per blocchi temporali decisamente interessanti. 🚀🤖. Non da ultimo kaggle offre sempre gratuitamente tutorial e corsi su molteplici argomenti relativi al mondo dell'AI e similari (in inglese ma traducibile con la traduzione automatica di google). Ultima chicca riguardo vibe coding x python o qualsiasi altro linguaggio o app AI o meno oriented: OPAL nuovo servizio di google per fare vibe coding tramite diagrammi di flusso visivi... (stile n8n, comfyUI ecc...) . Per adesso ci vuole una vpn per poterlo utilizzare.

👋🙂
 
Ultima modifica:

Ultima estrazione Lotto

  • Estrazione del lotto
    sabato 02 agosto 2025
    Bari
    65
    06
    49
    14
    01
    Cagliari
    16
    20
    15
    28
    45
    Firenze
    39
    10
    83
    09
    16
    Genova
    52
    74
    79
    63
    59
    Milano
    44
    88
    57
    34
    80
    Napoli
    20
    29
    78
    84
    79
    Palermo
    76
    68
    60
    64
    02
    Roma
    80
    84
    27
    78
    57
    Torino
    25
    50
    41
    49
    69
    Venezia
    85
    33
    60
    45
    84
    Nazionale
    05
    02
    64
    79
    37
    Estrazione Simbolotto
    Nazionale
    41
    07
    11
    17
    22
Indietro
Alto