Download src/model.py from HaseebArif11/DeepFake-Face-Detection: direct link, hf CLI and curl.
- Browser
- Download file 3.7 kB
-
https://huggingface.co/spaces/HaseebArif11/DeepFake-Face-Detection/resolve/main/src/model.py
- Command line
-
hf download hf://spaces/HaseebArif11/DeepFake-Face-Detection/src/model.py
-
curl -L -o model.py https://huggingface.co/spaces/HaseebArif11/DeepFake-Face-Detection/resolve/main/src/model.py
3.7 kB
| import os | |
| import shutil | |
| import tempfile | |
| import torch | |
| import torch.nn as nn | |
| import torchvision.models as models | |
| def build_efficientnet_b3(num_classes=2, dropout=0.4, pretrained=True): | |
| """ | |
| Constructs EfficientNet-B3 model architecture for binary DeepFake detection. | |
| Class order: 0 = fake / AI-generated, 1 = real / authentic. | |
| Default classifier matches saved checkpoint architecture: | |
| Dropout(0.4) -> Linear(1536, 512) -> SiLU() -> Dropout(0.4) -> Linear(512, 2) | |
| """ | |
| if pretrained: | |
| try: | |
| weights = models.EfficientNet_B3_Weights.DEFAULT | |
| model = models.efficientnet_b3(weights=weights) | |
| except Exception: | |
| model = models.efficientnet_b3(weights="IMAGENET1K_V1") | |
| else: | |
| model = models.efficientnet_b3(weights=None) | |
| in_features = model.classifier[1].in_features | |
| model.classifier = nn.Sequential( | |
| nn.Dropout(p=dropout, inplace=True), | |
| nn.Linear(in_features, 512), | |
| nn.SiLU(inplace=True), | |
| nn.Dropout(p=dropout, inplace=True), | |
| nn.Linear(512, num_classes) | |
| ) | |
| return model | |
| def load_model_weights(model: nn.Module, weights_path: str, device: torch.device) -> nn.Module: | |
| """ | |
| Loads saved model weights from a .pth file, PyTorch model checkpoint, or unzipped directory. | |
| """ | |
| if not os.path.exists(weights_path): | |
| raise FileNotFoundError(f"Model weights path does not exist: {weights_path}") | |
| loaded_obj = None | |
| # Handle directory format (e.g. unzipped PyTorch archive folder) | |
| if os.path.isdir(weights_path): | |
| import zipfile | |
| temp_pth = os.path.join(tempfile.gettempdir(), "temp_model_archive.pth") | |
| try: | |
| with zipfile.ZipFile(temp_pth, 'w', compression=zipfile.ZIP_STORED) as z: | |
| for root, _, files in os.walk(weights_path): | |
| for file in files: | |
| full_path = os.path.join(root, file) | |
| rel_path = os.path.relpath(full_path, weights_path) | |
| arc_name = os.path.join("archive", rel_path).replace("\\", "/") | |
| z.write(full_path, arcname=arc_name) | |
| try: | |
| loaded_obj = torch.load(temp_pth, map_location=device, weights_only=True) | |
| except Exception: | |
| loaded_obj = torch.load(temp_pth, map_location=device, weights_only=False) | |
| finally: | |
| if os.path.exists(temp_pth): | |
| os.remove(temp_pth) | |
| else: | |
| # File path | |
| try: | |
| loaded_obj = torch.load(weights_path, map_location=device, weights_only=True) | |
| except Exception: | |
| loaded_obj = torch.load(weights_path, map_location=device, weights_only=False) | |
| state_dict = loaded_obj | |
| if isinstance(loaded_obj, nn.Module): | |
| model = loaded_obj | |
| model = model.to(device) | |
| model.eval() | |
| return model | |
| elif isinstance(loaded_obj, dict): | |
| if "state_dict" in loaded_obj: | |
| state_dict = loaded_obj["state_dict"] | |
| elif "model_state_dict" in loaded_obj: | |
| state_dict = loaded_obj["model_state_dict"] | |
| # Adapt classifier if state_dict has single-layer classifier (classifier.1.weight shape [2, 1536]) | |
| if "classifier.1.weight" in state_dict and state_dict["classifier.1.weight"].shape == torch.Size([2, 1536]): | |
| in_features = model.classifier[1].in_features if hasattr(model.classifier[1], 'in_features') else 1536 | |
| model.classifier = nn.Sequential( | |
| nn.Dropout(p=0.4, inplace=True), | |
| nn.Linear(in_features, 2) | |
| ) | |
| model.load_state_dict(state_dict) | |
| model = model.to(device) | |
| model.eval() | |
| return model | |