Package: meitorch
Most Exciting InputGenerateMost Exciting Inputto explore and understand PyTorch model's behavior by identifying input samples that induce high activation from specific neurons in your model.Paperpaper:Input optimization for interpreting neural generative modelsInstallationpipinstallmeitorchUsageLoad the model you want to generate interpretable visualizations for.model=load_your_model()Define the operation you want to optimize most exciting inputs for.Your operation must take a batch of inputs as parameters and return a dictionary of losses.
Visualizations will be generated for the input that maximizes the loss named "objective".importtorchdefoperation(inputs):outputs=model(inputs)activation=outputs[:,0]activation=torch.mean(activation,dim=0)loss=-activationlosses=dict(objective=loss,activation=activation,)returnlossesYou can also define more complex operations that include multiple losses.
Adding other losses to the dictionary will enable you to plot them after the optimization.defoperation(inputs):outputs=model(inputs)activation=outputs[:,0]activation=torch.mean(activation,dim=0)model_losses=compute_loss(inputs,outputs)regularization=losses["elbo"]*0.1loss=-activation+regularizationlosses=dict(objective=loss,activation=activation,elbo_regularization=regularization,)returnlossesCreate a MEI object with your operation and the input shape of your model.frommeitorch.meiimportMEImei=MEI(operation=operation(),shape=(1,40,40),device=device)Define a configuration for the optimization and generateMost Exciting Inputs.
There are minor differences between the configuration for different optimization schemes, more on configurations below.Generate pixel-wise MEIpixel_mei_config=dict(/*yourconfighere*/)result=mei.generate_pixel_mei(config=pixel_mei_config)Generate variational MEIvariational_mei_config=dict(/*yourconfighere*/)result=mei.generate_variational_mei(config=variational_mei_config)Generate transformation MEItransformation_mei_config=dict(/*yourconfighere*/)result=mei.generate_transformation_mei(config=transformation_mei_config)Analyze the results
Access the generated images and the losses from the result object.Plot the loss curves and the visualizationsresult.plot_losses(show=False,save_path=None,ranges=None)result.plot_image_and_losses(self,save_path=None,ranges=None)Plot spatial frequency spectrum of the generated imagesresult.plot_spatial_frequency_spectrum()Further analysisYou can further analyze the results with themeitorch.analyzemodule.frommeitorch.analyzeimportAnalyzeConfigurationsFor all configurations, you can use a schedule instead of a constant value for any parameter.
A schedule is a function that takes the current iteration as input and returns the value for that iteration.
You can access the schedule class inmeitorch.tools.schedules.frommeitorch.tools.schedulesimportLinearScheduleschedule=LinearSchedule(start=0.1,end=0.01)Available schedules are:- LinearSchedule(start, end)
- OctaveSchedule(values)
- RandomSchedule(minimum, maximum)Pixel-wise MEI configuration exampleimage_mei_config=dict(iter_n=2,# number of optimization stepsn_samples=1,# number of samples per batchsave_every=1,# save copy of image every n iterationsbias=0,# bias of the distribution the image is sampled fromscale=1,# scaling of the distribution the image is sampled fromdiverse=False,# whether to use diverse samplingdiverse_params=dict(div_metric='euclidean',# distance metric for diversity (euclidean, cosine, correlation)div_linkage='minimum',# linkage criterion for diversity (minimum, average)div_weight=1.1,# weight of diversity loss),#pre-step transformationsscaler=1.01,# scaling of the image before each stepjitter=3,# size of translational jittering before each step#normalization/clippingtrain_norm=1,# norm adjustment during stepnorm=1,# norm adjustment after step#optmizeroptimizer="rmsprop",# optimizer (sgd, mei, rmsprop, adam)optimizer_params=dict(lr=0.03,# learning rateweight_decay=1e-6,# weight decay),#preconditioning in the gradientprecond=0.3,# strength of gradient preconditioning filter falloff (float or schedule)#denoiser after each stepblur='gaussian',# denoiser type (gaussian, tv, bilateral)blur_params=dict(#gaussiankernel_size=3,sigma=LinearSchedule(0.1,0.01)#tv#regularization_scaler=1e-7,#lr=0.0001,#num_iters=5,#bilateral#kernel_size=3,#sigma_color=LinearSchedule(1, 0.01),#sigma_spatial=LinearSchedule(0.25, 0.01),),)Variational MEI configuration examplevar_mei_config=dict(iter_n=1,# number of optimization stepssave_every=100,# save image every n iterationsbias=0,# bias of the distribution the image is sampled fromscale=1,# scaling of the distribution the image is sampled from#transformationsscaler=RandomSchedule(1,1.025),# scaling of the image (float or schedule)jitter=None,# size of translational jittering#optmizeroptimizer="rmsprop",# optimizer (sgd, mei, rmsprop, adam)optimizer_params=dict(lr=0.04,# learning rateweight_decay=1e-7,# weight decay),#preconditioningprecond=0.4,# strength of gradient preconditioning filter#variationaldistribution='normal',# distribution of the MEI (normal, laplace)n_samples_per_batch=(128,),# number of samples per batch (tuple)fixed_stddev=0.4,# fixed stddev of the distribution, None for learned stddev)Transformation MEI configuration exampleFor the transformation MEI, you need to define a transformation operation that takes an image as input and returns a transformed image.
Any backpropagatable operation can be used as a transformation. In the example below, we use a generative convolutional network, which is defined inmeitorch.tools.transformations.tranformation_mei_config=dict(iter_n=150,# number of optimization stepssave_every=1,# save image every n iterationsbias=0,# bias of the distribution the image is sampled fromscale=1,# scaling of the distribution the image is sampled fromn_samples=128,# number of samples per batch#transformations before each stepscaler=None,# scaling of the image (float or schedule)jitter=None,# size of translational jittering#normalizationtrain_norm=None,# norm adjustment during step#optmizeroptimizer="mei",# optimizer (sgd, mei, rmsprop, adam)optimizer_params=dict(lr=0.02,# learning rateweight_decay=1e-5,# weight decay),#preconditioningprecond=0.4,# strength of gradient preconditioning filter# transformation operationtransform=GenerativeConvNet(hidden_sizes=[1],fixed_stddev=0.6,kernel_size=9,activation=torch.nn.ReLU(),activate_output=False,shape=(1,40,40)))