ai-critic 0.1.0__tar.gz → 0.2.0__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/PKG-INFO +250 -0
- ai_critic-0.2.0/README.md +240 -0
- ai_critic-0.2.0/ai_critic/critic.py +79 -0
- ai_critic-0.2.0/ai_critic/evaluators/config.py +35 -0
- ai_critic-0.2.0/ai_critic/evaluators/data.py +49 -0
- ai_critic-0.2.0/ai_critic/evaluators/performance.py +20 -0
- ai_critic-0.2.0/ai_critic/evaluators/robustness.py +47 -0
- ai_critic-0.2.0/ai_critic/evaluators/summary.py +96 -0
- ai_critic-0.2.0/ai_critic.egg-info/PKG-INFO +250 -0
- {ai_critic-0.1.0 → ai_critic-0.2.0}/ai_critic.egg-info/SOURCES.txt +1 -0
- {ai_critic-0.1.0 → ai_critic-0.2.0}/pyproject.toml +2 -2
- ai_critic-0.2.0/test/test_in_ia.py +55 -0
- ai_critic-0.1.0/PKG-INFO +0 -64
- ai_critic-0.1.0/README.md +0 -54
- ai_critic-0.1.0/ai_critic/critic.py +0 -30
- ai_critic-0.1.0/ai_critic/evaluators/config.py +0 -6
- ai_critic-0.1.0/ai_critic/evaluators/data.py +0 -14
- ai_critic-0.1.0/ai_critic/evaluators/performance.py +0 -11
- ai_critic-0.1.0/ai_critic/evaluators/robustness.py +0 -18
- ai_critic-0.1.0/ai_critic.egg-info/PKG-INFO +0 -64
- ai_critic-0.1.0/test/test_in_ia.py +0 -16
- {ai_critic-0.1.0 → ai_critic-0.2.0}/ai_critic/__init__.py +0 -0
- {ai_critic-0.1.0 → ai_critic-0.2.0}/ai_critic/evaluators/__init__.py +0 -0
- {ai_critic-0.1.0 → ai_critic-0.2.0}/ai_critic.egg-info/dependency_links.txt +0 -0
- {ai_critic-0.1.0 → ai_critic-0.2.0}/ai_critic.egg-info/requires.txt +0 -0
- {ai_critic-0.1.0 → ai_critic-0.2.0}/ai_critic.egg-info/top_level.txt +0 -0
- {ai_critic-0.1.0 → ai_critic-0.2.0}/setup.cfg +0 -0
- {ai_critic-0.1.0 → ai_critic-0.2.0}/test/test_model.py +0 -0
ai_critic-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ai-critic
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Fast AI evaluator for scikit-learn models
|
|
5
|
+
Author-email: Luiz Seabra <filipedemarco@yahoo.com>
|
|
6
|
+
Requires-Python: >=3.9
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: numpy
|
|
9
|
+
Requires-Dist: scikit-learn
|
|
10
|
+
|
|
11
|
+
# ai-critic
|
|
12
|
+
|
|
13
|
+
Automated Risk Auditor for Machine Learning Models
|
|
14
|
+
|
|
15
|
+
[](https://pypi.org/project/ai-critic/)
|
|
16
|
+
[](https://opensource.org/licenses/MIT)
|
|
17
|
+
|
|
18
|
+
## 🚀 O que é ai-critic?
|
|
19
|
+
|
|
20
|
+
**ai-critic** é um auditor de risco automatizado e 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.
|
|
21
|
+
|
|
22
|
+
Em vez de apenas relatar métricas, **ai-critic** responde a uma pergunta crítica:
|
|
23
|
+
|
|
24
|
+
> “Este modelo pode ser implantado com segurança?”
|
|
25
|
+
|
|
26
|
+
Ele faz isso analisando:
|
|
27
|
+
* **Integridade dos Dados:** (vazamento de dados, desequilíbrio, valores NaNs)
|
|
28
|
+
* **Estrutura do Modelo:** (risco de *overfitting*, complexidade)
|
|
29
|
+
* **Comportamento de Validação:** (pontuações suspeitamente perfeitas)
|
|
30
|
+
* **Robustez:** (sensibilidade a ruído)
|
|
31
|
+
|
|
32
|
+
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
|
+
|
|
37
|
+
## 🎯 Por que ai-critic existe: Filosofia Central
|
|
38
|
+
|
|
39
|
+
A maioria das ferramentas de ML:
|
|
40
|
+
* assume que métricas = verdade
|
|
41
|
+
* confia cegamente na validação cruzada
|
|
42
|
+
* expõe números brutos sem interpretação
|
|
43
|
+
|
|
44
|
+
**ai-critic é cético por design.**
|
|
45
|
+
|
|
46
|
+
Ele trata:
|
|
47
|
+
* pontuações perfeitas como sinais, não como sucesso
|
|
48
|
+
* métricas de robustez como dependentes do contexto
|
|
49
|
+
* a implantação como uma decisão de risco, não um limite de métrica
|
|
50
|
+
|
|
51
|
+
A filosofia central é: **Métricas não falham modelos — o contexto falha.**
|
|
52
|
+
|
|
53
|
+
ai-critic aplica heurísticas de raciocínio humano à avaliação de *machine learning*:
|
|
54
|
+
* “Isso é bom demais para ser verdade?”
|
|
55
|
+
* “Isso pode estar vazando o alvo?”
|
|
56
|
+
* “A robustez ainda importa se a linha de base estiver errada?”
|
|
57
|
+
|
|
58
|
+
## 🛠️ Instalação
|
|
59
|
+
|
|
60
|
+
Você pode instalar `ai-critic` usando pip:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install ai-critic
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Requisitos:**
|
|
67
|
+
* Python ≥ 3.8
|
|
68
|
+
* scikit-learn
|
|
69
|
+
|
|
70
|
+
## 💡 Início Rápido
|
|
71
|
+
|
|
72
|
+
Audite seu modelo treinado em poucas linhas de código:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from sklearn.datasets import load_breast_cancer
|
|
76
|
+
from sklearn.ensemble import RandomForestClassifier
|
|
77
|
+
from ai_critic import AICritic
|
|
78
|
+
|
|
79
|
+
# 1. Carregar dados e treinar um modelo (exemplo)
|
|
80
|
+
X, y = load_breast_cancer(return_X_y=True)
|
|
81
|
+
model = RandomForestClassifier(max_depth=20, random_state=42)
|
|
82
|
+
model.fit(X, y) # O modelo precisa estar treinado
|
|
83
|
+
|
|
84
|
+
# 2. Inicializar e avaliar com ai-critic
|
|
85
|
+
critic = AICritic(model, X, y)
|
|
86
|
+
report = critic.evaluate()
|
|
87
|
+
|
|
88
|
+
# O padrão é a visualização 'all' (todas as camadas)
|
|
89
|
+
print(report)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## 🧩 Saída Multi-Camadas
|
|
93
|
+
|
|
94
|
+
`ai-critic` nunca despeja tudo de uma vez. Ele estrutura os resultados em camadas de decisão claras.
|
|
95
|
+
|
|
96
|
+
### 🔹 Visão Executiva (`view="executive"`)
|
|
97
|
+
|
|
98
|
+
Projetada para CTOs, gerentes e *stakeholders*. Zero jargão de ML.
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
critic.evaluate(view="executive")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Exemplo de Saída:**
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"verdict": "❌ Não Confiável",
|
|
108
|
+
"risk_level": "high",
|
|
109
|
+
"deploy_recommended": false,
|
|
110
|
+
"main_reason": "Forte evidência de vazamento de dados inflando o desempenho do modelo."
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 🔹 Visão Técnica (`view="technical"`)
|
|
115
|
+
|
|
116
|
+
Projetada para engenheiros de ML. É acionável, diagnóstica e focada no que precisa ser corrigido.
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
critic.evaluate(view="technical")
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Exemplo de Saída:**
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"key_risks": [
|
|
126
|
+
"Vazamento de dados suspeito devido à correlação quase perfeita entre recurso e alvo.",
|
|
127
|
+
"Pontuação de validação cruzada perfeita detectada (estatisticamente improvável).",
|
|
128
|
+
"A profundidade da árvore pode ser muito alta para o tamanho do conjunto de dados."
|
|
129
|
+
],
|
|
130
|
+
"model_health": {
|
|
131
|
+
"data_leakage": true,
|
|
132
|
+
"suspicious_cv": true,
|
|
133
|
+
"structural_risk": true,
|
|
134
|
+
"robustness_verdict": "misleading"
|
|
135
|
+
},
|
|
136
|
+
"recommendations": [
|
|
137
|
+
"Auditar e remover recursos com vazamento.",
|
|
138
|
+
"Reduzir a complexidade do modelo.",
|
|
139
|
+
"Executar novamente a validação após a mitigação do vazamento."
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### 🔹 Visão Detalhada (`view="details"`)
|
|
145
|
+
|
|
146
|
+
Projetada para auditoria, depuração e conformidade.
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
critic.evaluate(view="details")
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Inclui:
|
|
153
|
+
* Métricas brutas
|
|
154
|
+
* Correlações
|
|
155
|
+
* Pontuações de robustez
|
|
156
|
+
* Avisos estruturais
|
|
157
|
+
* Rastreabilidade completa
|
|
158
|
+
|
|
159
|
+
### 🔹 Visão Combinada (`view="all"`)
|
|
160
|
+
|
|
161
|
+
Retorna todas as três camadas em um único dicionário.
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
critic.evaluate(view="all")
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Retorna:**
|
|
168
|
+
```json
|
|
169
|
+
{
|
|
170
|
+
"executive": {...},
|
|
171
|
+
"technical": {...},
|
|
172
|
+
"details": {...}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## ⚙️ API Principal
|
|
177
|
+
|
|
178
|
+
### `AICritic`
|
|
179
|
+
|
|
180
|
+
| Parâmetro | Descrição |
|
|
181
|
+
| :--- | :--- |
|
|
182
|
+
| `model` | Modelo `scikit-learn` treinado. |
|
|
183
|
+
| `X` | Matriz de recursos (features). |
|
|
184
|
+
| `y` | Vetor alvo (target). |
|
|
185
|
+
|
|
186
|
+
**Uso:** `AICritic(model, X, y)`
|
|
187
|
+
|
|
188
|
+
### `evaluate()`
|
|
189
|
+
|
|
190
|
+
| Parâmetro | Descrição |
|
|
191
|
+
| :--- | :--- |
|
|
192
|
+
| `view` | A camada de saída desejada: `"executive"`, `"technical"`, `"details"`, ou `"all"` (padrão). |
|
|
193
|
+
|
|
194
|
+
**Uso:** `evaluate(view="all")`
|
|
195
|
+
|
|
196
|
+
## 🧠 O que ai-critic Detecta
|
|
197
|
+
|
|
198
|
+
| Categoria | Riscos Detectados |
|
|
199
|
+
| :--- | :--- |
|
|
200
|
+
| **🔍 Riscos de Dados** | Vazamento de alvo via correlação, NaNs, Desequilíbrio de classe. |
|
|
201
|
+
| **🧱 Riscos Estruturais** | Árvores excessivamente complexas, Altas proporções de recurso/amostra, *Configuration smells*. |
|
|
202
|
+
| **📈 Riscos de Validação** | Pontuações de CV suspeitamente perfeitas, Variância irrealista. |
|
|
203
|
+
| **🧪 Riscos de Robustez** | Sensibilidade a ruído, Robustez enganosa quando a linha de base está inflada. |
|
|
204
|
+
|
|
205
|
+
### 🧪 Exemplo: Detecção de Vazamento de Dados
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
import numpy as np
|
|
209
|
+
# ... (código de importação e modelo)
|
|
210
|
+
|
|
211
|
+
# Vazamento artificial: adicionando o alvo como um recurso
|
|
212
|
+
X_leaky = np.hstack([X, y.reshape(-1, 1)])
|
|
213
|
+
|
|
214
|
+
critic = AICritic(model, X_leaky, y)
|
|
215
|
+
executive_report = critic.evaluate(view="executive")
|
|
216
|
+
|
|
217
|
+
print(executive_report)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**Resultado (Executive View):**
|
|
221
|
+
```
|
|
222
|
+
❌ Não Confiável
|
|
223
|
+
Forte evidência de vazamento de dados inflando o desempenho do modelo.
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## 🛡️ Melhores Práticas
|
|
227
|
+
|
|
228
|
+
* Execute `ai-critic` antes da implantação.
|
|
229
|
+
* Nunca confie cegamente em pontuações de CV perfeitas.
|
|
230
|
+
* Use a **Visão Executiva** no seu pipeline de CI/CD como um *gate* de modelo.
|
|
231
|
+
* Use a **Visão Técnica** durante a iteração do modelo.
|
|
232
|
+
* Use a **Visão Detalhada** para auditorias e conformidade.
|
|
233
|
+
|
|
234
|
+
## 🧭 Casos de Uso Típicos
|
|
235
|
+
|
|
236
|
+
* Auditorias de modelo pré-implantação.
|
|
237
|
+
* Governança e conformidade de ML.
|
|
238
|
+
* *Gates* de modelo em CI/CD.
|
|
239
|
+
* Ensino de ceticismo em ML.
|
|
240
|
+
* Explicação de risco de ML para *stakeholders* não técnicos.
|
|
241
|
+
|
|
242
|
+
## 📄 Licença
|
|
243
|
+
|
|
244
|
+
Distribuído sob a **Licença MIT**.
|
|
245
|
+
|
|
246
|
+
## 🧠 Nota Final
|
|
247
|
+
|
|
248
|
+
`ai-critic` não é uma ferramenta de *benchmark*. **É uma ferramenta de decisão.**
|
|
249
|
+
|
|
250
|
+
Se um modelo falhar aqui, isso não significa que ele é ruim — significa que ele não deve ser confiável **ainda**.
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# ai-critic
|
|
2
|
+
|
|
3
|
+
Automated Risk Auditor for Machine Learning Models
|
|
4
|
+
|
|
5
|
+
[](https://pypi.org/project/ai-critic/)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## 🚀 O que é ai-critic?
|
|
9
|
+
|
|
10
|
+
**ai-critic** é um auditor de risco automatizado e 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.
|
|
11
|
+
|
|
12
|
+
Em vez de apenas relatar métricas, **ai-critic** responde a uma pergunta crítica:
|
|
13
|
+
|
|
14
|
+
> “Este modelo pode ser implantado com segurança?”
|
|
15
|
+
|
|
16
|
+
Ele faz isso analisando:
|
|
17
|
+
* **Integridade dos Dados:** (vazamento de dados, desequilíbrio, valores NaNs)
|
|
18
|
+
* **Estrutura do Modelo:** (risco de *overfitting*, complexidade)
|
|
19
|
+
* **Comportamento de Validação:** (pontuações suspeitamente perfeitas)
|
|
20
|
+
* **Robustez:** (sensibilidade a ruído)
|
|
21
|
+
|
|
22
|
+
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
|
+
|
|
27
|
+
## 🎯 Por que ai-critic existe: Filosofia Central
|
|
28
|
+
|
|
29
|
+
A maioria das ferramentas de ML:
|
|
30
|
+
* assume que métricas = verdade
|
|
31
|
+
* confia cegamente na validação cruzada
|
|
32
|
+
* expõe números brutos sem interpretação
|
|
33
|
+
|
|
34
|
+
**ai-critic é cético por design.**
|
|
35
|
+
|
|
36
|
+
Ele trata:
|
|
37
|
+
* pontuações perfeitas como sinais, não como sucesso
|
|
38
|
+
* métricas de robustez como dependentes do contexto
|
|
39
|
+
* a implantação como uma decisão de risco, não um limite de métrica
|
|
40
|
+
|
|
41
|
+
A filosofia central é: **Métricas não falham modelos — o contexto falha.**
|
|
42
|
+
|
|
43
|
+
ai-critic aplica heurísticas de raciocínio humano à avaliação de *machine learning*:
|
|
44
|
+
* “Isso é bom demais para ser verdade?”
|
|
45
|
+
* “Isso pode estar vazando o alvo?”
|
|
46
|
+
* “A robustez ainda importa se a linha de base estiver errada?”
|
|
47
|
+
|
|
48
|
+
## 🛠️ Instalação
|
|
49
|
+
|
|
50
|
+
Você pode instalar `ai-critic` usando pip:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install ai-critic
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Requisitos:**
|
|
57
|
+
* Python ≥ 3.8
|
|
58
|
+
* scikit-learn
|
|
59
|
+
|
|
60
|
+
## 💡 Início Rápido
|
|
61
|
+
|
|
62
|
+
Audite seu modelo treinado em poucas linhas de código:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from sklearn.datasets import load_breast_cancer
|
|
66
|
+
from sklearn.ensemble import RandomForestClassifier
|
|
67
|
+
from ai_critic import AICritic
|
|
68
|
+
|
|
69
|
+
# 1. Carregar dados e treinar um modelo (exemplo)
|
|
70
|
+
X, y = load_breast_cancer(return_X_y=True)
|
|
71
|
+
model = RandomForestClassifier(max_depth=20, random_state=42)
|
|
72
|
+
model.fit(X, y) # O modelo precisa estar treinado
|
|
73
|
+
|
|
74
|
+
# 2. Inicializar e avaliar com ai-critic
|
|
75
|
+
critic = AICritic(model, X, y)
|
|
76
|
+
report = critic.evaluate()
|
|
77
|
+
|
|
78
|
+
# O padrão é a visualização 'all' (todas as camadas)
|
|
79
|
+
print(report)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## 🧩 Saída Multi-Camadas
|
|
83
|
+
|
|
84
|
+
`ai-critic` nunca despeja tudo de uma vez. Ele estrutura os resultados em camadas de decisão claras.
|
|
85
|
+
|
|
86
|
+
### 🔹 Visão Executiva (`view="executive"`)
|
|
87
|
+
|
|
88
|
+
Projetada para CTOs, gerentes e *stakeholders*. Zero jargão de ML.
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
critic.evaluate(view="executive")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Exemplo de Saída:**
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"verdict": "❌ Não Confiável",
|
|
98
|
+
"risk_level": "high",
|
|
99
|
+
"deploy_recommended": false,
|
|
100
|
+
"main_reason": "Forte evidência de vazamento de dados inflando o desempenho do modelo."
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### 🔹 Visão Técnica (`view="technical"`)
|
|
105
|
+
|
|
106
|
+
Projetada para engenheiros de ML. É acionável, diagnóstica e focada no que precisa ser corrigido.
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
critic.evaluate(view="technical")
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Exemplo de Saída:**
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"key_risks": [
|
|
116
|
+
"Vazamento de dados suspeito devido à correlação quase perfeita entre recurso e alvo.",
|
|
117
|
+
"Pontuação de validação cruzada perfeita detectada (estatisticamente improvável).",
|
|
118
|
+
"A profundidade da árvore pode ser muito alta para o tamanho do conjunto de dados."
|
|
119
|
+
],
|
|
120
|
+
"model_health": {
|
|
121
|
+
"data_leakage": true,
|
|
122
|
+
"suspicious_cv": true,
|
|
123
|
+
"structural_risk": true,
|
|
124
|
+
"robustness_verdict": "misleading"
|
|
125
|
+
},
|
|
126
|
+
"recommendations": [
|
|
127
|
+
"Auditar e remover recursos com vazamento.",
|
|
128
|
+
"Reduzir a complexidade do modelo.",
|
|
129
|
+
"Executar novamente a validação após a mitigação do vazamento."
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 🔹 Visão Detalhada (`view="details"`)
|
|
135
|
+
|
|
136
|
+
Projetada para auditoria, depuração e conformidade.
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
critic.evaluate(view="details")
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Inclui:
|
|
143
|
+
* Métricas brutas
|
|
144
|
+
* Correlações
|
|
145
|
+
* Pontuações de robustez
|
|
146
|
+
* Avisos estruturais
|
|
147
|
+
* Rastreabilidade completa
|
|
148
|
+
|
|
149
|
+
### 🔹 Visão Combinada (`view="all"`)
|
|
150
|
+
|
|
151
|
+
Retorna todas as três camadas em um único dicionário.
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
critic.evaluate(view="all")
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Retorna:**
|
|
158
|
+
```json
|
|
159
|
+
{
|
|
160
|
+
"executive": {...},
|
|
161
|
+
"technical": {...},
|
|
162
|
+
"details": {...}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## ⚙️ API Principal
|
|
167
|
+
|
|
168
|
+
### `AICritic`
|
|
169
|
+
|
|
170
|
+
| Parâmetro | Descrição |
|
|
171
|
+
| :--- | :--- |
|
|
172
|
+
| `model` | Modelo `scikit-learn` treinado. |
|
|
173
|
+
| `X` | Matriz de recursos (features). |
|
|
174
|
+
| `y` | Vetor alvo (target). |
|
|
175
|
+
|
|
176
|
+
**Uso:** `AICritic(model, X, y)`
|
|
177
|
+
|
|
178
|
+
### `evaluate()`
|
|
179
|
+
|
|
180
|
+
| Parâmetro | Descrição |
|
|
181
|
+
| :--- | :--- |
|
|
182
|
+
| `view` | A camada de saída desejada: `"executive"`, `"technical"`, `"details"`, ou `"all"` (padrão). |
|
|
183
|
+
|
|
184
|
+
**Uso:** `evaluate(view="all")`
|
|
185
|
+
|
|
186
|
+
## 🧠 O que ai-critic Detecta
|
|
187
|
+
|
|
188
|
+
| Categoria | Riscos Detectados |
|
|
189
|
+
| :--- | :--- |
|
|
190
|
+
| **🔍 Riscos de Dados** | Vazamento de alvo via correlação, NaNs, Desequilíbrio de classe. |
|
|
191
|
+
| **🧱 Riscos Estruturais** | Árvores excessivamente complexas, Altas proporções de recurso/amostra, *Configuration smells*. |
|
|
192
|
+
| **📈 Riscos de Validação** | Pontuações de CV suspeitamente perfeitas, Variância irrealista. |
|
|
193
|
+
| **🧪 Riscos de Robustez** | Sensibilidade a ruído, Robustez enganosa quando a linha de base está inflada. |
|
|
194
|
+
|
|
195
|
+
### 🧪 Exemplo: Detecção de Vazamento de Dados
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
import numpy as np
|
|
199
|
+
# ... (código de importação e modelo)
|
|
200
|
+
|
|
201
|
+
# Vazamento artificial: adicionando o alvo como um recurso
|
|
202
|
+
X_leaky = np.hstack([X, y.reshape(-1, 1)])
|
|
203
|
+
|
|
204
|
+
critic = AICritic(model, X_leaky, y)
|
|
205
|
+
executive_report = critic.evaluate(view="executive")
|
|
206
|
+
|
|
207
|
+
print(executive_report)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Resultado (Executive View):**
|
|
211
|
+
```
|
|
212
|
+
❌ Não Confiável
|
|
213
|
+
Forte evidência de vazamento de dados inflando o desempenho do modelo.
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## 🛡️ Melhores Práticas
|
|
217
|
+
|
|
218
|
+
* Execute `ai-critic` antes da implantação.
|
|
219
|
+
* Nunca confie cegamente em pontuações de CV perfeitas.
|
|
220
|
+
* Use a **Visão Executiva** no seu pipeline de CI/CD como um *gate* de modelo.
|
|
221
|
+
* Use a **Visão Técnica** durante a iteração do modelo.
|
|
222
|
+
* Use a **Visão Detalhada** para auditorias e conformidade.
|
|
223
|
+
|
|
224
|
+
## 🧭 Casos de Uso Típicos
|
|
225
|
+
|
|
226
|
+
* Auditorias de modelo pré-implantação.
|
|
227
|
+
* Governança e conformidade de ML.
|
|
228
|
+
* *Gates* de modelo em CI/CD.
|
|
229
|
+
* Ensino de ceticismo em ML.
|
|
230
|
+
* Explicação de risco de ML para *stakeholders* não técnicos.
|
|
231
|
+
|
|
232
|
+
## 📄 Licença
|
|
233
|
+
|
|
234
|
+
Distribuído sob a **Licença MIT**.
|
|
235
|
+
|
|
236
|
+
## 🧠 Nota Final
|
|
237
|
+
|
|
238
|
+
`ai-critic` não é uma ferramenta de *benchmark*. **É uma ferramenta de decisão.**
|
|
239
|
+
|
|
240
|
+
Se um modelo falhar aqui, isso não significa que ele é ruim — significa que ele não deve ser confiável **ainda**.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from ai_critic.evaluators import (
|
|
2
|
+
robustness,
|
|
3
|
+
config,
|
|
4
|
+
data,
|
|
5
|
+
performance
|
|
6
|
+
)
|
|
7
|
+
from ai_critic.evaluators.summary import HumanSummary
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AICritic:
|
|
11
|
+
"""
|
|
12
|
+
Automated reviewer for scikit-learn models.
|
|
13
|
+
Produces a multi-layered risk assessment.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, model, X, y):
|
|
17
|
+
self.model = model
|
|
18
|
+
self.X = X
|
|
19
|
+
self.y = y
|
|
20
|
+
|
|
21
|
+
def evaluate(self, view="all"):
|
|
22
|
+
"""
|
|
23
|
+
view:
|
|
24
|
+
- "all"
|
|
25
|
+
- "executive"
|
|
26
|
+
- "technical"
|
|
27
|
+
- "details"
|
|
28
|
+
- list of views
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
# =========================
|
|
32
|
+
# Low-level technical details
|
|
33
|
+
# =========================
|
|
34
|
+
details = {}
|
|
35
|
+
|
|
36
|
+
data_report = data(self.X, self.y)
|
|
37
|
+
details["data"] = data_report
|
|
38
|
+
|
|
39
|
+
details["config"] = config(
|
|
40
|
+
self.model,
|
|
41
|
+
n_samples=data_report["n_samples"],
|
|
42
|
+
n_features=data_report["n_features"]
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
details["performance"] = performance(
|
|
46
|
+
self.model, self.X, self.y
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
details["robustness"] = robustness(
|
|
50
|
+
self.model,
|
|
51
|
+
self.X,
|
|
52
|
+
self.y,
|
|
53
|
+
leakage_suspected=data_report["data_leakage"]["suspected"]
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
# =========================
|
|
57
|
+
# Human interpretation
|
|
58
|
+
# =========================
|
|
59
|
+
human = HumanSummary().generate(details)
|
|
60
|
+
|
|
61
|
+
# =========================
|
|
62
|
+
# Full payload
|
|
63
|
+
# =========================
|
|
64
|
+
payload = {
|
|
65
|
+
"executive": human["executive_summary"],
|
|
66
|
+
"technical": human["technical_summary"],
|
|
67
|
+
"details": details
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# =========================
|
|
71
|
+
# View selector
|
|
72
|
+
# =========================
|
|
73
|
+
if view == "all":
|
|
74
|
+
return payload
|
|
75
|
+
|
|
76
|
+
if isinstance(view, list):
|
|
77
|
+
return {k: payload[k] for k in view if k in payload}
|
|
78
|
+
|
|
79
|
+
return payload.get(view)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
def evaluate(model, n_samples=None, n_features=None):
|
|
4
|
+
params = model.get_params()
|
|
5
|
+
model_type = type(model).__name__
|
|
6
|
+
|
|
7
|
+
report = {
|
|
8
|
+
"model_type": model_type,
|
|
9
|
+
"n_params": len(params),
|
|
10
|
+
"uses_random_state": "random_state" in params
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
# 🧠 Structural overfitting heuristics
|
|
14
|
+
warnings = []
|
|
15
|
+
|
|
16
|
+
if n_samples and hasattr(model, "max_depth"):
|
|
17
|
+
max_depth = params.get("max_depth")
|
|
18
|
+
if max_depth is not None:
|
|
19
|
+
recommended_depth = math.log2(n_samples)
|
|
20
|
+
if max_depth > recommended_depth:
|
|
21
|
+
warnings.append({
|
|
22
|
+
"issue": "structural_overfitting_risk",
|
|
23
|
+
"max_depth": max_depth,
|
|
24
|
+
"recommended_max_depth": int(recommended_depth),
|
|
25
|
+
"message": "Tree depth may be too high for dataset size."
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
if n_samples and n_features and n_features > n_samples:
|
|
29
|
+
warnings.append({
|
|
30
|
+
"issue": "high_feature_sample_ratio",
|
|
31
|
+
"message": "More features than samples can cause instability."
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
report["structural_warnings"] = warnings
|
|
35
|
+
return report
|
|
@@ -0,0 +1,49 @@
|
|
|
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
|
|
@@ -0,0 +1,20 @@
|
|
|
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
|
+
}
|