본문 바로가기
코딩

TTS AI 예제 1

by 나는야석사 2024. 7. 11.

음성 파일 시각화

import librosa
import matplotlib.pyplot as plt

# 파일 경로 설정
audio_file_path = '/mnt/data/0005_G1A3E7_KYG_000001.wav'

# 음성 파일 로드
y, sr = librosa.load(audio_file_path, sr=16000)

# 음성 신호 시각화
plt.figure(figsize=(14, 5))
plt.plot(y)
plt.title("Waveform of the audio signal")
plt.xlabel("Time (samples)")
plt.ylabel("Amplitude")
plt.show()

# 기본 정보 출력
print(f"Sample rate: {sr}")
print(f"Duration: {len(y) / sr:.2f} seconds")

노이즈 제거

import noisereduce as nr
import librosa

# 음성 파일 로드
y, sr = librosa.load("path/to/audio.wav", sr=16000)

# 노이즈 제거
reduced_noise = nr.reduce_noise(y=y, sr=sr)

# 결과 저장
librosa.output.write_wav("path/to/reduced_noise_audio.wav", reduced_noise, sr)

특성 추출: MFCC 추출 및 시각

import librosa
import librosa.display
import matplotlib.pyplot as plt

# 음성 파일 로드
y, sr = librosa.load("path/to/audio.wav", sr=16000)

# MFCC 추출
mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)

# MFCC 시각화
plt.figure(figsize=(10, 4))
librosa.display.specshow(mfccs, x_axis='time')
plt.colorbar()
plt.title('MFCC')
plt.tight_layout()
plt.show()

 

 

모델 평가: WER 계산

from jiwer import wer

# 원본 텍스트와 예측 텍스트
reference = "지금 바로 보험사에게 전화 걸어줄래?"
hypothesis = "지금 바로 보험사에게 전화 걸어줄 래?"

# WER 계산
error = wer(reference, hypothesis)
print(f"Word Error Rate: {error}")

 

학습

import json
import os
import numpy as np
import librosa
from transformers import Wav2Vec2ForCTC, Wav2Vec2Processor, Trainer, TrainingArguments
from datasets import Dataset
from sklearn.model_selection import train_test_split
import evaluate

# 파일 경로 설정
audio_dir = '/mnt/data'
label_dir = '/mnt/data'

# 파일 확장자가 .wav인 파일 목록 가져오기
audio_files = [f for f in os.listdir(audio_dir) if f.endswith('.wav')]

# 라벨 파일 로드
label_file = '/mnt/data/label.json'  # 실제 라벨 파일 경로로 변경
with open(label_file, 'r', encoding='utf-8') as f:
    labels = json.load(f)

# 데이터 준비
X = []
y = []

for audio_file in audio_files:
    file_path = os.path.join(audio_dir, audio_file)
    if audio_file in labels:
        y_audio, sr = librosa.load(file_path, sr=16000)
        label_data = labels[audio_file]
        if "OrgLabelText" in label_data["전사정보"]:
            transcript = label_data["전사정보"]["OrgLabelText"]
            X.append({"array": y_audio, "sampling_rate": sr})
            y.append(transcript)

# train_test_split을 사용하여 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 데이터셋 준비
train_data = Dataset.from_list([{"audio": X, "transcript": y} for X, y in zip(X_train, y_train)])
test_data = Dataset.from_list([{"audio": X, "transcript": y} for X, y in zip(X_test, y_test)])

# Wav2Vec 2.0 모델 및 프로세서 로드
processor = Wav2Vec2Processor.from_pretrained("facebook/wav2vec2-large-960h")
model = Wav2Vec2ForCTC.from_pretrained("facebook/wav2vec2-large-960h")

# 데이터셋 전처리 함수
def prepare_dataset(batch):
    audio = batch["audio"]
    inputs = processor(audio["array"], sampling_rate=audio["sampling_rate"], return_tensors="pt", padding="max_length", truncation=True, max_length=16000)
    labels = processor(text=[batch["transcript"]], return_tensors="pt", padding="max_length", truncation=True, max_length=64).input_ids
    batch["input_values"] = inputs.input_values[0].numpy()
    batch["labels"] = labels[0].numpy()
    return batch

# 데이터셋 처리
train_dataset = train_data.map(prepare_dataset, remove_columns=["audio", "transcript"])
test_dataset = test_data.map(prepare_dataset, remove_columns=["audio", "transcript"])

