jpterry's picture
plot modifications
1e0dfd1
import gradio as gr
from huggingface_hub import hf_hub_url, cached_download
from matplotlib import cm
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np
# import onnxruntime as ort
from PIL import Image
from scipy import special
import sys
# import timm
from types import SimpleNamespace
# from transformers import AutoModel, pipeline
from transformers import AutoModelForImageClassification, AutoModel, AutoConfig
import torch
sys.path.insert(1, "../")
# from utils import model_utils, train_utils, data_utils, run_utils
# from model_utils import jason_regnet_maker, jason_efficientnet_maker
from model_utils.efficientnet_config import EfficientNetConfig, EfficientNetPreTrained, EfficientNet
model_path = 'chlab/'
# model_path = './models/'
# plotting a prameters
labels = 20
ticks = 14
legends = 14
text = 14
titles = 22
lw = 3
ps = 200
cmap = 'magma'
effnet_hparams = {47: {"num_classes": 2,
"gamma": 0.04294256770072906,
"lr": 0.010208864616781627,
"weight_decay": 0.00014537466483781656,
"batch_size": 16,
"num_channels": 47,
"stochastic_depth_prob": 0.017760418815821067,
"dropout": 0.039061686292663655,
"width_mult": 0.7540060155156922,
"depth_mult": 0.9378692812212488,
"size": "v2_s",
"model_type": "efficientnet_47_planet_detection"
},
61: {
"num_classes": 2,
"gamma": 0.032606396652426956,
"lr": 0.008692971067922545,
"weight_decay": 0.00008348389688708425,
"batch_size": 23,
"num_channels": 61,
"stochastic_depth_prob": 0.003581930052432713,
"dropout": 0.027804120950575217,
"width_mult": 1.060782511229692,
"depth_mult": 0.7752918857163054,
"size": "v2_s",
"model_type": "efficientnet_61_planet_detection"
},
75: {
"num_classes": 2,
"gamma": 0.029768470449465057,
"lr": 0.008383851744497892,
"weight_decay": 0.000196304392793202,
"batch_size": 32,
"num_channels": 75,
"stochastic_depth_prob": 0.08398410137077088,
"dropout": 0.03351826828687193,
"width_mult": 1.144132674734038,
"depth_mult": 1.2267023928285563,
"size": "v2_s",
"model_type": "efficientnet_75_planet_detection"
}
}
# effnet_config = SimpleNamespace(**effnet_hparams)
# which layers to look at
activation_indices = {'efficientnet': [0, 3]}
def normalize_array(x: list):
'''Makes array between 0 and 1'''
x = np.array(x)
return (x - np.min(x)) / np.max(x - np.min(x))
# def load_model(model: str, activation: bool=True):
# if activation:
# model += '_w_activation'
# # set options for onnx runtime
# options = ort.SessionOptions()
# options.intra_op_num_threads = 1
# options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
# provider = "CPUExecutionProvider"
# # start session
# ort_session = ort.InferenceSession(model_path + '%s.onnx' % (model), options, providers=[provider])
# # ort_session = ORTModel.load_model(model_path + '%s.onnx' % (model))
# return ort_session
def get_activations(model, image: list, model_name: str,
layer=None, vmax=2.5, sub_mean=True,
channel: int=0):
'''Gets activations for a given input image'''
# run model
# input_name = intermediate_model.get_inputs()[0].name
# outputs = intermediate_model.run(None, {input_name: image})
layer_outputs = {}
temp_image = image
for i in range(len(model.features)):
temp_image = model.features[i](temp_image)
if i in activation_indices[model_name]:
layer_outputs[i] = temp_image
# print(i, layer_outputs[i].shape)
if i == max(activation_indices[model_name]):
break
output = model(image).detach().cpu().numpy()
# print(model(image), model.model(image))
image = image.detach().cpu().numpy()
output_1 = layer_outputs[activation_indices[model_name][0]].detach().cpu().numpy()
output_2 = layer_outputs[activation_indices[model_name][1]].detach().cpu().numpy()
# print(image.shape, output.shape, output_1.shape, output_2.shape)
# get activations
# output_1 = outputs[1]
# output_2 = outputs[2]
# get prediction
# output = outputs[0][0]
output = special.softmax(output)
print(output)
# sum over velocity channels
if channel == 0:
in_image = np.sum(image[0, :, :, :], axis=0)
else:
image[0, int(channel-1), :, :]
in_image = normalize_array(in_image)
if layer is None:
# sum over all velocity channels
activation_1 = np.sum(output_1[0, :, :, :], axis=0)
activation_2 = np.sum(output_2[0, :, :, :], axis=0)
else:
# select a single channel
activation_1 = output_1[0, layer, :, :]
activation_2 = output_2[0, layer, :, :]
if sub_mean:
# y = |x - <x>|
activation_1 -= np.mean(activation_1)
activation_1 = np.abs(activation_1)
activation_2 -= np.mean(activation_2)
activation_2 = np.abs(activation_2)
return output, in_image, activation_1, activation_2
def plot_input(input_image: list, origin='lower'):
##### make the figure for the input image #####
plt.rcParams['xtick.labelsize'] = ticks
plt.rcParams['ytick.labelsize'] = ticks
input_fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(6, 5))
im0 = ax.imshow(input_image, cmap=cmap,
origin=origin)
divider = make_axes_locatable(ax)
cax = divider.append_axes('right', size='5%', pad=0.05)
input_fig.colorbar(im0, cax=cax, orientation='vertical')
ax.set_title('Input', fontsize=titles)
return input_fig
def plot_activations(activation_1: list, activation_2: list, origin='lower'):
##### Make the activation figure ######
plt.rcParams['xtick.labelsize'] = ticks
plt.rcParams['ytick.labelsize'] = ticks
fig, axs = plt.subplots(nrows=1, ncols=2, figsize=(18, 7))
ax1, ax2 = axs[0], axs[1]
im1 = ax1.imshow(activation_1, cmap=cmap,
origin=origin)
im2 = ax2.imshow(activation_2, cmap=cmap,
origin=origin)
ims = [im1, im2]
for (i, ax) in enumerate(axs):
divider = make_axes_locatable(ax)
cax = divider.append_axes('right', size='5%', pad=0.05)
fig.colorbar(ims[i], cax=cax, orientation='vertical')
# ax0.set_title('Input', fontsize=titles)
ax1.set_title('Early Activation', fontsize=titles)
ax2.set_title('Late Activation', fontsize=titles)
return fig
def predict_and_analyze(model_name, num_channels, dim, input_channel, image):
'''
Loads a model with activations, passes through image and shows activations
The image must be a numpy array of shape (C, W, W) or (1, C, W, W)
'''
model_name = model_name.lower()
num_channels = int(num_channels)
W = int(dim)
print("Running %s for %i channels" % (model_name, num_channels))
print("Loading data")
# print(image)
image = np.load(image.name, allow_pickle=True)
image = image.astype(np.float32)
if len(image.shape) != 4:
image = image[np.newaxis, :, :, :]
image = torch.from_numpy(image)
assert image.shape == (1, num_channels, W, W), "Data is the wrong shape"
print("Data loaded")
print("Loading model")
model_loading_name = "%s_%i_planet_detection" % (model_name, num_channels)
if 'eff' in model_name:
hparams = effnet_hparams[num_channels]
hparams = SimpleNamespace(**hparams)
config = EfficientNetConfig(
dropout=hparams.dropout,
num_channels=hparams.num_channels,
num_classes=hparams.num_classes,
size=hparams.size,
stochastic_depth_prob=hparams.stochastic_depth_prob,
width_mult=hparams.width_mult,
depth_mult=hparams.depth_mult,
)
# EfficientNetConfig.model_type = "efficientnet_%s_planet_detection" % (hparams.num_channels)
# EfficientNetConfig.model_type = hparams.model_type
# config.save_pretrained(save_directory=model_loading_name)
# model = EfficientNet(dropout=hparams.dropout,
# num_channels=hparams.num_channels,
# num_classes=hparams.num_classes,
# size=hparams.size,
# stochastic_depth_prob=hparams.stochastic_depth_prob,
# width_mult=hparams.width_mult,
# depth_mult=hparams.depth_mult,)
###### kinda working #####
# AutoConfig.register(model_loading_name, EfficientNetConfig)
# AutoModel.register(EfficientNetConfig, EfficientNetPreTrained)
# model = AutoModel.from_pretrained(model_path + model_loading_name)
# config = EfficientNetConfig.from_pretrained(model_loading_name)
# model = EfficientNetPreTrained.from_pretrained(model_loading_name)
# model = AutoModel.from_pretrained(model_loading_name, trust_remote_code=True)
# model = AutoModel.from_pretrained(model_path + model_loading_name)
model = EfficientNet(dropout=hparams.dropout,
num_channels=hparams.num_channels,
num_classes=hparams.num_classes,
size=hparams.size,
stochastic_depth_prob=hparams.stochastic_depth_prob,
width_mult=hparams.width_mult,
depth_mult=hparams.depth_mult,)
model_url = cached_download(hf_hub_url(model_path + model_loading_name, filename="pytorch_model.bin"))
# print(model_url)
loaded = torch.load(model_url, map_location='cpu',)
# print(loaded.keys())
model.load_state_dict(loaded['state_dict'])
# print(model)
# model = EfficientNetPreTrained(config)
# config.register_for_auto_class()
# model.register_for_auto_class("AutoModelForImageClassification")
# pretrained_model = timm.create_model(model_loading_name, pretrained=True)
# model.model.load_state_dict(pretrained_model.state_dict())
# pipeline = pipeline(task="image-classification", model=model_loading_name)
# model = load_model(model_name, activation=True)
# model = AutoModel.from_pretrained(model_loading_name)
print("Model loaded")
print("Looking at activations")
output, input_image, activation_1, activation_2 = get_activations(model, image, model_name,
channel=input_channel,
sub_mean=True)
print("Activations and predictions finished")
# print(output)
if output[0][0] < output[0][1]:
output = 'Planet predicted with %.3f percent confidence' % (100*output[0][1])
else:
output = 'No planet predicted with %.3f percent confidence' % (100*output[0][0])
print(output)
input_image = normalize_array(input_image)
activation_1 = normalize_array(activation_1)
activation_2 = normalize_array(activation_2)
# convert input image to RGB (unused for now since not outputting actual image)
# input_pil_image = Image.fromarray(np.uint8(cm.magma(input_image)*255))
print("Plotting")
origin = 'lower'
# plot input image
input_fig = plot_input(input_image, origin=origin)
# plot mean subtracted activations
fig1 = plot_activations(activation_1, activation_2, origin=origin)
# plot raw activations
_, _, activation_1, activation_2 = get_activations(model, image, model_name,
channel=input_channel,
sub_mean=False)
activation_1 = normalize_array(activation_1)
activation_2 = normalize_array(activation_2)
fig2 = plot_activations(activation_1, activation_2, origin=origin)
print("Sending to Hugging Face")
return output, input_fig, fig1, fig2
if __name__ == "__main__":
demo = gr.Interface(
fn=predict_and_analyze,
inputs=[gr.Dropdown(["EfficientNet"],
# "RegNet"],
value="EfficientNet",
label="Model Selection",
show_label=True),
gr.Dropdown(["47", "61", "75"],
value="61",
label="Number of Velocity Channels",
show_label=True),
gr.Dropdown(["600"],
value="600",
label="Image Dimensions",
show_label=True),
gr.Number(value=0.,
label="Input Channel to show (0 = sum over all)",
show_label=True),
gr.File(label="Input Data", show_label=True)],
outputs=[gr.Textbox(lines=1, label="Prediction", show_label=True),
# gr.Image(label="Input Image", show_label=True),
gr.Plot(label="Input Image", show_label=True),
gr.Plot(label="Mean-Subtracted Activations", show_label=True),
gr.Plot(label="Raw Activations", show_label=True)
],
title="Kinematic Planet Detector"
)
demo.launch()