Neural Architecture Search (신경망 구조 탐색)¶
메타 정보¶
| 항목 | 내용 |
|---|---|
| 분류 | AutoML / Architecture Design / Optimization |
| 핵심 논문 | "Neural Architecture Search with Reinforcement Learning" (Zoph & Le, ICLR 2017), "Learning Transferable Architectures for Scalable Image Recognition" (Zoph et al., CVPR 2018, NASNet), "Efficient Neural Architecture Search via Parameter Sharing" (Pham et al., ICML 2018, ENAS), "DARTS: Differentiable Architecture Search" (Liu et al., ICLR 2019), "ProxylessNAS: Direct Neural Architecture Search on Target Task and Hardware" (Cai et al., ICLR 2019), "EfficientNet: Rethinking Model Scaling for CNNs" (Tan & Le, ICML 2019), "Once-for-All: Train One Network and Specialize it for Efficient Deployment" (Cai et al., ICLR 2020), "A Survey on Neural Architecture Search" (Elsken et al., JMLR 2019) |
| 주요 저자 | Barret Zoph (NAS 개척), Quoc V. Le (Google Brain, NAS/EfficientNet), Hanxiao Liu (DARTS), Han Cai (ProxylessNAS, OFA, MIT HAN Lab), Song Han (MIT HAN Lab, Hardware-Aware NAS), Mingxing Tan (EfficientNet/EfficientDet), Frank Hutter (NAS-Bench, Survey) |
| 핵심 개념 | 사람이 수동으로 설계하던 신경망 구조(layer 수, 연결 방식, 연산 종류 등)를 자동으로 탐색하는 기법으로, 탐색 공간(Search Space), 탐색 전략(Search Strategy), 성능 추정(Performance Estimation)의 세 축으로 구성 |
| 관련 분야 | Bayesian Optimization, Meta-Learning, Knowledge Distillation, Model Compression, Transfer Learning |
정의¶
Neural Architecture Search(NAS)는 주어진 태스크와 데이터셋에 대해 최적의 신경망 구조를 자동으로 발견하는 기법이다. 전통적인 딥러닝에서는 연구자가 수동으로 네트워크 아키텍처를 설계하지만, NAS는 이 과정을 최적화 문제로 정식화하여 알고리즘이 탐색하도록 한다.
NAS는 세 가지 핵심 구성요소로 이루어진다:
- Search Space (탐색 공간): 탐색 가능한 아키텍처의 집합을 정의
- Search Strategy (탐색 전략): 탐색 공간에서 후보 아키텍처를 효율적으로 선택하는 방법
- Performance Estimation Strategy (성능 추정): 후보 아키텍처의 성능을 빠르게 평가하는 방법
Neural Architecture Search 프레임워크:
탐색 공간 (Search Space)
- Cell-based / Global
- 연산 종류, 연결 패턴
|
v
+-------------------------------------------+
| 탐색 전략 (Search Strategy) |
| |
| RL-based Evolutionary Gradient-based |
| (NASNet) (AmoebaNet) (DARTS) |
| |
| One-Shot / Weight Sharing |
| (ENAS, SuperNet) |
+-------------------------------------------+
|
후보 아키텍처
|
v
+-------------------------------------------+
| 성능 추정 (Performance Estimation) |
| |
| Full Training | Proxy Tasks | Predictor|
| (정확하나 느림) | (축소 데이터) | (학습 기반) |
| | | |
| Weight Sharing | Early Stop | Zero-Cost|
| (SuperNet) | (학습곡선) | (초기화) |
+-------------------------------------------+
|
v
최적 아키텍처 A*
핵심 원리¶
1. 탐색 공간 (Search Space)¶
탐색 공간의 설계가 NAS의 성능과 효율성을 결정한다. 크게 두 가지 패러다임이 존재한다.
Global Search Space¶
전체 네트워크 구조를 한꺼번에 탐색한다. 초기 NAS(Zoph & Le, 2017)에서 사용된 방식으로, 탐색 공간이 매우 크다.
Cell-based Search Space¶
NASNet(Zoph et al., 2018)에서 도입된 방식으로, 전체 네트워크 대신 반복되는 셀(cell)의 구조만 탐색한다.
- Normal Cell: 입력과 동일한 공간 해상도를 유지하는 특징 추출 블록
- Reduction Cell: 공간 해상도를 절반으로 줄이는 다운샘플링 블록
Cell-based Search Space:
셀 내부 구조 탐색:
Input1 ---+--- [op1] ---+
| |--- [combine] --- Output
Input2 ---+--- [op2] ---+
op in {3x3 conv, 5x5 conv, 3x3 sep_conv,
max_pool, avg_pool, identity, zero}
전체 네트워크 = Normal Cell x N + Reduction Cell 반복 적재:
[Normal] x 6 -> [Reduction] -> [Normal] x 6 -> [Reduction] -> [Normal] x 6
셀 기반 탐색은 (1) 탐색 공간을 크게 축소하고, (2) 작은 데이터셋에서 찾은 셀을 큰 데이터셋에 전이(transfer)할 수 있다는 장점이 있다.
2. 탐색 전략 (Search Strategy)¶
2.1 강화학습 기반 (RL-based)¶
Zoph & Le (2017)가 처음 제안한 방식. 컨트롤러(controller) RNN이 아키텍처를 토큰 시퀀스로 생성하고, 생성된 아키텍처의 검증 정확도를 보상(reward)으로 사용하여 REINFORCE 알고리즘으로 학습한다.
RL 기반 NAS:
Controller (RNN)
|
| 아키텍처 토큰 시퀀스 생성
| [layer1_type, kernel_size, stride, ...]
v
Child Network 학습 & 평가
|
| 검증 정확도 = Reward R
v
Controller 파라미터 업데이트
theta <- theta + alpha * nabla_theta * log(P(a|theta)) * R
(REINFORCE)
- 비용: 원본 NAS는 500 GPU-days (800 GPU로 28일). NASNet은 프록시 태스크로 줄였지만 여전히 2,000 GPU-hours 수준.
2.2 진화 알고리즘 기반 (Evolutionary)¶
Real et al. (2019)의 AmoebaNet이 대표적. 아키텍처 집단(population)을 유지하면서 돌연변이(mutation)와 선택(selection)을 반복하여 진화시킨다.
- Tournament Selection: 무작위로 S개를 뽑아 가장 좋은 것을 부모로 선택
- Aging Evolution: 가장 오래된 개체를 제거하여 최근 성능이 좋은 구조를 유지
2.3 미분 가능 탐색 (Differentiable / Gradient-based)¶
DARTS (Liu et al., 2019)가 개척한 방식으로, 이산적인 아키텍처 선택을 연속 완화(continuous relaxation)하여 경사하강법으로 탐색한다.
# DARTS 핵심 아이디어: Continuous Relaxation
# 이산적 연산 선택을 softmax 가중합으로 변환
import torch
import torch.nn.functional as F
class MixedOp(torch.nn.Module):
"""DARTS의 혼합 연산: 모든 후보 연산의 가중합"""
def __init__(self, C, stride, ops_list):
super().__init__()
self.ops = torch.nn.ModuleList()
for op_name in ops_list:
self.ops.append(build_op(op_name, C, stride))
def forward(self, x, weights):
# weights = softmax(alpha): 각 연산의 가중치
return sum(w * op(x) for w, op in zip(weights, self.ops))
class DARTSCell(torch.nn.Module):
"""DARTS 셀: 노드 간 혼합 연산으로 구성"""
def __init__(self, steps, C, ops_list):
super().__init__()
self.steps = steps
# 아키텍처 파라미터 alpha: 각 에지의 연산 가중치
self.alphas = torch.nn.ParameterList()
self.mixed_ops = torch.nn.ModuleList()
for i in range(steps):
for j in range(i + 2): # 이전 노드 + 2개 입력
alpha = torch.nn.Parameter(
torch.randn(len(ops_list)) * 1e-3
)
self.alphas.append(alpha)
self.mixed_ops.append(MixedOp(C, stride=1, ops_list=ops_list))
def forward(self, s0, s1):
states = [s0, s1]
offset = 0
for i in range(self.steps):
s = sum(
self.mixed_ops[offset + j](
states[j],
F.softmax(self.alphas[offset + j], dim=-1)
)
for j in range(len(states))
)
offset += len(states)
states.append(s)
return torch.cat(states[-self.steps:], dim=1)
DARTS의 Bilevel Optimization:
- 상위 문제: 아키텍처 파라미터 alpha를 검증 손실로 최적화
- 하위 문제: 네트워크 가중치 w를 학습 손실로 최적화
실제로는 w와 alpha를 번갈아 업데이트하는 근사를 사용한다. 탐색 비용은 약 1.5 GPU-days로, RL 기반 대비 1000배 이상 효율적이다.
DARTS의 한계와 개선¶
| 문제 | 설명 | 해결 방법 |
|---|---|---|
| Performance Collapse | skip connection에 과도하게 편향 | DARTS+ (early stopping), Fair DARTS (sigmoid 대체) |
| Search-Eval Gap | 탐색 시와 최종 학습 시 성능 차이 | P-DARTS (점진적 깊이 증가), SDARTS (정규화) |
| 메모리 비용 | 모든 연산을 동시 유지 | ProxylessNAS (이진 게이트), GDAS (Gumbel sampling) |
| 불안정한 탐색 | alpha 수렴이 불안정 | DARTS- (auxiliary skip), Single-DARTS |
3. 성능 추정 전략 (Performance Estimation)¶
후보 아키텍처를 처음부터 끝까지 학습시키는 것은 비현실적이므로, 빠른 성능 추정이 필수적이다.
| 방법 | 설명 | 속도 | 정확도 |
|---|---|---|---|
| Full Training | 완전 학습 후 평가 | 매우 느림 | 가장 정확 |
| Proxy Task | 축소 데이터/에폭에서 학습 | 빠름 | 양호 |
| Weight Sharing | SuperNet에서 서브네트워크 추출 | 빠름 | 양호 |
| Learning Curve Extrapolation | 초기 학습 곡선으로 최종 성능 예측 | 빠름 | 보통 |
| Zero-Cost Proxy | 학습 없이 초기화 상태에서 점수 산출 | 매우 빠름 | 제한적 |
| Predictor-based | 학습된 예측기로 성능 추정 | 빠름 | 양호 |
Weight Sharing (One-Shot NAS)¶
ENAS(Pham et al., 2018)에서 제안된 핵심 기법. 하나의 SuperNet(과네트워크)에 모든 후보 아키텍처를 포함시키고, 파라미터를 공유한다.
Weight Sharing 개념:
SuperNet (모든 가능한 연산과 연결 포함)
|
+-- SubNet A (경로 1) ---> 성능 평가
|
+-- SubNet B (경로 2) ---> 성능 평가
|
+-- SubNet C (경로 3) ---> 성능 평가
|
...
모든 SubNet이 SuperNet의 가중치를 공유
-> 각 SubNet을 독립적으로 학습할 필요 없음
-> 탐색 비용: 500 GPU-days -> 0.5 GPU-days
4. Hardware-Aware NAS¶
실제 배포 환경에서는 정확도뿐만 아니라 지연시간(latency), 에너지 소비, 모델 크기 등 하드웨어 제약을 함께 고려해야 한다.
ProxylessNAS (Cai et al., 2019)¶
- DARTS처럼 미분 가능한 탐색을 사용하되, 이진 게이트(binary gate)로 메모리 문제를 해결
- 하드웨어 지연시간을 미분 가능한 손실로 통합
- GPU, CPU, Mobile 각 타겟에 맞춘 전용 아키텍처를 탐색
ProxylessNAS 목적함수:
min_{alpha} E[L_val(w, alpha)] + lambda * E[Latency(alpha)]
Latency(alpha) = sum_i sum_j p_j^i * lat_j^i
(각 레이어 i의 연산 j 선택 확률 x 해당 연산의 지연시간)
Once-for-All (OFA, Cai et al., 2020)¶
한 번 학습한 SuperNet에서 다양한 하드웨어 제약에 맞는 서브네트워크를 추가 학습 없이 추출한다.
# Once-for-All 활용 예시: 타겟 하드웨어에 맞는 서브네트워크 추출
# OFA는 학습된 SuperNet에서 탐색만으로 최적 서브넷 획득
from ofa.model_zoo import ofa_net
from ofa.nas.efficiency_predictor import LatencyTable
# 1. 사전학습된 OFA 네트워크 로드
ofa_network = ofa_net("ofa_mbv3_d234_e346_k357_w1.2", pretrained=True)
# 2. 타겟 하드웨어의 지연시간 테이블
latency_table = LatencyTable(device="note10") # Samsung Note 10
# 3. 제약 조건 하에서 진화 탐색
from ofa.nas.search_algorithm import EvolutionFinder
finder = EvolutionFinder(
efficiency_predictor=latency_table,
accuracy_predictor=accuracy_predictor, # 학습된 정확도 예측기
constraint_type="latency",
constraint=25, # 25ms 이내
)
best_config, best_info = finder.run_evolution_search()
# best_config: {"ks": [7,3,5,...], "d": [4,3,4,...], "e": [6,4,3,...]}
# 4. 서브네트워크 추출 (추가 학습 불필요)
ofa_network.set_active_subnet(**best_config)
subnet = ofa_network.get_active_subnet(preserve_weight=True)
# 5. 추출된 서브넷 평가
top1_acc = evaluate(subnet, imagenet_val_loader)
latency = measure_latency(subnet, device="note10")
print(f"Top-1: {top1_acc:.1f}%, Latency: {latency:.1f}ms")
5. NAS Benchmarks¶
공정한 비교를 위한 표준 벤치마크:
| 벤치마크 | 설명 | 탐색 공간 크기 | 논문 |
|---|---|---|---|
| NAS-Bench-101 | CIFAR-10 위 423K 아키텍처 사전 평가 | ~423K | Ying et al., ICML 2019 |
| NAS-Bench-201 | 3개 데이터셋, 15,625 아키텍처 | 15,625 | Dong & Yang, ICLR 2020 |
| NAS-Bench-301 | DARTS 탐색 공간의 surrogate benchmark | ~10^18 | Siems et al., 2020 |
| TransNAS-Bench-101 | 7개 태스크, 아키텍처 전이성 평가 | 4,096 / 3,256 | Duan et al., CVPR 2021 |
주요 방법론 계보¶
NAS 발전 계보:
2017 [NAS-RL] 강화학습 기반, 500 GPU-days
(Zoph & Le, ICLR 2017)
|
2018 [NASNet] Cell-based 탐색 공간 도입, 전이 가능
(Zoph et al., CVPR 2018)
|
+--- [ENAS] Weight Sharing, 0.5 GPU-days
| (Pham et al., ICML 2018)
|
+--- [AmoebaNet] 진화 알고리즘, 정규화된 진화
(Real et al., AAAI 2019)
|
2019 [DARTS] 미분 가능 탐색, 1.5 GPU-days
(Liu et al., ICLR 2019)
|
+--- [ProxylessNAS] Hardware-Aware, 이진 게이트
| (Cai et al., ICLR 2019)
|
+--- [FBNet] Facebook, 미분가능 + HW-Aware
| (Wu et al., CVPR 2019)
|
+--- [MnasNet / EfficientNet] 복합 스케일링
(Tan & Le, ICML 2019)
|
2020 [OFA] 한번 학습, 다수 배포
(Cai et al., ICLR 2020)
|
+--- [Zero-Cost NAS] 학습 없는 프록시
(Mellor et al., ICML 2021)
|
2021+ [NAS for Transformers / LLMs]
AutoFormer, BossNAS, LiteTransformerSearch
하드웨어 효율적 Transformer 구조 탐색
EfficientNet: NAS의 산업적 성공 사례¶
EfficientNet(Tan & Le, 2019)은 NAS의 가장 성공적인 산업 적용 사례 중 하나이다.
- MnasNet의 NAS로 기본 아키텍처(EfficientNet-B0)를 탐색
- Compound Scaling: 깊이(depth), 너비(width), 해상도(resolution)를 동시에 스케일링
Compound Scaling:
depth: d = alpha^phi
width: w = beta^phi
resolution: r = gamma^phi
제약: alpha * beta^2 * gamma^2 ~= 2
(FLOPS가 약 2^phi 배 증가)
EfficientNet-B0 (NAS로 탐색) -> B1 -> B2 -> ... -> B7
phi = 1.0 1.0 1.1 5.3
| 모델 | Top-1 (ImageNet) | Params | FLOPS |
|---|---|---|---|
| EfficientNet-B0 | 77.1% | 5.3M | 0.39B |
| EfficientNet-B3 | 81.6% | 12M | 1.8B |
| EfficientNet-B7 | 84.3% | 66M | 37B |
| ResNet-50 | 76.0% | 26M | 4.1B |
| ResNet-152 | 78.3% | 60M | 11.6B |
EfficientNet-B0은 ResNet-50보다 적은 파라미터와 FLOPS로 더 높은 정확도를 달성한다.
실전 Python 예시¶
NNI를 활용한 NAS¶
# Microsoft NNI 프레임워크를 활용한 NAS 파이프라인
# NNI는 다양한 NAS 알고리즘을 통합된 인터페이스로 제공
import nni
import nni.nas.nn.pytorch as nas_nn
from nni.nas import strategy, evaluator
import torch
import torch.nn as nn
# 1. 탐색 공간 정의: ValueChoice로 후보 설정
class SearchableBlock(nas_nn.Module):
"""탐색 가능한 CNN 블록"""
def __init__(self, in_channels, out_channels):
super().__init__()
# 커널 크기 탐색: 3x3, 5x5, 7x7 중 선택
kernel_size = nni.nas.nn.ValueChoice([3, 5, 7])
self.conv = nas_nn.Conv2d(
in_channels, out_channels,
kernel_size=kernel_size,
padding=kernel_size // 2
)
self.bn = nn.BatchNorm2d(out_channels)
self.relu = nn.ReLU()
def forward(self, x):
return self.relu(self.bn(self.conv(x)))
class SearchableNetwork(nas_nn.Module):
"""탐색 가능한 전체 네트워크"""
def __init__(self, num_classes=10):
super().__init__()
# 레이어 수 탐색: 2, 3, 4 중 선택
num_layers = nni.nas.nn.ValueChoice([2, 3, 4])
channels = [32, 64, 128, 256]
self.stem = nn.Sequential(
nn.Conv2d(3, 32, 3, padding=1),
nn.BatchNorm2d(32),
nn.ReLU()
)
self.layers = nni.nas.nn.Repeat(
lambda i: SearchableBlock(
channels[min(i, len(channels)-2)],
channels[min(i+1, len(channels)-1)]
),
depth=num_layers
)
self.classifier = nn.Sequential(
nn.AdaptiveAvgPool2d(1),
nn.Flatten(),
nn.Linear(256, num_classes)
)
def forward(self, x):
x = self.stem(x)
x = self.layers(x)
return self.classifier(x)
# 2. 평가기 정의
from nni.nas.evaluator.pytorch import Classification
eval = Classification(
train_dataloaders=train_loader,
val_dataloaders=val_loader,
max_epochs=50,
learning_rate=0.025,
)
# 3. 탐색 전략 선택 및 실행
# DARTS 전략 사용
search_strategy = strategy.DARTS()
# 탐색 실행
from nni.nas.experiment import NasExperiment
experiment = NasExperiment(
model=SearchableNetwork(),
evaluator=eval,
strategy=search_strategy,
)
experiment.run()
# 4. 최적 아키텍처 추출
best_arch = experiment.export_top_models(top_k=1)[0]
print("Best architecture:", best_arch)
Optuna + NAS 스타일 하이퍼파라미터 탐색¶
# Optuna를 활용한 경량 NAS: 아키텍처 하이퍼파라미터 탐색
# 실무에서 가장 접근하기 쉬운 방법
import optuna
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
def build_model(trial):
"""Optuna trial로 아키텍처 구성"""
layers = []
in_channels = 3
# 레이어 수 탐색
n_layers = trial.suggest_int("n_layers", 2, 5)
for i in range(n_layers):
out_channels = trial.suggest_categorical(
f"channels_{i}", [32, 64, 128, 256]
)
kernel_size = trial.suggest_categorical(
f"kernel_{i}", [3, 5]
)
use_bn = trial.suggest_categorical(
f"use_bn_{i}", [True, False]
)
layers.append(nn.Conv2d(
in_channels, out_channels,
kernel_size=kernel_size,
padding=kernel_size // 2
))
if use_bn:
layers.append(nn.BatchNorm2d(out_channels))
layers.append(nn.ReLU())
# 매 2번째 레이어마다 풀링
if i % 2 == 1:
layers.append(nn.MaxPool2d(2))
in_channels = out_channels
model = nn.Sequential(
*layers,
nn.AdaptiveAvgPool2d(1),
nn.Flatten(),
nn.Linear(out_channels, 10)
)
return model
def objective(trial):
"""Optuna 목적함수: 검증 정확도 최대화"""
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = build_model(trial).to(device)
lr = trial.suggest_float("lr", 1e-4, 1e-1, log=True)
optimizer = torch.optim.Adam(model.parameters(), lr=lr)
criterion = nn.CrossEntropyLoss()
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
train_data = datasets.CIFAR10("./data", train=True, transform=transform)
val_data = datasets.CIFAR10("./data", train=False, transform=transform)
train_loader = DataLoader(train_data, batch_size=128, shuffle=True)
val_loader = DataLoader(val_data, batch_size=256)
# 프록시 태스크: 적은 에폭으로 빠르게 평가
for epoch in range(10):
model.train()
for x, y in train_loader:
x, y = x.to(device), y.to(device)
loss = criterion(model(x), y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 중간 결과 보고 (pruning 지원)
model.eval()
correct, total = 0, 0
with torch.no_grad():
for x, y in val_loader:
x, y = x.to(device), y.to(device)
correct += (model(x).argmax(1) == y).sum().item()
total += y.size(0)
accuracy = correct / total
trial.report(accuracy, epoch)
if trial.should_prune():
raise optuna.TrialPruned()
return accuracy
# 탐색 실행
study = optuna.create_study(
direction="maximize",
pruner=optuna.pruners.MedianPruner(n_warmup_steps=3),
)
study.optimize(objective, n_trials=100)
print(f"Best accuracy: {study.best_value:.4f}")
print(f"Best architecture: {study.best_params}")
비교 분석¶
탐색 전략 비교¶
| 전략 | 탐색 비용 | 대표 방법 | 장점 | 단점 |
|---|---|---|---|---|
| RL 기반 | 500+ GPU-days | NAS, NASNet | 유연한 탐색 공간 | 매우 높은 비용 |
| 진화 알고리즘 | 300+ GPU-days | AmoebaNet | 병렬화 용이, 다목적 최적화 | 높은 비용 |
| 미분 가능 | 1-4 GPU-days | DARTS, ProxylessNAS | 효율적, 그래디언트 활용 | 안정성 이슈, 메모리 |
| One-Shot | 0.5-2 GPU-days | ENAS, SPOS | 매우 효율적 | 순위 상관 불완전 |
| Zero-Cost | 수 초 | SynFlow, NASWOT | 즉시 평가 | 낮은 상관성 |
NAS 발견 아키텍처 vs 수동 설계¶
| 모델 | 설계 방법 | CIFAR-10 Error | ImageNet Top-1 | 탐색 비용 |
|---|---|---|---|---|
| ResNet-110 | 수동 | 6.41% | - | - |
| DenseNet-BC | 수동 | 3.46% | - | - |
| NASNet-A | RL-NAS | 2.65% | 82.7% | 2,000 GPU-hrs |
| AmoebaNet-A | 진화-NAS | 2.55% | 83.1% | 3,150 GPU-hrs |
| DARTS (2nd) | 미분-NAS | 2.76% | 73.3% | 4 GPU-days |
| ProxylessNAS | 미분-NAS (HW) | 2.08% | 75.1% | 200 GPU-hrs |
| EfficientNet-B0 | NAS + Scaling | - | 77.1% | - |
최근 동향 (2023-2025)¶
NAS for Large Language Models¶
Transformer 아키텍처에 NAS를 적용하여 효율적인 LLM 구조를 탐색하는 연구가 활발하다.
| 방향 | 설명 | 예시 |
|---|---|---|
| Attention 구조 탐색 | Multi-Head, Group-Query, Sparse Attention 등 자동 선택 | AutoFormer, S3 (Searching for Sparse Transformers) |
| MoE 라우팅 구조 | Expert 수, 라우팅 전략 자동 탐색 | AutoMoE |
| 경량 모델 탐색 | Edge/Mobile 배포를 위한 소형 LM | LiteTransformerSearch |
| Elastic Inference | 입력에 따라 동적으로 구조 조정 | MatFormer, FlexiBERT |
Zero-Cost NAS¶
학습 없이 초기화 상태에서 아키텍처의 잠재적 성능을 추정하는 프록시 지표:
- SynFlow: 시냅스 흐름 기반 파라미터 중요도
- NASWOT: 학습 없는 상태에서의 activation overlap
- GradNorm: 그래디언트 노름 기반 추정
초 단위로 수천 개 아키텍처를 스크리닝할 수 있어, 기존 NAS의 전처리 단계로 활용된다.
실무 가이드¶
언제 NAS를 사용하는가¶
| 상황 | 권장 접근 | 이유 |
|---|---|---|
| 컴퓨팅 자원 제한적 | Optuna/Ray Tune으로 HPO | NAS 대비 간단하고 효과적 |
| 특정 하드웨어 타겟 | OFA / ProxylessNAS | HW-Aware 탐색이 핵심 |
| 연구/논문 목적 | DARTS + NAS-Bench | 공정 비교 가능 |
| 산업 배포 | EfficientNet 계열 직접 사용 | 이미 최적화된 아키텍처 |
| Edge/Mobile 최적화 | OFA + TensorRT/ONNX | 한번 학습, 다수 배포 |
실무 체크리스트¶
- 먼저 기존 아키텍처 시도: ResNet, EfficientNet 등을 먼저 실험
- HPO 우선: 아키텍처보다 하이퍼파라미터 튜닝이 효과적인 경우가 많음
- 탐색 공간 축소: 도메인 지식으로 불필요한 연산 제외
- 프록시 태스크 설계: 작은 데이터/에폭으로 빠르게 평가
- 재현성 확보: NAS-Bench 사용 또는 시드 고정
참고 자료¶
| 자료 | 유형 | URL |
|---|---|---|
| Zoph & Le (2017) "NAS with RL" | 논문 | https://arxiv.org/abs/1611.01578 |
| Liu et al. (2019) "DARTS" | 논문 | https://arxiv.org/abs/1806.09055 |
| Cai et al. (2019) "ProxylessNAS" | 논문 | https://arxiv.org/abs/1812.00332 |
| Cai et al. (2020) "Once-for-All" | 논문 | https://arxiv.org/abs/1908.09791 |
| Tan & Le (2019) "EfficientNet" | 논문 | https://arxiv.org/abs/1905.11946 |
| Elsken et al. (2019) "NAS Survey" | 서베이 | https://arxiv.org/abs/1808.05377 |
| Lilian Weng "NAS" Blog | 블로그 | https://lilianweng.github.io/posts/2020-08-06-nas/ |
| NNI NAS Documentation | 도구 | https://nni.readthedocs.io/en/stable/nas/ |
| NAS-Bench-201 | 벤치마크 | https://github.com/D-X-Y/NAS-Bench-201 |