Um framework modular e extensível para experimentos de inferência sintética e perturbações controladas em algoritmos de Inteligência Artificial (IA), com foco em robustez, variabilidade e testes de falhas em dados e parâmetros.
smart-inference-ai-fusion/
├── main.py # Ponto de entrada principal para execução dos experiments
├── run.sh # Script utilitário para execução rápida
├── datasets/ # Arquivos CSV utilizados por loaders do tipo CSVDatasetLoader
├── experiments/ # Experimentos organizados por dataset (ex: iris/, wine/)
│ └── iris/
│ ├── knn_iris.py # KNN aplicado ao dataset Iris
│ ├── svm_iris.py # SVM aplicado ao dataset Iris
│ ├── run_all.py # Executa todos os experimentos do Iris
│ └── ...
├── results/ # Resultados e logs de inferência (ex: parâmetros perturbados)
├── src/ # Código-fonte principal do framework
│ ├── core/ # Classes base para Experiment, Model e Dataset
│ ├── datasets/ # Factory e loaders de datasets (sklearn, csv, etc.)
│ ├── inference/ # Módulo de inferência
│ │ ├── engine/ # Orquestradores de inferência (InferenceEngine, LabelRunner, etc.)
│ │ ├── pipeline/ # Pipeline unificada que aplica todas as inferências
│ │ ├── transformations/
│ │ │ ├── data/ # Técnicas aplicadas aos dados de entrada (X)
│ │ │ ├── label/ # Técnicas aplicadas aos rótulos (y)
│ │ │ └── params/ # Estratégias de perturbação nos parâmetros
│ ├── models/ # Implementações dos modelos de IA (KNN, SVM, Tree, etc.)
│ ├── utils/ # Relatórios, enums, tipos e métricas
│ │ └── types.py # Tipos pydantic e enums como DatasetSourceType, ReportMode
└── requirements.txt # Lista de dependências do projeto
- Python 3.10+
- Ambiente virtual (ex:
venv
ouconda
)
pip install -r requirements.txt
# Forma recomendada
./run.sh
# Ou manualmente:
PYTHONPATH=src python main.py
Um experimento representa a aplicação de um algoritmo a um dataset, com ou sem inferência aplicada (nos dados e/ou nos parâmetros).
Utilize a DatasetFactory
para criar dinamicamente o carregador com o dataset na origem (sklearn
, csv
, etc):
from datasets.factory import DatasetFactory
from utils.types import DatasetSourceType, SklearnDatasetName
dataset = DatasetFactory.create(
source_type=DatasetSourceType.SKLEARN,
name=SklearnDatasetName.IRIS
)
Para dataset externos (ex: .csv
), troque o tipo e informe o caminho:
dataset = DatasetFactory.create(
source_type=DatasetSourceType.CSV,
path="datasets/wine/wine.csv",
label_column="target"
)
Importe o modelo desejado e configure os parâmetros base:
from models.knn_model import KNNModel
base_params = {"n_neighbors": 3, "weights": "uniform"}
model = KNNModel(base_params)
Use a função apply_param_inference
para aplicar perturbações nos hiperparâmetros:
from inference.pipeline.inference_pipeline import InferencePipeline
pipeline = InferencePipeline()
model, param_log = pipeline.apply_param_inference(
model_class=KNNModel,
base_params=base_params,
seed=42,
ignore_rules={"weights"}
)
- Crie o dicionário com as configurações de perturbação validadas por Pydantic:
from utils.types import DatasetNoiseConfig
dataset_noise_config = DatasetNoiseConfig(
noise_level=0.2,
truncate_decimals=1,
quantize_bins=5,
cast_to_int=False,
shuffle_fraction=0.1,
scale_range=(0.8, 1.2),
zero_out_fraction=0.05,
insert_nan_fraction=0.05,
outlier_fraction=0.05,
add_dummy_features=2,
duplicate_features=2,
feature_selective_noise=(0.3, [0, 2]),
remove_features=[1, 3],
feature_swap=[0, 2],
label_noise_fraction=0.1
)
pipeline = InferencePipeline(dataset_noise_config=dataset_noise_config)
X_train, X_test, y_train, y_test = dataset.load_data()
X_train, X_test = pipeline.apply_data_inference(X_train, X_test)
y_train, y_test = pipeline.apply_label_inference(y_train, y_test)
Monte o experimento com ou sem inferência:
from core.experiment import Experiment
experiment = Experiment(model, dataset)
metrics = experiment.run(X_train, X_test, y_train, y_test)
from utils.report import report_data, ReportMode
report_data(metrics, mode=ReportMode.PRINT)
report_data(param_log, mode=ReportMode.JSON, file_path="results/knn_param_log.json")
- Crie uma função run() que chame:
run_<algoritmo>_without_inference()
run_<algoritmo>_with_inference()
-
Registre essa função em
experiments/<dataset>/run_all.py
-
Inclua no
__init__.py
da pastaexperiments/<dataset>/
Os algoritmos são encapsulados em classes e herdados de BaseModel
.
- Crie um novo arquivo em
src/models/
, ex:knn_model.py
- Implemente a classe
KNNModel
, com os métodos:train(self, X_train, y_train)
evaluate(self, X_test, y_test)
→ usandoevaluate_all()
- Use esse novo modelo em um experimento como qualquer outro
O carregamento de datasets é feito através da classe DatasetFactory
, que seleciona dinamicamente a origem dos dados: sklearn
, csv
, ou futuras integrações.
-
Via
scikit-learn
: usando oSklearnDatasetLoader
-
Via
.csv
: usando oCSVDatasetLoader
- Registre o nome do dataset no enum
SklearnDatasetName
:class SklearnDatasetName(Enum): IRIS = "iris" WINE = "wine"
- Use no experimento:
dataset = DatasetFactory.create(DatasetSourceType.SKLEARN, name=SklearnDatasetName.IRIS)
-
Coloque o arquivo
.csv
emdatasets/<nome>/
, ex:datasets/iris/iris.csv
-
Use o
CSVDatasetLoader
no experimento:dataset = DatasetFactory.create( DatasetSourceType.CSV, path="datasets/wine/wine.csv", label_column="target" )
Técnicas de inferência são componentes modulares aplicadas aos dados de entrada (X), aos rótulos (y) ou aos parâmetros (kwargs) dos modelos.
Cada técnica de inferência é representada por uma classe que herda de InferenceTransformation
(ou equivalente) e implementa o método apply(...)
.
Cada técnica de inferência é representada por uma classe que herda de InferenceTransformation
(ou equivalente) e implementa o método apply(...)
.
Passos:
-
Crie um novo arquivo ou edite um existente em
src/inference/transformations/data/
. -
Crie uma nova classe com o método:
class MinhaTransformacao(InferenceTransformation):
def apply(self, X):
# sua lógica de transformação
return X_modificado
-
Registre a nova transformação em
src/inference/engine/inference_engine.py
, adicionando uma verificação no construtor e incluindo no pipeline. -
Adicione um campo correspondente no
DatasetNoiseConfig
(com validação Pydantic). -
Utilize nos experimentos via
InferencePipeline
.
Passos:
-
Crie uma nova classe em
src/inference/transformations/label/
, herdando de LabelTransformation (ou base similar). -
Implemente o método
apply(self, y)
. -
Registre no
LabelInferenceEngine
(src/inference/engine/label_runner.py
). -
Configure no campo
label_noise_fraction
ou crie um novo campo emDatasetNoiseConfig
.
Essas técnicas são tratadas por SmartParameterPerturber
.
-
A lógica de perturbação está em
src/inference/transformations/params/parameter_perturber.py
. -
Para novas estratégias (ex:
replace_with_random
), adicione métodos internos na classe. -
O ponto de entrada principal está em
src/inference/engine/param_runner.py
via a funçãoapply_param_inference()
.
⚠️ As três categorias são independentes, mas integradas por meio da InferencePipeline. Você pode aplicar apenas uma, duas ou todas combinadas.
Este framework suporta inferência em dois níveis:
Técnicas que simulam ruído, falhas e distorções nos dados de entrada.
- Ruído Aditivo:
GaussianNoise, FeatureSelectiveNoise
- Redução de Precisão:
TruncateDecimals, CastToInt, Quantize
- Perturbação Estrutural:
ShuffleFeatures, ScaleFeatures, RemoveFeatures, FeatureSwap
- Corrupção Direta:
ZeroOut, InsertNaN
- Outliers:
InjectOutliers
- Distração Semântica:
AddDummyFeatures, DuplicateFeatures
- Label Noise:
LabelNoise
- Alterações baseadas em tipo (
int
,float
,str
,bool
) - Estratégias como
add_noise
,cast
,drop
,flip,
etc. - Filtros por nome de parâmetro e validação automática do modelo
- Geração de logs JSON para rastreamento de inferências aplicadas
Essa seção serve como referência rápida para desenvolvedores que forem integrar novos módulos, criar loaders ou escrever experimentos
Local: src/utils/types.py
class DatasetSourceType(Enum):
SKLEARN = "sklearn"
CSV = "csv"
class ReportMode(Enum):
PRINT = "print"
JSON = "json"
class SklearnDatasetName(Enum):
IRIS = "iris"
WINE = "wine"
BREAST_CANCER = "breast_cancer"
DIGITS = "digits"
class DatasetNoiseConfig(BaseModel):
noise_level: Optional[float] = None # Intensidade de ruído gaussiano
truncate_decimals: Optional[int] = None # Número de casas decimais
quantize_bins: Optional[int] = None # Quantização em N bins
cast_to_int: Optional[bool] = None # Converte para int
shuffle_fraction: Optional[float] = None # Fração de colunas embaralhadas
scale_range: Optional[Tuple[float, float]] = None # Intervalo de escala (min, max)
zero_out_fraction: Optional[float] = None # Fração de valores zerados
insert_nan_fraction: Optional[float] = None # Fração de NaNs inseridos
outlier_fraction: Optional[float] = None # Fração de outliers
add_dummy_features: Optional[int] = None # N novas features aleatórias
duplicate_features: Optional[int] = None # N features duplicadas
feature_selective_noise: Optional[Tuple[float, List[int]]] = None # (nível, índices)
remove_features: Optional[List[int]] = None # Índices a remover
feature_swap: Optional[List[int]] = None # Índices a trocar entre si
label_noise_fraction: Optional[float] = None # Ruído nos rótulos
class CSVDatasetName(Enum):
TITANIC = "datasets/titanic/titanic_dataset.csv"
@property
def path(self):
return self.value
Avaliar a robustez e sensibilidade de algoritmos de IA em cenários realistas com:
- Ruído nos dados
- Falhas de coleta ou sensores
- Valores fora do padrão esperado
- Perturbações nos parâmetros do modelo