Skip to content

Commit

Permalink
Merge pull request #11 from TW-Robotics/devel_muster
Browse files Browse the repository at this point in the history
Devel muster
  • Loading branch information
SimonSchwaiger committed Jan 29, 2024
2 parents 4ecda2b + d5ba2e8 commit c29c3f4
Show file tree
Hide file tree
Showing 11 changed files with 101,922 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/bin/bash

# Dieses Skript führt ein Beispielprojekt für die Naive Bayes Klassifizierung aus.
#
# This code is available under a GPL v3.0 license and comes without
# any explicit or implicit warranty.
#
# (C) Lucas Muster 2021 <muster@technikum-wien.at>

import pandas as pd
import os

class csvReader:
def __init__(self,input):
self.input = input
self.data = []

def showDirectory(self):
print(os.path.dirname(os.path.abspath(__file__)))

def showDataDirectory(self):
path = os.path.dirname(os.path.abspath(__file__)) + "/data/"
return path

def readCSV(self):
path = self.showDataDirectory()
datapath = str(path) + str(self.input)
self.data = pd.read_csv(datapath)
x = self.data['text']
y = []
for i in range(0,len(x)):
y.append(self.data['label_num'][i])
return x,y
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "18fcba18",
"metadata": {},
"source": [
"# Einleitung\n",
"\n",
"Jede Person mit einem Emailaccount wird bereits Erfahrungen mit Spam gemacht haben. Entweder man soll einen hilfslosen Prinzen aus der finanziellen Krise helfen oder ist nur einen Klick davon entfernt ein neues IPhone zu gewinnen.\n",
"Die Ideen hinter Spamnachrichten sind endlos und können nach und nach richtig nervig werden, wenn sie öfters erscheinen.\n",
"\n",
"Eine Abhilfe ist dabei der Spamfilter, welcher hinterlistigen Nachrichten entdeckt und diese anschließend in den Spamordner verbannt. Doch wie genau entscheidet der Filter eigentlich welche Nachrichten Spam sind und welche nicht?\n",
"Genau diese Antwort soll dieses Notebook liefern, in der ein Klassifierungsalgorithmus, genauer gesagt ein multinominal Naive Bayes Klassifizierer, eingesetzt wird, um Spam emails zu detektierten.\n",
"\n",
"Der Naive Bayes beruht auf dem Bayes Theorem, welcher Wahrscheinlichkeiten bezogen auf Ereignisse berechnet.\n",
"Für unsere konkretes Beispiel des Filters, wird für jede Email die Anzahl an Wörtern gezählt, um anschließend bestimmen zu können, ob es sich tatsächlich um Spam handelt, oder doch nur um eine ganz normale Email. Dabei geht der Klassifizier davon aus, dass die einzelnen Variablen unabhängig sind.\n",
"\n",
"Für die Berechnung der Wahrscheinlichkeiten werden durch folgende Gleichung berechnet:\n",
"\n",
"$P(Spam|Suchwort) = \\frac{P(Suchwort|Spam) \\cdot P(Spam)}{P(Suchwort)} = \\frac{P(Suchwort|Spam) \\cdot P(Spam)}{P(Suchwort|Spam) \\cdot P(Spam) + P(Suchwort|kein Spam) \\cdot P(kein Spam)}$\n",
"\n",
"\n",
"Die Wahrscheinlichkeit, dass eine Email Spam ist unter der Bedingung des Wortes P(Spam|Suchwort) ist gesucht. Über das Bayes Theorem kann dies wie auf der rechten Seite der Gleichung dargestellt berechnet werden und zwar über die Wahrscheinlichkeit, dass ein Wort in einer Spamemail vorkommt P(Suchwort|Spam), multipliziert mit der Wahrscheinlichkeit dass es sich um eine Spamemail handelt P(Spam). Diese Wahrscheinlichkeit muss noch durch die Wahrscheinlichkeit P(Suchwort) dividiert werden, welche eine Addition der Wahrscheinlichkeit des Wortes in Spamemails und normalen Emails sind.\n",
"\n",
"Eine mögliche Implementierung des Klassifizieres kann wie folgt umgesetzt werden. Dabei wurde der Datensatz \"spam_ham_dataset\" verwendet, welcher eine große Anzahl an englischen Emails und Spamemails beinhaltet. Von den ingesamt 5170 Email sind 1500 mit Spam klassifiziert.\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "9856018a",
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"from sklearn.feature_extraction.text import CountVectorizer\n",
"from sklearn.feature_extraction.text import TfidfTransformer\n",
"from sklearn.naive_bayes import MultinomialNB\n",
"from sklearn.model_selection import train_test_split\n",
"\n",
"from sklearn.metrics import classification_report\n",
"from sklearn.metrics import confusion_matrix\n",
"from sklearn.metrics import accuracy_score\n",
"\n",
"from NB_Classifier import NB_Class\n",
"from CSV_Converter import csvReader"
]
},
{
"cell_type": "markdown",
"id": "f748b0ad",
"metadata": {},
"source": [
"Nachdem die benötigten Bibliotheken geladen wurden, muss der Datensatz geladen und verarbeitet werden. Dazu wird die csvReader Klasse verwendet, welche die Daten in X (Input) und y (Output) verwandelt, um sie in den nächsten Schritten zu verarbeiten."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "f87c7237",
"metadata": {},
"outputs": [],
"source": [
"inputData = \"spam_ham_dataset.csv\"\n",
"\n",
"count_vector = CountVectorizer() \n",
"tfidf_transformer = TfidfTransformer()\n",
"\n",
"#Einlesen des Datensatzes\n",
"reader = csvReader(inputData)\n",
"X, y = reader.readCSV()"
]
},
{
"cell_type": "markdown",
"id": "4504cf37",
"metadata": {},
"source": [
"Nach die Daten eingelsen wurden, mussen die Wörter innerhalb einer Email in Vektoren umgewandelt und weiters auch noch gezählt werden. Dies erfolgt über die vorhin eingefügten Bibliotheken. Zusätzlich werden die Daten in Trainings- und Testdaten aufgeteilt."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "729d26a2",
"metadata": {},
"outputs": [],
"source": [
"#Verarbeitung der Texte\n",
"X_train_counts = count_vector.fit_transform(X)\n",
"X_train_tfidf = tfidf_transformer.fit_transform(X_train_counts)\n",
"\n",
"#Aufsplitten des Datensatzes in Test und Training\n",
"x_train, x_test , y_train, y_test = train_test_split(X_train_tfidf,y, test_size = 0.1, shuffle = True)"
]
},
{
"cell_type": "markdown",
"id": "54bec3b6",
"metadata": {},
"source": [
"Nun muss der Klassifizierer mit den Trainingsdaten trainiert werden, um anschließend eine Vorhersage über den Testdatensatzes zu generieren.\n",
"\n",
"Die Ergebnisse können in der daraus resultierenden Tabelle herausgelesen werden."
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "27652726",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Klassifikation Ergebnis:\n",
" precision recall f1-score support\n",
"\n",
" 0 1.00 0.86 0.92 428\n",
" 1 0.60 1.00 0.75 90\n",
"\n",
" accuracy 0.88 518\n",
" macro avg 0.80 0.93 0.84 518\n",
"weighted avg 0.93 0.88 0.89 518\n",
"\n",
"Confusion matrix:\n",
" [[367 61]\n",
" [ 0 90]]\n",
"Genauigkeit: 88.22393822393822 %\n"
]
}
],
"source": [
"#Bestimmung des Klassifizieres\n",
"clf = MultinomialNB().fit(x_train, y_train)\n",
"\n",
"#Vorhersage\n",
"predicted = clf.predict(x_test)\n",
"\n",
"print(\"Klassifikation Ergebnis:\\n\",classification_report(predicted, y_test))\n",
"print(\"Confusion matrix:\\n\",confusion_matrix(predicted, y_test))\n",
"print(\"Genauigkeit:\",accuracy_score(predicted, y_test)*100,\"%\")"
]
},
{
"cell_type": "markdown",
"id": "12900c76",
"metadata": {},
"source": [
"Die Ergebnisse zeigen, dass mit einem Naive Bayes einfach ein Spamfilter für den Emailverkehr generiert werden kann. Die Genauigkeit, welche damit ereicht werden konnte ist für einen solchen Fall durchaus verwendbar. Jedoch sollte jeder seinen Spamordner immer wieder kontrollieren, ob der Filter sich nicht doch geirrt haben könnte. "
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/bin/bash

# Dieses Skript implementiert ein Naive Bayes Klassifizierungsmodell.
#
# This code is available under a GPL v3.0 license and comes without
# any explicit or implicit warranty.
#
# (C) Lucas Muster 2021 <muster@technikum-wien.at>

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split

from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score

from CSV_Converter import csvReader

class NB_Class:
def __init__(self):
self.count_vector = CountVectorizer()
self.tfidf_transformer = TfidfTransformer()
self.X = []
self.y = []

def pipeline(self,inputData):
self.makeData(inputData)
self.trainModel()

def makeData(self,inputData):
self.reader = csvReader(inputData)
self.X, self.y = self.reader.readCSV()

def trainModel(self):
self.X_train_counts = self.count_vector.fit_transform(self.X)
self.X_train_tfidf = self.tfidf_transformer.fit_transform(self.X_train_counts)

x_train, x_test , y_train, y_test = train_test_split(self.X_train_tfidf,self.y, test_size = 0.1, shuffle = True)
self.clf = MultinomialNB().fit(x_train, y_train)
predicted = self.clf.predict(x_test)
print("Classification report:\n",classification_report(predicted, y_test))
print("Confusion matrix:\n",confusion_matrix(predicted, y_test))
print("\n\033[92mAccuracy score:",accuracy_score(predicted, y_test)*100,"% \033[0m \n")
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Einsatz einer Naive Bayes Klassifikation für die Emailspam Filterung

Jede Person mit einem Emailaccount wird bereits Erfahrungen mit Spam gemacht haben. Entweder man soll einen hilflosen Prinzen aus der finanziellen Krise helfen oder ist nur einen Klick davon entfernt ein neues iPhone zu gewinnen. Die Ideen hinter Spamnachrichten sind endlos und können nach und nach richtig nervig werden, wenn sie öfters erscheinen.

Eine Abhilfe ist dabei der Spamfilter, welcher hinterlistigen Nachrichten entdeckt und diese anschließend in den Spamordner verbannt. Doch wie genau entscheidet der Filter eigentlich, welche Nachrichten Spam sind und welche nicht? Genau diese Antwort soll dieses Notebook liefern, in der ein Klassifizierungsalgorithmus, genauer gesagt ein multinominal Naive Bayes Klassifizierer, eingesetzt wird, um Spam Emails zu detektierten.

Der Naive Bayes beruht auf dem Bayes Theorem, welcher Wahrscheinlichkeiten bezogen auf Ereignisse berechnet. Für unsere konkretes Beispiel des Filters, wird für jede Email die Anzahl an Wörtern gezählt, um anschließend bestimmen zu können, ob es sich tatsächlich um Spam handelt, oder doch nur um eine ganz normale Email. Dabei geht der Klassifizier davon aus, dass die einzelnen Variablen unabhängig sind.

Eine mögliche Implementierung des Klassifizierers kann wie in diesem Projekt gezeigt, umgesetzt werden. Dabei wurde der Datensatz "spam_ham_dataset" verwendet, welcher eine große Anzahl an englischen Emails und Spamemails beinhaltet. Von den insgesamt 5170 Emails sind 1500 mit Spam klassifiziert.
Als Grundlage wurde die [sklearn](https://scikit-learn.org/stable/) Bibliothek verwendet.

## Ausführung

Zum Ausführen des Projektes die Datei start.bash im Terminal ausführen. Nach der Installierung in der virtuellen Umgebung, wird der Naive Bayes Klassifizierer am Datensatz [spam_ham_dataset](https://www.kaggle.com/ayhampar/spam-ham-dataset/data).

Alternativ kann auch das vorhandene Jupyter Notebook ausgeführt werden, wo zusätzliche Beschreibungen zum Code vorhanden sind.

## Zusätzliche Informationen

Für mehr Informationen kann das [AIAV Naive Bayes Video](https://youtu.be/ioDdAE6AOMQ) betrachtet werden, in der die mathematischen Hintergründe erklärt werden.
Zusätzlich finden sich viele Informationen und Beispiele zum Thema Machine Learning und Künstlicher Intelligenz auf unserer offiziellen [AIAV Website](https://www.aiav.technikum-wien.at/).


<p align="center">
<img src="img/wien_ma23.png" width="480"> <img src="img/FH_Technikum_Wien_logo.png" width="260">
</p>
Loading

0 comments on commit c29c3f4

Please sign in to comment.