Untitled

 avatar
unknown
plain_text
a month ago
6.0 kB
2
Indexable
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
from sklearn.model_selection import train_test_split

# 1. Caricamento e preprocessamento del dataset
def load_monk_dataset(file_path):
    """
    Carica il dataset MONK dal file specificato e lo preprocessa.

    - file_path: Percorso del file del dataset.

    Ritorna:
    - X: Tensor con le feature.
    - y: Tensor con le label.
    """
    features = []
    labels = []
    
    with open(file_path, 'r') as file:
        for line in file:
            parts = line.strip().split()
            labels.append(int(parts[0]))  # La prima colonna è la label (class)
            features.append([int(x) for x in parts[1:-1]])  # Le colonne da a1 a a6 sono le feature
    
    X = torch.tensor(features, dtype=torch.float32)
    y = torch.tensor(labels, dtype=torch.long)
    return X, y

# 2. Definizione della rete neurale
class SimpleNN(nn.Module):
    def __init__(self, input_size, hidden_size, num_classes):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(input_size, hidden_size)  # Primo layer: da input a hidden
        self.relu = nn.ReLU()  # Funzione di attivazione ReLU
        self.fc2 = nn.Linear(hidden_size, num_classes)  # Secondo layer: da hidden a output

    def forward(self, x):
        x = self.fc1(x)  # Passa attraverso il primo layer
        x = self.relu(x)  # Applica ReLU
        x = self.fc2(x)  # Passa attraverso il secondo layer
        return x

# 3. Funzione per preparare i dati in DataLoader
def prepare_data(X_train, y_train, X_test, y_test, batch_size=16):
    """
    Trasforma i dati di addestramento e test in tensori PyTorch
    e li organizza in DataLoader per facilitarne la gestione in mini-batch.

    - X_train, y_train: Dati di addestramento (features e label).
    - X_test, y_test: Dati di test (features e label).

    Ritorna:
    - train_loader: DataLoader per i dati di addestramento.
    - test_loader: DataLoader per i dati di test.
    """
    train_dataset = TensorDataset(X_train, y_train)
    test_dataset = TensorDataset(X_test, y_test)

    train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
    test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
    return train_loader, test_loader

# 4. Funzione per addestrare il modello
def train_model(model, train_loader, criterion, optimizer, epochs=10):
    """
    Addestra il modello sui dati di training.

    - model: Rete neurale da addestrare.
    - train_loader: DataLoader per i dati di addestramento.
    - criterion: Funzione di perdita da minimizzare.
    - optimizer: Algoritmo di ottimizzazione (es. Adam).
    - epochs: Numero di epoche (cicli di addestramento).
    """
    model.train()
    for epoch in range(epochs):
        total_loss = 0
        for X_batch, y_batch in train_loader:
            optimizer.zero_grad()
            outputs = model(X_batch)
            loss = criterion(outputs, y_batch)
            loss.backward()
            optimizer.step()
            total_loss += loss.item()
        # print(f"Epoch {epoch+1}/{epochs}, Loss: {total_loss:.4f}")

# 5. Funzione per valutare il modello
def evaluate_model(model, test_loader):
    """
    Valuta il modello sui dati di test.

    - model: Rete neurale da valutare.
    - test_loader: DataLoader per i dati di test.
    """
    model.eval()
    correct = 0
    total = 0
    with torch.no_grad():
        for X_batch, y_batch in test_loader:
            outputs = model(X_batch)
            _, predicted = torch.max(outputs, 1)
            total += y_batch.size(0)
            correct += (predicted == y_batch).sum().item()
    accuracy = correct / total * 100
    print(f"Test Accuracy: {accuracy:.2f}%")
    return accuracy

# 6. Carica e preprocessa il dataset
X, y = load_monk_dataset('monks-1.train')

# Normalizzazione delle feature
X_min = X.min(dim=0, keepdim=True)[0]
X_max = X.max(dim=0, keepdim=True)[0]
X = (X - X_min) / (X_max - X_min)  # Normalizzazione min-max

# Split in training e validation (cross-validation)
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)

# 7. Configurazione del modello
input_size = X.shape[1]  # Numero di feature nel dataset (a1, a2, ..., a6)
hidden_size = 10  # Numero di neuroni nel layer nascosto
num_classes = 2  # Classificazione binaria (0, 1)
learning_rate = 0.001  # Velocità di apprendimento
epochs = 20  # Numero di epoche per l'addestramento

# Inizializza il modello
model = SimpleNN(input_size, hidden_size, num_classes)

# Definisci la funzione di perdita (CrossEntropyLoss per classificazione)
criterion = nn.CrossEntropyLoss()

# Definisci l'ottimizzatore (Adam)
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

# 8. Applicare Cross-Validation (5 fold)
best_model = None
best_accuracy = 0
for fold in range(5):
    print(f"\nTraining Fold {fold + 1}/5")
    
    # Prepara i DataLoader per il training e validation
    train_loader, val_loader = prepare_data(X_train, y_train, X_val, y_val)

    # Addestra il modello
    train_model(model, train_loader, criterion, optimizer, epochs)

    # Valuta il modello
    accuracy = evaluate_model(model, val_loader)

    # Se l'accuratezza è migliore, salva il modello
    if accuracy > best_accuracy:
        best_accuracy = accuracy
        best_model = model

# 9. Test del modello su "monk-1.test"
X_test, y_test = load_monk_dataset('monks-1.test')
X_test = (X_test - X_min) / (X_max - X_min)  # Normalizza anche i dati di test

# Prepara i DataLoader per il test
_, test_loader = prepare_data(X_test, y_test, X_test, y_test)

# Valuta il miglior modello sui dati di test
print("\nEvaluating the Best Model on Test Data:")
evaluate_model(best_model, test_loader)
Editor is loading...
Leave a Comment