Following is a Keras implementation of a Partial Domain Adaptation Model that assigns class labels to images in the Target domain by extracting domain-invariant features from the labelled Source and unlabelled Target domain images. This work caters towards a realistic scenario which relaxes the shared label space assumption (i.e., the target label space is a subspace of the source label space) by introducing a class-level weighting mechanism to remove the negative influence of outlier source classes. The architecture involves three sub-networks: (a) domain-invariant feature extractor, (b) classifier and (c) domain discriminator.
The code is tested on the Office-31 dataset.
- Download it from this link: Office-31.
- Create a domain_adaptation_images directory under Data/Office/ and place the downloaded images inside.
- Image paths, along with the corresponding class labels, are listed in the .txt files present in the Office directory.
- The Data directory structure should look like this:
.
├── Data
| └── Office
| ├── domain_adaptation_images
| | └── place the office-31 image folders here (amazon, dslr, webcam)
| ├── amazon_10_list.txt
| ├── amazon_31_list.txt
| ├── dslr_10_list.txt
| ├── dslr_31_list.txt
| ├── webcam_31_list.txt
| └── webcam_10_list.txt
└── ...
This code is compatible with the mentioned versions of the following libraries. However, it might also be compatible with their prior versions.
pillow 6.0.0
scikit-learn 0.20.2
tensorflow 1.12.0
keras 2.2.4
Domain-Invariant Feature Extractor:
- Model : Resnet50 (initialized with 'imagenet' weights)
- Loss : w1 * classifier loss - w2 * discriminator loss (w1 = classifier loss weight and w2 = discriminator loss weight)
- The gradient-reversal process is done in a GAN fashion where the domain labels are flipped for the Source and Target (i.e. Source labels changed to 1 and Target labels changed to 0).
- Optimizer : Adam
Classifier:
- Model : Dense(400) --> Dense(100) --> Dense(number of classes)
- Loss : Categorical cross-entropy
- Optimizer : Adam
Domain Discriminator:
- Model : Dense(400) --> Dense(100) --> Dense(1)
- Loss : Binary cross-entropy
- Optimizer : Adam
The model outputs the Target_labels and the Source and Target classification accuracies, which are saved under the Snapshot/Models directory.
- An example starter code is given below:
python driver.py --batch_size 32 --number_of_gpus 2 --lr_combined 0.00001 --num_iterations 5000
- Parameters:
Parameter Name | Default Value | Description |
---|---|---|
--number_of_gpus |
default = '1' | "Number of gpus required to run" |
--network_name |
default = 'ResNet50' | "Name of the feature extractor network" |
--dataset_name |
default = 'Office' | "Name of the source dataset" |
--dropout_classifier |
default = 0.25 | "Dropout ratio for classifier" |
--dropout_discriminator |
default = 0.25 | "Dropout ratio for discriminator" |
--source_path |
default = 'amazon_10_list.txt' | "Path to source dataset" |
--target_path |
default = 'webcam_10_list.txt' | "Path to target dataset" |
--lr_classifier |
default = 0.0001 | "Learning rate for classifier model" |
--lr_discriminator |
default = 0.0001 | "Learning rate for discriminator model" |
--lr_combined |
default = 0.00001 | "Learning rate for combined model" |
--b1_classifier |
default = 0.9 | "Exponential decay rate of first moment for classifier model optimizer" |
--b2_classifier |
default = 0.999 | "Exponential decay rate of second moment for classifier model optimizer" |
--b1_discriminator |
default = 0.9 | "Exponential decay rate of first moment for discriminator model optimizer" |
--b2_discriminator |
default = 0.999 | "Exponential decay rate of second moment for discriminator model optimizer" |
--b1_combined |
default = 0.9 | "Exponential decay rate of first moment for combined model optimizer" |
--b2_combined |
default = 0.999 | "Exponential decay rate of second moment for combined model optimizer" |
--classifier_loss_weight |
default = 1 | "Classifier loss weight" |
--discriminator_loss_weight |
default = 4 | "Discriminator loss weight" |
--batch_size |
default = 32 | "Batch size for training" |
--test_interval |
default = 3 | "Gap between two successive test phases" |
--num_iterations |
default = 12000 | "Number of iterations" |
--snapshot_interval |
default = 500 | "Minimum gap between saving output models" |
--output_dir |
default = 'models' | "Directory for saving output model" |
The following code has drawn inspiration from the following papers:
-
Zhangjie Cao, Mingsheng Long, Jianmin Wang and Michael I. Jordan. "Partial Transfer Learning with Selective Adversarial Networks." [Link]
-
Jing Zhang, Zewei Ding, Wanqing Li and Philip Ogunbona. "Importance Weighted Adversarial Nets for Partial Domain Adaptation." [Link]
-
Ganin, Yaroslav and Lempitsky. "Unsupervised domain adaptation by backpropagation." [Link]
-
Li, Yanghao, Naiyan Wang, Jianping Shi, Jiaying Liu, and Xiaodi Hou. "Revisiting batch normalization for practical domain adaptation." [Link]
-
Tzeng, Eric, Judy Hoffman, Kate Saenko, and Trevor Darrell. "Adversarial discriminative domain adaptation." [Link]