이번에 리뷰할 논문은 Almost Unsupervised Text to Speech and Automatic Speech Recognition [1]이며, ICLR 2019에 억셉되었다.
Overview
- 음성 및 텍스트 영역 모두에서 언어 이해 및 모델링 기능을 구축하기 위해 짝을 이루지 않는 음성 및 텍스트 데이터에 대한 self-supervised learning 아이디어를 활용함
- 특히, 인코더-디코더 프레임 워크에서 손상된 음성 및 텍스트를 재구성하기 위해 Denoising Auto-Encoder를 사용함
- 역 번역의 개념인 Dual transformation을 사용하여 텍스트를 음성으로 (TTS) 및 음성을 텍스트로 (ASR) 변환하는 기능을 제안함
- 음성 및 텍스트 시퀀스가 일반적으로 Neural Machine Translation과 같은 다른 시퀀스-투-시퀀스 학습 작업보다 길다는 점을 고려하면 오류 전파로 인해 더 많은 어려움을 겪을텐데, 이는 생성된 시퀀스의 오른쪽 부분이 일반적으로 왼쪽 부분보다 나쁘다는 문제를 나타냄
- 특히 Supervised 데이터가 부족하여 리소스가 없거나 리소스가 부족한 설정에서(즉 데이터가 부족한 상황)자주 나타나는 현상임
- 따라서 Denoising Auto-Encoder 및 Dual Transformation을 기반으로 텍스트와 음성 모두에 대해 양방향 시퀀스 모델링을 추가로 활용하여 오류 전파 문제를 완화하는 것을 제안함
Intro & Related works
- 최근, 최첨단 성능의 TTS 및 ASR 시스템은 대부분 Neural Networks 기반이며, 모두 대규모 데이터를 많이 사용하므로, 쌍을 이루는 음성 및 텍스트 데이터셋이 부족한 언어에는 문제가 발생함
- 비지도 ASR에 초첨을 맞춘 작업에서는 TTS의 추가 정보를 활용하지 않는데(2019년 기준), 이는 ASR의 이중 작업이며, ASR의 성능을 향상시킬 수 있는 큰 잠재력임
- 게다가 비지도 ASR은 일반적으로 음성 파형을 단어 또는 음소로 먼저 분할하고, 세그먼트 수준에서 텍스트 데이터와 음성을 정렬하는 일부 작업별 알고리즘을 활용함
- 그러나 TTS는 일반적으로 음성 파형을 Mel-spectrogram 또는 MFCC로 변환하여 프레임 수준에서 처리함
- 따라서 비지도 ASR 용으로 설계된 알고리즘을 TTS에 쉽게 적용하기 힘듬
- 샘플이 거의 없는 특정 화자의 음성을 합성하려는 작업은 일반적으로 전이 학습 문제로 간주되지만, 비지도 학습 문제가 아닌 다른 화자의 레이블이 지정된 다량의 음성 및 텍스트 데이터를 활용함
- 그리하여 이 논문에서는, TTS와 ASR 작업의 이중 특성으로부터 영감을 받아 TTS와 ASR 모두에 대해 몇 가지 쌍을 이루는 음성 및 텍스트 데이터와 추가로 쌍을 이루지 않는 데이터를 활용하여 거의 감독되지 않는 새로운 방법을 제안함
Method
1. DAE (Denoising Auto-Encoder)
- 짝을 이루지 않는 대량의 음성 및 텍스트 데이터를 감안할 때 표현 추출 및 언어 모델링 기능을 구축하는 것이 음성과 텍스트 간의 변환을 위한 첫 번째 단계임 - 이를 위해 논문에서는 DAE를 활용하여 손상된 버전 자체에서 음성 및 텍스트 시퀀스를 재구성함 - 노이즈 제거 자동 인코더는 일반적인자가지도 학습 방법이며 비지도 학습에 널리 사용되는데, 음성 및 텍스트 데이터에 대한 노이즈 제거 자동 인코더의 손실 함수 $L^{dae}$ 는 다음과 같이 공식화됨
- 여기에서, $S, T$는 각각 음성과 텍스트 도메인의 시퀀스 데이터이며, $\theta_{enc}^T,\theta_{dec}^T$는 음성 인코더, 음성 디코더, 텍스트 인코더 그리고 텍스트 디코더의 파라미터들임 - $C$는 0값을 갖는 벡터로 일부 요소를 무작위로 마스킹하거나 음성 및 텍스트 시퀀스의 특정 창에서 요소를 교체하는 손상된 연산을 나타냄
- $L_s, L_T$ 각각 음성 및 텍스트 대상 시퀀스의 손실을 나타냄
- 이를 정리하면, $L_s$ 는 음성의 Mean Squared Errors로, $L_T$는 text Classification으로 나타낼 수 있음
2. Dual Transformation (DT)
1) DT는 TTS 및 ASR 작업의 이중 특성을 활용하고 텍스트를 음성으로 (TTS) 및 음성을 텍스트로 (ASR) 변환하는 기능을 개발하는 핵심 구성 요소임 - ASR 모델을 사용하여 음성 시퀀스 $x$를 텍스트 시퀀스 $\hat{y}$로 변환 한 다음 변환 된 쌍 $(\hat{y},x)$에서 TTS 모델을 훈련시킴 - 마찬가지로 TTS 모델에 의해 생성 된 변환 된 쌍 $(\hat{x},y)$에 대해 ASR 모델을 훈련함 - 이중 변환은 번역을 위해 단일 언어 데이터를 활용하는 가장 효과적인 방법 중 하나인 backtranslation(역번역) 으로서, Neural Machine Translation - DT는 번역을 위해 단일 언어 데이터를 활용하는 가장 효과적인 방법 중 하나인 Neural Machine Translation의 backtranslation(역-번역) 방법에서 제안되었음
- 여기에서, $\hat{y}$=argmax$P(y|x;\theta_{enc}^s,\theta_{dec}^S)$ 및, $\hat{x}=f(y;\theta_{enc}^T,\theta_{dec}^S)$는 각각 음성 $x$ 및 텍스트 $y$에서 변환된 텍스트 및 음성 시퀀스임 - 모델 학습 중에는 TTS 모델이 변환된 최신 텍스트 시퀀스를 활용하는 DT가 즉시 실행되며, 훈련을 위해 ASR 모델에 의해 또는 그 반대로 TTS 및 ASR의 정확도가 점진적으로 향상될 수 있도록 보장함
3. Bidirectional Sequence Modeling
1) Seq2seq 학습은 일반적으로 오류 전파로 어려움을 겪음
- 예를 들어, 추론 중에 요소가 실수로 예측되면 오류가 전파되며, 이로 인해 생성된 시퀀스의 오른쪽 부분 (끝 부분)이 왼쪽 부분보다(앞 부분) 정확도가 떨어짐 - 음성 및 텍스트 시퀀스는 일반적으로 신경 기계 번역과 같은 다른 NLP 작업의 시퀀스보다 길며 오류 전파로 인해 더 많은 문제를 겪을 수 있음 - 예를 들어, 실험에서 DT중에 생성된 음성 시퀀스의 오른쪽 부분은 일반적으로 반복되는 단어나 누락된 단어가 있는 왼쪽 부분보다 품질이 낮음 - 결과적으로 훈련을 위해 변환된 데이터에 의존하는 DT이 영향을 받고 텍스트의 오른쪽 부분과 음성 시퀀스가 잘 훈련될 수 없음 - 따라서 TTS 및 ASR 모델은 모두 시퀀스의 오른쪽 부분, 특히 label이 있는 데이터가 부족하여 리소스가 낮거나 없는 환경에서 낮은 품질의 결과가 도출되는 경향이 있음 2) 위의 문제를 해결하기 위해 양방향 시퀀스 모델링을 활용하여 왼쪽에서 오른쪽 및 오른쪽에서 왼쪽 방향으로 음성 및 텍스트 시퀀스를 생성하는 것을 제안함 - 이러한 방식으로 기존의 DT 프로세스에서 항상 품질이 낮았던 시퀀스의 오른쪽 부분을 좋은 품질을 유지한 채로 오른쪽에서 왼쪽 방향으로 생성 가능함 - 결과적으로, 훈련을 위해 변환된 데이터에 의존하는 이중 작업은 시퀀스의 오른쪽 부분에서 개선된 품질의 혜택을 받을 것이며, 시퀀스의 왼쪽과 오른쪽 부분 사이의 생성 품질에서 더 균형을 이룰 것임 - 원래 왼쪽에서 오른쪽으로 생성된 것보다 더 높은 변환 정확도를 제공함
- 동시에 양방향 시퀀스 모델링은 양방향으로 데이터를 활용하는 데이터 증대 효과로도 작용할 수 있으며, 이는 특히 거의 비지도 학습 설정에서 쌍을 이룬 데이터가 거의 없을 때 유용하게 사용될 수 있음 - 양방향 DAE는 다음과 같이 구성할 수 있음
- 왼쪽에서 오른쪽 및 오른쪽에서 왼쪽 방향으로 손상된 음성 및 텍스트 시퀀스를 재구성하는 경우 $C(\cdot)$은 masking 연산임 - 시퀀스를 두 방향으로 모델링할 때 모델 매개 변수를 공유함 - DAE 및 DT를 기반으로 한 양방향 시퀀스 모델링은 왼쪽에서 오른쪽 및 오른쪽에서 왼쪽 세대 간에 모델을 공유함 - 즉, 시퀀스를 양방향으로 생성하는 하나의 모델을 학습할 수 있으며, 모델 매개 변수를 줄이는 것도 가능함 - 모델에게 훈련과 추론의 시작 요소로 제로 벡터를 사용하는 기존의 디코더와는 달리, 제안하는 방법은 두 개의 학습 가능한 내장 벡터를 훈련과 추론 방향을 나타내는 두 개의 시작 요소로, 하나는 왼쪽에서 오른쪽으로, 다른 하나는 오른쪽에서 왼쪽으로 사용함 - 따라서 총 4 개의 시작 임베딩을 학습함 - 2 개는 음성 생성 용이고 다른 2 개는 텍스트 생성 용임
- TTS 및 ASR의 음성 및 텍스트 시퀀스는 일반적으로 monotonic attention에 의해 alignment되므로, 예를 들어 디코더의 음성 시퀀스의 왼쪽 부분은 일반적으로 TTS의 인코더에서 텍스트 시퀀스의 왼쪽 부분에 집중될 수 있음 - 왼쪽에서 오른쪽 생성과 일치하기 위해 오른쪽에서 왼쪽 방향으로 대상 시퀀스를 생성할 때 오른쪽에서 왼쪽 방향으로 소스 시퀀스를 인코더에 공급함 - 따라서 소스 시퀀스를 역순으로 대상 시퀀스와 일치시킴
4. Proposed model details
1) 시퀀스 모델링에서 기존 RNN / CNN 보다 장점이 있기 때문에 Transformer로 선택하였음
2) 그림 a - 녹색 및 노란색 화살표는 음성 및 텍스트에 대한 DAE를 나타냄 - 빨간색 화살표는 텍스트에서 음성으로 (TTS) - 파란색 화살표는 음성에서 텍스트로 (ASR)의 DT를 나타냄 - DAE와 DT 모두 양방향 시퀀스 모델링을 포함함
3) 그림 b - Transformer를 기반으로 하는 음성 및 텍스트 인코더 및 디코더 - Transformer는 주로 교차 위치 정보를 추출하기 위한 MHA와 각 위치에서 non-linear 변환을 보장하기 위한 FFN로 구성된 self-attention 메커니즘을 사용하고, 각각에 residual 연결 및 layer norm이 이루어짐 - 디코더는 인코더의 마지막 레이어에서 hidden representation을 추출하기 위해 추가 MHA를 사용함 - 인코더와 디코더는 모두 input d_model이 256이고 FFN은 1024의 크기이며, 4 layer로 쌓았음 - TTS와 ASR은 인코더와 디코더에 대해 동일한 모델 구조를 공유하지만 모델 매개 변수가 다름 (공개 안되어있음)
4) 그림 c - 음성 및 텍스트에 대한 입력 및 출력 모듈이며, 음성 입력 모듈 (그림 c의 왼쪽 하단)은 hidden size가 256 인 Pre-Net으로 구성되며 출력 차원은 Transformer의 hidden size인 256과 같음 - 음성 출력 모듈 (그림 c의 왼쪽 상단)은 두 가지 구성 요소로 구성됨 - 하나는 출력 차원이 1 인 stop linear layer와 현재 디코딩 단계가 중지되어야 하는지 여부를 예측하는 sigmoid임 - 다른 하나는 각 단계에서 80 차원 벡터로 mel-spectrogram을 생성하기 위해 추가 Post-Net이 있는 mel linear layer임 - Post-Net은 생성된 mel-spectrogram의 품질을 개선하는 것을 목표로 하는 256의 hidden size를 갖는 5-layer 1-D Convolution 네트워크로 구성됨 - Griffin-Lim 알고리즘을 사용하여 mel-spectrogram을 audio로 변환함 - 텍스트 입력 모듈 (그림 c의 오른쪽 하단)은 phoneme 임베딩으로, phoneme ID를 임베딩으로 변환함 - 출력 모듈의 텍스트 linear layer (그림 c의 오른쪽 상단)와 phoneme 임베딩의 매개 변수를 공유함 - 텍스트 시퀀스는 모델에 입력하기 전에 먼저 텍스트-음소 변환기를 사용하여 음소 시퀀스로 변환됨
[1] Ren, Yi, et al. "Almost unsupervised text to speech and automatic speech recognition."International Conference on Machine Learning. PMLR, 2019.
- 우리가 많이 사용하는 supervised learning setting은 입력 $X$와 그에 해당하는 label $Y$가 있으며, 이를 paired dataset이라 부름. 이는 아래와 같음
$\mathcal{D}={(X_1,Y_1),...,(X_n,Y_n)}$
- 아래의 식처럼, $D$에 대해 학습된 모델은 레이블이 있는 $Y$에 주어진 ground-truth의 가능성을 최대화 함
$\sum_{(X,Y)\in\mathcal{D}}$log$P(Y|X)$ ...(2)
2) Semi-supervised setting
- $mathcal{D}$ 외에 label이 없는 오디오 데이터 세트 $\mathcal{X}$ 및 페어링되지 않은 텍스트 데이터 세트 $mathcal{Y}$ 만 포함 됨
- 먼저, 식 (2)를 최대화하여 $mathcal{D}$에서 AM 모델을 훈련함 - 둘째, $mathcal{Y}$에서 LM 교육
- 셋째, 두 모델을 결합하여 식 (1)을 적용하고, label이 지정되지 않은 각 데이터에 대한 pseudo label을 생성하고, 아래와 같이 paired pseudo label을 이룬 데이터 세트를 얻음 $\mathcal{D}={(X_i,\bar{Y_i})|X_i\in\mathcal{X}}$
- 마지막으로 새 AM은 $mathcal{D}$와 $D$의 조합에 대해 아래와 같은 목표로 훈련 할 수 있음
- Implementation으로, 먼저 labelled $\mathcal{D}$를 이용하여 randomly initialized weights로 모델 $M$학습
- 이후, 각각의 모델에 맞춰 tuning된 hyper-parameter로 $\bar{D_m}$생성
- 학습 동안, 모델 $M$중 하나에서 매 epoch마다 target으로 pseudo-label을 균일하게 샘플링함
Experiments
1. Data (LibriSpeech)
- Paired dataset: Train-clean 100
- Unpaired dataset (clean): Train-clean-360
- Unparied dataset (noisy): Train-other-500
- Realistic for self training
-> LibriSpeech는 총 14,476권의 공개 도서에서 파생되어 생성된 데이터셋임
-> LM을 위한 훈련 데이터에서 AM 훈련 셋과 관련된 모든 책 제거 (997개)
- NLTK toolkit for text normalization
--> 문장 분할 적용, 소문자로 모두 변경, ` 를 제외한 구두점 제거, 하이픈 공백으로 대체
2. Model
- 각각 10, 14 및 16 채널과 $k$ = 21이 있는 3 개 그룹의 9 개의 TDS 블록 - Soft-window 사전 교육 (attention 수렴을 위해), teacher-forcing, 20%의 dropout, 1%의 random sampling, 10%의 Label smoothing, 정규화를위한 1%의 word piece sampling - SentencePiece [7]을 사용하여 "train-clean-100"의 transcripts에서 5,000 개의 word piece을 대상 토큰으로 계산
3. Training
- Pseudo-labels 학습시 8GPUs 사용
- Learning rate가 0.05 인 200 Epoch 동안 momentum이 없는 SGD 사용
- GPU 1개를 사용할 때 Epoch 40마다 0.5 씩 decay, GPU 8개에 Epoch 80 개씩 decay 먹임 - wav2letter ++ 프레임 워크 사용 [8]
4. LM
- ConvLM [9]과 동일한 model architecture 및 학습 방법 사용하여 word piece 학습
- 모든 beam search hyper-parameter는 pseudo-label 생성 전 dev set에서 조정
Results
1. Label measure
- Ground truth와 비교하여 필터링 된 pseudo-label의 WER로 정의함 (논문 자체에서 이렇게 했다는 말임)
2. Heuristic filtering
- No EOS + n-gram필터를 $c=2, n=4$에 적용
- 이후 필터링 된 데이터 세트 위에 confidence-based filtering 추가
- Confidence score에 대한 threshold 조정 시 pseudo-label 품질 개선됨 (그림 참조)
3. Model ensembles
- 여러 모델을 결합하면 특히 노이즈가 많은 설정에서 성능 향상
- 6개 모델과 heuristic filtering을 통해 13.7%의 상대적 개선률 획득
- 두 가지 필터링 기술이 ensemble과 효과적으로 결합 됨을 보임
- Sample ensemble이 학습 시간에 동일한 utterance에 대해 서로 다른 transcript를 사용하기 때문에 모델이 noise가 포함된 pseudo-label에 지나치게 확신하는 것을 방지함
4. Comparison with Literature
- 원본 책(label)과 비교를 하였는데 이때 쓰인 measure는 WRR (WER Recovery Rate) 이며 아래와 같음
$\frac{baseline WER - semi - supervised WER}{baseline WER - oracle WER}$
- WRR를 통해 pseudo-label과 연결할 수 있는 baseline과 oracle 사이의 간격을 보임
5. Comparison with other semi-supervised learning
- Seq2seq model에서 동일한 음성으로 실험 조건 세팅
- 기존 연구 (semi-supervised)
--> Cycle TTE [10]: input과 output사이에 cycle-consistency loss 도입
--> ASR+TTS [11]: TTS 모듈을 활용하여 unpaired text에서 합성 데이터 생성
- 제안한 Self-training 방법이 기존연구 보다 약 65.1% 우수한 WER 생성
Why?
- TDS 기반 encoder
- 실제 설정에서 쉽게 얻을 수 있는 훨씬 더 큰 unpaired text corpus 활용
Conclusion
- 대규모 Unlabelled dataset을 이용한 self-training은 end-to-end 시스템의 상당한 개선을 가져옴
- 기존의 Seq2seq 모델 및 앙상블에서 발생하는 문제점에 맞게 조정된 필터링 메커니즘의 효과
- Self-training에도 효과적임을 보임
- TDS block 및 이 논문 모두 Decoding, External LM 등에 대한 사전 지식이 있어야 충분히 이해할 수 있는 레벨이었음
- 소량의 Self-training을 통해 data augmentation 효과 및 unseen data의 distribution등의 개선을 기대할 수 있을 것 같고, real scenario에 사용해봄직 함
[1] Kahn, Jacob, Ann Lee, and AwniHannun. "Self-training for end-to-end speech recognition." ICASSP 2020-2020 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2020.
[2] Kahn, Jacob, Ann Lee, and AwniHannun. "Self-training for end-to-end speech recognition." ICASSP 2020-2020 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2020.
[3] Chorowski, Jan, and Navdeep Jaitly. "Towards Better Decoding and Language Model Integration in Sequence to Sequence Models." Proc. Interspeech 2017 (2017): 523-527.
[4] Veselý, Karel, Mirko Hannemann, and LukášBurget. "Semi-supervised training of deep neural networks." 2013 IEEE Workshop on Automatic Speech Recognition and Understanding. IEEE, 2013.
[5] Mangu, Lidia, Eric Brill, and Andreas Stolcke. "Finding consensus in speech recognition: word error minimization and other applications of confusion networks." Computer Speech & Language 14.4 (2000): 373-400.
[6] Xu, Haihua, et al. "An improved consensus-like method for Minimum Bayes Risk decoding and lattice combination." 2010 IEEE International Conference on Acoustics, Speech and Signal Processing. IEEE, 2010.
[7]Kudo, Taku, and John Richardson. "SentencePiece: A simple and language independent subword tokenizer and detokenizer for Neural Text Processing." Proceedings of the 2018 Conference on Empirical Methods in Natural Language Processing: System Demonstrations. 2018.
[8] Vineel Pratap, AwniHannun, Qiantong Xu, Jeff Cai, Jacob Kahn, Gabriel Synnaeve, et al., "Wav2letter++: A fast opensource speech recognition system", International Conference on Acoustics Speech and Signal Processing (ICASSP), 2019.
[9] Dauphin, Yann N., et al. "Language modeling with gated convolutional networks." International conference on machine learning. PMLR, 2017.
[10]Takaaki Hori, Ramon Astudillo, Tomoki Hayashi, Yu Zhang, Shinji Watanabe and Jonathan Le Roux, "Cycle-consistency training for end-to-end speech recognition", International Conference on Acoustics Speech and Signal Processing (ICASSP), 2019.
[11] Murali Karthick Baskar, Shinji Watanabe, Ramon Astudillo, Takaaki Hori, LukášBurget and Jan Černockỳ, "Semi-supervised sequence-to-sequence ASR using unpaired speech and text", Interspeech, 2019.
이번에 리뷰할 논문은 Sequence-to-sequence speech recognition with time-depth separable convolutions [1] 이며, receptive field를 크게 유지하면서 모델의 매개변수 수를 극적으로 줄이는 시간 깊이 분리형 CNN block을 제안한 논문임
Overview
1. TDS (Time-depth separable)
- Fully convolutional sequence-to-sequence encoder architecture - RNN baseline에 비해 WER 우수, 계산의 병렬 특성으로 인해 효율적임을 주장 - Receptive field를 크게 유지하면서 모델의 매개 변수 수를 극적으로 줄이는 시간 깊이 분리형 CNN block 제안
2. 또한, 느리고 순차적인 기술 폐기 - Neural content attention - Location based attention [2] - Scheduled sampling [3]
3. CNN 기반의 언어 모델 - CNN 기반의 언어 모델을 효과적으로 통합할 수 있는 Beam search 추론 절차 제공 - Beam size가 매우 크더라도 정확도가 저하되지 않음
Proposed model
1. Background
1) 주어진 음성 입력 $X=[x_1,...,x_t]$, $Y=[y_1,...,y_u]$가 있을 때, Seq2seq 모델의 인코더는 $X$를 hidden representation으로 인코딩하며, 디코더는 인코더로부터 받은 hidden represetation과 디코더의 입력을 각각의 출력 토큰으로 디코딩하여 문장으로 생성함. 이를 아래에 자세히 설명함
2) 인코더는 아래의 식으로 볼 수 있음
$(K, V)$ = encode$(X)$
- 여기에서 $K=[k_1,...,k_t]$ 는 key이며, $V=[v_1,...,v_t]$는 value임
3) 디코더는 아래처럼 주어질 수 있는데,
$Q_u = g(y_{u-1},Q_{u-1})$
$S_u = $attend$(Q_u,K,V)$
$P(y_u|X,y_<u)=h(S_u,Q_u)$
- 여기에서 $g(\cdot)$은 이전 token과 query vector $Q_{u-1}$을 인코딩하여 다음 query vector를 처리하는 RNN임
-> Beam의 모든 후보에 대해 업데이트 된 probability 집합을 일괄 계산하므로, 각 단계에서 한 번의 forward만 필요
Experiments
1. Data
- LibriSpeech 960h
2. Encoder
- Two 10-channel, three 14-channel 그리고 six 18-channel TDS blocks (11 blocks)
- Using 1D convolutions to sub-sample over time
-> One as the first layer
-> One in between each group of TDS blocks
- Kernel sizes: all 21 x 1
- Final linear layer produces the 1024-dimensional encoder output
3. Decoder
- One-layer GRU with 512 hidden units
4. Initialization
- uniform distribution $\mathcal{U}(-\sqrt\frac{4}{f_{in}},\sqrt\frac{4}{f_{in}})$으로 초기화 되었으며, $f_{in}$은 각 유닛에 대한 fan-in임
5. Speech preprocessing
- 80-dimensional mel-scale filter banks computed every 10ms with a 25ms window
6. Token preprocessing
- 10k word pieces computed from the Sentence Piece toolkit [8]
7. Optimizer
- Synchronous SGD with a learning rate of 0.05, decayed by a factor of 0.5 every 40 epochs
- Clip the gradient norm to 15
8. Pre-train
- 해당 모델은 soft window와 $\sigma=4$로 3에폭 동안 pre-train 됨
9. Hyperparameters
- Dropout as 20%, label smoothing as 5%, random sampling as 1%, word piece sampling as 1%
10. Two word piece LMs on the 800M-word text-only dataset
- 두 개의 word piece 언어 모델을 사용하였음
- 첫 번째는 4-gram trained with KenLM [9]
- 두 번째는 convolutional LM (ConvLM) [10]
11. Beam setting
- Beam size of 80
- $t_{max}=30$
- EOS penalty $\gamma=1.5, \eta=10$
- LM 가중치 및 토큰 삽입 조건은 dev set 및 LM 조합과 교차 검증으로 진행
- Wav2letter++ [11] 를 사용하여 training 및 evaluation 평가
Results
1. TDS 모델은 외부 LM을 사용시 더 많은 이점을 얻음
- Betterlossonthecorrecttranscription
- More effective beam search
2. Model variants
- Varying the number of channels in TDS blocks
-> TDS Block의 채널 개수 변경
-> 기존: 10, 14, 18, params=36.5
--> (10, 12, 14), params=24.4
--> (10, 10, 10), params=14.9
- Fix params, NumberofTDS blocks
-> N=9, k=27, c=(14, 16, 20), 5.18%
-> N=12, k=19, c=(10, 16, 16), 5.10%
- $P_{wp}$와 $P_{rs}$가 낮을수록 성능이 좋았음
- Soft window pre-training
--> Soft window 기법은 명확히 학습 초기에 모델 수렴에 도움이 되었음
- Receptive fields
--> 큰 사이즈의 receptive field가 없으면, encoder의 키 output에 decoder의 query를 명확하게 할 수 없음을 주장
- Number of beam size
--> Beamsize가 80까지 이득을 볼 수 있음
Conclusion
1. Fully convolutional encoder
- 제안하는 Fully convolutional encoder와 simple decoder가 강력한 RNN baseline의 도달함과 동시에 더 우수하고 효율적인 결과를 보임
2. TDS block
- CNN-based encode의 성공 핵심은 모델이 큰 사이즈의 receptive field를 유지할 수 있는 TDS에 의해 가능함
3. + ConvLM
- ConvolutionalLM을 안정적이고 확장 가능한 beam search 절차와 통합 하는 방법을 보임
[1] Hannun, Awni, et al. "Sequence-to-Sequence Speech Recognition with Time-Depth Separable Convolutions." Proc. Interspeech 2019 (2019): 3785-3789.
[2] Chorowski, Jan, et al. "Attention-based models for speech recognition." Proceedings of the 28th International Conference on Neural Information Processing Systems-Volume 1. 2015.
[3] Bengio, Samy, et al. "Scheduled sampling for sequence prediction with recurrent Neural networks." Proceedings of the 28th International Conference on Neural Information Processing Systems-Volume 1. 2015.
[4] Luong, Minh-Thang, Hieu Pham, and Christopher D. Manning. "Effective Approaches to Attention-based Neural Machine Translation." Proceedings of the 2015 Conference on Empirical Methods in Natural Language Processing. 2015.
[5] Wang, Xinyi, et al. "SwitchOut: an Efficient Data Augmentation Algorithm for Neural Machine Translation." Proceedings of the 2018 Conference on Empirical Methods in Natural Language Processing. 2018.
[6] Chorowski, Jan, and Navdeep Jaitly. "Towards Better Decoding and Language Model Integration in Sequence to Sequence Models." Proc. Interspeech 2017 (2017): 523-527.
[7] Collobert, Ronan, Christian Puhrsch, and Gabriel Synnaeve. "Wav2letter: an end-to-end convnet-based speech recognition system." arXiv preprint arXiv:1609.03193 (2016).
[8] Kudo, Taku, and John Richardson. "SentencePiece: A simple and language independent subword tokenizer and detokenizer for Neural Text Processing." Proceedings of the 2018 Conference on Empirical Methods in Natural Language Processing: System Demonstrations. 2018.
[9] Heafield, Kenneth. "KenLM: Faster and smaller language model queries." Proceedings of the sixth workshop on statistical machine translation. 2011.
[10] Dauphin, Yann N., et al. "Language modeling with gated convolutional networks." International conference on machine learning. PMLR, 2017.
[11] Pratap, Vineel, et al. "Wav2letter++: A fast open-source speech recognition system." ICASSP 2019-2019 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2019.
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
from torch.autograd import Variable
import os
import matplotlib.pyplot as plt
import numpy as np
torch.__version__
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
torch.manual_seed(2891)
num_gpu = 1
if torch.cuda.device_count() > 1:
num_gpu = torch.cuda.device_count()
print("Let's use", num_gpu, "GPUs!")
print('our device', device)
'''
Let's use 1 GPUs!
our device cuda
'''
def count_parameters(model):
return sum(p.numel() for p in model.parameters() if p.requires_grad)
model_hp = count_parameters(model)
print('model"s hyper parameters', model_hp)
# model"s hyper parameters 374026
Dataset load, train, test loader 선언
train_loader = torch.utils.data.DataLoader(datasets.MNIST('data', train=True, download=True, transform=transforms.ToTensor()),batch_size=batch_size, shuffle=True)
print(len(train_loader)) # 600
test_loader = torch.utils.data.DataLoader(datasets.MNIST('data', train=False, transform=transforms.ToTensor()),batch_size=1000)
print(len(test_loader)) # 10
'''
Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz to data/MNIST/raw/train-images-idx3-ubyte.gz
9913344/? [04:53<00:00, 33768.69it/s]
Extracting data/MNIST/raw/train-images-idx3-ubyte.gz to data/MNIST/raw
Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz to data/MNIST/raw/train-labels-idx1-ubyte.gz
29696/? [00:00<00:00, 433940.88it/s]
Extracting data/MNIST/raw/train-labels-idx1-ubyte.gz to data/MNIST/raw
Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz to data/MNIST/raw/t10k-images-idx3-ubyte.gz
1649664/? [00:51<00:00, 32232.92it/s]
Extracting data/MNIST/raw/t10k-images-idx3-ubyte.gz to data/MNIST/raw
Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz to data/MNIST/raw/t10k-labels-idx1-ubyte.gz
5120/? [00:00<00:00, 108088.65it/s]
Extracting data/MNIST/raw/t10k-labels-idx1-ubyte.gz to data/MNIST/raw
Processing...
Done!
600
10
/usr/local/lib/python3.7/dist-packages/torchvision/datasets/mnist.py:502: UserWarning: The given NumPy array is not writeable, and PyTorch does not support non-writeable tensors. This means you can write to the underlying (supposedly non-writeable) NumPy array using the tensor. You may want to copy the array to protect its data or make it writeable before converting it to a tensor. This type of warning will be suppressed for the rest of this program. (Triggered internally at /pytorch/torch/csrc/utils/tensor_numpy.cpp:143.)
return torch.from_numpy(parsed.astype(m[2], copy=False)).view(*s)
'''
Loss, optimizer 선언
이전에는 F.nll_loss로 하였는데, 이번에는 CrossEntropy loss를 선언하여 진행함
이번에는 이전 post와 같은 MNIST dataset을 활용하여, CNN으로 성능 뽑는것을 진행해본다.
CNN은 Fully-connected layer와 달리 flatten을 해줄 필요가 없어서 parameter가 비교적 적게 들고, 연산이 빠른 장점이 있으며, receptive field를 통해 local feature를 뽑는 것에 강인한 특징이 있음
Library importing 및 device 설정
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
from torch.autograd import Variable
import os
import matplotlib.pyplot as plt
import numpy as np
torch.__version__
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
torch.manual_seed(2891)
num_gpu = 1
if torch.cuda.device_count() > 1:
num_gpu = torch.cuda.device_count()
print("Let's use", num_gpu, "GPUs!")
print('our device', device)
'''
Let's use 1 GPUs!
our device cuda
'''
2-layer CNN 네트워크 설계 (add here 부분에 batchnormalization, 더 깊게 쌓는 것들을 연습해보세요)
class CNN(nn.Module):
def __init__(self, num_class, drop_prob):
super(CNN, self).__init__()
# input is 28x28
# padding=2 for same padding
self.conv1 = nn.Conv2d(1, 32, 5, padding=2) #input_channel, output_channel, filter_size, padding_size, (kernel=omit)
# feature map size is 14*14 by pooling
# padding=2 for same padding
self.conv2 = nn.Conv2d(32, 64, 5, padding=2)
# feature map size is 7*7 by pooling
'''
add here.. make more deep...
batchnormalization ++
'''
self.dropout = nn.Dropout(p=drop_prob)
self.fc1 = nn.Linear(64*7*7, 1024)
self.reduce_layer = nn.Linear(1024, num_class)
self.log_softmax = nn.LogSoftmax(dim=1)
def forward(self, x):
x = F.max_pool2d(F.relu(self.conv1(x)), 2) # -> (B, 14, 14, 32)
x = F.max_pool2d(F.relu(self.conv2(x)), 2)
'''
add here.. make more deep...
and use dropout
'''
x = x.view(-1, 64*7*7) # reshape Variable for using Linear (because linear only permit 1D. So we call this task as "flatten")
x = F.relu(self.fc1(x))
output = self.reduce_layer(x)
return self.log_softmax(output)
#model shape
for p in model.parameters():
print(p.size())
'''
torch.Size([32, 1, 5, 5])
torch.Size([32])
torch.Size([64, 32, 5, 5])
torch.Size([64])
torch.Size([1024, 3136])
torch.Size([1024])
torch.Size([10, 1024])
torch.Size([10])
'''
def count_parameters(model):
return sum(p.numel() for p in model.parameters() if p.requires_grad)
model_hp = count_parameters(model)
print('model"s hyper parameters', model_hp)
# model"s hyper parameters 3274634
Data setup 및 train, test loader 설정
batch_size = 64
train_loader = torch.utils.data.DataLoader(datasets.MNIST('data', train=True, download=True, transform=transforms.ToTensor()),batch_size=batch_size, shuffle=True)
print(len(train_loader)) # 938, 64 * 938 = 60032
test_loader = torch.utils.data.DataLoader(datasets.MNIST('data', train=False, transform=transforms.ToTensor()),batch_size=1000)
print(len(test_loader)) # 10, (10 * 1000 = 10000)
'''
Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz to data/MNIST/raw/train-images-idx3-ubyte.gz
9913344/? [04:51<00:00, 34050.71it/s]
Extracting data/MNIST/raw/train-images-idx3-ubyte.gz to data/MNIST/raw
Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz to data/MNIST/raw/train-labels-idx1-ubyte.gz
29696/? [00:01<00:00, 26930.77it/s]
Extracting data/MNIST/raw/train-labels-idx1-ubyte.gz to data/MNIST/raw
Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz to data/MNIST/raw/t10k-images-idx3-ubyte.gz
Failed to download (trying next):
HTTP Error 503: Service Unavailable
Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-images-idx3-ubyte.gz
Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-images-idx3-ubyte.gz to data/MNIST/raw/t10k-images-idx3-ubyte.gz
1649664/? [00:00<00:00, 3989386.71it/s]
Extracting data/MNIST/raw/t10k-images-idx3-ubyte.gz to data/MNIST/raw
Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz to data/MNIST/raw/t10k-labels-idx1-ubyte.gz
Failed to download (trying next):
HTTP Error 503: Service Unavailable
Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-labels-idx1-ubyte.gz
Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-labels-idx1-ubyte.gz to data/MNIST/raw/t10k-labels-idx1-ubyte.gz
5120/? [00:00<00:00, 139107.35it/s]
Extracting data/MNIST/raw/t10k-labels-idx1-ubyte.gz to data/MNIST/raw
Processing...
Done!
938
10
/usr/local/lib/python3.7/dist-packages/torchvision/datasets/mnist.py:502: UserWarning: The given NumPy array is not writeable, and PyTorch does not support non-writeable tensors. This means you can write to the underlying (supposedly non-writeable) NumPy array using the tensor. You may want to copy the array to protect its data or make it writeable before converting it to a tensor. This type of warning will be suppressed for the rest of this program. (Triggered internally at /pytorch/torch/csrc/utils/tensor_numpy.cpp:143.)
return torch.from_numpy(parsed.astype(m[2], copy=False)).view(*s)
'''
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
from torch.autograd import Variable
import os
import matplotlib.pyplot as plt
import numpy as np
또한 아래의 코드를 통해 현재의 pytorch 버전에 대해 확인함
torch.__version__
이후 연산할 장치에 대해 선언해야 함
아래와 같이 device를 gpu로 설정함
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
torch.manual_seed(2891)
num_gpu = 1
if torch.cuda.device_count() > 1:
num_gpu = torch.cuda.device_count()
print("Let's use", num_gpu, "GPUs!") # 1
print('device', device) # cuda
이후 간단한 MLP (Multi-Layer Perceptron) 모델을 구현함
입력은 MNIST dataset을 사용함
MNIST dataset의 각각의 요소는 (28, 28) 의 shape을 갖고 있기 때문에,
MNIST의 class 개수는 10개 이므로, 첫 번째 인자에 10을 넣었고, dropout은 30%확률로 진행
작성한 모델의 매 layer 마다의 shape은 아래를 통해서 확인할 수 있고,
#model shape
for p in model.parameters():
print(p.size())
'''
torch.Size([512, 784])
torch.Size([512])
torch.Size([256, 512])
torch.Size([256])
torch.Size([10, 256])
torch.Size([10])
torch.Size([10, 10])
torch.Size([10])
'''
총 hyperparameter는 아래를 통해 확인 가능함
def count_parameters(model):
return sum(p.numel() for p in model.parameters() if p.requires_grad)
model_hp = count_parameters(model)
print('model"s hyper parameters', model_hp)
'''
model"s hyper parameters 535928
'''
이제 모델 선언은 끝났고, data를 loading 해야 함
아래의 코드를 통해 MNIST dataset을 다운받고, train 및 test로 분할함
batch_size = 128
train_loader = torch.utils.data.DataLoader(datasets.MNIST('data', train=True, download=True, transform=transforms.ToTensor()),batch_size=batch_size, shuffle=True)
print(len(train_loader)) # 118, 512 * 118 = 60000
test_loader = torch.utils.data.DataLoader(datasets.MNIST('data', train=False, transform=transforms.ToTensor()),batch_size=1000)
print(len(test_loader)) # 10, 10 * 1000 = 10000
'''
Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz to data/MNIST/raw/train-images-idx3-ubyte.gz
9913344/? [04:54<00:00, 33670.03it/s]
Extracting data/MNIST/raw/train-images-idx3-ubyte.gz to data/MNIST/raw
Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz to data/MNIST/raw/train-labels-idx1-ubyte.gz
29696/? [00:01<00:00, 26891.25it/s]
Extracting data/MNIST/raw/train-labels-idx1-ubyte.gz to data/MNIST/raw
Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz to data/MNIST/raw/t10k-images-idx3-ubyte.gz
Failed to download (trying next):
HTTP Error 503: Service Unavailable
Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-images-idx3-ubyte.gz
Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-images-idx3-ubyte.gz to data/MNIST/raw/t10k-images-idx3-ubyte.gz
1649664/? [00:00<00:00, 3911534.90it/s]
Extracting data/MNIST/raw/t10k-images-idx3-ubyte.gz to data/MNIST/raw
Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz to data/MNIST/raw/t10k-labels-idx1-ubyte.gz
5120/? [00:00<00:00, 159181.34it/s]
Extracting data/MNIST/raw/t10k-labels-idx1-ubyte.gz to data/MNIST/raw
Processing...
Done!
469
10
/usr/local/lib/python3.7/dist-packages/torchvision/datasets/mnist.py:502: UserWarning: The given NumPy array is not writeable, and PyTorch does not support non-writeable tensors. This means you can write to the underlying (supposedly non-writeable) NumPy array using the tensor. You may want to copy the array to protect its data or make it writeable before converting it to a tensor. This type of warning will be suppressed for the rest of this program. (Triggered internally at /pytorch/torch/csrc/utils/tensor_numpy.cpp:143.)
return torch.from_numpy(parsed.astype(m[2], copy=False)).view(*s)
'''
Optimizer 선언은 아래와 같이 진행하며, 가장 많이 사용되는 Adam을 learning rate 1e-4로 사용