저전력 자율 배포를 위한 순환 제조 공급망의 Cross-Modal Knowledge Distillation
Source: Dev.to
Introduction: The Learning Journey That Sparked This Exploration
모든 것은 스마트 재활용 시설을 위한 엣지 디바이스에 컴퓨터 비전 모델을 배포해 보면서 시작되었습니다. 저는 시각, 열, 스펙트럼 데이터를 이용해 재료를 식별하고, 품질을 평가하며, 열화 패턴을 예측할 수 있는 정교한 멀티모달 AI 시스템을 개발했습니다. 이 모델은 실험실에서 재료 분류 정확도 98.7 %를 달성하며 뛰어난 성능을 보였습니다. 하지만 실제 시설의 분류 로봇에 배포했을 때는 문제가 발생했습니다: 태양광 배터리로 구동되는 저전력 ARM 프로세서에서는 계산 요구량이 너무 높았던 것입니다.
모델 압축 기법을 조사하던 중, 처리 비용이 큰 열영상 데이터가 시각 데이터만으로도 근사될 수 있는 패턴을 포함하고 있다는 사실을 발견했습니다. 모델이 기본 관계를 학습하면 시각 데이터만으로도 열영상 정보를 추정할 수 있다는 통찰이 교차 모달 지식 증류로 이어졌습니다. 여기서 가벼운 “학생” 모델은 단일 모달(시각)만을 사용해 다중 모달을 처리하는 복잡한 “교사” 앙상블의 행동을 모방합니다.
핵심 발견은 지식 전달이 단순히 모델 압축을 넘어, 순환 공급망에서 복잡한 의사결정을 수행할 수 있는 지능을 유지하면서도 자원 제한 환경에서 AI 시스템이 자율적으로 동작할 수 있게 만든다는 점이었습니다.
Technical Background: The Convergence of Multiple Disciplines
The Circular Manufacturing Challenge
순환 제조는 선형 “채취‑제조‑폐기” 모델에서 재료가 지속적으로 회수·재처리·재사용되는 폐쇄 루프 시스템으로 전환합니다. 이 맥락에서 자율 AI는 다음을 처리해야 합니다:
- 재료 식별 – 다양한 열화 상태의 재료를 인식합니다.
- 품질 평가 – 재료가 재사용, 수리 또는 재활용이 필요한지를 판단합니다.
- 프로세스 최적화 – 실시간으로 분류, 라우팅, 가공에 대한 결정을 내립니다.
- 예측 유지보수 – 원격 위치에서 장비 고장을 사전에 예측합니다.
전통적으로 각 작업마다 다른 데이터 모달을 처리하는 별도 AI 모델이 필요했으며, 이는 저전력 배포 시 계산 병목을 초래했습니다.
Cross‑Modal Knowledge Distillation Fundamentals
전통적인 지식 증류는 큰 모델을 작은 모델로 압축하면서 성능을 유지합니다. 교차 모달 증류는 새로운 차원을 추가합니다: 서로 다른 데이터 유형 간에 지식을 전달하는 것입니다.
세 가지 기본 접근 방식:
- 특징 기반 증류 – 모달 간 중간 표현을 일치시킵니다.
- 주의 기반 증류 – 중요한 영역을 강조하는 어텐션 패턴을 전달합니다.
- 관계 증류 – 서로 다른 샘플 또는 특징 간의 관계를 보존합니다.
순환 제조 응용에서는 시각적 외관을 재료 특성과 연결할 때, 세 가지 방법을 모두 결합한 하이브리드 접근이 최상의 결과를 제공합니다.
Implementation Details: Building the Cross‑Modal Framework
Architecture Overview
모달별 인코더와 공유 증류 모듈을 갖춘 교사‑학생 프레임워크가 가장 효과적이었습니다. 아래는 핵심 교사 아키텍처입니다:
import torch
import torch.nn as nn
import torch.nn.functional as F
class MultiModalTeacher(nn.Module):
"""Teacher model processing multiple modalities"""
def __init__(self, visual_dim=512, thermal_dim=256, spectral_dim=128):
super().__init__()
# Modality‑specific encoders
self.visual_encoder = self._build_visual_encoder(visual_dim)
self.thermal_encoder = self._build_thermal_encoder(thermal_dim)
self.spectral_encoder = self._build_spectral_encoder(spectral_dim)
# Cross‑modal fusion
self.fusion_layer = nn.Sequential(
nn.Linear(visual_dim + thermal_dim + spectral_dim, 512),
nn.ReLU(),
nn.Dropout(0.3)
)
# Task‑specific heads
self.material_classifier = nn.Linear(512, 50) # 50 material types
self.quality_regressor = nn.Linear(512, 1) # Quality score
self.degradation_predictor = nn.Linear(512, 10) # Degradation states
def forward(self, visual_input, thermal_input, spectral_input):
visual_features = self.visual_encoder(visual_input)
thermal_features = self.thermal_encoder(thermal_input)
spectral_features = self.spectral_encoder(spectral_input)
# Concatenate and fuse
fused = torch.cat([visual_features, thermal_features, spectral_features], dim=1)
fused = self.fusion_layer(fused)
return {
'material': self.material_classifier(fused),
'quality': self.quality_regressor(fused),
'degradation': self.degradation_predictor(fused),
'features': {
'visual': visual_features,
'thermal': thermal_features,
'spectral': spectral_features,
'fused': fused
}
}
The Lightweight Student Model
학생 모델은 시각 데이터만을 처리하지만 교사의 멀티모달 이해를 근사하도록 학습합니다:
class VisualOnlyStudent(nn.Module):
"""Student model using only visual input"""
def __init__(self, visual_dim=256, hidden_dim=128):
super().__init__()
# Efficient visual encoder (MobileNet‑like)
self.visual_encoder = nn.Sequential(
nn.Conv2d(3, 32, kernel_size=3, stride=2, padding=1),
nn.BatchNorm2d(32),
nn.ReLU6(),
nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),
nn.BatchNorm2d(64),
nn.ReLU6(),
nn.AdaptiveAvgPool2d((1, 1)),
nn.Flatten(),
nn.Linear(64, visual_dim)
)
# Compact task heads
self.material_classifier = nn.Linear(visual_dim, 50)
self.quality_regressor = nn.Linear(visual_dim, 1)
def forward(self, visual_input):
visual_features = self.visual_encoder(visual_input)
return {
'material': self.material_classifier(visual_features),
'quality': self.quality_regressor(visual_features),
'features': visual_features
}
Cross‑Modal Distillation Loss
복합 손실 함수는 소프트 타깃 매칭, 특징 정렬, 관계 제약을 결합합니다:
class CrossModalDistillationLoss(nn.Module):
def __init__(self, temperature=3.0, alpha=0.7, beta=0.2, gamma=0.1):
super().__init__()
self.temperature = temperature
self.alpha = alpha
self.beta = beta
self.gamma = gamma
self.kl_div = nn.KLDivLoss(reduction='batchmean')
self.mse = nn.MSELoss()
self.cosine = nn.CosineEmbeddingLoss()
def forward(self, teacher_outputs, student_outputs):
# 1. Soft target (logits) distillation
t_logits = teacher_outputs['material'] / self.temperature
s_logits = student_outputs['material'] / self.temperature
loss_soft = self.kl_div(F.log_softmax(s_logits, dim=1),
F.softmax(t_logits, dim=1)) * (self.temperature ** 2)
# 2. Feature‑based distillation (visual features)
loss_feat = self.mse(student_outputs['features'],
teacher_outputs['features']['visual'])
# 3. Relational distillation (pairwise similarity)
t_feat = teacher_outputs['features']['visual']
s_feat = student_outputs['features']
t_sim = F.normalize(t_feat, dim=1) @ F.normalize(t_feat, dim=1).t()
s_sim = F.normalize(s_feat, dim=1) @ F.normalize(s_feat, dim=1).t()
loss_rel = self.mse(s_sim, t_sim)
# Composite loss
total_loss = self.alpha * loss_soft + self.beta * loss_feat + self.gamma * loss_rel
return total_loss
손실은 세 가지 항을 결합합니다:
- 소프트 타깃 손실 (
loss_soft)은 학생의 클래스 예측을 교사의 부드러운 로짓과 정렬합니다. - 특징 손실 (
loss_feat)은 학생의 시각 임베딩이 교사의 시각 임베딩과 일치하도록 강제합니다. - 관계 손실 (
loss_rel)은 샘플 간의 쌍별 관계를 보존하여 학생이 교사의 내부 기하 구조를 포착하도록 돕습니다.