カスタムオーディオパスによるAcousticSense推論エンジンの活用方法

プロジェクト概要

AcousticSenseは音響信号処理とコンピュータビジョンを統合した音楽ジャンル分類システムです。オーディオをメルスペクトログラムに変換し、Vision Transformerモデルで16種類の音楽ジャンル(ブルース、クラシック、ジャズなど)を識別します。

環境設定と主要コンポーネント

動作要件

  • Python 3.10以上
  • PyTorchフレームワーク
  • Librosaオーディオ処理ライブラリ

中核スクリプト

  • app_gradio.py: Webインターフェース
  • inference.py: 推論処理コア
  • start.sh: サービス起動スクリプト

推論エンジンの主要関数

モデル初期化処理

def initialize_model(weights_path="/data/models/vit_b_16_mel/checkpoint.pt"):
    """ViT-B/16モデルをロード
    引数:
        weights_path: モデル重みファイルのパス
    戻り値:
        初期化済みモデルインスタンス
    """
    vit_model = torchvision.models.vit_b_16(pretrained=False)
    vit_model.heads.head = nn.Linear(vit_model.heads.head.in_features, 16)
    model_weights = torch.load(weights_path, map_location='cpu')
    vit_model.load_state_dict(model_weights['model_state_dict'])
    vit_model.eval()
    return vit_model

音響特徴量変換処理

def transform_audio(input_path, duration=10, sample_rate=22050):
    """オーディオをメルスペクトログラムに変換
    引数:
        input_path: オーディオファイルパス
        duration: 対象長(秒)
        sample_rate: サンプリングレート
    戻り値:
        前処理済みスペクトログラム
    """
    audio_data, _ = librosa.load(input_path, sr=sample_rate)
    if len(audio_data) > sample_rate * duration:
        audio_data = audio_data[:sample_rate * duration]
    else:
        audio_data = np.pad(audio_data, (0, sample_rate * duration - len(audio_data)))
    
    mel_spec = librosa.feature.melspectrogram(y=audio_data, sr=sample_rate, n_mels=128)
    log_mel = librosa.power_to_db(mel_spec, ref=np.max)
    normalized = (log_mel - log_mel.min()) / (log_mel.max() - log_mel.min())
    return np.stack([normalized] * 3, axis=-1)

ジャンル分類処理

def classify_music(input_file, model_instance):
    """オーディオの音楽ジャンルを分類
    引数:
        input_file: オーディオファイルパス
        model_instance: 初期化済みモデル
    戻り値:
        ジャンル予測結果
    """
    spectrogram_data = transform_audio(input_file)
    input_data = torch.tensor(spectrogram_data).permute(2, 0, 1).unsqueeze(0).float()
    
    with torch.no_grad():
        model_output = model_instance(input_data)
        probs = torch.nn.functional.softmax(model_output, dim=1)
    
    top_probs, top_indices = torch.topk(probs, 5)
    genres = ['Blues', 'Classical', 'Jazz', 'Folk', 'Pop', 'Electronic', 
              'Disco', 'Rock', 'Hip-Hop', 'Metal', 'R&B', 'Reggae', 
              'World', 'Latin', 'Country', 'Alternative']
    
    return [{
        'genre': genres[idx.item()], 
        'confidence': round(prob.item() * 100, 2)
    } for prob, idx in zip(top_probs[0], top_indices[0])]

カスタムパス実装例

単一ファイル処理

from inference import initialize_model, classify_music

model_ref = initialize_model()
result = classify_music("/user/data/track.mp3", model_ref)

print("分類結果:")
for idx, item in enumerate(result, 1):
    print(f"{idx}. {item['genre']}: {item['confidence']}%")

ディレクトリ一括処理

import os

def process_directory(music_dir, output="predictions.csv"):
    model_ref = initialize_model()
    with open(output, 'w') as f:
        f.write("ファイル名,主要ジャンル,確信度\n")
        for file in os.listdir(music_dir):
            if file.endswith(('.mp3', '.wav')):
                try:
                    file_path = os.path.join(music_dir, file)
                    prediction = classify_music(file_path, model_ref)[0]
                    f.write(f"{file},{prediction['genre']},{prediction['confidence']}\n")
                except Exception as e:
                    print(f"エラー {file}: {e}")

Web API統合

from flask import Flask, request, jsonify

app = Flask(__name__)
classifier_model = initialize_model()

@app.route('/classify', methods=['POST'])
def classification_handler():
    if 'audio_file' not in request.files:
        return jsonify(error="オーディオファイルがありません"), 400
    
    audio = request.files['audio_file']
    temp_path = f"/tmp/{audio.filename}"
    audio.save(temp_path)
    
    try:
        result = classify_music(temp_path, classifier_model)
        os.remove(temp_path)
        return jsonify(results=result)
    except Exception as e:
        if os.path.exists(temp_path):
            os.remove(temp_path)
        return jsonify(error=str(e)), 500

トラブルシューティング

信頼性向上処理

def validate_and_process(audio_path, model_ref):
    if not os.path.exists(audio_path):
        return {"error": "ファイルが見つかりません"}
    if os.path.getsize(audio_path) > 50 * 1024 * 1024:
        return {"error": "ファイルサイズ超過"}
    return classify_music(audio_path, model_ref)

並列処理最適化

from concurrent.futures import ThreadPoolExecutor

def parallel_processing(file_list, model_ref, workers=4):
    with ThreadPoolExecutor(max_workers=workers) as executor:
        futures = {executor.submit(classify_music, f, model_ref): f for f in file_list}
        return {f: future.result() for future, f in futures.items()}

タグ: PyTorch Vision-Transformer Librosa オーディオ前処理 音楽ジャンル分類

6月18日 20:12 投稿