-->

Intelligenza Artificiale

A un certo punto non fu più la biologia a dominare il destino dell'uomo, ma il prodotto del suo cervello: la cultura.
Cosicché: "Le uniche leggi della materia sono quelle che la nostra mente deve architettare e le uniche leggi della mente sono architettate per essa dalla materia".
JAMES CLERK MAXWELL

Riconoscere Email Spam


Un'analisi del testo per classificare le email come non-spam o spam con logistic regression.

Analisi Email Spam

Il codice esegue un'analisi del testo per classificare le email come ham (non-spam) o spam utilizzando la logistic regression.
Qui di seguito, spiego passo per passo come funziona il codice e le sue singole sezioni.

Importazione delle librerie



import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
from sklearn.impute import SimpleImputer
from nltk.corpus import stopwords
import string
from nltk.stem import WordNetLemmatizer


- NumPy, Pandas: Utilizzati per la gestione dei dati numerici e tabulari (rispettivamente).
- Matplotlib, Seaborn: Per la visualizzazione dei dati (grafici e diagrammi).
- Scikit-learn (sklearn): Contiene strumenti per l'elaborazione del testo, la creazione di modelli, la suddivisione del dataset e la valutazione delle prestazioni del modello.
- NLTK: Libreria per l'elaborazione del linguaggio naturale (in questo caso, per le stopwords e la lemmatizzazione).

Caricamento e preprocessing del dataset



df = pd.read_csv('spam.csv', encoding='latin-1')

df = df[['v1', 'v2']]  # Siamo interessati solo alle colonne 'v1' (etichetta) e 'v2' (messaggio)
df.columns = ['label', 'message']  # Rinomina le colonne per maggiore chiarezza
df['label'] = df['label'].map({'ham': 0, 'spam': 1})  # Mappa 'ham' (non-spam) a 0 e 'spam' a 1


- Il dataset viene caricato da un file CSV denominato `spam.csv`.
- Vengono selezionate solo due colonne: `v1` (etichetta, "ham" o "spam") e `v2` (contenuto del messaggio).
- Le colonne vengono rinominate come `label` (per la classe, 0 = "ham", 1 = "spam") e `message` (per il contenuto del messaggio).
- L'etichetta `ham` viene mappata al valore `0`, mentre `spam` viene mappato a `1`.

Preprocessing del testo


stop_words = set(stopwords.words('english'))
lemmatizer = WordNetLemmatizer()

def preprocess_text(text):
    # Rimuove la punteggiatura e converte tutto in minuscolo
    text = text.lower()
    text = ''.join([char for char in text if char not in string.punctuation])
    # Tokenizzazione e lemmatizzazione
    text = ' '.join([lemmatizer.lemmatize(word) for word in text.split() if word not in stop_words])
    return text

df['message'] = df['message'].apply(preprocess_text)


- Stopwords: Vengono caricate le **stopwords** della lingua inglese, cioè le parole comuni (come "e", "il", "a") che non aggiungono valore informativo nel modello.
- Lemmatizzazione: Viene utilizzato un lemmatizzatore per ridurre le parole alle loro forme di base (ad esempio, "running" diventa "run").
- Funzione `preprocess_text`:
- La funzione converte tutto il testo in minuscolo.
- Rimuove la punteggiatura.
- Esegue la lemmatizzazione di ogni parola del testo, mantenendo solo le parole che non sono stopwords.
- La funzione `apply` viene utilizzata per applicare il preprocessing a ciascun messaggio del dataset.

Suddivisione del dataset in addestramento e test


X_train, X_test, y_train, y_test = train_test_split(df['message'], df['label'], test_size=0.2, random_state=42)


- Il dataset viene suddiviso in un **training set** (80%) e un **test set** (20%) utilizzando la funzione `train_test_split`.
- `X_train` e `X_test` contengono rispettivamente i messaggi di addestramento e test.
- `y_train` e `y_test` contengono le etichette corrispondenti.

Vettorizzazione del testo



vectorizer = CountVectorizer(max_features=5000)  # Limita il numero di parole
X_train_vec = vectorizer.fit_transform(X_train)
X_test_vec = vectorizer.transform(X_test)


- CountVectorizer: Converte i messaggi di testo in vettori numerici (bag of words). Ogni parola diventa una caratteristica (colonna) e il valore in ogni cella rappresenta la frequenza della parola in quel messaggio.
- `max_features=5000`: Limita il numero massimo di parole prese in considerazione a 5000 per evitare che il modello diventi troppo complesso.
- La funzione `fit_transform` viene utilizzata sui dati di addestramento per "insegnare" al modello il vocabolario e trasformare i dati in vettori.
- La funzione `transform` viene utilizzata sui dati di test per trasformarli con lo stesso vocabolario.

Creazione e addestramento del modello



model = make_pipeline(StandardScaler(with_mean=False), LogisticRegression(max_iter=1000, class_weight='balanced'))
model.fit(X_train_vec, y_train)


- Pipeline: Combina il StandardScaler (per la normalizzazione dei dati) e LogisticRegression in un'unica pipeline.
- `StandardScaler(with_mean=False)` normalizza i dati, ma senza centrarli attorno alla media, dato che la matrice di caratteristiche è sparsa.
- Logistic Regression è utilizzata per la classificazione binaria.
- `class_weight='balanced'` gestisce uno squilibrio tra le classi, bilanciando i pesi tra la classe "ham" e "spam".
- Il modello viene addestrato sui dati di addestramento (`X_train_vec` e `y_train`).

Previsioni e valutazione del modello



y_pred = model.predict(X_test_vec)

accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)


- Previsioni: Il modello fa previsioni sui dati di test (`X_test_vec`), restituendo le etichette predette (`y_pred`).
- Le metriche di valutazione vengono calcolate per misurare le prestazioni del modello:
- Accuratezza: Percentuale di previsioni corrette sul totale. - Precisione: Percentuale di messaggi correttamente classificati come "spam" rispetto a tutti quelli classificati come "spam".
- Recall: Percentuale di messaggi effettivamente "spam" che sono stati correttamente identificati.
- F1-score: Media armonica tra precisione e recall, utile quando le classi sono sbilanciate.

Stampa dei risultati



print(f"Accuratezza: {accuracy * 100:.2f}%")
print(f"Precisione: {precision * 100:.2f}%")
print(f"Recall: {recall * 100:.2f}%")
print(f"F1-score: {f1 * 100:.2f}%")


- Vengono stampate le metriche calcolate: accuratezza, precisione, recall e F1-score.

Matrice di confusione



conf_matrix = confusion_matrix(y_test, y_pred)

plt.figure(figsize=(8, 6))
sns.heatmap(conf_matrix, annot=True, fmt="d", cmap="Blues", xticklabels=["Ham", "Spam"], yticklabels=["Ham", "Spam"])
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.title('Confusion Matrix')
plt.show()


- La matrice di confusione viene calcolata per visualizzare il numero di previsioni corrette e errate per ciascuna classe (ham/spam).
- Viene visualizzata utilizzando Seaborn come una heatmap, con annotazioni per visualizzare i valori numerici.
Le etichette degli assi vengono modificate per riflettere le classi "Ham" e "Spam".

Riassunto


Il codice esegue una classificazione del testo per distinguere tra email "ham" e "spam", usando il modello di Logistic Regression e le tecniche di preprocessing come rimozione di stopwords, lemmatizzazione e vettorizzazione del testo.
Viene valutato con accuratezza, precisione, recall, F1-score e una matrice di confusione visualizzata tramite una heatmap.