# 모델 학습 설정
training_args = TrainingArguments(
    output_dir="./results",
    evaluation_strategy="epoch",
    per_device_train_batch_size=4,
    per_device_eval_batch_size=4,
    num_train_epochs=3,
    save_steps=10,
    save_total_limit=2,
    fp16=True,
    logging_dir='./logs',
)

# 모델 평가 함수 정의
wer_metric = evaluate.load("wer")

def compute_metrics(pred):
    pred_logits = pred.predictions
    pred_ids = np.argmax(pred_logits, axis=-1)
    pred_str = processor.batch_decode(pred_ids, skip_special_tokens=True)
    labels_ids = pred.label_ids
    labels_str = processor.batch_decode(labels_ids, skip_special_tokens=True)

    wer = wer_metric.compute(predictions=pred_str, references=labels_str)

    return {"wer": wer}

# 트레이너 설정
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=test_dataset,
    tokenizer=processor.feature_extractor,
    compute_metrics=compute_metrics,
)

# 모델 학습
trainer.train()

# 모델 평가
results = trainer.evaluate()
print(results)
print(f"Word Error Rate (WER): {results['eval_wer'] * 100:.2f}%")

 

종합

from google.colab import drive
drive.mount('/content/drive')
# !pip install numpy
# !pip install librosa
# !pip install scikit-learn
# !pip install transformers
# !pip uninstall datasets
# !pip install  datasets==2.6.1
# !pip install torchaudio
# !pip install torch
# !pip install requests
# !pip uninstall pyarrow
# !pip install pyarrow==8.0.0
# !pip install accelerate -U
# !pip install transformers[torch]
# !pip install transformers[torch] accelerate -U
# !pip install pyarrow==8.0.0
import os
import json
import numpy as np
import librosa
from transformers import Wav2Vec2ForCTC, Wav2Vec2Processor, Trainer, TrainingArguments
import torch
from datasets import load_dataset, load_metric, Dataset
from sklearn.model_selection import train_test_split
audio_dir = '/content/drive/MyDrive/origin_0005_G1A3E7_KYG/'
label_dir = '/content/drive/MyDrive/label_0005_G1A3E7_KYG/'
# 파일 확장자가 .wav인 파일 목록 가져오기
audio_files = [f for f in os.listdir(audio_dir) if f.endswith('.wav')]

# 파일 확장자가 .json인 라벨 파일 목록 가져오기
label_files = [f for f in os.listdir(label_dir) if f.endswith('.json')]
# 음성 파일을 로드하고 전처리 함수 정의
def load_audio_file(file_path, sr=16000):
    y, sr = librosa.load(file_path, sr=sr)
    return y, sr
# 모든 라벨 파일 로드 및 병합
all_labels = {}
for label_file in label_files:
    with open(os.path.join(label_dir, label_file), 'r', encoding='utf-8') as f:
        labels = json.load(f)
        file_name = labels['파일정보']['FileName']
        all_labels[file_name] = labels
# 데이터 준비
X = []
y = []

for audio_file in audio_files:
    file_path = os.path.join(audio_dir, audio_file)
    if audio_file in all_labels:
        y_audio, sr = load_audio_file(file_path)
        label_data = all_labels[audio_file]
        if "OrgLabelText" in label_data["전사정보"]:
            transcript = label_data["전사정보"]["OrgLabelText"]
            X.append({"array": y_audio, "sampling_rate": sr})
            y.append(transcript)
# X, y 출력 확인
print("X: ", len(X))  # 데이터 개수 확인
print("y: ", len(y))  # 데이터 개수 확인
# train_test_split을 사용하여 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 데이터셋 준비
train_data = Dataset.from_list([{"audio": X, "transcript": y} for X, y in zip(X_train, y_train)])
test_data = Dataset.from_list([{"audio": X, "transcript": y} for X, y in zip(X_test, y_test)])
# Wav2Vec 2.0 모델 및 프로세서 로드
processor = Wav2Vec2Processor.from_pretrained("facebook/wav2vec2-large-960h")
model = Wav2Vec2ForCTC.from_pretrained("facebook/wav2vec2-large-960h")
# 토크나이저 업데이트
def update_tokenizer(processor, transcripts):
    tokenizer = processor.tokenizer
    new_tokens = set()
    for transcript in transcripts:
        new_tokens.update(transcript)
    tokenizer.add_tokens(list(new_tokens))
    processor = Wav2Vec2Processor(
        feature_extractor=processor.feature_extractor,
        tokenizer=tokenizer
    )
    return processor
