ai-critic 0.2.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ai_critic-0.2.0 → ai_critic-0.2.1}/PKG-INFO +69 -61
- {ai_critic-0.2.0 → ai_critic-0.2.1}/README.md +68 -60
- {ai_critic-0.2.0 → ai_critic-0.2.1}/ai_critic/critic.py +13 -5
- ai_critic-0.2.1/ai_critic/evaluators/data.py +57 -0
- ai_critic-0.2.1/ai_critic/evaluators/performance.py +43 -0
- {ai_critic-0.2.0 → ai_critic-0.2.1}/ai_critic/evaluators/robustness.py +18 -11
- {ai_critic-0.2.0 → ai_critic-0.2.1}/ai_critic.egg-info/PKG-INFO +69 -61
- {ai_critic-0.2.0 → ai_critic-0.2.1}/pyproject.toml +1 -1
- {ai_critic-0.2.0 → ai_critic-0.2.1}/test/test_in_ia.py +7 -6
- ai_critic-0.2.0/ai_critic/evaluators/data.py +0 -49
- ai_critic-0.2.0/ai_critic/evaluators/performance.py +0 -20
- {ai_critic-0.2.0 → ai_critic-0.2.1}/ai_critic/__init__.py +0 -0
- {ai_critic-0.2.0 → ai_critic-0.2.1}/ai_critic/evaluators/__init__.py +0 -0
- {ai_critic-0.2.0 → ai_critic-0.2.1}/ai_critic/evaluators/config.py +0 -0
- {ai_critic-0.2.0 → ai_critic-0.2.1}/ai_critic/evaluators/summary.py +0 -0
- {ai_critic-0.2.0 → ai_critic-0.2.1}/ai_critic.egg-info/SOURCES.txt +0 -0
- {ai_critic-0.2.0 → ai_critic-0.2.1}/ai_critic.egg-info/dependency_links.txt +0 -0
- {ai_critic-0.2.0 → ai_critic-0.2.1}/ai_critic.egg-info/requires.txt +0 -0
- {ai_critic-0.2.0 → ai_critic-0.2.1}/ai_critic.egg-info/top_level.txt +0 -0
- {ai_critic-0.2.0 → ai_critic-0.2.1}/setup.cfg +0 -0
- {ai_critic-0.2.0 → ai_critic-0.2.1}/test/test_model.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ai-critic
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Fast AI evaluator for scikit-learn models
|
|
5
5
|
Author-email: Luiz Seabra <filipedemarco@yahoo.com>
|
|
6
6
|
Requires-Python: >=3.9
|
|
@@ -8,68 +8,71 @@ Description-Content-Type: text/markdown
|
|
|
8
8
|
Requires-Dist: numpy
|
|
9
9
|
Requires-Dist: scikit-learn
|
|
10
10
|
|
|
11
|
-
# ai-critic
|
|
11
|
+
# ai-critic: Automated Risk Auditor for Machine Learning Models**
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
---
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
[](https://opensource.org/licenses/MIT)
|
|
15
|
+
## 🚀 What is ai-critic?
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
`ai-critic` é um **auditor de risco automatizado baseado em heurísticas** para modelos de *machine learning*. Ele avalia modelos treinados antes da implantação e traduz riscos técnicos de ML em decisões claras e centradas no ser humano.
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
Em vez de apenas relatar métricas, **ai-critic** responde a uma pergunta crítica:
|
|
19
|
+
Em vez de apenas relatar métricas, o `ai-critic` responde à pergunta crítica:
|
|
23
20
|
|
|
24
21
|
> “Este modelo pode ser implantado com segurança?”
|
|
25
22
|
|
|
26
|
-
Ele faz isso analisando:
|
|
27
|
-
|
|
23
|
+
Ele faz isso analisando as principais áreas de risco:
|
|
24
|
+
|
|
25
|
+
* **Integridade dos Dados:** (*data leakage*, desequilíbrio, NaNs)
|
|
28
26
|
* **Estrutura do Modelo:** (risco de *overfitting*, complexidade)
|
|
29
27
|
* **Comportamento de Validação:** (pontuações suspeitamente perfeitas)
|
|
30
28
|
* **Robustez:** (sensibilidade a ruído)
|
|
31
29
|
|
|
32
30
|
Os resultados são organizados em três camadas semânticas para diferentes *stakeholders*:
|
|
33
|
-
1. **Executiva:** (tomadores de decisão)
|
|
34
|
-
2. **Técnica:** (engenheiros de ML)
|
|
35
|
-
3. **Detalhes:** (auditores e depuração)
|
|
36
31
|
|
|
37
|
-
|
|
32
|
+
* **Executiva:** (tomadores de decisão)
|
|
33
|
+
* **Técnica:** (engenheiros de ML)
|
|
34
|
+
* **Detalhada:** (auditores e depuração)
|
|
35
|
+
|
|
36
|
+
## 🎯 Por que o ai-critic Existe: Filosofia Central
|
|
38
37
|
|
|
39
38
|
A maioria das ferramentas de ML:
|
|
39
|
+
|
|
40
40
|
* assume que métricas = verdade
|
|
41
41
|
* confia cegamente na validação cruzada
|
|
42
|
-
*
|
|
42
|
+
* despeja números brutos sem interpretação
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
O `ai-critic` é cético por design.
|
|
45
45
|
|
|
46
46
|
Ele trata:
|
|
47
|
-
|
|
48
|
-
*
|
|
49
|
-
*
|
|
47
|
+
|
|
48
|
+
* pontuações perfeitas como **sinais**, não sucesso
|
|
49
|
+
* métricas de robustez como **dependentes do contexto**
|
|
50
|
+
* implantação como uma **decisão de risco**, não um limite de métrica
|
|
50
51
|
|
|
51
52
|
A filosofia central é: **Métricas não falham modelos — o contexto falha.**
|
|
52
53
|
|
|
53
|
-
ai-critic aplica heurísticas de raciocínio humano à avaliação de
|
|
54
|
+
O `ai-critic` aplica heurísticas de raciocínio humano à avaliação de ML:
|
|
55
|
+
|
|
54
56
|
* “Isso é bom demais para ser verdade?”
|
|
55
|
-
* “Isso pode estar vazando o alvo?”
|
|
56
|
-
* “A robustez
|
|
57
|
+
* “Isso pode estar vazando o alvo (*target*)?”
|
|
58
|
+
* “A robustez importa se a linha de base estiver errada?”
|
|
57
59
|
|
|
58
60
|
## 🛠️ Instalação
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
Instale o `ai-critic` via pip:
|
|
61
63
|
|
|
62
64
|
```bash
|
|
63
65
|
pip install ai-critic
|
|
64
66
|
```
|
|
65
67
|
|
|
66
68
|
**Requisitos:**
|
|
69
|
+
|
|
67
70
|
* Python ≥ 3.8
|
|
68
|
-
* scikit-learn
|
|
71
|
+
* `scikit-learn`
|
|
69
72
|
|
|
70
73
|
## 💡 Início Rápido
|
|
71
74
|
|
|
72
|
-
Audite seu modelo treinado em
|
|
75
|
+
Audite seu modelo treinado em apenas algumas linhas:
|
|
73
76
|
|
|
74
77
|
```python
|
|
75
78
|
from sklearn.datasets import load_breast_cancer
|
|
@@ -79,29 +82,30 @@ from ai_critic import AICritic
|
|
|
79
82
|
# 1. Carregar dados e treinar um modelo (exemplo)
|
|
80
83
|
X, y = load_breast_cancer(return_X_y=True)
|
|
81
84
|
model = RandomForestClassifier(max_depth=20, random_state=42)
|
|
82
|
-
model.fit(X, y)
|
|
85
|
+
model.fit(X, y) # O modelo deve estar treinado
|
|
83
86
|
|
|
84
87
|
# 2. Inicializar e avaliar com ai-critic
|
|
85
88
|
critic = AICritic(model, X, y)
|
|
86
89
|
report = critic.evaluate()
|
|
87
90
|
|
|
88
|
-
#
|
|
91
|
+
# A visualização padrão é 'all' (todas as camadas)
|
|
89
92
|
print(report)
|
|
90
93
|
```
|
|
91
94
|
|
|
92
95
|
## 🧩 Saída Multi-Camadas
|
|
93
96
|
|
|
94
|
-
`ai-critic` nunca despeja tudo de uma vez. Ele estrutura os resultados em camadas de decisão claras.
|
|
97
|
+
O `ai-critic` nunca despeja tudo de uma vez. Ele estrutura os resultados em camadas de decisão claras.
|
|
95
98
|
|
|
96
|
-
### 🔹
|
|
99
|
+
### 🔹 Visualização Executiva (`view="executive"`)
|
|
97
100
|
|
|
98
|
-
|
|
101
|
+
Projetado para CTOs, gerentes e *stakeholders*. Sem jargão de ML.
|
|
99
102
|
|
|
100
103
|
```python
|
|
101
104
|
critic.evaluate(view="executive")
|
|
102
105
|
```
|
|
103
106
|
|
|
104
107
|
**Exemplo de Saída:**
|
|
108
|
+
|
|
105
109
|
```json
|
|
106
110
|
{
|
|
107
111
|
"verdict": "❌ Não Confiável",
|
|
@@ -111,15 +115,16 @@ critic.evaluate(view="executive")
|
|
|
111
115
|
}
|
|
112
116
|
```
|
|
113
117
|
|
|
114
|
-
### 🔹
|
|
118
|
+
### 🔹 Visualização Técnica (`view="technical"`)
|
|
115
119
|
|
|
116
|
-
|
|
120
|
+
Projetado para engenheiros de ML. Acionável, diagnóstico e focado no que precisa ser corrigido.
|
|
117
121
|
|
|
118
122
|
```python
|
|
119
123
|
critic.evaluate(view="technical")
|
|
120
124
|
```
|
|
121
125
|
|
|
122
126
|
**Exemplo de Saída:**
|
|
127
|
+
|
|
123
128
|
```json
|
|
124
129
|
{
|
|
125
130
|
"key_risks": [
|
|
@@ -141,22 +146,23 @@ critic.evaluate(view="technical")
|
|
|
141
146
|
}
|
|
142
147
|
```
|
|
143
148
|
|
|
144
|
-
### 🔹
|
|
149
|
+
### 🔹 Visualização Detalhada (`view="details"`)
|
|
145
150
|
|
|
146
|
-
|
|
151
|
+
Projetado para auditoria, depuração e conformidade.
|
|
147
152
|
|
|
148
153
|
```python
|
|
149
154
|
critic.evaluate(view="details")
|
|
150
155
|
```
|
|
151
156
|
|
|
152
157
|
Inclui:
|
|
158
|
+
|
|
153
159
|
* Métricas brutas
|
|
154
|
-
* Correlações
|
|
160
|
+
* Correlações de recursos
|
|
155
161
|
* Pontuações de robustez
|
|
156
162
|
* Avisos estruturais
|
|
157
163
|
* Rastreabilidade completa
|
|
158
164
|
|
|
159
|
-
### 🔹
|
|
165
|
+
### 🔹 Visualização Combinada (`view="all"`)
|
|
160
166
|
|
|
161
167
|
Retorna todas as três camadas em um único dicionário.
|
|
162
168
|
|
|
@@ -165,6 +171,7 @@ critic.evaluate(view="all")
|
|
|
165
171
|
```
|
|
166
172
|
|
|
167
173
|
**Retorna:**
|
|
174
|
+
|
|
168
175
|
```json
|
|
169
176
|
{
|
|
170
177
|
"executive": {...},
|
|
@@ -179,9 +186,9 @@ critic.evaluate(view="all")
|
|
|
179
186
|
|
|
180
187
|
| Parâmetro | Descrição |
|
|
181
188
|
| :--- | :--- |
|
|
182
|
-
| `model` | Modelo `scikit-learn` treinado
|
|
183
|
-
| `X` | Matriz de recursos
|
|
184
|
-
| `y` | Vetor alvo
|
|
189
|
+
| `model` | Modelo `scikit-learn` treinado |
|
|
190
|
+
| `X` | Matriz de recursos |
|
|
191
|
+
| `y` | Vetor alvo |
|
|
185
192
|
|
|
186
193
|
**Uso:** `AICritic(model, X, y)`
|
|
187
194
|
|
|
@@ -189,24 +196,24 @@ critic.evaluate(view="all")
|
|
|
189
196
|
|
|
190
197
|
| Parâmetro | Descrição |
|
|
191
198
|
| :--- | :--- |
|
|
192
|
-
| `view` |
|
|
199
|
+
| `view` | Camada de saída desejada: `"executive"`, `"technical"`, `"details"`, ou `"all"` (padrão) |
|
|
193
200
|
|
|
194
201
|
**Uso:** `evaluate(view="all")`
|
|
195
202
|
|
|
196
|
-
## 🧠 O que ai-critic Detecta
|
|
203
|
+
## 🧠 O que o ai-critic Detecta
|
|
197
204
|
|
|
198
205
|
| Categoria | Riscos Detectados |
|
|
199
206
|
| :--- | :--- |
|
|
200
|
-
| **🔍 Riscos de Dados** | Vazamento de alvo via correlação, NaNs,
|
|
201
|
-
| **🧱 Riscos Estruturais** | Árvores excessivamente complexas,
|
|
202
|
-
| **📈 Riscos de Validação** | Pontuações de CV
|
|
203
|
-
| **🧪 Riscos de Robustez** | Sensibilidade a ruído,
|
|
207
|
+
| **🔍 Riscos de Dados** | Vazamento de alvo via correlação, NaNs, desequilíbrio de classes |
|
|
208
|
+
| **🧱 Riscos Estruturais** | Árvores excessivamente complexas, altas taxas de recurso/amostra, *configuration smells* |
|
|
209
|
+
| **📈 Riscos de Validação** | Pontuações de CV suspeitosamente perfeitas, variância irreal |
|
|
210
|
+
| **🧪 Riscos de Robustez** | Sensibilidade a ruído, robustez enganosa se a linha de base estiver inflada |
|
|
204
211
|
|
|
205
|
-
|
|
212
|
+
## 🧪 Exemplo: Detectando Vazamento de Dados
|
|
206
213
|
|
|
207
214
|
```python
|
|
208
215
|
import numpy as np
|
|
209
|
-
# ... (
|
|
216
|
+
# ... (imports e código do modelo)
|
|
210
217
|
|
|
211
218
|
# Vazamento artificial: adicionando o alvo como um recurso
|
|
212
219
|
X_leaky = np.hstack([X, y.reshape(-1, 1)])
|
|
@@ -217,7 +224,8 @@ executive_report = critic.evaluate(view="executive")
|
|
|
217
224
|
print(executive_report)
|
|
218
225
|
```
|
|
219
226
|
|
|
220
|
-
**
|
|
227
|
+
**Saída (Visualização Executiva):**
|
|
228
|
+
|
|
221
229
|
```
|
|
222
230
|
❌ Não Confiável
|
|
223
231
|
Forte evidência de vazamento de dados inflando o desempenho do modelo.
|
|
@@ -225,26 +233,26 @@ Forte evidência de vazamento de dados inflando o desempenho do modelo.
|
|
|
225
233
|
|
|
226
234
|
## 🛡️ Melhores Práticas
|
|
227
235
|
|
|
228
|
-
* Execute `ai-critic` antes da implantação.
|
|
236
|
+
* Execute o `ai-critic` antes da implantação.
|
|
229
237
|
* Nunca confie cegamente em pontuações de CV perfeitas.
|
|
230
|
-
* Use a
|
|
231
|
-
* Use a
|
|
232
|
-
* Use a
|
|
238
|
+
* Use a Visualização Executiva em seu *pipeline* de CI/CD como um portão de modelo.
|
|
239
|
+
* Use a Visualização Técnica durante a iteração do modelo.
|
|
240
|
+
* Use a Visualização Detalhada para auditoria e conformidade.
|
|
233
241
|
|
|
234
242
|
## 🧭 Casos de Uso Típicos
|
|
235
243
|
|
|
236
|
-
* Auditorias de modelo pré-implantação
|
|
237
|
-
* Governança e conformidade de ML
|
|
238
|
-
*
|
|
239
|
-
* Ensino de ceticismo em ML
|
|
240
|
-
* Explicação de risco de ML para *stakeholders* não técnicos
|
|
244
|
+
* Auditorias de modelo pré-implantação
|
|
245
|
+
* Governança e conformidade de ML
|
|
246
|
+
* Portões de modelo CI/CD
|
|
247
|
+
* Ensino de ceticismo em ML
|
|
248
|
+
* Explicação de risco de ML para *stakeholders* não técnicos
|
|
241
249
|
|
|
242
250
|
## 📄 Licença
|
|
243
251
|
|
|
244
|
-
Distribuído sob a
|
|
252
|
+
Distribuído sob a Licença MIT.
|
|
245
253
|
|
|
246
254
|
## 🧠 Nota Final
|
|
247
255
|
|
|
248
|
-
`ai-critic` não é uma ferramenta de *
|
|
256
|
+
O `ai-critic` não é uma ferramenta de *benchmarking*. É uma **ferramenta de decisão**.
|
|
249
257
|
|
|
250
|
-
Se um modelo falhar aqui,
|
|
258
|
+
Se um modelo falhar aqui, não significa que seja ruim — significa que **não deve ser confiável ainda**.
|
|
@@ -1,65 +1,68 @@
|
|
|
1
|
-
# ai-critic
|
|
1
|
+
# ai-critic: Automated Risk Auditor for Machine Learning Models**
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
---
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
## 🚀 What is ai-critic?
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
`ai-critic` é um **auditor de risco automatizado baseado em heurísticas** para modelos de *machine learning*. Ele avalia modelos treinados antes da implantação e traduz riscos técnicos de ML em decisões claras e centradas no ser humano.
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
Em vez de apenas relatar métricas, **ai-critic** responde a uma pergunta crítica:
|
|
9
|
+
Em vez de apenas relatar métricas, o `ai-critic` responde à pergunta crítica:
|
|
13
10
|
|
|
14
11
|
> “Este modelo pode ser implantado com segurança?”
|
|
15
12
|
|
|
16
|
-
Ele faz isso analisando:
|
|
17
|
-
|
|
13
|
+
Ele faz isso analisando as principais áreas de risco:
|
|
14
|
+
|
|
15
|
+
* **Integridade dos Dados:** (*data leakage*, desequilíbrio, NaNs)
|
|
18
16
|
* **Estrutura do Modelo:** (risco de *overfitting*, complexidade)
|
|
19
17
|
* **Comportamento de Validação:** (pontuações suspeitamente perfeitas)
|
|
20
18
|
* **Robustez:** (sensibilidade a ruído)
|
|
21
19
|
|
|
22
20
|
Os resultados são organizados em três camadas semânticas para diferentes *stakeholders*:
|
|
23
|
-
1. **Executiva:** (tomadores de decisão)
|
|
24
|
-
2. **Técnica:** (engenheiros de ML)
|
|
25
|
-
3. **Detalhes:** (auditores e depuração)
|
|
26
21
|
|
|
27
|
-
|
|
22
|
+
* **Executiva:** (tomadores de decisão)
|
|
23
|
+
* **Técnica:** (engenheiros de ML)
|
|
24
|
+
* **Detalhada:** (auditores e depuração)
|
|
25
|
+
|
|
26
|
+
## 🎯 Por que o ai-critic Existe: Filosofia Central
|
|
28
27
|
|
|
29
28
|
A maioria das ferramentas de ML:
|
|
29
|
+
|
|
30
30
|
* assume que métricas = verdade
|
|
31
31
|
* confia cegamente na validação cruzada
|
|
32
|
-
*
|
|
32
|
+
* despeja números brutos sem interpretação
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
O `ai-critic` é cético por design.
|
|
35
35
|
|
|
36
36
|
Ele trata:
|
|
37
|
-
|
|
38
|
-
*
|
|
39
|
-
*
|
|
37
|
+
|
|
38
|
+
* pontuações perfeitas como **sinais**, não sucesso
|
|
39
|
+
* métricas de robustez como **dependentes do contexto**
|
|
40
|
+
* implantação como uma **decisão de risco**, não um limite de métrica
|
|
40
41
|
|
|
41
42
|
A filosofia central é: **Métricas não falham modelos — o contexto falha.**
|
|
42
43
|
|
|
43
|
-
ai-critic aplica heurísticas de raciocínio humano à avaliação de
|
|
44
|
+
O `ai-critic` aplica heurísticas de raciocínio humano à avaliação de ML:
|
|
45
|
+
|
|
44
46
|
* “Isso é bom demais para ser verdade?”
|
|
45
|
-
* “Isso pode estar vazando o alvo?”
|
|
46
|
-
* “A robustez
|
|
47
|
+
* “Isso pode estar vazando o alvo (*target*)?”
|
|
48
|
+
* “A robustez importa se a linha de base estiver errada?”
|
|
47
49
|
|
|
48
50
|
## 🛠️ Instalação
|
|
49
51
|
|
|
50
|
-
|
|
52
|
+
Instale o `ai-critic` via pip:
|
|
51
53
|
|
|
52
54
|
```bash
|
|
53
55
|
pip install ai-critic
|
|
54
56
|
```
|
|
55
57
|
|
|
56
58
|
**Requisitos:**
|
|
59
|
+
|
|
57
60
|
* Python ≥ 3.8
|
|
58
|
-
* scikit-learn
|
|
61
|
+
* `scikit-learn`
|
|
59
62
|
|
|
60
63
|
## 💡 Início Rápido
|
|
61
64
|
|
|
62
|
-
Audite seu modelo treinado em
|
|
65
|
+
Audite seu modelo treinado em apenas algumas linhas:
|
|
63
66
|
|
|
64
67
|
```python
|
|
65
68
|
from sklearn.datasets import load_breast_cancer
|
|
@@ -69,29 +72,30 @@ from ai_critic import AICritic
|
|
|
69
72
|
# 1. Carregar dados e treinar um modelo (exemplo)
|
|
70
73
|
X, y = load_breast_cancer(return_X_y=True)
|
|
71
74
|
model = RandomForestClassifier(max_depth=20, random_state=42)
|
|
72
|
-
model.fit(X, y)
|
|
75
|
+
model.fit(X, y) # O modelo deve estar treinado
|
|
73
76
|
|
|
74
77
|
# 2. Inicializar e avaliar com ai-critic
|
|
75
78
|
critic = AICritic(model, X, y)
|
|
76
79
|
report = critic.evaluate()
|
|
77
80
|
|
|
78
|
-
#
|
|
81
|
+
# A visualização padrão é 'all' (todas as camadas)
|
|
79
82
|
print(report)
|
|
80
83
|
```
|
|
81
84
|
|
|
82
85
|
## 🧩 Saída Multi-Camadas
|
|
83
86
|
|
|
84
|
-
`ai-critic` nunca despeja tudo de uma vez. Ele estrutura os resultados em camadas de decisão claras.
|
|
87
|
+
O `ai-critic` nunca despeja tudo de uma vez. Ele estrutura os resultados em camadas de decisão claras.
|
|
85
88
|
|
|
86
|
-
### 🔹
|
|
89
|
+
### 🔹 Visualização Executiva (`view="executive"`)
|
|
87
90
|
|
|
88
|
-
|
|
91
|
+
Projetado para CTOs, gerentes e *stakeholders*. Sem jargão de ML.
|
|
89
92
|
|
|
90
93
|
```python
|
|
91
94
|
critic.evaluate(view="executive")
|
|
92
95
|
```
|
|
93
96
|
|
|
94
97
|
**Exemplo de Saída:**
|
|
98
|
+
|
|
95
99
|
```json
|
|
96
100
|
{
|
|
97
101
|
"verdict": "❌ Não Confiável",
|
|
@@ -101,15 +105,16 @@ critic.evaluate(view="executive")
|
|
|
101
105
|
}
|
|
102
106
|
```
|
|
103
107
|
|
|
104
|
-
### 🔹
|
|
108
|
+
### 🔹 Visualização Técnica (`view="technical"`)
|
|
105
109
|
|
|
106
|
-
|
|
110
|
+
Projetado para engenheiros de ML. Acionável, diagnóstico e focado no que precisa ser corrigido.
|
|
107
111
|
|
|
108
112
|
```python
|
|
109
113
|
critic.evaluate(view="technical")
|
|
110
114
|
```
|
|
111
115
|
|
|
112
116
|
**Exemplo de Saída:**
|
|
117
|
+
|
|
113
118
|
```json
|
|
114
119
|
{
|
|
115
120
|
"key_risks": [
|
|
@@ -131,22 +136,23 @@ critic.evaluate(view="technical")
|
|
|
131
136
|
}
|
|
132
137
|
```
|
|
133
138
|
|
|
134
|
-
### 🔹
|
|
139
|
+
### 🔹 Visualização Detalhada (`view="details"`)
|
|
135
140
|
|
|
136
|
-
|
|
141
|
+
Projetado para auditoria, depuração e conformidade.
|
|
137
142
|
|
|
138
143
|
```python
|
|
139
144
|
critic.evaluate(view="details")
|
|
140
145
|
```
|
|
141
146
|
|
|
142
147
|
Inclui:
|
|
148
|
+
|
|
143
149
|
* Métricas brutas
|
|
144
|
-
* Correlações
|
|
150
|
+
* Correlações de recursos
|
|
145
151
|
* Pontuações de robustez
|
|
146
152
|
* Avisos estruturais
|
|
147
153
|
* Rastreabilidade completa
|
|
148
154
|
|
|
149
|
-
### 🔹
|
|
155
|
+
### 🔹 Visualização Combinada (`view="all"`)
|
|
150
156
|
|
|
151
157
|
Retorna todas as três camadas em um único dicionário.
|
|
152
158
|
|
|
@@ -155,6 +161,7 @@ critic.evaluate(view="all")
|
|
|
155
161
|
```
|
|
156
162
|
|
|
157
163
|
**Retorna:**
|
|
164
|
+
|
|
158
165
|
```json
|
|
159
166
|
{
|
|
160
167
|
"executive": {...},
|
|
@@ -169,9 +176,9 @@ critic.evaluate(view="all")
|
|
|
169
176
|
|
|
170
177
|
| Parâmetro | Descrição |
|
|
171
178
|
| :--- | :--- |
|
|
172
|
-
| `model` | Modelo `scikit-learn` treinado
|
|
173
|
-
| `X` | Matriz de recursos
|
|
174
|
-
| `y` | Vetor alvo
|
|
179
|
+
| `model` | Modelo `scikit-learn` treinado |
|
|
180
|
+
| `X` | Matriz de recursos |
|
|
181
|
+
| `y` | Vetor alvo |
|
|
175
182
|
|
|
176
183
|
**Uso:** `AICritic(model, X, y)`
|
|
177
184
|
|
|
@@ -179,24 +186,24 @@ critic.evaluate(view="all")
|
|
|
179
186
|
|
|
180
187
|
| Parâmetro | Descrição |
|
|
181
188
|
| :--- | :--- |
|
|
182
|
-
| `view` |
|
|
189
|
+
| `view` | Camada de saída desejada: `"executive"`, `"technical"`, `"details"`, ou `"all"` (padrão) |
|
|
183
190
|
|
|
184
191
|
**Uso:** `evaluate(view="all")`
|
|
185
192
|
|
|
186
|
-
## 🧠 O que ai-critic Detecta
|
|
193
|
+
## 🧠 O que o ai-critic Detecta
|
|
187
194
|
|
|
188
195
|
| Categoria | Riscos Detectados |
|
|
189
196
|
| :--- | :--- |
|
|
190
|
-
| **🔍 Riscos de Dados** | Vazamento de alvo via correlação, NaNs,
|
|
191
|
-
| **🧱 Riscos Estruturais** | Árvores excessivamente complexas,
|
|
192
|
-
| **📈 Riscos de Validação** | Pontuações de CV
|
|
193
|
-
| **🧪 Riscos de Robustez** | Sensibilidade a ruído,
|
|
197
|
+
| **🔍 Riscos de Dados** | Vazamento de alvo via correlação, NaNs, desequilíbrio de classes |
|
|
198
|
+
| **🧱 Riscos Estruturais** | Árvores excessivamente complexas, altas taxas de recurso/amostra, *configuration smells* |
|
|
199
|
+
| **📈 Riscos de Validação** | Pontuações de CV suspeitosamente perfeitas, variância irreal |
|
|
200
|
+
| **🧪 Riscos de Robustez** | Sensibilidade a ruído, robustez enganosa se a linha de base estiver inflada |
|
|
194
201
|
|
|
195
|
-
|
|
202
|
+
## 🧪 Exemplo: Detectando Vazamento de Dados
|
|
196
203
|
|
|
197
204
|
```python
|
|
198
205
|
import numpy as np
|
|
199
|
-
# ... (
|
|
206
|
+
# ... (imports e código do modelo)
|
|
200
207
|
|
|
201
208
|
# Vazamento artificial: adicionando o alvo como um recurso
|
|
202
209
|
X_leaky = np.hstack([X, y.reshape(-1, 1)])
|
|
@@ -207,7 +214,8 @@ executive_report = critic.evaluate(view="executive")
|
|
|
207
214
|
print(executive_report)
|
|
208
215
|
```
|
|
209
216
|
|
|
210
|
-
**
|
|
217
|
+
**Saída (Visualização Executiva):**
|
|
218
|
+
|
|
211
219
|
```
|
|
212
220
|
❌ Não Confiável
|
|
213
221
|
Forte evidência de vazamento de dados inflando o desempenho do modelo.
|
|
@@ -215,26 +223,26 @@ Forte evidência de vazamento de dados inflando o desempenho do modelo.
|
|
|
215
223
|
|
|
216
224
|
## 🛡️ Melhores Práticas
|
|
217
225
|
|
|
218
|
-
* Execute `ai-critic` antes da implantação.
|
|
226
|
+
* Execute o `ai-critic` antes da implantação.
|
|
219
227
|
* Nunca confie cegamente em pontuações de CV perfeitas.
|
|
220
|
-
* Use a
|
|
221
|
-
* Use a
|
|
222
|
-
* Use a
|
|
228
|
+
* Use a Visualização Executiva em seu *pipeline* de CI/CD como um portão de modelo.
|
|
229
|
+
* Use a Visualização Técnica durante a iteração do modelo.
|
|
230
|
+
* Use a Visualização Detalhada para auditoria e conformidade.
|
|
223
231
|
|
|
224
232
|
## 🧭 Casos de Uso Típicos
|
|
225
233
|
|
|
226
|
-
* Auditorias de modelo pré-implantação
|
|
227
|
-
* Governança e conformidade de ML
|
|
228
|
-
*
|
|
229
|
-
* Ensino de ceticismo em ML
|
|
230
|
-
* Explicação de risco de ML para *stakeholders* não técnicos
|
|
234
|
+
* Auditorias de modelo pré-implantação
|
|
235
|
+
* Governança e conformidade de ML
|
|
236
|
+
* Portões de modelo CI/CD
|
|
237
|
+
* Ensino de ceticismo em ML
|
|
238
|
+
* Explicação de risco de ML para *stakeholders* não técnicos
|
|
231
239
|
|
|
232
240
|
## 📄 Licença
|
|
233
241
|
|
|
234
|
-
Distribuído sob a
|
|
242
|
+
Distribuído sob a Licença MIT.
|
|
235
243
|
|
|
236
244
|
## 🧠 Nota Final
|
|
237
245
|
|
|
238
|
-
`ai-critic` não é uma ferramenta de *
|
|
246
|
+
O `ai-critic` não é uma ferramenta de *benchmarking*. É uma **ferramenta de decisão**.
|
|
239
247
|
|
|
240
|
-
Se um modelo falhar aqui,
|
|
248
|
+
Se um modelo falhar aqui, não significa que seja ruim — significa que **não deve ser confiável ainda**.
|
|
@@ -10,7 +10,7 @@ from ai_critic.evaluators.summary import HumanSummary
|
|
|
10
10
|
class AICritic:
|
|
11
11
|
"""
|
|
12
12
|
Automated reviewer for scikit-learn models.
|
|
13
|
-
Produces a multi-layered risk assessment.
|
|
13
|
+
Produces a multi-layered risk assessment with visualizations.
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
16
|
def __init__(self, model, X, y):
|
|
@@ -18,7 +18,7 @@ class AICritic:
|
|
|
18
18
|
self.X = X
|
|
19
19
|
self.y = y
|
|
20
20
|
|
|
21
|
-
def evaluate(self, view="all"):
|
|
21
|
+
def evaluate(self, view="all", plot=False):
|
|
22
22
|
"""
|
|
23
23
|
view:
|
|
24
24
|
- "all"
|
|
@@ -26,6 +26,9 @@ class AICritic:
|
|
|
26
26
|
- "technical"
|
|
27
27
|
- "details"
|
|
28
28
|
- list of views
|
|
29
|
+
plot:
|
|
30
|
+
- True: gera gráficos de learning curve, heatmap e robustez
|
|
31
|
+
- False: sem gráficos
|
|
29
32
|
"""
|
|
30
33
|
|
|
31
34
|
# =========================
|
|
@@ -33,24 +36,29 @@ class AICritic:
|
|
|
33
36
|
# =========================
|
|
34
37
|
details = {}
|
|
35
38
|
|
|
36
|
-
|
|
39
|
+
# Data analysis + heatmap
|
|
40
|
+
data_report = data(self.X, self.y, plot=plot)
|
|
37
41
|
details["data"] = data_report
|
|
38
42
|
|
|
43
|
+
# Model configuration
|
|
39
44
|
details["config"] = config(
|
|
40
45
|
self.model,
|
|
41
46
|
n_samples=data_report["n_samples"],
|
|
42
47
|
n_features=data_report["n_features"]
|
|
43
48
|
)
|
|
44
49
|
|
|
50
|
+
# Performance + learning curve
|
|
45
51
|
details["performance"] = performance(
|
|
46
|
-
self.model, self.X, self.y
|
|
52
|
+
self.model, self.X, self.y, plot=plot
|
|
47
53
|
)
|
|
48
54
|
|
|
55
|
+
# Robustness + CV clean vs noisy
|
|
49
56
|
details["robustness"] = robustness(
|
|
50
57
|
self.model,
|
|
51
58
|
self.X,
|
|
52
59
|
self.y,
|
|
53
|
-
leakage_suspected=data_report["data_leakage"]["suspected"]
|
|
60
|
+
leakage_suspected=data_report["data_leakage"]["suspected"],
|
|
61
|
+
plot=plot
|
|
54
62
|
)
|
|
55
63
|
|
|
56
64
|
# =========================
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import matplotlib.pyplot as plt
|
|
3
|
+
import seaborn as sns
|
|
4
|
+
import pandas as pd
|
|
5
|
+
|
|
6
|
+
def evaluate(X, y, plot=False):
|
|
7
|
+
report = {
|
|
8
|
+
"n_samples": int(X.shape[0]),
|
|
9
|
+
"n_features": int(X.shape[1]),
|
|
10
|
+
"has_nan": bool(np.isnan(X).any() or np.isnan(y).any())
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
# Class balance
|
|
14
|
+
if len(set(y)) < 20:
|
|
15
|
+
values, counts = np.unique(y, return_counts=True)
|
|
16
|
+
report["class_balance"] = {int(v): int(c) for v, c in zip(values, counts)}
|
|
17
|
+
else:
|
|
18
|
+
report["class_balance"] = "many_classes"
|
|
19
|
+
|
|
20
|
+
# Data leakage detection
|
|
21
|
+
suspicious_features = []
|
|
22
|
+
y_mean = np.mean(y)
|
|
23
|
+
y_centered = y - y_mean
|
|
24
|
+
for i in range(X.shape[1]):
|
|
25
|
+
feature = X[:, i]
|
|
26
|
+
if np.std(feature) == 0:
|
|
27
|
+
continue
|
|
28
|
+
corr = np.corrcoef(feature, y_centered)[0, 1]
|
|
29
|
+
if abs(corr) > 0.98:
|
|
30
|
+
suspicious_features.append({"feature_index": int(i), "correlation": float(corr)})
|
|
31
|
+
|
|
32
|
+
report["data_leakage"] = {
|
|
33
|
+
"suspected": bool(len(suspicious_features) > 0),
|
|
34
|
+
"details": suspicious_features,
|
|
35
|
+
"message": (
|
|
36
|
+
"Highly correlated features may reveal the target directly."
|
|
37
|
+
if suspicious_features else "No obvious data leakage detected."
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# =========================
|
|
42
|
+
# Heatmap de correlação Features x Target
|
|
43
|
+
# =========================
|
|
44
|
+
if plot:
|
|
45
|
+
feature_names = [f"feat_{i}" for i in range(X.shape[1])]
|
|
46
|
+
df = pd.DataFrame(X, columns=feature_names)
|
|
47
|
+
df['target'] = y
|
|
48
|
+
corr_matrix = df.corr()
|
|
49
|
+
|
|
50
|
+
plt.figure(figsize=(10,8))
|
|
51
|
+
sns.heatmap(corr_matrix, annot=False, cmap="coolwarm") # <- removi os números
|
|
52
|
+
plt.title("Correlação Features x Target")
|
|
53
|
+
plt.tight_layout()
|
|
54
|
+
plt.savefig("heatmap_correlation.png", dpi=150) # Salva automaticamente
|
|
55
|
+
plt.show()
|
|
56
|
+
|
|
57
|
+
return report
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from sklearn.model_selection import cross_val_score, learning_curve
|
|
2
|
+
import matplotlib.pyplot as plt
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
def evaluate(model, X, y, plot=False):
|
|
6
|
+
# CV básico
|
|
7
|
+
scores = cross_val_score(model, X, y, cv=3)
|
|
8
|
+
mean = float(scores.mean())
|
|
9
|
+
std = float(scores.std())
|
|
10
|
+
suspicious = mean > 0.995
|
|
11
|
+
|
|
12
|
+
result = {
|
|
13
|
+
"cv_mean_score": mean,
|
|
14
|
+
"cv_std": std,
|
|
15
|
+
"suspiciously_perfect": suspicious,
|
|
16
|
+
"message": (
|
|
17
|
+
"Perfect CV score detected — possible data leakage."
|
|
18
|
+
if suspicious else "CV performance within expected range."
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
# =========================
|
|
23
|
+
# Learning curve
|
|
24
|
+
# =========================
|
|
25
|
+
if plot:
|
|
26
|
+
train_sizes, train_scores, test_scores = learning_curve(
|
|
27
|
+
model, X, y, cv=3, train_sizes=np.linspace(0.1, 1.0, 5)
|
|
28
|
+
)
|
|
29
|
+
plt.figure(figsize=(6,4))
|
|
30
|
+
plt.plot(train_sizes, np.mean(train_scores, axis=1), label="Treino")
|
|
31
|
+
plt.plot(train_sizes, np.mean(test_scores, axis=1), label="Validação")
|
|
32
|
+
plt.fill_between(train_sizes,
|
|
33
|
+
np.mean(test_scores, axis=1)-np.std(test_scores, axis=1),
|
|
34
|
+
np.mean(test_scores, axis=1)+np.std(test_scores, axis=1),
|
|
35
|
+
alpha=0.2)
|
|
36
|
+
plt.xlabel("Amostra de treino")
|
|
37
|
+
plt.ylabel("Score")
|
|
38
|
+
plt.title("Learning Curve")
|
|
39
|
+
plt.legend()
|
|
40
|
+
plt.tight_layout()
|
|
41
|
+
plt.show()
|
|
42
|
+
|
|
43
|
+
return result
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
from sklearn.base import clone
|
|
3
3
|
from sklearn.model_selection import cross_val_score
|
|
4
|
+
import matplotlib.pyplot as plt
|
|
4
5
|
|
|
5
|
-
def evaluate(model, X, y, leakage_suspected=False):
|
|
6
|
+
def evaluate(model, X, y, leakage_suspected=False, plot=False):
|
|
6
7
|
noise_level = 0.02 # 2% relative noise
|
|
7
|
-
|
|
8
8
|
scale = np.std(X)
|
|
9
9
|
noise = np.random.normal(0, noise_level * scale, X.shape)
|
|
10
10
|
X_noisy = X + noise
|
|
@@ -12,18 +12,12 @@ def evaluate(model, X, y, leakage_suspected=False):
|
|
|
12
12
|
model_clean = clone(model)
|
|
13
13
|
model_noisy = clone(model)
|
|
14
14
|
|
|
15
|
-
score_clean = cross_val_score(
|
|
16
|
-
|
|
17
|
-
).mean()
|
|
18
|
-
|
|
19
|
-
score_noisy = cross_val_score(
|
|
20
|
-
model_noisy, X_noisy, y, cv=3, n_jobs=1
|
|
21
|
-
).mean()
|
|
22
|
-
|
|
15
|
+
score_clean = cross_val_score(model_clean, X, y, cv=3, n_jobs=1).mean()
|
|
16
|
+
score_noisy = cross_val_score(model_noisy, X_noisy, y, cv=3, n_jobs=1).mean()
|
|
23
17
|
drop = score_clean - score_noisy
|
|
24
18
|
|
|
25
19
|
# =========================
|
|
26
|
-
#
|
|
20
|
+
# Verdict
|
|
27
21
|
# =========================
|
|
28
22
|
if leakage_suspected and score_clean > 0.98:
|
|
29
23
|
verdict = "misleading"
|
|
@@ -38,6 +32,19 @@ def evaluate(model, X, y, leakage_suspected=False):
|
|
|
38
32
|
verdict = "stable"
|
|
39
33
|
message = "Model shows acceptable robustness to noise."
|
|
40
34
|
|
|
35
|
+
# =========================
|
|
36
|
+
# Plot CV Clean vs Noisy
|
|
37
|
+
# =========================
|
|
38
|
+
if plot:
|
|
39
|
+
plt.figure(figsize=(4,4))
|
|
40
|
+
plt.bar(["Original", "Com Ruído"], [score_clean, score_noisy], color=['green','red'])
|
|
41
|
+
plt.ylabel("CV Score")
|
|
42
|
+
plt.title("Robustez do Modelo")
|
|
43
|
+
plt.ylim(0, 1)
|
|
44
|
+
plt.tight_layout()
|
|
45
|
+
plt.savefig("robustness.png", dpi=150) # Salva automaticamente
|
|
46
|
+
plt.show()
|
|
47
|
+
|
|
41
48
|
return {
|
|
42
49
|
"cv_score_original": float(score_clean),
|
|
43
50
|
"cv_score_noisy": float(score_noisy),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ai-critic
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Fast AI evaluator for scikit-learn models
|
|
5
5
|
Author-email: Luiz Seabra <filipedemarco@yahoo.com>
|
|
6
6
|
Requires-Python: >=3.9
|
|
@@ -8,68 +8,71 @@ Description-Content-Type: text/markdown
|
|
|
8
8
|
Requires-Dist: numpy
|
|
9
9
|
Requires-Dist: scikit-learn
|
|
10
10
|
|
|
11
|
-
# ai-critic
|
|
11
|
+
# ai-critic: Automated Risk Auditor for Machine Learning Models**
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
---
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
[](https://opensource.org/licenses/MIT)
|
|
15
|
+
## 🚀 What is ai-critic?
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
`ai-critic` é um **auditor de risco automatizado baseado em heurísticas** para modelos de *machine learning*. Ele avalia modelos treinados antes da implantação e traduz riscos técnicos de ML em decisões claras e centradas no ser humano.
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
Em vez de apenas relatar métricas, **ai-critic** responde a uma pergunta crítica:
|
|
19
|
+
Em vez de apenas relatar métricas, o `ai-critic` responde à pergunta crítica:
|
|
23
20
|
|
|
24
21
|
> “Este modelo pode ser implantado com segurança?”
|
|
25
22
|
|
|
26
|
-
Ele faz isso analisando:
|
|
27
|
-
|
|
23
|
+
Ele faz isso analisando as principais áreas de risco:
|
|
24
|
+
|
|
25
|
+
* **Integridade dos Dados:** (*data leakage*, desequilíbrio, NaNs)
|
|
28
26
|
* **Estrutura do Modelo:** (risco de *overfitting*, complexidade)
|
|
29
27
|
* **Comportamento de Validação:** (pontuações suspeitamente perfeitas)
|
|
30
28
|
* **Robustez:** (sensibilidade a ruído)
|
|
31
29
|
|
|
32
30
|
Os resultados são organizados em três camadas semânticas para diferentes *stakeholders*:
|
|
33
|
-
1. **Executiva:** (tomadores de decisão)
|
|
34
|
-
2. **Técnica:** (engenheiros de ML)
|
|
35
|
-
3. **Detalhes:** (auditores e depuração)
|
|
36
31
|
|
|
37
|
-
|
|
32
|
+
* **Executiva:** (tomadores de decisão)
|
|
33
|
+
* **Técnica:** (engenheiros de ML)
|
|
34
|
+
* **Detalhada:** (auditores e depuração)
|
|
35
|
+
|
|
36
|
+
## 🎯 Por que o ai-critic Existe: Filosofia Central
|
|
38
37
|
|
|
39
38
|
A maioria das ferramentas de ML:
|
|
39
|
+
|
|
40
40
|
* assume que métricas = verdade
|
|
41
41
|
* confia cegamente na validação cruzada
|
|
42
|
-
*
|
|
42
|
+
* despeja números brutos sem interpretação
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
O `ai-critic` é cético por design.
|
|
45
45
|
|
|
46
46
|
Ele trata:
|
|
47
|
-
|
|
48
|
-
*
|
|
49
|
-
*
|
|
47
|
+
|
|
48
|
+
* pontuações perfeitas como **sinais**, não sucesso
|
|
49
|
+
* métricas de robustez como **dependentes do contexto**
|
|
50
|
+
* implantação como uma **decisão de risco**, não um limite de métrica
|
|
50
51
|
|
|
51
52
|
A filosofia central é: **Métricas não falham modelos — o contexto falha.**
|
|
52
53
|
|
|
53
|
-
ai-critic aplica heurísticas de raciocínio humano à avaliação de
|
|
54
|
+
O `ai-critic` aplica heurísticas de raciocínio humano à avaliação de ML:
|
|
55
|
+
|
|
54
56
|
* “Isso é bom demais para ser verdade?”
|
|
55
|
-
* “Isso pode estar vazando o alvo?”
|
|
56
|
-
* “A robustez
|
|
57
|
+
* “Isso pode estar vazando o alvo (*target*)?”
|
|
58
|
+
* “A robustez importa se a linha de base estiver errada?”
|
|
57
59
|
|
|
58
60
|
## 🛠️ Instalação
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
Instale o `ai-critic` via pip:
|
|
61
63
|
|
|
62
64
|
```bash
|
|
63
65
|
pip install ai-critic
|
|
64
66
|
```
|
|
65
67
|
|
|
66
68
|
**Requisitos:**
|
|
69
|
+
|
|
67
70
|
* Python ≥ 3.8
|
|
68
|
-
* scikit-learn
|
|
71
|
+
* `scikit-learn`
|
|
69
72
|
|
|
70
73
|
## 💡 Início Rápido
|
|
71
74
|
|
|
72
|
-
Audite seu modelo treinado em
|
|
75
|
+
Audite seu modelo treinado em apenas algumas linhas:
|
|
73
76
|
|
|
74
77
|
```python
|
|
75
78
|
from sklearn.datasets import load_breast_cancer
|
|
@@ -79,29 +82,30 @@ from ai_critic import AICritic
|
|
|
79
82
|
# 1. Carregar dados e treinar um modelo (exemplo)
|
|
80
83
|
X, y = load_breast_cancer(return_X_y=True)
|
|
81
84
|
model = RandomForestClassifier(max_depth=20, random_state=42)
|
|
82
|
-
model.fit(X, y)
|
|
85
|
+
model.fit(X, y) # O modelo deve estar treinado
|
|
83
86
|
|
|
84
87
|
# 2. Inicializar e avaliar com ai-critic
|
|
85
88
|
critic = AICritic(model, X, y)
|
|
86
89
|
report = critic.evaluate()
|
|
87
90
|
|
|
88
|
-
#
|
|
91
|
+
# A visualização padrão é 'all' (todas as camadas)
|
|
89
92
|
print(report)
|
|
90
93
|
```
|
|
91
94
|
|
|
92
95
|
## 🧩 Saída Multi-Camadas
|
|
93
96
|
|
|
94
|
-
`ai-critic` nunca despeja tudo de uma vez. Ele estrutura os resultados em camadas de decisão claras.
|
|
97
|
+
O `ai-critic` nunca despeja tudo de uma vez. Ele estrutura os resultados em camadas de decisão claras.
|
|
95
98
|
|
|
96
|
-
### 🔹
|
|
99
|
+
### 🔹 Visualização Executiva (`view="executive"`)
|
|
97
100
|
|
|
98
|
-
|
|
101
|
+
Projetado para CTOs, gerentes e *stakeholders*. Sem jargão de ML.
|
|
99
102
|
|
|
100
103
|
```python
|
|
101
104
|
critic.evaluate(view="executive")
|
|
102
105
|
```
|
|
103
106
|
|
|
104
107
|
**Exemplo de Saída:**
|
|
108
|
+
|
|
105
109
|
```json
|
|
106
110
|
{
|
|
107
111
|
"verdict": "❌ Não Confiável",
|
|
@@ -111,15 +115,16 @@ critic.evaluate(view="executive")
|
|
|
111
115
|
}
|
|
112
116
|
```
|
|
113
117
|
|
|
114
|
-
### 🔹
|
|
118
|
+
### 🔹 Visualização Técnica (`view="technical"`)
|
|
115
119
|
|
|
116
|
-
|
|
120
|
+
Projetado para engenheiros de ML. Acionável, diagnóstico e focado no que precisa ser corrigido.
|
|
117
121
|
|
|
118
122
|
```python
|
|
119
123
|
critic.evaluate(view="technical")
|
|
120
124
|
```
|
|
121
125
|
|
|
122
126
|
**Exemplo de Saída:**
|
|
127
|
+
|
|
123
128
|
```json
|
|
124
129
|
{
|
|
125
130
|
"key_risks": [
|
|
@@ -141,22 +146,23 @@ critic.evaluate(view="technical")
|
|
|
141
146
|
}
|
|
142
147
|
```
|
|
143
148
|
|
|
144
|
-
### 🔹
|
|
149
|
+
### 🔹 Visualização Detalhada (`view="details"`)
|
|
145
150
|
|
|
146
|
-
|
|
151
|
+
Projetado para auditoria, depuração e conformidade.
|
|
147
152
|
|
|
148
153
|
```python
|
|
149
154
|
critic.evaluate(view="details")
|
|
150
155
|
```
|
|
151
156
|
|
|
152
157
|
Inclui:
|
|
158
|
+
|
|
153
159
|
* Métricas brutas
|
|
154
|
-
* Correlações
|
|
160
|
+
* Correlações de recursos
|
|
155
161
|
* Pontuações de robustez
|
|
156
162
|
* Avisos estruturais
|
|
157
163
|
* Rastreabilidade completa
|
|
158
164
|
|
|
159
|
-
### 🔹
|
|
165
|
+
### 🔹 Visualização Combinada (`view="all"`)
|
|
160
166
|
|
|
161
167
|
Retorna todas as três camadas em um único dicionário.
|
|
162
168
|
|
|
@@ -165,6 +171,7 @@ critic.evaluate(view="all")
|
|
|
165
171
|
```
|
|
166
172
|
|
|
167
173
|
**Retorna:**
|
|
174
|
+
|
|
168
175
|
```json
|
|
169
176
|
{
|
|
170
177
|
"executive": {...},
|
|
@@ -179,9 +186,9 @@ critic.evaluate(view="all")
|
|
|
179
186
|
|
|
180
187
|
| Parâmetro | Descrição |
|
|
181
188
|
| :--- | :--- |
|
|
182
|
-
| `model` | Modelo `scikit-learn` treinado
|
|
183
|
-
| `X` | Matriz de recursos
|
|
184
|
-
| `y` | Vetor alvo
|
|
189
|
+
| `model` | Modelo `scikit-learn` treinado |
|
|
190
|
+
| `X` | Matriz de recursos |
|
|
191
|
+
| `y` | Vetor alvo |
|
|
185
192
|
|
|
186
193
|
**Uso:** `AICritic(model, X, y)`
|
|
187
194
|
|
|
@@ -189,24 +196,24 @@ critic.evaluate(view="all")
|
|
|
189
196
|
|
|
190
197
|
| Parâmetro | Descrição |
|
|
191
198
|
| :--- | :--- |
|
|
192
|
-
| `view` |
|
|
199
|
+
| `view` | Camada de saída desejada: `"executive"`, `"technical"`, `"details"`, ou `"all"` (padrão) |
|
|
193
200
|
|
|
194
201
|
**Uso:** `evaluate(view="all")`
|
|
195
202
|
|
|
196
|
-
## 🧠 O que ai-critic Detecta
|
|
203
|
+
## 🧠 O que o ai-critic Detecta
|
|
197
204
|
|
|
198
205
|
| Categoria | Riscos Detectados |
|
|
199
206
|
| :--- | :--- |
|
|
200
|
-
| **🔍 Riscos de Dados** | Vazamento de alvo via correlação, NaNs,
|
|
201
|
-
| **🧱 Riscos Estruturais** | Árvores excessivamente complexas,
|
|
202
|
-
| **📈 Riscos de Validação** | Pontuações de CV
|
|
203
|
-
| **🧪 Riscos de Robustez** | Sensibilidade a ruído,
|
|
207
|
+
| **🔍 Riscos de Dados** | Vazamento de alvo via correlação, NaNs, desequilíbrio de classes |
|
|
208
|
+
| **🧱 Riscos Estruturais** | Árvores excessivamente complexas, altas taxas de recurso/amostra, *configuration smells* |
|
|
209
|
+
| **📈 Riscos de Validação** | Pontuações de CV suspeitosamente perfeitas, variância irreal |
|
|
210
|
+
| **🧪 Riscos de Robustez** | Sensibilidade a ruído, robustez enganosa se a linha de base estiver inflada |
|
|
204
211
|
|
|
205
|
-
|
|
212
|
+
## 🧪 Exemplo: Detectando Vazamento de Dados
|
|
206
213
|
|
|
207
214
|
```python
|
|
208
215
|
import numpy as np
|
|
209
|
-
# ... (
|
|
216
|
+
# ... (imports e código do modelo)
|
|
210
217
|
|
|
211
218
|
# Vazamento artificial: adicionando o alvo como um recurso
|
|
212
219
|
X_leaky = np.hstack([X, y.reshape(-1, 1)])
|
|
@@ -217,7 +224,8 @@ executive_report = critic.evaluate(view="executive")
|
|
|
217
224
|
print(executive_report)
|
|
218
225
|
```
|
|
219
226
|
|
|
220
|
-
**
|
|
227
|
+
**Saída (Visualização Executiva):**
|
|
228
|
+
|
|
221
229
|
```
|
|
222
230
|
❌ Não Confiável
|
|
223
231
|
Forte evidência de vazamento de dados inflando o desempenho do modelo.
|
|
@@ -225,26 +233,26 @@ Forte evidência de vazamento de dados inflando o desempenho do modelo.
|
|
|
225
233
|
|
|
226
234
|
## 🛡️ Melhores Práticas
|
|
227
235
|
|
|
228
|
-
* Execute `ai-critic` antes da implantação.
|
|
236
|
+
* Execute o `ai-critic` antes da implantação.
|
|
229
237
|
* Nunca confie cegamente em pontuações de CV perfeitas.
|
|
230
|
-
* Use a
|
|
231
|
-
* Use a
|
|
232
|
-
* Use a
|
|
238
|
+
* Use a Visualização Executiva em seu *pipeline* de CI/CD como um portão de modelo.
|
|
239
|
+
* Use a Visualização Técnica durante a iteração do modelo.
|
|
240
|
+
* Use a Visualização Detalhada para auditoria e conformidade.
|
|
233
241
|
|
|
234
242
|
## 🧭 Casos de Uso Típicos
|
|
235
243
|
|
|
236
|
-
* Auditorias de modelo pré-implantação
|
|
237
|
-
* Governança e conformidade de ML
|
|
238
|
-
*
|
|
239
|
-
* Ensino de ceticismo em ML
|
|
240
|
-
* Explicação de risco de ML para *stakeholders* não técnicos
|
|
244
|
+
* Auditorias de modelo pré-implantação
|
|
245
|
+
* Governança e conformidade de ML
|
|
246
|
+
* Portões de modelo CI/CD
|
|
247
|
+
* Ensino de ceticismo em ML
|
|
248
|
+
* Explicação de risco de ML para *stakeholders* não técnicos
|
|
241
249
|
|
|
242
250
|
## 📄 Licença
|
|
243
251
|
|
|
244
|
-
Distribuído sob a
|
|
252
|
+
Distribuído sob a Licença MIT.
|
|
245
253
|
|
|
246
254
|
## 🧠 Nota Final
|
|
247
255
|
|
|
248
|
-
`ai-critic` não é uma ferramenta de *
|
|
256
|
+
O `ai-critic` não é uma ferramenta de *benchmarking*. É uma **ferramenta de decisão**.
|
|
249
257
|
|
|
250
|
-
Se um modelo falhar aqui,
|
|
258
|
+
Se um modelo falhar aqui, não significa que seja ruim — significa que **não deve ser confiável ainda**.
|
|
@@ -35,21 +35,22 @@ model = RandomForestClassifier(
|
|
|
35
35
|
)
|
|
36
36
|
|
|
37
37
|
# =========================
|
|
38
|
-
# 4️⃣ Run AI Critic
|
|
38
|
+
# 4️⃣ Run AI Critic with plots
|
|
39
39
|
# =========================
|
|
40
40
|
critic = AICritic(model, X_leaky, y)
|
|
41
|
+
report = critic.evaluate(view="all", plot=True) # <<< plot=True ativa os gráficos
|
|
41
42
|
|
|
42
43
|
# =========================
|
|
43
|
-
# 5️⃣
|
|
44
|
+
# 5️⃣ Print selectable views
|
|
44
45
|
# =========================
|
|
45
46
|
print("\n================ EXECUTIVE VIEW ================\n")
|
|
46
|
-
pprint(
|
|
47
|
+
pprint(report["executive"])
|
|
47
48
|
|
|
48
49
|
print("\n================ TECHNICAL VIEW ================\n")
|
|
49
|
-
pprint(
|
|
50
|
+
pprint(report["technical"])
|
|
50
51
|
|
|
51
52
|
print("\n================ DETAILS VIEW ==================\n")
|
|
52
|
-
pprint(
|
|
53
|
+
pprint(report["details"])
|
|
53
54
|
|
|
54
55
|
print("\n================ MULTI VIEW ====================\n")
|
|
55
|
-
pprint(
|
|
56
|
+
pprint({k: report[k] for k in ["executive", "technical"]})
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
|
|
3
|
-
def evaluate(X, y):
|
|
4
|
-
report = {
|
|
5
|
-
"n_samples": int(X.shape[0]),
|
|
6
|
-
"n_features": int(X.shape[1]),
|
|
7
|
-
"has_nan": bool(np.isnan(X).any() or np.isnan(y).any())
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
# Class balance (JSON-safe)
|
|
11
|
-
if len(set(y)) < 20:
|
|
12
|
-
values, counts = np.unique(y, return_counts=True)
|
|
13
|
-
report["class_balance"] = {
|
|
14
|
-
int(v): int(c) for v, c in zip(values, counts)
|
|
15
|
-
}
|
|
16
|
-
else:
|
|
17
|
-
report["class_balance"] = "many_classes"
|
|
18
|
-
|
|
19
|
-
# 🔎 Data leakage detection (high correlation with target)
|
|
20
|
-
suspicious_features = []
|
|
21
|
-
|
|
22
|
-
y_mean = np.mean(y)
|
|
23
|
-
y_centered = y - y_mean
|
|
24
|
-
|
|
25
|
-
for i in range(X.shape[1]):
|
|
26
|
-
feature = X[:, i]
|
|
27
|
-
|
|
28
|
-
if np.std(feature) == 0:
|
|
29
|
-
continue
|
|
30
|
-
|
|
31
|
-
corr = np.corrcoef(feature, y_centered)[0, 1]
|
|
32
|
-
|
|
33
|
-
if abs(corr) > 0.98:
|
|
34
|
-
suspicious_features.append({
|
|
35
|
-
"feature_index": int(i),
|
|
36
|
-
"correlation": float(corr)
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
report["data_leakage"] = {
|
|
40
|
-
"suspected": bool(len(suspicious_features) > 0),
|
|
41
|
-
"details": suspicious_features,
|
|
42
|
-
"message": (
|
|
43
|
-
"Highly correlated features may reveal the target directly."
|
|
44
|
-
if suspicious_features
|
|
45
|
-
else "No obvious data leakage detected."
|
|
46
|
-
)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return report
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
from sklearn.model_selection import cross_val_score
|
|
2
|
-
|
|
3
|
-
def evaluate(model, X, y):
|
|
4
|
-
scores = cross_val_score(model, X, y, cv=3)
|
|
5
|
-
|
|
6
|
-
mean = float(scores.mean())
|
|
7
|
-
std = float(scores.std())
|
|
8
|
-
|
|
9
|
-
suspicious = mean > 0.995
|
|
10
|
-
|
|
11
|
-
return {
|
|
12
|
-
"cv_mean_score": mean,
|
|
13
|
-
"cv_std": std,
|
|
14
|
-
"suspiciously_perfect": suspicious,
|
|
15
|
-
"message": (
|
|
16
|
-
"Perfect CV score detected — possible data leakage."
|
|
17
|
-
if suspicious
|
|
18
|
-
else "CV performance within expected range."
|
|
19
|
-
)
|
|
20
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|