项目文件夹

文件
wehub-resource-sync 593b94c120
pytest / Unit Tests (push) Has been cancelled
pytest / Integration (integration_tests_a) (push) Has been cancelled
pytest / Integration (integration_tests_b) (push) Has been cancelled
pytest / Integration (integration_tests_c) (push) Has been cancelled
pytest / Integration (integration_tests_d) (push) Has been cancelled
pytest / Integration (integration_tests_e) (push) Has been cancelled
pytest / Integration (integration_tests_f) (push) Has been cancelled
pytest / Integration (integration_tests_g) (push) Has been cancelled
pytest / Integration (integration_tests_h) (push) Has been cancelled
pytest / Integration (integration_tests_i) (push) Has been cancelled
pytest / Integration (integration_tests_j) (push) Has been cancelled
pytest / Distributed (distributed_a) (push) Has been cancelled
pytest / Distributed (distributed_b) (push) Has been cancelled
pytest / Distributed (distributed_c) (push) Has been cancelled
pytest / Distributed (distributed_d) (push) Has been cancelled
pytest / Distributed (distributed_e) (push) Has been cancelled
pytest / Distributed (distributed_f) (push) Has been cancelled
pytest / Minimal Install (push) Has been cancelled
pytest / Event File (push) Has been cancelled
pytest (slow) / py-slow (push) Has been cancelled
Publish JSON Schema / publish-schema (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:49:20 +08:00

104 行
3.7 KiB
Python

"""Model introspection utilities.
Extracted from LudwigModel to reduce the god object. Provides:
- Weight collection
- Activation collection
- Schema generation
- Model summary
"""
import logging
from typing import Any
import torch
logger = logging.getLogger(__name__)
class ModelInspector:
"""Inspect and analyze a trained Ludwig model."""
def __init__(self, model: torch.nn.Module, config: dict, training_set_metadata: dict):
self.model = model
self.config = config
self.training_set_metadata = training_set_metadata
def collect_weights(self, tensor_names: list[str] | None = None) -> list[dict[str, Any]]:
"""Collect model weight tensors.
Args:
tensor_names: Specific parameter names to collect. None for all.
Returns:
List of dicts with 'name', 'shape', 'dtype', 'values' keys.
"""
results = []
for name, param in self.model.named_parameters():
if tensor_names is None or name in tensor_names:
results.append(
{
"name": name,
"shape": list(param.shape),
"dtype": str(param.dtype),
"requires_grad": param.requires_grad,
"num_elements": param.numel(),
}
)
return results
def model_summary(self) -> dict[str, Any]:
"""Generate a summary of the model architecture.
Returns:
Dict with parameter counts, layer info, and feature details.
"""
total_params = sum(p.numel() for p in self.model.parameters())
trainable_params = sum(p.numel() for p in self.model.parameters() if p.requires_grad)
frozen_params = total_params - trainable_params
# Model size in MB
model_size_mb = sum(p.numel() * p.element_size() for p in self.model.parameters()) / (1024 * 1024)
# Count layers by type
layer_counts = {}
for module in self.model.modules():
class_name = type(module).__name__
layer_counts[class_name] = layer_counts.get(class_name, 0) + 1
return {
"total_parameters": total_params,
"trainable_parameters": trainable_params,
"frozen_parameters": frozen_params,
"model_size_mb": round(model_size_mb, 2),
"layer_counts": layer_counts,
"model_type": self.config.get("model_type", "ecd"),
"combiner_type": self.config.get("combiner", {}).get("type", "concat"),
"num_input_features": len(self.config.get("input_features", [])),
"num_output_features": len(self.config.get("output_features", [])),
}
def feature_importance_proxy(self) -> dict[str, float]:
"""Estimate feature importance from encoder weight magnitudes.
This is a rough proxy, not a rigorous importance measure. For proper
feature importance, use SHAP or Captum via Ludwig's explain module.
Returns:
Dict mapping feature names to relative importance scores.
"""
importance = {}
if hasattr(self.model, "input_features"):
for name, feature in self.model.input_features.items():
total_weight_magnitude = 0.0
for param in feature.parameters():
total_weight_magnitude += param.abs().mean().item()
importance[name] = total_weight_magnitude
# Normalize to 0-1 range
if importance:
max_imp = max(importance.values())
if max_imp > 0:
importance = {k: v / max_imp for k, v in importance.items()}
return importance