anggars commited on
Commit
5e534b1
Β·
verified Β·
1 Parent(s): e2cd312

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +29 -55
app.py CHANGED
@@ -3,7 +3,7 @@ import torch.nn as nn
3
  import librosa
4
  import numpy as np
5
  import gradio as gr
6
- from transformers import AutoTokenizer, AutoModel
7
  from huggingface_hub import hf_hub_download
8
  import warnings
9
 
@@ -12,14 +12,7 @@ warnings.filterwarnings('ignore')
12
  # ── CONFIGURATION ──
13
  REPO_ID = "anggars/neural-mathrock"
14
  SR = 16000
15
- DURATION = 10
16
- N_MELS = 32
17
- N_MFCC = 13
18
- HOP_LENGTH = 512
19
- MAX_LENGTH = 128
20
- AUDIO_EMB = 256
21
- TEXT_EMB = 768
22
- FUSED_EMB = 1024
23
  TARGET_COLS = ['mbti', 'emotion', 'vibe', 'intensity', 'tempo']
24
 
25
  print("Downloading model and extracting label encoders...")
@@ -29,28 +22,21 @@ ckpt = torch.load(model_path, map_location=torch.device('cpu'), weights_only=Fal
29
  label_encoders = ckpt['label_encoders']
30
  num_classes = {col: len(le.classes_) for col, le in label_encoders.items()}
31
 
32
- # ── ARCHITECTURE ──
33
- class AudioCNNTransformer(nn.Module):
 
 
 
 
34
  def __init__(self):
35
  super().__init__()
36
- self.cnn = nn.Sequential(
37
- nn.Conv2d(3, 16, 3, padding=1), nn.BatchNorm2d(16), nn.ReLU(), nn.MaxPool2d(2),
38
- nn.Conv2d(16, 32, 3, padding=1), nn.BatchNorm2d(32), nn.ReLU(), nn.MaxPool2d(2),
39
- nn.Conv2d(32, 64, 3, padding=1), nn.BatchNorm2d(64), nn.ReLU(), nn.MaxPool2d(2),
40
- nn.Conv2d(64, 128, 3, padding=1), nn.BatchNorm2d(128), nn.ReLU(),
41
- nn.AdaptiveAvgPool2d((8, 8))
42
- )
43
- encoder_layer = nn.TransformerEncoderLayer(d_model=128, nhead=4, dim_feedforward=512, batch_first=True)
44
- self.transformer = nn.TransformerEncoder(encoder_layer, num_layers=2)
45
- self.fc_out = nn.Linear(128, AUDIO_EMB)
46
 
47
  def forward(self, x):
48
- features = self.cnn(x)
49
- B, C, H, W = features.shape
50
- features = features.view(B, C, H * W).transpose(1, 2)
51
- out = self.transformer(features)
52
- out = out.mean(dim=1)
53
- return self.fc_out(out)
54
 
55
  class TextTransformer(nn.Module):
56
  def __init__(self):
@@ -66,10 +52,10 @@ class TextTransformer(nn.Module):
66
  class MultimodalMathRock(nn.Module):
67
  def __init__(self):
68
  super().__init__()
69
- self.audio = AudioCNNTransformer()
70
  self.text = TextTransformer()
71
  self.fusion = nn.Sequential(
72
- nn.Linear(FUSED_EMB, 512),
73
  nn.ReLU(),
74
  nn.Dropout(0.3)
75
  )
@@ -77,17 +63,21 @@ class MultimodalMathRock(nn.Module):
77
  col: nn.Linear(512, num_classes[col]) for col in TARGET_COLS
78
  })
79
 
80
- def forward(self, audio, input_ids, attention_mask):
81
- x_a = self.audio(audio)
82
  x_t = self.text(input_ids, attention_mask)
83
  fused = self.fusion(torch.cat([x_a, x_t], dim=1))
84
  return {col: self.heads[col](fused) for col in TARGET_COLS}
85
 
 
 
86
  print("Initializing architecture and loading weights...")
87
  model = MultimodalMathRock()
88
  model.load_state_dict(ckpt['model_state'])
89
  model.eval()
 
90
  tokenizer = AutoTokenizer.from_pretrained('xlm-roberta-base')
 
91
 
92
  # ── INFERENCE PIPELINE ──
93
  def predict_multimodal(audio_path, lyrics):
@@ -95,39 +85,23 @@ def predict_multimodal(audio_path, lyrics):
95
  return [None]*5
96
 
97
  try:
 
98
  y, _ = librosa.load(audio_path, sr=SR, duration=DURATION, mono=True)
99
- target_len = SR * DURATION
100
 
101
- if len(y) < target_len:
102
- y = np.pad(y, (0, target_len - len(y)))
103
- else:
104
- y = y[:target_len]
105
-
106
- mel = librosa.power_to_db(librosa.feature.melspectrogram(y=y, sr=SR, n_mels=N_MELS, hop_length=HOP_LENGTH), ref=np.max)
107
- mfcc = librosa.feature.mfcc(y=y, sr=SR, n_mfcc=N_MFCC, hop_length=HOP_LENGTH)
108
- chroma = librosa.feature.chroma_stft(y=y, sr=SR, hop_length=HOP_LENGTH)
109
-
110
- T = mel.shape[1]
111
- feat = np.stack([
112
- mel,
113
- np.resize(mfcc, (N_MELS, T)),
114
- np.resize(chroma, (N_MELS, T))
115
- ], axis=0).astype(np.float32)
116
-
117
- for i in range(3):
118
- std = feat[i].std()
119
- feat[i] = (feat[i] - feat[i].mean()) / (std + 1e-8)
120
-
121
- audio_tensor = torch.from_numpy(feat).unsqueeze(0)
122
 
 
123
  if not lyrics or lyrics.strip() == "":
