Views
No views yet
1# requirement packages
2!pip install git+https://github.com/huggingface/datasets.git
3!pip install git+https://github.com/huggingface/transformers.git
4!pip install torchaudio1import os
2import torch
3import torchaudio
4import torch.nn as nn
5import torch.nn.functional as F
6from typing import Optional, Tuple
7from dataclasses import dataclass
8from transformers import AutoConfig, Wav2Vec2FeatureExtractor, HubertPreTrainedModel, HubertModel
9from transformers.file_utils import ModelOutput
10
11def speech_file_to_array_fn(path, sampling_rate):
12 speech_array, _sampling_rate = torchaudio.load(path)
13 resampler = torchaudio.transforms.Resample(_sampling_rate,sampling_rate)
14 speech = resampler(speech_array).squeeze().numpy()
15 return speech
16
17
18@dataclass
19class SpeechClassifierOutput(ModelOutput):
20 loss: Optional[torch.FloatTensor] = None
21 logits: torch.FloatTensor = None
22 hidden_states: Optional[Tuple[torch.FloatTensor]] = None
23 attentions: Optional[Tuple[torch.FloatTensor]] = None
24
25class HubertClassificationHead(nn.Module):
26 """Head for hubert classification task."""
27
28 def __init__(self, config):
29 super().__init__()
30 self.dense = nn.Linear(config.hidden_size, config.hidden_size)
31 self.dropout = nn.Dropout(config.final_dropout)
32 self.out_proj = nn.Linear(config.hidden_size, config.num_labels)
33
34 def forward(self, features, **kwargs):
35 x = features
36 x = self.dropout(x)
37 x = self.dense(x)
38 x = torch.tanh(x)
39 x = self.dropout(x)
40 x = self.out_proj(x)
41 return x
42
43
44class HubertForSpeechClassification(HubertPreTrainedModel):
45 def __init__(self, config):
46 super().__init__(config)
47 self.config = config
48 self.pooling_mode = config.pooling_mode
49
50 self.hubert = HubertModel(config)
51 self.classifier = HubertClassificationHead(config)
52 self.init_weights()
53
54 def merged_strategy(
55 self,
56 hidden_states,
57 mode="mean"
58 ):
59 if mode == "mean":
60 outputs = torch.mean(hidden_states, dim=1)
61 elif mode == "sum":
62 outputs = torch.sum(hidden_states, dim=1)
63 elif mode == "max":
64 outputs = torch.max(hidden_states, dim=1)[0]
65 else:
66 raise Exception(
67 "The pooling method hasn't been defined! Your pooling mode must be one of these ['mean', 'sum', 'max']")
68
69 return outputs
70
71 def forward(self, x):
72 outputs = self.hubert(x)
73 hidden_states = outputs[0]
74 hidden_states = self.merged_strategy(hidden_states, mode=self.pooling_mode)
75 logits = self.classifier(hidden_states)
76 # 返回SpeechClassifierOutput对象
77 return SpeechClassifierOutput(logits=logits)
78
79
80def main():
81 print("正在加载模型...")
82
83 device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
84 model_name_or_path = "ZipperDeng/hubert-base-ser"
85 config = AutoConfig.from_pretrained(model_name_or_path)
86 feature_extractor = Wav2Vec2FeatureExtractor.from_pretrained(model_name_or_path)
87 sampling_rate = feature_extractor.sampling_rate
88 model = HubertForSpeechClassification.from_pretrained(model_name_or_path).to(device)
89
90
91 def predict_single_file(file_path, sampling_rate):
92 """预测单个音频文件的情感"""
93 try:
94 speech = speech_file_to_array_fn(file_path, sampling_rate)
95 features = feature_extractor(speech, sampling_rate=sampling_rate, return_tensors="pt", padding=True)
96
97 input_values = features.input_values.to(device)
98
99 with torch.no_grad():
100 logits = model(input_values).logits
101
102 scores = F.softmax(logits, dim=1).detach().cpu().numpy()[0]
103 outputs = [{"Label": config.id2label[i], "Score": f"{round(score * 100, 3):.1f}%"} for i, score in enumerate(scores)]
104 return outputs
105 except Exception as e:
106 print(f"处理文件 {file_path} 时出错: {e}")
107 return None
108
109 # 检查测试数据目录是否存在
110 test_data = r"F:\test_ser"
111 if not os.path.exists(test_data):
112 print(f"测试数据目录不存在: {test_data}")
113 print("请确保目录存在并包含音频文件")
114 return
115
116 file_path_list = [f"{test_data}/{path}" for path in os.listdir(f"{test_data}") if path.endswith(('.wav', '.mp3', '.flac'))]
117 print(f"找到 {len(file_path_list)} 个音频文件")
118
119 # 逐个处理每个文件
120 for file_path in file_path_list:
121 print(f"\n处理文件: {file_path}")
122 outputs = predict_single_file(file_path, sampling_rate)
123 print("预测结果:")
124 for result in outputs:
125 print(f" {result['Label']}: {result['Score']}")
126
127
128if __name__ == "__main__":
129 # multiprocessing.freeze_support()
130 main()| Training Loss | Epoch | Step | Validation Loss | Accuracy |
|---|---|---|---|---|
| 0.9709 | 0.0229 | 10 | 0.8923 | 0.6399 |
| 0.9219 | 0.0457 | 20 | 0.6903 | 0.7664 |
| 0.7112 | 0.0686 | 30 | 0.5838 | 0.7909 |
| 0.567 | 0.0914 | 40 | 0.5405 | 0.8159 |
| 0.6184 | 0.1143 | 50 | 0.4148 | 0.8581 |
| 0.5291 | 0.1371 | 60 | 0.4444 | 0.8511 |
| 0.533 | 0.16 | 70 | 0.4643 | 0.8271 |
| 0.4753 | 0.1829 | 80 | 0.3560 | 0.8767 |
| 0.4252 | 0.2057 | 90 | 0.5889 | 0.8103 |
| 0.5007 | 0.2286 | 100 | 0.3882 | 0.8663 |
| 0.5605 | 0.2514 | 110 | 0.3221 | 0.8921 |
| 0.4875 | 0.2743 | 120 | 0.3639 | 0.8559 |
| 0.4277 | 0.2971 | 130 | 0.3571 | 0.8746 |
| 0.3415 | 0.32 | 140 | 0.3382 | 0.8861 |
| 0.413 | 0.3429 | 150 | 0.2596 | 0.9104 |
| 0.377 | 0.3657 | 160 | 0.3519 | 0.8711 |
| 0.4219 | 0.3886 | 170 | 0.2979 | 0.8947 |
| 0.3317 | 0.4114 | 180 | 0.2227 | 0.9226 |
| 0.3131 | 0.4343 | 190 | 0.3680 | 0.8693 |
| 0.3266 | 0.4571 | 200 | 0.2098 | 0.9309 |
| 0.3306 | 0.48 | 210 | 0.3849 | 0.8824 |
| 0.3037 | 0.5029 | 220 | 0.2852 | 0.9024 |
| 0.3086 | 0.5257 | 230 | 0.2725 | 0.9121 |
| 0.2576 | 0.5486 | 240 | 0.1869 | 0.9356 |
| 0.2469 | 0.5714 | 250 | 0.2262 | 0.9243 |
| 0.2405 | 0.5943 | 260 | 0.1963 | 0.9347 |
| 0.2802 | 0.6171 | 270 | 0.3680 | 0.8804 |
| 0.2442 | 0.64 | 280 | 0.2053 | 0.9293 |
| 0.2302 | 0.6629 | 290 | 0.3356 | 0.8967 |
| 0.2492 | 0.6857 | 300 | 0.1880 | 0.9371 |
| 0.2089 | 0.7086 | 310 | 0.2076 | 0.9289 |
| 0.2824 | 0.7314 | 320 | 0.1999 | 0.9301 |
| 0.2009 | 0.7543 | 330 | 0.1492 | 0.9521 |
| 0.2001 | 0.7771 | 340 | 0.1496 | 0.9517 |
| 0.2298 | 0.8 | 350 | 0.1579 | 0.9490 |
| 0.1802 | 0.8229 | 360 | 0.1506 | 0.9501 |
| 0.1914 | 0.8457 | 370 | 0.2036 | 0.9311 |
| 0.1897 | 0.8686 | 380 | 0.1838 | 0.9383 |
| 0.1203 | 0.8914 | 390 | 0.1459 | 0.9504 |
| 0.1372 | 0.9143 | 400 | 0.1748 | 0.9419 |
| 0.1942 | 0.9371 | 410 | 0.1813 | 0.9406 |
| 0.1886 | 0.96 | 420 | 0.1536 | 0.9510 |
| 0.1872 | 0.9829 | 430 | 0.1466 | 0.9526 |