Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added PROD_EXPORT_FINAL.sqlite
Binary file not shown.
17 changes: 17 additions & 0 deletions benchmarks/templates/benchmarks/model.html
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,19 @@ <h1 class="title">Anonymous Model #{{ model.id }}</h1>
<span class="has-text-weight-bold">{{ visual_degrees }}</span> degrees
</div>
</div>

<div class="box" id="selected-metadata-box">
<div class="card-content">
<p id="selected-metadata-title" class="subtitle is-5" style="display: none;">
Selected Layers Metadata
</p>
<div id="selected-metadata-content">
<span class="has-text-grey">Shift-click layers to view metadata.</span>
</div>
</div>
</div>


{% endblock %}


Expand Down Expand Up @@ -287,6 +300,10 @@ <h3 id="scores" class="title is-3">Scores on benchmarks</h3>
</div>
</div>

<!-- ADD VISUALIZATION HERE -->
{% include "benchmarks/model_visual.html" with model_architecture=model_architecture %}


{# Usage #}
<div class="box">
<h4 class="subtitle is-4">
Expand Down
45 changes: 45 additions & 0 deletions benchmarks/templates/benchmarks/model_visual.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{% load static %}

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Model Visualization - {{ model.id }}</title>
<script src="https://d3js.org/d3.v7.min.js"></script>

</head>
<script>
document.addEventListener("DOMContentLoaded", function() {
console.log("D3.js is loaded:", d3);
});
</script>


<body>
<h1>Model Architecture Visualization (Model ID: {{ model.id }})</h1>

<div id="svg-wrapper" style="width: 100%; overflow-x: auto;">
<svg width="1600" height="600"></svg>
</div>

<!-- Floating info box for layer metadata -->
<div id="layer-info-box"
style="display:none; position:absolute; z-index:1000; background:white; border:1px solid #ccc;
padding:10px; border-radius:8px; box-shadow:0 4px 8px rgba(0,0,0,0.2); font-size:14px;">
</div>


{{ visualization_metadata|json_script:"layers-json" }}




<script src="{% static 'benchmarks/js/draw_layers.js' %}"></script>



</body>
</html>



131 changes: 131 additions & 0 deletions benchmarks/views/extract_model_architecture.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# import json
# import os
# import torch
# from torchsummary import summary
# from io import StringIO
# from contextlib import redirect_stdout
#
# # Directory where model JSON files will be stored
# ARCHITECTURE_JSON_DIR = "static/model_architecture_json/"
#
#
# def extract_trainable_layers(model, model_id):
# """
# Extracts trainable layers from a PyTorch model and saves them as a JSON file.
# - Trainable layers are those where `Param # != 0`
# - Uses `torchsummary.summary()` to get layer details.
# """
# os.makedirs(ARCHITECTURE_JSON_DIR, exist_ok=True)
#
# # Redirect torchsummary output to a string buffer
# buffer = StringIO()
# with redirect_stdout(buffer):
# summary(model, input_size=(3, 224, 224)) # Assuming an image model with 3x224x224 input
#
# output = buffer.getvalue()
# lines = output.split("\n") # Convert output to lines
#
# model_params = {
# "Visualization-Layer-Parameters": {}
# }
#
# # Process each line and extract Layer Type, Output Shape, and Param #
# for line in lines[3:]: # Skip the header
# parts = line.split()
# if len(parts) < 4: # Ignore invalid lines
# continue
#
# layer_name = parts[0] # First column is Layer Type
# param_count = parts[-1] # Last column is Param #
#
# try:
# param_count = int(param_count) # Convert to integer
# except ValueError:
# continue # Skip if it's not a number
#
# if param_count > 0: # **Only keep trainable layers**
# model_params["Visualization-Layer-Parameters"][layer_name] = [param_count, param_count + 5] # Example range
#
# # Define JSON file path
# json_file_path = os.path.join(ARCHITECTURE_JSON_DIR, f"model_{model_id}.json")
#
# # Save JSON data
# with open(json_file_path, "w") as json_file:
# json.dump(model_params, json_file, indent=4)
#
# print(f"Model architecture saved at: {json_file_path}")
#
#
# if __name__ == "__main__":
# # Example: Use a pre-trained ResNet model for testing
# model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet50', pretrained=True)
# extract_trainable_layers(model, model_id="resnet50")

import json
import os
import torch
from torchsummary import summary
from io import StringIO
from contextlib import redirect_stdout

ARCHITECTURE_JSON_DIR = "static/model_architecture_json/"

import json
import os
import torch
from torchsummary import summary
from io import StringIO
from contextlib import redirect_stdout

ARCHITECTURE_JSON_DIR = "static/model_architecture_json/"


def extract_model_parameters(model, model_id):
"""
Extracts model layer details (Layer Name, Output Shape, Param #) and saves as JSON.
"""
os.makedirs(ARCHITECTURE_JSON_DIR, exist_ok=True)

model_params = {"layers": []}

buffer = StringIO()
with redirect_stdout(buffer):
summary(model, input_size=(3, 224, 224))

output = buffer.getvalue()
lines = output.split("\n")

for line in lines[3:]:
parts = line.split()
if len(parts) < 4:
continue

print(parts)
layer_name = parts[0]
output_shape = parts[1]
param_count = parts[-1]

try:
param_count = int(param_count)
except ValueError:
continue

model_params["layers"].append({
"layer_name": layer_name,
"output_shape": output_shape,
"param_count": param_count
})


json_file_path = os.path.join(ARCHITECTURE_JSON_DIR, f"model_{model_id}.json")

with open(json_file_path, "w") as json_file:
json.dump(model_params, json_file, indent=4)

print(f"✅ Model architecture saved at: {json_file_path}")
print(json.dumps(model_params, indent=4))


if __name__ == "__main__":
model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet50', pretrained=True)
extract_model_parameters(model, model_id="1226")
3 changes: 2 additions & 1 deletion benchmarks/views/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ def view(request, domain: str):
leaderboard_context = get_context(domain=domain)
return render(request, 'benchmarks/leaderboard/leaderboard.html', leaderboard_context)


# get_context is used for both leaderboard and model views. We can cache the results of it so that after the first
# request, the cached results is served faster
@cache_get_context()
Expand Down Expand Up @@ -192,7 +193,7 @@ def get_context(user=None, domain: str = "vision", benchmark_filter=None, model_
'citation_domain_url': citation_domain_url,
'citation_domain_title': citation_domain_title,
'citation_domain_bibtex': citation_domain_bibtex,
'csv_downloadable': csv_data
'csv_downloadable': csv_data,
}


Expand Down
26 changes: 26 additions & 0 deletions benchmarks/views/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,17 @@
from .index import get_context
from ..models import BenchmarkType, Model

# FOR DUMMY VISUALIZATION #
import json
import os




_logger = logging.getLogger(__name__)

# Load JSON file for model architecture visualization
ARCHITECTURE_JSON_DIR = "static/model_architecture_json/"

def view(request, id: int, domain: str):
model, model_context, reference_context = determine_context(id, request, domain)
Expand All @@ -31,12 +40,29 @@ def view(request, id: int, domain: str):
layers = get_layers(model)
model_context['layers'] = layers

# _logger.info(f"Extracted Layers Data: {json.dumps(layers, indent=4)}")

DUMMY_LAYERS_FILE = os.path.join(ARCHITECTURE_JSON_DIR, "dummy_layers.json")

# Add Visualization-Layer-Parameters to model_context
if os.path.exists(DUMMY_LAYERS_FILE):
with open(DUMMY_LAYERS_FILE, 'r') as f:
dummy_layers_data = json.load(f)

model_context['visualization_metadata'] = dummy_layers_data # Store full JSON

if "Visualization-Layer-Parameters" in dummy_layers_data:
vis_layers = dummy_layers_data["Visualization-Layer-Parameters"]
model_context['visualization_layers'] = vis_layers


# only show detailed model info to superuser or owner:
if request.user.is_superuser or model.user.id == request.user.id:
model_context['submission_details_visible'] = True
return render(request, 'benchmarks/model.html', model_context)



def determine_context(id, request, domain: str):
# this is a bit hacky: we're loading scores for *all* public models as well as *all* of the user's models
# so we're loading a lot of unnecessary detail. But it lets us re-use already existing code.
Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
asgiref==3.7.2
backports.zoneinfo==0.2.1
boto3==1.28.15
botocore==1.31.15
certifi==2023.7.22
Expand Down
Loading