# 데이터셋 전처리
def prepare_dataset(batch):
    audio = batch["audio"]
    inputs = processor(audio["array"], sampling_rate=audio["sampling_rate"], return_tensors="pt", padding="max_length", truncation=True, max_length=32000)
    labels = processor(text=[batch["transcript"]], return_tensors="pt", padding="max_length", truncation=True, max_length=128).input_ids
    batch["input_values"] = inputs.input_values[0].numpy()  # Correctly reshape input_values
    batch["labels"] = labels[0].numpy()
    return batch
# 데이터셋 처리
train_dataset = train_data.map(prepare_dataset, remove_columns=["audio", "transcript"])
test_dataset = test_data.map(prepare_dataset, remove_columns=["audio", "transcript"])
# 데이터셋의 일부를 출력하여 확인
for i in range(5):
    sample = train_dataset[i]
    print(f"Sample {i+1}:")
    print(f"  Input values: {sample['input_values'][:10]}")  # 입력 값의 처음 10개 값만 출력
    print(f"  Labels: {sample['labels']}")
    print()
# # 사전 업데이트
# def update_vocab(processor, transcripts):
#     tokenizer = processor.tokenizer
#     new_tokens = set()
#     for transcript in transcripts:
#         new_tokens.update(tokenizer.tokenize(transcript))
#     tokenizer.add_tokens(list(new_tokens))
#     processor.feature_extractor._processor = processor
#     return processor
# 데이터 시각화
import matplotlib.pyplot as plt

def plot_waveform_and_transcript(sample, index):
    plt.figure(figsize=(14, 5))
    plt.plot(sample['input_values'])
    decoded_text = processor.tokenizer.decode(sample['labels'], skip_special_tokens=True)
    plt.title(f"Sample {index+1} - Transcript: {decoded_text}")
    plt.xlabel("Time")
    plt.ylabel("Amplitude")
    plt.show()
# 데이터셋의 일부 샘플을 시각화하여 확인
for i in range(5):
    sample = train_dataset[i]
    plot_waveform_and_transcript(sample, i)
# 모델 학습 설정
training_args = TrainingArguments(
    output_dir="./results",
    evaluation_strategy="epoch",
    per_device_train_batch_size=4,  # 배치 크기 줄이기
    per_device_eval_batch_size=4,  # 배치 크기 줄이기
    num_train_epochs=1,
    save_steps=10,
    save_total_limit=2,
    #fp16=True,  # FP16 혼합 정밀도 사용
    logging_dir='./logs',  # 로그 디렉토리 추가
)
def compute_metrics(pred):
    pred_logits = pred.predictions
    pred_ids = np.argmax(pred_logits, axis=-1)
    pred_str = processor.batch_decode(pred_ids, skip_special_tokens=True)
    labels_ids = pred.label_ids
    labels_str = processor.batch_decode(labels_ids, skip_special_tokens=True)

    # 정확도 계산
    correct_predictions = sum([1 for pred, label in zip(pred_str, labels_str) if pred == label])
    accuracy = correct_predictions / len(pred_str)

    # WER 계산
    wer = wer_metric.compute(predictions=pred_str, references=labels_str)

    return {"accuracy": accuracy, "wer": wer}
# 트레이너 설정
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=test_dataset,
    tokenizer=processor.feature_extractor,
    compute_metrics=compute_metrics,  # compute_metrics 함수 추가
)
# 모델 학습
trainer.train()
# !pip install jiwer
# 모델 평가
wer_metric = load_metric("wer")
results = trainer.evaluate()
print(f"Word Error Rate (WER): {results['eval_wer'] * 100:.2f}%")
print(f"Word Error Rate (WER): {results['wer'] * 100:.2f}%")

'코딩' 카테고리의 다른 글

TTS AI 예제 3  (0) 2024.07.11
TTS AI 예제 2  (0) 2024.07.11
Git 설치 방법  (0) 2024.04.10
파이토치 GPU 사용하는 방법  (0) 2024.01.16
아나콘다 가상환경 requirements.txt 파일 생성하기  (0) 2024.01.11