Αλγόριθμοι Επιβλεπόμενης Μάθησης
Reading time: 55 minutes
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Βασικές Πληροφορίες
Η επιβλεπόμενη μάθηση χρησιμοποιεί επισημασμένα δεδομένα για να εκπαιδεύσει μοντέλα που μπορούν να κάνουν προβλέψεις σε νέα, αόρατα δεδομένα. Στην κυβερνοασφάλεια, η επιβλεπόμενη μηχανική μάθηση εφαρμόζεται ευρέως σε καθήκοντα όπως η ανίχνευση εισβολών (κατηγοριοποίηση της δικτυακής κίνησης ως κανονική ή επίθεση), η ανίχνευση κακόβουλου λογισμικού (διάκριση κακόβουλου λογισμικού από καλοήθες), η ανίχνευση phishing (ταυτοποίηση δόλιων ιστοσελίδων ή emails) και η φιλτράρισμα spam, μεταξύ άλλων. Κάθε αλγόριθμος έχει τα πλεονεκτήματά του και είναι κατάλληλος για διαφορετικούς τύπους προβλημάτων (κατηγοριοποίηση ή παλινδρόμηση). Παρακάτω ανασκοπούμε βασικούς αλγόριθμους επιβλεπόμενης μάθησης, εξηγούμε πώς λειτουργούν και δείχνουμε τη χρήση τους σε πραγματικά σύνολα δεδομένων κυβερνοασφάλειας. Συζητάμε επίσης πώς ο συνδυασμός μοντέλων (συγκεντρωτική μάθηση) μπορεί συχνά να βελτιώσει την προγνωστική απόδοση.
Αλγόριθμοι
-
Γραμμική Παλινδρόμηση: Ένας θεμελιώδης αλγόριθμος παλινδρόμησης για την πρόβλεψη αριθμητικών αποτελεσμάτων προσαρμόζοντας μια γραμμική εξίσωση στα δεδομένα.
-
Λογιστική Παλινδρόμηση: Ένας αλγόριθμος κατηγοριοποίησης (παρά το όνομά του) που χρησιμοποιεί μια λογιστική συνάρτηση για να μοντελοποιήσει την πιθανότητα ενός δυαδικού αποτελέσματος.
-
Δέντρα Απόφασης: Μοντέλα δομής δέντρου που χωρίζουν τα δεδομένα με βάση τα χαρακτηριστικά για να κάνουν προβλέψεις· συχνά χρησιμοποιούνται για την ερμηνευσιμότητά τους.
-
Τυχαία Δάση: Ένα σύνολο δέντρων απόφασης (μέσω bagging) που βελτιώνει την ακρίβεια και μειώνει την υπερβολική προσαρμογή.
-
Μηχανές Υποστήριξης Διανυσμάτων (SVM): Ταξινομητές μέγιστου περιθωρίου που βρίσκουν το βέλτιστο διαχωριστικό υπερεπίπεδο· μπορούν να χρησιμοποιούν πυρήνες για μη γραμμικά δεδομένα.
-
Naive Bayes: Ένας πιθανοτικός ταξινομητής βασισμένος στο θεώρημα του Bayes με υπόθεση ανεξαρτησίας χαρακτηριστικών, που χρησιμοποιείται διάσημα στη φιλτράρισμα spam.
-
k-Πλησιέστεροι Γείτονες (k-NN): Ένας απλός ταξινομητής "βάσει παραδείγματος" που επισημαίνει ένα δείγμα με βάση την πλειοψηφία της κατηγορίας των πλησιέστερων γειτόνων του.
-
Μηχανές Βελτίωσης Κλίσης: Συγκεντρωτικά μοντέλα (π.χ., XGBoost, LightGBM) που δημιουργούν έναν ισχυρό προγνωστικό παράγοντα προσθέτοντας διαδοχικά ασθενέστερους μαθητές (συνήθως δέντρα απόφασης).
Κάθε ενότητα παρακάτω παρέχει μια βελτιωμένη περιγραφή του αλγορίθμου και ένα παράδειγμα κώδικα Python χρησιμοποιώντας βιβλιοθήκες όπως pandas
και scikit-learn
(και PyTorch
για το παράδειγμα του νευρωνικού δικτύου). Τα παραδείγματα χρησιμοποιούν δημόσια διαθέσιμα σύνολα δεδομένων κυβερνοασφάλειας (όπως NSL-KDD για ανίχνευση εισβολών και ένα σύνολο δεδομένων Ιστοσελίδων Phishing) και ακολουθούν μια συνεπή δομή:
-
Φόρτωση του συνόλου δεδομένων (λήψη μέσω URL αν είναι διαθέσιμο).
-
Προετοιμασία των δεδομένων (π.χ. κωδικοποίηση κατηγορικών χαρακτηριστικών, κλιμάκωση τιμών, διαχωρισμός σε σύνολα εκπαίδευσης/δοκιμής).
-
Εκπαίδευση του μοντέλου στα δεδομένα εκπαίδευσης.
-
Αξιολόγηση σε ένα σύνολο δοκιμής χρησιμοποιώντας μετρικές: ακρίβεια, ευαισθησία, ανάκληση, F1-score και ROC AUC για κατηγοριοποίηση (και μέσο τετραγωνικό σφάλμα για παλινδρόμηση).
Ας εμβαθύνουμε σε κάθε αλγόριθμο:
Γραμμική Παλινδρόμηση
Η γραμμική παλινδρόμηση είναι ένας αλγόριθμος παλινδρόμησης που χρησιμοποιείται για την πρόβλεψη συνεχών αριθμητικών τιμών. Υποθέτει μια γραμμική σχέση μεταξύ των εισαγωγικών χαρακτηριστικών (ανεξάρτητες μεταβλητές) και της εξόδου (εξαρτημένη μεταβλητή). Το μοντέλο προσπαθεί να προσαρμόσει μια ευθεία γραμμή (ή υπερεπίπεδο σε υψηλότερες διαστάσεις) που περιγράφει καλύτερα τη σχέση μεταξύ των χαρακτηριστικών και του στόχου. Αυτό συνήθως γίνεται ελαχιστοποιώντας το άθροισμα των τετραγωνικών σφαλμάτων μεταξύ των προβλεπόμενων και των πραγματικών τιμών (μέθοδος Κανονικών Ελαχίστων Τετραγώνων).
Ο απλούστερος τρόπος για να αναπαραστήσουμε τη γραμμική παλινδρόμηση είναι με μια γραμμή:
y = mx + b
Όπου:
y
είναι η προβλεπόμενη τιμή (έξοδος)m
είναι η κλίση της γραμμής (συντελεστής)x
είναι το χαρακτηριστικό εισόδουb
είναι η τομή y
Ο στόχος της γραμμικής παλινδρόμησης είναι να βρει τη γραμμή που ταιριάζει καλύτερα και ελαχιστοποιεί τη διαφορά μεταξύ των προβλεπόμενων τιμών και των πραγματικών τιμών στο σύνολο δεδομένων. Φυσικά, αυτό είναι πολύ απλό, θα ήταν μια ευθεία γραμμή που χωρίζει 2 κατηγορίες, αλλά αν προστεθούν περισσότερες διαστάσεις, η γραμμή γίνεται πιο περίπλοκη:
y = w1*x1 + w2*x2 + ... + wn*xn + b
tip
Περίπτωσεις χρήσης στην κυβερνοασφάλεια: Η γραμμική παλινδρόμηση από μόνη της είναι λιγότερο συχνή για βασικές εργασίες ασφάλειας (οι οποίες είναι συχνά ταξινόμηση), αλλά μπορεί να εφαρμοστεί για την πρόβλεψη αριθμητικών αποτελεσμάτων. Για παράδειγμα, θα μπορούσε να χρησιμοποιηθεί η γραμμική παλινδρόμηση για να προβλέψει τον όγκο της κυκλοφορίας δικτύου ή να εκτιμήσει τον αριθμό επιθέσεων σε μια χρονική περίοδο με βάση ιστορικά δεδομένα. Θα μπορούσε επίσης να προβλέψει μια βαθμολογία κινδύνου ή τον αναμενόμενο χρόνο μέχρι την ανίχνευση μιας επίθεσης, δεδομένων ορισμένων μετρικών συστήματος. Στην πράξη, οι αλγόριθμοι ταξινόμησης (όπως η λογιστική παλινδρόμηση ή τα δέντρα) χρησιμοποιούνται πιο συχνά για την ανίχνευση εισβολών ή κακόβουλου λογισμικού, αλλά η γραμμική παλινδρόμηση χρησιμεύει ως θεμέλιο και είναι χρήσιμη για αναλύσεις προσανατολισμένες στην παλινδρόμηση.
Βασικά χαρακτηριστικά της Γραμμικής Παλινδρόμησης:
-
Τύπος Προβλήματος: Παλινδρόμηση (πρόβλεψη συνεχών τιμών). Δεν είναι κατάλληλη για άμεση ταξινόμηση εκτός αν εφαρμοστεί ένα κατώφλι στην έξοδο.
-
Ερμηνευσιμότητα: Υψηλή -- οι συντελεστές είναι απλοί στην ερμηνεία, δείχνοντας την γραμμική επίδραση κάθε χαρακτηριστικού.
-
Πλεονεκτήματα: Απλή και γρήγορη; μια καλή βάση για εργασίες παλινδρόμησης; λειτουργεί καλά όταν η πραγματική σχέση είναι περίπου γραμμική.
-
Περιορισμοί: Δεν μπορεί να συλλάβει πολύπλοκες ή μη γραμμικές σχέσεις (χωρίς χειροκίνητη μηχανική χαρακτηριστικών); επιρρεπής σε υποπροσαρμογή αν οι σχέσεις είναι μη γραμμικές; ευαίσθητη σε εξωγενείς τιμές που μπορούν να παραμορφώσουν τα αποτελέσματα.
-
Εύρεση της Καλύτερης Προσαρμογής: Για να βρούμε τη γραμμή της καλύτερης προσαρμογής που διαχωρίζει τις πιθανές κατηγορίες, χρησιμοποιούμε μια μέθοδο που ονομάζεται Ordinary Least Squares (OLS). Αυτή η μέθοδος ελαχιστοποιεί το άθροισμα των τετραγωνικών διαφορών μεταξύ των παρατηρούμενων τιμών και των τιμών που προβλέπονται από το γραμμικό μοντέλο.
Παράδειγμα -- Πρόβλεψη Διάρκειας Σύνδεσης (Παλινδρόμηση) σε ένα Σύνολο Δεδομένων Εισβολής
Παρακάτω δείχνουμε τη γραμμική παλινδρόμηση χρησιμοποιώντας το σύνολο δεδομένων κυβερνοασφάλειας NSL-KDD. Θα το αντιμετωπίσουμε ως πρόβλημα παλινδρόμησης προβλέποντας τη `διάρκεια` των συνδέσεων δικτύου με βάση άλλα χαρακτηριστικά. (Στην πραγματικότητα, η `διάρκεια` είναι ένα χαρακτηριστικό του NSL-KDD; το χρησιμοποιούμε εδώ απλώς για να απεικονίσουμε την παλινδρόμηση.) Φορτώνουμε το σύνολο δεδομένων, το προεπεξεργαζόμαστε (κωδικοποιούμε κατηγορικά χαρακτηριστικά), εκπαιδεύουμε ένα μοντέλο γραμμικής παλινδρόμησης και αξιολογούμε το Μέσο Τετραγωνικό Σφάλμα (MSE) και τη βαθμολογία R² σε ένα σύνολο δοκιμών.import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
# ── 1. Column names taken from the NSL‑KDD documentation ──────────────
col_names = [
"duration","protocol_type","service","flag","src_bytes","dst_bytes","land",
"wrong_fragment","urgent","hot","num_failed_logins","logged_in",
"num_compromised","root_shell","su_attempted","num_root",
"num_file_creations","num_shells","num_access_files","num_outbound_cmds",
"is_host_login","is_guest_login","count","srv_count","serror_rate",
"srv_serror_rate","rerror_rate","srv_rerror_rate","same_srv_rate",
"diff_srv_rate","srv_diff_host_rate","dst_host_count",
"dst_host_srv_count","dst_host_same_srv_rate","dst_host_diff_srv_rate",
"dst_host_same_src_port_rate","dst_host_srv_diff_host_rate",
"dst_host_serror_rate","dst_host_srv_serror_rate","dst_host_rerror_rate",
"dst_host_srv_rerror_rate","class","difficulty_level"
]
# ── 2. Load data *without* header row ─────────────────────────────────
train_url = "https://raw.githubusercontent.com/Mamcose/NSL-KDD-Network-Intrusion-Detection/master/NSL_KDD_Train.csv"
test_url = "https://raw.githubusercontent.com/Mamcose/NSL-KDD-Network-Intrusion-Detection/master/NSL_KDD_Test.csv"
df_train = pd.read_csv(train_url, header=None, names=col_names)
df_test = pd.read_csv(test_url, header=None, names=col_names)
# ── 3. Encode the 3 nominal features ─────────────────────────────────
for col in ['protocol_type', 'service', 'flag']:
le = LabelEncoder()
le.fit(pd.concat([df_train[col], df_test[col]], axis=0))
df_train[col] = le.transform(df_train[col])
df_test[col] = le.transform(df_test[col])
# ── 4. Prepare features / target ─────────────────────────────────────
X_train = df_train.drop(columns=['class', 'difficulty_level', 'duration'])
y_train = df_train['duration']
X_test = df_test.drop(columns=['class', 'difficulty_level', 'duration'])
y_test = df_test['duration']
# ── 5. Train & evaluate simple Linear Regression ─────────────────────
model = LinearRegression().fit(X_train, y_train)
y_pred = model.predict(X_test)
print(f"Test MSE: {mean_squared_error(y_test, y_pred):.2f}")
print(f"Test R² : {r2_score(y_test, y_pred):.3f}")
"""
Test MSE: 3021333.56
Test R² : -0.526
"""
Σε αυτό το παράδειγμα, το μοντέλο γραμμικής παλινδρόμησης προσπαθεί να προβλέψει τη διάρκεια της σύνδεσης duration
από άλλα χαρακτηριστικά δικτύου. Μετράμε την απόδοση με το Μέσο Τετραγωνικό Σφάλμα (MSE) και το R². Ένα R² κοντά στο 1.0 θα υποδείκνυε ότι το μοντέλο εξηγεί τη μεγαλύτερη διακύμανση στη duration
, ενώ ένα χαμηλό ή αρνητικό R² υποδεικνύει κακή προσαρμογή. (Μην εκπλαγείτε αν το R² είναι χαμηλό εδώ -- η πρόβλεψη της duration
μπορεί να είναι δύσκολη από τα δεδομένα χαρακτηριστικά, και η γραμμική παλινδρόμηση μπορεί να μην αποτυπώνει τα μοτίβα αν είναι περίπλοκα.)
Λογιστική Παλινδρόμηση
Η λογιστική παλινδρόμηση είναι ένας αλγόριθμος ταξινόμησης που μοντελοποιεί την πιθανότητα ότι μια περίπτωση ανήκει σε μια συγκεκριμένη κατηγορία (συνήθως την "θετική" κατηγορία). Παρά το όνομά της, η λογιστική παλινδρόμηση χρησιμοποιείται για διακριτά αποτελέσματα (σε αντίθεση με τη γραμμική παλινδρόμηση που είναι για συνεχόμενα αποτελέσματα). Χρησιμοποιείται ιδιαίτερα για δυαδική ταξινόμηση (δύο κατηγορίες, π.χ., κακόβουλο vs. καλοήθες), αλλά μπορεί να επεκταθεί σε προβλήματα πολλαπλών κατηγοριών (χρησιμοποιώντας προσεγγίσεις softmax ή one-vs-rest).
Η λογιστική παλινδρόμηση χρησιμοποιεί τη λογιστική συνάρτηση (γνωστή και ως συνάρτηση σιγμοειδούς) για να χαρτογραφήσει τις προβλεπόμενες τιμές σε πιθανότητες. Σημειώστε ότι η συνάρτηση σιγμοειδούς είναι μια συνάρτηση με τιμές μεταξύ 0 και 1 που αυξάνεται σε μια καμπύλη σχήματος S σύμφωνα με τις ανάγκες της ταξινόμησης, η οποία είναι χρήσιμη για καθήκοντα δυαδικής ταξινόμησης. Επομένως, κάθε χαρακτηριστικό κάθε εισόδου πολλαπλασιάζεται με το ανατεθέν βάρος του, και το αποτέλεσμα περνάει μέσω της συνάρτησης σιγμοειδούς για να παραγάγει μια πιθανότητα:
p(y=1|x) = 1 / (1 + e^(-z))
Όπου:
p(y=1|x)
είναι η πιθανότητα ότι η έξοδοςy
είναι 1 δεδομένης της εισόδουx
e
είναι η βάση του φυσικού λογαρίθμουz
είναι μια γραμμική συνδυαστική των χαρακτηριστικών εισόδου, συνήθως αναπαριστάται ωςz = w1*x1 + w2*x2 + ... + wn*xn + b
. Σημειώστε πώς και πάλι στην πιο απλή του μορφή είναι μια ευθεία γραμμή, αλλά σε πιο σύνθετες περιπτώσεις γίνεται ένα υπερεπίπεδο με πολλές διαστάσεις (μία ανά χαρακτηριστικό).
tip
Χρήσεις στην κυβερνοασφάλεια: Δεδομένου ότι πολλά προβλήματα ασφάλειας είναι ουσιαστικά αποφάσεις ναι/όχι, η λογιστική παλινδρόμηση χρησιμοποιείται ευρέως. Για παράδειγμα, ένα σύστημα ανίχνευσης εισβολών μπορεί να χρησιμοποιήσει λογιστική παλινδρόμηση για να αποφασίσει αν μια σύνδεση δικτύου είναι επίθεση με βάση τα χαρακτηριστικά αυτής της σύνδεσης. Στην ανίχνευση phishing, η λογιστική παλινδρόμηση μπορεί να συνδυάσει χαρακτηριστικά μιας ιστοσελίδας (μήκος URL, παρουσία του συμβόλου "@", κ.λπ.) σε μια πιθανότητα να είναι phishing. Έχει χρησιμοποιηθεί σε φίλτρα spam πρώτης γενιάς και παραμένει μια ισχυρή βάση για πολλές εργασίες ταξινόμησης.
Λογιστική Παλινδρόμηση για μη δυαδική ταξινόμηση
Η λογιστική παλινδρόμηση έχει σχεδιαστεί για δυαδική ταξινόμηση, αλλά μπορεί να επεκταθεί για να χειριστεί πολυκατηγορικές προβλήματα χρησιμοποιώντας τεχνικές όπως one-vs-rest (OvR) ή softmax regression. Στο OvR, εκπαιδεύεται ένα ξεχωριστό μοντέλο λογιστικής παλινδρόμησης για κάθε κατηγορία, αντιμετωπίζοντάς την ως την θετική κατηγορία έναντι όλων των άλλων. Η κατηγορία με την υψηλότερη προβλεπόμενη πιθανότητα επιλέγεται ως η τελική πρόβλεψη. Η softmax regression γενικεύει τη λογιστική παλινδρόμηση σε πολλές κατηγορίες εφαρμόζοντας τη συνάρτηση softmax στην έξοδο, παράγοντας μια κατανομή πιθανότητας σε όλες τις κατηγορίες.
Κύρια χαρακτηριστικά της Λογιστικής Παλινδρόμησης:
-
Τύπος Προβλήματος: Ταξινόμηση (συνήθως δυαδική). Προβλέπει την πιθανότητα της θετικής κατηγορίας.
-
Ερμηνευσιμότητα: Υψηλή -- όπως η γραμμική παλινδρόμηση, οι συντελεστές χαρακτηριστικών μπορούν να υποδείξουν πώς κάθε χαρακτηριστικό επηρεάζει τις λογαριθμικές πιθανότητες του αποτελέσματος. Αυτή η διαφάνεια εκτιμάται συχνά στην ασφάλεια για την κατανόηση των παραγόντων που συμβάλλουν σε μια ειδοποίηση.
-
Πλεονεκτήματα: Απλή και γρήγορη στην εκπαίδευση; λειτουργεί καλά όταν η σχέση μεταξύ των χαρακτηριστικών και των λογαριθμικών πιθανοτήτων του αποτελέσματος είναι γραμμική. Παράγει πιθανότητες, επιτρέποντας την αξιολόγηση κινδύνου. Με κατάλληλη κανονικοποίηση, γενικεύει καλά και μπορεί να χειριστεί την πολυκολληλότητα καλύτερα από την απλή γραμμική παλινδρόμηση.
-
Περιορισμοί: Υποθέτει μια γραμμική απόφαση στα όρια του χώρου χαρακτηριστικών (αποτυγχάνει αν το πραγματικό όριο είναι σύνθετο/μη γραμμικό). Μπορεί να αποδώσει λιγότερο σε προβλήματα όπου οι αλληλεπιδράσεις ή οι μη γραμμικές επιδράσεις είναι κρίσιμες, εκτός αν προσθέσετε χειροκίνητα πολυωνυμικά ή αλληλεπιδραστικά χαρακτηριστικά. Επίσης, η λογιστική παλινδρόμηση είναι λιγότερο αποτελεσματική αν οι κατηγορίες δεν είναι εύκολα διαχωρίσιμες από μια γραμμική συνδυαστική χαρακτηριστικών.
Παράδειγμα -- Ανίχνευση Ιστοσελίδων Phishing με Λογιστική Παλινδρόμηση:
Θα χρησιμοποιήσουμε ένα Σύνολο Δεδομένων Ιστοσελίδων Phishing (από το αποθετήριο UCI) το οποίο περιέχει εξαγόμενα χαρακτηριστικά ιστοσελίδων (όπως αν το URL έχει διεύθυνση IP, την ηλικία του τομέα, παρουσία ύποπτων στοιχείων στο HTML, κ.λπ.) και μια ετικέτα που υποδεικνύει αν η ιστοσελίδα είναι phishing ή νόμιμη. Εκπαιδεύουμε ένα μοντέλο λογιστικής παλινδρόμησης για να ταξινομήσουμε ιστοσελίδες και στη συνέχεια αξιολογούμε την ακρίβεια, την ακρίβεια, την ανάκληση, το F1-score και το ROC AUC σε ένα δοκιμαστικό σύνολο.
import pandas as pd
from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score
# 1. Load dataset
data = fetch_openml(data_id=4534, as_frame=True) # PhishingWebsites
df = data.frame
print(df.head())
# 2. Target mapping ─ legitimate (1) → 0, everything else → 1
df['Result'] = df['Result'].astype(int)
y = (df['Result'] != 1).astype(int)
# 3. Features
X = df.drop(columns=['Result'])
# 4. Train/test split with stratify
## Stratify ensures balanced classes in train/test sets
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.20, random_state=42, stratify=y)
# 5. Scale
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
# 6. Logistic Regression
## L‑BFGS is a modern, memory‑efficient “quasi‑Newton” algorithm that works well for medium/large datasets and supports multiclass natively.
## Upper bound on how many optimization steps the solver may take before it gives up. Not all steps are guaranteed to be taken, but would be the maximum before a "failed to converge" error.
clf = LogisticRegression(max_iter=1000, solver='lbfgs', random_state=42)
clf.fit(X_train, y_train)
# 7. Evaluation
y_pred = clf.predict(X_test)
y_prob = clf.predict_proba(X_test)[:, 1]
print(f"Accuracy : {accuracy_score(y_test, y_pred):.3f}")
print(f"Precision: {precision_score(y_test, y_pred):.3f}")
print(f"Recall : {recall_score(y_test, y_pred):.3f}")
print(f"F1-score : {f1_score(y_test, y_pred):.3f}")
print(f"ROC AUC : {roc_auc_score(y_test, y_prob):.3f}")
"""
Accuracy : 0.928
Precision: 0.934
Recall : 0.901
F1-score : 0.917
ROC AUC : 0.979
"""
Σε αυτό το παράδειγμα ανίχνευσης phishing, η λογιστική παλινδρόμηση παράγει μια πιθανότητα για κάθε ιστότοπο να είναι phishing. Αξιολογώντας την ακρίβεια, την ακρίβεια, την ανάκληση και το F1, αποκτούμε μια αίσθηση της απόδοσης του μοντέλου. Για παράδειγμα, μια υψηλή ανάκληση θα σήμαινε ότι πιάνει τους περισσότερους ιστότοπους phishing (σημαντικό για την ασφάλεια για να ελαχιστοποιηθούν οι χαμένες επιθέσεις), ενώ η υψηλή ακρίβεια σημαίνει ότι έχει λίγες ψευδείς συναγερμούς (σημαντικό για να αποφευχθεί η κόπωση των αναλυτών). Ο ROC AUC (Area Under the ROC Curve) παρέχει ένα μέτρο απόδοσης ανεξάρτητο από το κατώφλι (1.0 είναι ιδανικό, 0.5 δεν είναι καλύτερο από την τύχη). Η λογιστική παλινδρόμηση συχνά αποδίδει καλά σε τέτοιες εργασίες, αλλά αν το όριο απόφασης μεταξύ phishing και νόμιμων ιστότοπων είναι περίπλοκο, μπορεί να χρειαστούν πιο ισχυρά μη γραμμικά μοντέλα.
Δέντρα Απόφασης
Ένα δέντρο απόφασης είναι ένας ευέλικτος αλγόριθμος επιβλεπόμενης μάθησης που μπορεί να χρησιμοποιηθεί τόσο για ταξινόμηση όσο και για παλινδρόμηση. Μαθαίνει ένα ιεραρχικό μοντέλο δέντρου αποφάσεων βασισμένο στα χαρακτηριστικά των δεδομένων. Κάθε εσωτερικός κόμβος του δέντρου αντιπροσωπεύει μια δοκιμή σε ένα συγκεκριμένο χαρακτηριστικό, κάθε κλάδος αντιπροσωπεύει ένα αποτέλεσμα αυτής της δοκιμής και κάθε φύλλο αντιπροσωπεύει μια προβλεπόμενη κατηγορία (για ταξινόμηση) ή τιμή (για παλινδρόμηση).
Για να κατασκευάσουν ένα δέντρο, αλγόριθμοι όπως το CART (Classification and Regression Tree) χρησιμοποιούν μέτρα όπως η ακαθαρσία Gini ή το κέρδος πληροφορίας (εντροπία) για να επιλέξουν το καλύτερο χαρακτηριστικό και κατώφλι για να χωρίσουν τα δεδομένα σε κάθε βήμα. Ο στόχος σε κάθε διαχωρισμό είναι να κατανεμηθούν τα δεδομένα ώστε να αυξηθεί η ομοιογένεια της στοχευμένης μεταβλητής στα προκύπτοντα υποσύνολα (για ταξινόμηση, κάθε κόμβος στοχεύει να είναι όσο το δυνατόν πιο καθαρός, περιέχοντας κυρίως μια μόνο κατηγορία).
Τα δέντρα απόφασης είναι πολύ ερμηνεύσιμα -- μπορεί κανείς να ακολουθήσει την πορεία από τη ρίζα στο φύλλο για να κατανοήσει τη λογική πίσω από μια πρόβλεψη (π.χ., "ΑΝ service = telnet
ΚΑΙ src_bytes > 1000
ΚΑΙ failed_logins > 3
ΤΟΤΕ ταξινόμησε ως επίθεση"). Αυτό είναι πολύτιμο στην κυβερνοασφάλεια για να εξηγήσει γιατί ανυψώθηκε μια συγκεκριμένη ειδοποίηση. Τα δέντρα μπορούν φυσικά να χειριστούν τόσο αριθμητικά όσο και κατηγορικά δεδομένα και απαιτούν λίγη προεπεξεργασία (π.χ., η κλιμάκωση χαρακτηριστικών δεν είναι απαραίτητη).
Ωστόσο, ένα μόνο δέντρο απόφασης μπορεί εύκολα να υπερπροσαρμοστεί στα δεδομένα εκπαίδευσης, ειδικά αν αναπτυχθεί βαθιά (πολλοί διαχωρισμοί). Τεχνικές όπως η κλάδεμα (περιορισμός του βάθους του δέντρου ή απαίτηση ελάχιστου αριθμού δειγμάτων ανά φύλλο) χρησιμοποιούνται συχνά για να αποτραπεί η υπερπροσαρμογή.
Υπάρχουν 3 κύρια στοιχεία ενός δέντρου απόφασης:
- Κόμβος Ρίζας: Ο κορυφαίος κόμβος του δέντρου, που αντιπροσωπεύει το σύνολο των δεδομένων.
- Εσωτερικοί Κόμβοι: Κόμβοι που αντιπροσωπεύουν χαρακτηριστικά και αποφάσεις βασισμένες σε αυτά τα χαρακτηριστικά.
- Φύλλα: Κόμβοι που αντιπροσωπεύουν το τελικό αποτέλεσμα ή πρόβλεψη.
Ένα δέντρο μπορεί να καταλήξει να φαίνεται έτσι:
[Root Node]
/ \
[Node A] [Node B]
/ \ / \
[Leaf 1] [Leaf 2] [Leaf 3] [Leaf 4]
tip
Χρήσεις στην κυβερνοασφάλεια: Τα δέντρα απόφασης έχουν χρησιμοποιηθεί σε συστήματα ανίχνευσης εισβολών για την εξαγωγή κανόνων για την αναγνώριση επιθέσεων. Για παράδειγμα, πρώιμα IDS όπως τα συστήματα βασισμένα σε ID3/C4.5 θα δημιουργούσαν κανόνες αναγνώσιμους από ανθρώπους για να διακρίνουν την κανονική από την κακόβουλη κίνηση. Χρησιμοποιούνται επίσης στην ανάλυση κακόβουλου λογισμικού για να αποφασίσουν αν ένα αρχείο είναι κακόβουλο με βάση τα χαρακτηριστικά του (μέγεθος αρχείου, εντροπία τμήματος, κλήσεις API, κ.λπ.). Η σαφήνεια των δέντρων απόφασης τα καθιστά χρήσιμα όταν απαιτείται διαφάνεια -- ένας αναλυτής μπορεί να επιθεωρήσει το δέντρο για να επικυρώσει τη λογική ανίχνευσης.
Βασικά χαρακτηριστικά των Δέντρων Απόφασης:
-
Τύπος Προβλήματος: Και ταξινόμηση και παλινδρόμηση. Χρησιμοποιούνται συνήθως για την ταξινόμηση επιθέσεων έναντι κανονικής κίνησης, κ.λπ.
-
Ερμηνευσιμότητα: Πολύ υψηλή -- οι αποφάσεις του μοντέλου μπορούν να οπτικοποιηθούν και να κατανοηθούν ως ένα σύνολο κανόνων αν-τότε. Αυτό είναι ένα σημαντικό πλεονέκτημα στην ασφάλεια για την εμπιστοσύνη και την επαλήθευση της συμπεριφοράς του μοντέλου.
-
Πλεονεκτήματα: Μπορούν να συλλάβουν μη γραμμικές σχέσεις και αλληλεπιδράσεις μεταξύ χαρακτηριστικών (κάθε διαχωρισμός μπορεί να θεωρηθεί ως αλληλεπίδραση). Δεν χρειάζεται να κλιμακώσετε τα χαρακτηριστικά ή να κωδικοποιήσετε κατηγορικές μεταβλητές -- τα δέντρα τα χειρίζονται εγγενώς. Γρήγορη συμπερασματολογία (η πρόβλεψη είναι απλώς η ακολουθία ενός μονοπατιού στο δέντρο).
-
Περιορισμοί: Επιρρεπή σε υπερπροσαρμογή αν δεν ελέγχονται (ένα βαθύ δέντρο μπορεί να απομνημονεύσει το σύνολο εκπαίδευσης). Μπορεί να είναι ασταθή -- μικρές αλλαγές στα δεδομένα μπορεί να οδηγήσουν σε διαφορετική δομή δέντρου. Ως μεμονωμένα μοντέλα, η ακρίβειά τους μπορεί να μην ταιριάζει με πιο προηγμένες μεθόδους (συνδυασμοί όπως τα Τυχαία Δάση συνήθως αποδίδουν καλύτερα μειώνοντας την παραλλαγή).
-
Εύρεση του Καλύτερου Διαχωρισμού:
-
Ακαθαρσία Gini: Μετρά την ακαθαρσία ενός κόμβου. Μια χαμηλότερη ακαθαρσία Gini υποδεικνύει έναν καλύτερο διαχωρισμό. Ο τύπος είναι:
Gini = 1 - Σ(p_i^2)
Όπου p_i
είναι το ποσοστό των περιπτώσεων στην κατηγορία i
.
- Εντροπία: Μετρά την αβεβαιότητα στο σύνολο δεδομένων. Μια χαμηλότερη εντροπία υποδεικνύει έναν καλύτερο διαχωρισμό. Ο τύπος είναι:
Entropy = -Σ(p_i * log2(p_i))
Όπου p_i
είναι το ποσοστό των περιπτώσεων στην κατηγορία i
.
- Κέρδος Πληροφορίας: Η μείωση της εντροπίας ή της ακαθαρσίας Gini μετά από έναν διαχωρισμό. Όσο υψηλότερο είναι το κέρδος πληροφορίας, τόσο καλύτερος είναι ο διαχωρισμός. Υπολογίζεται ως:
Information Gain = Entropy(parent) - (Weighted Average of Entropy(children))
Επιπλέον, ένα δέντρο τελειώνει όταν:
- Όλες οι περιπτώσεις σε έναν κόμβο ανήκουν στην ίδια κατηγορία. Αυτό μπορεί να οδηγήσει σε υπερπροσαρμογή.
- Έχει επιτευχθεί το μέγιστο βάθος (σκληρά κωδικοποιημένο) του δέντρου. Αυτό είναι ένας τρόπος για να αποτραπεί η υπερπροσαρμογή.
- Ο αριθμός των περιπτώσεων σε έναν κόμβο είναι κάτω από ένα συγκεκριμένο κατώφλι. Αυτό είναι επίσης ένας τρόπος για να αποτραπεί η υπερπροσαρμογή.
- Το κέρδος πληροφορίας από περαιτέρω διαχωρισμούς είναι κάτω από ένα συγκεκριμένο κατώφλι. Αυτό είναι επίσης ένας τρόπος για να αποτραπεί η υπερπροσαρμογή.
Παράδειγμα -- Δέντρο Απόφασης για Ανίχνευση Εισβολών:
Θα εκπαιδεύσουμε ένα δέντρο απόφασης στο σύνολο δεδομένων NSL-KDD για να ταξινομήσουμε τις συνδέσεις δικτύου ως *κανονικές* ή *επίθεση*. Το NSL-KDD είναι μια βελτιωμένη έκδοση του κλασικού συνόλου δεδομένων KDD Cup 1999, με χαρακτηριστικά όπως τύπος πρωτοκόλλου, υπηρεσία, διάρκεια, αριθμός αποτυχημένων συνδέσεων, κ.λπ., και μια ετικέτα που υποδεικνύει τον τύπο επίθεσης ή "κανονικό". Θα αντιστοιχίσουμε όλους τους τύπους επιθέσεων σε μια κατηγορία "ανωμαλία" (δυαδική ταξινόμηση: κανονικό έναντι ανωμαλίας). Μετά την εκπαίδευση, θα αξιολογήσουμε την απόδοση του δέντρου στο σύνολο δοκιμής.import pandas as pd
from sklearn.tree import DecisionTreeClassifier
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score
# 1️⃣ NSL‑KDD column names (41 features + class + difficulty)
col_names = [
"duration","protocol_type","service","flag","src_bytes","dst_bytes","land",
"wrong_fragment","urgent","hot","num_failed_logins","logged_in","num_compromised",
"root_shell","su_attempted","num_root","num_file_creations","num_shells",
"num_access_files","num_outbound_cmds","is_host_login","is_guest_login","count",
"srv_count","serror_rate","srv_serror_rate","rerror_rate","srv_rerror_rate",
"same_srv_rate","diff_srv_rate","srv_diff_host_rate","dst_host_count",
"dst_host_srv_count","dst_host_same_srv_rate","dst_host_diff_srv_rate",
"dst_host_same_src_port_rate","dst_host_srv_diff_host_rate","dst_host_serror_rate",
"dst_host_srv_serror_rate","dst_host_rerror_rate","dst_host_srv_rerror_rate",
"class","difficulty_level"
]
# 2️⃣ Load data ➜ *headerless* CSV
train_url = "https://raw.githubusercontent.com/Mamcose/NSL-KDD-Network-Intrusion-Detection/master/NSL_KDD_Train.csv"
test_url = "https://raw.githubusercontent.com/Mamcose/NSL-KDD-Network-Intrusion-Detection/master/NSL_KDD_Test.csv"
df_train = pd.read_csv(train_url, header=None, names=col_names)
df_test = pd.read_csv(test_url, header=None, names=col_names)
# 3️⃣ Encode the 3 nominal features
for col in ['protocol_type', 'service', 'flag']:
le = LabelEncoder().fit(pd.concat([df_train[col], df_test[col]]))
df_train[col] = le.transform(df_train[col])
df_test[col] = le.transform(df_test[col])
# 4️⃣ Prepare X / y (binary: 0 = normal, 1 = attack)
X_train = df_train.drop(columns=['class', 'difficulty_level'])
y_train = (df_train['class'].str.lower() != 'normal').astype(int)
X_test = df_test.drop(columns=['class', 'difficulty_level'])
y_test = (df_test['class'].str.lower() != 'normal').astype(int)
# 5️⃣ Train Decision‑Tree
clf = DecisionTreeClassifier(max_depth=10, random_state=42)
clf.fit(X_train, y_train)
# 6️⃣ Evaluate
y_pred = clf.predict(X_test)
y_prob = clf.predict_proba(X_test)[:, 1]
print(f"Accuracy : {accuracy_score(y_test, y_pred):.3f}")
print(f"Precision: {precision_score(y_test, y_pred):.3f}")
print(f"Recall : {recall_score(y_test, y_pred):.3f}")
print(f"F1‑score : {f1_score(y_test, y_pred):.3f}")
print(f"ROC AUC : {roc_auc_score(y_test, y_prob):.3f}")
"""
Accuracy : 0.772
Precision: 0.967
Recall : 0.621
F1‑score : 0.756
ROC AUC : 0.758
"""
Σε αυτό το παράδειγμα δέντρου απόφασης, περιορίσαμε το βάθος του δέντρου σε 10 για να αποφύγουμε την ακραία υπερπροσαρμογή (η παράμετρος max_depth=10
). Οι μετρικές δείχνουν πόσο καλά το δέντρο διακρίνει την κανονική από την επιθετική κίνηση. Ένας υψηλός ανακλητικός δείκτης θα σήμαινε ότι πιάνει τις περισσότερες επιθέσεις (σημαντικό για ένα IDS), ενώ η υψηλή ακρίβεια σημαίνει λίγες ψευδείς συναγερμούς. Τα δέντρα απόφασης συχνά επιτυγχάνουν ικανοποιητική ακρίβεια σε δομημένα δεδομένα, αλλά ένα μόνο δέντρο μπορεί να μην φτάσει την καλύτερη δυνατή απόδοση. Παρ' όλα αυτά, η ερμηνευσιμότητα του μοντέλου είναι ένα μεγάλο πλεονέκτημα -- θα μπορούσαμε να εξετάσουμε τις διακλαδώσεις του δέντρου για να δούμε, για παράδειγμα, ποιες χαρακτηριστικές (π.χ., service
, src_bytes
, κ.λπ.) είναι οι πιο επιδραστικές στην επισήμανση μιας σύνδεσης ως κακόβουλης.
Τυχαία Δάση
Το Τυχαίο Δάσος είναι μια μέθοδος συγκεντρωτικής μάθησης που βασίζεται σε δέντρα απόφασης για να βελτιώσει την απόδοση. Ένα τυχαίο δάσος εκπαιδεύει πολλαπλά δέντρα απόφασης (γι' αυτό και "δάσος") και συνδυάζει τις εξόδους τους για να κάνει μια τελική πρόβλεψη (για ταξινόμηση, συνήθως με πλειοψηφική ψήφο). Οι δύο κύριες ιδέες σε ένα τυχαίο δάσος είναι η bagging (bootstrap aggregating) και η τυχαία χαρακτηριστικά:
-
Bagging: Κάθε δέντρο εκπαιδεύεται σε ένα τυχαίο δείγμα bootstrap των εκπαιδευτικών δεδομένων (δειγματοληπτικά με αντικατάσταση). Αυτό εισάγει ποικιλία μεταξύ των δέντρων.
-
Τυχαία Χαρακτηριστικά: Σε κάθε διακλάδωση ενός δέντρου, εξετάζεται ένα τυχαίο υποσύνολο χαρακτηριστικών για τη διακλάδωση (αντί για όλα τα χαρακτηριστικά). Αυτό αποδιασυνδέει περαιτέρω τα δέντρα.
Με την μέση τιμή των αποτελεσμάτων πολλών δέντρων, το τυχαίο δάσος μειώνει την παραλλαγή που μπορεί να έχει ένα μόνο δέντρο απόφασης. Με απλά λόγια, τα μεμονωμένα δέντρα μπορεί να υπερπροσαρμόζονται ή να είναι θορυβώδη, αλλά ένας μεγάλος αριθμός ποικίλων δέντρων που ψηφίζουν μαζί εξομαλύνει αυτά τα σφάλματα. Το αποτέλεσμα είναι συχνά ένα μοντέλο με υψηλότερη ακρίβεια και καλύτερη γενίκευση από ένα μόνο δέντρο απόφασης. Επιπλέον, τα τυχαία δάση μπορούν να παρέχουν μια εκτίμηση της σημασίας των χαρακτηριστικών (εξετάζοντας πόσο κάθε χαρακτηριστικό μειώνει την ακαθαρσία κατά μέσο όρο).
Τα τυχαία δάση έχουν γίνει ένα εργαλείο στον τομέα της κυβερνοασφάλειας για εργασίες όπως η ανίχνευση εισβολών, η ταξινόμηση κακόβουλου λογισμικού και η ανίχνευση spam. Συχνά αποδίδουν καλά από το κουτί με ελάχιστη ρύθμιση και μπορούν να χειριστούν μεγάλες ομάδες χαρακτηριστικών. Για παράδειγμα, στην ανίχνευση εισβολών, ένα τυχαίο δάσος μπορεί να υπερβεί ένα μεμονωμένο δέντρο απόφασης πιάνοντας πιο λεπτές προτύπες επιθέσεων με λιγότερους ψευδείς θετικούς. Έρευνες έχουν δείξει ότι τα τυχαία δάση αποδίδουν ευνοϊκά σε σύγκριση με άλλους αλγόριθμους στην ταξινόμηση επιθέσεων σε σύνολα δεδομένων όπως το NSL-KDD και το UNSW-NB15.
Κύριες χαρακτηριστικές του Τυχαίου Δάσους:
-
Τύπος Προβλήματος: Κυρίως ταξινόμηση (χρησιμοποιείται επίσης για παλινδρόμηση). Πολύ κατάλληλο για υψηλής διάστασης δομημένα δεδομένα που είναι κοινά σε αρχεία καταγραφής ασφαλείας.
-
Ερμηνευσιμότητα: Χαμηλότερη από ένα μόνο δέντρο απόφασης -- δεν μπορείτε εύκολα να οπτικοποιήσετε ή να εξηγήσετε εκατοντάδες δέντρα ταυτόχρονα. Ωστόσο, οι βαθμολογίες σημασίας χαρακτηριστικών παρέχουν κάποια εικόνα για το ποια χαρακτηριστικά είναι τα πιο επιδραστικά.
-
Πλεονεκτήματα: Γενικά υψηλότερη ακρίβεια από τα μοντέλα ενός δέντρου λόγω του συγκεντρωτικού αποτελέσματος. Ανθεκτικό στην υπερπροσαρμογή -- ακόμη και αν τα μεμονωμένα δέντρα υπερπροσαρμόζονται, το σύνολο γενικεύει καλύτερα. Χειρίζεται τόσο αριθμητικά όσο και κατηγορικά χαρακτηριστικά και μπορεί να διαχειριστεί ελλιπή δεδομένα σε κάποιο βαθμό. Είναι επίσης σχετικά ανθεκτικό σε εξωτικά δεδομένα.
-
Περιορισμοί: Το μέγεθος του μοντέλου μπορεί να είναι μεγάλο (πολλά δέντρα, το καθένα δυνητικά βαθύ). Οι προβλέψεις είναι πιο αργές από ένα μόνο δέντρο (καθώς πρέπει να συγκεντρώσετε πάνω από πολλά δέντρα). Λιγότερο ερμηνεύσιμο -- ενώ γνωρίζετε τα σημαντικά χαρακτηριστικά, η ακριβής λογική δεν είναι εύκολα ανιχνεύσιμη ως απλός κανόνας. Εάν το σύνολο δεδομένων είναι εξαιρετικά υψηλής διάστασης και αραιό, η εκπαίδευση ενός πολύ μεγάλου δάσους μπορεί να είναι υπολογιστικά βαριά.
-
Διαδικασία Εκπαίδευσης:
- Bootstrap Sampling: Τυχαία δειγματοληψία των εκπαιδευτικών δεδομένων με αντικατάσταση για να δημιουργηθούν πολλαπλά υποσύνολα (δείγματα bootstrap).
- Κατασκευή Δέντρου: Για κάθε δείγμα bootstrap, κατασκευάστε ένα δέντρο απόφασης χρησιμοποιώντας ένα τυχαίο υποσύνολο χαρακτηριστικών σε κάθε διακλάδωση. Αυτό εισάγει ποικιλία μεταξύ των δέντρων.
- Συγκέντρωση: Για εργασίες ταξινόμησης, η τελική πρόβλεψη γίνεται με την πλειοψηφική ψήφο μεταξύ των προβλέψεων όλων των δέντρων. Για εργασίες παλινδρόμησης, η τελική πρόβλεψη είναι ο μέσος όρος των προβλέψεων από όλα τα δέντρα.
Παράδειγμα -- Τυχαίο Δάσος για Ανίχνευση Εισβολών (NSL-KDD):
Θα χρησιμοποιήσουμε το ίδιο σύνολο δεδομένων NSL-KDD (δυαδικά επισημασμένο ως κανονικό έναντι ανωμαλίας) και θα εκπαιδεύσουμε έναν ταξινομητή Τυχαίου Δάσους. Αναμένουμε το τυχαίο δάσος να αποδώσει όσο καλά ή καλύτερα από το μεμονωμένο δέντρο απόφασης, χάρη στη μέση τιμή του συγκεντρωτικού που μειώνει την παραλλαγή. Θα το αξιολογήσουμε με τις ίδιες μετρικές.import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import (accuracy_score, precision_score,
recall_score, f1_score, roc_auc_score)
# ──────────────────────────────────────────────
# 1. LOAD DATA ➜ files have **no header row**, so we
# pass `header=None` and give our own column names.
# ──────────────────────────────────────────────
col_names = [ # 41 features + 2 targets
"duration","protocol_type","service","flag","src_bytes","dst_bytes","land",
"wrong_fragment","urgent","hot","num_failed_logins","logged_in",
"num_compromised","root_shell","su_attempted","num_root","num_file_creations",
"num_shells","num_access_files","num_outbound_cmds","is_host_login",
"is_guest_login","count","srv_count","serror_rate","srv_serror_rate",
"rerror_rate","srv_rerror_rate","same_srv_rate","diff_srv_rate",
"srv_diff_host_rate","dst_host_count","dst_host_srv_count",
"dst_host_same_srv_rate","dst_host_diff_srv_rate",
"dst_host_same_src_port_rate","dst_host_srv_diff_host_rate",
"dst_host_serror_rate","dst_host_srv_serror_rate","dst_host_rerror_rate",
"dst_host_srv_rerror_rate","class","difficulty_level"
]
train_url = "https://raw.githubusercontent.com/Mamcose/NSL-KDD-Network-Intrusion-Detection/master/NSL_KDD_Train.csv"
test_url = "https://raw.githubusercontent.com/Mamcose/NSL-KDD-Network-Intrusion-Detection/master/NSL_KDD_Test.csv"
df_train = pd.read_csv(train_url, header=None, names=col_names)
df_test = pd.read_csv(test_url, header=None, names=col_names)
# ──────────────────────────────────────────────
# 2. PRE‑PROCESSING
# ──────────────────────────────────────────────
# 2‑a) Encode the three categorical columns so that the model
# receives integers instead of strings.
# LabelEncoder gives an int to each unique value in the column: {'icmp':0, 'tcp':1, 'udp':2}
for col in ['protocol_type', 'service', 'flag']:
le = LabelEncoder().fit(pd.concat([df_train[col], df_test[col]]))
df_train[col] = le.transform(df_train[col])
df_test[col] = le.transform(df_test[col])
# 2‑b) Build feature matrix X (drop target & difficulty)
X_train = df_train.drop(columns=['class', 'difficulty_level'])
X_test = df_test.drop(columns=['class', 'difficulty_level'])
# 2‑c) Convert multi‑class labels to binary
# label 0 → 'normal' traffic, label 1 → any attack
y_train = (df_train['class'].str.lower() != 'normal').astype(int)
y_test = (df_test['class'].str.lower() != 'normal').astype(int)
# ──────────────────────────────────────────────
# 3. MODEL: RANDOM FOREST
# ──────────────────────────────────────────────
# • n_estimators = 100 ➜ build 100 different decision‑trees.
# • max_depth=None ➜ let each tree grow until pure leaves
# (or until it hits other stopping criteria).
# • random_state=42 ➜ reproducible randomness.
model = RandomForestClassifier(
n_estimators=100,
max_depth=None,
random_state=42,
bootstrap=True # default: each tree is trained on a
# bootstrap sample the same size as
# the original training set.
# max_samples # ← you can set this (float or int) to
# use a smaller % of samples per tree.
)
model.fit(X_train, y_train)
# ──────────────────────────────────────────────
# 4. EVALUATION
# ──────────────────────────────────────────────
y_pred = model.predict(X_test)
y_prob = model.predict_proba(X_test)[:, 1]
print(f"Accuracy : {accuracy_score(y_test, y_pred):.3f}")
print(f"Precision: {precision_score(y_test, y_pred):.3f}")
print(f"Recall : {recall_score(y_test, y_pred):.3f}")
print(f"F1‑score : {f1_score(y_test, y_pred):.3f}")
print(f"ROC AUC : {roc_auc_score(y_test, y_prob):.3f}")
"""
Accuracy: 0.770
Precision: 0.966
Recall: 0.618
F1-score: 0.754
ROC AUC: 0.962
"""
Το τυχαίο δάσος συνήθως επιτυγχάνει ισχυρά αποτελέσματα σε αυτήν την εργασία ανίχνευσης εισβολών. Μπορεί να παρατηρήσουμε μια βελτίωση σε μετρικές όπως το F1 ή το AUC σε σύγκριση με το ενιαίο δέντρο απόφασης, ειδικά στην ανάκληση ή την ακρίβεια, ανάλογα με τα δεδομένα. Αυτό ευθυγραμμίζεται με την κατανόηση ότι "Το Τυχαίο Δάσος (RF) είναι ένας συνδυαστικός ταξινομητής και αποδίδει καλά σε σύγκριση με άλλους παραδοσιακούς ταξινομητές για την αποτελεσματική ταξινόμηση επιθέσεων.". Σε ένα πλαίσιο επιχειρήσεων ασφαλείας, ένα μοντέλο τυχαίου δάσους μπορεί να επισημαίνει πιο αξιόπιστα επιθέσεις ενώ μειώνει τις ψευδείς συναγερμούς, χάρη στη μέση τιμή πολλών κανόνων απόφασης. Η σημασία χαρακτηριστικών από το δάσος θα μπορούσε να μας πει ποια χαρακτηριστικά δικτύου είναι πιο ενδεικτικά επιθέσεων (π.χ., ορισμένες υπηρεσίες δικτύου ή ασυνήθιστοι αριθμοί πακέτων).
Support Vector Machines (SVM)
Οι Support Vector Machines είναι ισχυρά μοντέλα επιβλεπόμενης μάθησης που χρησιμοποιούνται κυρίως για ταξινόμηση (και επίσης για παλινδρόμηση ως SVR). Ένα SVM προσπαθεί να βρει το βέλτιστο διαχωριστικό υπερεπίπεδο που μεγιστοποιεί το περιθώριο μεταξύ δύο κατηγοριών. Μόνο ένα υποσύνολο σημείων εκπαίδευσης (οι "υποστηρικτικοί διανύσματα" που είναι πιο κοντά στο όριο) καθορίζει τη θέση αυτού του υπερεπίπεδου. Με την μεγιστοποίηση του περιθωρίου (απόσταση μεταξύ υποστηρικτικών διανυσμάτων και του υπερεπίπεδου), τα SVM τείνουν να επιτυγχάνουν καλή γενίκευση.
Κλειδί για τη δύναμη του SVM είναι η ικανότητα χρήσης συναρτήσεων πυρήνα για την αντιμετώπιση μη γραμμικών σχέσεων. Τα δεδομένα μπορούν να μετατραπούν έμμεσα σε έναν χώρο χαρακτηριστικών υψηλότερης διάστασης όπου μπορεί να υπάρχει ένας γραμμικός διαχωριστής. Κοινές συναρτήσεις πυρήνα περιλαμβάνουν πολυωνυμικές, συναρτήσεις ραδίου βάσης (RBF) και σιγμοειδείς. Για παράδειγμα, αν οι κατηγορίες δικτυακής κίνησης δεν είναι γραμμικά διαχωρίσιμες στον αρχικό χώρο χαρακτηριστικών, ένας πυρήνας RBF μπορεί να τις χαρτογραφήσει σε μια υψηλότερη διάσταση όπου το SVM βρίσκει μια γραμμική διαίρεση (η οποία αντιστοιχεί σε ένα μη γραμμικό όριο στον αρχικό χώρο). Η ευελιξία επιλογής πυρήνων επιτρέπει στα SVM να αντιμετωπίζουν μια ποικιλία προβλημάτων.
Τα SVM είναι γνωστά ότι αποδίδουν καλά σε καταστάσεις με χώρους χαρακτηριστικών υψηλής διάστασης (όπως δεδομένα κειμένου ή ακολουθίες opcode κακόβουλου λογισμικού) και σε περιπτώσεις όπου ο αριθμός των χαρακτηριστικών είναι μεγάλος σε σχέση με τον αριθμό των δειγμάτων. Ήταν δημοφιλή σε πολλές πρώιμες εφαρμογές κυβερνοασφάλειας όπως η ταξινόμηση κακόβουλου λογισμικού και η ανίχνευση εισβολών βάσει ανωμαλιών τη δεκαετία του 2000, συχνά δείχνοντας υψηλή ακρίβεια.
Ωστόσο, τα SVM δεν κλιμακώνονται εύκολα σε πολύ μεγάλες βάσεις δεδομένων (η πολυπλοκότητα εκπαίδευσης είναι υπερ-γραμμική ως προς τον αριθμό των δειγμάτων, και η χρήση μνήμης μπορεί να είναι υψηλή καθώς μπορεί να χρειαστεί να αποθηκεύσει πολλά υποστηρικτικά διανύσματα). Στην πράξη, για εργασίες όπως η ανίχνευση εισβολών δικτύου με εκατομμύρια εγγραφές, το SVM μπορεί να είναι πολύ αργό χωρίς προσεκτική υποδειγματοληψία ή χρήση προσεγγιστικών μεθόδων.
Κύρια χαρακτηριστικά του SVM:
-
Τύπος Προβλήματος: Ταξινόμηση (δυαδική ή πολυκατηγορία μέσω one-vs-one/one-vs-rest) και παραλλαγές παλινδρόμησης. Συχνά χρησιμοποιείται σε δυαδική ταξινόμηση με σαφή διαχωρισμό περιθωρίου.
-
Ερμηνευσιμότητα: Μέτρια -- Τα SVM δεν είναι τόσο ερμηνεύσιμα όσο τα δέντρα απόφασης ή η λογιστική παλινδρόμηση. Ενώ μπορείτε να προσδιορίσετε ποια σημεία δεδομένων είναι υποστηρικτικά διανύσματα και να αποκτήσετε κάποια αίσθηση για το ποια χαρακτηριστικά μπορεί να είναι επιδραστικά (μέσω των βαρών στην περίπτωση γραμμικού πυρήνα), στην πράξη τα SVM (ιδιαίτερα με μη γραμμικούς πυρήνες) θεωρούνται ως ταξινομητές μαύρου κουτιού.
-
Πλεονεκτήματα: Αποτελεσματικά σε χώρους υψηλής διάστασης; μπορούν να μοντελοποιήσουν πολύπλοκα όρια απόφασης με το κόλπο του πυρήνα; ανθεκτικά στην υπερβολική προσαρμογή αν το περιθώριο είναι μεγιστοποιημένο (ιδιαίτερα με κατάλληλη παράμετρο κανονικοποίησης C); λειτουργούν καλά ακόμη και όταν οι κατηγορίες δεν είναι διαχωρισμένες από μεγάλη απόσταση (βρίσκουν την καλύτερη συμβιβαστική οριακή γραμμή).
-
Περιορισμοί: Υπολογιστικά εντατικά για μεγάλες βάσεις δεδομένων (τόσο η εκπαίδευση όσο και η πρόβλεψη κλιμακώνονται κακώς καθώς τα δεδομένα αυξάνονται). Απαιτεί προσεκτική ρύθμιση παραμέτρων πυρήνα και κανονικοποίησης (C, τύπος πυρήνα, γάμμα για RBF, κ.λπ.). Δεν παρέχει άμεσα πιθανολογικές εξόδους (αν και μπορεί να χρησιμοποιηθεί η κλίμακα Platt για να αποκτηθούν πιθανότητες). Επίσης, τα SVM μπορεί να είναι ευαίσθητα στην επιλογή παραμέτρων πυρήνα --- μια κακή επιλογή μπορεί να οδηγήσει σε υποπροσαρμογή ή υπερπροσαρμογή.
Χρήσεις στην κυβερνοασφάλεια: Τα SVM έχουν χρησιμοποιηθεί στην ανίχνευση κακόβουλου λογισμικού (π.χ., ταξινόμηση αρχείων με βάση εξαγόμενα χαρακτηριστικά ή ακολουθίες opcode), ανίχνευση ανωμαλιών δικτύου (ταξινόμηση της κίνησης ως κανονική ή κακόβουλη), και ανίχνευση phishing (χρησιμοποιώντας χαρακτηριστικά URL). Για παράδειγμα, ένα SVM θα μπορούσε να πάρει χαρακτηριστικά ενός email (αριθμούς ορισμένων λέξεων-κλειδιών, βαθμολογίες φήμης αποστολέα, κ.λπ.) και να το ταξινομήσει ως phishing ή νόμιμο. Έχουν επίσης εφαρμοστεί σε ανίχνευση εισβολών σε σύνολα χαρακτηριστικών όπως το KDD, συχνά επιτυγχάνοντας υψηλή ακρίβεια με κόστος υπολογισμού.
Παράδειγμα -- SVM για Ταξινόμηση Κακόβουλου Λογισμικού:
Θα χρησιμοποιήσουμε ξανά το σύνολο δεδομένων ιστοσελίδων phishing, αυτή τη φορά με ένα SVM. Δεδομένου ότι τα SVM μπορεί να είναι αργά, θα χρησιμοποιήσουμε ένα υποσύνολο των δεδομένων για εκπαίδευση αν χρειαστεί (το σύνολο δεδομένων έχει περίπου 11k περιπτώσεις, τις οποίες το SVM μπορεί να διαχειριστεί λογικά). Θα χρησιμοποιήσουμε έναν πυρήνα RBF, ο οποίος είναι μια κοινή επιλογή για μη γραμμικά δεδομένα, και θα ενεργοποιήσουμε τις εκτιμήσεις πιθανοτήτων για να υπολογίσουμε το ROC AUC.import pandas as pd
from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import (accuracy_score, precision_score,
recall_score, f1_score, roc_auc_score)
# ─────────────────────────────────────────────────────────────
# 1️⃣ LOAD DATASET (OpenML id 4534: “PhishingWebsites”)
# • as_frame=True ➜ returns a pandas DataFrame
# ─────────────────────────────────────────────────────────────
data = fetch_openml(data_id=4534, as_frame=True) # or data_name="PhishingWebsites"
df = data.frame
print(df.head()) # quick sanity‑check
# ─────────────────────────────────────────────────────────────
# 2️⃣ TARGET: 0 = legitimate, 1 = phishing
# The raw column has values {1, 0, -1}:
# 1 → legitimate → 0
# 0 & -1 → phishing → 1
# ─────────────────────────────────────────────────────────────
y = (df["Result"].astype(int) != 1).astype(int)
X = df.drop(columns=["Result"])
# Train / test split (stratified keeps class proportions)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.20, random_state=42, stratify=y)
# ─────────────────────────────────────────────────────────────
# 3️⃣ PRE‑PROCESS: Standardize features (mean‑0 / std‑1)
# ─────────────────────────────────────────────────────────────
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
# ─────────────────────────────────────────────────────────────
# 4️⃣ MODEL: RBF‑kernel SVM
# • C=1.0 (regularization strength)
# • gamma='scale' (1 / [n_features × var(X)])
# • probability=True → enable predict_proba for ROC‑AUC
# ─────────────────────────────────────────────────────────────
clf = SVC(kernel="rbf", C=1.0, gamma="scale",
probability=True, random_state=42)
clf.fit(X_train, y_train)
# ─────────────────────────────────────────────────────────────
# 5️⃣ EVALUATION
# ─────────────────────────────────────────────────────────────
y_pred = clf.predict(X_test)
y_prob = clf.predict_proba(X_test)[:, 1] # P(class 1)
print(f"Accuracy : {accuracy_score(y_test, y_pred):.3f}")
print(f"Precision: {precision_score(y_test, y_pred):.3f}")
print(f"Recall : {recall_score(y_test, y_pred):.3f}")
print(f"F1‑score : {f1_score(y_test, y_pred):.3f}")
print(f"ROC AUC : {roc_auc_score(y_test, y_prob):.3f}")
"""
Accuracy : 0.956
Precision: 0.963
Recall : 0.937
F1‑score : 0.950
ROC AUC : 0.989
"""
Το μοντέλο SVM θα εξάγει μετρικές που μπορούμε να συγκρίνουμε με τη λογιστική παλινδρόμηση στην ίδια εργασία. Μπορεί να διαπιστώσουμε ότι το SVM επιτυγχάνει υψηλή ακρίβεια και AUC αν τα δεδομένα είναι καλά διαχωρισμένα από τα χαρακτηριστικά. Από την άλλη πλευρά, αν το σύνολο δεδομένων είχε πολύ θόρυβο ή επικαλυπτόμενες κλάσεις, το SVM μπορεί να μην υπερέχει σημαντικά της λογιστικής παλινδρόμησης. Στην πράξη, τα SVM μπορούν να δώσουν ώθηση όταν υπάρχουν σύνθετες, μη γραμμικές σχέσεις μεταξύ χαρακτηριστικών και κλάσης -- ο πυρήνας RBF μπορεί να συλλάβει καμπύλες αποφασιστικές γραμμές που θα έχανε η λογιστική παλινδρόμηση. Όπως με όλα τα μοντέλα, απαιτείται προσεκτή ρύθμιση των παραμέτρων C
(κανονικοποίηση) και πυρήνα (όπως gamma
για RBF) για να ισορροπήσουν την προκατάληψη και τη διακύμανση.
Διαφορά Λογιστικών Παλινδρομήσεων & SVM
Πτυχή | Λογιστική Παλινδρόμηση | Μηχανές Υποστήριξης Διανυσμάτων |
---|---|---|
Συνάρτηση στόχου | Ελαχιστοποιεί την log‑loss (διασταυρωμένη εντροπία). | Μεγιστοποιεί το περιθώριο ενώ ελαχιστοποιεί την hinge‑loss. |
Αποφασιστικό όριο | Βρίσκει το καλύτερο προσαρμοσμένο υπερπλάνο που μοντελοποιεί P(y|x). | Βρίσκει το υπερπλάνο μέγιστου περιθωρίου (μεγαλύτερο κενό προς τα κοντινότερα σημεία). |
Έξοδος | Πιθανότητα – δίνει καλιμπραρισμένες πιθανότητες κλάσης μέσω σ(w·x + b). | Καθοριστική – επιστρέφει ετικέτες κλάσης; οι πιθανότητες χρειάζονται επιπλέον εργασία (π.χ. κλιμάκωση Platt). |
Κανονικοποίηση | L2 (προεπιλογή) ή L1, ισορροπεί άμεσα την υπο/υπερ-προσαρμογή. | Η παράμετρος C ισορροπεί το πλάτος του περιθωρίου έναντι των λανθασμένων ταξινομήσεων; οι παράμετροι πυρήνα προσθέτουν πολυπλοκότητα. |
Πυρήνες / Μη γραμμικοί | Η εγγενής μορφή είναι γραμμική; η μη γραμμικότητα προστίθεται μέσω μηχανικής χαρακτηριστικών. | Το ενσωματωμένο trick πυρήνα (RBF, πολυ, κ.λπ.) του επιτρέπει να μοντελοποιεί σύνθετα όρια σε υψηλής διάστασης χώρο. |
Κλιμάκωση | Λύνει μια κυρτή βελτιστοποίηση σε O(nd); χειρίζεται πολύ μεγάλα n καλά. | Η εκπαίδευση μπορεί να είναι O(n²–n³) μνήμης/χρόνου χωρίς εξειδικευμένους λύτες; λιγότερο φιλικό σε τεράστια n. |
Ερμηνευσιμότητα | Υψηλή – τα βάρη δείχνουν την επιρροή των χαρακτηριστικών; ο λόγος πιθανοτήτων είναι διαισθητικός. | Χαμηλή για μη γραμμικούς πυρήνες; οι υποστηρικτικοί διανύσματα είναι σπάνιοι αλλά δεν είναι εύκολο να εξηγηθούν. |
Ευαισθησία σε εξωγενείς τιμές | Χρησιμοποιεί ομαλή log‑loss → λιγότερο ευαίσθητη. | Η hinge‑loss με σκληρό περιθώριο μπορεί να είναι ευαίσθητη; το μαλακό περιθώριο (C) μετριάζει. |
Τυπικές περιπτώσεις χρήσης | Αξιολόγηση πιστοληπτικής ικανότητας, ιατρικός κίνδυνος, A/B testing – όπου μετράνε οι πιθανότητες & η ερμηνευσιμότητα. | Ταξινόμηση εικόνας/κείμενου, βιοπληροφορική – όπου μετράνε τα σύνθετα όρια και τα υψηλής διάστασης δεδομένα. |
- Αν χρειάζεστε καλιμπραρισμένες πιθανότητες, ερμηνευσιμότητα ή λειτουργείτε σε τεράστια σύνολα δεδομένων — επιλέξτε Λογιστική Παλινδρόμηση.
- Αν χρειάζεστε ένα ευέλικτο μοντέλο που μπορεί να συλλάβει μη γραμμικές σχέσεις χωρίς χειροκίνητη μηχανική χαρακτηριστικών — επιλέξτε SVM (με πυρήνες).
- Και τα δύο βελτιστοποιούν κυρτούς στόχους, οπότε οι παγκόσμιες ελάχιστες τιμές είναι εγγυημένες, αλλά οι πυρήνες του SVM προσθέτουν υπερ-παραμέτρους και υπολογιστικό κόστος.
Ναΐβ Μπέις
Ο Ναΐβ Μπέις είναι μια οικογένεια πιθανοτικών ταξινομητών που βασίζεται στην εφαρμογή του Θεωρήματος του Μπέις με μια ισχυρή υπόθεση ανεξαρτησίας μεταξύ των χαρακτηριστικών. Παρά αυτή την "ναΐβ" υπόθεση, ο Ναΐβ Μπέις συχνά λειτουργεί εκπληκτικά καλά για ορισμένες εφαρμογές, ειδικά αυτές που αφορούν κείμενο ή κατηγορικά δεδομένα, όπως η ανίχνευση spam.
Θεώρημα του Μπέις
Το θεώρημα του Μπέις είναι η βάση των ταξινομητών Ναΐβ Μπέις. Σχετίζει τις συνθήκες και τις περιθωριακές πιθανότητες τυχαίων γεγονότων. Ο τύπος είναι:
P(A|B) = (P(B|A) * P(A)) / P(B)
Where:
P(A|B)
είναι η μεταγενέστερη πιθανότητα της κλάσηςA
δεδομένου του χαρακτηριστικούB
.P(B|A)
είναι η πιθανότητα του χαρακτηριστικούB
δεδομένου της κλάσηςA
.P(A)
είναι η προγενέστερη πιθανότητα της κλάσηςA
.P(B)
είναι η προγενέστερη πιθανότητα του χαρακτηριστικούB
.
Για παράδειγμα, αν θέλουμε να ταξινομήσουμε αν ένα κείμενο είναι γραμμένο από ένα παιδί ή έναν ενήλικα, μπορούμε να χρησιμοποιήσουμε τις λέξεις στο κείμενο ως χαρακτηριστικά. Βασισμένος σε κάποια αρχικά δεδομένα, ο ταξινομητής Naive Bayes θα υπολογίσει προηγουμένως τις πιθανότητες κάθε λέξης να ανήκει σε κάθε πιθανή κλάση (παιδί ή ενήλικας). Όταν δοθεί ένα νέο κείμενο, θα υπολογίσει την πιθανότητα κάθε πιθανής κλάσης δεδομένων των λέξεων στο κείμενο και θα επιλέξει την κλάση με την υψηλότερη πιθανότητα.
Όπως μπορείτε να δείτε σε αυτό το παράδειγμα, ο ταξινομητής Naive Bayes είναι πολύ απλός και γρήγορος, αλλά υποθέτει ότι τα χαρακτηριστικά είναι ανεξάρτητα, κάτι που δεν ισχύει πάντα στα πραγματικά δεδομένα.
Τύποι ταξινομητών Naive Bayes
Υπάρχουν αρκετοί τύποι ταξινομητών Naive Bayes, ανάλογα με τον τύπο των δεδομένων και την κατανομή των χαρακτηριστικών:
- Gaussian Naive Bayes: Υποθέτει ότι τα χαρακτηριστικά ακολουθούν μια κανονική (Gaussian) κατανομή. Είναι κατάλληλο για συνεχόμενα δεδομένα.
- Multinomial Naive Bayes: Υποθέτει ότι τα χαρακτηριστικά ακολουθούν μια πολυωνυμική κατανομή. Είναι κατάλληλο για διακριτά δεδομένα, όπως οι μετρήσεις λέξεων στην ταξινόμηση κειμένων.
- Bernoulli Naive Bayes: Υποθέτει ότι τα χαρακτηριστικά είναι δυαδικά (0 ή 1). Είναι κατάλληλο για δυαδικά δεδομένα, όπως η παρουσία ή απουσία λέξεων στην ταξινόμηση κειμένων.
- Categorical Naive Bayes: Υποθέτει ότι τα χαρακτηριστικά είναι κατηγορικές μεταβλητές. Είναι κατάλληλο για κατηγορικά δεδομένα, όπως η ταξινόμηση φρούτων με βάση το χρώμα και το σχήμα.
#### Κύριες χαρακτηριστικές του Naive Bayes:
-
Τύπος Προβλήματος: Ταξινόμηση (δυαδική ή πολυκατηγορική). Χρησιμοποιείται συχνά για εργασίες ταξινόμησης κειμένων στην κυβερνοασφάλεια (spam, phishing, κ.λπ.).
-
Ερμηνευσιμότητα: Μεσαία -- δεν είναι τόσο άμεσα ερμηνεύσιμος όσο ένα δέντρο απόφασης, αλλά μπορεί κανείς να εξετάσει τις μαθημένες πιθανότητες (π.χ., ποιες λέξεις είναι πιο πιθανές σε spam σε σχέση με τα κανονικά emails). Η μορφή του μοντέλου (πιθανότητες για κάθε χαρακτηριστικό δεδομένης της κλάσης) μπορεί να γίνει κατανοητή αν χρειαστεί.
-
Πλεονεκτήματα: Πολύ γρήγορη εκπαίδευση και πρόβλεψη, ακόμη και σε μεγάλες βάσεις δεδομένων (γραμμική ως προς τον αριθμό των περιπτώσεων * αριθμός χαρακτηριστικών). Απαιτεί σχετικά μικρή ποσότητα δεδομένων για να εκτιμήσει αξιόπιστα τις πιθανότητες, ειδικά με κατάλληλη εξομάλυνση. Συχνά είναι εκπληκτικά ακριβής ως βάση, ειδικά όταν τα χαρακτηριστικά συμβάλλουν ανεξάρτητα στην απόδειξη της κλάσης. Λειτουργεί καλά με δεδομένα υψηλής διάστασης (π.χ., χιλιάδες χαρακτηριστικά από κείμενο). Δεν απαιτεί πολύπλοκη ρύθμιση πέρα από την ρύθμιση μιας παραμέτρου εξομάλυνσης.
-
Περιορισμοί: Η υπόθεση ανεξαρτησίας μπορεί να περιορίσει την ακρίβεια αν τα χαρακτηριστικά είναι πολύ συσχετισμένα. Για παράδειγμα, σε δεδομένα δικτύου, χαρακτηριστικά όπως
src_bytes
καιdst_bytes
μπορεί να είναι συσχετισμένα; ο Naive Bayes δεν θα καταγράψει αυτή την αλληλεπίδραση. Καθώς το μέγεθος των δεδομένων αυξάνεται πολύ, πιο εκφραστικά μοντέλα (όπως τα σύνολα ή τα νευρωνικά δίκτυα) μπορούν να ξεπεράσουν τον NB μαθαίνοντας τις εξαρτήσεις των χαρακτηριστικών. Επίσης, αν μια συγκεκριμένη συνδυασμένη ομάδα χαρακτηριστικών είναι απαραίτητη για να προσδιοριστεί μια επίθεση (όχι μόνο μεμονωμένα χαρακτηριστικά ανεξάρτητα), ο NB θα δυσκολευτεί.
tip
Χρήσεις στην κυβερνοασφάλεια: Η κλασική χρήση είναι η ανίχνευση spam -- ο Naive Bayes ήταν ο πυρήνας των πρώτων φίλτρων spam, χρησιμοποιώντας τις συχνότητες ορισμένων tokens (λέξεις, φράσεις, διευθύνσεις IP) για να υπολογίσει την πιθανότητα ένα email να είναι spam. Χρησιμοποιείται επίσης στην ανίχνευση phishing emails και στην ταξινόμηση URL, όπου η παρουσία ορισμένων λέξεων-κλειδιών ή χαρακτηριστικών (όπως το "login.php" σε μια διεύθυνση URL, ή το @
σε μια διαδρομή URL) συμβάλλει στην πιθανότητα phishing. Στην ανάλυση κακόβουλου λογισμικού, θα μπορούσε κανείς να φανταστεί έναν ταξινομητή Naive Bayes που χρησιμοποιεί την παρουσία ορισμένων κλήσεων API ή αδειών σε λογισμικό για να προβλέψει αν είναι κακόβουλο. Ενώ πιο προηγμένοι αλγόριθμοι συχνά αποδίδουν καλύτερα, ο Naive Bayes παραμένει μια καλή βάση λόγω της ταχύτητας και της απλότητάς του.
Παράδειγμα -- Naive Bayes για Ανίχνευση Phishing:
Για να δείξουμε τον Naive Bayes, θα χρησιμοποιήσουμε τον Gaussian Naive Bayes στο σύνολο δεδομένων NSL-KDD για επιθέσεις (με δυαδικές ετικέτες). Ο Gaussian NB θα θεωρήσει κάθε χαρακτηριστικό ότι ακολουθεί μια κανονική κατανομή ανά κλάση. Αυτή είναι μια χονδροειδής επιλογή καθώς πολλά χαρακτηριστικά δικτύου είναι διακριτά ή πολύ κεκλιμένα, αλλά δείχνει πώς θα εφαρμοστεί ο NB σε δεδομένα συνεχών χαρακτηριστικών. Θα μπορούσαμε επίσης να επιλέξουμε τον Bernoulli NB σε ένα σύνολο δεδομένων δυαδικών χαρακτηριστικών (όπως ένα σύνολο ενεργοποιημένων ειδοποιήσεων), αλλά θα παραμείνουμε με το NSL-KDD εδώ για συνέχεια.import pandas as pd
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score
# 1. Load NSL-KDD data
col_names = [ # 41 features + 2 targets
"duration","protocol_type","service","flag","src_bytes","dst_bytes","land",
"wrong_fragment","urgent","hot","num_failed_logins","logged_in",
"num_compromised","root_shell","su_attempted","num_root","num_file_creations",
"num_shells","num_access_files","num_outbound_cmds","is_host_login",
"is_guest_login","count","srv_count","serror_rate","srv_serror_rate",
"rerror_rate","srv_rerror_rate","same_srv_rate","diff_srv_rate",
"srv_diff_host_rate","dst_host_count","dst_host_srv_count",
"dst_host_same_srv_rate","dst_host_diff_srv_rate",
"dst_host_same_src_port_rate","dst_host_srv_diff_host_rate",
"dst_host_serror_rate","dst_host_srv_serror_rate","dst_host_rerror_rate",
"dst_host_srv_rerror_rate","class","difficulty_level"
]
train_url = "https://raw.githubusercontent.com/Mamcose/NSL-KDD-Network-Intrusion-Detection/master/NSL_KDD_Train.csv"
test_url = "https://raw.githubusercontent.com/Mamcose/NSL-KDD-Network-Intrusion-Detection/master/NSL_KDD_Test.csv"
df_train = pd.read_csv(train_url, header=None, names=col_names)
df_test = pd.read_csv(test_url, header=None, names=col_names)
# 2. Preprocess (encode categorical features, prepare binary labels)
from sklearn.preprocessing import LabelEncoder
for col in ['protocol_type', 'service', 'flag']:
le = LabelEncoder()
le.fit(pd.concat([df_train[col], df_test[col]], axis=0))
df_train[col] = le.transform(df_train[col])
df_test[col] = le.transform(df_test[col])
X_train = df_train.drop(columns=['class', 'difficulty_level'], errors='ignore')
y_train = df_train['class'].apply(lambda x: 0 if x.strip().lower() == 'normal' else 1)
X_test = df_test.drop(columns=['class', 'difficulty_level'], errors='ignore')
y_test = df_test['class'].apply(lambda x: 0 if x.strip().lower() == 'normal' else 1)
# 3. Train Gaussian Naive Bayes
model = GaussianNB()
model.fit(X_train, y_train)
# 4. Evaluate on test set
y_pred = model.predict(X_test)
# For ROC AUC, need probability of class 1:
y_prob = model.predict_proba(X_test)[:, 1] if hasattr(model, "predict_proba") else y_pred
print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}")
print(f"Precision: {precision_score(y_test, y_pred):.3f}")
print(f"Recall: {recall_score(y_test, y_pred):.3f}")
print(f"F1-score: {f1_score(y_test, y_pred):.3f}")
print(f"ROC AUC: {roc_auc_score(y_test, y_prob):.3f}")
"""
Accuracy: 0.450
Precision: 0.937
Recall: 0.037
F1-score: 0.071
ROC AUC: 0.867
"""
Αυτός ο κώδικας εκπαιδεύει έναν ταξινομητή Naive Bayes για να ανιχνεύει επιθέσεις. Ο Naive Bayes θα υπολογίσει πράγματα όπως το P(service=http | Attack)
και το P(Service=http | Normal)
με βάση τα δεδομένα εκπαίδευσης, υποθέτοντας ανεξαρτησία μεταξύ των χαρακτηριστικών. Στη συνέχεια, θα χρησιμοποιήσει αυτές τις πιθανότητες για να ταξινομήσει νέες συνδέσεις ως κανονικές ή επιθέσεις με βάση τα παρατηρούμενα χαρακτηριστικά. Η απόδοση του NB στο NSL-KDD μπορεί να μην είναι τόσο υψηλή όσο πιο προηγμένα μοντέλα (καθώς παραβιάζεται η ανεξαρτησία των χαρακτηριστικών), αλλά συχνά είναι ικανοποιητική και προσφέρει το πλεονέκτημα της εξαιρετικής ταχύτητας. Σε σενάρια όπως η φιλτράρισμα email σε πραγματικό χρόνο ή η αρχική τριχοτόμηση URL, ένα μοντέλο Naive Bayes μπορεί γρήγορα να επισημάνει προφανώς κακόβουλες περιπτώσεις με χαμηλή χρήση πόρων.
k-Nearest Neighbors (k-NN)
Το k-Nearest Neighbors είναι ένας από τους πιο απλούς αλγόριθμους μηχανικής μάθησης. Είναι μια μη παραμετρική, βασισμένη σε παραδείγματα μέθοδος που κάνει προβλέψεις με βάση την ομοιότητα με παραδείγματα στο σύνολο εκπαίδευσης. Η ιδέα για την ταξινόμηση είναι: για να ταξινομήσετε ένα νέο σημείο δεδομένων, βρείτε τα k πιο κοντινά σημεία στα δεδομένα εκπαίδευσης (τους "πλησιέστερους γείτονες") και αναθέστε την πλειοψηφία της κατηγορίας μεταξύ αυτών των γειτόνων. Η "κοντινότητα" ορίζεται από ένα μέτρο απόστασης, συνήθως την ευκλείδεια απόσταση για αριθμητικά δεδομένα (άλλες αποστάσεις μπορούν να χρησιμοποιηθούν για διαφορετικούς τύπους χαρακτηριστικών ή προβλημάτων).
Το K-NN απαιτεί καμία ρητή εκπαίδευση -- η φάση "εκπαίδευσης" είναι απλώς η αποθήκευση του συνόλου δεδομένων. Όλη η εργασία συμβαίνει κατά τη διάρκεια του ερωτήματος (πρόβλεψη): ο αλγόριθμος πρέπει να υπολογίσει αποστάσεις από το σημείο ερωτήματος σε όλα τα σημεία εκπαίδευσης για να βρει τα πιο κοντινά. Αυτό καθιστά τον χρόνο πρόβλεψης γραμμικό ως προς τον αριθμό των δειγμάτων εκπαίδευσης, κάτι που μπορεί να είναι δαπανηρό για μεγάλα σύνολα δεδομένων. Λόγω αυτού, το k-NN είναι καλύτερα προσαρμοσμένο για μικρότερα σύνολα δεδομένων ή σενάρια όπου μπορείτε να ανταλλάξετε μνήμη και ταχύτητα για απλότητα.
Παρά την απλότητά του, το k-NN μπορεί να μοντελοποιήσει πολύ περίπλοκα όρια απόφασης (καθώς στην πραγματικότητα το όριο απόφασης μπορεί να έχει οποιοδήποτε σχήμα που καθορίζεται από την κατανομή των παραδειγμάτων). Τείνει να αποδίδει καλά όταν το όριο απόφασης είναι πολύ ακανόνιστο και έχετε πολλά δεδομένα -- ουσιαστικά επιτρέποντας στα δεδομένα να "μιλήσουν από μόνα τους". Ωστόσο, σε υψηλές διαστάσεις, τα μέτρα απόστασης μπορεί να γίνουν λιγότερο σημαντικά (κατάρα της διαστατικότητας), και η μέθοδος μπορεί να δυσκολευτεί εκτός αν έχετε έναν τεράστιο αριθμό δειγμάτων.
Χρήσεις στην κυβερνοασφάλεια: Το k-NN έχει εφαρμοστεί στην ανίχνευση ανωμαλιών -- για παράδειγμα, ένα σύστημα ανίχνευσης εισβολών μπορεί να χαρακτηρίσει ένα γεγονός δικτύου ως κακόβουλο αν οι περισσότεροι από τους πλησιέστερους γείτονές του (προηγούμενα γεγονότα) ήταν κακόβουλοι. Αν η κανονική κίνηση σχηματίζει συστάδες και οι επιθέσεις είναι εξαιρέσεις, μια προσέγγιση K-NN (με k=1 ή μικρό k) ουσιαστικά κάνει μια ανίχνευση ανωμαλιών πλησιέστερου γείτονα. Το K-NN έχει επίσης χρησιμοποιηθεί για την ταξινόμηση οικογενειών κακόβουλου λογισμικού με διανύσματα δυαδικών χαρακτηριστικών: ένα νέο αρχείο μπορεί να ταξινομηθεί ως μια συγκεκριμένη οικογένεια κακόβουλου λογισμικού αν είναι πολύ κοντά (στον χώρο χαρακτηριστικών) σε γνωστά παραδείγματα αυτής της οικογένειας. Στην πράξη, το k-NN δεν είναι τόσο κοινό όσο πιο κλιμακούμενοι αλγόριθμοι, αλλά είναι εννοιολογικά απλό και μερικές φορές χρησιμοποιείται ως βάση ή για προβλήματα μικρής κλίμακας.
Κύρια χαρακτηριστικά του k-NN:
-
Τύπος Προβλήματος: Ταξινόμηση (και υπάρχουν παραλλαγές παλινδρόμησης). Είναι μια τεμπέλικη μέθοδος μάθησης -- καμία ρητή προσαρμογή μοντέλου.
-
Ερμηνευσιμότητα: Χαμηλή έως μέτρια -- δεν υπάρχει παγκόσμιο μοντέλο ή συνοπτική εξήγηση, αλλά μπορεί κανείς να ερμηνεύσει τα αποτελέσματα κοιτάζοντας τους πλησιέστερους γείτονες που επηρέασαν μια απόφαση (π.χ., "αυτή η ροή δικτύου ταξινομήθηκε ως κακόβουλη επειδή είναι παρόμοια με αυτές τις 3 γνωστές κακόβουλες ροές"). Έτσι, οι εξηγήσεις μπορούν να είναι βασισμένες σε παραδείγματα.
-
Πλεονεκτήματα: Πολύ απλό στην υλοποίηση και κατανόηση. Δεν κάνει υποθέσεις σχετικά με την κατανομή των δεδομένων (μη παραμετρικό). Μπορεί φυσικά να χειριστεί προβλήματα πολλαπλών κατηγοριών. Είναι προσαρμοστικό με την έννοια ότι τα όρια απόφασης μπορεί να είναι πολύ περίπλοκα, διαμορφωμένα από την κατανομή των δεδομένων.
-
Περιορισμοί: Η πρόβλεψη μπορεί να είναι αργή για μεγάλα σύνολα δεδομένων (πρέπει να υπολογιστούν πολλές αποστάσεις). Χρειάζεται πολλή μνήμη -- αποθηκεύει όλα τα δεδομένα εκπαίδευσης. Η απόδοση επιδεινώνεται σε χώρους χαρακτηριστικών υψηλής διάστασης επειδή όλα τα σημεία τείνουν να γίνονται σχεδόν ισαπέχοντα (κάνοντάς το έννοια του "πλησιέστερου" λιγότερο σημαντική). Πρέπει να επιλέξετε το k (αριθμός γειτόνων) κατάλληλα -- πολύ μικρό k μπορεί να είναι θορυβώδες, πολύ μεγάλο k μπορεί να περιλαμβάνει άσχετα σημεία από άλλες κατηγορίες. Επίσης, τα χαρακτηριστικά θα πρέπει να κλιμακωθούν κατάλληλα επειδή οι υπολογισμοί αποστάσεων είναι ευαίσθητοι στην κλίμακα.
Παράδειγμα -- k-NN για Ανίχνευση Phishing:
Θα χρησιμοποιήσουμε ξανά το NSL-KDD (δυαδική ταξινόμηση). Δεδομένου ότι το k-NN είναι υπολογιστικά βαρύ, θα χρησιμοποιήσουμε ένα υποσύνολο των δεδομένων εκπαίδευσης για να το διατηρήσουμε διαχειρίσιμο σε αυτήν την επίδειξη. Θα επιλέξουμε, ας πούμε, 20.000 δείγματα εκπαίδευσης από το πλήρες 125k, και θα χρησιμοποιήσουμε k=5 γείτονες. Μετά την εκπαίδευση (στην πραγματικότητα απλώς αποθηκεύοντας τα δεδομένα), θα αξιολογήσουμε στο σύνολο δοκιμής. Θα κλιμακώσουμε επίσης τα χαρακτηριστικά για τον υπολογισμό αποστάσεων για να διασφαλίσουμε ότι κανένα μεμονωμένο χαρακτηριστικό δεν κυριαρχεί λόγω κλίμακας.
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score
# 1. Load NSL-KDD and preprocess similarly
col_names = [ # 41 features + 2 targets
"duration","protocol_type","service","flag","src_bytes","dst_bytes","land",
"wrong_fragment","urgent","hot","num_failed_logins","logged_in",
"num_compromised","root_shell","su_attempted","num_root","num_file_creations",
"num_shells","num_access_files","num_outbound_cmds","is_host_login",
"is_guest_login","count","srv_count","serror_rate","srv_serror_rate",
"rerror_rate","srv_rerror_rate","same_srv_rate","diff_srv_rate",
"srv_diff_host_rate","dst_host_count","dst_host_srv_count",
"dst_host_same_srv_rate","dst_host_diff_srv_rate",
"dst_host_same_src_port_rate","dst_host_srv_diff_host_rate",
"dst_host_serror_rate","dst_host_srv_serror_rate","dst_host_rerror_rate",
"dst_host_srv_rerror_rate","class","difficulty_level"
]
train_url = "https://raw.githubusercontent.com/Mamcose/NSL-KDD-Network-Intrusion-Detection/master/NSL_KDD_Train.csv"
test_url = "https://raw.githubusercontent.com/Mamcose/NSL-KDD-Network-Intrusion-Detection/master/NSL_KDD_Test.csv"
df_train = pd.read_csv(train_url, header=None, names=col_names)
df_test = pd.read_csv(test_url, header=None, names=col_names)
from sklearn.preprocessing import LabelEncoder
for col in ['protocol_type', 'service', 'flag']:
le = LabelEncoder()
le.fit(pd.concat([df_train[col], df_test[col]], axis=0))
df_train[col] = le.transform(df_train[col])
df_test[col] = le.transform(df_test[col])
X = df_train.drop(columns=['class', 'difficulty_level'], errors='ignore')
y = df_train['class'].apply(lambda x: 0 if x.strip().lower() == 'normal' else 1)
# Use a random subset of the training data for K-NN (to reduce computation)
X_train = X.sample(n=20000, random_state=42)
y_train = y[X_train.index]
# Use the full test set for evaluation
X_test = df_test.drop(columns=['class', 'difficulty_level'], errors='ignore')
y_test = df_test['class'].apply(lambda x: 0 if x.strip().lower() == 'normal' else 1)
# 2. Feature scaling for distance-based model
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
# 3. Train k-NN classifier (store data)
model = KNeighborsClassifier(n_neighbors=5, n_jobs=-1)
model.fit(X_train, y_train)
# 4. Evaluate on test set
y_pred = model.predict(X_test)
y_prob = model.predict_proba(X_test)[:, 1]
print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}")
print(f"Precision: {precision_score(y_test, y_pred):.3f}")
print(f"Recall: {recall_score(y_test, y_pred):.3f}")
print(f"F1-score: {f1_score(y_test, y_pred):.3f}")
print(f"ROC AUC: {roc_auc_score(y_test, y_prob):.3f}")
"""
Accuracy: 0.780
Precision: 0.972
Recall: 0.632
F1-score: 0.766
ROC AUC: 0.837
"""
Το μοντέλο k-NN θα ταξινομήσει μια σύνδεση εξετάζοντας τις 5 πιο κοντινές συνδέσεις στο υποσύνολο του εκπαιδευτικού συνόλου. Αν, για παράδειγμα, 4 από αυτούς τους γείτονες είναι επιθέσεις (ανωμαλίες) και 1 είναι κανονική, η νέα σύνδεση θα ταξινομηθεί ως επίθεση. Η απόδοση μπορεί να είναι λογική, αν και συχνά δεν είναι τόσο υψηλή όσο ενός καλά ρυθμισμένου Random Forest ή SVM στα ίδια δεδομένα. Ωστόσο, το k-NN μπορεί μερικές φορές να διαπρέψει όταν οι κατανομές των κλάσεων είναι πολύ ανώμαλες και περίπλοκες -- χρησιμοποιώντας αποτελεσματικά μια αναζήτηση βασισμένη στη μνήμη. Στην κυβερνοασφάλεια, το k-NN (με k=1 ή μικρό k) θα μπορούσε να χρησιμοποιηθεί για την ανίχνευση γνωστών προτύπων επιθέσεων μέσω παραδείγματος, ή ως συστατικό σε πιο σύνθετα συστήματα (π.χ., για ομαδοποίηση και στη συνέχεια ταξινόμηση με βάση την ένταξη σε ομάδες).
Gradient Boosting Machines (π.χ., XGBoost)
Οι Gradient Boosting Machines είναι από τους πιο ισχυρούς αλγόριθμους για δομημένα δεδομένα. Gradient boosting αναφέρεται στην τεχνική κατασκευής ενός συνόλου αδύναμων μαθητών (συχνά δέντρα αποφάσεων) με διαδοχικό τρόπο, όπου κάθε νέο μοντέλο διορθώνει τα σφάλματα του προηγούμενου συνόλου. Σε αντίθεση με το bagging (Random Forests) που κατασκευάζει δέντρα παράλληλα και τα μέσωνε, το boosting κατασκευάζει δέντρα ένα προς ένα, το καθένα εστιάζοντας περισσότερο στις περιπτώσεις που τα προηγούμενα δέντρα προέβλεψαν λανθασμένα.
Οι πιο δημοφιλείς υλοποιήσεις τα τελευταία χρόνια είναι οι XGBoost, LightGBM και CatBoost, όλες οι οποίες είναι βιβλιοθήκες δέντρων απόφασης gradient boosting (GBDT). Έχουν σημειώσει εξαιρετική επιτυχία σε διαγωνισμούς και εφαρμογές μηχανικής μάθησης, συχνά επιτυγχάνοντας κορυφαία απόδοση σε πίνακες δεδομένων. Στην κυβερνοασφάλεια, ερευνητές και επαγγελματίες έχουν χρησιμοποιήσει δέντρα με gradient boosting για εργασίες όπως ανίχνευση κακόβουλου λογισμικού (χρησιμοποιώντας χαρακτηριστικά που εξάγονται από αρχεία ή συμπεριφορά κατά την εκτέλεση) και ανίχνευση δικτυακής εισβολής. Για παράδειγμα, ένα μοντέλο gradient boosting μπορεί να συνδυάσει πολλούς αδύναμους κανόνες (δέντρα) όπως "αν υπάρχουν πολλοί SYN πακέτα και ασυνήθιστη θύρα -> πιθανή σάρωση" σε έναν ισχυρό σύνθετο ανιχνευτή που λαμβάνει υπόψη πολλές λεπτές προσαρμογές.
Γιατί είναι τόσο αποτελεσματικά τα δέντρα που ενισχύονται; Κάθε δέντρο στη σειρά εκπαιδεύεται στα υπολειμματικά σφάλματα (γραμμές) των προβλέψεων του τρέχοντος συνόλου. Με αυτόν τον τρόπο, το μοντέλο σταδιακά "ενισχύει" τις περιοχές όπου είναι αδύναμο. Η χρήση δέντρων αποφάσεων ως βασικών μαθητών σημαίνει ότι το τελικό μοντέλο μπορεί να συλλάβει περίπλοκες αλληλεπιδράσεις και μη γραμμικές σχέσεις. Επίσης, το boosting έχει εγγενώς μια μορφή ενσωματωμένης κανονικοποίησης: προσθέτοντας πολλά μικρά δέντρα (και χρησιμοποιώντας ένα ρυθμό μάθησης για να κλιμακώσει τις συνεισφορές τους), συχνά γενικεύει καλά χωρίς υπερβολική προσαρμογή, εφόσον επιλεγούν σωστά οι παράμετροι.
Κύρια χαρακτηριστικά του Gradient Boosting:
-
Τύπος Προβλήματος: Κυρίως ταξινόμηση και παλινδρόμηση. Στην ασφάλεια, συνήθως ταξινόμηση (π.χ., δυαδική ταξινόμηση μιας σύνδεσης ή αρχείου). Διαχειρίζεται δυαδικά, πολυταξινομημένα (με κατάλληλη απώλεια) και ακόμη και προβλήματα κατάταξης.
-
Ερμηνευσιμότητα: Χαμηλή έως μέτρια. Ενώ ένα μόνο ενισχυμένο δέντρο είναι μικρό, ένα πλήρες μοντέλο μπορεί να έχει εκατοντάδες δέντρα, τα οποία δεν είναι κατανοητά από τον άνθρωπο ως σύνολο. Ωστόσο, όπως και το Random Forest, μπορεί να παρέχει βαθμολογίες σημασίας χαρακτηριστικών, και εργαλεία όπως το SHAP (SHapley Additive exPlanations) μπορούν να χρησιμοποιηθούν για την ερμηνεία μεμονωμένων προβλέψεων σε κάποιο βαθμό.
-
Πλεονεκτήματα: Συχνά ο καλύτερα αποδοτικός αλγόριθμος για δομημένα/πίνακες δεδομένων. Μπορεί να ανιχνεύσει περίπλοκα πρότυπα και αλληλεπιδράσεις. Έχει πολλές ρυθμιστικές ρυθμίσεις (αριθμός δέντρων, βάθος δέντρων, ρυθμός μάθησης, όροι κανονικοποίησης) για να προσαρμόσει την πολυπλοκότητα του μοντέλου και να αποτρέψει την υπερβολική προσαρμογή. Οι σύγχρονες υλοποιήσεις είναι βελτιστοποιημένες για ταχύτητα (π.χ., το XGBoost χρησιμοποιεί πληροφορίες δεύτερης τάξης και αποδοτικές δομές δεδομένων). Τείνει να διαχειρίζεται καλύτερα τα ανισοκατανεμημένα δεδομένα όταν συνδυάζεται με κατάλληλες συναρτήσεις απώλειας ή προσαρμόζοντας τα βάρη δειγμάτων.
-
Περιορισμοί: Πιο περίπλοκο να ρυθμιστεί από απλούστερα μοντέλα; η εκπαίδευση μπορεί να είναι αργή αν τα δέντρα είναι βαθιά ή ο αριθμός των δέντρων είναι μεγάλος (αν και συνήθως είναι πιο γρήγορη από την εκπαίδευση ενός συγκρίσιμου βαθιού νευρωνικού δικτύου στα ίδια δεδομένα). Το μοντέλο μπορεί να υπερπροσαρμοστεί αν δεν ρυθμιστεί (π.χ., πάρα πολλά βαθιά δέντρα με ανεπαρκή κανονικοποίηση). Λόγω πολλών υπερπαραμέτρων, η αποτελεσματική χρήση του gradient boosting μπορεί να απαιτεί περισσότερη εμπειρία ή πειραματισμό. Επίσης, όπως οι μέθοδοι βασισμένες σε δέντρα, δεν διαχειρίζεται εγγενώς πολύ αραιά υψηλής διάστασης δεδομένα όσο αποδοτικά όσο τα γραμμικά μοντέλα ή το Naive Bayes (αν και μπορεί να εφαρμοστεί, π.χ., στην ταξινόμηση κειμένου, αλλά μπορεί να μην είναι η πρώτη επιλογή χωρίς μηχανική χαρακτηριστικών).
tip
Χρήσεις στην κυβερνοασφάλεια: Σχεδόν οπουδήποτε θα μπορούσε να χρησιμοποιηθεί ένα δέντρο απόφασης ή ένα τυχαίο δάσος, ένα μοντέλο gradient boosting μπορεί να επιτύχει καλύτερη ακρίβεια. Για παράδειγμα, οι διαγωνισμοί ανίχνευσης κακόβουλου λογισμικού της Microsoft έχουν δει εκτενή χρήση του XGBoost σε μηχανικά χαρακτηριστικά από δυαδικά αρχεία. Η έρευνα για την ανίχνευση δικτυακής εισβολής συχνά αναφέρει κορυφαία αποτελέσματα με GBDTs (π.χ., XGBoost σε CIC-IDS2017 ή UNSW-NB15 σύνολα δεδομένων). Αυτά τα μοντέλα μπορούν να λάβουν μια ευρεία γκάμα χαρακτηριστικών (τύποι πρωτοκόλλων, συχνότητα ορισμένων γεγονότων, στατιστικά χαρακτηριστικά της κίνησης, κ.λπ.) και να τα συνδυάσουν για να ανιχνεύσουν απειλές. Στην ανίχνευση phishing, το gradient boosting μπορεί να συνδυάσει λεξιλογικά χαρακτηριστικά URL, χαρακτηριστικά φήμης τομέα και χαρακτηριστικά περιεχομένου σελίδας για να επιτύχει πολύ υψηλή ακρίβεια. Η προσέγγιση του συνόλου βοηθά στην κάλυψη πολλών περιθωριακών περιπτώσεων και λεπτομερειών στα δεδομένα.
Παράδειγμα -- XGBoost για Ανίχνευση Phishing:
Θα χρησιμοποιήσουμε έναν ταξινομητή gradient boosting στο σύνολο δεδομένων phishing. Για να διατηρήσουμε τα πράγματα απλά και αυτοτελή, θα χρησιμοποιήσουμε το `sklearn.ensemble.GradientBoostingClassifier` (το οποίο είναι μια πιο αργή αλλά απλή υλοποίηση). Κανονικά, θα μπορούσε κανείς να χρησιμοποιήσει τις βιβλιοθήκες `xgboost` ή `lightgbm` για καλύτερη απόδοση και επιπλέον χαρακτηριστικά. Θα εκπαιδεύσουμε το μοντέλο και θα το αξιολογήσουμε παρόμοια με πριν.import pandas as pd
from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score
# 1️⃣ Load the “Phishing Websites” data directly from OpenML
data = fetch_openml(data_id=4534, as_frame=True) # or data_name="PhishingWebsites"
df = data.frame
# 2️⃣ Separate features/target & make sure everything is numeric
X = df.drop(columns=["Result"])
y = df["Result"].astype(int).apply(lambda v: 1 if v == 1 else 0) # map {-1,1} → {0,1}
# (If any column is still object‑typed, coerce it to numeric.)
X = X.apply(pd.to_numeric, errors="coerce").fillna(0)
# 3️⃣ Train/test split
X_train, X_test, y_train, y_test = train_test_split(
X.values, y, test_size=0.20, random_state=42
)
# 4️⃣ Gradient Boosting model
model = GradientBoostingClassifier(
n_estimators=100, learning_rate=0.1, max_depth=3, random_state=42
)
model.fit(X_train, y_train)
# 5️⃣ Evaluation
y_pred = model.predict(X_test)
y_prob = model.predict_proba(X_test)[:, 1]
print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}")
print(f"Precision: {precision_score(y_test, y_pred):.3f}")
print(f"Recall: {recall_score(y_test, y_pred):.3f}")
print(f"F1‑score: {f1_score(y_test, y_pred):.3f}")
print(f"ROC AUC: {roc_auc_score(y_test, y_prob):.3f}")
"""
Accuracy: 0.951
Precision: 0.949
Recall: 0.965
F1‑score: 0.957
ROC AUC: 0.990
"""
Το μοντέλο gradient boosting θα επιτύχει πιθανώς πολύ υψηλή ακρίβεια και AUC σε αυτό το σύνολο δεδομένων phishing (συχνά αυτά τα μοντέλα μπορούν να ξεπεράσουν το 95% ακρίβεια με σωστή ρύθμιση σε τέτοια δεδομένα, όπως φαίνεται στη βιβλιογραφία. Αυτό δείχνει γιατί τα GBDTs θεωρούνται "το μοντέλο αιχμής για πίνακες δεδομένων" -- συχνά υπερβαίνουν απλούστερες αλγορίθμους συλλαμβάνοντας πολύπλοκα μοτίβα. Σε ένα πλαίσιο κυβερνοασφάλειας, αυτό θα μπορούσε να σημαίνει ότι θα εντοπίζουμε περισσότερους phishing ιστότοπους ή επιθέσεις με λιγότερες παραλείψεις. Φυσικά, πρέπει να είμαστε προσεκτικοί σχετικά με την υπερπροσαρμογή -- συνήθως θα χρησιμοποιούσαμε τεχνικές όπως η διασταυρούμενη επικύρωση και θα παρακολουθούσαμε την απόδοση σε ένα σύνολο επικύρωσης κατά την ανάπτυξη ενός τέτοιου μοντέλου για ανάπτυξη.
Συνδυασμός Μοντέλων: Ensemble Learning και Stacking
Το ensemble learning είναι μια στρατηγική συνδυασμού πολλαπλών μοντέλων για τη βελτίωση της συνολικής απόδοσης. Ήδη είδαμε συγκεκριμένες μεθόδους ensemble: Random Forest (ένα σύνολο δέντρων μέσω bagging) και Gradient Boosting (ένα σύνολο δέντρων μέσω διαδοχικού boosting). Αλλά τα ensembles μπορούν να δημιουργηθούν και με άλλους τρόπους, όπως voting ensembles ή stacked generalization (stacking). Η κύρια ιδέα είναι ότι διαφορετικά μοντέλα μπορεί να συλλαμβάνουν διαφορετικά μοτίβα ή να έχουν διαφορετικές αδυναμίες. Συνδυάζοντάς τα, μπορούμε να αντισταθμίσουμε τα λάθη κάθε μοντέλου με τις δυνάμεις ενός άλλου.
-
Voting Ensemble: Σε έναν απλό ψηφοφόρο ταξινομητή, εκπαιδεύουμε πολλαπλά διαφορετικά μοντέλα (ας πούμε, μια λογιστική παλινδρόμηση, ένα δέντρο απόφασης και ένα SVM) και τους κάνουμε να ψηφίσουν για την τελική πρόβλεψη (ψηφοφορία πλειοψηφίας για ταξινόμηση). Αν ζυγίσουμε τις ψήφους (π.χ., μεγαλύτερο βάρος σε πιο ακριβή μοντέλα), είναι ένα σύστημα ψηφοφορίας με βάρη. Αυτό συνήθως βελτιώνει την απόδοση όταν τα ατομικά μοντέλα είναι αρκετά καλά και ανεξάρτητα -- το ensemble μειώνει τον κίνδυνο λάθους ενός ατομικού μοντέλου, καθώς άλλα μπορεί να το διορθώσουν. Είναι σαν να έχουμε μια επιτροπή ειδικών αντί για μια μόνο γνώμη.
-
Stacking (Stacked Ensemble): Το stacking προχωρά ένα βήμα παραπέρα. Αντί για μια απλή ψήφο, εκπαιδεύει ένα meta-model για να μάθει πώς να συνδυάζει καλύτερα τις προβλέψεις των βασικών μοντέλων. Για παράδειγμα, εκπαιδεύετε 3 διαφορετικούς ταξινομητές (βασικούς μαθητές), και στη συνέχεια τροφοδοτείτε τις εξόδους τους (ή πιθανότητες) ως χαρακτηριστικά σε έναν meta-classifier (συνήθως ένα απλό μοντέλο όπως η λογιστική παλινδρόμηση) που μαθαίνει τον βέλτιστο τρόπο να τα συνδυάζει. Το meta-model εκπαιδεύεται σε ένα σύνολο επικύρωσης ή μέσω διασταυρούμενης επικύρωσης για να αποφευχθεί η υπερπροσαρμογή. Το stacking μπορεί συχνά να υπερβεί την απλή ψηφοφορία μαθαίνοντας ποια μοντέλα να εμπιστεύονται περισσότερο σε ποιες περιστάσεις. Στην κυβερνοασφάλεια, ένα μοντέλο μπορεί να είναι καλύτερο στο να εντοπίζει σάρωση δικτύου ενώ ένα άλλο είναι καλύτερο στο να εντοπίζει beaconing κακόβουλου λογισμικού. Ένα μοντέλο stacking θα μπορούσε να μάθει να βασίζεται σε κάθε ένα κατάλληλα.
Τα ensembles, είτε μέσω ψηφοφορίας είτε stacking, τείνουν να ενισχύουν την ακρίβεια και την ανθεκτικότητα. Το μειονέκτημα είναι η αυξημένη πολυπλοκότητα και μερικές φορές η μειωμένη ερμηνευσιμότητα (αν και ορισμένες προσεγγίσεις ensemble όπως ο μέσος όρος δέντρων απόφασης μπορούν να παρέχουν ακόμα κάποια κατανόηση, π.χ., σημασία χαρακτηριστικών). Στην πράξη, αν οι επιχειρησιακοί περιορισμοί το επιτρέπουν, η χρήση ενός ensemble μπορεί να οδηγήσει σε υψηλότερους ρυθμούς ανίχνευσης. Πολλές νικηφόρες λύσεις σε προκλήσεις κυβερνοασφάλειας (και σε διαγωνισμούς Kaggle γενικά) χρησιμοποιούν τεχνικές ensemble για να αποσπάσουν την τελευταία σταγόνα απόδοσης.
Παράδειγμα -- Voting Ensemble για Ανίχνευση Phishing:
Για να απεικονίσουμε το stacking μοντέλων, ας συνδυάσουμε μερικά από τα μοντέλα που συζητήσαμε στο σύνολο δεδομένων phishing. Θα χρησιμοποιήσουμε μια λογιστική παλινδρόμηση, ένα δέντρο απόφασης και ένα k-NN ως βασικούς μαθητές, και θα χρησιμοποιήσουμε ένα Random Forest ως meta-learner για να συγκεντρώσουμε τις προβλέψεις τους. Ο meta-learner θα εκπαιδευτεί στις εξόδους των βασικών μαθητών (χρησιμοποιώντας διασταυρούμενη επικύρωση στο σύνολο εκπαίδευσης). Αναμένουμε το stacked μοντέλο να αποδώσει όσο καλά ή ελαφρώς καλύτερα από τα ατομικά μοντέλα.import pandas as pd
from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import StackingClassifier, RandomForestClassifier
from sklearn.metrics import (accuracy_score, precision_score,
recall_score, f1_score, roc_auc_score)
# ──────────────────────────────────────────────
# 1️⃣ LOAD DATASET (OpenML id 4534)
# ──────────────────────────────────────────────
data = fetch_openml(data_id=4534, as_frame=True) # “PhishingWebsites”
df = data.frame
# Target mapping: 1 → legitimate (0), 0/‑1 → phishing (1)
y = (df["Result"].astype(int) != 1).astype(int)
X = df.drop(columns=["Result"])
# Train / test split (stratified to keep class balance)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.20, random_state=42, stratify=y)
# ──────────────────────────────────────────────
# 2️⃣ DEFINE BASE LEARNERS
# • LogisticRegression and k‑NN need scaling ➜ wrap them
# in a Pipeline(StandardScaler → model) so that scaling
# happens inside each CV fold of StackingClassifier.
# ──────────────────────────────────────────────
base_learners = [
('lr', make_pipeline(StandardScaler(),
LogisticRegression(max_iter=1000,
solver='lbfgs',
random_state=42))),
('dt', DecisionTreeClassifier(max_depth=5, random_state=42)),
('knn', make_pipeline(StandardScaler(),
KNeighborsClassifier(n_neighbors=5)))
]
# Meta‑learner (level‑2 model)
meta_learner = RandomForestClassifier(n_estimators=50, random_state=42)
stack_model = StackingClassifier(
estimators = base_learners,
final_estimator = meta_learner,
cv = 5, # 5‑fold CV to create meta‑features
passthrough = False # only base learners’ predictions go to meta‑learner
)
# ──────────────────────────────────────────────
# 3️⃣ TRAIN ENSEMBLE
# ──────────────────────────────────────────────
stack_model.fit(X_train, y_train)
# ──────────────────────────────────────────────
# 4️⃣ EVALUATE
# ──────────────────────────────────────────────
y_pred = stack_model.predict(X_test)
y_prob = stack_model.predict_proba(X_test)[:, 1] # P(phishing)
print(f"Accuracy : {accuracy_score(y_test, y_pred):.3f}")
print(f"Precision: {precision_score(y_test, y_pred):.3f}")
print(f"Recall : {recall_score(y_test, y_pred):.3f}")
print(f"F1‑score : {f1_score(y_test, y_pred):.3f}")
print(f"ROC AUC : {roc_auc_score(y_test, y_prob):.3f}")
"""
Accuracy : 0.954
Precision: 0.951
Recall : 0.946
F1‑score : 0.948
ROC AUC : 0.992
"""
Ο στοίβας συνδυασμός εκμεταλλεύεται τα συμπληρωματικά πλεονεκτήματα των βασικών μοντέλων. Για παράδειγμα, η λογιστική παλινδρόμηση μπορεί να χειριστεί τις γραμμικές πτυχές των δεδομένων, το δέντρο απόφασης μπορεί να συλλάβει συγκεκριμένες αλληλεπιδράσεις τύπου κανόνα, και το k-NN μπορεί να διαπρέπει σε τοπικές γειτονιές του χώρου χαρακτηριστικών. Το μετα-μοντέλο (ένα τυχαίο δάσος εδώ) μπορεί να μάθει πώς να ζυγίζει αυτές τις εισόδους. Οι προκύπτουσες μετρήσεις συχνά δείχνουν μια βελτίωση (ακόμα και αν είναι ελαφριά) σε σχέση με τις μετρήσεις οποιουδήποτε μεμονωμένου μοντέλου. Στο παράδειγμα phishing μας, αν η λογιστική από μόνη της είχε F1 π.χ. 0.95 και το δέντρο 0.94, η στοίβα μπορεί να επιτύχει 0.96 επιλέγοντας πού σφάλλει κάθε μοντέλο.
Οι μέθοδοι συνδυασμού όπως αυτή αποδεικνύουν την αρχή ότι "ο συνδυασμός πολλαπλών μοντέλων συνήθως οδηγεί σε καλύτερη γενίκευση". Στην κυβερνοασφάλεια, αυτό μπορεί να εφαρμοστεί με την ύπαρξη πολλαπλών μηχανών ανίχνευσης (μία μπορεί να είναι βασισμένη σε κανόνες, μία μηχανικής μάθησης, μία βασισμένη σε ανωμαλίες) και στη συνέχεια μια στρώση που συγκεντρώνει τις ειδοποιήσεις τους -- αποτελεσματικά μια μορφή συνδυασμού -- για να λάβει μια τελική απόφαση με υψηλότερη εμπιστοσύνη. Κατά την ανάπτυξη τέτοιων συστημάτων, πρέπει να ληφθεί υπόψη η προστιθέμενη πολυπλοκότητα και να διασφαλιστεί ότι ο συνδυασμός δεν γίνεται πολύ δύσκολος στη διαχείριση ή την εξήγηση. Αλλά από την άποψη της ακρίβειας, οι συνδυασμοί και η στοίβα είναι ισχυρά εργαλεία για τη βελτίωση της απόδοσης του μοντέλου.
Αναφορές
- https://madhuramiah.medium.com/logistic-regression-6e55553cc003
- https://www.geeksforgeeks.org/decision-tree-introduction-example/
- https://rjwave.org/ijedr/viewpaperforall.php?paper=IJEDR1703132
- https://www.ibm.com/think/topics/support-vector-machine
- https://en.m.wikipedia.org/wiki/Naive_Bayes_spam_filtering
- https://medium.com/@rupalipatelkvc/gbdt-demystified-how-lightgbm-xgboost-and-catboost-work-9479b7262644
- https://zvelo.com/ai-and-machine-learning-in-cybersecurity/
- https://medium.com/@chaandram/linear-regression-explained-28d5bf1934ae
- https://cybersecurity.springeropen.com/articles/10.1186/s42400-021-00103-8
- https://www.ibm.com/think/topics/knn
- https://www.ibm.com/think/topics/knn
- https://arxiv.org/pdf/2101.02552
- https://cybersecurity-magazine.com/how-deep-learning-enhances-intrusion-detection-systems/
- https://cybersecurity-magazine.com/how-deep-learning-enhances-intrusion-detection-systems/
- https://medium.com/@sarahzouinina/ensemble-learning-boosting-model-performance-by-combining-strengths-02e56165b901
- https://medium.com/@sarahzouinina/ensemble-learning-boosting-model-performance-by-combining-strengths-02e56165b901
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.