Rename classifiers/ package to models/
Aligns module naming with the upcoming classification_neural lab, which will use the same models/ package convention. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
0
models/__init__.py
Normal file
0
models/__init__.py
Normal file
46
models/bow.py
Normal file
46
models/bow.py
Normal file
@@ -0,0 +1,46 @@
|
||||
from collections import Counter
|
||||
|
||||
import numpy as np
|
||||
from sklearn.feature_extraction import DictVectorizer
|
||||
from sklearn.linear_model import LogisticRegression
|
||||
from sklearn.pipeline import Pipeline
|
||||
|
||||
from models.cleaning import LowercaseTransformer, PunctuationRemover
|
||||
|
||||
|
||||
class FeatureExtractor:
|
||||
def fit(self, X, y=None):
|
||||
return self
|
||||
|
||||
def transform(self, X):
|
||||
return [self.extract_features(msg) for msg in X]
|
||||
|
||||
def extract_features(self, message):
|
||||
return dict(Counter(message.split()))
|
||||
|
||||
|
||||
class BagOfWordsClassifier:
|
||||
def fit(self, X, y):
|
||||
self._pipeline = Pipeline([
|
||||
("lowercase", LowercaseTransformer()),
|
||||
("punctuation", PunctuationRemover()),
|
||||
("features", FeatureExtractor()),
|
||||
("vectorizer", DictVectorizer()),
|
||||
("classifier", LogisticRegression(max_iter=1000)),
|
||||
])
|
||||
y_binary = (np.array(y) == "spam").astype(int)
|
||||
self._pipeline.fit(X, y_binary)
|
||||
return self
|
||||
|
||||
def predict(self, X):
|
||||
y_binary = self._pipeline.predict(X)
|
||||
return np.where(y_binary == 1, "spam", "ham")
|
||||
|
||||
def feature_weights(self, top_n=10):
|
||||
vectorizer = self._pipeline.named_steps["vectorizer"]
|
||||
classifier = self._pipeline.named_steps["classifier"]
|
||||
names = vectorizer.get_feature_names_out()
|
||||
weights = classifier.coef_[0]
|
||||
pairs = sorted(zip(names, weights), key=lambda x: x[1])
|
||||
half = top_n // 2
|
||||
return pairs[-half:][::-1] + pairs[:half]
|
||||
41
models/cleaning.py
Normal file
41
models/cleaning.py
Normal file
@@ -0,0 +1,41 @@
|
||||
import re
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
STOPWORDS = {
|
||||
"a", "an", "the", "is", "it", "in", "on", "at", "to", "for",
|
||||
"of", "and", "or", "but", "not", "with", "as", "by", "from",
|
||||
"this", "that", "was", "are", "be", "been", "have", "has",
|
||||
"had", "do", "did", "will", "would", "could", "should",
|
||||
"i", "me", "my", "you", "your", "he", "she", "we", "they",
|
||||
"his", "her", "our", "their", "its", "what", "which",
|
||||
}
|
||||
|
||||
|
||||
class LowercaseTransformer:
|
||||
def fit(self, X, y=None):
|
||||
return self
|
||||
|
||||
def transform(self, X):
|
||||
return np.array([msg.lower() for msg in X])
|
||||
|
||||
|
||||
class StopwordRemover:
|
||||
def fit(self, X, y=None):
|
||||
return self
|
||||
|
||||
def transform(self, X):
|
||||
return np.array([self._remove(msg) for msg in X])
|
||||
|
||||
def _remove(self, message):
|
||||
words = message.split()
|
||||
return " ".join(w for w in words if w.lower() not in STOPWORDS)
|
||||
|
||||
|
||||
class PunctuationRemover:
|
||||
def fit(self, X, y=None):
|
||||
return self
|
||||
|
||||
def transform(self, X):
|
||||
return np.array([re.sub(r"[^\w\s]", " ", msg) for msg in X])
|
||||
43
models/features.py
Normal file
43
models/features.py
Normal file
@@ -0,0 +1,43 @@
|
||||
import numpy as np
|
||||
from sklearn.feature_extraction import DictVectorizer
|
||||
from sklearn.linear_model import LogisticRegression
|
||||
from sklearn.pipeline import Pipeline
|
||||
|
||||
|
||||
class FeatureExtractor:
|
||||
def fit(self, X, y=None):
|
||||
return self
|
||||
|
||||
def transform(self, X):
|
||||
return [self.extract_features(msg) for msg in X]
|
||||
|
||||
def extract_features(self, message):
|
||||
return {
|
||||
"contains_free": int("free" in message.lower()),
|
||||
"num_exclamations": message.count("!"),
|
||||
"length": len(message),
|
||||
}
|
||||
|
||||
|
||||
class FeatureClassifier:
|
||||
def fit(self, X, y):
|
||||
self._pipeline = Pipeline([
|
||||
("features", FeatureExtractor()),
|
||||
("vectorizer", DictVectorizer()),
|
||||
("classifier", LogisticRegression(max_iter=1000)),
|
||||
])
|
||||
y_binary = (np.array(y) == "spam").astype(int)
|
||||
self._pipeline.fit(X, y_binary)
|
||||
return self
|
||||
|
||||
def predict(self, X):
|
||||
y_binary = self._pipeline.predict(X)
|
||||
return np.where(y_binary == 1, "spam", "ham")
|
||||
|
||||
def feature_weights(self, top_n=10):
|
||||
vectorizer = self._pipeline.named_steps["vectorizer"]
|
||||
classifier = self._pipeline.named_steps["classifier"]
|
||||
names = vectorizer.get_feature_names_out()
|
||||
weights = classifier.coef_[0]
|
||||
pairs = sorted(zip(names, weights), key=lambda x: abs(x[1]), reverse=True)
|
||||
return pairs[:top_n]
|
||||
12
models/manual.py
Normal file
12
models/manual.py
Normal file
@@ -0,0 +1,12 @@
|
||||
import numpy as np
|
||||
|
||||
|
||||
class ManualClassifier:
|
||||
def fit(self, X, y):
|
||||
return self
|
||||
|
||||
def predict(self, X):
|
||||
return np.array([self.predict_one(msg) for msg in X])
|
||||
|
||||
def predict_one(self, message):
|
||||
return "ham"
|
||||
Reference in New Issue
Block a user