124
  lyrics = "instrumental"
125
 
126
  enc = tokenizer(
127
- lyrics, max_length=MAX_LENGTH, padding='max_length',
128
  truncation=True, return_tensors='pt'
129
  )
130
 
 
131
  with torch.no_grad():
132
  out = model(audio_tensor, enc['input_ids'], enc['attention_mask'])
133
 
@@ -148,7 +122,7 @@ def predict_multimodal(audio_path, lyrics):
148
  # ── UI ──
149
  with gr.Blocks() as demo:
150
  gr.Markdown("# Neural Math Rock Classifier")
151
- gr.Markdown("Audio feature-based MBTI and emotion classification system. Upload an MP3 or WAV file!")
152
 
153
  with gr.Row():
154
  with gr.Column():
 
3
  import librosa
4
  import numpy as np
5
  import gradio as gr
6
+ from transformers import AutoTokenizer, AutoModel, WavLMModel, AutoFeatureExtractor
7
  from huggingface_hub import hf_hub_download
8
  import warnings
9
 
 
12
  # ── CONFIGURATION ──
13
  REPO_ID = "anggars/neural-mathrock"
14
  SR = 16000
15
+ DURATION = 10 # Potong 10 detik aja biar RAM HF Space gratisan kaga jebol
 
 
 
 
 
 
 
16
  TARGET_COLS = ['mbti', 'emotion', 'vibe', 'intensity', 'tempo']
17
 
18
  print("Downloading model and extracting label encoders...")
 
22
  label_encoders = ckpt['label_encoders']
23
  num_classes = {col: len(le.classes_) for col, le in label_encoders.items()}
24
 
25
+ # ============================================================
26
+ # ── ARCHITECTURE (WAJIB SESUAIKAN SAMA IPYNB TRAINING LU) ──
27
+ # ============================================================
28
+ # HAPUS DAN GANTI blok arsitektur ini pake class asli lu dari jupyter notebook.
29
+
30
+ class AudioTransformer(nn.Module):
31
  def __init__(self):
32
  super().__init__()
33
+ self.wavlm = WavLMModel.from_pretrained("microsoft/wavlm-base")
34
+ for p in self.wavlm.parameters():
35
+ p.requires_grad = False
 
 
 
 
 
 
 
36
 
37
  def forward(self, x):
38
+ out = self.wavlm(x).last_hidden_state
39
+ return out.mean(dim=1)
 
 
 
 
40
 
41
  class TextTransformer(nn.Module):
42
  def __init__(self):
 
52
  class MultimodalMathRock(nn.Module):
53
  def __init__(self):
54
  super().__init__()
55
+ self.audio = AudioTransformer()
56
  self.text = TextTransformer()
57
  self.fusion = nn.Sequential(
58
+ nn.Linear(768 + 768, 512),
59
  nn.ReLU(),
60
  nn.Dropout(0.3)
61
  )
 
63
  col: nn.Linear(512, num_classes[col]) for col in TARGET_COLS
64
  })
65
 
66
+ def forward(self, audio_values, input_ids, attention_mask):
67
+ x_a = self.audio(audio_values)
68
  x_t = self.text(input_ids, attention_mask)
69
  fused = self.fusion(torch.cat([x_a, x_t], dim=1))
70
  return {col: self.heads[col](fused) for col in TARGET_COLS}
71
 
72
+ # ============================================================
73
+
74
  print("Initializing architecture and loading weights...")
75
  model = MultimodalMathRock()
76
  model.load_state_dict(ckpt['model_state'])
77
  model.eval()
78
+
79
  tokenizer = AutoTokenizer.from_pretrained('xlm-roberta-base')
80
+ audio_processor = AutoFeatureExtractor.from_pretrained("microsoft/wavlm-base")
81
 
82
  # ── INFERENCE PIPELINE ──
83
  def predict_multimodal(audio_path, lyrics):
 
85
  return [None]*5
86
 
87
  try:
88
+ # 1. Load audio mentah (otomatis jadi 16kHz mono)
89
  y, _ = librosa.load(audio_path, sr=SR, duration=DURATION, mono=True)
 
90
 
91
+ # 2. Ekstraksi fitur pake WavLM processor
92
+ inputs = audio_processor(y, sampling_rate=SR, return_tensors="pt")
93
+ audio_tensor = inputs.input_values
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
+ # 3. Proses Lirik
96
  if not lyrics or lyrics.strip() == "":
97
  lyrics = "instrumental"
98
 
99
  enc = tokenizer(
100
+ lyrics, max_length=128, padding='max_length',
101
  truncation=True, return_tensors='pt'
102
  )
103
 
104
+ # 4. Forward pass
105
  with torch.no_grad():
106
  out = model(audio_tensor, enc['input_ids'], enc['attention_mask'])
107
 
 
122
  # ── UI ──
123
  with gr.Blocks() as demo:
124
  gr.Markdown("# Neural Math Rock Classifier")
125
+ gr.Markdown("Multimodal WavLM & XLM-RoBERTa based MBTI and emotion classification system.")
126
 
127
  with gr.Row():
128
  with gr.Column():