提交 18eca268 编写于 作者: xuchaoxin1375's avatar xuchaoxin1375

- "update PCA transformer to the SER system"

- "there are some problems with recognize the single audio with pca preprocessing,the idea is to save the pca transformer when it was first fited,and then try to load corresponding file(joblib or pickle) when you need to recognize several audios that need extract the required dimension feature"
上级 63c5dd05
...@@ -310,7 +310,7 @@ The initial letter(s) of the file name represents the emotion class, and the fol ...@@ -310,7 +310,7 @@ The initial letter(s) of the file name represents the emotion class, and the fol
- 添加语料库(记为db)到本项目中比较简单,只需要在config模块中执行一定的配置即可 - 添加语料库(记为db)到本项目中比较简单,只需要在config模块中执行一定的配置即可
- 不过由于语料库的命名规范的不同,您或许要亲自编写针对于db的`create_{db}_meta()`函数, - 不过由于语料库的命名规范的不同,您或许要亲自编写针对于db的`create_{db}_meta()`函数,
### 语料库文件在项目中的组织 ## 语料库文件在项目中的组织与划分
- 将EMODB语料库放在单独的目录`data/emodb` - 将EMODB语料库放在单独的目录`data/emodb`
- 将RAVDESS语料库 - 将RAVDESS语料库
...@@ -340,6 +340,7 @@ The initial letter(s) of the file name represents the emotion class, and the fol ...@@ -340,6 +340,7 @@ The initial letter(s) of the file name represents the emotion class, and the fol
- `ls |%{$_;(ls $_| measure)|select count}`可以统计子目录的文件数 - `ls |%{$_;(ls $_| measure)|select count}`可以统计子目录的文件数
### desc_files(csv 元数据文件)🎈 ### desc_files(csv 元数据文件)🎈
- 由于不同语料库的文件名规范不同,所以在使用前应该进行基本的统一处理(主要抽取语音文件路径和文件的情感标签) - 由于不同语料库的文件名规范不同,所以在使用前应该进行基本的统一处理(主要抽取语音文件路径和文件的情感标签)
...@@ -389,7 +390,96 @@ The initial letter(s) of the file name represents the emotion class, and the fol ...@@ -389,7 +390,96 @@ The initial letter(s) of the file name represents the emotion class, and the fol
- MEL Spectrogram Frequency (mel) - MEL Spectrogram Frequency (mel)
- Tonnetz (tonal centroid features) - Tonnetz (tonal centroid features)
### 特征预处理
- 对于语音信号的情感识别任务,MFCC、MEL、Contrast 等特征通常是最常用的特征。在使用这些特征进行建模之前,可以考虑进行以下预处理:
1. 归一化:对于不同的特征,可能具有不同的取值范围,例如 MFCC 和 MEL 系数具有不同的幅度范围。因此,可以对所有特征进行归一化或标准化,以确保它们具有相同的尺度。
2. 帧级别的能量归一化:语音信号在录制过程中可能会存在噪声或音量变化等问题,这可能会导致特征的幅度变化。因此,可以对每个帧的能量进行归一化,以确保在不同的录音条件下,特征的幅度保持一致。
3. 去除静音部分:对于包含静音的语音信号,可以通过阈值或其他语音活动检测算法来去除静音部分,以减少噪声的影响。
4. 数据增强:可以通过变换语音信号的速度、音量、音调等方式,生成更多的训练数据,以提高模型的鲁棒性和泛化能力。
5. 特征选择:可以使用特征选择算法,如相关系数或基于模型的方法,来选择最相关的特征,以减少特征的数量和计算成本。
总之,在使用 MFCC、MEL、Contrast 等特征进行语音情感识别任务之前,可以对数据进行归一化、能量归一化、去除静音部分、数据增强和特征选择等预处理,以获得更好的模型性能。
1. 归一化
可以使用 sklearn 中的 StandardScaler 对特征进行归一化,代码如下:
```python
from sklearn.preprocessing import StandardScaler
# X为特征矩阵,axis=0对每列进行归一化
scaler = StandardScaler()
X = scaler.fit_transform(X)
```
1. 帧级别的能量归一化
可以使用 librosa 中的 power_to_db 函数计算每个帧的能量,然后使用 sklearn 中的 MinMaxScaler 对能量进行归一化,代码如下:
```python
from sklearn.preprocessing import MinMaxScaler
import librosa
# y为语音信号,sr为采样率
S = librosa.feature.melspectrogram(y=y, sr=sr, n_mels=128, fmax=8000)
log_S = librosa.power_to_db(S, ref=np.max)
# 计算每个帧的能量
frame_energy = np.sum(np.exp(log_S), axis=0)
# 对帧级别的能量进行归一化
scaler = MinMaxScaler()
frame_energy = scaler.fit_transform(frame_energy.reshape(-1, 1)).reshape(-1)
```
1. 去除静音部分
可以使用 librosa 中的 amplitude_to_db 函数将语音信号转换为分贝表示,然后使用 librosa 中的 onset_detect 函数检测语音活动部分,代码如下:
```python
import librosa
# y为语音信号,sr为采样率
S = librosa.feature.melspectrogram(y=y, sr=sr, n_mels=128, fmax=8000)
log_S = librosa.power_to_db(S, ref=np.max)
# 将语音信号转换为分贝表示
db_S = librosa.amplitude_to_db(S, ref=np.max)
# 检测语音活动部分
onset_frames = librosa.onset.onset_detect(y=y, sr=sr)
onset_times = librosa.frames_to_time(onset_frames, sr=sr)
```
1. 数据增强
可以使用 librosa.effects 中的 time_stretch、pitch_shift 和 dynamic_range_compression 函数,对语音信号进行时间拉伸、音高变换和动态范围压缩,代码如下:
```python
import librosa
# y为语音信号,sr为采样率
y_stretch = librosa.effects.time_stretch(y, rate=0.8)
y_pitch = librosa.effects.pitch_shift(y, sr=sr, n_steps=-3)
y_drc = librosa.effects.dynamic_range_compression(y, threshold=1.0, ratio=4.0)
```
1. 特征选择
可以使用 sklearn 中的 SelectKBest 和 mutual_info_classif 函数,选择与情感识别任务最相关的 k 个特征,代码如下:
```python
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import mutual_info_classif
# X为特征矩阵,y为情感标签
selector = SelectKBest(mutual_info_classif, k=10)
X_new = selector.fit_transform(X, y)
```
以上是一些在使用 MFCC、MEL、Contrast 等特征进行语音情感识别任务时的代码建议,希望能对你有所帮助。
### 补充 ### 补充
...@@ -809,6 +899,16 @@ SVR(Support Vector Regression)是一种基于支持向量机(SVM)的回 ...@@ -809,6 +899,16 @@ SVR(Support Vector Regression)是一种基于支持向量机(SVM)的回
另一种常见的方法是使用逻辑函数(如sigmoid函数)将回归输出映射到[0,1]区间上,并将映射后的输出视为正类概率。 另一种常见的方法是使用逻辑函数(如sigmoid函数)将回归输出映射到[0,1]区间上,并将映射后的输出视为正类概率。
## scikit-learn 加速
Windows 64-bit packages of scikit-learn can be accelerated using scikit-learn-intelex.
More details are available here: https://intel.github.io/scikit-learn-intelex
For example:
$ conda install scikit-learn-intelex
$ python -m sklearnex my_application.py
## DeepLearning method ## DeepLearning method
### Tensorflow.Keras ### Tensorflow.Keras
...@@ -1029,7 +1129,52 @@ SVR(Support Vector Regression)是一种基于支持向量机(SVM)的回 ...@@ -1029,7 +1129,52 @@ SVR(Support Vector Regression)是一种基于支持向量机(SVM)的回
test_score=0.6744186046511628 test_score=0.6744186046511628
``` ```
### HNS
```bash
@{model}
partition='train'
D:\repos\CCSER\SER\meta_files\train_emodb_HNS.csv @🎈{meta_file}
[I] Loading audio file paths and its corresponding labels...
meta_file存在D:\repos\CCSER\SER\meta_files\train_emodb_HNS.csv文件!
检查特征文件D:\repos\CCSER\SER\features\emodb_chroma-mel-mfcc_HNS_169_@std_scaler=False.npy是否存在...
self.e_config=['happy', 'neutral', 'sad']
use StandardScaler to transform features
特征矩阵文件(.npy)已经存在,直接导入:loading...
(169, 180) @{feature.shape}
[Info] Adding train samples
partition='test'
D:\repos\CCSER\SER\meta_files\test_ravdess_HNS.csv @🎈{meta_file}
[I] Loading audio file paths and its corresponding labels...
meta_file存在D:\repos\CCSER\SER\meta_files\test_ravdess_HNS.csv文件!
检查特征文件D:\repos\CCSER\SER\features\ravdess_chroma-mel-mfcc_HNS_552_@std_scaler=False.npy是否存在...
self.e_config=['happy', 'neutral', 'sad']
use StandardScaler to transform features
npy文件不存在,尝试创建...
Extracting features for : 100%|██████████| 552/552 [00:23<00:00, 23.56it/s]
(552, 180) @{feature.shape}
[Info] Adding test samples
[I] Data loaded
@{self.model}:
SVC(C=0.001, gamma=0.001, kernel='poly', probability=True)
train_score=1.0
verbose=0 precision recall f1-score support
happy 0.97 0.29 0.44 215
neutral 0.00 0.00 0.00 145
sad 0.39 1.00 0.56 192
accuracy 0.46 552
macro avg 0.45 0.43 0.34 552
weighted avg 0.51 0.46 0.37 552
SVC
test_score=0.4601449275362319
(169, 180) (169,) 🎈
n_splits=5
cv_score=0.9
```
......
...@@ -34,7 +34,7 @@ import sys ...@@ -34,7 +34,7 @@ import sys
# from SG.psgdemos import find_in_file, get_editor, get_explorer, get_file_list, filter_tooltip, find_re_tooltip, find_tooltip, get_file_list_dict, settings_window, using_local_editor, window_choose_line_to_edit # from SG.psgdemos import find_in_file, get_editor, get_explorer, get_file_list, filter_tooltip, find_re_tooltip, find_tooltip, get_file_list_dict, settings_window, using_local_editor, window_choose_line_to_edit
from audio.core import get_used_keys from audio.core import get_used_keys
from audio.graph import showFreqGraph, showMelFreqGraph, showWaveForm from audio.graph import showFreqGraph, showMelFreqGraph, showWaveForm
from config.EF import ava_algorithms, ava_emotions, ava_features from config.EF import ava_algorithms, ava_emotions, ava_features, ava_svd_solver
from config.MetaPath import ( from config.MetaPath import (
ava_dbs, ava_dbs,
bclf, bclf,
...@@ -66,9 +66,20 @@ test = "test" ...@@ -66,9 +66,20 @@ test = "test"
algorithm = "" algorithm = ""
audio_selected = "" audio_selected = ""
speech_folder = speech_dbs_dir speech_folder = speech_dbs_dir
start_train_key = "start train"
no_result_yet = f"No Result Yet" no_result_yet = f"No Result Yet"
predict_res_key = "emotion_predict_res" predict_res_key = "emotion_predict_res"
std_scaler_key = "std_scaler"
pca_key = "pca_params"
feature_dimension_key = "feature_dimension"
feature_dimension_pca_tip_key = "feature_dimension_pca_tip"
feature_dimension_pca_key = "feature_dimension_pca"
pca_enable_key = "pca_enable"
pca_components_key = "pca_components"
pca_svd_solver_key = "pca_svd_solver"
kfold_radio_key = "kfold" kfold_radio_key = "kfold"
skfold_radio_key = "skfold"
shuffle_split_radio_key = "ss" shuffle_split_radio_key = "ss"
show_confusion_matrix_key = "show_confusion_matrix" show_confusion_matrix_key = "show_confusion_matrix"
...@@ -113,6 +124,7 @@ def get_algos_elements_list(ava_algorithms=ava_algorithms): ...@@ -113,6 +124,7 @@ def get_algos_elements_list(ava_algorithms=ava_algorithms):
) )
return algos_radios return algos_radios
def get_train_fit_start_layout(): def get_train_fit_start_layout():
train_fit_start_layout = [ train_fit_start_layout = [
[ [
...@@ -133,6 +145,7 @@ def get_train_fit_start_layout(): ...@@ -133,6 +145,7 @@ def get_train_fit_start_layout():
return train_fit_start_layout return train_fit_start_layout
## ##
# ---create the window--- # ---create the window---
def make_window(theme=None, size=None): def make_window(theme=None, size=None):
...@@ -151,6 +164,7 @@ def make_window(theme=None, size=None): ...@@ -151,6 +164,7 @@ def make_window(theme=None, size=None):
db_choose_layout = get_db_choose_layout() db_choose_layout = get_db_choose_layout()
e_config_layout = get_e_config_layout() e_config_layout = get_e_config_layout()
f_config_layout = get_f_config_layout() f_config_layout = get_f_config_layout()
f_transform_layout = get_f_transform_layout()
algos_layout = get_algo_layout() algos_layout = get_algo_layout()
other_settings_frame_layout = get_other_settings_layout() other_settings_frame_layout = get_other_settings_layout()
train_fit_start_layout = get_train_fit_start_layout() train_fit_start_layout = get_train_fit_start_layout()
...@@ -171,6 +185,7 @@ def make_window(theme=None, size=None): ...@@ -171,6 +185,7 @@ def make_window(theme=None, size=None):
db_choose_layout db_choose_layout
+ e_config_layout + e_config_layout
+ f_config_layout + f_config_layout
+ f_transform_layout
+ algos_layout + algos_layout
+ other_settings_frame_layout + other_settings_frame_layout
+ train_fit_start_layout + train_fit_start_layout
...@@ -202,7 +217,8 @@ def make_window(theme=None, size=None): ...@@ -202,7 +217,8 @@ def make_window(theme=None, size=None):
] + theme_layout ] + theme_layout
about_layout = info_layout about_layout = info_layout
# ---column right--- # ---column right---
right_column_layout = audio_viewer_layout + get_logging_viewer_layout() right_column_layout = audio_viewer_layout
# + get_logging_viewer_layout()
right_column = sg.Column( right_column = sg.Column(
right_column_layout, right_column_layout,
...@@ -266,6 +282,7 @@ def make_window(theme=None, size=None): ...@@ -266,6 +282,7 @@ def make_window(theme=None, size=None):
) )
return window return window
def get_user_layout(): def get_user_layout():
global userUI global userUI
userUI = UserAuthenticatorGUI() userUI = UserAuthenticatorGUI()
...@@ -274,7 +291,7 @@ def get_user_layout(): ...@@ -274,7 +291,7 @@ def get_user_layout():
# [sg.Input(default_text="user name or ID",key="-USER-")], # [sg.Input(default_text="user name or ID",key="-USER-")],
# [sg.Input(default_text="password",key="-PASSWORD-")], # [sg.Input(default_text="password",key="-PASSWORD-")],
] + userUI.create_user_layout() ] + userUI.create_user_layout()
return user_layout return user_layout
...@@ -292,8 +309,6 @@ def train_res_frame_layout(train_result_tables_layout): ...@@ -292,8 +309,6 @@ def train_res_frame_layout(train_result_tables_layout):
return train_result_frame_layout return train_result_frame_layout
def get_db_choose_layout(): def get_db_choose_layout():
db_choose_layout = [ db_choose_layout = [
[bt.h2("Select the training database")], [bt.h2("Select the training database")],
...@@ -422,6 +437,30 @@ def get_draw_layout(): ...@@ -422,6 +437,30 @@ def get_draw_layout():
def get_logging_viewer_layout(): def get_logging_viewer_layout():
"""
#!这个函数可能潜在的导致特征提取变得异常缓慢,可能是:
- GUI框架中将输出导出到sg.Multiline问题(比如将这部分抽出为函数导致的,在实际试验中,tqdm进度条会因为使用这个组件实时输出导致样式发生变换)
- 这其中的具体原因尚不明确
- 也可能是tqdm可视化的问题
Returns a layout for a dev logging tool.
The layout consists of a Text element with the label "dev logging tool:",
a HorizontalSeparator element with the color specified by the bt.seperator_color
variable, and a Multiline element with the following parameters:
- size: specified by the bt.ml_size variable
- write_only: True
- key: specified by the ML_KEY variable
- reroute_stdout: True
- echo_stdout_stderr: True
- reroute_cprint: True
- auto_refresh: True
- autoscroll: True
Returns:
- A list containing the layout elements as described above.
"""
return [ return [
[sg.Text("dev logging tool:")], [sg.Text("dev logging tool:")],
[sg.HorizontalSeparator(color=bt.seperator_color)], [sg.HorizontalSeparator(color=bt.seperator_color)],
...@@ -430,7 +469,7 @@ def get_logging_viewer_layout(): ...@@ -430,7 +469,7 @@ def get_logging_viewer_layout():
size=bt.ml_size, size=bt.ml_size,
write_only=True, write_only=True,
# expand_x=True, # expand_x=True,
expand_y=True, # expand_y=True,
key=ML_KEY, key=ML_KEY,
reroute_stdout=True, reroute_stdout=True,
echo_stdout_stderr=True, echo_stdout_stderr=True,
...@@ -550,6 +589,13 @@ def get_other_settings_layout(): ...@@ -550,6 +589,13 @@ def get_other_settings_layout():
"k-fold", "k-fold",
group_id="cv_mode", group_id="cv_mode",
key=kfold_radio_key, key=kfold_radio_key,
default=True,
enable_events=True,
),
sg.Radio(
"sk-fold",
group_id="cv_mode",
key=skfold_radio_key,
default=False, default=False,
enable_events=True, enable_events=True,
), ),
...@@ -564,7 +610,7 @@ def get_other_settings_layout(): ...@@ -564,7 +610,7 @@ def get_other_settings_layout():
"stratified-shuffle-split", "stratified-shuffle-split",
group_id="cv_mode", group_id="cv_mode",
key=stratified_shuffle_split_radio_key, key=stratified_shuffle_split_radio_key,
default=True, default=False,
enable_events=True, enable_events=True,
), ),
] ]
...@@ -646,6 +692,36 @@ def get_e_config_layout(): ...@@ -646,6 +692,36 @@ def get_e_config_layout():
return e_config_layout return e_config_layout
tooltip_pca_components = """
PCA components
Number of components to keep. if n_components is not set all components are kept:
n_components == min(n_samples, n_features)
If n_components == 'mle' and svd_solver == 'full', Minka’s MLE is used to guess the dimension. Use of n_components == 'mle' will interpret svd_solver == 'auto' as svd_solver == 'full'.
If 0 < n_components < 1 and svd_solver == 'full', select the number of components such that the amount of variance that needs to be explained is greater than the percentage specified by n_components.
If svd_solver == 'arpack', the number of components must be strictly less than the minimum of n_features and n_samples.
Hence, the None case results in:
n_components == min(n_samples, n_features) - 1
"""
tooltip_pca_svd_solver = """
If auto :
The solver is selected by a default policy based on X.shape and n_components: if the input data is larger than 500x500 and the number of components to extract is lower than 80% of the smallest dimension of the data, then the more efficient ‘randomized’ method is enabled. Otherwise the exact full SVD is computed and optionally truncated afterwards.
If full :
run exact full SVD calling the standard LAPACK solver via scipy.linalg.svd and select the components by postprocessing
If arpack :
run SVD truncated to n_components calling ARPACK solver via scipy.sparse.linalg.svds. It requires strictly 0 < n_components < min(X.shape)
If randomized :
run randomized SVD by the method of Halko et al.
"""
def get_f_config_layout(): def get_f_config_layout():
f_config_option_frame = option_frame( f_config_option_frame = option_frame(
title="Feature Config chooser", title="Feature Config chooser",
...@@ -654,9 +730,6 @@ def get_f_config_layout(): ...@@ -654,9 +730,6 @@ def get_f_config_layout():
sg.Checkbox("MFCC", key="mfcc", default=True, enable_events=True), sg.Checkbox("MFCC", key="mfcc", default=True, enable_events=True),
sg.Checkbox("Mel", key="mel", enable_events=True), sg.Checkbox("Mel", key="mel", enable_events=True),
sg.Checkbox("Contrast", key="contrast", enable_events=True), sg.Checkbox("Contrast", key="contrast", enable_events=True),
# 可以考虑在这里换行
# ],
# [
sg.Checkbox("Chromagram", key="chroma", enable_events=True), sg.Checkbox("Chromagram", key="chroma", enable_events=True),
sg.Checkbox("Tonnetz", key="tonnetz", enable_events=True), sg.Checkbox("Tonnetz", key="tonnetz", enable_events=True),
], ],
...@@ -671,6 +744,59 @@ def get_f_config_layout(): ...@@ -671,6 +744,59 @@ def get_f_config_layout():
return f_config_layout return f_config_layout
def get_f_transform_layout():
f_transform_frame_layout = option_frame(
title="Feature Transform chooser",
layout=[
[
sg.Checkbox(
text="StandardScaler",
key=std_scaler_key,
default=False,
enable_events=True,
),
sg.Checkbox(
text="pca", key=pca_enable_key, default=False, enable_events=True
),
],
[
sg.Input(
key=pca_components_key,
default_text="35",
tooltip=tooltip_pca_components,
enable_events=True,
),
sg.Combo(
values=ava_svd_solver,
default_value="auto",
tooltip=tooltip_pca_svd_solver,
enable_events=True,
key=pca_svd_solver_key,
),
],
[
sg.Text(text="feature_dimension:"),
sg.pin(sg.Text("pending", key=feature_dimension_key)),
],
[
sg.pin(
sg.Text(
text="after pca",
key=feature_dimension_pca_tip_key,
visible=False,
)
),
sg.Text("pending", key=feature_dimension_pca_key, visible=False),
],
],
)
f_transform_layout = [
[bt.h2(lang["feature_transfomr_config"])],
[f_transform_frame_layout],
]
return f_transform_layout
def initial(values=None, verbose=1): def initial(values=None, verbose=1):
"""收集组件的默认值,在用户操作前就应该扫描一遍设置在组件的默认值 """收集组件的默认值,在用户操作前就应该扫描一遍设置在组件的默认值
...@@ -779,14 +905,7 @@ def recognize_auido( ...@@ -779,14 +905,7 @@ def recognize_auido(
sys.exit("Please select an audio file at first!") sys.exit("Please select an audio file at first!")
if er is None: if er is None:
sg.popup("Please train an emotion recognition model at frist !") sg.popup("Please train an emotion recognition model at frist !")
# return
# er = start_train_model(
# train_db=train_db,
# test_db=test_db,
# e_config=e_config,
# f_config=f_config,
# algorithm=algorithm,
# )
else: else:
emotion_predict_result = er.predict(audio_selected) emotion_predict_result = er.predict(audio_selected)
print(f"{emotion_predict_result=}") print(f"{emotion_predict_result=}")
...@@ -829,7 +948,13 @@ def recognize_auido( ...@@ -829,7 +948,13 @@ def recognize_auido(
def start_train_model( def start_train_model(
train_db=None, test_db=None, e_config=None, f_config=None, algorithm=None, verbose=1 train_db=None,
test_db=None,
e_config=None,
f_config=None,
algorithm=None,
values=None,
verbose=1,
): ):
""" """
Train an emotion recognition model and returns an EmotionRecognizer object. Train an emotion recognition model and returns an EmotionRecognizer object.
...@@ -869,6 +994,24 @@ def start_train_model( ...@@ -869,6 +994,24 @@ def start_train_model(
model = ML_estimators_dict[algorithm] model = ML_estimators_dict[algorithm]
print(train_db, test_db, e_config, f_config, algorithm, model, audio_selected) print(train_db, test_db, e_config, f_config, algorithm, model, audio_selected)
# 设置特征预处理(transform)参数
pca_enable = values[pca_enable_key]
pca_params = None
if pca_enable:
pca_params = dict(
n_components=values[pca_components_key],
svd_solver=values[pca_svd_solver_key],
)
fts = dict(
std_scaler=values[std_scaler_key],
pca_params=pca_params,
)
if verbose:
print(fts, "@{fts}🎈")
fts_non_None = {key: value for key, value in fts.items() if value is not None}
# 正式开始拟合/训练模型
if algorithm == "RNN": if algorithm == "RNN":
from recognizer.deep import DeepEmotionRecognizer from recognizer.deep import DeepEmotionRecognizer
...@@ -884,6 +1027,7 @@ def start_train_model( ...@@ -884,6 +1027,7 @@ def start_train_model(
e_config=e_config, e_config=e_config,
f_config=f_config, f_config=f_config,
verbose=1, verbose=1,
**fts_non_None,
) )
# 对数据进行训练(train方法自动导入数据) # 对数据进行训练(train方法自动导入数据)
er.train() er.train()
...@@ -933,11 +1077,11 @@ def main(verbose=1): ...@@ -933,11 +1077,11 @@ def main(verbose=1):
if event: # 监听任何event if event: # 监听任何event
print(event, "@{event}", __file__) print(event, "@{event}", __file__)
# 检测是否窗口要被关闭
# 语料库的选择
if event in (ufg.close, sg.WIN_CLOSED): if event in (ufg.close, sg.WIN_CLOSED):
print(ufg.close, "关闭窗口") print(ufg.close, "关闭窗口")
break break
# 语料库的选择
elif event == "train_db": elif event == "train_db":
train_db = values["train_db"] train_db = values["train_db"]
if verbose > 1: if verbose > 1:
...@@ -984,14 +1128,16 @@ def main(verbose=1): ...@@ -984,14 +1128,16 @@ def main(verbose=1):
open_folder_event(window) open_folder_event(window)
# print("完成文件选取") # print("完成文件选取")
# --情感识别阶段-- # --情感识别阶段--
elif event == "start train": elif event == start_train_key:
n_splits = values[cv_splits_slider_key] # n_splits = values[cv_splits_slider_key]
# std_scaler=values[std_scaler_key]
er = start_train_model( er = start_train_model(
train_db=train_db, train_db=train_db,
test_db=test_db, test_db=test_db,
e_config=e_config, e_config=e_config,
f_config=f_config, f_config=f_config,
algorithm=algorithm, algorithm=algorithm,
values=values,
) )
# 训练收尾工作:将计算结果(识别器)传递给fviewer,赋能fviewer可以(直接利用识别器对象)进行识别 # 训练收尾工作:将计算结果(识别器)传递给fviewer,赋能fviewer可以(直接利用识别器对象)进行识别
...@@ -1084,6 +1230,13 @@ def refresh_trained_view(verbose, window, er, values): ...@@ -1084,6 +1230,13 @@ def refresh_trained_view(verbose, window, er, values):
) # values类型是list[list[any]],每个内部列表表示表格的一个行的数据 ) # values类型是list[list[any]],每个内部列表表示表格的一个行的数据
window[current_model_tip_key].update(visible=True) window[current_model_tip_key].update(visible=True)
window[current_model_key].update(value=er.model) window[current_model_key].update(value=er.model)
ae = er.ae
window[feature_dimension_key].update(value=ae.feature_dimension)
window[feature_dimension_pca_tip_key].update(visible=True)
window[feature_dimension_pca_key].update(
value=ae.get_dimensions(), visible=True
)
n_splits = values[cv_splits_slider_key] n_splits = values[cv_splits_slider_key]
# cv_mode=values[kfold_radio_key] # cv_mode=values[kfold_radio_key]
cv_mode = selected_radio_in(values, ava_list=ava_cv_modes) cv_mode = selected_radio_in(values, ava_list=ava_cv_modes)
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
"welcome_message": "Welcome to My App!", "welcome_message": "Welcome to My App!",
"choose_emotion_config": "Please select an emotional combination for testing: recommended combinations are AS, HNS, AHNS, AHNPS. \nNote that there is a difference between 'surprise' and 'pleasantSurprise' in the SAVEE dataset, \nso the AHNPS combination is not recommended for use on SAVEE.", "choose_emotion_config": "Please select an emotional combination for testing: recommended combinations are AS, HNS, AHNS, AHNPS. \nNote that there is a difference between 'surprise' and 'pleasantSurprise' in the SAVEE dataset, \nso the AHNPS combination is not recommended for use on SAVEE.",
"choose_feature_config": "Please choose one or more features", "choose_feature_config": "Please choose one or more features",
"feature_transfomr_config":"feature transfomer config",
"choose_algorithm": "Choose an algorithm for testing", "choose_algorithm": "Choose an algorithm for testing",
"choose_audio": "Please select an audio sample file to recognize its emotion.", "choose_audio": "Please select an audio sample file to recognize its emotion.",
"recognize_the_audio_emotion": "Recognize the emotion of the selected audio file.", "recognize_the_audio_emotion": "Recognize the emotion of the selected audio file.",
......
...@@ -109,7 +109,7 @@ def extract_feature_of_audio(audio_file_name, f_config): ...@@ -109,7 +109,7 @@ def extract_feature_of_audio(audio_file_name, f_config):
raise ValueError(f"{f_config}包含不受支持的特征名字,请在{ava_features}中选取") raise ValueError(f"{f_config}包含不受支持的特征名字,请在{ava_features}中选取")
try: try:
print(audio_file_name,"@{audio_file_name}") # print(audio_file_name,"@{audio_file_name}")
#考虑将此时的工作路径切换为项目根目录,以便利用相对路径访问文件 #考虑将此时的工作路径切换为项目根目录,以便利用相对路径访问文件
# os.chdir(project_dir) # os.chdir(project_dir)
p = Path(audio_file_name) p = Path(audio_file_name)
...@@ -286,13 +286,8 @@ def mfcc_extract(X, sample_rate): ...@@ -286,13 +286,8 @@ def mfcc_extract(X, sample_rate):
mfcc = librosa.feature.mfcc(y=X, sr=sample_rate, n_mfcc=40) mfcc = librosa.feature.mfcc(y=X, sr=sample_rate, n_mfcc=40)
# shape=(40,60) # shape=(40,60)
mfccT = mfcc.T # shape=(60,40) mfccT = mfcc.T # shape=(60,40)
mfccs = np.mean(mfccT, axis=0) mfccs = np.mean(mfccT, axis=0)
# log:info
# print(f'{mfcc=},{mfcc.shape=}')
# print(f'{mfccT=},{mfccT.shape=}')
# print(f'{mfccs=},{mfccs.shape=}')
# result = np.hstack((result, mfccs))
return mfccs return mfccs
......
...@@ -27,6 +27,22 @@ emodb_files_glob, ravdess_files_glob, savee_files_glob = [ ...@@ -27,6 +27,22 @@ emodb_files_glob, ravdess_files_glob, savee_files_glob = [
def check_meta_names(e_config, train_name=None, test_name=None, db=""): def check_meta_names(e_config, train_name=None, test_name=None, db=""):
"""
Check and retrieve the names of the metadata files for a given database.
Args:
e_config (dict): A dictionary containing the configuration parameters for the experiment.
train_name (str, optional): The name of the training metadata file. Defaults to None.
test_name (str, optional): The name of the testing metadata file. Defaults to None.
db (str, optional): The name of the database. Defaults to "".
Raises:
ValueError: If db is an empty string.
Returns:
A tuple (train_name, test_name) with the names of the metadata files for the given database.
If train_name or test_name are not provided, they are obtained from the metadata paths of the database.
"""
if train_name is None or test_name is None: if train_name is None or test_name is None:
train_name, test_name = meta_paths_of_db(db, e_config=e_config) train_name, test_name = meta_paths_of_db(db, e_config=e_config)
if db == "": if db == "":
...@@ -261,8 +277,9 @@ def create_ravdess_meta( ...@@ -261,8 +277,9 @@ def create_ravdess_meta(
""" """
db = ravdess db = ravdess
# 这个数据库文件比较多,为了敏捷性,控制只处理特定情感的文件而不是全部情感文件 print(f"{db} @files meta extracting!...")
print(f"{db} files meta extacting...") train_name, test_name = check_meta_names(e_config, train_name, test_name, db)
if e_config is None: if e_config is None:
raise ValueError(f"{db}e_config is None") raise ValueError(f"{db}e_config is None")
# 对特定情感文件的过滤(这里直接通过遍历指定的情感种类,配合glob来直接过滤掉不需要的情感) # 对特定情感文件的过滤(这里直接通过遍历指定的情感种类,配合glob来直接过滤掉不需要的情感)
...@@ -271,6 +288,7 @@ def create_ravdess_meta( ...@@ -271,6 +288,7 @@ def create_ravdess_meta(
emos = [] emos = []
paths = [] paths = []
audios = glob(ravdess_files_glob) audios = glob(ravdess_files_glob)
# total = len(audios) # total = len(audios)
# audios = audios[: int(total * subset_size)] # audios = audios[: int(total * subset_size)]
for audio in audios: for audio in audios:
...@@ -284,7 +302,7 @@ def create_ravdess_meta( ...@@ -284,7 +302,7 @@ def create_ravdess_meta(
# 打印出所有匹配项的值 # 打印出所有匹配项的值
emo = m.group(1) emo = m.group(1)
print(emo,"@{emo}") # print(emo,"@{emo}")
paths.append(audio) paths.append(audio)
emos.append(emo) emos.append(emo)
...@@ -301,7 +319,7 @@ def create_ravdess_meta( ...@@ -301,7 +319,7 @@ def create_ravdess_meta(
p_e_df = p_e_df[emo_bool_mask] p_e_df = p_e_df[emo_bool_mask]
if verbose: if verbose:
print(f"{p_e_df.shape=}") print(f"{p_e_df.shape=}🎈")
n_samples = len(p_e_df) n_samples = len(p_e_df)
print("[ravdess] Total files to write:", n_samples) print("[ravdess] Total files to write:", n_samples)
# dividing training/testing sets # dividing training/testing sets
...@@ -321,7 +339,7 @@ def create_ravdess_meta( ...@@ -321,7 +339,7 @@ def create_ravdess_meta(
if verbose: if verbose:
print(train_name, "@{train_name}") print(train_name, "@{train_name}")
print(test_name, "@{test_name}") print(test_name, "@{test_name}")
print("文件创建完毕!") print("file created!")
return spl return spl
# meta_df = DataFrame(meta_dict) # meta_df = DataFrame(meta_dict)
...@@ -340,7 +358,7 @@ def create_ravdess_meta( ...@@ -340,7 +358,7 @@ def create_ravdess_meta(
# print(f"the train/test size rate is:{train_size}:{(1-train_size)}") # print(f"the train/test size rate is:{train_size}:{(1-train_size)}")
def from_df_write_to_csv(train_name="", test_name="", sort=True, Xy_train=None, Xy_test=None): def from_df_write_to_csv(train_name="", test_name="", sort=True, Xy_train=None, Xy_test=None,verbose=1):
train_df = DataFrame(Xy_train) train_df = DataFrame(Xy_train)
test_df = DataFrame(Xy_test) test_df = DataFrame(Xy_test)
if sort: if sort:
...@@ -348,6 +366,8 @@ def from_df_write_to_csv(train_name="", test_name="", sort=True, Xy_train=None, ...@@ -348,6 +366,8 @@ def from_df_write_to_csv(train_name="", test_name="", sort=True, Xy_train=None,
sorted_test_df = test_df.sort_values(by="emotion") sorted_test_df = test_df.sort_values(by="emotion")
sorted_train_df.to_csv(train_name) sorted_train_df.to_csv(train_name)
sorted_test_df.to_csv(test_name) sorted_test_df.to_csv(test_name)
if verbose:
print(f"{train_name}&{train_name} created!")
# 不可以挪到顶部,因为下面的selector的定义需要用到上面定义的函数 # 不可以挪到顶部,因为下面的selector的定义需要用到上面定义的函数
...@@ -358,7 +378,7 @@ selector = { ...@@ -358,7 +378,7 @@ selector = {
} }
def create_csv_by_metaname(meta_file, shuffle=True): def create_csv_by_metaname(meta_file, shuffle=True,verbose=1):
"""根据给定的符合本项目的文件名构造规范的文件名,生成对应的train/test dataset metadata files """根据给定的符合本项目的文件名构造规范的文件名,生成对应的train/test dataset metadata files
Parameters Parameters
...@@ -373,6 +393,10 @@ def create_csv_by_metaname(meta_file, shuffle=True): ...@@ -373,6 +393,10 @@ def create_csv_by_metaname(meta_file, shuffle=True):
# 直接解析成三个字符串 # 直接解析成三个字符串
# print(name,"@{name}") # print(name,"@{name}")
_partitoin, db, emotion_first_letters = name.split("_") _partitoin, db, emotion_first_letters = name.split("_")
if verbose:
print(db, "@{db}")
print(emotion_first_letters, "@{emotion_first_letters}")
e_config = extend_emotion_names(emotion_first_letters) e_config = extend_emotion_names(emotion_first_letters)
if 'others' in e_config: if 'others' in e_config:
use_others=True use_others=True
...@@ -403,7 +427,9 @@ if __name__ == "__main__": ...@@ -403,7 +427,9 @@ if __name__ == "__main__":
# create_csv_by_metaname(name1) # create_csv_by_metaname(name1)
name2 = "train_savee_AS.csv" name2 = "train_savee_AS.csv"
name3 = "test_savee_HNS.csv" name3 = "test_savee_HNS.csv"
# create_csv_by_metaname(name3, shuffle=True) name4="test_ravdess_AS.csv"
create_csv_by_metaname(name4, shuffle=True)
## ##
# create_emodb_meta(e_config=e_config_def+["others"],train_name="tr_emodb.csv",test_name='te_emodb.csv',use_others=True) # create_emodb_meta(e_config=e_config_def+["others"],train_name="tr_emodb.csv",test_name='te_emodb.csv',use_others=True)
# create_ravdess_meta(e_config=e_config_def+["others"],train_name="tr_ravdess.csv",test_name='te_ravdess.csv',use_others=True) # create_ravdess_meta(e_config=e_config_def+["others"],train_name="tr_ravdess.csv",test_name='te_ravdess.csv',use_others=True)
......
import os import os
from collections import defaultdict from collections import defaultdict
import sys
import ipdb import ipdb
import numpy as np import numpy as np
...@@ -40,6 +41,7 @@ class AudioExtractor: ...@@ -40,6 +41,7 @@ class AudioExtractor:
classification_task=True, classification_task=True,
balance=True, balance=True,
shuffle=True, shuffle=True,
feature_transforms_dict=None,
): ):
""" """
初始化AE对象,在init中对构造器中传入None或者不传值得参数设置了默认值,默认参数为None是参考Numpy的风格 初始化AE对象,在init中对构造器中传入None或者不传值得参数设置了默认值,默认参数为None是参考Numpy的风格
...@@ -74,10 +76,16 @@ class AudioExtractor: ...@@ -74,10 +76,16 @@ class AudioExtractor:
self.verbose = verbose self.verbose = verbose
self.features_dir = features_dir # 默认为features目录 self.features_dir = features_dir # 默认为features目录
self.classification_task = classification_task self.classification_task = classification_task
self.feature_transforms = (
feature_transforms_dict
if feature_transforms_dict
else dict(std_scaler=True)
)
self.balance = balance self.balance = balance
self.shuffle=shuffle self.shuffle = shuffle
# input dimension # input dimension
self.feature_dimension = None self.feature_dimension = None
self.feature_dimension_pca = None
# 记录最后一次提取语音文件信息 # 记录最后一次提取语音文件信息
self.audio_paths = [] self.audio_paths = []
self.emotions = [] self.emotions = []
...@@ -91,6 +99,7 @@ class AudioExtractor: ...@@ -91,6 +99,7 @@ class AudioExtractor:
self.test_emotions = [] self.test_emotions = []
self.test_features = [] self.test_features = []
# 使用字典打包 # 使用字典打包
self.pca = None
def get_partition_features(self, partition) -> np.ndarray: def get_partition_features(self, partition) -> np.ndarray:
"""将包含若干个二维ndarray的列表vstack成1个二维ndarray """将包含若干个二维ndarray的列表vstack成1个二维ndarray
...@@ -113,7 +122,7 @@ class AudioExtractor: ...@@ -113,7 +122,7 @@ class AudioExtractor:
# print("len(self.train_features),len(self.test_features):") # print("len(self.train_features),len(self.test_features):")
# print(len(self.train_features),len(self.test_features)) # print(len(self.train_features),len(self.test_features))
# return # return
partition = validate_partition(partition,Noneable=False) partition = validate_partition(partition, Noneable=False)
if partition == "test": if partition == "test":
res = np.vstack(self.test_features) if self.test_features else np.array([]) res = np.vstack(self.test_features) if self.test_features else np.array([])
else: else:
...@@ -154,7 +163,7 @@ class AudioExtractor: ...@@ -154,7 +163,7 @@ class AudioExtractor:
if not os.path.exists(meta_file): if not os.path.exists(meta_file):
# create_csv_by_meta_name # create_csv_by_meta_name
print(f"{meta_file} does not exist,creating...😂") print(f"{meta_file} does not exist,creating...😂")
create_csv_by_metaname(meta_file,shuffle=self.shuffle) create_csv_by_metaname(meta_file, shuffle=self.shuffle)
else: else:
print(f"meta_file存在{meta_file}文件!") print(f"meta_file存在{meta_file}文件!")
df_meta = pd.read_csv(meta_file) df_meta = pd.read_csv(meta_file)
...@@ -294,7 +303,7 @@ class AudioExtractor: ...@@ -294,7 +303,7 @@ class AudioExtractor:
print([id(attr) for attr in attributes]) print([id(attr) for attr in attributes])
return attributes return attributes
def _extract_feature_in_meta(self, partition="", meta_path="",verbose=1): def _extract_feature_in_meta(self, partition="", meta_path="", verbose=1):
"""根据meta_files提取相应语音文件的特征 """根据meta_files提取相应语音文件的特征
这里仅完成单次提取 这里仅完成单次提取
...@@ -309,7 +318,7 @@ class AudioExtractor: ...@@ -309,7 +318,7 @@ class AudioExtractor:
标记被提取文件是来自训练集还是测试集(验证集) 标记被提取文件是来自训练集还是测试集(验证集)
""" """
# 检查数据集是否按照配置的情感进行筛选和划分: # 检查数据集是否按照配置的情感进行筛选和划分:
audio_paths, emotions = self.load_metadata(meta_path) audio_paths, emotions = self.load_metadata(meta_path)
# 将计算结果保存为对象属性 # 将计算结果保存为对象属性
self.audio_paths = audio_paths self.audio_paths = audio_paths
...@@ -317,7 +326,7 @@ class AudioExtractor: ...@@ -317,7 +326,7 @@ class AudioExtractor:
# 尝试计算语料库的名字和情感配置名字 # 尝试计算语料库的名字和情感配置名字
db = self.fields_parse(meta_path) db = self.fields_parse(meta_path)
if not os.path.isdir(self.features_dir): if not os.path.isdir(self.features_dir):
os.mkdir(self.features_dir) os.mkdir(self.features_dir)
...@@ -330,6 +339,7 @@ class AudioExtractor: ...@@ -330,6 +339,7 @@ class AudioExtractor:
f_config=self.f_config, f_config=self.f_config,
n_samples=n_samples, n_samples=n_samples,
ext="npy", ext="npy",
**(self.feature_transforms),
) )
# 构造保存特征矩阵npy文件的路径 # 构造保存特征矩阵npy文件的路径
...@@ -340,53 +350,62 @@ class AudioExtractor: ...@@ -340,53 +350,62 @@ class AudioExtractor:
if verbose: if verbose:
print(f"检查特征文件{features_file_path}是否存在...") print(f"检查特征文件{features_file_path}是否存在...")
print(f"{self.e_config=}") print(f"{self.e_config=}")
print(f"{self.f_config=}")
ffp = os.path.isfile(features_file_path) ffp = os.path.isfile(features_file_path)
if self.feature_transforms.get("std_scaler"):
print("use StandardScaler to transform features🎈")
if ffp: if ffp:
# if file already exists, just load # if file already exists, just load
if self.verbose: if self.verbose:
print(f"特征矩阵文件(.npy)已经存在,直接导入:loading...") print(f"特征矩阵文件(.npy)已经存在,直接导入:loading...")
features = np.load(features_file_path) features = np.load(features_file_path)
self.feature_dimension = features.shape[1]
else: else:
# file does not exist, extract those features and dump them into the file # file does not exist, extract those features and dump them into the file
if self.verbose: if self.verbose:
print("npy文件不存在,尝试创建...") print("npy文件不存在,尝试创建...")
# 如果尚未提取过特征,则在此处进行提取,同时保存提取结果,以便下次直接使用 # 如果尚未提取过特征,则在此处进行提取,同时保存提取结果,以便下次直接使用
features = self.features_extract_save(partition, audio_paths, features_file_path) features = self.features_extract_save(
partition, audio_paths, features_file_path
)
return features, audio_paths, emotions return features, audio_paths, emotions
def fields_parse(self, meta_path): def fields_parse(self, meta_path):
# 计算语料库字段名
#计算语料库字段名
meta_fields, db = self.db_field_parse(meta_path) meta_fields, db = self.db_field_parse(meta_path)
#计算情感字段并检查 # 计算情感字段并检查
self.validate_emotion_config_consistence(meta_fields) self.validate_emotion_config_consistence(meta_fields)
return db return db
def db_field_parse(self, meta_path): def db_field_parse(self, meta_path):
meta_name = os.path.basename(meta_path) meta_name = os.path.basename(meta_path)
meta_name,ext=os.path.splitext(meta_name) meta_name, ext = os.path.splitext(meta_name)
meta_fields = meta_name.split("_") meta_fields = meta_name.split("_")
db = meta_fields[1] db = meta_fields[1]
# print(f"{meta_path=}@") # print(f"{meta_path=}@")
# print(f"{db=}@") # print(f"{db=}@")
db = db if db in ava_dbs else "" db = db if db in ava_dbs else ""
return meta_fields,db return meta_fields, db
def validate_emotion_config_consistence(self, meta_fields): def validate_emotion_config_consistence(self, meta_fields):
emotions_first_letters=meta_fields[-1] emotions_first_letters = meta_fields[-1]
origin_efls = get_first_letters(self.e_config) origin_efls = get_first_letters(self.e_config)
#检查情感配置是否具有一致性 # 检查情感配置是否具有一致性
if emotions_first_letters != origin_efls: if emotions_first_letters != origin_efls:
raise ValueError( raise ValueError(
f"{emotions_first_letters} is not inconsistant with {self.e_config}" f"{emotions_first_letters} is not inconsistant with {self.e_config}"
) )
def features_extract_save(self, partition, audio_paths, features_file_path): def features_extract_save(
self, partition, audio_paths, features_file_path, verbose=1
):
"""将提取的特征(ndarray)保存持久化保存(为npy文件) """将提取的特征(ndarray)保存持久化保存(为npy文件)
利用qtmd提供可视化特征抽取进度 利用qtmd提供可视化特征抽取进度
...@@ -397,39 +416,120 @@ class AudioExtractor: ...@@ -397,39 +416,120 @@ class AudioExtractor:
audio_paths_ : str audio_paths_ : str
音频文件的路径 音频文件的路径
features_file_path : str features_file_path : str
保存文件名 保存文件名(路径)
Returns Returns
------- -------
ndarray ndarray
提取的特征数组 提取的特征数组
""" """
features = self.extract_features(partition, audio_paths)
# 保存数据
np.save(features_file_path, features)
return features
def extract_features(self, partition=None, audio_paths=None):
"""
Extract features from audio_paths for a specific partition.
处理包括标准化放缩
pca降维等特征优选操作
Args:
-
- partition: str, the partition to extract features for (train, val, test).
- audio_paths: List[str], the list of audio file paths to extract features from.
- verbose: bool, whether or not to print debugging info.
Returns:
-
- features: np.ndarray, the extracted features as a numpy array.
"""
features = self.extract_raw_features(partition=partition, audio_paths=audio_paths)
# 考虑特征预处理
from sklearn.preprocessing import StandardScaler
# X为特征矩阵,axis=0对每列进行归一化
# if kwargs.get("std_scaler"):
fts = self.feature_transforms
if fts.get("std_scaler"):
print("use StandardScaler to transform features")
std_scaler = StandardScaler()
features = std_scaler.fit_transform(features)
# 小心字典关键字名字pca和pca_params,否则后面代码无法执行!
pca_params_dict = fts.get("pca_params")
if not pca_params_dict:
print("the pca params may be invalid!")
print("🎈🎈🎈特征提取")
if pca_params_dict:
from sklearn.decomposition import PCA
print("use PCA to transform features")
n_components = pca_params_dict.get("n_components")
if n_components == "None":
# pca_params_dict["n_components"] = None
n_components=None
else:
# if n_components.isdigit():
# int()函数自带类型错误检测,有非法输入会自动抛出错误,所以这里直接使用,而不去手动检测输入的合法性
# pca_params_dict['n_components'] = int(n_components)
n_components=int(n_components)
# 将检验&处理后的n_components写入到pca字典中
pca_params_dict['n_components']=n_components
# 根据当前ae对象中的pca属性以及参数情况决定构造pca对象
if self.pca is None:
pca = self.pca = PCA(**pca_params_dict)
pca.fit(features)
else:
pca = self.pca
print(pca_params_dict, "@{pca_params_dict}😂")
print(pca.n_components_, "@{pca.n_components_}")
features = pca.transform(features)
print(features.shape, "{features.shape}😂")
# sys.exit()
# 这部分可以抽取为单独的函数get_n_features_pca更加灵活
# 使用面向对象的编程方式有点就显示出来了,可以通过对象属性或get方法来提高访问对象数据或属性,实现灵活通信,减少对于特定函数的依赖
self.feature_dimension_pca = pca.n_components
return features
def get_dimensions(self):
return np.array(self.test_features).shape[1]
def extract_raw_features(self, partition=None, audio_paths=None):
features = [] features = []
# print(audio_paths) # print(audio_paths)
# append = features.append # append = features.append
# 特征提取是一个比较耗时的过程,特征种类越多越耗时,这里采用tqdm显示特征提取进度条(已处理文件/文件总数) # 特征提取是一个比较耗时的过程,特征种类越多越耗时,这里采用tqdm显示特征提取进度条(已处理文件/文件总数)
cnt=0 cnt = 0
for audio_file in tqdm.tqdm( for audio_file in tqdm.tqdm(
audio_paths, f"Extracting features for {partition}" audio_paths, f"Extracting features for partition:{partition}"
): ):
cnt+=1
if cnt%20 ==0: if self.verbose > 1:
print(f"正在抽取第{cnt}个文件的特征..") cnt += 1
if cnt % 20 == 0:
print(f"正在抽取第{cnt}个文件的特征..")
# 调用utils模块中的extract_featrue进行特征提取 # 调用utils模块中的extract_featrue进行特征提取
f_config = self.f_config f_config = self.f_config
#! 抽取特征
feature = extract_feature_of_audio(audio_file, f_config=f_config) feature = extract_feature_of_audio(audio_file, f_config=f_config)
if self.feature_dimension is None: if self.feature_dimension is None:
# MCM特征组合下(3特征),有180维的单轴数组,5特征下,有193维 # MCM特征组合下(3特征),有180维的单轴数组,5特征下,有193维
self.feature_dimension = feature.shape[0] self.feature_dimension = feature.shape[0]
# 把当前文件提取出来特征添加到features数组中 # 把当前文件提取出来特征添加到features数组中
features.append(feature) features.append(feature)
# features是一个二维数组(n_samples,feature_dimension),每一行代表一个特征 # features是一个二维数组(n_samples,feature_dimension),每一行代表一个特征
# 此时所有文件特征提取完毕,将其用numpy保存为npy文件 # 此时所有文件特征提取完毕,将其用numpy保存为npy文件
features = np.array(features) # 构成二维数组 # 构成二维数组
np.save(features_file_path, features) features = np.array(features)
# print(features)
# sys.exit(1)
return features return features
def extract_update(self, partition="", meta_paths="", verbose=1): def extract_update(self, partition="", meta_paths="", verbose=1):
...@@ -453,10 +553,13 @@ class AudioExtractor: ...@@ -453,10 +553,13 @@ class AudioExtractor:
for meta_file in meta_paths: for meta_file in meta_paths:
print(meta_file, "@🎈{meta_file}") print(meta_file, "@🎈{meta_file}")
# sys.exit() # sys.exit()
# 根据meta文件进行批量地特征提取
features, audio_paths, emotions = self._extract_feature_in_meta( features, audio_paths, emotions = self._extract_feature_in_meta(
meta_path=meta_file, partition="" meta_path=meta_file, partition=""
) )
# 这里将partition设置为空字符串,是因为标记特征是用来训练还是用来测试意义不大,而且在跨库试验中,我们会让一个train/test features 小环身份,只需要知道这个特征文件包含哪些情感特征,来自哪个语料库,以及有多少个文件即可 # 这里将partition设置为空字符串,是因为标记特征是用来训练还是用来测试意义不大
# 而且在跨库试验中,我们会让一个train/test features 交换身份,
# 只需要知道这个特征文件包含哪些情感特征,来自哪个语料库,以及有多少个文件即可
# 如果要更细致一些,可以考虑加入balance或shuffle信息,但这不是必须的,而且会对调试造成不变 # 如果要更细致一些,可以考虑加入balance或shuffle信息,但这不是必须的,而且会对调试造成不变
if verbose >= 1: if verbose >= 1:
print(features.shape, "@{feature.shape}") print(features.shape, "@{feature.shape}")
...@@ -488,7 +591,11 @@ class AudioExtractor: ...@@ -488,7 +591,11 @@ class AudioExtractor:
# print(meta_files,"@{meta_files}in load_data_preprossing") # print(meta_files,"@{meta_files}in load_data_preprossing")
if not meta_files: if not meta_files:
return return
self.extract_update(partition=partition, meta_paths=meta_files) self.extract_update(
partition=partition,
meta_paths=meta_files,
# feature_transforms=self.feature_transforms,
)
# balancing the datasets ( both training or testing ) # balancing the datasets ( both training or testing )
if self.balance: if self.balance:
...@@ -516,9 +623,10 @@ class AudioExtractor: ...@@ -516,9 +623,10 @@ class AudioExtractor:
self.train_emotions, self.train_emotions,
self.train_features, self.train_features,
) = shuffle_data( ) = shuffle_data(
self.train_audio_paths, self.train_emotions, self.train_audio_paths,
self.train_emotions,
# self.train_features # self.train_features
self.get_partition_features("train") self.get_partition_features("train"),
) )
elif partition == "test": elif partition == "test":
( (
...@@ -526,9 +634,10 @@ class AudioExtractor: ...@@ -526,9 +634,10 @@ class AudioExtractor:
self.test_emotions, self.test_emotions,
self.test_features, self.test_features,
) = shuffle_data( ) = shuffle_data(
self.test_audio_paths, self.test_emotions, self.test_audio_paths,
self.test_emotions,
# self.test_features # self.test_features
self.get_partition_features("test") self.get_partition_features("test"),
) )
else: else:
raise TypeError("Invalid partition, must be either train/test") raise TypeError("Invalid partition, must be either train/test")
...@@ -715,7 +824,7 @@ def shuffle_data(audio_paths, emotions, features): ...@@ -715,7 +824,7 @@ def shuffle_data(audio_paths, emotions, features):
# 根据统一的乱序序列,便于统一audio_paths,emotions,features # 根据统一的乱序序列,便于统一audio_paths,emotions,features
# 因此这里不可用直接地对三个列表各自地运行shuffle或permutation,会导致对应不上 # 因此这里不可用直接地对三个列表各自地运行shuffle或permutation,会导致对应不上
p = np.random.permutation(length) p = np.random.permutation(length)
#手动在此处抛出调试性异常(此处采用pdb模块来调试) # 手动在此处抛出调试性异常(此处采用pdb模块来调试)
# raise ValueError("short!") # raise ValueError("short!")
audio_paths = [audio_paths[i] for i in p] audio_paths = [audio_paths[i] for i in p]
emotions = [emotions[i] for i in p] emotions = [emotions[i] for i in p]
...@@ -732,6 +841,7 @@ def load_data_from_meta( ...@@ -732,6 +841,7 @@ def load_data_from_meta(
classification_task=True, classification_task=True,
shuffle=True, shuffle=True,
balance=False, balance=False,
feature_transforms=None,
) -> dict: ) -> dict:
"""导入语音数据,并返回numpy打包train/test dataset相关属性的ndarray类型 """导入语音数据,并返回numpy打包train/test dataset相关属性的ndarray类型
如果只想提取train/test dataset中的一方,那么另一方就传None(或者不传对应参数) 如果只想提取train/test dataset中的一方,那么另一方就传None(或者不传对应参数)
...@@ -766,6 +876,7 @@ def load_data_from_meta( ...@@ -766,6 +876,7 @@ def load_data_from_meta(
balance=balance, balance=balance,
shuffle=shuffle, shuffle=shuffle,
verbose=True, verbose=True,
feature_transforms_dict=feature_transforms,
) )
# print(test_meta_files, "@{test_meta_files} in load_data_from_meta") # print(test_meta_files, "@{test_meta_files} in load_data_from_meta")
...@@ -776,8 +887,7 @@ def load_data_from_meta( ...@@ -776,8 +887,7 @@ def load_data_from_meta(
) )
# Loads testing data # Loads testing data
ae.load_data_preprocessing( ae.load_data_preprocessing(
meta_files=test_meta_files, partition="test", meta_files=test_meta_files, partition="test", shuffle=shuffle
shuffle=shuffle
) )
# 以train集为例检查self属性 # 以train集为例检查self属性
...@@ -793,13 +903,17 @@ def load_data_from_meta( ...@@ -793,13 +903,17 @@ def load_data_from_meta(
"y_test": np.array(ae.test_emotions), "y_test": np.array(ae.test_emotions),
"train_audio_paths": np.array(ae.train_audio_paths), "train_audio_paths": np.array(ae.train_audio_paths),
"test_audio_paths": np.array(ae.test_audio_paths), "test_audio_paths": np.array(ae.test_audio_paths),
"balance": ae.balance,#反馈是否顺利执行了balance "balance": ae.balance, # 反馈是否顺利执行了balance
"ae": ae, "ae": ae,
} }
if __name__ == "__main__": if __name__ == "__main__":
ae = AudioExtractor(f_config=f_config_def,shuffle=True) ftd = dict(std_scaler=False, pca=dict(n_components=39))
ae = AudioExtractor(
e_config=e_config_def,
f_config=f_config_def, shuffle=True, feature_transforms_dict=ftd
)
print(ae) print(ae)
ae._extract_feature_in_meta(meta_path=train_emodb_csv) ae._extract_feature_in_meta(meta_path=train_emodb_csv)
......
...@@ -12,27 +12,30 @@ AVAILABLE_EMOTIONS = { ...@@ -12,27 +12,30 @@ AVAILABLE_EMOTIONS = {
"angry", "angry",
"fear", "fear",
"disgust", "disgust",
"ps", # pleasant surprised "ps", # pleasant surprised
"boredom", "boredom",
"others" "others",
} }
#deprecated
def get_f_config_dict(features_list)->dict[str,bool]:
# deprecated
def get_f_config_dict(features_list) -> dict[str, bool]:
""" """
解析features_list中的特征,并检查特征要求是否在识别计划内 解析features_list中的特征,并检查特征要求是否在识别计划内
Converts a list of features into a dictionary understandable by Converts a list of features into a dictionary understandable by
`data_extractor.AudioExtractor` class `data_extractor.AudioExtractor` class
返回值:一个bool字典,对各种特征的开关 返回值:一个bool字典,对各种特征的开关
""" """
#计划最多提取5种,默认不提取任何一种 # 计划最多提取5种,默认不提取任何一种
# f_config_default = {'mfcc': False, 'chroma': False, 'mel': False, 'contrast': False, 'tonnetz': False} # f_config_default = {'mfcc': False, 'chroma': False, 'mel': False, 'contrast': False, 'tonnetz': False}
f_config={} f_config = {}
for feature in features_list: for feature in features_list:
validate_feature(feature) validate_feature(feature)
# 将提出的合法特征的提取请求修改为True # 将提出的合法特征的提取请求修改为True
f_config[feature] = True f_config[feature] = True
return f_config return f_config
def validate_feature(feature): def validate_feature(feature):
"""验证特征feature是否是合法的(单个特征验证) """验证特征feature是否是合法的(单个特征验证)
...@@ -47,18 +50,21 @@ def validate_feature(feature): ...@@ -47,18 +50,21 @@ def validate_feature(feature):
特征字符串不可识别 特征字符串不可识别
""" """
if feature not in ava_features: if feature not in ava_features:
raise TypeError(f"Feature passed: {feature} is not recognized.only features in {ava_features} are supported!") raise TypeError(
f"Feature passed: {feature} is not recognized.only features in {ava_features} are supported!"
)
def validate_emotions(emotions,Noneable=False):
def validate_emotions(emotions, Noneable=False):
"""验证emotions参数是否都是有效的情感标签 """验证emotions参数是否都是有效的情感标签
注意这里也排查emotions是否为空的情况 注意这里也排查emotions是否为空的情况
params params
- -
emotions:list[str] emotions:list[str]
Note Note
- -
粗糙的实现 粗糙的实现
if(set(emotions)<=set(ava_emotions)): if(set(emotions)<=set(ava_emotions)):
return True return True
...@@ -74,25 +80,26 @@ def validate_emotions(emotions,Noneable=False): ...@@ -74,25 +80,26 @@ def validate_emotions(emotions,Noneable=False):
if emotions is None and Noneable == False: if emotions is None and Noneable == False:
raise TypeError("Emotions is None!🎈") raise TypeError("Emotions is None!🎈")
# 提供对单个情感字符串的支持(包装为list) # 提供对单个情感字符串的支持(包装为list)
if isinstance(emotions,str): if isinstance(emotions, str):
emotions=[emotions] emotions = [emotions]
# print(emotions) # print(emotions)
for e in emotions: for e in emotions:
if e not in ava_emotions: if e not in ava_emotions:
raise TypeError(f"Emotion passed: {e} is not recognized.") raise TypeError(f"Emotion passed: {e} is not recognized.")
return emotions return emotions
# 预设特征组合 # 预设特征组合
ava_features = ["mfcc", "chroma", "mel", "contrast", "tonnetz"] ava_features = ["mfcc", "chroma", "mel", "contrast", "tonnetz"]
mfcc,chroma,mel,contrast,tonnetz=ava_features mfcc, chroma, mel, contrast, tonnetz = ava_features
ava_emotions=sorted(list(AVAILABLE_EMOTIONS)) ava_emotions = sorted(list(AVAILABLE_EMOTIONS))
# #最基础的3情感组合 # #最基础的3情感组合
MCM = ["mfcc", "chroma", "mel"] MCM = ["mfcc", "chroma", "mel"]
MCM_dict = get_f_config_dict(MCM) MCM_dict = get_f_config_dict(MCM)
# 预设情感组合 # 预设情感组合
HNS = ["sad", "neutral", "happy"] HNS = ["sad", "neutral", "happy"]
AHNPS = ["sad", "neutral", "happy", "ps", "angry"] AHNPS = ["sad", "neutral", "happy", "ps", "angry"]
emotions_extend_dict={e[0].upper():e for e in ava_emotions} emotions_extend_dict = {e[0].upper(): e for e in ava_emotions}
HNS_dict = {"sad": 1, "neutral": 2, "happy": 3} HNS_dict = {"sad": 1, "neutral": 2, "happy": 3}
AHNPS_dict = {"angry": 1, "sad": 2, "neutral": 3, "ps": 4, "happy": 5} AHNPS_dict = {"angry": 1, "sad": 2, "neutral": 3, "ps": 4, "happy": 5}
# 语料库的标签对应关系 # 语料库的标签对应关系
...@@ -104,42 +111,50 @@ categories_emodb = { ...@@ -104,42 +111,50 @@ categories_emodb = {
"A": "fear", "A": "fear",
"F": "happy", "F": "happy",
"T": "sad", "T": "sad",
"N": "neutral" "N": "neutral",
} }
# The letters 'a', 'd', 'f', 'h', 'n', 'sa' and 'su' represent 'anger', 'disgust', 'fear', 'happiness', 'neutral', 'sadness' and 'surprise' emotion classes respectively. # The letters 'a', 'd', 'f', 'h', 'n', 'sa' and 'su' represent 'anger', 'disgust', 'fear', 'happiness', 'neutral', 'sadness' and 'surprise' emotion classes respectively.
#为了和其他库标签接轨,这里需要将名词转换为形容词(也可以将其他库的形若词转为名词) # 为了和其他库标签接轨,这里需要将名词转换为形容词(也可以将其他库的形若词转为名词)
categories_savee={ categories_savee = {
'a':'angry', "a": "angry",
'h':'happy', "h": "happy",
'n':'neutral', "n": "neutral",
'sa':'sad', "sa": "sad",
'su':'surprise',#和ps(PleasantSurprise)相关但是有一定区别 "su": "surprise", # 和ps(PleasantSurprise)相关但是有一定区别
'd':'disgust', "d": "disgust",
'f':'fear', "f": "fear",
} }
# 配置当前(默认变量) # 配置当前(默认变量)
f_config_def = MCM f_config_def = MCM
e_config_def = HNS e_config_def = HNS
ava_algorithms = ['BEST_ML_MODEL', 'SVC', 'RandomForestClassifier', 'MLPClassifier', 'KNeighborsClassifier','BaggingClassifier','GradientBoostingClassifier','RNN'] ava_algorithms = [
"BEST_ML_MODEL",
"SVC",
"RandomForestClassifier",
"MLPClassifier",
"KNeighborsClassifier",
"BaggingClassifier",
"GradientBoostingClassifier",
"RNN",
]
ava_svd_solver = ["auto", "full", "arpack", "randomized"]
# #
def extend_emotion_names(emotion_first_letters): def extend_emotion_names(emotion_first_letters):
emotion_first_letters=emotion_first_letters.upper() emotion_first_letters = emotion_first_letters.upper()
res=[emotions_extend_dict.get(e) for e in emotion_first_letters] res = [emotions_extend_dict.get(e) for e in emotion_first_letters]
return res return res
if __name__ == "__main__":
if __name__=="__main__":
# res=extend_names("HNS") # res=extend_names("HNS")
# print(res) # print(res)
res=get_f_config_dict(f_config_def) res = get_f_config_dict(f_config_def)
print(res) print(res)
# layout=[ # layout=[
# [sg.T(f"chose the db for {train}:")],[sg.LB(values=ava_dbs,size=(15,5))] # [sg.T(f"chose the db for {train}:")],[sg.LB(values=ava_dbs,size=(15,5))]
# ] # ]
## ##
import collections import collections
import json
from pathlib import Path from pathlib import Path
from typing import List from typing import List
from glob import glob from glob import glob
...@@ -53,13 +54,14 @@ ava_dbs: list[str] = [emodb, ravdess, savee] ...@@ -53,13 +54,14 @@ ava_dbs: list[str] = [emodb, ravdess, savee]
# !模型超参数路径 # !模型超参数路径
bclf1 = "bclf.joblib" bclf1 = "bclf.joblib"
brgr1 = "brgr.joblib" brgr1 = "brgr.joblib"
bclf2 = "bclf_u1.joblib" bclf2 = "bclf_v2.joblib"
brgr2 = "bclf_u1.joblib" brgr2 = "bclf_v2.joblib"
# bclf = bclf1 # bclf = bclf1
# brgr = brgr1 # brgr = brgr1
# 通过字典选取超参数版本(组合) # 通过字典选取超参数版本(组合)
cuple_dict = dict(c1=(bclf1, brgr1), c2=(bclf2, brgr2)) cuple_dict = dict(c1=(bclf1, brgr1), c2=(bclf2, brgr2))
bclf, brgr = cuple_dict["c1"] bclf, brgr = cuple_dict["c2"]
# 补齐具体路径 # 补齐具体路径
bclf, brgr = [grid_dir / item for item in (bclf, brgr)] bclf, brgr = [grid_dir / item for item in (bclf, brgr)]
...@@ -145,12 +147,35 @@ def get_first_letters(emotions) -> str: ...@@ -145,12 +147,35 @@ def get_first_letters(emotions) -> str:
需要注意的是,如果emotions参数为空列表,则该函数将返回一个空字符串。此外,由于该函数只考虑每个标签的首字母,因此如果存在两个标签具有相同的首字母,则它们将在结果字符串中出现在一起。 需要注意的是,如果emotions参数为空列表,则该函数将返回一个空字符串。此外,由于该函数只考虑每个标签的首字母,因此如果存在两个标签具有相同的首字母,则它们将在结果字符串中出现在一起。
""" """
# if validate_emotions(emotions):
res = "" res = ""
if validate_emotions(emotions): if emotions is not None:
res = "".join(sorted([e[0].upper() for e in emotions])) res = "".join(sorted([e[0].upper() for e in emotions]))
return res return res
def dict_to_filetag(d):
# Convert dictionary to JSON string
json_str = json.dumps(d)
remove_chars=['"',' ']
for c in remove_chars:
json_str=json_str.replace(c,'')
# Replace invalid characters with hyphen
rep_dict={
":":"=",
# '"':'',
# "'":""
}
for char in json_str:
if rep_dict.get(char):
json_str = json_str.replace(char, rep_dict[char])
# Truncate string if too long
# max_len = 260
# if len(json_str) > max_len:
# json_str = json_str[:max_len]
# json_str=json_str.
return json_str
##
def create_tag_name( def create_tag_name(
db="", db="",
partition="", partition="",
...@@ -180,8 +205,14 @@ def create_tag_name( ...@@ -180,8 +205,14 @@ def create_tag_name(
>>> MCM=['chroma', 'mel', 'mfcc'] >>> MCM=['chroma', 'mel', 'mfcc']
>>> create_tag_name(emodb,f_config=MCM,n_samples=7,ext="npy") >>> create_tag_name(emodb,f_config=MCM,n_samples=7,ext="npy")
>>> 'emodb_chroma-mel-mfcc_7_npy' >>> 'emodb_chroma-mel-mfcc_7_npy'
-
Returns >>> MCM=['chroma', 'mel', 'mfcc']
>>> create_tag_name(emodb,f_config=MCM,n_samples=7,ext="npy",std_scaler=True,pca={"n_components":3,"svd_solver":"full"})
>>> 'emodb_chroma-mel-mfcc_7_@std_scaler=True_@pca={n_components=3,svd_solver=full}.npy'
-
>>> create_tag_name(emodb,f_config=MCM,n_samples=7,ext="npy",std_scaler=False,pca={"n_components":4})
>>> 'emodb_chroma-mel-mfcc_7_@pca={n_components=4}.npy'
------- -------
str str
构造好的文件名 构造好的文件名
...@@ -191,23 +222,31 @@ def create_tag_name( ...@@ -191,23 +222,31 @@ def create_tag_name(
emotions = get_first_letters(e_config) emotions = get_first_letters(e_config)
# partition = tag_field(partition)
# emotions = tag_field(emotions)
# features = tag_field(features)
# n_samples=tag_field(str(n_samples))
# bool("")#False
# bool(None)#False
# res = f"{partition}{emotions}{features}{db}{n_samples}.{ext}"
# str(None)#'None'
n_samples = str(n_samples) if n_samples else "" n_samples = str(n_samples) if n_samples else ""
# 如果是用来生成特征提取的文件名,可能需要加上额外的信息: # 如果是用来生成特征提取的文件名,可能需要加上额外的信息:
balance = "balanced" if balance else "" balance = "balanced" if balance else ""
shuffle = "shuffled" if shuffle else "" shuffle = "shuffled" if shuffle else ""
# other_tags=[f"@{key}={value}" for key,value in kwargs.items()]
other_tags=[]
for key,value in kwargs.items():
# print(key,value)
# 这里将开关为False的参数不显示
#但这个方案并不完美,有些参数默认是True,反而False才更应该显示
# 但目前本项目当开关为True是才显示
if isinstance(value,bool) :
if value==False:
continue
if isinstance(value,dict):
# print('value: ', value)
if value=={}:
# print("value is empty")
continue
value=dict_to_filetag(value)
other_tags.append(f"@{key}={value}")
fields = [partition, db, features, emotions, n_samples]+other_tags
fields = [partition, db, features, emotions, n_samples]
# print("{fields:}")
# print(fields)
# return
true_fields = [f for f in fields if f] # 标识非空的值 true_fields = [f for f in fields if f] # 标识非空的值
# print(true_fields,"@{true_fields}") # print(true_fields,"@{true_fields}")
res = "_".join(true_fields) + f".{ext}" res = "_".join(true_fields) + f".{ext}"
......
语音情感识别是指利用计算机技术分析人类语音中所表达的情感状态,如高兴、悲伤、愤怒等。语音情感识别在人机交互、智能客服、心理健康等领域有着广泛的应用价值和市场需求。然而,目前的语音情感识别系统面临着一个重要的挑战,即跨库问题。跨库问题是指不同的语音数据库之间存在着标注不一致、说话人差异、录制环境变化等因素,导致训练和测试数据分布不匹配,从而影响了模型的泛化能力和实际效果。为了解决这一问题,本文旨在设计和开发一个跨库语音情感识别系统,利用若干浅层机器学习算法和深度学习算法等方法进行跨库语音情感识别系统的设计与开发
通过该课题的学习和研究,本文分析当前已有的传统语音情感识别和跨库语音情感识别算法的发展状况和存在的问题,设计并实现了一个可以进行跨库语音情感识别的系统应用。
该应用用基于Python的GUI框架进行开发,具有较为丰富的可操作性
\ No newline at end of file
{
"cells": [
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"# feature=np.load(r\"D:\\repos\\CCSER\\SER\\features\\emodb_chroma-mel-mfcc_ANOS_107.npy\")\n",
"feature=np.load(r\"emodb_chroma-mel-mfcc_ANOS_107_@pca_params={n_components=35,svd_solver=auto}.npy\")"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(107, 35)"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#第shape[1]就是pca降维后的维数\n",
"feature.shape"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"emodb_chroma-mel-mfcc_ANOS_107_@pca_params={n_components=35,svd_solver=auto}.npy\n",
"emodb_chroma-mel-mfcc_ANOS_107_@pca_params={n_components=None,svd_solver=auto}.npy\n",
"emodb_chroma-mel-mfcc_ANOS_107_@pca_params={n_components=mle,svd_solver=auto}.npy\n",
"emodb_chroma-mel-mfcc_ANOS_428_@pca_params={n_components=35,svd_solver=auto}.npy\n",
"emodb_chroma-mel-mfcc_ANOS_428_@pca_params={n_components=None,svd_solver=auto}.npy\n",
"emodb_chroma-mel-mfcc_ANOS_428_@pca_params={n_components=mle,svd_solver=auto}.npy\n",
"emodb_chroma-mel-mfcc_HNS_169_@pca={n_components=39}.npy\n",
"emodb_mfcc_ANOS_107_@pca={n_components=30}.npy\n",
"emodb_mfcc_ANOS_107_@pca={n_components=mle}.npy\n",
"emodb_mfcc_ANOS_107_@pca_params={n_components=25,svd_solver=auto}.npy\n",
"emodb_mfcc_ANOS_107_@pca_params={n_components=31,svd_solver=auto}.npy\n",
"emodb_mfcc_ANOS_107_@pca_params={n_components=35,svd_solver=auto}.npy\n",
"emodb_mfcc_ANOS_107_@pca_params={n_components=None,svd_solver=auto}.npy\n",
"emodb_mfcc_ANOS_428_@pca={n_components=30}.npy\n",
"emodb_mfcc_ANOS_428_@pca={n_components=mle}.npy\n",
"emodb_mfcc_ANOS_428_@pca_params={n_components=25,svd_solver=auto}.npy\n",
"emodb_mfcc_ANOS_428_@pca_params={n_components=31,svd_solver=auto}.npy\n",
"emodb_mfcc_ANOS_428_@pca_params={n_components=35,svd_solver=auto}.npy\n",
"emodb_mfcc_ANOS_428_@pca_params={n_components=None,svd_solver=auto}.npy\n",
"emodb_mfcc_AS_151_@pca={n_components=39}.npy\n",
"emodb_mfcc_AS_38_@pca={n_components=39}.npy\n"
]
}
],
"source": [
"!ls *pca*"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"((107, 180), (107, 41))"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from sklearn.datasets import load_digits\n",
"from sklearn.decomposition import PCA\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.neighbors import KNeighborsClassifier\n",
"\n",
"pca=PCA(n_components=41,svd_solver='auto')\n",
"pca.fit(feature)\n",
"feature_pca =pca.transform(feature)\n",
"feature.shape,feature_pca.shape"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"a=[1,2,3]"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"b=a[1]"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"b=3"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1, 2, 3]"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"a"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"load"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "tf2.10",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.16"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}
文件已添加
文件已添加
...@@ -17,7 +17,7 @@ from sklearn.pipeline import Pipeline ...@@ -17,7 +17,7 @@ from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC, SVR from sklearn.svm import SVC, SVR
from utils import dump_pickle_by_name, load_pickle_by_name from utils import dump_pickle_by_name, load_pickle_by_name,now_utc_field_str
...@@ -50,11 +50,20 @@ rf_best=(RandomForestClassifier(max_depth=7, max_features=0.5, n_estimators=40), ...@@ -50,11 +50,20 @@ rf_best=(RandomForestClassifier(max_depth=7, max_features=0.5, n_estimators=40),
gb_best=(GradientBoostingClassifier(learning_rate=0.3, loss='log_loss', max_depth=7, gb_best=(GradientBoostingClassifier(learning_rate=0.3, loss='log_loss', max_depth=7,
subsample=0.7), {'learning_rate': 0.3, 'max_depth': 7, 'max_features': None, 'min_samples_leaf': 1, 'min_samples_split': 2, 'n_estimators': 100, 'subsample': 0.7}, 0.9476937708036139) subsample=0.7), {'learning_rate': 0.3, 'max_depth': 7, 'max_features': None, 'min_samples_leaf': 1, 'min_samples_split': 2, 'n_estimators': 100, 'subsample': 0.7}, 0.9476937708036139)
# bclf[1]=rf_best
# bclf[2]=gb_best
## ##
bclf=load("bclf.joblib")
# bclf[-1] = bag_best # bclf[-1] = bag_best
##
bclf_res=load("bclf.joblib") bclf_res=load("bclf.joblib")
for item in bclf_res: for item in bclf_res:
print(item) print(item)
......
,path,emotion
0,data/emodb/wav\15a02Ta.wav,sad
1,data/emodb/wav\15a04Fd.wav,happy
2,data/emodb/wav\15a04Nc.wav,neutral
3,data/emodb/wav\15a05Fb.wav,happy
4,data/emodb/wav\15a05Na.wav,neutral
5,data/emodb/wav\15a07Fa.wav,happy
6,data/emodb/wav\15a07Fb.wav,happy
7,data/emodb/wav\15a07Nc.wav,neutral
8,data/emodb/wav\15b01Na.wav,neutral
9,data/emodb/wav\15b02Nd.wav,neutral
10,data/emodb/wav\15b02Tc.wav,sad
11,data/emodb/wav\15b03Nb.wav,neutral
12,data/emodb/wav\15b03Tc.wav,sad
13,data/emodb/wav\15b09Fa.wav,happy
14,data/emodb/wav\15b09Nb.wav,neutral
15,data/emodb/wav\15b09Ta.wav,sad
16,data/emodb/wav\15b10Nb.wav,neutral
17,data/emodb/wav\15b10Nc.wav,neutral
18,data/emodb/wav\16a01Fc.wav,happy
19,data/emodb/wav\16a01Nc.wav,neutral
20,data/emodb/wav\16a01Tb.wav,sad
21,data/emodb/wav\16a02Nb.wav,neutral
22,data/emodb/wav\16a02Tc.wav,sad
23,data/emodb/wav\16a04Fa.wav,happy
24,data/emodb/wav\16a04Nc.wav,neutral
25,data/emodb/wav\16a04Tc.wav,sad
26,data/emodb/wav\16a05Fc.wav,happy
27,data/emodb/wav\16a05Tb.wav,sad
28,data/emodb/wav\16a07Fa.wav,happy
29,data/emodb/wav\16a07Fb.wav,happy
30,data/emodb/wav\16a07Nb.wav,neutral
31,data/emodb/wav\16a07Td.wav,sad
32,data/emodb/wav\16b01Fa.wav,happy
33,data/emodb/wav\16b01Tb.wav,sad
34,data/emodb/wav\16b02Fd.wav,happy
35,data/emodb/wav\16b03Fa.wav,happy
36,data/emodb/wav\16b03Fd.wav,happy
37,data/emodb/wav\16b03Nb.wav,neutral
38,data/emodb/wav\16b03Ta.wav,sad
39,data/emodb/wav\16b09Fb.wav,happy
40,data/emodb/wav\16b10Fb.wav,happy
41,data/emodb/wav\16b10Tb.wav,sad
42,data/emodb/wav\16b10Td.wav,sad
此差异已折叠。
,path,emotion
0,data/emodb/wav\03a01Fa.wav,happy
1,data/emodb/wav\03a01Nc.wav,neutral
2,data/emodb/wav\03a02Fc.wav,happy
3,data/emodb/wav\03a02Nc.wav,neutral
4,data/emodb/wav\03a02Ta.wav,sad
5,data/emodb/wav\03a04Fd.wav,happy
6,data/emodb/wav\03a04Nc.wav,neutral
7,data/emodb/wav\03a04Ta.wav,sad
8,data/emodb/wav\03a05Fc.wav,happy
9,data/emodb/wav\03a05Nd.wav,neutral
10,data/emodb/wav\03a05Tc.wav,sad
11,data/emodb/wav\03a07Fa.wav,happy
12,data/emodb/wav\03a07Fb.wav,happy
13,data/emodb/wav\03a07Nc.wav,neutral
14,data/emodb/wav\03b01Fa.wav,happy
15,data/emodb/wav\03b01Nb.wav,neutral
16,data/emodb/wav\03b01Td.wav,sad
17,data/emodb/wav\03b02Na.wav,neutral
18,data/emodb/wav\03b02Tb.wav,sad
19,data/emodb/wav\03b03Nb.wav,neutral
20,data/emodb/wav\03b03Tc.wav,sad
21,data/emodb/wav\03b09Nc.wav,neutral
22,data/emodb/wav\03b09Tc.wav,sad
23,data/emodb/wav\03b10Na.wav,neutral
24,data/emodb/wav\03b10Nc.wav,neutral
25,data/emodb/wav\08a01Fd.wav,happy
26,data/emodb/wav\08a01Na.wav,neutral
27,data/emodb/wav\08a02Fe.wav,happy
28,data/emodb/wav\08a02Na.wav,neutral
29,data/emodb/wav\08a02Tb.wav,sad
30,data/emodb/wav\08a04Ff.wav,happy
31,data/emodb/wav\08a04Nc.wav,neutral
32,data/emodb/wav\08a04Tb.wav,sad
33,data/emodb/wav\08a05Fe.wav,happy
34,data/emodb/wav\08a05Nb.wav,neutral
35,data/emodb/wav\08a05Ta.wav,sad
36,data/emodb/wav\08a07Fd.wav,happy
37,data/emodb/wav\08a07Na.wav,neutral
38,data/emodb/wav\08a07Ta.wav,sad
39,data/emodb/wav\08a07Tb.wav,sad
40,data/emodb/wav\08b01Fd.wav,happy
41,data/emodb/wav\08b01Fe.wav,happy
42,data/emodb/wav\08b01Na.wav,neutral
43,data/emodb/wav\08b02Ff.wav,happy
44,data/emodb/wav\08b02Nb.wav,neutral
45,data/emodb/wav\08b02Tc.wav,sad
46,data/emodb/wav\08b03Fe.wav,happy
47,data/emodb/wav\08b03Nb.wav,neutral
48,data/emodb/wav\08b03Tc.wav,sad
49,data/emodb/wav\08b09Fd.wav,happy
50,data/emodb/wav\08b09Nb.wav,neutral
51,data/emodb/wav\08b09Tb.wav,sad
52,data/emodb/wav\08b10Fd.wav,happy
53,data/emodb/wav\08b10Nc.wav,neutral
54,data/emodb/wav\08b10Tc.wav,sad
55,data/emodb/wav\09a01Fa.wav,happy
56,data/emodb/wav\09a01Nb.wav,neutral
57,data/emodb/wav\09a04Fd.wav,happy
58,data/emodb/wav\09a04Nb.wav,neutral
59,data/emodb/wav\09a05Nb.wav,neutral
60,data/emodb/wav\09a05Tb.wav,sad
61,data/emodb/wav\09a07Na.wav,neutral
62,data/emodb/wav\09a07Ta.wav,sad
63,data/emodb/wav\09b01Na.wav,neutral
64,data/emodb/wav\09b02Na.wav,neutral
65,data/emodb/wav\09b02Tb.wav,sad
66,data/emodb/wav\09b03Fa.wav,happy
67,data/emodb/wav\09b03Fd.wav,happy
68,data/emodb/wav\09b03Nb.wav,neutral
69,data/emodb/wav\09b03Ta.wav,sad
70,data/emodb/wav\09b09Nd.wav,neutral
71,data/emodb/wav\09b10Nd.wav,neutral
72,data/emodb/wav\10a01Nb.wav,neutral
73,data/emodb/wav\10a02Fa.wav,happy
74,data/emodb/wav\10a02Na.wav,neutral
75,data/emodb/wav\10a04Fd.wav,happy
76,data/emodb/wav\10a04Nb.wav,neutral
77,data/emodb/wav\10a05Tb.wav,sad
78,data/emodb/wav\10a07Ta.wav,sad
79,data/emodb/wav\10b01Fa.wav,happy
80,data/emodb/wav\10b02Na.wav,neutral
81,data/emodb/wav\10b03Tb.wav,sad
82,data/emodb/wav\10b10Fc.wav,happy
83,data/emodb/wav\11a01Nd.wav,neutral
84,data/emodb/wav\11a02Fb.wav,happy
85,data/emodb/wav\11a02Nc.wav,neutral
86,data/emodb/wav\11a02Tc.wav,sad
87,data/emodb/wav\11a04Fd.wav,happy
88,data/emodb/wav\11a04Nd.wav,neutral
89,data/emodb/wav\11a05Fb.wav,happy
90,data/emodb/wav\11a05Fc.wav,happy
91,data/emodb/wav\11a05Na.wav,neutral
92,data/emodb/wav\11a05Td.wav,sad
93,data/emodb/wav\11a07Ta.wav,sad
94,data/emodb/wav\11b01Fc.wav,happy
95,data/emodb/wav\11b01Nc.wav,neutral
96,data/emodb/wav\11b02Fd.wav,happy
97,data/emodb/wav\11b02Na.wav,neutral
98,data/emodb/wav\11b02Td.wav,sad
99,data/emodb/wav\11b03Fc.wav,happy
100,data/emodb/wav\11b03Nb.wav,neutral
101,data/emodb/wav\11b03Td.wav,sad
102,data/emodb/wav\11b09Fd.wav,happy
103,data/emodb/wav\11b09Na.wav,neutral
104,data/emodb/wav\11b09Td.wav,sad
105,data/emodb/wav\11b10Nc.wav,neutral
106,data/emodb/wav\11b10Td.wav,sad
107,data/emodb/wav\12a01Fb.wav,happy
108,data/emodb/wav\12a01Nb.wav,neutral
109,data/emodb/wav\12a02Nb.wav,neutral
110,data/emodb/wav\12a05Nd.wav,neutral
111,data/emodb/wav\12a05Ta.wav,sad
112,data/emodb/wav\12b01Ta.wav,sad
113,data/emodb/wav\12b02Fb.wav,happy
114,data/emodb/wav\12b02Na.wav,neutral
115,data/emodb/wav\12b03Ta.wav,sad
116,data/emodb/wav\12b09Td.wav,sad
117,data/emodb/wav\13a01Fd.wav,happy
118,data/emodb/wav\13a01Nb.wav,neutral
119,data/emodb/wav\13a02Fa.wav,happy
120,data/emodb/wav\13a02Nc.wav,neutral
121,data/emodb/wav\13a02Ta.wav,sad
122,data/emodb/wav\13a04Fc.wav,happy
123,data/emodb/wav\13a04Ta.wav,sad
124,data/emodb/wav\13a05Nb.wav,neutral
125,data/emodb/wav\13a05Tc.wav,sad
126,data/emodb/wav\13a07Fd.wav,happy
127,data/emodb/wav\13a07Na.wav,neutral
128,data/emodb/wav\13a07Tc.wav,sad
129,data/emodb/wav\13b01Fc.wav,happy
130,data/emodb/wav\13b01Nc.wav,neutral
131,data/emodb/wav\13b02Fb.wav,happy
132,data/emodb/wav\13b02Nb.wav,neutral
133,data/emodb/wav\13b03Fd.wav,happy
134,data/emodb/wav\13b03Na.wav,neutral
135,data/emodb/wav\13b03Td.wav,sad
136,data/emodb/wav\13b09Fb.wav,happy
137,data/emodb/wav\13b09Fc.wav,happy
138,data/emodb/wav\13b09Na.wav,neutral
139,data/emodb/wav\13b10Fa.wav,happy
140,data/emodb/wav\13b10Nc.wav,neutral
141,data/emodb/wav\14a01Na.wav,neutral
142,data/emodb/wav\14a02Fd.wav,happy
143,data/emodb/wav\14a02Nc.wav,neutral
144,data/emodb/wav\14a02Tb.wav,sad
145,data/emodb/wav\14a04Tb.wav,sad
146,data/emodb/wav\14a04Tc.wav,sad
147,data/emodb/wav\14a05Fa.wav,happy
148,data/emodb/wav\14a05Fb.wav,happy
149,data/emodb/wav\14a05Na.wav,neutral
150,data/emodb/wav\14a05Ta.wav,sad
151,data/emodb/wav\14a05Tc.wav,sad
152,data/emodb/wav\14a07Fd.wav,happy
153,data/emodb/wav\14a07Na.wav,neutral
154,data/emodb/wav\14a07Tc.wav,sad
155,data/emodb/wav\14b01Fa.wav,happy
156,data/emodb/wav\14b01Fc.wav,happy
157,data/emodb/wav\14b01Na.wav,neutral
158,data/emodb/wav\14b02Fb.wav,happy
159,data/emodb/wav\14b02Na.wav,neutral
160,data/emodb/wav\14b02Tc.wav,sad
161,data/emodb/wav\14b03Ta.wav,sad
162,data/emodb/wav\14b09Fc.wav,happy
163,data/emodb/wav\14b09Td.wav,sad
164,data/emodb/wav\14b10Nb.wav,neutral
165,data/emodb/wav\14b10Tc.wav,sad
166,data/emodb/wav\15a01Fb.wav,happy
167,data/emodb/wav\15a01Nb.wav,neutral
168,data/emodb/wav\15a02Na.wav,neutral
此差异已折叠。
,path,emotion ,path,emotion
45,D:\repos\CCSER\SER\data\savee\AudioData\DC\h01.wav,happy 415,D:\repos\CCSER\SER\data\savee\AudioData\KL\h11.wav,happy
57,D:\repos\CCSER\SER\data\savee\AudioData\DC\h13.wav,happy 53,D:\repos\CCSER\SER\data\savee\AudioData\DC\h09.wav,happy
171,D:\repos\CCSER\SER\data\savee\AudioData\JE\h07.wav,happy 405,D:\repos\CCSER\SER\data\savee\AudioData\KL\h01.wav,happy
169,D:\repos\CCSER\SER\data\savee\AudioData\JE\h05.wav,happy 417,D:\repos\CCSER\SER\data\savee\AudioData\KL\h13.wav,happy
50,D:\repos\CCSER\SER\data\savee\AudioData\DC\h06.wav,happy 412,D:\repos\CCSER\SER\data\savee\AudioData\KL\h08.wav,happy
54,D:\repos\CCSER\SER\data\savee\AudioData\DC\h10.wav,happy 287,D:\repos\CCSER\SER\data\savee\AudioData\JK\h03.wav,happy
49,D:\repos\CCSER\SER\data\savee\AudioData\DC\h05.wav,happy
286,D:\repos\CCSER\SER\data\savee\AudioData\JK\h02.wav,happy
177,D:\repos\CCSER\SER\data\savee\AudioData\JE\h13.wav,happy
172,D:\repos\CCSER\SER\data\savee\AudioData\JE\h08.wav,happy
175,D:\repos\CCSER\SER\data\savee\AudioData\JE\h11.wav,happy 175,D:\repos\CCSER\SER\data\savee\AudioData\JE\h11.wav,happy
293,D:\repos\CCSER\SER\data\savee\AudioData\JK\h09.wav,happy
176,D:\repos\CCSER\SER\data\savee\AudioData\JE\h12.wav,happy
168,D:\repos\CCSER\SER\data\savee\AudioData\JE\h04.wav,happy
295,D:\repos\CCSER\SER\data\savee\AudioData\JK\h11.wav,happy
177,D:\repos\CCSER\SER\data\savee\AudioData\JE\h13.wav,happy
294,D:\repos\CCSER\SER\data\savee\AudioData\JK\h10.wav,happy
416,D:\repos\CCSER\SER\data\savee\AudioData\KL\h12.wav,happy
68,D:\repos\CCSER\SER\data\savee\AudioData\DC\n09.wav,neutral
423,D:\repos\CCSER\SER\data\savee\AudioData\KL\n04.wav,neutral
203,D:\repos\CCSER\SER\data\savee\AudioData\JE\n24.wav,neutral
72,D:\repos\CCSER\SER\data\savee\AudioData\DC\n13.wav,neutral
78,D:\repos\CCSER\SER\data\savee\AudioData\DC\n19.wav,neutral
426,D:\repos\CCSER\SER\data\savee\AudioData\KL\n07.wav,neutral
431,D:\repos\CCSER\SER\data\savee\AudioData\KL\n12.wav,neutral
321,D:\repos\CCSER\SER\data\savee\AudioData\JK\n22.wav,neutral
88,D:\repos\CCSER\SER\data\savee\AudioData\DC\n29.wav,neutral
180,D:\repos\CCSER\SER\data\savee\AudioData\JE\n01.wav,neutral
186,D:\repos\CCSER\SER\data\savee\AudioData\JE\n07.wav,neutral
440,D:\repos\CCSER\SER\data\savee\AudioData\KL\n21.wav,neutral
447,D:\repos\CCSER\SER\data\savee\AudioData\KL\n28.wav,neutral 447,D:\repos\CCSER\SER\data\savee\AudioData\KL\n28.wav,neutral
195,D:\repos\CCSER\SER\data\savee\AudioData\JE\n16.wav,neutral
443,D:\repos\CCSER\SER\data\savee\AudioData\KL\n24.wav,neutral
302,D:\repos\CCSER\SER\data\savee\AudioData\JK\n03.wav,neutral
300,D:\repos\CCSER\SER\data\savee\AudioData\JK\n01.wav,neutral
324,D:\repos\CCSER\SER\data\savee\AudioData\JK\n25.wav,neutral
204,D:\repos\CCSER\SER\data\savee\AudioData\JE\n25.wav,neutral
70,D:\repos\CCSER\SER\data\savee\AudioData\DC\n11.wav,neutral
60,D:\repos\CCSER\SER\data\savee\AudioData\DC\n01.wav,neutral
424,D:\repos\CCSER\SER\data\savee\AudioData\KL\n05.wav,neutral
305,D:\repos\CCSER\SER\data\savee\AudioData\JK\n06.wav,neutral 305,D:\repos\CCSER\SER\data\savee\AudioData\JK\n06.wav,neutral
318,D:\repos\CCSER\SER\data\savee\AudioData\JK\n19.wav,neutral 207,D:\repos\CCSER\SER\data\savee\AudioData\JE\n28.wav,neutral
202,D:\repos\CCSER\SER\data\savee\AudioData\JE\n23.wav,neutral
429,D:\repos\CCSER\SER\data\savee\AudioData\KL\n10.wav,neutral
184,D:\repos\CCSER\SER\data\savee\AudioData\JE\n05.wav,neutral
304,D:\repos\CCSER\SER\data\savee\AudioData\JK\n05.wav,neutral 304,D:\repos\CCSER\SER\data\savee\AudioData\JK\n05.wav,neutral
65,D:\repos\CCSER\SER\data\savee\AudioData\DC\n06.wav,neutral 199,D:\repos\CCSER\SER\data\savee\AudioData\JE\n20.wav,neutral
84,D:\repos\CCSER\SER\data\savee\AudioData\DC\n25.wav,neutral
445,D:\repos\CCSER\SER\data\savee\AudioData\KL\n26.wav,neutral 445,D:\repos\CCSER\SER\data\savee\AudioData\KL\n26.wav,neutral
329,D:\repos\CCSER\SER\data\savee\AudioData\JK\n30.wav,neutral
322,D:\repos\CCSER\SER\data\savee\AudioData\JK\n23.wav,neutral 322,D:\repos\CCSER\SER\data\savee\AudioData\JK\n23.wav,neutral
86,D:\repos\CCSER\SER\data\savee\AudioData\DC\n27.wav,neutral 220,D:\repos\CCSER\SER\data\savee\AudioData\JE\sa11.wav,sad
188,D:\repos\CCSER\SER\data\savee\AudioData\JE\n09.wav,neutral
301,D:\repos\CCSER\SER\data\savee\AudioData\JK\n02.wav,neutral
432,D:\repos\CCSER\SER\data\savee\AudioData\KL\n13.wav,neutral
200,D:\repos\CCSER\SER\data\savee\AudioData\JE\n21.wav,neutral
185,D:\repos\CCSER\SER\data\savee\AudioData\JE\n06.wav,neutral
309,D:\repos\CCSER\SER\data\savee\AudioData\JK\n10.wav,neutral
223,D:\repos\CCSER\SER\data\savee\AudioData\JE\sa14.wav,sad
97,D:\repos\CCSER\SER\data\savee\AudioData\DC\sa08.wav,sad
210,D:\repos\CCSER\SER\data\savee\AudioData\JE\sa01.wav,sad
456,D:\repos\CCSER\SER\data\savee\AudioData\KL\sa07.wav,sad
334,D:\repos\CCSER\SER\data\savee\AudioData\JK\sa05.wav,sad 334,D:\repos\CCSER\SER\data\savee\AudioData\JK\sa05.wav,sad
214,D:\repos\CCSER\SER\data\savee\AudioData\JE\sa05.wav,sad 339,D:\repos\CCSER\SER\data\savee\AudioData\JK\sa10.wav,sad
457,D:\repos\CCSER\SER\data\savee\AudioData\KL\sa08.wav,sad 223,D:\repos\CCSER\SER\data\savee\AudioData\JE\sa14.wav,sad
344,D:\repos\CCSER\SER\data\savee\AudioData\JK\sa15.wav,sad 460,D:\repos\CCSER\SER\data\savee\AudioData\KL\sa11.wav,sad
332,D:\repos\CCSER\SER\data\savee\AudioData\JK\sa03.wav,sad 343,D:\repos\CCSER\SER\data\savee\AudioData\JK\sa14.wav,sad
92,D:\repos\CCSER\SER\data\savee\AudioData\DC\sa03.wav,sad 340,D:\repos\CCSER\SER\data\savee\AudioData\JK\sa11.wav,sad
451,D:\repos\CCSER\SER\data\savee\AudioData\KL\sa02.wav,sad
331,D:\repos\CCSER\SER\data\savee\AudioData\JK\sa02.wav,sad
217,D:\repos\CCSER\SER\data\savee\AudioData\JE\sa08.wav,sad
100,D:\repos\CCSER\SER\data\savee\AudioData\DC\sa11.wav,sad
330,D:\repos\CCSER\SER\data\savee\AudioData\JK\sa01.wav,sad
450,D:\repos\CCSER\SER\data\savee\AudioData\KL\sa01.wav,sad
341,D:\repos\CCSER\SER\data\savee\AudioData\JK\sa12.wav,sad
此差异已折叠。
## ##
# from typing_extensions import deprecated # from typing_extensions import deprecated
from config.MetaPath import test_emodb_csv
import random import random
from time import time from time import time
from config.algoparams import ava_cv_modes from config.algoparams import ava_cv_modes
...@@ -7,40 +8,63 @@ import matplotlib.pyplot as pl ...@@ -7,40 +8,63 @@ import matplotlib.pyplot as pl
import numpy as np import numpy as np
import pandas as pd import pandas as pd
from sklearn.ensemble import RandomForestClassifier from sklearn.ensemble import RandomForestClassifier
# from deprecated import deprecated # from deprecated import deprecated
from sklearn.metrics import (accuracy_score, classification_report, from sklearn.metrics import (
confusion_matrix, fbeta_score, make_scorer, accuracy_score,
mean_absolute_error, mean_squared_error) classification_report,
from sklearn.model_selection import GridSearchCV, KFold, ShuffleSplit, StratifiedShuffleSplit, cross_val_score confusion_matrix,
fbeta_score,
make_scorer,
mean_absolute_error,
mean_squared_error,
)
from sklearn.model_selection import (
GridSearchCV,
KFold,
ShuffleSplit,
StratifiedKFold,
StratifiedShuffleSplit,
cross_val_score,
)
from sklearn.neighbors import KNeighborsClassifier from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC from sklearn.svm import SVC
from tqdm import tqdm from tqdm import tqdm
from audio.extractor import load_data_from_meta from audio.extractor import AudioExtractor, load_data_from_meta
from config.EF import (e_config_def, f_config_def, validate_emotions) from config.EF import e_config_def, f_config_def, validate_emotions
from config.MetaPath import (emodb, meta_paths_of_db, ravdess, savee,validate_partition,project_dir) from config.MetaPath import (
emodb,
meta_paths_of_db,
ravdess,
savee,
validate_partition,
project_dir,
)
import config.MetaPath as meta import config.MetaPath as meta
from audio.core import best_estimators, extract_feature_of_audio from audio.core import best_estimators, extract_feature_of_audio
## ##
class EmotionRecognizer: class EmotionRecognizer:
"""A class for training, testing and predicting emotions based on """A class for training, testing and predicting emotions based on
speech's features that are extracted and fed into `sklearn` or `keras` model""" speech's features that are extracted and fed into `sklearn` or `keras` model"""
def __init__( def __init__(
self, self,
model=None, model=None,
classification_task=True, classification_task=True,
dbs=None, dbs=None,
e_config=None, e_config=None,
f_config=None, f_config=None,
train_dbs=None, train_dbs=None,
test_dbs=None, test_dbs=None,
balance=False, balance=False,
shuffle=True, shuffle=True,
override_csv=True, override_csv=True,
verbose=1, verbose=1,
**kwargs, **feature_transforms,
# **kwargs,
): ):
""" """
Params: Params:
...@@ -98,31 +122,22 @@ class EmotionRecognizer: ...@@ -98,31 +122,22 @@ class EmotionRecognizer:
) )
# print(self.train_meta_files, self.test_meta_files) # print(self.train_meta_files, self.test_meta_files)
self.feature_transforms = (
# if self.train_dbs and self.test_dbs: feature_transforms if feature_transforms else {"std_scaler": False}
# if isinstance( self.train_dbs,str): )
# self.train_dbs = [self.train_dbs]
# self.train_meta_files=[
# meta_paths_of_db(db,e_config=self.e_config) for db in self.train_dbs
# ]
# if isinstance( self.test_dbs,str):
# self.test_dbs = [self.test_dbs]
# self.test_meta_files=[
# meta_paths_of_db(db,e_config=self.e_config) for db in self.test_dbs
# ]
# 可以使用python 默认参数来改造写法 # 可以使用python 默认参数来改造写法
# 默认执行分类任务 # 默认执行分类任务
self.classification_task = classification_task self.classification_task = classification_task
self.balance = balance self.balance = balance
self.shuffle=shuffle self.shuffle = shuffle
self.override_csv = override_csv self.override_csv = override_csv
self.verbose = verbose self.verbose = verbose
# boolean attributes # boolean attributes
self.balance = False self.balance = False
self.data_loaded = False self.data_loaded = False
self.model_trained = False self.model_trained = False
self.ae=None
self.dbs = dbs if dbs else [ravdess] self.dbs = dbs if dbs else [ravdess]
# 鉴于数据集(特征和标签)在评估方法时将反复用到,因此这里将设置相应的属性来保存它们 # 鉴于数据集(特征和标签)在评估方法时将反复用到,因此这里将设置相应的属性来保存它们
# 另一方面,如果模仿sklearn中的编写风格,其实是将数据和模型计算分布在不同的模块(类)中,比如 # 另一方面,如果模仿sklearn中的编写风格,其实是将数据和模型计算分布在不同的模块(类)中,比如
...@@ -158,7 +173,7 @@ class EmotionRecognizer: ...@@ -158,7 +173,7 @@ class EmotionRecognizer:
""" """
# 判断是否已经导入过数据.如果已经导入,则跳过,否则执行导入 # 判断是否已经导入过数据.如果已经导入,则跳过,否则执行导入
if not self.data_loaded: if not self.data_loaded:
# 调用data_extractor中的数据导入函数 # 调用extractor中的数据导入函数
data = load_data_from_meta( data = load_data_from_meta(
train_meta_files=self.train_meta_files, train_meta_files=self.train_meta_files,
test_meta_files=self.test_meta_files, test_meta_files=self.test_meta_files,
...@@ -166,19 +181,24 @@ class EmotionRecognizer: ...@@ -166,19 +181,24 @@ class EmotionRecognizer:
e_config=self.e_config, e_config=self.e_config,
classification_task=self.classification_task, classification_task=self.classification_task,
balance=self.balance, balance=self.balance,
shuffle=self.shuffle shuffle=self.shuffle,
feature_transforms=self.feature_transforms,
) )
# 设置实例的各个属性 # 设置实例的各个属性
# 事实上,也可以直接用load_data_from_meta返回的结果中的ae对象,赋值ER对象(self.ae=data["ae"])
self.ae=data["ae"]
self.X_train = data["X_train"] self.X_train = data["X_train"]
self.X_test = data["X_test"] self.X_test = data["X_test"]
self.y_train = data["y_train"] self.y_train = data["y_train"]
self.y_test = data["y_test"] self.y_test = data["y_test"]
self.train_audio_paths = data["train_audio_paths"] self.train_audio_paths = data["train_audio_paths"]
self.test_audio_paths = data["test_audio_paths"] self.test_audio_paths = data["test_audio_paths"]
self.balanced_success(data) self.balanced_success(data)
if self.verbose: if self.verbose:
print("[I] Data loaded\n") print("[I] Data loaded\n")
print(f"{self.ae=}")
print(f"{self.ae.pca=}🎈")
self.data_loaded = True self.data_loaded = True
# print(id(self)) # print(id(self))
if self.verbose > 1: if self.verbose > 1:
...@@ -197,9 +217,9 @@ class EmotionRecognizer: ...@@ -197,9 +217,9 @@ class EmotionRecognizer:
if not self.data_loaded: if not self.data_loaded:
# if data isn't loaded yet, load it then # if data isn't loaded yet, load it then
self.load_data() self.load_data()
if verbose > 1:
print("@{self.model}:") print("@{self.model}:")
print(self.model) print(self.model)
model = self.model if self.model is not None else self.best_model() model = self.model if self.model is not None else self.best_model()
if not self.model_trained or choosing: if not self.model_trained or choosing:
X_train = self.X_train X_train = self.X_train
...@@ -218,20 +238,35 @@ class EmotionRecognizer: ...@@ -218,20 +238,35 @@ class EmotionRecognizer:
由于是单个音频的情感预测,因此不需要考虑shuffle和balance这些操作,只需要提取语音特征,然后进行调用模型预测即可 由于是单个音频的情感预测,因此不需要考虑shuffle和balance这些操作,只需要提取语音特征,然后进行调用模型预测即可
given an `audio_path`, this method extracts the features given an `audio_path`, this method extracts the features
and predicts the emotion and predicts the emotion
以下语句不再适合具有pca降维操作下的情形
feature_audio = extract_feature_of_audio(audio_path, self.f_config)
print(feature1.shape)
print(feature1,"@{feature1}",feature1.shape)
feature2=feature1.T
print(feature2,"@{feature2}",feature2.shape)
print(feature3,"@{feature3}",feature3.shape)
""" """
feature1 = extract_feature_of_audio(audio_path, self.f_config) feature_audio = self.extract_feature_single_audio(audio_path)
# print(feature1.shape)
# print(feature1,"@{feature1}",feature1.shape)
# feature2=feature1.T feature = feature_audio.reshape(1, -1)
# print(feature2,"@{feature2}",feature2.shape)
feature = feature1.reshape(1, -1)
# print(feature3,"@{feature3}",feature3.shape)
model = self.model if self.model else self.best_model() model = self.model if self.model else self.best_model()
res = model.predict(feature) res = model.predict(feature)
# res可能是个列表 # res可能是个列表
# print(res, "@{res}") # print(res, "@{res}")
return res[0] return res[0]
def extract_feature_single_audio(self, audio_path):
ae:AudioExtractor=self.ae
pca = ae.pca
print(pca,"@{pca} in 'predict' method")
# if pca:
# feature_audio=pca.transform(feature_audio)
# print(feature_audio.shape, "@{feature_audio.shape}")
feature_audio=ae.extract_features(partition="test",audio_paths=[audio_path])
return feature_audio
# return self.model.predict(feature2)[0] # return self.model.predict(feature2)[0]
def peek_test_set(self, n=5): def peek_test_set(self, n=5):
...@@ -248,7 +283,8 @@ class EmotionRecognizer: ...@@ -248,7 +283,8 @@ class EmotionRecognizer:
Predicts the probability of each emotion. Predicts the probability of each emotion.
""" """
if self.classification_task: if self.classification_task:
feature = extract_feature_of_audio(audio_path, self.f_config).reshape(1, -1) # feature = extract_feature_of_audio(audio_path, self.f_config).reshape(1, -1)
feature=self.extract_feature_single_audio(audio_path)
proba = self.model.predict_proba(feature)[0] proba = self.model.predict_proba(feature)[0]
result = {} result = {}
for emotion, prob in zip(self.model.classes_, proba): for emotion, prob in zip(self.model.classes_, proba):
...@@ -336,7 +372,7 @@ class EmotionRecognizer: ...@@ -336,7 +372,7 @@ class EmotionRecognizer:
f_config=self.f_config, f_config=self.f_config,
balance=self.balance, balance=self.balance,
override_csv=False, override_csv=False,
verbose=0 verbose=0,
) )
# data already loaded # data already loaded
er.X_train = self.X_train er.X_train = self.X_train
...@@ -353,7 +389,7 @@ class EmotionRecognizer: ...@@ -353,7 +389,7 @@ class EmotionRecognizer:
# 使用本对象self而不是在创建一个ER对象 # 使用本对象self而不是在创建一个ER对象
# self.model = estimator # self.model = estimator
# er = self # er = self
# 以下的计算是用来选出model的,而不是直接作为self对象的属性,这里将self赋值给er,以示区别 # 以下的计算是用来选出model的,而不是直接作为self对象的属性,这里将self赋值给er,以示区别
# train(fit) the model # train(fit) the model
...@@ -401,14 +437,11 @@ class EmotionRecognizer: ...@@ -401,14 +437,11 @@ class EmotionRecognizer:
y_test = self.y_test y_test = self.y_test
# 调用训练好的模型进行预测 # 调用训练好的模型进行预测
model = self.model if self.model is not None else self.best_model() model = self.model if self.model is not None else self.best_model()
self.validate_empty_array(X_test=X_test,y_test=y_test) self.validate_empty_array(X_test=X_test, y_test=y_test)
# if len(X_test) == 0:
# raise ValueError("X_test is empty")
# if len(y_test) == 0:
# raise ValueError("y_test is empty")
# 预测计算 # 预测计算
if verbose: if verbose:
print(X_test.shape, y_test.shape,"🎈") print(X_test.shape, y_test.shape, "🎈")
y_pred = model.predict(X_test) # type: ignore y_pred = model.predict(X_test) # type: ignore
if choosing == False: if choosing == False:
self.y_pred = np.array(y_pred) self.y_pred = np.array(y_pred)
...@@ -417,11 +450,21 @@ class EmotionRecognizer: ...@@ -417,11 +450,21 @@ class EmotionRecognizer:
res = accuracy_score(y_true=y_test, y_pred=y_pred) res = accuracy_score(y_true=y_test, y_pred=y_pred)
else: else:
res = mean_squared_error(y_true=y_test, y_pred=y_pred) res = mean_squared_error(y_true=y_test, y_pred=y_pred)
if self.verbose >= 2 or verbose >= 1: if self.verbose >= 1:
report = classification_report(y_true=y_test, y_pred=y_pred) report = classification_report(y_true=y_test, y_pred=y_pred)
print(report, self.model.__class__.__name__)
print(f"{verbose=}", report, self.model.__class__.__name__)
return res return res
def model_cv_score(self, choosing=False, verbose=1,mean_only=True,n_splits=5,test_size=0.2,cv_mode="sss"):
def model_cv_score(
self,
choosing=False,
verbose=1,
mean_only=True,
n_splits=5,
test_size=0.2,
cv_mode="sss",
):
""" """
使用交叉验证的方式来评估模型 使用交叉验证的方式来评估模型
Calculates score on testing data Calculates score on testing data
...@@ -434,32 +477,37 @@ class EmotionRecognizer: ...@@ -434,32 +477,37 @@ class EmotionRecognizer:
# 预测计算 # 预测计算
if verbose: if verbose:
print(X_train.shape, y_train.shape,"🎈") print(X_train.shape, y_train.shape, "🎈")
print(f"{n_splits=}") print(f"{n_splits=}")
n_splits=int(n_splits) n_splits = int(n_splits)
y_pred = model.predict(X_train) # type: ignore y_pred = model.predict(X_train) # type: ignore
if choosing == False: if choosing == False:
self.y_pred = np.array(y_pred) self.y_pred = np.array(y_pred)
# 交叉验证的方式评估模型的得分 # 交叉验证的方式评估模型的得分
cv_mode_dict=dict( cv_mode_dict = dict(
sss=StratifiedShuffleSplit(n_splits=n_splits, test_size=test_size, random_state=0), sss=StratifiedShuffleSplit(
n_splits=n_splits, test_size=test_size, random_state=0
),
ss=ShuffleSplit(n_splits=n_splits, test_size=test_size, random_state=0), ss=ShuffleSplit(n_splits=n_splits, test_size=test_size, random_state=0),
kfold=KFold(n_splits=n_splits, shuffle=True, random_state=0), kfold=KFold(n_splits=n_splits, shuffle=True, random_state=0),
skfold=StratifiedKFold(n_splits=n_splits, shuffle=True, random_state=0),
) )
cv_mode_selected=cv_mode_dict[cv_mode] cv_mode_selected = cv_mode_dict[cv_mode]
if verbose: if verbose > 1:
print(f"{cv_mode=}🎈") print(f"{cv_mode=}🎈")
if self.classification_task: if self.classification_task:
# res = accuracy_score(y_true=y_test, y_pred=y_pred) # res = accuracy_score(y_true=y_test, y_pred=y_pred)
res=cross_val_score(model, X_train, y_train, cv=cv_mode_selected) res = cross_val_score(model, X_train, y_train, cv=cv_mode_selected)
if mean_only: if mean_only:
res=res.mean() res = res.mean()
else: else:
res = mean_squared_error(y_true=y_train, y_pred=y_pred) res = mean_squared_error(y_true=y_train, y_pred=y_pred)
if self.verbose >= 2 or verbose >= 1: if self.verbose > 2:
report = classification_report(y_true=y_train, y_pred=y_pred) report = classification_report(
y_true=y_train, y_pred=y_pred
) # 训练集上,几乎总是是满分
print(report, self.model.__class__.__name__) print(report, self.model.__class__.__name__)
return res return res
...@@ -468,6 +516,7 @@ class EmotionRecognizer: ...@@ -468,6 +516,7 @@ class EmotionRecognizer:
raise ValueError("X is empty") raise ValueError("X is empty")
if len(y_test) == 0: if len(y_test) == 0:
raise ValueError("y is empty") raise ValueError("y is empty")
def meta_paths_of_db(self, db, partition="test"): def meta_paths_of_db(self, db, partition="test"):
res = meta_paths_of_db( res = meta_paths_of_db(
db=db, db=db,
...@@ -661,55 +710,64 @@ class EmotionRecognizer: ...@@ -661,55 +710,64 @@ class EmotionRecognizer:
return random.choice(indices) return random.choice(indices)
def main():
passive_emo = ["angry", "sad"]
passive_emo_others = passive_emo + ["others"]
typical_emo = ["happy", "neutral", "sad"]
AHSO = ["angry", "neutral", "sad", "others"]
e_config = passive_emo
f_config = ["mfcc"]
from config.MetaPath import (test_emodb_csv)
passive_emo = ["angry", "sad"]
passive_emo_others=passive_emo+["others"]
typical_emo = ['happy', 'neutral', 'sad']
e_config = typical_emo
def main(EmotionRecognizer, e_config):
# my_model = RandomForestClassifier(max_depth=3, max_features=0.2) # my_model = RandomForestClassifier(max_depth=3, max_features=0.2)
my_model = SVC(C=0.001, gamma=0.001, kernel="poly",probability=True) my_model = SVC(C=0.001, gamma=0.001, kernel="poly", probability=True)
my_model=KNeighborsClassifier(n_neighbors=3, p=1, weights='distance') # my_model=KNeighborsClassifier(n_neighbors=3, p=1, weights='distance')
# my_model = None # my_model = None
# rec = EmotionRecognizer(model=my_model,e_config=AHNPS,f_config=f_config_def,test_dbs=[ravdess],train_dbs=[ravdess], verbose=1) # rec = EmotionRecognizer(model=my_model,e_config=AHNPS,f_config=f_config_def,test_dbs=[ravdess],train_dbs=[ravdess], verbose=1)
# rec = EmotionRecognizer(model=my_model,e_config=AHNPS,f_config=f_config_def,test_dbs=emodb,train_dbs=emodb, verbose=1) # rec = EmotionRecognizer(model=my_model,e_config=AHNPS,f_config=f_config_def,test_dbs=emodb,train_dbs=emodb, verbose=1)
single_db=emodb single_db = emodb
meta_dict = {"train_dbs": single_db, "test_dbs": single_db} meta_dict = {"train_dbs": single_db, "test_dbs": single_db}
# meta_dict=dict(
# train_dbs=emodb,
# test_dbs=ravdess
# )
er = EmotionRecognizer( er = EmotionRecognizer(
model=my_model, model=my_model,
e_config=e_config,
f_config=f_config_def,
**meta_dict, **meta_dict,
e_config=e_config,
f_config=f_config,
verbose=1, verbose=1,
std_scaler=False, pca=dict(n_components=39)
# std_scaler=False,
# pca={"n_components":"mle"}
# pca={'n_components': 60}
) )
er.train() er.train()
train_score=er.train_score() train_score = er.train_score()
print(f"{train_score=}") print(f"{train_score=}")
test_score = er.test_score() test_score = er.test_score()
print(f"{test_score=}") print(f"{test_score=}")
cv_score=er.model_cv_score()
cv_score = er.model_cv_score()
print(f"{cv_score=}") print(f"{cv_score=}")
return er return er
if __name__ == "__main__":
er=main(EmotionRecognizer, e_config) if __name__ == "__main__":
er = main()
## ##
# file=r'D:\repos\CCSER\SER\data\savee\AudioData\DC\h01.wav' # file=r'D:\repos\CCSER\SER\data\savee\AudioData\DC\h01.wav'
# file=meta.speech_dbs_dir/emodb/r'wav/03a01Fa.wav' # file=meta.speech_dbs_dir/emodb/r'wav/03a01Fa.wav'
# predict_res=er.predict(file) # predict_res=er.predict(file)
# print(f"{predict_res=}") # print(f"{predict_res=}")
# predict_proba=er.predict_proba(file) # predict_proba=er.predict_proba(file)
# print(f"{predict_proba=}") # print(f"{predict_proba=}")
## ##
......
##
from sklearn.datasets import fetch_openml,load_digits
from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
# 加载数据集
# mnist = load('mnist_784', version=1)
mnist=load_digits()
X = mnist.data
y = mnist.target
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 不使用PCA进行训练和测试
knn = KNeighborsClassifier()
knn.fit(X_train, y_train)
accuracy = knn.score(X_test, y_test)
print("Accuracy without PCA: {:.2f}%".format(accuracy * 100))
# 使用PCA进行训练和测试
pca = PCA(n_components=None)
pca.fit(X_train)
X_train_pca = pca.transform(X_train)
X_test_pca = pca.transform(X_test)
knn_pca = KNeighborsClassifier()
knn_pca.fit(X_train_pca, y_train)
accuracy_pca = knn_pca.score(X_test_pca, y_test)
print("Accuracy with PCA: {:.2f}%".format(accuracy_pca * 100))
#对比降维后的维数
print(X_test_pca.shape,"@shape of {X_test_pca}")
print(X_test.shape,"@shape of {X_test}")
##
import numpy as np
from sklearn.decomposition import PCA
rng=np.random.default_rng()
X=rng.integers(10,size=(15,10))
def check_attributes_of_pca(n_components='mle',svd_solver='auto'):
pca = PCA(n_components=n_components,svd_solver=svd_solver)
# 训练PCA模型,并对样本进行降维
X_pca = pca.fit_transform(X)
# 查看PCA模型的各个属性
print("PCA模型的主成分数:", pca.n_components_)
print("PCA模型的主成分:", pca.components_)
print("PCA模型的各主成分的方差值:", pca.explained_variance_)
print("PCA模型各主成分方差值所占比例:", pca.explained_variance_ratio_)
print("PCA模型的均值:", pca.mean_)
print("PCA模型的噪声方差:", pca.noise_variance_)
print("降维后的样本矩阵:\n", X_pca)
for nc in ['mle',2,5,None]:
check_attributes_of_pca(n_components=nc)
print("-"*20)
##
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# 加载iris数据集
iris = load_iris()
# 提取特征和标签
X = iris.data
y = iris.target
# 将数据集分割为训练集、验证集和测试集
X_trainval, X_test, y_trainval, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 将训练集和验证集的组合再次分割为训练集和验证集
X_train, X_val, y_train, y_val = train_test_split(X_trainval, y_trainval, test_size=0.2, random_state=42)
# 打印分割后的数据集大小
print('训练集大小:', X_train.shape[0])
print('验证集大小:', X_val.shape[0])
print('测试集大小:', X_test.shape[0])
\ No newline at end of file
...@@ -36,5 +36,6 @@ ...@@ -36,5 +36,6 @@
- support the `n_splits` as a slider element for use to adjust th - support the `n_splits` as a slider element for use to adjust th
- update the `confusion matrix table`show button - update the `confusion matrix table`show button
- 2023-04-28@11:27:17
- "update the make_window function in the ccser_client main file with more clear modular extraction"
- 2023
\ No newline at end of file
## d = {'A': [1, 2, 3], 'B': [4, 5, 6], 'C':{"a":[7, 8, 9],"b":7}}
from tqdm import tqdm import json
from time import sleep
from audio.core import best_estimators def dict_to_filetag(d):
ests=best_estimators() # Convert dictionary to JSON string
ests=tqdm(ests) json_str = json.dumps(d)
for x in ests: remove_chars=['"',' ']
sleep(0.5) for c in remove_chars:
print(x) json_str=json_str.replace(c,'')
## # Replace invalid characters with hyphen
rep_dict={
":":"=",
# '"':'',
# "'":""
}
for char in json_str:
if rep_dict.get(char):
json_str = json_str.replace(char, rep_dict[char])
# Truncate string if too long
# max_len = 260
# if len(json_str) > max_len:
# json_str = json_str[:max_len]
return json_str
res=dict_to_filetag(d)
print(res)
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册