Views
No views yet
| Class | Precision | Recall | F1-Score | Support |
|---|---|---|---|---|
| F | 0.8361 | 0.7876 | 0.8111 | 965 |
| R | 0.5978 | 0.5959 | 0.5969 | 641 |
| N | 0.7556 | 0.8104 | 0.7821 | 828 |
| M | 0.7450 | 0.7485 | 0.7468 | 851 |
| S | 0.2456 | 0.2222 | 0.2333 | 63 |
pip install huggingface_hub scikit-learn numpy scipy1import joblib
2import numpy as np
3import re
4from scipy.special import softmax
5from scipy.sparse import hstack, csr_matrix
6from huggingface_hub import hf_hub_download
7
8# Configuration
9REPO_NAME = "Kenny-lalek/algerian-darija-misinformation-svm"
10
11# Load model artifacts
12print("Loading model from Hugging Face...")
13tfidf_vectorizer = joblib.load(
14 hf_hub_download(repo_id=REPO_NAME, filename="tfidf_vectorizer.joblib")
15)
16svm_model = joblib.load(
17 hf_hub_download(repo_id=REPO_NAME, filename="svm_model.joblib")
18)
19metadata_scaler = joblib.load(
20 hf_hub_download(repo_id=REPO_NAME, filename="metadata_scaler.joblib")
21)
22print("Model loaded successfully!")
23
24# Preprocessing function
25def remove_diacritics(text):
26 """Remove Arabic diacritics (tashkeel)"""
27 arabic_diacritics = re.compile("""
28 ّ | # Tashdid
29 َ | # Fatha
30 ً | # Tanwin Fath
31 ُ | # Damma
32 ٌ | # Tanwin Damm
33 ِ | # Kasra
34 ٍ | # Tanwin Kasr
35 ْ | # Sukun
36 ـ # Tatwil/Kashida
37 """, re.VERBOSE)
38 return re.sub(arabic_diacritics, '', text)
39
40def preprocess_text(text):
41 """
42 Preprocess text according to training specifications
43 - Remove diacritics
44 - Normalize whitespace
45 """
46 if text is None or text == "":
47 return ""
48
49 text = str(text)
50 text = remove_diacritics(text)
51 text = ' '.join(text.split()) # Normalize whitespace
52
53 return text.strip()
54
55def extract_metadata_features(text):
56 """
57 Extract metadata features for the enhanced model
58 Returns a numpy array of shape (1, 6)
59 """
60 # Word count
61 word_count = len(text.split())
62
63 # Punctuation density
64 punctuation_chars = ".,!?;:،؛"
65 punctuation_count = sum(1 for char in text if char in punctuation_chars)
66 punctuation_density = punctuation_count / len(text) if len(text) > 0 else 0
67
68 # Exclamation and question counts
69 exclamation_count = text.count('!')
70 question_count = text.count('?') + text.count('؟') # Include Arabic question mark
71
72 # All caps ratio
73 letters = [c for c in text if c.isalpha()]
74 all_caps_ratio = sum(1 for c in letters if c.isupper()) / len(letters) if len(letters) > 0 else 0
75
76 # Emoji count (simplified - would need emoji library for full detection)
77 emoji_count = 0
78
79 return np.array([[word_count, punctuation_density, exclamation_count,
80 question_count, all_caps_ratio, emoji_count]])
81
82def predict(text):
83 """
84 Predict the misinformation class for input text
85
86 Args:
87 text (str): Input text in Algerian Darija
88
89 Returns:
90 dict: Dictionary containing:
91 - predicted_label: The predicted class (F, R, N, M, or S)
92 - confidence: Confidence score (0-1)
93 - probabilities: Dictionary of probabilities for each class
94 """
95 # Step 1: Preprocess text
96 processed_text = preprocess_text(text)
97
98 # Step 2: Extract TF-IDF features
99 text_features = tfidf_vectorizer.transform([processed_text])
100
101 # Step 3: Extract and normalize metadata features
102 metadata = extract_metadata_features(processed_text)
103 metadata_scaled = metadata_scaler.transform(metadata)
104
105 # Step 4: Combine TF-IDF and metadata features
106 features = hstack([text_features, csr_matrix(metadata_scaled)])
107
108 # Step 5: Predict using SVM
109 prediction = svm_model.predict(features)[0]
110
111 # Step 6: Get decision function scores and convert to probabilities
112 # Note: SVM doesn't have predict_proba by default, so we use decision_function
113 decision_scores = svm_model.decision_function(features)[0]
114 probabilities = softmax(decision_scores) # Convert to pseudo-probabilities
115
116 # Step 7: Format results
117 classes = ['F', 'R', 'N', 'M', 'S']
118 result = {
119 'predicted_label': prediction,
120 'confidence': float(np.max(probabilities)),
121 'probabilities': {
122 class_label: float(prob)
123 for class_label, prob in zip(classes, probabilities)
124 }
125 }
126
127 return result
128
129# Example usage
130if __name__ == "__main__":
131 # Test examples
132 test_texts = [
133 "الحكومة الجزائرية تعلن عن إجراءات جديدة لدعم الاقتصاد",
134 "هذا الخبر كذب ومفبرك بالكامل!",
135 "تقرير رسمي من وزارة الصحة حول الوضع الصحي"
136 ]
137
138 print("Testing Algerian Darija Misinformation Detection (SVM)")
139
140 for i, text in enumerate(test_texts, 1):
141 print(f"\nExample {i}:")
142 print(f"Text: {text}")
143
144 result = predict(text)
145
146 print(f"Predicted Label: {result['predicted_label']}")
147 print(f"Confidence: {result['confidence']:.4f}")
148 print(f"Class Probabilities:")
149 for label, prob in result['probabilities'].items():
150 print(f" {label}: {prob:.4f}")AlgerianDarijaSVMClassifier wrapper class:1from huggingface_hub import hf_hub_download
2import joblib
3import numpy as np
4import re
5from scipy.special import softmax
6from scipy.sparse import hstack, csr_matrix
7
8class AlgerianDarijaSVMClassifier:
9 """
10 Wrapper class for Algerian Darija Misinformation Detection using SVM
11
12 This class handles model loading, text preprocessing, feature extraction,
13 and prediction in a convenient interface.
14 """
15
16 def __init__(self, repo_name, model_type="enhanced"):
17 """
18 Initialize the classifier
19
20 Args:
21 repo_name (str): HuggingFace repository name
22 model_type (str): "enhanced" (with metadata) or "baseline" (text only)
23 """
24 self.repo_name = repo_name
25 self.model_type = model_type
26 self.classes = ['F', 'R', 'N', 'M', 'S']
27
28 print(f"Loading SVM model from {repo_name}...")
29
30 # Load TF-IDF vectorizer
31 self.tfidf_vectorizer = joblib.load(
32 hf_hub_download(repo_id=repo_name, filename="tfidf_vectorizer.joblib")
33 )
34
35 # Load SVM model
36 self.model = joblib.load(
37 hf_hub_download(repo_id=repo_name, filename="svm_model.joblib")
38 )
39
40 # Load metadata scaler if enhanced model
41 if model_type == "enhanced":
42 self.metadata_scaler = joblib.load(
43 hf_hub_download(repo_id=repo_name, filename="metadata_scaler.joblib")
44 )
45 else:
46 self.metadata_scaler = None
47
48 print("Model loaded successfully!")
49
50 def _remove_diacritics(self, text):
51 """Remove Arabic diacritics"""
52 arabic_diacritics = re.compile("""
53 ّ | # Tashdid
54 َ | # Fatha
55 ً | # Tanwin Fath
56 ُ | # Damma
57 ٌ | # Tanwin Damm
58 ِ | # Kasra
59 ٍ | # Tanwin Kasr
60 ْ | # Sukun
61 ـ # Tatwil/Kashida
62 """, re.VERBOSE)
63 return re.sub(arabic_diacritics, '', text)
64
65 def _preprocess_text(self, text):
66 """Preprocess text"""
67 if text is None or text == "":
68 return ""
69 text = str(text)
70 text = self._remove_diacritics(text)
71 text = ' '.join(text.split())
72 return text.strip()
73
74 def _extract_metadata_features(self, text):
75 """Extract metadata features"""
76 word_count = len(text.split())
77 punctuation_chars = ".,!?;:،؛"
78 punctuation_count = sum(1 for char in text if char in punctuation_chars)
79 punctuation_density = punctuation_count / len(text) if len(text) > 0 else 0
80 exclamation_count = text.count('!')
81 question_count = text.count('?') + text.count('؟')
82 letters = [c for c in text if c.isalpha()]
83 all_caps_ratio = sum(1 for c in letters if c.isupper()) / len(letters) if len(letters) > 0 else 0
84 emoji_count = 0
85 return np.array([[word_count, punctuation_density, exclamation_count,
86 question_count, all_caps_ratio, emoji_count]])
87
88 def predict(self, text):
89 """
90 Predict misinformation class for a single text
91
92 Args:
93 text (str): Input text in Algerian Darija
94
95 Returns:
96 dict: Prediction results with label, confidence, and probabilities
97 """
98 # Preprocess
99 processed_text = self._preprocess_text(text)
100
101 # Extract TF-IDF features
102 text_features = self.tfidf_vectorizer.transform([processed_text])
103
104 # Add metadata if enhanced model
105 if self.model_type == "enhanced":
106 metadata = self._extract_metadata_features(processed_text)
107 metadata_scaled = self.metadata_scaler.transform(metadata)
108 features = hstack([text_features, csr_matrix(metadata_scaled)])
109 else:
110 features = text_features
111
112 # Predict
113 prediction = self.model.predict(features)[0]
114 decision_scores = self.model.decision_function(features)[0]
115 probabilities = softmax(decision_scores)
116
117 return {
118 'predicted_label': prediction,
119 'confidence': float(np.max(probabilities)),
120 'probabilities': {
121 class_label: float(prob)
122 for class_label, prob in zip(self.classes, probabilities)
123 }
124 }
125
126 def predict_batch(self, texts):
127 """
128 Predict misinformation classes for multiple texts
129
130 Args:
131 texts (list): List of input texts
132
133 Returns:
134 list: List of prediction dictionaries
135 """
136 return [self.predict(text) for text in texts]
137
138# Usage example
139classifier = AlgerianDarijaSVMClassifier(
140 repo_name="Kenny-lalek/algerian-darija-misinformation-svm",
141 model_type="enhanced"
142)
143
144# Single prediction
145result = classifier.predict("النظام المافيوي العصاباباتي")
146print(f"Predicted: {result['predicted_label']}")
147print(f"Confidence: {result['confidence']:.4f}")
148
149# Batch prediction
150texts = [
151 "الحكومة تعلن عن إجراءات جديدة",
152 "هذا خبر كاذب ومفبرك",
153 "تقرير رسمي من الوزارة"
154]
155results = classifier.predict_batch(texts)
156for text, result in zip(texts, results):
157 print(f"{text} -> {result['predicted_label']}")weight[class] = n_samples / (n_classes * n_samples_per_class)