A framework to compute threshold sensitivity of deep networks to visual stimuli.
I have converted this project into a pip package called osculari . Please use the osculari package
instead of this repository.
This repository provides an easy interface to train a linear classifier on top of the extract features from pretrained networks implemented in PyTorch. It includes:
- Most models and pretrained networks from PyTorch's official website.
- CLIP language-vision model.
- Taskonomy networks.
- Different architectures (e.g., CNN and ViT).
- Different tasks (e.g., classification and segmentation).
- Training/testing routines for 2AFC and 4AFC tasks.
Let's create a linear classifier to perform a binary-classification 2AFC (two-alternative-force-choice) task. This is easily achieved by inheriting the readout.ClassifierNet .
from deepths.models import readout class FeatureDiscrimination2AFC(readout.ClassifierNet): def __init__(self, classifier_kwargs, readout_kwargs): super(FeatureDiscrimination2AFC, self).__init__( input_nodes=2, num_classes=2, **classifier_kwargs, **readout_kwargs ) def forward(self, x0, x1): x0 = self.do_features(x0) x1 = self.do_features(x1) x = torch.cat([x0, x1], dim=1) return self.do_classifier(x)The parameter input_nodes specify the number of images we are extracting features from. The parameter num_classes specifies the number of outputs for the linear classifier.
Let's use ResNet50 as our pretrained network and extract feature from the layer area0.
net_name = 'resnet50' weights = 'resnet50' target_size = 224 readout_kwargs = { 'architecture': net_name, 'target_size': target_size, 'transfer_weights': [weights, 'area0'], } classifier_lwargs = { 'classifier': 'nn', 'pooling': None } net = FeatureDiscrimination2AFC(classifier_lwargs, readout_kwargs)The variable readout_kwargs specifies the details of the pretrained network:
architectureis network's architecture (e.g.,ResNet50orViT-B32).transfer_weightsdefines the weights of the pretrained network and the layer(s) to use:- The first index must be either path to the pretrained weights or PyTorch supported weights (in this example we are using the default PyTorch weights of
ResNet50). - The second index is the read-out (cut-off) layer. In this example, we extract features from
area0.
- The first index must be either path to the pretrained weights or PyTorch supported weights (in this example we are using the default PyTorch weights of
The variable classifier_lwargs specifies the details of the linear classifier:
classifierspecifies types of linear classifier. It mainly supports neural network (NN) with partial support for SVM.poolingspecifies whether to perform pooling over extracted features (without any new weights to learn). This is useful to reduce the dimensionality of the extracted features.
Let's print our network:
print(net) FeatureDiscrimination2AFC( (backbone): Sequential( (0): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False) (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU(inplace=True) (3): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False) ) (fc): Linear(in_features=401408, out_features=2, bias=True) ) We can see that it contains of two nodes: backbone and fc corresponding to the pretrained network and linear classifier, respectively.
From the print above, we can observe that the dimensionality of the input to the linear classifier is too large (a vector of 401408 elements). It might be of interest to reduce this by means of pooling operations. For instance, we can make an instance of FeatureDiscrimination2AFC with 'pooling': 'avg_2_2' (i.e., average pooling over a 2-by-2 window). In the new instance the input to the linear layer is only 512 elements.
FeatureDiscrimination2AFC( (backbone): Sequential( (0): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False) (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (2): ReLU(inplace=True) (3): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False) ) (pool_avg): AdaptiveAvgPool2d(output_size=(2, 2)) (fc): Linear(in_features=512, out_features=2, bias=True) ) - To use max pooling:
'pooling': 'max_2_2'. - To pool over a different window: e.g.,
'pooling': 'max_5_3'pools over a 5-by-3 window.
We have used this repository to measure the networks' CSF.
To train a contrast discriminator linear classifier:
python csf_train.py -aname $MODEL --transfer_weights $WEIGHTS $LAYER \ --target_size 224 --classifier "nn" \ -dname $DB --data_dir $DATA_DIR --train_samples 15000 --val_sample 1000 \ --contrast_space "rgb" --colour_space "imagenet_rgb" --vision_type "trichromat" \ -b 64 --experiment_name $EXPERIMENT_NAME --output_dir $OUT_DIR \ -j 4 --gpu 0 --epochs 10 To measure the CSFs ($CONTRAST_SPACE can be one of the following values "lum_ycc" "rg_ycc" "yb_ycc" corresponding to luminance, red-green and yellow-blue channels).
python csf_test.py -aname $MODEL_PATH --contrast_space $CONTRAST_SPACE \ --target_size 224 --classifier "nn" --mask_image "fixed_cycle" \ --experiment_name $EXPERIMENT_NAME \ --colour_space "imagenet_rgb" --vision_type "trichromat" \ --print_freq 1000 --output_dir $OUT_DIR --gpu 0We have used this repository to measure the networks' colour discrimination.
To train a colour discriminator linear classifier:
python colour_discrimination.py -aname $MODEL --transfer_weights $WEIGHTS $LAYER \ --target_size 224 --classifier "nn" \ -dname $DB --data_dir $DATA_DIR --train_samples 15000 --val_sample 1000 \ --colour_space "imagenet_rgb" \ -b 64 --experiment_name $EXPERIMENT_NAME --output_dir $OUT_DIR \ -j 4 --gpu 0 --epochs 10To measure the sensitivity threshold $TEST_FILE must be passed
python colour_discrimination.py -aname $MODEL --test_net $MODEL_PATH \ --target_size 224 --classifier "nn" \ -dname $DB --data_dir $DATA_DIR \ --test_file $TEST_FILE --background 128 \ --colour_space "imagenet_rgb" \ -b 64 --experiment_name $TEST_NAME --output_dir $OUT_DIR \ -j 4 --gpu 0 We have used this repository to measure the networks' colour categories.
python colour_cat_odd4.py -aname $MODEL --test_net $MODEL_PATH \ --target_size 224 --classifier "nn" \ -dname $DB --data_dir $DATA_DIR \ --test_file $TEST_FILE --focal_file $FOCAL_FILE --background 128 \ --colour_space "imagenet_rgb" \ -b 64 --experiment_name $TEST_NAME --output_dir $OUT_DIR \ -j 4 --gpu 0