O DASSL é uma caixa de ferramentas Pytorch desenvolvida inicialmente para o nosso Projeto Domínio Adaptive Ensemble Learning (DAEL) para apoiar a pesquisa em adaptação e generalização de domínio-como em Dael, estudamos como unificar esses dois problemas em uma única estrutura de aprendizagem. Dado que a adaptação do domínio está intimamente relacionada ao aprendizado semi-supervisionado-ambos estudam como explorar dados não marcados-também incorporamos componentes que apóiam a pesquisa para o último.
Por que o nome "Dassl"? O DASSL combina as iniciais da adaptação do domínio (DA) e do aprendizado semi-supervisionado (SSL), que parece natural e informativo.
O DASSL possui um design modular e interfaces unificadas, permitindo prototipagem rápida e experimentação de novos métodos DA/DG/SSL. Com o DASSL, um novo método pode ser implementado com apenas algumas linhas de código. Não acredita? Dê uma olhada na pasta do motor, que contém as implementações de muitos métodos existentes (então você voltará e estrelará este repositório). :-)
Basicamente, Dassl é perfeito para fazer pesquisas nas seguintes áreas:
Mas, graças ao design interessante, o DASSL também pode ser usado como uma base de código para desenvolver qualquer projeto de aprendizado profundo, como esse. :-)
Uma desvantagem do DASSL é que ainda não (ainda não é o treinamento de multi-GPU distribuído (hmm) (o DASSL usa DataParallel para embrulhar um modelo, que é menos eficiente que DistributedDataParallel ).
Não fornecemos documentações detalhadas para o DASSL, ao contrário de outro projeto nosso. Isso ocorre porque o DASSL é desenvolvido para fins de pesquisa e, como pesquisador, achamos importante poder ler o código-fonte e o incentivamos a fazê-lo-definitivamente não porque somos preguiçosos. :-)
v0.6.0 : faça cfg.TRAINER.METHOD_NAME consistente com o nome da classe do método.v0.5.0 : alterações importantes feitas no transforms.py . 1) center_crop se torna uma transformação padrão no teste (aplicado após redimensionar a borda menor em um determinado tamanho para manter a proporção da imagem). 2) Para treinamento, Resize(cfg.INPUT.SIZE) é desativado quando random_crop ou random_resized_crop são usados. Essas alterações não farão diferença nas transformações de treinamento usadas nos arquivos de configuração existentes, nem nas transformações de teste, a menos que as imagens brutas não sejam quadradas (a única diferença é que agora a proporção da imagem é respeitada).v0.4.3 : Copie os atributos no self.dm (Data Manager) para ser SimpleTrainer e tornar self.dm opcional, o que significa que a partir de agora você pode criar carregadores de dados a partir de qualquer fonte que desejar, em vez de ser forçado a usar DataManager .v0.4.2 : Uma atualização importante é definir drop_last=is_train and len(data_source)>=batch_size ao construir um carregador de dados para evitar 0 comprimentos. Dassl implementou os seguintes métodos:
Adaptação de domínio de fonte única
Adaptação de domínio de várias fontes
Generalização do domínio
Aprendizado semi-supervisionado
Sinta -se à vontade para fazer um PR para adicionar seus métodos aqui para facilitar a referência para os outros!
DASSL suporta os seguintes conjuntos de dados:
Adaptação de domínio
Generalização do domínio
Aprendizado semi-supervisionado
Verifique se o CONDA está instalado corretamente.
# Clone this repo
git clone https://github.com/KaiyangZhou/Dassl.pytorch.git
cd Dassl.pytorch/
# Create a conda environment
conda create -y -n dassl python=3.8
# Activate the environment
conda activate dassl
# Install torch (requires version >= 1.8.1) and torchvision
# Please refer to https://pytorch.org/ if you need a different cuda version
conda install pytorch torchvision cudatoolkit=10.2 -c pytorch
# Install dependencies
pip install -r requirements.txt
# Install this library (no need to re-build if the source code is modified)
python setup.py developSiga as instruções nos conjuntos de dados.md para pré -processar os conjuntos de dados.
A interface principal é implementada em tools/train.py , o que basicamente faz
cfg = setup_cfg(args) , onde args contém a entrada da linha de comando (consulte tools/train.py para a lista de argumentos de entrada);trainer com build_trainer(cfg) que carrega o conjunto de dados e cria um modelo de rede neural profundo;trainer.train() para treinamento e avaliação do modelo.Abaixo, fornecemos um exemplo para treinar uma linha de base somente fonte no conjunto de dados de adaptação de domínio popular, Office-31,
CUDA_VISIBLE_DEVICES=0 python tools/train.py
--root $DATA
--trainer SourceOnly
--source-domains amazon
--target-domains webcam
--dataset-config-file configs/datasets/da/office31.yaml
--config-file configs/trainers/da/source_only/office31.yaml
--output-dir output/source_only_office31 $DATA indicam o local onde os conjuntos de dados são instalados. --dataset-config-file carrega a configuração comum para o conjunto de dados (Office-31 neste caso), como tamanho da imagem e arquitetura do modelo. --config-file carrega a configuração específica do algoritmo, como hiper-parâmetros e parâmetros de otimização.
Para usar várias fontes, a saber, a tarefa de adaptação de domínio de várias fontes, é preciso apenas adicionar mais fontes a --source-domains . Por exemplo, para treinar uma linha de base somente de fonte no Minidomainnet, pode-se fazer
CUDA_VISIBLE_DEVICES=0 python tools/train.py
--root $DATA
--trainer SourceOnly
--source-domains clipart painting real
--target-domains sketch
--dataset-config-file configs/datasets/da/mini_domainnet.yaml
--config-file configs/trainers/da/source_only/mini_domainnet.yaml
--output-dir output/source_only_minidnApós o acabamento do treinamento, os pesos do modelo serão salvos no diretório de saída especificado, juntamente com um arquivo de log e um arquivo de tensorboard para visualização.
Para imprimir os resultados salvos no arquivo de log (para que você não precise passar exaustivamente por todos os arquivos de log e calcular a média/std sozinho), você pode usar tools/parse_test_res.py . A instrução pode ser encontrada no código.
Para outros treinadores, como MCD , você pode definir --trainer MCD , mantendo o arquivo de configuração inalterado, ou seja, usando os mesmos parâmetros de treinamento que SourceOnly (no caso mais simples). Para modificar os hiper-parâmetros no MCD, como N_STEP_F (número de etapas para atualizar o extrator de recurso), você pode anexar TRAINER.MCD.N_STEP_F 4 aos argumentos de entrada existentes (caso contrário, o valor padrão será usado). Como alternativa, você pode criar um novo arquivo de configuração .yaml para armazenar sua configuração personalizada. Veja aqui uma lista completa de hiper-parâmetros específicos do algoritmo.
O teste de modelo pode ser feito usando --eval-only , que pede ao código para executar trainer.test() . Você também precisa fornecer o modelo treinado e especificar qual arquivo de modelo (ou seja, salvo em qual época) usar. Por exemplo, para usar model.pth.tar-20 salvo em output/source_only_office31/model , você pode fazer
CUDA_VISIBLE_DEVICES=0 python tools/train.py
--root $DATA
--trainer SourceOnly
--source-domains amazon
--target-domains webcam
--dataset-config-file configs/datasets/da/office31.yaml
--config-file configs/trainers/da/source_only/office31.yaml
--output-dir output/source_only_office31_test
--eval-only
--model-dir output/source_only_office31
--load-epoch 20 Observe que --model-dir toma como entrada o caminho do diretório especificado em --output-dir no estágio de treinamento.
Uma boa prática é passar pelo dassl/engine/trainer.py para obter a Familar com as classes de treinadores base, que fornecem funções genéricas e loops de treinamento. Para escrever uma classe de treinador para adaptação de domínio ou aprendizado semi-supervisionado, a nova classe pode subclasse TrainerXU . Para generalização do domínio, a nova classe pode subclasse TrainerX . Em particular, TrainerXU e TrainerX diferem principalmente no uso de um carregador de dados para dados não marcados. Com as classes base, um novo treinador pode precisar implementar apenas o método forward_backward() , que executa a computação de perdas e a atualização do modelo. Consulte dassl/enigne/da/source_only.py por exemplo.
backbone corresponde a um modelo de rede neural convolucional que executa a extração de recursos. head (que é um módulo opcional) é montada na parte superior da backbone para processamento adicional, que pode ser, por exemplo, um MLP. backbone e head são blocos básicos de construção para construir um SimpleNet() (consulte dassl/engine/trainer.py ), que serve como modelo principal para uma tarefa. network contém modelos de rede neural personalizados, como um gerador de imagens.
Para adicionar um novo módulo, ou seja, uma espinha dorsal/cabeça/rede, você precisa primeiro registrar o módulo usando o registry correspondente, ou seja, BACKBONE_REGISTRY para backbone , HEAD_REGISTRY for head e NETWORK_RESIGTRY for network . Observe que, para um novo backbone , exigimos que o modelo subclasse Backbone , conforme definido no dassl/modeling/backbone/backbone.py e especifique o atributo self._out_features .
Fornecemos um exemplo abaixo sobre como adicionar uma nova backbone .
from dassl . modeling import Backbone , BACKBONE_REGISTRY
class MyBackbone ( Backbone ):
def __init__ ( self ):
super (). __init__ ()
# Create layers
self . conv = ...
self . _out_features = 2048
def forward ( self , x ):
# Extract and return features
@ BACKBONE_REGISTRY . register ()
def my_backbone ( ** kwargs ):
return MyBackbone () Em seguida, você pode definir MODEL.BACKBONE.NAME como my_backbone para usar sua própria arquitetura. Para mais detalhes, consulte o código -fonte em dassl/modeling .
Um exemplo de estrutura de código é mostrado abaixo. Certifique -se de subclasse DatasetBase e registrar o conjunto de dados com @DATASET_REGISTRY.register() . Tudo o que você precisa é carregar train_x , train_u (opcional), val (opcional) e test , entre os quais train_u e val não podem ser None ou simplesmente ignorado. Cada uma dessas variáveis contém uma lista de objetos Datum . Um objeto Datum (implementado aqui) contém informações para uma única imagem, como impath (string) e label (int).
from dassl . data . datasets import DATASET_REGISTRY , Datum , DatasetBase
@ DATASET_REGISTRY . register ()
class NewDataset ( DatasetBase ):
dataset_dir = ''
def __init__ ( self , cfg ):
train_x = ...
train_u = ... # optional, can be None
val = ... # optional, can be None
test = ...
super (). __init__ ( train_x = train_x , train_u = train_u , val = val , test = test )Sugerimos que você dê uma olhada no código dos conjuntos de dados em alguns projetos como esse, que é construído sobre o DASSL.
Gostaríamos de compartilhar aqui nossa pesquisa relevante para Dassl.
Se você achar este código útil para sua pesquisa, dê crédito ao artigo a seguir
@article{zhou2022domain,
title={Domain generalization: A survey},
author={Zhou, Kaiyang and Liu, Ziwei and Qiao, Yu and Xiang, Tao and Loy, Chen Change},
journal={IEEE Transactions on Pattern Analysis and Machine Intelligence},
year={2022},
publisher={IEEE}
}
@article{zhou2021domain,
title={Domain adaptive ensemble learning},
author={Zhou, Kaiyang and Yang, Yongxin and Qiao, Yu and Xiang, Tao},
journal={IEEE Transactions on Image Processing},
volume={30},
pages={8008--8018},
year={2021},
publisher={IEEE}
}