Ear-VoM_Integrate System to Combat DeepVoice-based Voice Phishing Crimes
2024년 2학기 18기 이화여자대학교 미래혁신센터의 도전학기제 프로그램에 선발되어 딥보이스 보이스피싱 범죄 근절을 위한 애플리케이션 탑재용 인공지능 모델 개발이라는 주제로 개인 프로젝트를 진행하였다.
프로젝트의 주요 성취(실적)는 다음과 같다.
- 1️⃣ First Korean SV2TTS Implementation: Github
- 2️⃣ Proposal & Implementation of Deepvoice Detection w/ Federated Learning: Github
- Using Deep-Fingerprinting(DF) Model
- Convert TensorFlow Code to PyTorch (DF)
- Apply unstrctured pruning
- 3️⃣ Proposal of Ear-VoM system: Github
- Research paper submission
- Experiment on the importance of considering emotion in the construction of a deep voice discrimination dataset (d-vector)
- Experiment on the discrimination of deep voices generated by different models (x-vector)
먼저 3️⃣ Ear-VoM system에 대해 소개하고, 뒤이어 1️⃣, 2️⃣에 대해 서술할 예정이다. 1️⃣, 2️⃣는 3️⃣의 구성 요소로 들어갈 수 있다.
3️⃣ Ear-VoM
작성한 Ear-VoM paper는 딥보이스 보이스피싱을 막기 위한 정책을 제안하는 논문이다. 따라서 기술적인 내용도 들어가지만 보이스피싱 실태, 현재 민간과 공공 기관의 노력, 관련 선행 연구 분석이 앞부분을 차지한다. 그리고 기존 정책들의 단점을 보완하고 인공지능 기술에 기반한 좀더 현실적인 정책이 뒷 부분에 나온다. 논문의 분량이 상당하기 때문에, 블로그 글에서는 핵심만 간단하게만 짚고 넘어가려 한다.
Overview
지인 사칭형 및 협박형 보이스피싱은 국민의 정서적 및 경제적 행복을 심각하게 저하한다. 최근 보이스피싱 피해자들은 고액의 피해를 보는 경우가 많으며, 단 한 통의 의심 전화가 개인의 삶을 송두리째 변화시킬 수 있다.
Ear-VoM은 딥보이스 보이스피싱 근절을 위해 고안된 예방, 대처·신고, 수사의 세 가지 단계로 구성된 통합 시스템이다. 기존 연구들과 달리 감정을 고려하여 더욱 범죄 상황에 특화된 판별 모델 데이터셋 구축 방법을 포함한다.
각 단계를 간략하게 소개하면 다음과 같다.
- 1️⃣ 예방
- TTS로 생성된 가족 및 지인의 딥보이스를 직접 들어본다.
- 이를 통해 딥보이스의 정교성을 인식한다.
- 2️⃣ 대처·신고
- 연합학습으로 꾸준히 업데이트되는 딥보이스 판별 모델
- 애플리케이션을 통한 국민-경찰과의 긴밀한 소통
- 3️⃣ 수사
- 케이-봄(K-VoM): 기존 수사용 한국형 보이스피싱 음성분석 모델
- MDVF(악의적 딥보이스 핑거프린팅): given 딥보이스의 출처 구분
- ➕ 미리-봄(Miri-VoM) : 자동 딥보이스 보이스피싱 시나리오를 구축하고 오디오 적대적 공격을 활용한 대응책
케이-봄 모델이 수사 도구로써 국민을 지킨다면 이어-봄 시스템은 국민의 동행자로서 인공지능·경찰과 함께 범죄시도 전·중·후 시점에서 국민을 지키도록 고안되었다. ‘이어-봄’의 ‘이어(Ear)’는 딥보이스 의심 전화를 판별해 낼 수 있는 국민의 ’귀‘라 는 뜻이다.
Experiment
Ear-VoM에서의 주장을 뒷받침하기 위한 2개의 simple한 실험을 진행하였다. 3️⃣의 주 포커스는 정책 제안이기 때문에 3️⃣에서 진행한 실험은 1️⃣, 2️⃣보다 비교적 간단하다.
- Experiment1: Importance of considering emotion in the construction of a deep voice discrimination dataset (d-vector)
- Experiment2: Discrimination of deep voices generated by different models (x-vector)
이렇게 2개의 실험을 진행했지만 이 글에서는 따로 설명하지 않는다.
1️⃣Korean SV2TTS Implementation
TTS 논문 중 재미있게 읽었던 SV2TTS를 선택하였다. SV2TTS는 Zero-shot inference가 가능하여 Ear-VoM 예방 단계의 생성 모델로 적합하다.
24.12.06 현재 Korean SV2TTS로 검색한 결과 완성된 깃허브 repository는 없다.
SV2TTS는 아래 세 가지 요소로 이루어져 있다. 각 요소는 독립적으로 훈련된다. 이전 STEP의 결과를 이용하여 다음 STEP이 진행된다.
- STEP1: speaker encoder NW
- task: speaker verification
- STEP2: seq2seq synthesis NW
- based on Tacotron2
- speaker embedding → mel-spectrogram
- STEP3: auto-regressive vocoder NW
- based on WaveNet
- mel-spectrogram → time-domain waveform
STEP1: Speech Encoder
Brief Explanation
- Input: log mel-spectrogram (from raw speech data w/ arbitrary length)
- Output: speaker embedding w/ fixed dimension
- Action: Learn speaker embedding via speaker verification task
- d-vector 사용
- 같은 화자의 임베딩은 가깝게, 서로 다른 화자의 임베딩은 서로 멀게 (cosine similarity)
Dataset
- Dataset: AIHub 화자 인식용 음성 데이터
- Preprocessing
- total 98GB
- 전체 데이터셋 중
호출어
타입은 제외하였다. - sample의 개수가 8개 미만인 speaker는 제외하였다.
- 따라서 총 2,535명의 speaker 데이터를 전처리하였다.
1
2
3
4
5
6
7
8
9
10
11
12
$ encoder_preprocess.py
Arguments:
datasets_root: /GENERATION
out_dir: /GENERATION/SV2TTS/encoder
datasets: ['enc003']
skip_existing: False
Preprocessing enc003
enc003_spkr: Before filtering, there are 2607 speakers.
enc003_spkr: Filter out speakers under 8 samples.
enc003_spkr: Preprocessing data for 2535 speakers.
Done preprocessing enc003_spkr.
Network structure
- Stack of 3 LSTM layers (768 cells per layer), followed by a projection to 256 dimensions after each layer.
- 최종 embedding: 최상위 레이어에서 마지막 frame의 출력을 L2-normalization하여 생성
1
2
3
4
5
6
7
8
9
# Pass the input through the LSTM layers and retrieve all outputs, the final hidden state
# and the final cell state.
out, (hidden, cell) = self.lstm(utterances, hidden_init)
# We take only the hidden state of the last layer
embeds_raw = self.relu(self.linear(hidden[-1]))
# L2-normalize it
embeds = embeds_raw / (torch.norm(embeds_raw, dim=1, keepdim=True) + 1e-5)
Training
CorentinJ/Real-Time-Voice-Cloning 에서의 English weight으로 initialize하였다. 한국어와 언어적인 특성은 다르더라도 성별이나 pitch 등 여러 다양한 요소는 공통된다고 판단했기 때문이다.
사용한 hyper-parameter는 다음과 같다.
- Model parameters
- model_hidden_size = 256
- model_embedding_size = 256
- model_num_layers = 3
- Training parameters
- learning_rate_init = 1e-4
- speakers_per_batch = 64
- utterances_per_speaker = 10
따로 학습 종료 조건은 없다. 사용자가 임의로 끊어야 한다.
Result
Loss & EER
loss가 정상적으로 계속 감소하다가 1.5656M step 전후로 수렴하는 것을 확인할 수 있다.
EER은 Loss보다 좀더 빨리 수렴한다. 1.5646M step 전후로 수렴한다.
STEP 2️⃣의 학습을 위해 1.5646M과 1.5656M step의 중간인 1.5650M step을 선택하였다.
Umap
랜덤으로 선택된 9명의 화자의 embedding(d-vector)를 UMAP을 이용하여 차원축소한 결과를 시각화한 것이다. 아래 그래프는 Encoder 학습 초기의 모습이다. 즉, English weight에서 크게 바뀌지 않은 모습이다. 서로 다른 화자의 임베딩이 뚜렷하게 구분되지 않는 것을 알 수 있다. 크게 두 가지 cluster로 나뉘는데 성별이 그 기준일 거라고 예상한다.
다음 그래프는 Synthesizer에 넣어주기로 선택된 1.565M step에서의 UMAP 결과이다. 같은 화자의 sample은 가까이, 서로 다른 화자의 sample끼리는 멀리 떨어져 있는 것을 확인할 수 있다. 즉, Encoder가 성공적으로 학습되었음을 알 수 있다.
Visdom
Visdom은 rich, live visualization을 위한 tool이다. VS Code SSH remote 연결 상태에서 이 tool을 처음 사용해보아서 처음에 많이 헤맸다. Visdom server를 선언할 때 port # 을 따로 넘겨주지 않아서 에러가 발생한 것이였다. 최종적으로 완성한 visdom server 선언 코드는 아래와 같다.
1
2
# visdom_server_port: 8097
self.vis = visdom.Visdom(port=self.port, env=self.env_name, raise_exceptions=True)
한 screen 에서 아래 명령어로 visdom server를 실행하고,
1
python -m visdom.server
encoder를 training하는 코드를 실행하면 된다.
학습을 약 5일 동안 진행하였을 때 visdom 창의 모습은 위 사진과 같다.
STEP2: Synthesizer
한국어로 구현하기가 가장 어려웠던 부분이었다. 따라서 한국어 전처리와 한국어 TTS에 대해 공부하고 진행하였다.
참고) STEP1의 Encoder는 Synthesizer의 Encoder와 다르며, TTS의 필수 요소는 아니다.
Brief Explanation
- Input: grapheme or phoneme sequence
- Output: log-mel spectrogram
- Action: target speaker에 대한 Text-to-spectrogram
Dataset
- Dataset: AIHub 다화자 음성합성 데이터
- Random으로 ZIP 파일 선택 후 다운로드
- Total Raw data size(791 speaker 기준): 704GB
- Preprocessing
korean_dataset.py
- Speaker별로 폴더 정리
- Extract Korean transcript
korean_normalize.py
- preprocessing
- normalizing
- 총 791 speaker 중 202명의 데이터만 사용
- 총 633517 samples 사용
Convert to Korean
한국어로 바꾸는 작업은 아래 순서로 구성되어 있다.
korean_dataset.py
- speaker 별 폴더 구조로 정리한다.
- raw label file에서 translabel을 추출하여
.txt
파일로 저장한다.
korean_normalize.py
- 문자열 앞뒤로 공백을 제거한다(strip).
- ⺀-⺙⺛-⻳⼀-⿕々〇 와 같은 character를 제거한다.
- 한국어 dictionary를 이용하여 normalize
- 영어 normalize (uppercase)
- 인용 문자 normalize
- 숫자 normalize
가장 흥미로웠던 것은 한글의 초성과 종성이 다른 character로 처리된다는 것이다.
Preprocessing
한국어 label을 완성하고 Synthesizer에 넣기 전, 추가적인 preprocessing과 학습된 encoder 가중치를 이용해 embedding을 추출해야 했었다. 생각보다 이 단계들이 시간이 많이 소요되어 놀랐다. 추가적인 preprocessing 단계는 아래 사진처럼 100시간 이상 소요되어, 전체 791 speaker 중에 202 speaker만 사용하게 되었다.
Network structure
위 그림은 STEP2, 3의 base가 되는 Tacotron2의 구조도이다. 그림에서 Task1은 STEP2, Task2는 STEP3이다.
Training
hyper parameter는 hyper parameter 수가 encoder에 비해 매우 많기 때문에 synthesizer/hparams.py
를 참고하면 된다.
Epoch 7로 설정해두고, log를 보면서 loss의 변화를 관찰하였다. log는 아래와 같이 기록된다.
1
2
3
4
5
6
{| Epoch: 1/7 (6495/52794) | Loss: 0.5121 | 1.4 steps/s | Step: 326k | }
{| Epoch: 1/7 (6496/52794) | Loss: 0.5117 | 1.4 steps/s | Step: 326k | }
{| Epoch: 1/7 (6497/52794) | Loss: 0.5113 | 1.4 steps/s | Step: 326k | }
{| Epoch: 1/7 (6498/52794) | Loss: 0.5109 | 1.4 steps/s | Step: 326k | }
{| Epoch: 1/7 (6499/52794) | Loss: 0.5097 | 1.4 steps/s | Step: 326k | }
{| Epoch: 1/7 (6500/52794) | Loss: 0.5105 | 1.4 steps/s | Step: 326k | }Input at step 326500: ?~___
Result
Vocoder 학습에 사용할 Synthesizer 가중치의 step을 정할 때 loss가 감소하다가 증가하는 상황을 고려하였다. 위 이미지들은은 각각 학습 초기인 1000 step과, 채택된 61500 step 때, 하나의 sample을 임의로 고 른 후 정답과 Synthesizer이 생성해 낸 Mel-spectrogram의 모습이다. 왼쪽은 아직 학습이 덜 되어 Mel-spectrogram이 세분화되지 않고 뭉뚱그려져 있다. 반면 오른쪽은 정답 Mel-spectrogram과 거의 흡사하다.
STEP3: Vocoder
Brief Explanation
- Input: log-mel spectrogram
- Output: time-domain waveform
- Action: mel-spectrogram을 waveform으로 변환한다.
- Dataset: STEP2의 결과 사용
Training
Synthesizer와 마찬가지로 hyper parameter는 hyper parameter 수가 encoder에 비해 매우 많기 때문에 vocoder/hparams.py
를 참고하면 된다.
vocoder training의 log 기록 중 일부는 아래와 같다.
1
2
3
4
5
6
7
8
| Generating: 5/5
{| ████████████████ 43500/44000 | Batch Size: 5 | Gen Rate: 1.4kHz | }
{| Epoch: 14 (1/6336) | Loss: 3.2885 | 0.4 steps/s | Step: 1241k | }
{| Epoch: 14 (2/6336) | Loss: 3.2606 | 0.7 steps/s | Step: 1241k | }
{| Epoch: 14 (3/6336) | Loss: 3.2942 | 0.8 steps/s | Step: 1241k | }
{| Epoch: 14 (4/6336) | Loss: 3.2930 | 0.9 steps/s | Step: 1241k | }
{| Epoch: 14 (5/6336) | Loss: 3.2851 | 1.0 steps/s | Step: 1241k | }
Demo result analysis
완성된 SV2TTS에 자신의 목소리를 참조 음성으로 넣어, 자신의 목소리로 입력한 텍스트를 읽는 음성을 생성하는 데모 영상을 녹화하였다. 출력 화면 중 진한 분홍색 글씨가 자막 역할을 한다. 이화여자대학교의 교육 목적을 직접 읽어 녹음했다. 길이는 14초 남짓 이다. ‘강아지 고양이.’, ‘오늘은 수요일입니다.’, ‘도와주세요.’의 세 개의 텍스트를 읽는 음성 파일을 생성하였다. 합성된 음성을 들어보면, 참조 음성의 음색(Encoder)을 매우 잘 반영한다는 걸 알 수 있다. 합성 품질도 나쁘지 않다. 다만 감정이나 발화 속도 등을 조절할 수 없어, 사람만큼 자연스럽지 않다. 하지만 ExpressiveTTS가 아닌 일반 TTS인 것을 고려하면 꽤 괜찮은 결과를 내었다. 데모 영상은 따로 공개하지 않는다.
Reference
- baseline: CorentinJ/Real-Time-Voice-Cloning
- baseline: esoyeon/KoreanTTS
- hccho2/Tacotron2-Wavenet-Korean-TTS
2️⃣ Proposal & Implementation of Deepvoice Detection w/ Federated Learning
Project Structure
1
2
3
4
5
6
7
8
9
10
11
DETECT
├── preprocess # preprocess raw data
├── non_fl # traditional classification with DF
├── fl # federated learning with flwr
│ ├── dvd # DeepVoice Detection
│ │ ├── __init__.py
│ │ ├── client_app.py # Define ClientApp
│ │ ├── server_app.py # Define ServerApp
│ | └── task.py # Define model, training and data loading
│ └── pyproject.toml # Project metadata like dependencies and configs
└── README.md
Dataset
- ASVspoof 2019
- homepage: https://www.asvspoof.org/index2019.html
- LA (Logical Access): 공격자가 시스템이나 네트워크를 통해 음성 합성 또는 변조를 시도하는 공격 방식
- PA (Physical Access): 공격자가 물리적으로 장치에 접근하여 음성을 변조하는 공격 방식
- 딥보이스 보이스피싱은 LA에 더 가깝다고 판단하여 LA 데이터셋만 사용
- Fake-or-Real (FoR)
- kaggle: https://www.kaggle.com/datasets/mohammedabdeldayem/the-fake-or-real-dataset/data
총 257,865개의 audio sample을 사용하였다. 그중 fake sample은 164,977개, real sample은 92,888개이다.
Data Preprocessing
Dataset의 version을 2가지 만들었다. 첫 번째는 librosa로 load한 raw dataset이다. 최대 길이인 80,000으로 padding하였다. 두 번째는 Pretrained Wav2Vec을 feature extractor로 사용한 것이다. 이 경우 역시 최대 길이인 80,000으로 padding하였다.
1
2
3
4
5
$ python preprocess.py
[INFO] max_length: 80000
[INFO] Audio loaded (257865, 80000)
[INFO] Audio padded with 80000
[INFO] Feature extracted (257865, 80000)
DF
Deepvoice detection task에서는 주로 transformer, Wav2Vec, MLP가 쓰인다. 그중에서 Deepvoice detection model은 1d CNN 기반인 Deep-Fingerprinting(DF)을 선택하였다. 이 모델을 선택한 이유는 크게 두 가지이다. 첫 번째는 DF가 Website Fingerprinting에서 매우 강력하기 때문에 이진 분류 역시 잘 할 것이라 판단했기 때문이다. 두 번째 이유는 기존에 자주 사용되는 모델보다 DF가 더 deep하기 때문에 경량화를 진행할 수 있기 때문이다. 학습을 위해 경량화를 적용해보고 싶었다. DF 공식 레퍼지토리와 [NetCLR] 코드(https://github.com/SPIN-UMass/Realistic-Website-Fingerprinting-By-Augmenting-Network-Traces/blob/main/artifacts/src/NetCLR/pre-training.ipynb)를 참고하였다.
DF의 구조는 위 그림과 같다. DF의 official implementation은 Tensorflow 기반이다. FL을 Pytorch 기반으로 진행할 것이기 때문에 통일성을 위해 DF를 Pytorch로 바꿔주었다.
Flower Framework
연합학습 framework인 Flower 를 선택하였다. FL Framework를 처음 다뤄보는 것이기 때문에 Flower에서 제공하는 Tutorial을 따라 하며 공부하였다.
다만 어려웠던 점은 Flower api에 대한 resource가 official하게나, unofficial하게나(unofficial github, stackoverflow 등) 거의 없다는 것이었다. 첫 번째 난관은 Custom dataset 사용이었다. 2d numpy array를 사용하려 하는데, 관련해서 딱 하나 찾은 페이지에서는 1d numpy array를, 이미 deprecated된 method로 설명하고 있었다. 다행히 Flower official page와 연결된 huggingface의 dataset load 방식을 이용하여 해결하였다. raw feature와 w2v feature 모두 실험하였다.
Experiment
실험하는 Federated Learning 방식은 논문을 읽었던 FedAvg으로, FL의 근간이 되는 방식이다.
Non-FL Setting
아래 2가지 요소를 다르게 하며 실험하였다.
- Raw 또는 W2V embedding
- Input dimension of DF: 80000, 50000, 10000, 5000
DF의 주요 hyper parameter는 아래와 같이 세팅하였다.
- epoch = 30
- batch-size = 128
- learning-rate = 0.002
- temperature = 0.5
이 setting에서는 추가적인 실험으로 경량화 기법 중 하나인 pruning을 적용해보았다. DF의 layer 중 1d conv layer에 적용하였다. jhson989/pytorch-pruning-basic 레파지토리를 참고하였다.
1
2
3
4
5
import torch.nn.utils.prune as prune
for name, module in model.named_modules():
if isinstance(module, torch.nn.Conv2d) or isinstance(module, torch.nn.Linear):
prune.l1_unstructured(module, name='weight', amount=prune_amount)
prune.l1_unstructured(module, name='bias', amount=prune_amount)
FL Setting
raw feature와 w2v feature 모두 실험하였다.
기존 목표는 동일 조건에서 non-FL setting과 FL setting의 성능 차이를 비교하는 것이었으나, OOM error로 인해 non-FL setting보다 데이터셋 크기와 batch size를 낮춰야만 했다. 추후 FL setting을 non-FL setting에 맞춰서 규모를 줄여 다시 실험하였다. 발생했던 OOM error message는 아래와 같다.
1
2
3
4
5
6
ERROR : Task was killed due to the node running low on memory.
Memory on the node (IP: 203.255.xxx.xxx, ID: b5f5d2651f852e02e1xxxxxxxxxxxxxxxxxx)
where the task (actor ID: 6ee320246624xxxxxxxxxxxxxxxxxx, name=ClientAppActor.__init__, pid=3360949, memory used=23.97GB) was running was 957.43GB / 1007.75GB (0.950067),
which exceeds the memory usage threshold of 0.95.
Ray killed this worker (ID: 3b281265d654bd06xxxxxxxxxxxxxxxxxx) because it was the most recently scheduled task;
to see more information about memory usage on this node, use `ray logs raylet.out -ip 203.255.xxx.xxx`.
따라서 input dimension을 5000으로 고정하였고, sample 수도 random으로 50k개로 줄였다. 주요 hyper parameter는 아래와 같다.
- num-server-rounds = 10
- fraction-evaluate = 0.5
- local-epochs = 3
- learning-rate = 0.001
- batch-size = 16
- num-supernodes = 8
non-FL setting은 이를 고려하여 test set 비율을 50%로, epoch를 30으로도 실험했다(Result의 FL Setting 표). FL Setting과 비슷하게 조건을 맞췄지만, 근본적으로 동일하게는 맞출 수 없다.
Result
Non-FL Setting
딥보이스 판별에서 DF 자체의 성능(test accuracy, 단위: %)은 아래 표와 같았다. ‘*’표시는 50 epoch가 아닌 21 epoch까지 진행했을 때 best validation accuracy를 나타낸다. 80K 기준 1개의 epoch에는 아래 log 기록과 같이 12시간이 소요된다.
5K | 10K | 50K | 80K | |
---|---|---|---|---|
raw | 95.8661 | 96.7115 | *99.5950 | *99.6348 |
w2v | 96.3160 | 96.8123 | *99.5206 | *99.6585 |
1
2
3
4
5
6
2024-12-07 09:38:17,033 - root - INFO - [Epoch 16/50]
2024-12-07 09:38:17,073 - root - INFO - Train - loss: 0.007225 acc: 99.6819%
2024-12-07 09:38:17,074 - root - INFO - Evaluation - loss: 0.013327 acc: 99.6154%
2024-12-07 21:03:38,109 - root - INFO - [Epoch 17/50]
2024-12-07 21:03:38,111 - root - INFO - Train - loss: 0.006091 acc: 99.7257%
2024-12-07 21:03:38,111 - root - INFO - Evaluation - loss: 0.013456 acc: 99.6284%
w2v가 근소하지만 raw보다 더 좋은 성능을 낸다. 데이터셋 크기가 작을수록 w2v feature가 더 크게 성능을 향상시켰다. 하지만 w2v extract하는 overhead에 비해 유의미한 성능 향상을 가져오지는 않았다.
추가적인 실험으로 경량화 기법 중 하나인 unstructured pruning을 적용해보았다. DF의 입력 차원을 5000으로 고정시키고 나머지는 Non-FL Setting에서의 실험과 동일하게 했을 때 best validation accuarcy(단위: %) 결과는 아래 표와 같다.
non-pruning | pruning | |
---|---|---|
raw | 96.1500 | 96.2211 |
w2v | 96.4462 | 96.5335 |
예상과 달리 pruning을 적용했을 때 근소하지만 더 높은 성능이 나왔다. 이는 실험한 데이터셋의 복잡함 이 DF가 지원하는 것보다 간단했음을 시사한다.
FL Setting
test accuracy(단위: %)은 아래 표와 같다.
non-FL | FL | |
---|---|---|
raw | 93.1800 | 87.1 |
w2v | 93.3400 | 88.84 |
연합학습 방식은 프라이버시 보호의 장점이 있지만, 각 클라이언트에서의 데이터 불균형 등의 문제로 상대적으로 성능이 낮다는 단점이 있다. 이 실험에서는 연합학습으로 scratch부터 학습했기 때문에 성능 차이가 더 벌어졌다. 하지만 실제 애플리케이션에서 사용할 때는 중앙 서버를 미리 학습시키고, 클라이언트가 이 가중치로부터 학습을 시작하면 높은 성능 개선을 보일 것이다.
추가적으로, 각 feature에서의 summary는 다음과 같다.
- raw
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
INFO : Run finished 10 round(s) in 587.91s INFO : History (loss, distributed): INFO : round 1: 0.5475497065182728 INFO : round 2: 0.42045295978837377 INFO : round 3: 0.3626457932110452 INFO : round 4: 0.34604969718552464 INFO : round 5: 0.33124802944167875 INFO : round 6: 0.3178197303197429 INFO : round 7: 0.302321320835831 INFO : round 8: 0.30323042901515773 INFO : round 9: 0.2833786549435669 INFO : round 10: 0.29180475404556794 INFO : History (metrics, distributed, evaluate): INFO : {'accuracy': [(1, 71.22), INFO : (2, 77.48), INFO : (3, 83.34), INFO : (4, 84.64), INFO : (5, 85.22), INFO : (6, 85.8), INFO : (7, 86.58), INFO : (8, 86.58), INFO : (9, 87.1), INFO : (10, 87.08)]}
- w2v
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
INFO : Run finished 10 round(s) in 648.81s INFO : History (loss, distributed): INFO : round 1: 0.4846841429324844 INFO : round 2: 0.404717463622742 INFO : round 3: 0.342460409231201 INFO : round 4: 0.3222664087020521 INFO : round 5: 0.2949012125712595 INFO : round 6: 0.28693371247264404 INFO : round 7: 0.27757263179467634 INFO : round 8: 0.26953118110570723 INFO : round 9: 0.2632884760298825 INFO : round 10: 0.2608155852781986 INFO : History (metrics, distributed, evaluate): INFO : {'accuracy': [(1, 77.88), INFO : (2, 82.18), INFO : (3, 85.78), INFO : (4, 86.48), INFO : (5, 88.02), INFO : (6, 88.0), INFO : (7, 88.42), INFO : (8, 89.0), INFO : (9, 88.64), INFO : (10, 88.84)]} INFO : (ClientAppActor pid=485443) Test - loss: 0.261077 acc: 88.6400% [repeated 3x across cluster]
데이터셋 크기가 작아졌기 때문에 w2v feature가 더 크게 성능을 향상시켰다.
terminal에서는 아래와 같이 보인다. 각 client와 server가 계속 소통하는 것을 확인할 수 있다.
Reference
- baseline: DF official implementation (Tensorflow)
- baseline: Flower quickstart-pytorch
- NetCLR
- Unstructured Pruning
- Flower Dataset
- Flower Tutorials 1~5
Looking Back: What I learn
audio와 federated learning 분야는 아예 처음이었다. 따라서 이 프로젝트의 모든 분야가 모두 새로운 도전이었다. 이 프로젝트 덕분에 해당 분야에 대한 이해 뿐만 아니라 실제로 파이프라인을 설계하여 구현해볼 수 있어서 뜻깊었다. 논문을 읽고 모델 구조를 이해하고, 실제로 작동시켜 내 목소리로 결과를 확인해볼 수 있었다. 가장 생각치 못한 어려움은 데이터셋 사이즈가 매우 커서 다운로드와 전처리에 예상했던 시간보다 오랜 시간이 소요되었다는 것이다.
혼자서 처음부터 끝까지 논문을 쓰는 것도 처음이었다. 기술적인 요소도 들어가 있지만 정책 제안 논문을 쓰면서 인공지능 윤리의 중요성에 대해 다시 한번 깨닫게 되었다. 또한 인공지능이 우리 사회를 위해 어느 방향으로 나아가야 될지도 알게 되었다.
Extra Trouble Shooting
Unzip extremely large ZIP file
Synthesizer에서 사용한 다화자 음성합성 데이터는 각 40~50GB의 ZIP 파일 여러 개로 이루어져 있다. 각각의 ZIP 파일을 unzip
명령어로 압축 해제하려 하면 다음과 같은 에러가 뜬다.
1
2
3
4
5
6
$ unzip VS4.zip -d VS4
Archive: VS4.zip
warning [VS4.zip]: 48227474065 extra bytes at beginning or within zipfile
(attempting to process anyway)
error [VS4.zip]: start of central directory not found; zipfile corrupt.
(please check that you have transferred or created the zipfile in the appropriate BINARY mode and that you have compiled UnZip properly)
처음에는 서버에 ZIP 파일이 제대로 업로드되지 않아서 이 에러가 발생했다고 생각했다. 하지만 서버에 잘 올라간 걸 분명히 확인한 경우에도 그대로라 다른 방법을 찾기 시작했다.
그 결과 이 블로그를 보고 대용량 ZIP 파일 압축 해제 시 이 에러가 발생한다는 것을 알았다.
1
$ zip -FF TS17.zip --out TS17_2.zip
위와 같은 명령어로 생성된 ZIP 파일을 unzip
해주면 정상적으로 압축해제된다.
보통 에러가 발생하면 바로 검색하는데 local - server 업로드에서 잘못 되었다고 생각해 안 찾아봤던 것이 화근이었다.
하위 파일 개수가 매우 많은 폴더를 vs code explorer로 연 이후 ssh remote open에 실패하는 경우
vs code에서 하단 output
을 누르면 아래와 같은 메시지가 보인다.
1
2
3
[10:21:53.924] [server] Checking /.vscode-server/cli/servers/Stable-f1a4fb101478ce6ecxxxxxxxxxxxxxxxx/log.txt and
/.vscode-server/cli/servers/Stable-f1a4fb101478ce6ecxxxxxxxxxxxxxxxx/pid.txt for a running server...
[10:21:53.927] [server] Found running server (pid=2823647)
- 1️⃣ 여기서
log.txt
와pid.txt
경로를 복사한다. - 2️⃣ vs code가 아닌 local의 command prompt로 ssh 접속한다.
- 3️⃣
rm
명령어로 복사한 두.txt
파일을 삭제한다.
vs code로 재접속했을 때 이전에 해당 폴더를 잘못 연 connection 정보가 사라지게 되어 새로운 connection이 열리게 된다.