컴퓨터/Etc

[NNI] Dependency-aware Mode

xeskin 2020. 10. 29. 14:20
반응형

*본 포스팅은 NNI 도큐먼트의 'Dependency-aware Mode' 항목을 번역한 것입니다. (nni.readthedocs.io/en/latest/Compression/DependencyAware.html)

 

Dependency-aware Mode for Filter Pruning

  지금까지 FPGM, L1, L2 APoZ Filter Pruner와 같이 컨볼루션 레이어를 위한 필터 프루닝 알고리즘을 봤다. 필터 프루닝 알고리즘은 컨볼루션 신경망을 독립적으로 프루닝한다. 그리고, 컨볼루션 레이어를 프루닝하는 동안 알고리즘은 각 규칙(예: L1-norm)에 따라 필터의 중요도를 계산하고 덜 중요한 필터를 프루닝한다.

 

  Dependency analysis utils에서 봤던 것처럼 두 개의 컨볼루션 레이어(conv1, conv2)의 아웃풋 채널이 합쳐지면 두 컨볼루션 레이어는 서로 채널 종속성을 갖는다. 다음 그림을 예로 들어보자.

  conv1 레이어에서 50%의 아웃풋 채널을 프루닝하고 conv2 레이어에서 다른 50%의 아웃풋 채널을 프루닝했다고 쳐보자. 그러면, 이 둘 레이어가 모두 필터를 50% 프루닝했지만 speedup modul은 아웃풋 채널을 정렬하기 위해서 0을 추가해야 된다. 이 경우, 우리는 프루닝을 통한 속도 향상 이점을 얻을 수 없다.

 

  NNI는 모델 프루닝의 이점을 얻기 위해서, 필터 프루닝에 대해 dependency-aware mode를 추가했다. Dependency-aware mode를 켠 Filter Pruner는 각 필터를 L1-norm에 기반해서 프루닝할 뿐 아니라 네트워크의 아키텍쳐 또한 고려한다.

 

  Dependency-aware mode(dependency_aware를 True로 세팅)에서 프루너는 다음 그림에서 보는 것과 같이 서로 채널 종속성이 있는 레이어에 대해 동일한 아웃풋 채널을 제거하려고 시도한다.

  예를 들어, L1 필터 프루너에 dependency-aware mode를 킨 경우를 생각해보자. 프루너는 각 채널의 dependency set에 있는 모든 레이어의 L1-norm을 계산한다. dependency set에서 실제로 제거되는 채널의 개수는 dependency set(min_sparsity로 표기된다.)에 있는 레이어의 sparsity의 최소값으로 결정된다. 각 채널의 L1-norm 값에 따라서 프루너는 모든 레이어에 대해서 같은 min_sparsity 채널을 제거할 것이다. 그리고난뒤, 프루너는 각 채널의 L1-norm에 따라서 'sparsity-min_sparsity'만큼 채널을 제거한다. 예를 들어서 conv1, conv2의 아웃풋 채널이 더해지고 각각의 configured sparsity가 0.3, 0.2라고 해보자. 이 경우 dependency-aware pruner는 다음과 같이 동작한다.

 

1. conv1, conv2의 L1-norm에 기반해 각각의 같은 위치에 있는 채널을 20%만큼 제거한다.

2. conv1의 각 채널에 L1-norm에 기반해 남은 10%를 제거한다.

 

  또한 필터 그룹이 두 개 이상인 컨볼루션 레이어의 경우 dependency-aware pruner는 각 필터 그룹에 대해 동일한 수의 아웃풋 채널을 정리한다. 전반적으로 프루너는 각 필터의 L1-norm에 따라 필터를 제거하고 네트워크 토폴로지 제약(channel dependency, etc)을 충족하여 속도 향상을 얻을 수 있는 프로세스를 진행한 이후 모델의 최종 속도에 이득을 높이려고 한다.

 

  Dependency-aware model에서 프루너는 일반적인 모델 프루닝보다 더 나은 속도 향상을 제공한다.

 

Usage

 이 섹션에서는 필터 프루너에 대해 dependency-aware mode를 사용할 수 있는 방법을 보일 것이다. 현재 NNI에서 제공하고 있는 FPGM, L1, L2, APoZ, Activation Mean, Taylor FO 등과 같은 프루너에 대해 dependency-aware mode를 지원한다.

 

  L1FilterPruner에 depencdency-aware mode를 사용하는 방법은 다음과 같다.

from nni.compression.torch import L1FilterPruner
config_list = [{ 'sparsity': 0.8, 'op_types': ['Conv2d'] }]
# dummy_input is necessary for the dependency_aware mode
dummy_input = torch.ones(1, 3, 224, 224).cuda()
pruner = L1FilterPruner(model, config_list, dependency_aware=True, dummy_input=dummy_input)
# for L2FilterPruner
# pruner = L2FilterPruner(model, config_list, dependency_aware=True, dummy_input=dummy_input)
# for FPGMPruner
# pruner = FPGMPruner(model, config_list, dependency_aware=True, dummy_input=dummy_input)
# for ActivationAPoZRankFilterPruner
# pruner = ActivationAPoZRankFilterPruner(model, config_list, statistics_batch_num=1, , dependency_aware=True, dummy_input=dummy_input)
# for ActivationMeanRankFilterPruner
# pruner = ActivationMeanRankFilterPruner(model, config_list, statistics_batch_num=1, dependency_aware=True, dummy_input=dummy_input)
# for TaylorFOWeightFilterPruner
# pruner = TaylorFOWeightFilterPruner(model, config_list, statistics_batch_num=1, dependency_aware=True, dummy_input=dummy_input)

pruner.compress()

 

Evaluation

 

 

 

 

 

 

 

 

반응형