서론: 음성 데이터를 활용한 딥러닝 프로젝트
이 프로젝트는 지난 2021년에 진행한 프로젝트이다. 당시 대학원 졸업 논문 주제를 고민하다가 LibriSpeech 데이터셋을 사용하여 음성 데이터를 기반으로 하는 ResNet, DenseNet 모델을 학습시키고, 이를 앙상블하여 성능을 향상하는 프로젝트를 진행하기로 결정했다.
이번 포스팅에서는 (매우 늦은 감이 있지만) 당시 프로젝트를 진행하며 겪은 다양한 오류와 해결 과정을 정리하고자 한다. 딥러닝 기반 음성 인식 모델을 구현하는 과정에서 발생하는 문제들을 어떻게 해결했는지 공유하기 위함이다.
1. LibriSpeech 데이터셋과 전처리 과정
1.1 LibriSpeech 데이터셋
LibriSpeech는 읽기 음성 데이터를 포함한 대규모 ASR(Auto Speech Recognition) 데이터셋이다. OpenSLR에서 제공하며, torchaudio 라이브러리를 통해 쉽게 다운로드할 수 있다.
from torchaudio.datasets import LIBRISPEECH # 데이터 다운로드
train_data = LIBRISPEECH("./data", url="train-clean-100", download=True)
test_data = LIBRISPEECH("./data", url="test-clean", download=True)
하지만 데이터를 불러오는 과정에서 FileNotFoundError가 발생했다.
1.2 오류 해결: 데이터 다운로드 문제
오류 메시지는 다음과 같다.
FileNotFoundError: No such file or directory: './data/train-clean-100.tar.gz.partial'
이 문제는 파일 다운로드가 완료되지 않았거나, 네트워크 문제로 인해 데이터가 손상된 경우 발생한다. 해결 방법은 데이터를 수동으로 삭제 후 다시 다운로드하는 것이다.
rm -rf ./data/train-clean-100 python script.py # 다시 실행
2. MFCC 변환 및 데이터 전처리
2.1 MFCC 변환 적용
음성 데이터를 딥러닝 모델에 입력하려면 MFCC(Mel Frequency Cepstral Coefficients) 변환을 수행해야 한다.
from torchaudio.transforms import MFCC
mfcc_transform = MFCC(sample_rate=16000, n_mfcc=13, log_mels=True)
그런데, MFCC 변환을 적용하는 과정에서 아래와 같은 오류가 발생했다.
RuntimeError: Given input size: (512x1x50).
Calculated output size: (512x0x25).
Output size is too small
2.2 해결: 입력 크기 조정
원인은 입력 데이터의 크기가 너무 작아 Conv 연산을 거치면서 차원이 0이 되는 문제였다. 이를 해결하기 위해 입력을 50x50 크기로 패딩/리사이징 했다.
import torch.nn.functional as F
def pad_or_resize(audio, target_height=50, target_width=50):
_, height, width = audio.shape
if height < target_height or width < target_width:
audio = F.pad(audio, (0, target_width - width, 0, target_height - height))
return audio
3. ResNet과 DenseNet 모델 구현
3.1 ResNet18 모델
기존 ResNet은 이미지 데이터(3채널)를 대상으로 설계되었기 때문에, 오디오 데이터를 다루기 위해 입력 채널을 변경했다.
from torchvision.models import resnet18
class ResNetModel(nn.Module):
def __init__(self, num_classes):
super(ResNetModel, self).__init__()
self.resnet = resnet18(pretrained=False, num_classes=num_classes)
self.resnet.conv1 = nn.Conv2d(1, 64, kernel_size=3, stride=1, padding=1, bias=False)
def forward(self, x):
return self.resnet(x)
3.2 DenseNet121 모델
DenseNet 역시 이미지 데이터 기반 모델이므로 입력 크기를 조정하였다.
from torchvision.models import densenet121
class DenseNetModel(nn.Module):
def __init__(self, num_classes):
super(DenseNetModel, self).__init__()
self.densenet = densenet121(pretrained=False)
self.densenet.features.conv0 = nn.Conv2d(1, 64, kernel_size=3, stride=1, padding=1, bias=False)
self.densenet.classifier = nn.Linear(self.densenet.classifier.in_features, num_classes)
def forward(self, x):
return self.densenet(x)
4. ResNet과 DenseNet 앙상블 모델
개별 모델보다 더 나은 성능을 위해 앙상블 모델을 설계했다. 이 논문의 목표는 이러한 앙상블을 통해 실제로 성능 향상을 이끌어 내는 것을 검증하는 것이었다. ResNet과 DenseNet의 출력을 평균 내어 최종 예측값을 생성하였다.
class EnsembleModel(nn.Module):
def __init__(self, resnet, densenet):
super(EnsembleModel, self).__init__()
self.resnet = resnet
self.densenet = densenet
def forward(self, x):
resnet_out = self.resnet(x)
densenet_out = self.densenet(x)
return (resnet_out + densenet_out) / 2
5. 학습 및 평가 과정
5.1 학습 루프
각 모델을 학습하기 위한 코드이다.
def train(model, dataloader, criterion, optimizer):
model.train()
total_loss = 0
for inputs, labels in dataloader:
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
total_loss += loss.item()
return total_loss / len(dataloader)
5.2 평가 루프
모델을 평가하여 정확도를 측정한다.
def evaluate(model, dataloader):
model.eval()
preds, targets = [], []
with torch.no_grad():
for inputs, labels in dataloader:
inputs, labels = inputs.to(device), labels.to(device)
outputs = model(inputs)
_, predicted = torch.max(outputs, 1)
preds.extend(predicted.cpu().numpy())
targets.extend(labels.cpu().numpy())
return accuracy_score(targets, preds)
6. 결론 및 최종 결과
6.1 결과 비교
- ResNet 단일 모델 정확도: 0.976
- DenseNet 단일 모델 정확도: 0.978
- Ensemble Model 정확도: 0.980
앙상블 모델이 개별 모델보다 성능이 높음을 확인할 수 있었습니다.
6.2 개선 방향
- 데이터 증강(Augmentation) 적용
- Transformer 기반 모델 적용
- 더 깊은 네트워크 구조 실험
마무리
이 프로젝트를 통해 음성 데이터를 딥러닝 모델에 적용하는 방법을 배웠고, 다양한 오류를 해결하는 과정에서 많은 인사이트를 얻을 수 있었다. 특히, 입력 크기 조정, 데이터 전처리, 모델 구조 변경 등 실전에서 발생하는 문제를 해결하는 능력이 중요함을 다시 한 번 느낀 시간이었다.
AI 서비스가 발전할수록 음성 인식의 수요가 커질 것이라고 생각한다. 이미 음성 검색이나 영어 회화 앱 등에서 상당한 성과를 거두고 있는 상황이다. 앞으로도 음성인식 분야에 대해서 지속적인 관심을 가지고 새로운 프로젝트도 진행해 볼 계획이다.
'Dev' 카테고리의 다른 글
[React Native] Invariant Violation: "main" has not been registered. (0) | 2025.01.28 |
---|---|
Deep residual learning for image recognition (0) | 2023.05.03 |
Mini-batch sample selection strategies for deep learning based speech recognitio (0) | 2023.05.02 |
딥러닝 기반 음성인식 (0) | 2023.05.01 |
DenseNet (0) | 2023.04.30 |
댓글