Download script.py from safe-challenge/safe-video-example-submission: direct link, hf CLI and curl.
- Browser
- Download file 4.2 kB
-
https://huggingface.co/safe-challenge/safe-video-example-submission/resolve/main/script.py
- Command line
-
hf download hf://safe-challenge/safe-video-example-submission/script.py
-
curl -L -o script.py https://huggingface.co/safe-challenge/safe-video-example-submission/resolve/main/script.py
4.2 kB
| import pandas as pd | |
| from datasets import load_dataset | |
| import numpy as np | |
| import tqdm.auto as tqdm | |
| import os | |
| import io | |
| import torch | |
| from torchvision import transforms | |
| import time | |
| import av | |
| import torch | |
| import numpy as np | |
| # Import your model and anything else you want | |
| # You can even install other packages included in your repo | |
| # However, during the evaluation the container will not have access to the internet. | |
| # So you must include everything you need in your model repo. | |
| def preprocess( | |
| file_like: io.BytesIO, crop_size: int = -1, max_memory: int = 50 * 1024 * 1024, device: str = "cpu" | |
| ) -> torch.Tensor: | |
| """ | |
| This preprocessing function loads videos and reduces their input size if necessary. | |
| This is just a guide function; square center cropping may not be the most appropriate, | |
| 50 MB per video may not be enough, etc. | |
| Args: | |
| file_like (io.BytesIO): video bytes | |
| crop_size (int, optional): center crop adjustment (if frames are too large, this will crop) | |
| max_memory (int, optional): maximum memory per video to be saved as a tensor | |
| device (str, optional): which device to store the tensors on | |
| Returns: | |
| torch.Tensor: Tensor of video | |
| """ | |
| ## Define crop if applicable | |
| center_crop_transform = None | |
| if crop_size > 0: | |
| center_crop_transform = transforms.CenterCrop(crop_size) | |
| ## Open the video file | |
| file_like.seek(0) | |
| container = av.open(file_like) | |
| frames = [] | |
| every = 10 | |
| current_memory = 0 | |
| for i, frame in enumerate(container.decode(video=0)): | |
| if i % every == 0: | |
| frame_array = frame.to_ndarray(format="rgb24") | |
| frame_tensor = torch.from_numpy(frame_array).permute(2, 0, 1).float() | |
| ## Crop | |
| if center_crop_transform is not None: | |
| frame_tensor = center_crop_transform(frame_tensor) | |
| ## Append to the list | |
| frames.append(frame_tensor.to(device)) | |
| ## Memory check | |
| frame_bytes = frame_tensor.numel() * 4 # float32 = 4 bytes | |
| current_memory += frame_bytes | |
| if current_memory >= max_memory: | |
| break | |
| ## Stack as video | |
| return torch.stack(frames) | |
| class Model(torch.nn.Module): | |
| def __init__(self): | |
| super(Model, self).__init__() | |
| self.fc1 = torch.nn.Linear(10, 5) | |
| self.threshold = 0.0 | |
| def forward(self, x): | |
| ## generates a random float the same size as x | |
| return torch.randn(x.shape[0]).to(x.device) | |
| # load the dataset. dataset will be automatically downloaded to /tmp/data during evaluation | |
| DATASET_PATH = "/tmp/data" | |
| dataset_remote = load_dataset(DATASET_PATH, split="test", streaming=True) | |
| # load your model | |
| device = "cuda:0" | |
| model = Model().to(device) | |
| # iterate over the dataset | |
| out = [] | |
| for el in tqdm.tqdm(dataset_remote): | |
| # start_time = time.time() | |
| # each element is a dict | |
| # el["video"]["bytes"] contains bytes from reading the raw file | |
| # el["video"]["path"] containts the filename. This is just for reference and you cant actually load it | |
| # if you are using libraries that expect a file. You can use BytesIO object | |
| try: | |
| file_like = io.BytesIO(el["video"]["bytes"]) | |
| tensor = preprocess(file_like, device=device) | |
| with torch.no_grad(): | |
| # soft decision (such as log likelihood score) | |
| # positive score correspond to synthetic prediction | |
| # negative score correspond to real prediction | |
| score = model(tensor[None].to(device)).cpu().item() | |
| # we require a hard decision to be submited. so you need to pick a threshold | |
| pred = "generated" if score > model.threshold else "real" | |
| # append your prediction | |
| # "id" and "pred" are required. "score" will not be used in scoring but we encourage you to include it. We'll use it for analysis of the results | |
| out.append(dict(id=el["id"], pred=pred, score=score)) | |
| except Exception as e: | |
| print(e) | |
| print("failed", el["id"]) | |
| out.append(dict(id=el["id"])) | |
| # save the final result and that's it | |
| pd.DataFrame(out).to_csv("submission.csv", index=False) |