Streamline code

This commit is contained in:
Chris Proctor
2026-06-08 09:43:29 -04:00
parent feeae0352b
commit 5f6f171369
3 changed files with 30 additions and 38 deletions

View File

@@ -1,41 +1,41 @@
from collections import Counter from collections import Counter
import numpy as np import numpy as np
from sklearn.base import BaseEstimator, ClassifierMixin
from sklearn.feature_extraction import DictVectorizer from sklearn.feature_extraction import DictVectorizer
from sklearn.linear_model import LogisticRegression from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline from sklearn.pipeline import Pipeline
from classifiers.feature_classifier import FeatureExtractor
from cleaning.transformers import LowercaseTransformer, PunctuationRemover from cleaning.transformers import LowercaseTransformer, PunctuationRemover
class BagOfWordsClassifier(BaseEstimator, ClassifierMixin): class FeatureExtractor:
def __init__(self): def fit(self, X, y=None):
self.cleaning = Pipeline([ 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()), ("lowercase", LowercaseTransformer()),
("punctuation", PunctuationRemover()), ("punctuation", PunctuationRemover()),
]) ("features", FeatureExtractor()),
def fit(self, X, y):
X_clean = self.cleaning.fit_transform(X)
self._pipeline = Pipeline([
("features", FeatureExtractor(self.extract_features)),
("vectorizer", DictVectorizer()), ("vectorizer", DictVectorizer()),
("classifier", LogisticRegression(max_iter=1000)), ("classifier", LogisticRegression(max_iter=1000)),
]) ])
y_binary = (np.array(y) == "spam").astype(int) y_binary = (np.array(y) == "spam").astype(int)
self._pipeline.fit(X_clean, y_binary) self._pipeline.fit(X, y_binary)
return self return self
def predict(self, X): def predict(self, X):
X_clean = self.cleaning.transform(X) y_binary = self._pipeline.predict(X)
y_binary = self._pipeline.predict(X_clean)
return np.where(y_binary == 1, "spam", "ham") return np.where(y_binary == 1, "spam", "ham")
def extract_features(self, message):
return dict(Counter(message.split()))
def feature_weights(self, top_n=10): def feature_weights(self, top_n=10):
vectorizer = self._pipeline.named_steps["vectorizer"] vectorizer = self._pipeline.named_steps["vectorizer"]
classifier = self._pipeline.named_steps["classifier"] classifier = self._pipeline.named_steps["classifier"]

View File

@@ -1,30 +1,30 @@
import numpy as np import numpy as np
from sklearn.base import BaseEstimator, ClassifierMixin, TransformerMixin
from sklearn.feature_extraction import DictVectorizer from sklearn.feature_extraction import DictVectorizer
from sklearn.linear_model import LogisticRegression from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline from sklearn.pipeline import Pipeline
class FeatureExtractor(BaseEstimator, TransformerMixin): class FeatureExtractor:
def __init__(self, extract_fn):
self.extract_fn = extract_fn
def fit(self, X, y=None): def fit(self, X, y=None):
return self return self
def transform(self, X): def transform(self, X):
return [self.extract_fn(msg) for msg in 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(BaseEstimator, ClassifierMixin): class FeatureClassifier:
def __init__(self, C=1.0):
self.C = C
def fit(self, X, y): def fit(self, X, y):
self._pipeline = Pipeline([ self._pipeline = Pipeline([
("features", FeatureExtractor(self.extract_features)), ("features", FeatureExtractor()),
("vectorizer", DictVectorizer()), ("vectorizer", DictVectorizer()),
("classifier", LogisticRegression(C=self.C, max_iter=1000)), ("classifier", LogisticRegression(max_iter=1000)),
]) ])
y_binary = (np.array(y) == "spam").astype(int) y_binary = (np.array(y) == "spam").astype(int)
self._pipeline.fit(X, y_binary) self._pipeline.fit(X, y_binary)
@@ -34,13 +34,6 @@ class FeatureClassifier(BaseEstimator, ClassifierMixin):
y_binary = self._pipeline.predict(X) y_binary = self._pipeline.predict(X)
return np.where(y_binary == 1, "spam", "ham") return np.where(y_binary == 1, "spam", "ham")
def extract_features(self, message):
return {
"contains_free": int("free" in message.lower()),
"num_exclamations": message.count("!"),
"length": len(message),
}
def feature_weights(self, top_n=10): def feature_weights(self, top_n=10):
vectorizer = self._pipeline.named_steps["vectorizer"] vectorizer = self._pipeline.named_steps["vectorizer"]
classifier = self._pipeline.named_steps["classifier"] classifier = self._pipeline.named_steps["classifier"]

View File

@@ -1,8 +1,7 @@
import numpy as np import numpy as np
from sklearn.base import BaseEstimator, ClassifierMixin
class ManualClassifier(BaseEstimator, ClassifierMixin): class ManualClassifier:
def fit(self, X, y): def fit(self, X, y):
return self return self