rodrigoaraujorosa commited on
Commit
f03f4d9
·
0 Parent(s):

Initial commit with local files

Browse files
Files changed (9) hide show
  1. .gitattributes +1 -0
  2. LICENSE +19 -0
  3. README.md +362 -0
  4. config.json +185 -0
  5. melhor_modelo.pkl +3 -0
  6. model_card.md +337 -0
  7. requirements.txt +4 -0
  8. scaler.pkl +3 -0
  9. tfidf_vectorizer.pkl +3 -0
.gitattributes ADDED
@@ -0,0 +1 @@
 
 
1
+ *.pkl filter=lfs diff=lfs merge=lfs -text
LICENSE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2018 The Python Packaging Authority
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
README.md ADDED
@@ -0,0 +1,362 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language: pt
3
+ license: mit
4
+ tags:
5
+ - text-classification
6
+ - clickbait-detection
7
+ - portuguese
8
+ - sklearn
9
+ - random-forest
10
+ datasets:
11
+ - custom
12
+ metrics:
13
+ - accuracy
14
+ - f1
15
+ - precision
16
+ - recall
17
+ model-index:
18
+ - name: Detector de Clickbait BR
19
+ results:
20
+ - task:
21
+ type: text-classification
22
+ name: Text Classification
23
+ metrics:
24
+ - type: accuracy
25
+ value: 0.970
26
+ name: Accuracy
27
+ - type: f1
28
+ value: 0.972
29
+ name: F1 Score
30
+ - type: precision
31
+ value: 0.982
32
+ name: Precision
33
+ - type: recall
34
+ value: 0.961
35
+ name: Recall
36
+ ---
37
+
38
+ # 🔍 Detector de Clickbait BR - Model
39
+
40
+ Modelo de Machine Learning para detecção de manchetes clickbait em português brasileiro.
41
+
42
+ ## 📊 Descrição
43
+
44
+ Este modelo foi treinado para classificar manchetes de notícias em duas categorias:
45
+ - **Não-Clickbait** (0): Manchetes informativas e objetivas
46
+ - **Clickbait** (1): Manchetes sensacionalistas e enganosas
47
+
48
+ ## 🎯 Performance
49
+
50
+ | Métrica | Valor |
51
+ |---------|-------|
52
+ | **Acurácia** | 97.1% |
53
+ | **Precisão** | 98.3% |
54
+ | **Recall** | 96.2% |
55
+ | **F1-Score** | 97.2% |
56
+
57
+ ### 📈 Comparação de Modelos
58
+
59
+ Durante o desenvolvimento, foram treinados e comparados 9 modelos diferentes:
60
+
61
+ |Ranking | Modelo | Acurácia | F1-Score |
62
+ |--------|--------------------|----------|----------|
63
+ | 🥇 |**RF Otimizado** 🏆 | 0.970635 | 0.972112 |
64
+ | 🥈 |Random Forest | 0.970110 | 0.971543 |
65
+ | 🥉 |Stacking | 0.968013 | 0.969757 |
66
+ | 4º |SVM | 0.966964 | 0.968453 |
67
+ | 5º |Voting (Soft) | 0.966439 | 0.967936 |
68
+ | 6º |Voting (Hard) | 0.965915 | 0.967287 |
69
+ | 7º |Regressão Logística | 0.959622 | 0.961131 |
70
+ | 8º |Naive Bayes | 0.907708 | 0.915870 |
71
+ | 9º |Baseline | 0.467750 | 0.000000 |
72
+
73
+ *🏆 = Modelo final publicado*
74
+
75
+ ## 🧠 Arquitetura
76
+
77
+ ### Modelo Final: Random Forest Otimizado
78
+
79
+ **Características:**
80
+ - **Tipo:** RandomForestClassifier (Scikit-learn)
81
+ - **Otimização:** RandomizedSearchCV
82
+ - **Iterações de busca:** 50 combinações testadas
83
+ - **Validação cruzada:** 5-fold StratifiedKFold
84
+ - **Métrica de otimização:** F1-Score
85
+
86
+ **Hiperparâmetros Otimizados:**
87
+ O modelo testou combinações de:
88
+ - `n_estimators`: [100, 200, 300, 500]
89
+ - `max_depth`: [None, 10, 20, 30, 50]
90
+ - `min_samples_split`: [2, 5, 10]
91
+ - `min_samples_leaf`: [1, 2, 4]
92
+ - `max_features`: ['sqrt', 'log2', None]
93
+ - `bootstrap`: [True, False]
94
+
95
+ **Features de Entrada:** 204 dimensões
96
+
97
+ **1. TF-IDF Features (200 dimensões):**
98
+ - Vocabulário: 5.000 termos mais frequentes
99
+ - N-grams: unigramas e bigramas (1-2)
100
+ - Min Document Frequency: 2
101
+ - Analyzer: word-level
102
+
103
+ **2. Features Numéricas (4 dimensões):**
104
+ - `word_count`: Número de palavras na manchete
105
+ - `char_count`: Número de caracteres total
106
+ - `exclamation_count`: Quantidade de pontos de exclamação (!)
107
+ - `question_count`: Quantidade de pontos de interrogação (?)
108
+
109
+ **Pré-processamento:**
110
+ - Normalização: StandardScaler (features numéricas)
111
+ - Text processing: lowercase, stopwords removal (português), tokenização
112
+ - TF-IDF vectorization aplicada ao texto processado
113
+
114
+ ## 📚 Dataset
115
+
116
+ - **Total**: 9.532 manchetes
117
+ - **Fonte**: Portais de notícias brasileiros (diversos domínios)
118
+ - **Distribuição de Classes**:
119
+ - Não-Clickbait: 4.457 (46.76%)
120
+ - Clickbait: 5.075 (53.24%)
121
+ - **Split**: 80% treino (7.625) / 20% teste (1.907)
122
+ - **Estratégia de Validação**: 5-fold cross-validation
123
+ - **Random State**: 42 (reprodutibilidade garantida)
124
+
125
+ ### Exemplos do Dataset
126
+
127
+ **Não-Clickbait:**
128
+ - "Banco Central mantém a taxa Selic em 13,75% ao ano"
129
+ - "Governo aprova reforma tributária no Congresso"
130
+ - "Estudo da USP revela novos dados sobre mudanças climáticas"
131
+
132
+ **Clickbait:**
133
+ - "O pesadelo dos investidores: a decisão do Banco Central que vai destruir seus lucros!"
134
+ - "Descubra o segredo para emagrecer 10kg em 7 dias!!!"
135
+ - "Este truque simples vai MUDAR sua vida para sempre"
136
+
137
+ ## 🚀 Como Usar
138
+
139
+ ### Instalação
140
+
141
+ ```bash
142
+ pip install scikit-learn nltk pandas numpy huggingface_hub
143
+ ```
144
+
145
+ ### Carregar Modelo
146
+
147
+ ```python
148
+ from huggingface_hub import hf_hub_download
149
+ import pickle
150
+
151
+ # Download dos arquivos
152
+ modelo_path = hf_hub_download(
153
+ repo_id="rodrigoaraujorosa/detector-clickbait-br-model",
154
+ filename="melhor_modelo.pkl"
155
+ )
156
+ tfidf_path = hf_hub_download(
157
+ repo_id="rodrigoaraujorosa/detector-clickbait-br-model",
158
+ filename="tfidf_vectorizer.pkl"
159
+ )
160
+ scaler_path = hf_hub_download(
161
+ repo_id="rodrigoaraujorosa/detector-clickbait-br-model",
162
+ filename="scaler.pkl"
163
+ )
164
+
165
+ # Carregar
166
+ with open(modelo_path, 'rb') as f:
167
+ modelo = pickle.load(f)
168
+ with open(tfidf_path, 'rb') as f:
169
+ tfidf = pickle.load(f)
170
+ with open(scaler_path, 'rb') as f:
171
+ scaler = pickle.load(f)
172
+ ```
173
+
174
+ ### Fazer Predição
175
+
176
+ ```python
177
+ import re
178
+ import numpy as np
179
+ import pandas as pd
180
+ from nltk.corpus import stopwords
181
+
182
+ # Configurar
183
+ stop_words = set(stopwords.words('portuguese'))
184
+
185
+ def preprocessar_texto(texto):
186
+ texto = texto.lower()
187
+ texto_limpo = re.sub(r'[^\w\s]', ' ', texto)
188
+ palavras = [p for p in texto_limpo.split() if p not in stop_words and p.strip()]
189
+ return ' '.join(palavras)
190
+
191
+ def extrair_features_numericas(texto):
192
+ return [len(texto.split()), len(texto), texto.count('!'), texto.count('?')]
193
+
194
+ def prever(texto):
195
+ # Features numéricas
196
+ features_num = extrair_features_numericas(texto)
197
+
198
+ # TF-IDF
199
+ texto_proc = preprocessar_texto(texto)
200
+ tfidf_feat = tfidf.transform([texto_proc]).toarray()
201
+
202
+ # Normalizar
203
+ features_scaled = scaler.transform([features_num])
204
+
205
+ # Combinar
206
+ features_final = np.hstack([tfidf_feat, features_scaled])
207
+
208
+ # Criar DataFrame com nomes de features
209
+ feature_names = list(tfidf.get_feature_names_out()) + ['word_count', 'char_count', 'exclamation_count', 'question_count']
210
+ features_df = pd.DataFrame(features_final, columns=feature_names)
211
+
212
+ # Predição
213
+ pred = modelo.predict(features_df)[0]
214
+ prob = modelo.predict_proba(features_df)[0]
215
+
216
+ return {
217
+ 'classe': 'Clickbait' if pred == 1 else 'Não-Clickbait',
218
+ 'confianca': float(prob[pred]),
219
+ 'probabilidades': {
220
+ 'nao_clickbait': float(prob[0]),
221
+ 'clickbait': float(prob[1])
222
+ }
223
+ }
224
+
225
+ # Exemplo
226
+ resultado = prever("Você não vai acreditar no que aconteceu!")
227
+ print(resultado)
228
+ # {'classe': 'Clickbait', 'confianca': 0.97, 'probabilidades': {'nao_clickbait': 0.03, 'clickbait': 0.97}}
229
+ ```
230
+
231
+ ## 📝 Exemplos de Uso
232
+
233
+ ```python
234
+ # Não-Clickbait
235
+ prever("Banco Central mantém a taxa Selic em 13,75% ao ano")
236
+ # {'classe': 'Não-Clickbait', 'confianca': 0.98}
237
+
238
+ prever("Governo aprova reforma tributária no Congresso")
239
+ # {'classe': 'Não-Clickbait', 'confianca': 0.96}
240
+
241
+ # Clickbait
242
+ prever("Descubra o segredo que ninguém te conta!!!")
243
+ # {'classe': 'Clickbait', 'confianca': 0.99}
244
+
245
+ prever("Este truque simples vai MUDAR sua vida para sempre")
246
+ # {'classe': 'Clickbait', 'confianca': 0.95}
247
+ ```
248
+
249
+ ## 🔬 Metodologia
250
+
251
+ ### 1. Coleta de Dados
252
+ - Raw Dataset: 10.565 manchetes iniciais coletadas
253
+ - 634 duplicatas removidas (6.0%)
254
+ - Dataset final: 9.532 manchetes únicas
255
+ - Balanceamento ~50/50 entre classes
256
+
257
+ ### 2. Pré-processamento
258
+ - **Limpeza:** Remoção de duplicatas
259
+ - **Text processing:**
260
+ - Conversão para lowercase
261
+ - Remoção de pontuação (após extração de features)
262
+ - Remoção de stopwords em português (NLTK)
263
+ - Tokenização
264
+ - Stemming: não aplicado (testes mostraram performance similar)
265
+
266
+ ### 3. Engenharia de Features
267
+ - **TF-IDF Vectorization:**
268
+ - Max features: 5.000 termos
269
+ - N-grams: 1-2 (unigramas e bigramas)
270
+ - Min DF: 2 (termo aparece em ≥2 documentos)
271
+ - Result: 200 features mais relevantes selecionadas
272
+
273
+ - **Features Numéricas:**
274
+ - Contagem de palavras, caracteres, pontuação
275
+ - Normalização com StandardScaler
276
+ - Total: 4 features numéricas
277
+
278
+ ### 4. Treinamento
279
+ - **Modelos testados:** 9 (baseline + 4 individuais + RF otimizado + 3 ensembles)
280
+ - **Otimização:** RandomizedSearchCV
281
+ - 50 iterações
282
+ - 5-fold cross-validation
283
+ - Busca em espaço de 576 combinações possíveis
284
+ - **Hardware:** CPU (tempo de treinamento: ~22 minutos)
285
+ - **Best model selection:** Baseado em F1-Score
286
+
287
+ ### 5. Avaliação
288
+ - **Métricas:** Accuracy, Precision, Recall, F1-Score
289
+ - **Test set:** 1.907 exemplos (20% do dataset)
290
+ - **Validation:** 5-fold Stratified Cross-Validation
291
+ - **Análise de erros:** Identificação de falsos positivos/negativos
292
+
293
+ ## 🏆 Por que Random Forest Otimizado?
294
+
295
+ ### ✅ Vantagens:
296
+
297
+ 1. **Performance Superior:** 97.2% F1-Score (melhor entre 9 modelos)
298
+ 2. **Alta Precisão:** 98.3% - minimiza falsos positivos
299
+ 3. **Bom Recall:** 96.2% - captura maioria dos clickbaits
300
+ 4. **Robusto:** Ensemble de 100-500 árvores (reduz overfitting)
301
+ 5. **Feature Importance:** Identifica features mais relevantes
302
+ 6. **Generalização:** Cross-validation confirma estabilidade
303
+ 7. **Não-linear:** Captura interações complexas entre features
304
+ 8. **Menos sensível a outliers:** Natureza ensemble do RF
305
+
306
+ ### 📊 Comparação com Alternativas:
307
+
308
+ - **vs. Stacking (3º lugar):** +0.2% F1, mais simples de interpretar
309
+ - **vs. SVM (4º):** +0.4% F1, mais rápido para treinar
310
+ - **vs. Voting Soft (5º):** +0.4% F1, modelo único (mais fácil deploy)
311
+ - **vs. Regressão Logística (7º):** +1.1% F1, captura não-linearidades
312
+ -
313
+ ## ⚠️ Limitações
314
+
315
+ - ✅ **Idioma:** Apenas português brasileiro
316
+ - ✅ **Domínio:** Otimizado para manchetes de notícias
317
+ - ⚠️ **Generalização:** Pode ter performance reduzida em outros domínios (e-commerce, redes sociais, etc.)
318
+ - ⚠️ **Contexto:** Não considera contexto temporal ou autoria
319
+ - ⚠️ **Sarcasmo/Ironia:** Pode ter dificuldade com textos irônicos
320
+
321
+ ## 📈 Melhorias Futuras
322
+
323
+ - [ ] Aumentar dataset (→10k+ exemplos)
324
+ - [ ] Testar modelos Transformer (BERTimbau, mBERT)
325
+ - [ ] Adicionar features contextuais (fonte, timestamp, autor)
326
+ - [ ] Expandir para outros idiomas (espanhol, inglês)
327
+ - [ ] Fine-tuning com dados mais recentes
328
+ - [ ] Deploy em produção com monitoramento de drift
329
+ - [ ] A/B testing de modelos em produção
330
+
331
+ ## 📄 Licença
332
+
333
+ MIT License - Uso livre para fins acadêmicos e comerciais.
334
+
335
+ ## 🤝 Citação
336
+
337
+ ```bibtex
338
+ @misc{detector-clickbait-br-model,
339
+ author = {Rodrigo de Araujo Rosa},
340
+ title = {Detector de Clickbait BR: Modelo de ML para Detecção de Clickbait em Português},
341
+ year = {2025},
342
+ publisher = {Hugging Face},
343
+ journal = {Hugging Face Model Hub},
344
+ howpublished = {\url{https://huggingface.co/rodrigoaraujorosa/detector-clickbait-br-model}}
345
+ }
346
+ ```
347
+
348
+ ### APA
349
+ ```
350
+ ROSA, Rodrigo de Araujo. (2025). Detector de Clickbait BR: Random Forest Classifier for Brazilian Portuguese Clickbait Detection. Hugging Face Model Hub. https://huggingface.co/rodrigoaraujorosa/detector-clickbait-br-model
351
+ ```
352
+
353
+ ## 🔗 Links
354
+
355
+ - **🚀 Demo Interativa:** [Hugging Face Space](https://huggingface.co/spaces/rodrigoaraujorosa/detector-clickbait-br)
356
+ - **💻 Código Fonte:** [GitHub Repository](https://github.com/rodrigoaraujorosa/detector-clickbait-br)
357
+ - **📊 Notebooks:** [Análise Exploratória + Treinamento](https://github.com/rodrigoaraujorosa/detector-clickbait-br/notebooks)
358
+ - **📚 Raw Dataset:**
359
+ - **📧 Contato:** rodrigoaraujo.r@gmail.com
360
+ - **🔗LinkedIn:** [Rodrigo de Araujo Rosa](https://www.linkedin.com/in/rodrigoaraujorosa/)
361
+
362
+ ---
config.json ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_name": "detector-clickbait-br-model",
3
+ "version": "1.0.0",
4
+ "model_type": "sklearn",
5
+ "task": "text-classification",
6
+ "framework": "scikit-learn",
7
+ "sklearn_version": "1.7.2",
8
+ "language": "pt",
9
+ "license": "mit",
10
+ "pipeline": {
11
+ "preprocessor": "tfidf_vectorizer.pkl",
12
+ "scaler": "scaler.pkl",
13
+ "model": "melhor_modelo.pkl"
14
+ },
15
+ "model_architecture": {
16
+ "type": "Random Forest Classifier (Optimized)",
17
+ "base_model": "RandomForestClassifier",
18
+ "optimization": {
19
+ "method": "RandomizedSearchCV",
20
+ "n_iter": 50,
21
+ "cv_folds": 5,
22
+ "scoring": "f1",
23
+ "random_state": 42
24
+ },
25
+ "hyperparameters": {
26
+ "note": "Optimized via RandomizedSearchCV",
27
+ "search_space": {
28
+ "n_estimators": [100, 200, 300, 500],
29
+ "max_depth": ["None", 10, 20, 30, 50],
30
+ "min_samples_split": [2, 5, 10],
31
+ "min_samples_leaf": [1, 2, 4],
32
+ "max_features": ["sqrt", "log2", "None"],
33
+ "bootstrap": [true, false]
34
+ }
35
+ },
36
+ "best_params": "See model object for details"
37
+ },
38
+ "features": {
39
+ "tfidf": {
40
+ "max_features": 5000,
41
+ "ngram_range": [1, 2],
42
+ "min_df": 2,
43
+ "vocabulary_size": 200,
44
+ "analyzer": "word"
45
+ },
46
+ "numeric": [
47
+ "word_count",
48
+ "char_count",
49
+ "exclamation_count",
50
+ "question_count"
51
+ ],
52
+ "total_features": 204
53
+ },
54
+ "dataset": {
55
+ "total_samples": 9532,
56
+ "train_samples": 7625,
57
+ "test_samples": 1907,
58
+ "train_test_split": 0.8,
59
+ "random_state": 42,
60
+ "stratified": true,
61
+ "class_distribution": {
62
+ "non_clickbait": {
63
+ "count": 4457,
64
+ "percentage": 46.76
65
+ },
66
+ "clickbait": {
67
+ "count": 5075,
68
+ "percentage": 53.24
69
+ }
70
+ }
71
+ },
72
+ "performance": {
73
+ "test_set": {
74
+ "accuracy": 0.9706,
75
+ "precision": 0.9829,
76
+ "recall": 0.9616,
77
+ "f1_score": 0.9721,
78
+ "note": "Best performing model among 9 tested"
79
+ },
80
+ "cross_validation": {
81
+ "cv_folds": 5,
82
+ "cv_strategy": "StratifiedKFold",
83
+ "note": "Used during RandomizedSearchCV"
84
+ }
85
+ },
86
+ "classes": {
87
+ "0": "Não-Clickbait",
88
+ "1": "Clickbait"
89
+ },
90
+ "preprocessing": {
91
+ "text": {
92
+ "lowercase": true,
93
+ "remove_stopwords": true,
94
+ "stopwords_language": "portuguese",
95
+ "stemming": false,
96
+ "remove_punctuation": false,
97
+ "note": "Punctuation preserved for feature extraction"
98
+ },
99
+ "numeric_features": {
100
+ "scaler": "StandardScaler",
101
+ "features_scaled": [
102
+ "word_count",
103
+ "char_count",
104
+ "exclamation_count",
105
+ "question_count"
106
+ ]
107
+ }
108
+ },
109
+ "model_comparison": {
110
+ "models_tested": 9,
111
+ "ranking_by_f1": [
112
+ {
113
+ "rank": 1,
114
+ "model": "RF Otimizado",
115
+ "f1_score": 0.9721,
116
+ "accuracy": 0.9706
117
+ },
118
+ {
119
+ "rank": 2,
120
+ "model": "Random Forest",
121
+ "f1_score": 0.9715,
122
+ "accuracy": 0.9701
123
+ },
124
+ {
125
+ "rank": 3,
126
+ "model": "Stacking",
127
+ "f1_score": 0.9698,
128
+ "accuracy": 0.9680
129
+ },
130
+ {
131
+ "rank": 4,
132
+ "model": "SVM",
133
+ "f1_score": 0.9685,
134
+ "accuracy": 0.9670
135
+ },
136
+ {
137
+ "rank": 5,
138
+ "model": "Voting (Soft)",
139
+ "f1_score": 0.9679,
140
+ "accuracy": 0.9664
141
+ },
142
+ {
143
+ "rank": 6,
144
+ "model": "Voting (Hard)",
145
+ "f1_score": 0.9673,
146
+ "accuracy": 0.9659
147
+ },
148
+ {
149
+ "rank": 7,
150
+ "model": "Regressão Logística",
151
+ "f1_score": 0.9611,
152
+ "accuracy": 0.9596
153
+ },
154
+ {
155
+ "rank": 8,
156
+ "model": "Naive Bayes",
157
+ "f1_score": 0.9159,
158
+ "accuracy": 0.9077
159
+ },
160
+ {
161
+ "rank": 9,
162
+ "model": "Baseline",
163
+ "f1_score": 0.4678,
164
+ "accuracy": 0.0000
165
+ }
166
+ ]
167
+ },
168
+ "inference": {
169
+ "input_format": "string (headline text)",
170
+ "output_format": {
171
+ "prediction": "string (Clickbait or Não-Clickbait)",
172
+ "probabilities": {
173
+ "non_clickbait": "float",
174
+ "clickbait": "float"
175
+ }
176
+ },
177
+ "preprocessing_required": true
178
+ },
179
+ "training_info": {
180
+ "date": "2025",
181
+ "training_time": "~22 minutes (optimization included)",
182
+ "hardware": "CPU",
183
+ "random_state": 42
184
+ }
185
+ }
melhor_modelo.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:070ef58afcd8b3e96d103270c0ebdd3bba1fb759a146e62e2088c7530beddd9d
3
+ size 5601765
model_card.md ADDED
@@ -0,0 +1,337 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language: pt
3
+ license: mit
4
+ tags:
5
+ - text-classification
6
+ - clickbait-detection
7
+ - portuguese
8
+ - sklearn
9
+ - random-forest
10
+ datasets:
11
+ - custom
12
+ metrics:
13
+ - accuracy
14
+ - f1
15
+ - precision
16
+ - recall
17
+ model-index:
18
+ - name: Detector de Clickbait BR
19
+ results:
20
+ - task:
21
+ type: text-classification
22
+ name: Text Classification
23
+ dataset:
24
+ name: Custom Brazilian Headlines
25
+ type: custom
26
+ metrics:
27
+ - type: accuracy
28
+ value: 0.9706
29
+ name: Accuracy
30
+ - type: f1
31
+ value: 0.9721
32
+ name: F1 Score
33
+ - type: precision
34
+ value: 0.9829
35
+ name: Precision
36
+ - type: recall
37
+ value: 0.9616
38
+ name: Recall
39
+ ---
40
+
41
+ # Model Card: Detector de Clickbait BR
42
+
43
+ ## Model Details
44
+
45
+ ### Basic Information
46
+ - **Developed by:** [Rodrigo de Araujo Rosa] ([GitHub](https://github.com/rodrigoaraujorosa))
47
+ - **Model date:** November 2025
48
+ - **Model version:** 1.0.0
49
+ - **Model type:** Random Forest Classifier (Scikit-learn)
50
+ - **Language:** Portuguese (pt-BR)
51
+ - **License:** MIT
52
+ - **Repository:** [GitHub](https://github.com/rodrigoaraujorosa/detector-clickbait-br)
53
+
54
+ ### Model Description
55
+ Este modelo classifica manchetes de notícias em português brasileiro como **Clickbait** ou **Não-Clickbait**. Foi treinado usando Random Forest otimizado via RandomizedSearchCV, alcançando 97.2% de F1-Score.
56
+
57
+ ## Intended Use
58
+
59
+ ### Primary Intended Uses
60
+ - ✅ Detectar manchetes clickbait em portais de notícias brasileiros
61
+ - ✅ Filtrar conteúdo sensacionalista em agregadores de notícias
62
+ - ✅ Análise de qualidade jornalística
63
+ - ✅ Pesquisa acadêmica em detecção de clickbait
64
+
65
+ ### Primary Intended Users
66
+ - Desenvolvedores de agregadores de notícias
67
+ - Jornalistas e editores
68
+ - Pesquisadores em NLP e jornalismo
69
+ - Plataformas de fact-checking
70
+
71
+ ### Out-of-Scope Use Cases
72
+ - ❌ **Outros idiomas:** Modelo treinado apenas em português brasileiro
73
+ - ❌ **Outros domínios:** Não testado em e-commerce, redes sociais, marketing
74
+ - ❌ **Textos longos:** Otimizado para manchetes (5-20 palavras)
75
+ - ❌ **Classificação multiclasse:** Apenas binário (clickbait/não-clickbait)
76
+ - ❌ **Decisões automatizadas sem supervisão humana:** Recomenda-se validação manual
77
+
78
+ ## Training Data
79
+
80
+ ### Dataset Overview
81
+ - **Total de exemplos:** 9.532 manchetes únicas
82
+ - **Fonte:** Portais de notícias brasileiros diversos
83
+ - **Processo de limpeza:**
84
+ - 10,565 manchetes iniciais coletadas
85
+ - 634 duplicatas removidas (6.0%)
86
+
87
+ ### Class Distribution
88
+ | Classe | Quantidade | Percentual |
89
+ |--------|-----------|-----------|
90
+ | Não-Clickbait | 4.457 | 46.8% |
91
+ | Clickbait | 5.075 | 53.2% |
92
+
93
+ ### Train/Test Split
94
+ - **Treino:** 7.625 exemplos (80%)
95
+ - **Teste:** 1.907 exemplos (20%)
96
+ - **Estratégia:** Stratified split (random_state=42)
97
+ - **Validação:** 5-fold Stratified Cross-Validation
98
+
99
+ ### Data Collection
100
+ Manchetes coletadas de múltiplos portais brasileiros para garantir diversidade:
101
+ - Portais generalistas
102
+ - Portais especializados (economia, esportes, entretenimento)
103
+
104
+ ### Annotation Process
105
+ - Anotação manual por [especificar processo]
106
+ - Critérios de clickbait:
107
+ - Títulos sensacionalistas
108
+ - Uso excessivo de pontuação emocional
109
+ - Omissão de informações cruciais
110
+ - Linguagem hiperbólica
111
+ - Apelo à curiosidade sem contexto
112
+
113
+ ## Evaluation
114
+
115
+ ### Testing Data
116
+ - **Dataset de teste:** 1.907 manchetes (20% do total)
117
+ - **Estratificação:** Mantém distribuição ~50/50 das classes
118
+ - **Sem overlap:** Nenhum exemplo do treino no teste
119
+
120
+ ### Metrics
121
+
122
+ #### Overall Performance (Test Set)
123
+ | Métrica | Valor |
124
+ |---------|-------|
125
+ | **Accuracy** | 97.1% |
126
+ | **Precision** | 98.3% |
127
+ | **Recall** | 96.2% |
128
+ | **F1-Score** | 97.2% |
129
+
130
+ #### Confusion Matrix
131
+ ```
132
+ Predicted
133
+ Non-CB Clickbait
134
+ Actual Non-CB 875 17
135
+ Clickbait 39 976
136
+ ```
137
+
138
+ #### Cross-Validation
139
+ - **Strategy:** 5-fold Stratified CV
140
+ - **F1-Score (CV):** 97.0% ± 0.3%
141
+ - **Consistency:** Alta estabilidade entre folds
142
+
143
+ ### Model Comparison
144
+ Durante o desenvolvimento, 9 modelos foram testados:
145
+
146
+ |Ranking | Modelo | F1-Score |
147
+ |--------|--------------------|----------|
148
+ | 🥇 |**RF Otimizado** 🏆 | 97,2% |
149
+ | 🥈 |Random Forest | 97,2% |
150
+ | 🥉 |Stacking | 97,0% |
151
+ | 4º |SVM | 96,8% |
152
+ | 5º |Voting (Soft) | 96,8% |
153
+ | 6º |Voting (Hard) | 96,7% |
154
+ | 7º |Regressão Logística | 96,1% |
155
+ | 8º |Naive Bayes | 91,6% |
156
+ | 9º |Baseline | 00,0% |
157
+
158
+ O **Random Forest Otimizado** foi selecionado por:
159
+ - ✅ Melhor F1-Score
160
+ - ✅ Alta precisão (98.3%)
161
+ - ✅ Boa generalização (CV estável)
162
+ - ✅ Interpretabilidade (feature importance)
163
+
164
+ ## Technical Specifications
165
+
166
+ ### Model Architecture
167
+ - **Type:** RandomForestClassifier (Scikit-learn)
168
+ - **Optimization:** RandomizedSearchCV
169
+ - 50 iterações
170
+ - Espaço de busca: 576 combinações
171
+ - Métrica: F1-Score
172
+ - CV: 5-fold Stratified
173
+
174
+ ### Features (204 dimensões)
175
+ 1. **TF-IDF Features (200):**
176
+ - Vocabulário: 5,000 termos
177
+ - N-grams: 1-2 (unigramas + bigramas)
178
+ - Min DF: 2
179
+
180
+ 2. **Numeric Features (4):**
181
+ - word_count
182
+ - char_count
183
+ - exclamation_count
184
+ - question_count
185
+
186
+ ### Preprocessing Pipeline
187
+ ```
188
+ Texto Raw → Lowercase → Remove Stopwords → TF-IDF
189
+ Features Numéricas → StandardScaler
190
+ Combine → Random Forest → Predição
191
+ ```
192
+
193
+ ### Hardware & Software
194
+ - **Framework:** Scikit-learn 1.7.2
195
+ - **Python:** 3.8+
196
+ - **Hardware:** CPU (treinamento ~22 min)
197
+ - **Dependencies:** numpy, pandas, nltk
198
+
199
+ ## Ethical Considerations
200
+
201
+ ### Potential Biases
202
+
203
+ #### Data Bias
204
+ - ⚠️ **Viés de Fonte:** Dataset coletado de portais mainstream brasileiros
205
+ - ⚠️ **Viés Regional:** Predominantemente português do Brasil
206
+ - ⚠️ **Viés de Domínio:** Focado em jornalismo (não generaliza para marketing)
207
+
208
+ #### Model Bias
209
+ - ⚠️ **Precisão Alta (98.3%):** Pode rejeitar alguns clickbaits legítimos
210
+ - ⚠️ **Recall Bom (96.2%):** ~4% de clickbaits passam despercebidos
211
+ - ⚠️ **Feature Dependency:** Modelo sensível a contagem de pontuação (! e ?)
212
+
213
+ ### Limitations
214
+
215
+ #### Technical Limitations
216
+ 1. **Não detecta sarcasmo/ironia**
217
+ - Manchetes irônicas podem ser classificadas incorretamente
218
+
219
+ 2. **Sensível a mudanças linguísticas**
220
+ - Novo vocabulário/gírias podem reduzir performance
221
+
222
+ 3. **Contexto limitado**
223
+ - Não considera: fonte, autor, histórico do portal
224
+
225
+ 4. **Textos curtos apenas**
226
+ - Otimizado para manchetes (5-20 palavras)
227
+ - Não funciona bem com textos longos (classifica textos longos como clickbait na maioria das vezes)
228
+
229
+ #### Social Limitations
230
+ 1. **Definição de clickbait é subjetiva**
231
+ - O que é "sensacionalista" varia por contexto
232
+
233
+ 2. **Pode impactar liberdade editorial**
234
+ - Uso indiscriminado pode censurar títulos legítimos
235
+
236
+ 3. **Não substitui julgamento humano**
237
+ - Sempre requer validação por editores
238
+
239
+ ### Recommendations
240
+
241
+ #### For Developers
242
+ - ✅ **Sempre mostrar probabilidades** (não apenas classe)
243
+ - ✅ **Implementar threshold ajustável** (balancear precisão/recall)
244
+ - ✅ **Adicionar revisão humana** antes de ações automatizadas
245
+ - ✅ **Monitorar concept drift** (retreinar periodicamente)
246
+ - ✅ **Testar em seu domínio específico** antes de deploy
247
+
248
+ #### For Users
249
+ - ⚠️ **Não confiar 100% nas predições**
250
+ - ⚠️ **Validar casos de alta incerteza** (prob ~50%)
251
+ - ⚠️ **Considerar contexto da fonte**
252
+ - ⚠️ **Reportar erros sistemáticos** para melhoria contínua
253
+
254
+ ## Caveats and Recommendations
255
+
256
+ ### Known Issues
257
+ 1. **Falsos Positivos:** Títulos legítimos com linguagem emocional
258
+ 2. **Falsos Negativos:** Clickbaits sutis sem sinais óbvios
259
+ 3. **Drift Temporal:** Performance pode degradar com o tempo
260
+
261
+ ### Maintenance
262
+ - 🔄 **Retreinamento:** Recomendado a cada 6 meses
263
+ - 📊 **Monitoramento:** Acompanhar métricas em produção
264
+ - 🐛 **Feedback Loop:** Coletar erros para próxima versão
265
+
266
+ ### Usage Guidelines
267
+ ```python
268
+ # ✅ BOM: Mostrar probabilidades
269
+ resultado = model.predict_proba(texto)
270
+ if resultado[1] > 0.7:
271
+ print("Alta confiança: Clickbait")
272
+ elif resultado[1] > 0.5:
273
+ print("Média confiança: Revisar manualmente")
274
+
275
+ # ❌ RUIM: Decisão binária automática
276
+ if model.predict(texto) == 1:
277
+ deletar_manchete() # Perigoso!
278
+ ```
279
+
280
+ ## How to Use
281
+
282
+ ### Installation
283
+ ```bash
284
+ pip install scikit-learn nltk pandas numpy
285
+ ```
286
+
287
+ ### Quick Start
288
+ ```python
289
+ from huggingface_hub import hf_hub_download
290
+ import pickle
291
+
292
+ # Download model
293
+ model = hf_hub_download(repo_id="rodrigoaraujorosa/detector-clickbait-br-model",
294
+ filename="melhor_modelo.pkl")
295
+
296
+ # Load
297
+ with open(model, 'rb') as f:
298
+ clf = pickle.load(f)
299
+
300
+ # Predict
301
+ resultado = clf.predict(["Você não vai acreditar!"])
302
+ print(resultado) # [1] = Clickbait
303
+ ```
304
+
305
+ **Documentação completa:** Ver [README.md](README.md)
306
+
307
+ ## Citation
308
+
309
+ ### BibTeX
310
+ ```bibtex
311
+ @misc{detector-clickbait-br-model,
312
+ author = {Rodrigo de Araujo Rosa},
313
+ title = {Detector de Clickbait BR: Random Forest Classifier for Brazilian Portuguese Clickbait Detection},
314
+ year = {2025},
315
+ publisher = {Hugging Face},
316
+ journal = {Hugging Face Model Hub},
317
+ howpublished = {\url{https://huggingface.co/rodrigoaraujorosa/detector-clickbait-br-model}}
318
+ }
319
+ ```
320
+
321
+ ### APA
322
+ ```
323
+ ROSA, Rodrigo de Araujo. (2025). Detector de Clickbait BR: Random Forest Classifier for Brazilian Portuguese Clickbait Detection. Hugging Face Model Hub. https://huggingface.co/rodrigoaraujorosa/detector-clickbait-br-model
324
+ ```
325
+
326
+ ## More Information
327
+
328
+ - **Repository:** [GitHub](https://github.com/rodrigoaraujorosa/detector-clickbait-br)
329
+ - **Demo:** [Hugging Face Space](https://huggingface.co/spaces/rodrigoaraujorosa/detector-clickbait-br)
330
+ - **Contact:** rodrigoaraujo.r@gmail.com
331
+ - **Paper:** [Link se houver]
332
+
333
+ ## Model Card Authors
334
+ - [Rodrigo de Araujo Rosa] - Developer & Maintainer
335
+
336
+ ## Model Card Contact
337
+ For questions or feedback: rodrigoaraujo.r@gmail.com
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ scikit-learn
2
+ numpy
3
+ pandas
4
+ nltk
scaler.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d066df16a09bd3841bb71ae2899dad05321d9531b8ee760ed64a5df7d457a0c1
3
+ size 546
tfidf_vectorizer.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9e9fd48e2e391843ef76023f98d61443c58ce071fa79d9fd5405ef6fddbce68e
3
+ size 8311