Files
b2txt25/brain-to-text-25/brain-to-text-25 copy 2.ipynb
2025-10-06 15:17:44 +08:00

5485 lines
564 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 环境配置 与 utils"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Looking in indexes: https://download.pytorch.org/whl/cu126\n",
"Requirement already satisfied: torch in /usr/local/lib/python3.11/dist-packages (2.6.0+cu124)\n",
"Requirement already satisfied: torchvision in /usr/local/lib/python3.11/dist-packages (0.21.0+cu124)\n",
"Requirement already satisfied: torchaudio in /usr/local/lib/python3.11/dist-packages (2.6.0+cu124)\n",
"Requirement already satisfied: filelock in /usr/local/lib/python3.11/dist-packages (from torch) (3.18.0)\n",
"Requirement already satisfied: typing-extensions>=4.10.0 in /usr/local/lib/python3.11/dist-packages (from torch) (4.14.0)\n",
"Requirement already satisfied: networkx in /usr/local/lib/python3.11/dist-packages (from torch) (3.5)\n",
"Requirement already satisfied: jinja2 in /usr/local/lib/python3.11/dist-packages (from torch) (3.1.6)\n",
"Requirement already satisfied: fsspec in /usr/local/lib/python3.11/dist-packages (from torch) (2025.5.1)\n",
"Collecting nvidia-cuda-nvrtc-cu12==12.4.127 (from torch)\n",
" Downloading https://download.pytorch.org/whl/cu126/nvidia_cuda_nvrtc_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)\n",
"Collecting nvidia-cuda-runtime-cu12==12.4.127 (from torch)\n",
" Downloading https://download.pytorch.org/whl/cu126/nvidia_cuda_runtime_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)\n",
"Collecting nvidia-cuda-cupti-cu12==12.4.127 (from torch)\n",
" Downloading https://download.pytorch.org/whl/cu126/nvidia_cuda_cupti_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl.metadata (1.6 kB)\n",
"Collecting nvidia-cudnn-cu12==9.1.0.70 (from torch)\n",
" Downloading https://download.pytorch.org/whl/cu126/nvidia_cudnn_cu12-9.1.0.70-py3-none-manylinux2014_x86_64.whl.metadata (1.6 kB)\n",
"Collecting nvidia-cublas-cu12==12.4.5.8 (from torch)\n",
" Downloading https://download.pytorch.org/whl/cu126/nvidia_cublas_cu12-12.4.5.8-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)\n",
"Collecting nvidia-cufft-cu12==11.2.1.3 (from torch)\n",
" Downloading https://download.pytorch.org/whl/cu126/nvidia_cufft_cu12-11.2.1.3-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)\n",
"Collecting nvidia-curand-cu12==10.3.5.147 (from torch)\n",
" Downloading https://download.pytorch.org/whl/cu126/nvidia_curand_cu12-10.3.5.147-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)\n",
"Collecting nvidia-cusolver-cu12==11.6.1.9 (from torch)\n",
" Downloading https://download.pytorch.org/whl/cu126/nvidia_cusolver_cu12-11.6.1.9-py3-none-manylinux2014_x86_64.whl.metadata (1.6 kB)\n",
"Collecting nvidia-cusparse-cu12==12.3.1.170 (from torch)\n",
" Downloading https://download.pytorch.org/whl/cu126/nvidia_cusparse_cu12-12.3.1.170-py3-none-manylinux2014_x86_64.whl.metadata (1.6 kB)\n",
"Requirement already satisfied: nvidia-cusparselt-cu12==0.6.2 in /usr/local/lib/python3.11/dist-packages (from torch) (0.6.2)\n",
"Requirement already satisfied: nvidia-nccl-cu12==2.21.5 in /usr/local/lib/python3.11/dist-packages (from torch) (2.21.5)\n",
"Requirement already satisfied: nvidia-nvtx-cu12==12.4.127 in /usr/local/lib/python3.11/dist-packages (from torch) (12.4.127)\n",
"Collecting nvidia-nvjitlink-cu12==12.4.127 (from torch)\n",
" Downloading https://download.pytorch.org/whl/cu126/nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)\n",
"Requirement already satisfied: triton==3.2.0 in /usr/local/lib/python3.11/dist-packages (from torch) (3.2.0)\n",
"Requirement already satisfied: sympy==1.13.1 in /usr/local/lib/python3.11/dist-packages (from torch) (1.13.1)\n",
"Requirement already satisfied: mpmath<1.4,>=1.1.0 in /usr/local/lib/python3.11/dist-packages (from sympy==1.13.1->torch) (1.3.0)\n",
"Requirement already satisfied: numpy in /usr/local/lib/python3.11/dist-packages (from torchvision) (1.26.4)\n",
"Requirement already satisfied: pillow!=8.3.*,>=5.3.0 in /usr/local/lib/python3.11/dist-packages (from torchvision) (11.2.1)\n",
"Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib/python3.11/dist-packages (from jinja2->torch) (3.0.2)\n",
"Requirement already satisfied: mkl_fft in /usr/local/lib/python3.11/dist-packages (from numpy->torchvision) (1.3.8)\n",
"Requirement already satisfied: mkl_random in /usr/local/lib/python3.11/dist-packages (from numpy->torchvision) (1.2.4)\n",
"Requirement already satisfied: mkl_umath in /usr/local/lib/python3.11/dist-packages (from numpy->torchvision) (0.1.1)\n",
"Requirement already satisfied: mkl in /usr/local/lib/python3.11/dist-packages (from numpy->torchvision) (2025.2.0)\n",
"Requirement already satisfied: tbb4py in /usr/local/lib/python3.11/dist-packages (from numpy->torchvision) (2022.2.0)\n",
"Requirement already satisfied: mkl-service in /usr/local/lib/python3.11/dist-packages (from numpy->torchvision) (2.4.1)\n",
"Requirement already satisfied: intel-openmp<2026,>=2024 in /usr/local/lib/python3.11/dist-packages (from mkl->numpy->torchvision) (2024.2.0)\n",
"Requirement already satisfied: tbb==2022.* in /usr/local/lib/python3.11/dist-packages (from mkl->numpy->torchvision) (2022.2.0)\n",
"Requirement already satisfied: tcmlib==1.* in /usr/local/lib/python3.11/dist-packages (from tbb==2022.*->mkl->numpy->torchvision) (1.4.0)\n",
"Requirement already satisfied: intel-cmplr-lib-rt in /usr/local/lib/python3.11/dist-packages (from mkl_umath->numpy->torchvision) (2024.2.0)\n",
"Requirement already satisfied: intel-cmplr-lib-ur==2024.2.0 in /usr/local/lib/python3.11/dist-packages (from intel-openmp<2026,>=2024->mkl->numpy->torchvision) (2024.2.0)\n",
"Downloading https://download.pytorch.org/whl/cu126/nvidia_cublas_cu12-12.4.5.8-py3-none-manylinux2014_x86_64.whl (363.4 MB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 363.4/363.4 MB 4.2 MB/s eta 0:00:00\n",
"Downloading https://download.pytorch.org/whl/cu126/nvidia_cuda_cupti_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl (13.8 MB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 13.8/13.8 MB 41.4 MB/s eta 0:00:00\n",
"Downloading https://download.pytorch.org/whl/cu126/nvidia_cuda_nvrtc_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl (24.6 MB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 24.6/24.6 MB 39.1 MB/s eta 0:00:00\n",
"Downloading https://download.pytorch.org/whl/cu126/nvidia_cuda_runtime_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl (883 kB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 883.7/883.7 kB 950.1 kB/s eta 0:00:00\n",
"Downloading https://download.pytorch.org/whl/cu126/nvidia_cudnn_cu12-9.1.0.70-py3-none-manylinux2014_x86_64.whl (664.8 MB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 664.8/664.8 MB 2.2 MB/s eta 0:00:00\n",
"Downloading https://download.pytorch.org/whl/cu126/nvidia_cufft_cu12-11.2.1.3-py3-none-manylinux2014_x86_64.whl (211.5 MB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 211.5/211.5 MB 7.3 MB/s eta 0:00:00\n",
"Downloading https://download.pytorch.org/whl/cu126/nvidia_curand_cu12-10.3.5.147-py3-none-manylinux2014_x86_64.whl (56.3 MB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 56.3/56.3 MB 24.7 MB/s eta 0:00:00\n",
"Downloading https://download.pytorch.org/whl/cu126/nvidia_cusolver_cu12-11.6.1.9-py3-none-manylinux2014_x86_64.whl (127.9 MB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 127.9/127.9 MB 11.0 MB/s eta 0:00:00\n",
"Downloading https://download.pytorch.org/whl/cu126/nvidia_cusparse_cu12-12.3.1.170-py3-none-manylinux2014_x86_64.whl (207.5 MB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 207.5/207.5 MB 3.9 MB/s eta 0:00:00\n",
"Downloading https://download.pytorch.org/whl/cu126/nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl (21.1 MB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 21.1/21.1 MB 28.8 MB/s eta 0:00:00\n",
"Installing collected packages: nvidia-nvjitlink-cu12, nvidia-curand-cu12, nvidia-cufft-cu12, nvidia-cuda-runtime-cu12, nvidia-cuda-nvrtc-cu12, nvidia-cuda-cupti-cu12, nvidia-cublas-cu12, nvidia-cusparse-cu12, nvidia-cudnn-cu12, nvidia-cusolver-cu12\n",
" Attempting uninstall: nvidia-nvjitlink-cu12\n",
" Found existing installation: nvidia-nvjitlink-cu12 12.5.82\n",
" Uninstalling nvidia-nvjitlink-cu12-12.5.82:\n",
" Successfully uninstalled nvidia-nvjitlink-cu12-12.5.82\n",
" Attempting uninstall: nvidia-curand-cu12\n",
" Found existing installation: nvidia-curand-cu12 10.3.6.82\n",
" Uninstalling nvidia-curand-cu12-10.3.6.82:\n",
" Successfully uninstalled nvidia-curand-cu12-10.3.6.82\n",
" Attempting uninstall: nvidia-cufft-cu12\n",
" Found existing installation: nvidia-cufft-cu12 11.2.3.61\n",
" Uninstalling nvidia-cufft-cu12-11.2.3.61:\n",
" Successfully uninstalled nvidia-cufft-cu12-11.2.3.61\n",
" Attempting uninstall: nvidia-cuda-runtime-cu12\n",
" Found existing installation: nvidia-cuda-runtime-cu12 12.5.82\n",
" Uninstalling nvidia-cuda-runtime-cu12-12.5.82:\n",
" Successfully uninstalled nvidia-cuda-runtime-cu12-12.5.82\n",
" Attempting uninstall: nvidia-cuda-nvrtc-cu12\n",
" Found existing installation: nvidia-cuda-nvrtc-cu12 12.5.82\n",
" Uninstalling nvidia-cuda-nvrtc-cu12-12.5.82:\n",
" Successfully uninstalled nvidia-cuda-nvrtc-cu12-12.5.82\n",
" Attempting uninstall: nvidia-cuda-cupti-cu12\n",
" Found existing installation: nvidia-cuda-cupti-cu12 12.5.82\n",
" Uninstalling nvidia-cuda-cupti-cu12-12.5.82:\n",
" Successfully uninstalled nvidia-cuda-cupti-cu12-12.5.82\n",
" Attempting uninstall: nvidia-cublas-cu12\n",
" Found existing installation: nvidia-cublas-cu12 12.5.3.2\n",
" Uninstalling nvidia-cublas-cu12-12.5.3.2:\n",
" Successfully uninstalled nvidia-cublas-cu12-12.5.3.2\n",
" Attempting uninstall: nvidia-cusparse-cu12\n",
" Found existing installation: nvidia-cusparse-cu12 12.5.1.3\n",
" Uninstalling nvidia-cusparse-cu12-12.5.1.3:\n",
" Successfully uninstalled nvidia-cusparse-cu12-12.5.1.3\n",
" Attempting uninstall: nvidia-cudnn-cu12\n",
" Found existing installation: nvidia-cudnn-cu12 9.3.0.75\n",
" Uninstalling nvidia-cudnn-cu12-9.3.0.75:\n",
" Successfully uninstalled nvidia-cudnn-cu12-9.3.0.75\n",
" Attempting uninstall: nvidia-cusolver-cu12\n",
" Found existing installation: nvidia-cusolver-cu12 11.6.3.83\n",
" Uninstalling nvidia-cusolver-cu12-11.6.3.83:\n",
" Successfully uninstalled nvidia-cusolver-cu12-11.6.3.83\n",
"Successfully installed nvidia-cublas-cu12-12.4.5.8 nvidia-cuda-cupti-cu12-12.4.127 nvidia-cuda-nvrtc-cu12-12.4.127 nvidia-cuda-runtime-cu12-12.4.127 nvidia-cudnn-cu12-9.1.0.70 nvidia-cufft-cu12-11.2.1.3 nvidia-curand-cu12-10.3.5.147 nvidia-cusolver-cu12-11.6.1.9 nvidia-cusparse-cu12-12.3.1.170 nvidia-nvjitlink-cu12-12.4.127\n",
"Collecting jupyter==1.1.1\n",
" Downloading jupyter-1.1.1-py2.py3-none-any.whl.metadata (2.0 kB)\n",
"Requirement already satisfied: numpy<2.1.0,>=1.26.0 in /usr/local/lib/python3.11/dist-packages (1.26.4)\n",
"Collecting pandas==2.3.0\n",
" Downloading pandas-2.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (91 kB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 91.2/91.2 kB 2.8 MB/s eta 0:00:00\n",
"Collecting matplotlib==3.10.1\n",
" Downloading matplotlib-3.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (11 kB)\n",
"Collecting scipy==1.15.2\n",
" Downloading scipy-1.15.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (61 kB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 62.0/62.0 kB 3.9 MB/s eta 0:00:00\n",
"Collecting scikit-learn==1.6.1\n",
" Downloading scikit_learn-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (18 kB)\n",
"Requirement already satisfied: tqdm==4.67.1 in /usr/local/lib/python3.11/dist-packages (4.67.1)\n",
"Collecting g2p_en==2.1.0\n",
" Downloading g2p_en-2.1.0-py3-none-any.whl.metadata (4.5 kB)\n",
"Collecting h5py==3.13.0\n",
" Downloading h5py-3.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (2.5 kB)\n",
"Requirement already satisfied: omegaconf==2.3.0 in /usr/local/lib/python3.11/dist-packages (2.3.0)\n",
"Requirement already satisfied: editdistance==0.8.1 in /usr/local/lib/python3.11/dist-packages (0.8.1)\n",
"Requirement already satisfied: huggingface-hub==0.33.1 in /usr/local/lib/python3.11/dist-packages (0.33.1)\n",
"Collecting transformers==4.53.0\n",
" Downloading transformers-4.53.0-py3-none-any.whl.metadata (39 kB)\n",
"Requirement already satisfied: tokenizers==0.21.2 in /usr/local/lib/python3.11/dist-packages (0.21.2)\n",
"Requirement already satisfied: accelerate==1.8.1 in /usr/local/lib/python3.11/dist-packages (1.8.1)\n",
"Collecting bitsandbytes==0.46.0\n",
" Downloading bitsandbytes-0.46.0-py3-none-manylinux_2_24_x86_64.whl.metadata (10 kB)\n",
"Requirement already satisfied: notebook in /usr/local/lib/python3.11/dist-packages (from jupyter==1.1.1) (6.5.4)\n",
"Requirement already satisfied: jupyter-console in /usr/local/lib/python3.11/dist-packages (from jupyter==1.1.1) (6.1.0)\n",
"Requirement already satisfied: nbconvert in /usr/local/lib/python3.11/dist-packages (from jupyter==1.1.1) (6.4.5)\n",
"Requirement already satisfied: ipykernel in /usr/local/lib/python3.11/dist-packages (from jupyter==1.1.1) (6.17.1)\n",
"Requirement already satisfied: ipywidgets in /usr/local/lib/python3.11/dist-packages (from jupyter==1.1.1) (8.1.5)\n",
"Requirement already satisfied: jupyterlab in /usr/local/lib/python3.11/dist-packages (from jupyter==1.1.1) (3.6.8)\n",
"Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.11/dist-packages (from pandas==2.3.0) (2.9.0.post0)\n",
"Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.11/dist-packages (from pandas==2.3.0) (2025.2)\n",
"Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.11/dist-packages (from pandas==2.3.0) (2025.2)\n",
"Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.11/dist-packages (from matplotlib==3.10.1) (1.3.2)\n",
"Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.11/dist-packages (from matplotlib==3.10.1) (0.12.1)\n",
"Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.11/dist-packages (from matplotlib==3.10.1) (4.58.4)\n",
"Requirement already satisfied: kiwisolver>=1.3.1 in /usr/local/lib/python3.11/dist-packages (from matplotlib==3.10.1) (1.4.8)\n",
"Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.11/dist-packages (from matplotlib==3.10.1) (25.0)\n",
"Requirement already satisfied: pillow>=8 in /usr/local/lib/python3.11/dist-packages (from matplotlib==3.10.1) (11.2.1)\n",
"Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.11/dist-packages (from matplotlib==3.10.1) (3.0.9)\n",
"Requirement already satisfied: joblib>=1.2.0 in /usr/local/lib/python3.11/dist-packages (from scikit-learn==1.6.1) (1.5.1)\n",
"Requirement already satisfied: threadpoolctl>=3.1.0 in /usr/local/lib/python3.11/dist-packages (from scikit-learn==1.6.1) (3.6.0)\n",
"Requirement already satisfied: nltk>=3.2.4 in /usr/local/lib/python3.11/dist-packages (from g2p_en==2.1.0) (3.9.1)\n",
"Requirement already satisfied: inflect>=0.3.1 in /usr/local/lib/python3.11/dist-packages (from g2p_en==2.1.0) (7.5.0)\n",
"Collecting distance>=0.1.3 (from g2p_en==2.1.0)\n",
" Downloading Distance-0.1.3.tar.gz (180 kB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 180.3/180.3 kB 6.0 MB/s eta 0:00:00\n",
" Preparing metadata (setup.py): started\n",
" Preparing metadata (setup.py): finished with status 'done'\n",
"Requirement already satisfied: antlr4-python3-runtime==4.9.* in /usr/local/lib/python3.11/dist-packages (from omegaconf==2.3.0) (4.9.3)\n",
"Requirement already satisfied: PyYAML>=5.1.0 in /usr/local/lib/python3.11/dist-packages (from omegaconf==2.3.0) (6.0.2)\n",
"Requirement already satisfied: filelock in /usr/local/lib/python3.11/dist-packages (from huggingface-hub==0.33.1) (3.18.0)\n",
"Requirement already satisfied: fsspec>=2023.5.0 in /usr/local/lib/python3.11/dist-packages (from huggingface-hub==0.33.1) (2025.5.1)\n",
"Requirement already satisfied: requests in /usr/local/lib/python3.11/dist-packages (from huggingface-hub==0.33.1) (2.32.4)\n",
"Requirement already satisfied: typing-extensions>=3.7.4.3 in /usr/local/lib/python3.11/dist-packages (from huggingface-hub==0.33.1) (4.14.0)\n",
"Requirement already satisfied: hf-xet<2.0.0,>=1.1.2 in /usr/local/lib/python3.11/dist-packages (from huggingface-hub==0.33.1) (1.1.5)\n",
"Requirement already satisfied: regex!=2019.12.17 in /usr/local/lib/python3.11/dist-packages (from transformers==4.53.0) (2024.11.6)\n",
"Requirement already satisfied: safetensors>=0.4.3 in /usr/local/lib/python3.11/dist-packages (from transformers==4.53.0) (0.5.3)\n",
"Requirement already satisfied: psutil in /usr/local/lib/python3.11/dist-packages (from accelerate==1.8.1) (7.0.0)\n",
"Requirement already satisfied: torch>=2.0.0 in /usr/local/lib/python3.11/dist-packages (from accelerate==1.8.1) (2.6.0+cu124)\n",
"Requirement already satisfied: mkl_fft in /usr/local/lib/python3.11/dist-packages (from numpy<2.1.0,>=1.26.0) (1.3.8)\n",
"Requirement already satisfied: mkl_random in /usr/local/lib/python3.11/dist-packages (from numpy<2.1.0,>=1.26.0) (1.2.4)\n",
"Requirement already satisfied: mkl_umath in /usr/local/lib/python3.11/dist-packages (from numpy<2.1.0,>=1.26.0) (0.1.1)\n",
"Requirement already satisfied: mkl in /usr/local/lib/python3.11/dist-packages (from numpy<2.1.0,>=1.26.0) (2025.2.0)\n",
"Requirement already satisfied: tbb4py in /usr/local/lib/python3.11/dist-packages (from numpy<2.1.0,>=1.26.0) (2022.2.0)\n",
"Requirement already satisfied: mkl-service in /usr/local/lib/python3.11/dist-packages (from numpy<2.1.0,>=1.26.0) (2.4.1)\n",
"Requirement already satisfied: more_itertools>=8.5.0 in /usr/local/lib/python3.11/dist-packages (from inflect>=0.3.1->g2p_en==2.1.0) (10.7.0)\n",
"Requirement already satisfied: typeguard>=4.0.1 in /usr/local/lib/python3.11/dist-packages (from inflect>=0.3.1->g2p_en==2.1.0) (4.4.4)\n",
"Requirement already satisfied: click in /usr/local/lib/python3.11/dist-packages (from nltk>=3.2.4->g2p_en==2.1.0) (8.2.1)\n",
"Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.11/dist-packages (from python-dateutil>=2.8.2->pandas==2.3.0) (1.17.0)\n",
"Requirement already satisfied: networkx in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.0->accelerate==1.8.1) (3.5)\n",
"Requirement already satisfied: jinja2 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.0->accelerate==1.8.1) (3.1.6)\n",
"Requirement already satisfied: nvidia-cuda-nvrtc-cu12==12.4.127 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.0->accelerate==1.8.1) (12.4.127)\n",
"Requirement already satisfied: nvidia-cuda-runtime-cu12==12.4.127 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.0->accelerate==1.8.1) (12.4.127)\n",
"Requirement already satisfied: nvidia-cuda-cupti-cu12==12.4.127 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.0->accelerate==1.8.1) (12.4.127)\n",
"Requirement already satisfied: nvidia-cudnn-cu12==9.1.0.70 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.0->accelerate==1.8.1) (9.1.0.70)\n",
"Requirement already satisfied: nvidia-cublas-cu12==12.4.5.8 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.0->accelerate==1.8.1) (12.4.5.8)\n",
"Requirement already satisfied: nvidia-cufft-cu12==11.2.1.3 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.0->accelerate==1.8.1) (11.2.1.3)\n",
"Requirement already satisfied: nvidia-curand-cu12==10.3.5.147 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.0->accelerate==1.8.1) (10.3.5.147)\n",
"Requirement already satisfied: nvidia-cusolver-cu12==11.6.1.9 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.0->accelerate==1.8.1) (11.6.1.9)\n",
"Requirement already satisfied: nvidia-cusparse-cu12==12.3.1.170 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.0->accelerate==1.8.1) (12.3.1.170)\n",
"Requirement already satisfied: nvidia-cusparselt-cu12==0.6.2 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.0->accelerate==1.8.1) (0.6.2)\n",
"Requirement already satisfied: nvidia-nccl-cu12==2.21.5 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.0->accelerate==1.8.1) (2.21.5)\n",
"Requirement already satisfied: nvidia-nvtx-cu12==12.4.127 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.0->accelerate==1.8.1) (12.4.127)\n",
"Requirement already satisfied: nvidia-nvjitlink-cu12==12.4.127 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.0->accelerate==1.8.1) (12.4.127)\n",
"Requirement already satisfied: triton==3.2.0 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.0->accelerate==1.8.1) (3.2.0)\n",
"Requirement already satisfied: sympy==1.13.1 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.0->accelerate==1.8.1) (1.13.1)\n",
"Requirement already satisfied: mpmath<1.4,>=1.1.0 in /usr/local/lib/python3.11/dist-packages (from sympy==1.13.1->torch>=2.0.0->accelerate==1.8.1) (1.3.0)\n",
"Requirement already satisfied: debugpy>=1.0 in /usr/local/lib/python3.11/dist-packages (from ipykernel->jupyter==1.1.1) (1.8.0)\n",
"Requirement already satisfied: ipython>=7.23.1 in /usr/local/lib/python3.11/dist-packages (from ipykernel->jupyter==1.1.1) (7.34.0)\n",
"Requirement already satisfied: jupyter-client>=6.1.12 in /usr/local/lib/python3.11/dist-packages (from ipykernel->jupyter==1.1.1) (8.6.3)\n",
"Requirement already satisfied: matplotlib-inline>=0.1 in /usr/local/lib/python3.11/dist-packages (from ipykernel->jupyter==1.1.1) (0.1.7)\n",
"Requirement already satisfied: nest-asyncio in /usr/local/lib/python3.11/dist-packages (from ipykernel->jupyter==1.1.1) (1.6.0)\n",
"Requirement already satisfied: pyzmq>=17 in /usr/local/lib/python3.11/dist-packages (from ipykernel->jupyter==1.1.1) (24.0.1)\n",
"Requirement already satisfied: tornado>=6.1 in /usr/local/lib/python3.11/dist-packages (from ipykernel->jupyter==1.1.1) (6.5.1)\n",
"Requirement already satisfied: traitlets>=5.1.0 in /usr/local/lib/python3.11/dist-packages (from ipykernel->jupyter==1.1.1) (5.7.1)\n",
"Requirement already satisfied: comm>=0.1.3 in /usr/local/lib/python3.11/dist-packages (from ipywidgets->jupyter==1.1.1) (0.2.2)\n",
"Requirement already satisfied: widgetsnbextension~=4.0.12 in /usr/local/lib/python3.11/dist-packages (from ipywidgets->jupyter==1.1.1) (4.0.14)\n",
"Requirement already satisfied: jupyterlab-widgets~=3.0.12 in /usr/local/lib/python3.11/dist-packages (from ipywidgets->jupyter==1.1.1) (3.0.15)\n",
"Requirement already satisfied: prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0 in /usr/local/lib/python3.11/dist-packages (from jupyter-console->jupyter==1.1.1) (3.0.51)\n",
"Requirement already satisfied: pygments in /usr/local/lib/python3.11/dist-packages (from jupyter-console->jupyter==1.1.1) (2.19.2)\n",
"Requirement already satisfied: jupyter-core in /usr/local/lib/python3.11/dist-packages (from jupyterlab->jupyter==1.1.1) (5.8.1)\n",
"Requirement already satisfied: jupyterlab-server~=2.19 in /usr/local/lib/python3.11/dist-packages (from jupyterlab->jupyter==1.1.1) (2.27.3)\n",
"Requirement already satisfied: jupyter-server<3,>=1.16.0 in /usr/local/lib/python3.11/dist-packages (from jupyterlab->jupyter==1.1.1) (2.12.5)\n",
"Requirement already satisfied: jupyter-ydoc~=0.2.4 in /usr/local/lib/python3.11/dist-packages (from jupyterlab->jupyter==1.1.1) (0.2.5)\n",
"Requirement already satisfied: jupyter-server-ydoc~=0.8.0 in /usr/local/lib/python3.11/dist-packages (from jupyterlab->jupyter==1.1.1) (0.8.0)\n",
"Requirement already satisfied: nbclassic in /usr/local/lib/python3.11/dist-packages (from jupyterlab->jupyter==1.1.1) (1.3.1)\n",
"Requirement already satisfied: argon2-cffi in /usr/local/lib/python3.11/dist-packages (from notebook->jupyter==1.1.1) (25.1.0)\n",
"Requirement already satisfied: ipython-genutils in /usr/local/lib/python3.11/dist-packages (from notebook->jupyter==1.1.1) (0.2.0)\n",
"Requirement already satisfied: nbformat in /usr/local/lib/python3.11/dist-packages (from notebook->jupyter==1.1.1) (5.10.4)\n",
"Requirement already satisfied: Send2Trash>=1.8.0 in /usr/local/lib/python3.11/dist-packages (from notebook->jupyter==1.1.1) (1.8.3)\n",
"Requirement already satisfied: terminado>=0.8.3 in /usr/local/lib/python3.11/dist-packages (from notebook->jupyter==1.1.1) (0.18.1)\n",
"Requirement already satisfied: prometheus-client in /usr/local/lib/python3.11/dist-packages (from notebook->jupyter==1.1.1) (0.22.1)\n",
"Requirement already satisfied: mistune<2,>=0.8.1 in /usr/local/lib/python3.11/dist-packages (from nbconvert->jupyter==1.1.1) (0.8.4)\n",
"Requirement already satisfied: jupyterlab-pygments in /usr/local/lib/python3.11/dist-packages (from nbconvert->jupyter==1.1.1) (0.3.0)\n",
"Requirement already satisfied: entrypoints>=0.2.2 in /usr/local/lib/python3.11/dist-packages (from nbconvert->jupyter==1.1.1) (0.4)\n",
"Requirement already satisfied: bleach in /usr/local/lib/python3.11/dist-packages (from nbconvert->jupyter==1.1.1) (6.2.0)\n",
"Requirement already satisfied: pandocfilters>=1.4.1 in /usr/local/lib/python3.11/dist-packages (from nbconvert->jupyter==1.1.1) (1.5.1)\n",
"Requirement already satisfied: testpath in /usr/local/lib/python3.11/dist-packages (from nbconvert->jupyter==1.1.1) (0.6.0)\n",
"Requirement already satisfied: defusedxml in /usr/local/lib/python3.11/dist-packages (from nbconvert->jupyter==1.1.1) (0.7.1)\n",
"Requirement already satisfied: beautifulsoup4 in /usr/local/lib/python3.11/dist-packages (from nbconvert->jupyter==1.1.1) (4.13.4)\n",
"Requirement already satisfied: nbclient<0.6.0,>=0.5.0 in /usr/local/lib/python3.11/dist-packages (from nbconvert->jupyter==1.1.1) (0.5.13)\n",
"Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib/python3.11/dist-packages (from nbconvert->jupyter==1.1.1) (3.0.2)\n",
"Requirement already satisfied: intel-openmp<2026,>=2024 in /usr/local/lib/python3.11/dist-packages (from mkl->numpy<2.1.0,>=1.26.0) (2024.2.0)\n",
"Requirement already satisfied: tbb==2022.* in /usr/local/lib/python3.11/dist-packages (from mkl->numpy<2.1.0,>=1.26.0) (2022.2.0)\n",
"Requirement already satisfied: tcmlib==1.* in /usr/local/lib/python3.11/dist-packages (from tbb==2022.*->mkl->numpy<2.1.0,>=1.26.0) (1.4.0)\n",
"Requirement already satisfied: intel-cmplr-lib-rt in /usr/local/lib/python3.11/dist-packages (from mkl_umath->numpy<2.1.0,>=1.26.0) (2024.2.0)\n",
"Requirement already satisfied: charset_normalizer<4,>=2 in /usr/local/lib/python3.11/dist-packages (from requests->huggingface-hub==0.33.1) (3.4.2)\n",
"Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.11/dist-packages (from requests->huggingface-hub==0.33.1) (3.10)\n",
"Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.11/dist-packages (from requests->huggingface-hub==0.33.1) (2.5.0)\n",
"Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.11/dist-packages (from requests->huggingface-hub==0.33.1) (2025.6.15)\n",
"Requirement already satisfied: intel-cmplr-lib-ur==2024.2.0 in /usr/local/lib/python3.11/dist-packages (from intel-openmp<2026,>=2024->mkl->numpy<2.1.0,>=1.26.0) (2024.2.0)\n",
"Requirement already satisfied: setuptools>=18.5 in /usr/local/lib/python3.11/dist-packages (from ipython>=7.23.1->ipykernel->jupyter==1.1.1) (75.2.0)\n",
"Requirement already satisfied: jedi>=0.16 in /usr/local/lib/python3.11/dist-packages (from ipython>=7.23.1->ipykernel->jupyter==1.1.1) (0.19.2)\n",
"Requirement already satisfied: decorator in /usr/local/lib/python3.11/dist-packages (from ipython>=7.23.1->ipykernel->jupyter==1.1.1) (4.4.2)\n",
"Requirement already satisfied: pickleshare in /usr/local/lib/python3.11/dist-packages (from ipython>=7.23.1->ipykernel->jupyter==1.1.1) (0.7.5)\n",
"Requirement already satisfied: backcall in /usr/local/lib/python3.11/dist-packages (from ipython>=7.23.1->ipykernel->jupyter==1.1.1) (0.2.0)\n",
"Requirement already satisfied: pexpect>4.3 in /usr/local/lib/python3.11/dist-packages (from ipython>=7.23.1->ipykernel->jupyter==1.1.1) (4.9.0)\n",
"Requirement already satisfied: platformdirs>=2.5 in /usr/local/lib/python3.11/dist-packages (from jupyter-core->jupyterlab->jupyter==1.1.1) (4.3.8)\n",
"Requirement already satisfied: anyio>=3.1.0 in /usr/local/lib/python3.11/dist-packages (from jupyter-server<3,>=1.16.0->jupyterlab->jupyter==1.1.1) (4.9.0)\n",
"Requirement already satisfied: jupyter-events>=0.9.0 in /usr/local/lib/python3.11/dist-packages (from jupyter-server<3,>=1.16.0->jupyterlab->jupyter==1.1.1) (0.12.0)\n",
"Requirement already satisfied: jupyter-server-terminals in /usr/local/lib/python3.11/dist-packages (from jupyter-server<3,>=1.16.0->jupyterlab->jupyter==1.1.1) (0.5.3)\n",
"Requirement already satisfied: overrides in /usr/local/lib/python3.11/dist-packages (from jupyter-server<3,>=1.16.0->jupyterlab->jupyter==1.1.1) (7.7.0)\n",
"Requirement already satisfied: websocket-client in /usr/local/lib/python3.11/dist-packages (from jupyter-server<3,>=1.16.0->jupyterlab->jupyter==1.1.1) (1.8.0)\n",
"Requirement already satisfied: jupyter-server-fileid<1,>=0.6.0 in /usr/local/lib/python3.11/dist-packages (from jupyter-server-ydoc~=0.8.0->jupyterlab->jupyter==1.1.1) (0.9.3)\n",
"Requirement already satisfied: ypy-websocket<0.9.0,>=0.8.2 in /usr/local/lib/python3.11/dist-packages (from jupyter-server-ydoc~=0.8.0->jupyterlab->jupyter==1.1.1) (0.8.4)\n",
"Requirement already satisfied: y-py<0.7.0,>=0.6.0 in /usr/local/lib/python3.11/dist-packages (from jupyter-ydoc~=0.2.4->jupyterlab->jupyter==1.1.1) (0.6.2)\n",
"Requirement already satisfied: babel>=2.10 in /usr/local/lib/python3.11/dist-packages (from jupyterlab-server~=2.19->jupyterlab->jupyter==1.1.1) (2.17.0)\n",
"Requirement already satisfied: json5>=0.9.0 in /usr/local/lib/python3.11/dist-packages (from jupyterlab-server~=2.19->jupyterlab->jupyter==1.1.1) (0.12.0)\n",
"Requirement already satisfied: jsonschema>=4.18.0 in /usr/local/lib/python3.11/dist-packages (from jupyterlab-server~=2.19->jupyterlab->jupyter==1.1.1) (4.24.0)\n",
"Requirement already satisfied: notebook-shim>=0.2.3 in /usr/local/lib/python3.11/dist-packages (from nbclassic->jupyterlab->jupyter==1.1.1) (0.2.4)\n",
"Requirement already satisfied: fastjsonschema>=2.15 in /usr/local/lib/python3.11/dist-packages (from nbformat->notebook->jupyter==1.1.1) (2.21.1)\n",
"Requirement already satisfied: wcwidth in /usr/local/lib/python3.11/dist-packages (from prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0->jupyter-console->jupyter==1.1.1) (0.2.13)\n",
"Requirement already satisfied: ptyprocess in /usr/local/lib/python3.11/dist-packages (from terminado>=0.8.3->notebook->jupyter==1.1.1) (0.7.0)\n",
"Requirement already satisfied: argon2-cffi-bindings in /usr/local/lib/python3.11/dist-packages (from argon2-cffi->notebook->jupyter==1.1.1) (21.2.0)\n",
"Requirement already satisfied: soupsieve>1.2 in /usr/local/lib/python3.11/dist-packages (from beautifulsoup4->nbconvert->jupyter==1.1.1) (2.7)\n",
"Requirement already satisfied: webencodings in /usr/local/lib/python3.11/dist-packages (from bleach->nbconvert->jupyter==1.1.1) (0.5.1)\n",
"Requirement already satisfied: sniffio>=1.1 in /usr/local/lib/python3.11/dist-packages (from anyio>=3.1.0->jupyter-server<3,>=1.16.0->jupyterlab->jupyter==1.1.1) (1.3.1)\n",
"Requirement already satisfied: parso<0.9.0,>=0.8.4 in /usr/local/lib/python3.11/dist-packages (from jedi>=0.16->ipython>=7.23.1->ipykernel->jupyter==1.1.1) (0.8.4)\n",
"Requirement already satisfied: attrs>=22.2.0 in /usr/local/lib/python3.11/dist-packages (from jsonschema>=4.18.0->jupyterlab-server~=2.19->jupyterlab->jupyter==1.1.1) (25.3.0)\n",
"Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /usr/local/lib/python3.11/dist-packages (from jsonschema>=4.18.0->jupyterlab-server~=2.19->jupyterlab->jupyter==1.1.1) (2025.4.1)\n",
"Requirement already satisfied: referencing>=0.28.4 in /usr/local/lib/python3.11/dist-packages (from jsonschema>=4.18.0->jupyterlab-server~=2.19->jupyterlab->jupyter==1.1.1) (0.36.2)\n",
"Requirement already satisfied: rpds-py>=0.7.1 in /usr/local/lib/python3.11/dist-packages (from jsonschema>=4.18.0->jupyterlab-server~=2.19->jupyterlab->jupyter==1.1.1) (0.25.1)\n",
"Requirement already satisfied: python-json-logger>=2.0.4 in /usr/local/lib/python3.11/dist-packages (from jupyter-events>=0.9.0->jupyter-server<3,>=1.16.0->jupyterlab->jupyter==1.1.1) (3.3.0)\n",
"Requirement already satisfied: rfc3339-validator in /usr/local/lib/python3.11/dist-packages (from jupyter-events>=0.9.0->jupyter-server<3,>=1.16.0->jupyterlab->jupyter==1.1.1) (0.1.4)\n",
"Requirement already satisfied: rfc3986-validator>=0.1.1 in /usr/local/lib/python3.11/dist-packages (from jupyter-events>=0.9.0->jupyter-server<3,>=1.16.0->jupyterlab->jupyter==1.1.1) (0.1.1)\n",
"Requirement already satisfied: aiofiles<23,>=22.1.0 in /usr/local/lib/python3.11/dist-packages (from ypy-websocket<0.9.0,>=0.8.2->jupyter-server-ydoc~=0.8.0->jupyterlab->jupyter==1.1.1) (22.1.0)\n",
"Requirement already satisfied: aiosqlite<1,>=0.17.0 in /usr/local/lib/python3.11/dist-packages (from ypy-websocket<0.9.0,>=0.8.2->jupyter-server-ydoc~=0.8.0->jupyterlab->jupyter==1.1.1) (0.21.0)\n",
"Requirement already satisfied: cffi>=1.0.1 in /usr/local/lib/python3.11/dist-packages (from argon2-cffi-bindings->argon2-cffi->notebook->jupyter==1.1.1) (1.17.1)\n",
"Requirement already satisfied: pycparser in /usr/local/lib/python3.11/dist-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi->notebook->jupyter==1.1.1) (2.22)\n",
"Requirement already satisfied: fqdn in /usr/local/lib/python3.11/dist-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=1.16.0->jupyterlab->jupyter==1.1.1) (1.5.1)\n",
"Requirement already satisfied: isoduration in /usr/local/lib/python3.11/dist-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=1.16.0->jupyterlab->jupyter==1.1.1) (20.11.0)\n",
"Requirement already satisfied: jsonpointer>1.13 in /usr/local/lib/python3.11/dist-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=1.16.0->jupyterlab->jupyter==1.1.1) (3.0.0)\n",
"Requirement already satisfied: uri-template in /usr/local/lib/python3.11/dist-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=1.16.0->jupyterlab->jupyter==1.1.1) (1.3.0)\n",
"Requirement already satisfied: webcolors>=24.6.0 in /usr/local/lib/python3.11/dist-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=1.16.0->jupyterlab->jupyter==1.1.1) (24.11.1)\n",
"Requirement already satisfied: arrow>=0.15.0 in /usr/local/lib/python3.11/dist-packages (from isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=1.16.0->jupyterlab->jupyter==1.1.1) (1.3.0)\n",
"Requirement already satisfied: types-python-dateutil>=2.8.10 in /usr/local/lib/python3.11/dist-packages (from arrow>=0.15.0->isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.9.0->jupyter-server<3,>=1.16.0->jupyterlab->jupyter==1.1.1) (2.9.0.20250516)\n",
"Downloading jupyter-1.1.1-py2.py3-none-any.whl (2.7 kB)\n",
"Downloading pandas-2.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.4 MB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 12.4/12.4 MB 70.6 MB/s eta 0:00:00\n",
"Downloading matplotlib-3.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (8.6 MB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.6/8.6 MB 81.5 MB/s eta 0:00:00\n",
"Downloading scipy-1.15.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (37.6 MB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 37.6/37.6 MB 41.5 MB/s eta 0:00:00\n",
"Downloading scikit_learn-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (13.5 MB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 13.5/13.5 MB 74.9 MB/s eta 0:00:00\n",
"Downloading g2p_en-2.1.0-py3-none-any.whl (3.1 MB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.1/3.1 MB 67.0 MB/s eta 0:00:00\n",
"Downloading h5py-3.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.5 MB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.5/4.5 MB 82.0 MB/s eta 0:00:00\n",
"Downloading transformers-4.53.0-py3-none-any.whl (10.8 MB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 10.8/10.8 MB 81.3 MB/s eta 0:00:00\n",
"Downloading bitsandbytes-0.46.0-py3-none-manylinux_2_24_x86_64.whl (67.0 MB)\n",
" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 67.0/67.0 MB 25.1 MB/s eta 0:00:00\n",
"Building wheels for collected packages: distance\n",
" Building wheel for distance (setup.py): started\n",
" Building wheel for distance (setup.py): finished with status 'done'\n",
" Created wheel for distance: filename=Distance-0.1.3-py3-none-any.whl size=16256 sha256=5e51a54903d8ad80b65102af3804db716112a6b20fb667574a353bc2a5beeb6a\n",
" Stored in directory: /root/.cache/pip/wheels/fb/cd/9c/3ab5d666e3bcacc58900b10959edd3816cc9557c7337986322\n",
"Successfully built distance\n",
"Installing collected packages: distance, jupyter, scipy, transformers, scikit-learn, pandas, matplotlib, h5py, g2p_en, bitsandbytes\n",
" Attempting uninstall: scipy\n",
" Found existing installation: scipy 1.15.3\n",
" Uninstalling scipy-1.15.3:\n",
" Successfully uninstalled scipy-1.15.3\n",
" Attempting uninstall: transformers\n",
" Found existing installation: transformers 4.52.4\n",
" Uninstalling transformers-4.52.4:\n",
" Successfully uninstalled transformers-4.52.4\n",
" Attempting uninstall: scikit-learn\n",
" Found existing installation: scikit-learn 1.2.2\n",
" Uninstalling scikit-learn-1.2.2:\n",
" Successfully uninstalled scikit-learn-1.2.2\n",
" Attempting uninstall: pandas\n",
" Found existing installation: pandas 2.2.3\n",
" Uninstalling pandas-2.2.3:\n",
" Successfully uninstalled pandas-2.2.3\n",
" Attempting uninstall: matplotlib\n",
" Found existing installation: matplotlib 3.7.2\n",
" Uninstalling matplotlib-3.7.2:\n",
" Successfully uninstalled matplotlib-3.7.2\n",
" Attempting uninstall: h5py\n",
" Found existing installation: h5py 3.14.0\n",
" Uninstalling h5py-3.14.0:\n",
" Successfully uninstalled h5py-3.14.0\n",
"Successfully installed bitsandbytes-0.46.0 distance-0.1.3 g2p_en-2.1.0 h5py-3.13.0 jupyter-1.1.1 matplotlib-3.10.1 pandas-2.3.0 scikit-learn-1.6.1 scipy-1.15.2 transformers-4.53.0\n",
"Obtaining file:///kaggle/working/nejm-brain-to-text\n",
" Preparing metadata (setup.py): started\n",
" Preparing metadata (setup.py): finished with status 'done'\n",
"Installing collected packages: nejm_b2txt_utils\n",
" Running setup.py develop for nejm_b2txt_utils\n",
"Successfully installed nejm_b2txt_utils-0.0.0\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Cloning into 'nejm-brain-to-text'...\n",
"ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n",
"bigframes 2.8.0 requires google-cloud-bigquery-storage<3.0.0,>=2.30.0, which is not installed.\n",
"gensim 4.3.3 requires scipy<1.14.0,>=1.7.0, but you have scipy 1.15.2 which is incompatible.\n",
"dask-cudf-cu12 25.2.2 requires pandas<2.2.4dev0,>=2.0, but you have pandas 2.3.0 which is incompatible.\n",
"cudf-cu12 25.2.2 requires pandas<2.2.4dev0,>=2.0, but you have pandas 2.3.0 which is incompatible.\n",
"datasets 3.6.0 requires fsspec[http]<=2025.3.0,>=2023.1.0, but you have fsspec 2025.5.1 which is incompatible.\n",
"ydata-profiling 4.16.1 requires matplotlib<=3.10,>=3.5, but you have matplotlib 3.10.1 which is incompatible.\n",
"category-encoders 2.7.0 requires scikit-learn<1.6.0,>=1.0.0, but you have scikit-learn 1.6.1 which is incompatible.\n",
"cesium 0.12.4 requires numpy<3.0,>=2.0, but you have numpy 1.26.4 which is incompatible.\n",
"google-colab 1.0.0 requires google-auth==2.38.0, but you have google-auth 2.40.3 which is incompatible.\n",
"google-colab 1.0.0 requires notebook==6.5.7, but you have notebook 6.5.4 which is incompatible.\n",
"google-colab 1.0.0 requires pandas==2.2.2, but you have pandas 2.3.0 which is incompatible.\n",
"google-colab 1.0.0 requires requests==2.32.3, but you have requests 2.32.4 which is incompatible.\n",
"google-colab 1.0.0 requires tornado==6.4.2, but you have tornado 6.5.1 which is incompatible.\n",
"dopamine-rl 4.1.2 requires gymnasium>=1.0.0, but you have gymnasium 0.29.0 which is incompatible.\n",
"pandas-gbq 0.29.1 requires google-api-core<3.0.0,>=2.10.2, but you have google-api-core 1.34.1 which is incompatible.\n",
"bigframes 2.8.0 requires google-cloud-bigquery[bqstorage,pandas]>=3.31.0, but you have google-cloud-bigquery 3.25.0 which is incompatible.\n",
"bigframes 2.8.0 requires rich<14,>=12.4.4, but you have rich 14.0.0 which is incompatible.\n"
]
}
],
"source": [
"%%bash\n",
"cd /kaggle/working/\n",
"rm -rf /kaggle/working/nejm-brain-to-text/\n",
"git clone https://github.com/ZH-CEN/nejm-brain-to-text.git\n",
"cd /kaggle/working/nejm-brain-to-text/\n",
"cp /kaggle/input/brain-to-text-baseline-model/t15_copyTask.pkl /kaggle/working/nejm-brain-to-text/data/t15_copyTask.pkl\n",
"# Install PyTorch with CUDA 12.6\n",
"pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126\n",
"\n",
"# Install additional packages with compatible versions\n",
"# TODO: remove redis\n",
"pip install \\\n",
" jupyter==1.1.1 \\\n",
" \"numpy>=1.26.0,<2.1.0\" \\\n",
" pandas==2.3.0 \\\n",
" matplotlib==3.10.1 \\\n",
" scipy==1.15.2 \\\n",
" scikit-learn==1.6.1 \\\n",
" tqdm==4.67.1 \\\n",
" g2p_en==2.1.0 \\\n",
" h5py==3.13.0 \\\n",
" omegaconf==2.3.0 \\\n",
" editdistance==0.8.1 \\\n",
" huggingface-hub==0.33.1 \\\n",
" transformers==4.53.0 \\\n",
" tokenizers==0.21.2 \\\n",
" accelerate==1.8.1 \\\n",
" bitsandbytes==0.46.0\n",
"\n",
"# Install the local package\n",
"pip install -e .\n",
"ln -s /kaggle/input/brain-to-text-25/t15_pretrained_rnn_baseline/t15_pretrained_rnn_baseline /kaggle/working/nejm-brain-to-text/data\n",
"ln -s /kaggle/input/brain-to-text-25/t15_copyTask_neuralData/hdf5_data_final /kaggle/working/nejm-brain-to-text/data\n",
"ln -s /kaggle/input/rnn-pretagged-data /kaggle/working/nejm-brain-to-text/data"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"/kaggle/working/nejm-brain-to-text\n"
]
}
],
"source": [
"%cd /kaggle/working/nejm-brain-to-text\n",
"import numpy as np\n",
"import os\n",
"import pickle\n",
"import matplotlib.pyplot as plt\n",
"import matplotlib\n",
"from g2p_en import G2p\n",
"import pandas as pd\n",
"import numpy as np\n",
"from nejm_b2txt_utils.general_utils import *\n",
"\n",
"matplotlib.rcParams['pdf.fonttype'] = 42\n",
"matplotlib.rcParams['ps.fonttype'] = 42\n",
"matplotlib.rcParams['font.family'] = 'sans-serif'\n"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"# from data_augmentations import gauss_smooth\n",
"# single decoding step function that also returns smoothed input\n",
"# smooths data and puts it through the model, returning both logits and smoothed input.\n",
"def runSingleDecodingStepWithSmoothedInput(x, input_layer, model, model_args, device):\n",
"\n",
" # Use autocast for efficiency\n",
" with torch.autocast(device_type = \"cuda\", enabled = model_args['use_amp'], dtype = torch.bfloat16):\n",
"\n",
" smoothed_x = gauss_smooth(\n",
" inputs = x, \n",
" device = device,\n",
" smooth_kernel_std = model_args['dataset']['data_transforms']['smooth_kernel_std'],\n",
" smooth_kernel_size = model_args['dataset']['data_transforms']['smooth_kernel_size'],\n",
" padding = 'valid',\n",
" )\n",
"\n",
" with torch.no_grad():\n",
" logits, _ = model(\n",
" x = smoothed_x,\n",
" day_idx = torch.tensor([input_layer], device=device),\n",
" states = None, # no initial states\n",
" return_state = True,\n",
" )\n",
"\n",
" # convert both logits and smoothed input from bfloat16 to float32\n",
" logits = logits.float().cpu().numpy()\n",
" smoothed_input = smoothed_x.float().cpu().numpy()\n",
"\n",
" # # original order is [BLANK, phonemes..., SIL]\n",
" # # rearrange so the order is [BLANK, SIL, phonemes...]\n",
" # logits = rearrange_speech_logits_pt(logits)\n",
"\n",
" return logits, smoothed_input\n",
"\n",
"\n",
"import h5py\n",
"def load_h5py_file(file_path, b2txt_csv_df):\n",
" data = {\n",
" 'neural_features': [],\n",
" 'n_time_steps': [],\n",
" 'seq_class_ids': [],\n",
" 'seq_len': [],\n",
" 'transcriptions': [],\n",
" 'sentence_label': [],\n",
" 'session': [],\n",
" 'block_num': [],\n",
" 'trial_num': [],\n",
" 'corpus': [],\n",
" }\n",
" # Open the hdf5 file for that day\n",
" with h5py.File(file_path, 'r') as f:\n",
"\n",
" keys = list(f.keys())\n",
"\n",
" # For each trial in the selected trials in that day\n",
" for key in keys:\n",
" g = f[key]\n",
"\n",
" neural_features = g['input_features'][:] # pyright: ignore[reportIndexIssue]\n",
" n_time_steps = g.attrs['n_time_steps']\n",
" seq_class_ids = g['seq_class_ids'][:] if 'seq_class_ids' in g else None # type: ignore\n",
" seq_len = g.attrs['seq_len'] if 'seq_len' in g.attrs else None\n",
" transcription = g['transcription'][:] if 'transcription' in g else None # type: ignore\n",
" sentence_label = g.attrs['sentence_label'][:] if 'sentence_label' in g.attrs else None # pyright: ignore[reportIndexIssue]\n",
" session = g.attrs['session']\n",
" block_num = g.attrs['block_num']\n",
" trial_num = g.attrs['trial_num']\n",
"\n",
" # match this trial up with the csv to get the corpus name\n",
" year, month, day = session.split('.')[1:] # pyright: ignore[reportAttributeAccessIssue]\n",
" date = f'{year}-{month}-{day}'\n",
" row = b2txt_csv_df[(b2txt_csv_df['Date'] == date) & (b2txt_csv_df['Block number'] == block_num)]\n",
" corpus_name = row['Corpus'].values[0]\n",
"\n",
" data['neural_features'].append(neural_features)\n",
" data['n_time_steps'].append(n_time_steps)\n",
" data['seq_class_ids'].append(seq_class_ids)\n",
" data['seq_len'].append(seq_len)\n",
" data['transcriptions'].append(transcription)\n",
" data['sentence_label'].append(sentence_label)\n",
" data['session'].append(session)\n",
" data['block_num'].append(block_num)\n",
" data['trial_num'].append(trial_num)\n",
" data['corpus'].append(corpus_name)\n",
" return data"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"LOGIT_TO_PHONEME = [\n",
" 'BLANK',\n",
" 'AA', 'AE', 'AH', 'AO', 'AW',\n",
" 'AY', 'B', 'CH', 'D', 'DH',\n",
" 'EH', 'ER', 'EY', 'F', 'G',\n",
" 'HH', 'IH', 'IY', 'JH', 'K',\n",
" 'L', 'M', 'N', 'NG', 'OW',\n",
" 'OY', 'P', 'R', 'S', 'SH',\n",
" 'T', 'TH', 'UH', 'UW', 'V',\n",
" 'W', 'Y', 'Z', 'ZH',\n",
" ' | ',\n",
"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 数据分析与预处理"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 数据准备"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"/kaggle/working/nejm-brain-to-text\n"
]
}
],
"source": [
"%cd /kaggle/working/nejm-brain-to-text/"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"data = load_h5py_file(file_path='data/hdf5_data_final/t15.2023.08.11/data_train.hdf5',\n",
" b2txt_csv_df=pd.read_csv('data/t15_copyTaskData_description.csv'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- **任务介绍** :机器学习解决高维信号的模式识别问题"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"我们的数据集标签缺少时间戳,现在要进行的是半监督学习"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- 音素时间均等分割或者按照调研数据设定初始长度。然后筛掉异常值。提取出可用的训练集,再控制时间长短,查看样本类的长度"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'neural_features': array([[ 2.3076649 , -0.78699756, -0.64687246, ..., 0.57367045,\n",
" -0.7091646 , -0.11018186],\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., 0.3122117 ,\n",
" 1.7943763 , -0.76884896],\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., -0.21193463,\n",
" -0.8481289 , -0.7648201 ],\n",
" ...,\n",
" [-0.5859305 , 0.22756557, 0.9262037 , ..., -0.34710956,\n",
" 0.9710176 , 2.5397465 ],\n",
" [-0.5859305 , 0.22756557, -0.64687246, ..., -0.83613133,\n",
" -0.68723625, 0.10479005],\n",
" [ 0.8608672 , -0.78699756, -0.64687246, ..., -0.7171131 ,\n",
" 0.7417906 , -0.7008622 ]], dtype=float32),\n",
" 'n_time_steps': 321,\n",
" 'seq_class_ids': array([ 7, 28, 17, 24, 40, 17, 31, 40, 20, 21, 25, 29, 12, 40, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0], dtype=int32),\n",
" 'seq_len': 14,\n",
" 'transcriptions': array([ 66, 114, 105, 110, 103, 32, 105, 116, 32, 99, 108, 111, 115,\n",
" 101, 114, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
" 0, 0, 0, 0, 0, 0], dtype=int32),\n",
" 'sentence_label': 'Bring it closer.',\n",
" 'session': 't15.2023.08.11',\n",
" 'block_num': 2,\n",
" 'trial_num': 0,\n",
" 'corpus': '50-Word'}"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def data_patch(data, index):\n",
" data_patch = {}\n",
" data_patch['neural_features'] = data['neural_features'][index]\n",
" data_patch['n_time_steps'] = data['n_time_steps'][index]\n",
" data_patch['seq_class_ids'] = data['seq_class_ids'][index]\n",
" data_patch['seq_len'] = data['seq_len'][index]\n",
" data_patch['transcriptions'] = data['transcriptions'][index]\n",
" data_patch['sentence_label'] = data['sentence_label'][index]\n",
" data_patch['session'] = data['session'][index]\n",
" data_patch['block_num'] = data['block_num'][index]\n",
" data_patch['trial_num'] = data['trial_num'][index]\n",
" data_patch['corpus'] = data['corpus'][index]\n",
" return data_patch\n",
"\n",
"data_patch(data, 0)"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [],
"source": [
"d1 = data_patch(data, 0)"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Transcriptions non-zero length: 16\n",
"Seq class ids non-zero length: 14\n",
"Seq len: 14\n"
]
}
],
"source": [
"trans_len = len([x for x in d1['transcriptions'] if x != 0])\n",
"seq_len_nonzero = len([x for x in d1['seq_class_ids'] if x != 0])\n",
"seq_len = d1['seq_len']\n",
"print(f\"Transcriptions non-zero length: {trans_len}\")\n",
"print(f\"Seq class ids non-zero length: {seq_len_nonzero}\")\n",
"print(f\"Seq len: {seq_len}\")"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Number of feature sequences: 14\n",
"Shape of first sequence: (22, 512)\n"
]
}
],
"source": [
"def create_time_windows(d1):\n",
" import numpy as np\n",
" n_time_steps = d1['n_time_steps']\n",
" seq_len = d1['seq_len']\n",
" # Create equal windows\n",
" edges = np.linspace(0, n_time_steps, seq_len + 1, dtype=int)\n",
" windows = [(edges[i], edges[i+1]) for i in range(seq_len)]\n",
" \n",
" # Extract feature sequences for each window\n",
" feature_sequences = []\n",
" for start, end in windows:\n",
" seq = d1['neural_features'][start:end, :]\n",
" feature_sequences.append(seq)\n",
" \n",
" return feature_sequences\n",
"\n",
"# Example usage\n",
"feature_sequences = create_time_windows(d1)\n",
"print(\"Number of feature sequences:\", len(feature_sequences))\n",
"print(\"Shape of first sequence:\", feature_sequences[0].shape)\n"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Train: 45, Val: 41, Test: 41\n",
"Train files (first 3): ['/kaggle/working/nejm-brain-to-text/data/hdf5_data_final/t15.2025.03.14/data_train.hdf5', '/kaggle/working/nejm-brain-to-text/data/hdf5_data_final/t15.2023.08.11/data_train.hdf5', '/kaggle/working/nejm-brain-to-text/data/hdf5_data_final/t15.2023.11.19/data_train.hdf5']\n",
"Val files (first 3): ['/kaggle/working/nejm-brain-to-text/data/hdf5_data_final/t15.2025.03.14/data_val.hdf5', '/kaggle/working/nejm-brain-to-text/data/hdf5_data_final/t15.2023.11.19/data_val.hdf5', '/kaggle/working/nejm-brain-to-text/data/hdf5_data_final/t15.2024.03.08/data_val.hdf5']\n",
"Test files (first 3): ['/kaggle/working/nejm-brain-to-text/data/hdf5_data_final/t15.2025.03.14/data_test.hdf5', '/kaggle/working/nejm-brain-to-text/data/hdf5_data_final/t15.2023.11.19/data_test.hdf5', '/kaggle/working/nejm-brain-to-text/data/hdf5_data_final/t15.2024.03.08/data_test.hdf5']\n"
]
}
],
"source": [
"import os\n",
"\n",
"def scan_hdf5_files(base_path):\n",
" train_files = []\n",
" val_files = []\n",
" test_files = []\n",
" for root, dirs, files in os.walk(base_path):\n",
" for file in files:\n",
" if file.endswith('.hdf5'):\n",
" abs_path = os.path.abspath(os.path.join(root, file))\n",
" if 'data_train.hdf5' in file:\n",
" train_files.append(abs_path)\n",
" elif 'data_val.hdf5' in file:\n",
" val_files.append(abs_path)\n",
" elif 'data_test.hdf5' in file:\n",
" test_files.append(abs_path)\n",
" return train_files, val_files, test_files\n",
"\n",
"# Example usage\n",
"FILE_PATH = 'data/hdf5_data_final'\n",
"train_list, val_list, test_list = scan_hdf5_files(FILE_PATH)\n",
"print(f\"Train: {len(train_list)}, Val: {len(val_list)}, Test: {len(test_list)}\")\n",
"print(\"Train files (first 3):\", train_list[:3])\n",
"print(\"Val files (first 3):\", val_list[:3])\n",
"print(\"Test files (first 3):\", test_list[:3])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 标签处理"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Classified windows by label: {'B': [array([[ 2.3076649 , -0.78699756, -0.64687246, ..., 0.57367045,\n",
" -0.7091646 , -0.11018186],\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., 0.3122117 ,\n",
" 1.7943763 , -0.76884896],\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., -0.21193463,\n",
" -0.8481289 , -0.7648201 ],\n",
" ...,\n",
" [-0.5859305 , 1.2421287 , 0.9262037 , ..., -0.75346303,\n",
" -0.0324782 , -0.00711001],\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., 0.76988614,\n",
" 0.5564136 , -0.07822285],\n",
" [-0.5859305 , -0.78699756, 0.9262037 , ..., -0.07598546,\n",
" -0.7657734 , 0.2922766 ]], dtype=float32)], 'R': [array([[-0.5859305 , 0.22756557, -0.64687246, ..., -0.3736147 ,\n",
" 1.8732225 , 0.41014147],\n",
" [ 0.8608672 , -0.78699756, -0.64687246, ..., -0.3927953 ,\n",
" -0.9493937 , -0.21906969],\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., -0.20892826,\n",
" -0.701334 , -0.35187167],\n",
" ...,\n",
" [ 0.8608672 , -0.78699756, -0.64687246, ..., -0.7120476 ,\n",
" 0.47390732, -0.4284464 ],\n",
" [-0.5859305 , 0.22756557, -0.64687246, ..., -0.52835166,\n",
" 0.6060386 , 0.50446767],\n",
" [-0.5859305 , 1.2421287 , -0.64687246, ..., -0.06846887,\n",
" 1.8789533 , 0.3322584 ]], dtype=float32)], 'IH': [array([[ 2.3076649 , 3.271255 , 0.9262037 , ..., -0.46287906,\n",
" 2.2606788 , 0.11010384],\n",
" [ 2.3076649 , -0.78699756, -0.64687246, ..., 0.29536775,\n",
" -0.28977907, 0.8965688 ],\n",
" [-0.5859305 , 0.22756557, -0.64687246, ..., 0.49674448,\n",
" 1.461203 , -0.06363419],\n",
" ...,\n",
" [-0.5859305 , 1.2421287 , -0.64687246, ..., -0.12479645,\n",
" 0.53602815, -0.5204039 ],\n",
" [-0.5859305 , -0.78699756, 0.9262037 , ..., -0.20539333,\n",
" -0.7720516 , -0.227756 ],\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., 2.6598215 ,\n",
" -0.4401024 , -0.06794682]], dtype=float32), array([[-0.5859305 , -0.78699756, 0.9262037 , ..., -0.06658573,\n",
" -0.47086054, -0.889744 ],\n",
" [-0.5859305 , 1.2421287 , 0.9262037 , ..., -0.50259936,\n",
" -1.2583027 , 1.931818 ],\n",
" [-0.5859305 , 0.22756557, -0.64687246, ..., -0.6938413 ,\n",
" -0.77351475, -0.64535946],\n",
" ...,\n",
" [-0.5859305 , 0.22756557, -0.64687246, ..., -0.6131182 ,\n",
" -0.23676614, -0.10696623],\n",
" [-0.5859305 , -0.78699756, 0.9262037 , ..., -0.47634864,\n",
" 0.3112853 , 3.5332208 ],\n",
" [-0.5859305 , 1.2421287 , -0.64687246, ..., -0.5784552 ,\n",
" -0.51007444, -0.09734279]], dtype=float32)], 'NG': [array([[-0.5859305 , -0.78699756, -0.64687246, ..., 1.2813864 ,\n",
" 0.11287313, 0.07477371],\n",
" [-0.5859305 , 0.22756557, -0.64687246, ..., 0.00400451,\n",
" 0.00695544, -0.11998311],\n",
" [ 0.8608672 , 3.271255 , -0.64687246, ..., 2.1416168 ,\n",
" -1.2592531 , -0.73054117],\n",
" ...,\n",
" [ 0.8608672 , -0.78699756, -0.64687246, ..., 2.1101472 ,\n",
" 1.4695522 , -0.48536113],\n",
" [-0.5859305 , 0.22756557, 0.9262037 , ..., -0.4418934 ,\n",
" 0.87822086, 1.6993542 ],\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., -0.40281335,\n",
" -0.58606327, -0.6359653 ]], dtype=float32)], ' | ': [array([[-0.5859305 , 1.2421287 , 2.49928 , ..., -0.26107296,\n",
" -1.1977003 , 2.3292913 ],\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., 0.7225826 ,\n",
" -1.3996706 , -0.75459015],\n",
" [-0.5859305 , 0.22756557, 0.9262037 , ..., 0.6730758 ,\n",
" 0.03320515, -0.6223642 ],\n",
" ...,\n",
" [-0.5859305 , 1.2421287 , -0.64687246, ..., -0.55813146,\n",
" 0.26701608, -0.04874306],\n",
" [-0.5859305 , 0.22756557, 0.9262037 , ..., -0.6814878 ,\n",
" -0.01564899, -0.90746546],\n",
" [-0.5859305 , 1.2421287 , -0.64687246, ..., 0.42634055,\n",
" 1.6927283 , -0.720613 ]], dtype=float32), array([[ 0.8608672 , 0.22756557, -0.64687246, ..., -0.12459313,\n",
" 0.56992066, 0.46668658],\n",
" [ 0.8608672 , 0.22756557, -0.64687246, ..., -0.49513015,\n",
" 0.3803942 , -0.08543972],\n",
" [ 2.3076649 , 0.22756557, 0.9262037 , ..., -0.6206294 ,\n",
" -0.12306548, -1.0812284 ],\n",
" ...,\n",
" [ 0.8608672 , -0.78699756, -0.64687246, ..., 0.9750461 ,\n",
" -0.13686022, -0.79080176],\n",
" [-0.5859305 , 0.22756557, -0.64687246, ..., -0.07434589,\n",
" -0.9413215 , -0.4658303 ],\n",
" [-0.5859305 , 1.2421287 , 2.49928 , ..., -0.7757695 ,\n",
" -0.6835335 , -0.68409824]], dtype=float32), array([[-0.5859305 , -0.78699756, -0.64687246, ..., -0.5901274 ,\n",
" 0.8180325 , 0.4539227 ],\n",
" [ 0.8608672 , -0.78699756, -0.64687246, ..., -0.52065 ,\n",
" -0.44605345, -0.521088 ],\n",
" [-0.5859305 , -0.78699756, 0.9262037 , ..., -0.34475404,\n",
" 1.1586384 , -0.91289103],\n",
" ...,\n",
" [-0.5859305 , 0.22756557, 0.9262037 , ..., -0.34710956,\n",
" 0.9710176 , 2.5397465 ],\n",
" [-0.5859305 , 0.22756557, -0.64687246, ..., -0.83613133,\n",
" -0.68723625, 0.10479005],\n",
" [ 0.8608672 , -0.78699756, -0.64687246, ..., -0.7171131 ,\n",
" 0.7417906 , -0.7008622 ]], dtype=float32)], 'T': [array([[-0.5859305 , 0.22756557, 0.9262037 , ..., -0.3633539 ,\n",
" 0.1948188 , 0.02193698],\n",
" [-0.5859305 , 1.2421287 , -0.64687246, ..., -0.705902 ,\n",
" 0.30386177, 0.34744045],\n",
" [-0.5859305 , 0.22756557, 0.9262037 , ..., -0.4043285 ,\n",
" 0.09212346, -0.4930836 ],\n",
" ...,\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., -0.26974732,\n",
" -0.79244477, -0.25389647],\n",
" [ 0.8608672 , -0.78699756, -0.64687246, ..., -0.51973546,\n",
" -0.8649677 , -0.5824467 ],\n",
" [ 0.8608672 , 3.271255 , -0.64687246, ..., -0.33695364,\n",
" 0.10188962, 0.40707737]], dtype=float32)], 'K': [array([[-0.5859305 , 2.2566917 , -0.64687246, ..., -0.7111183 ,\n",
" -0.50426114, -0.8210089 ],\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., -0.7410174 ,\n",
" -0.310759 , -0.18807623],\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., -0.5855862 ,\n",
" -0.8676304 , -0.9080846 ],\n",
" ...,\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., -0.85047436,\n",
" -0.7591654 , -0.8046305 ],\n",
" [-0.5859305 , -0.78699756, 0.9262037 , ..., -0.67423356,\n",
" 0.28169405, 0.03736721],\n",
" [-0.5859305 , 1.2421287 , 0.9262037 , ..., -0.29457176,\n",
" 1.3935786 , 0.09411274]], dtype=float32)], 'L': [array([[ 0.8608672 , 1.2421287 , -0.64687246, ..., 0.53003913,\n",
" -0.6619846 , -0.03552829],\n",
" [-0.5859305 , 0.22756557, 0.9262037 , ..., -0.38492173,\n",
" -0.45882 , -0.55801874],\n",
" [-0.5859305 , 0.22756557, -0.64687246, ..., -0.09687097,\n",
" -0.9094589 , -0.4827489 ],\n",
" ...,\n",
" [ 0.8608672 , -0.78699756, -0.64687246, ..., -0.36813277,\n",
" -0.6766601 , -0.4744243 ],\n",
" [-0.5859305 , -0.78699756, 2.49928 , ..., -0.10641227,\n",
" -0.6397728 , 0.27117467],\n",
" [ 0.8608672 , -0.78699756, -0.64687246, ..., 0.38900274,\n",
" 1.1399329 , -0.34859538]], dtype=float32)], 'OW': [array([[ 0.8608672 , -0.78699756, -0.64687246, ..., 0.03385801,\n",
" 1.2291765 , -0.43918422],\n",
" [ 0.8608672 , 1.2421287 , 0.9262037 , ..., -0.3641029 ,\n",
" -0.70306057, -0.46431223],\n",
" [ 2.3076649 , -0.78699756, -0.64687246, ..., -0.27893057,\n",
" 1.0241085 , -0.34416828],\n",
" ...,\n",
" [-0.5859305 , 0.22756557, -0.64687246, ..., -0.33649096,\n",
" -0.8570761 , -0.41159987],\n",
" [-0.5859305 , 0.22756557, -0.64687246, ..., -0.3202048 ,\n",
" -0.8541891 , 2.0682847 ],\n",
" [ 2.3076649 , -0.78699756, -0.64687246, ..., 1.5066667 ,\n",
" -1.3127886 , 0.40240076]], dtype=float32)], 'S': [array([[-0.5859305 , -0.78699756, -0.64687246, ..., -0.77958655,\n",
" -0.82638216, -0.1507452 ],\n",
" [-0.5859305 , -0.78699756, 2.49928 , ..., 2.6529667 ,\n",
" 0.25002635, -0.6923333 ],\n",
" [ 3.7544627 , 2.2566917 , -0.64687246, ..., -0.35525125,\n",
" 0.09916719, -0.44539186],\n",
" ...,\n",
" [-0.5859305 , 1.2421287 , 0.9262037 , ..., 5.125832 ,\n",
" -1.2622185 , -0.19771238],\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., 4.6158915 ,\n",
" 0.11883271, 1.9678138 ],\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., 0.0138065 ,\n",
" -0.1297041 , -0.6050371 ]], dtype=float32)], 'ER': [array([[-0.5859305 , -0.78699756, -0.64687246, ..., 0.64779747,\n",
" -1.3509088 , -0.27412868],\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., 3.0947933 ,\n",
" 1.6350334 , -0.2604134 ],\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., -0.50489277,\n",
" -1.0069674 , -0.47088766],\n",
" ...,\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., -0.17216069,\n",
" -0.74435145, 0.07106704],\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., 2.4750865 ,\n",
" -0.6133387 , -0.32327387],\n",
" [-0.5859305 , -0.78699756, -0.64687246, ..., -0.5103371 ,\n",
" -0.8298092 , -0.4389572 ]], dtype=float32)]}\n"
]
}
],
"source": [
"def classify_windows_by_labels(d1):\n",
" seq_class_ids = d1['seq_class_ids'][:d1['seq_len']] # Take only the non-zero part\n",
" windows = create_time_windows(d1)\n",
" \n",
" classified_windows = {}\n",
" for i, label in enumerate(seq_class_ids):\n",
" char = LOGIT_TO_PHONEME[label]\n",
" if char not in classified_windows:\n",
" classified_windows[char] = []\n",
" classified_windows[char].append(windows[i])\n",
" \n",
" return classified_windows\n",
"\n",
"# Example usage\n",
"classified = classify_windows_by_labels(d1)\n",
"print(\"Classified windows by label:\", classified)"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
" 98%|█████████▊| 44/45 [03:08<00:04, 4.99s/it]\n",
"100%|██████████| 45/45 [03:14<00:00, 4.33s/it]\n"
]
}
],
"source": [
"import pandas as pd\n",
"import tqdm\n",
"\n",
"b2txt_csv_df = pd.read_csv('data/t15_copyTaskData_description.csv')\n",
"\n",
"def workflow(max_files=None):\n",
" group_by_labels = {}\n",
" files_to_process = train_list[:max_files] if max_files is not None else train_list\n",
" for file_path in tqdm.tqdm(files_to_process):\n",
" data = load_h5py_file(file_path, b2txt_csv_df)\n",
" for i in tqdm.tqdm(range(len(data['neural_features'])), leave=False):\n",
" # Process only the first trial for simplicity\n",
" d1 = data_patch(data, i)\n",
" classified = classify_windows_by_labels(d1)\n",
" for key, value in classified.items():\n",
" if key not in group_by_labels:\n",
" group_by_labels[key] = []\n",
" group_by_labels[key].extend(value)\n",
" return group_by_labels\n",
"\n",
"# Example usage\n",
"result = workflow()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 核函数扭曲时间\n",
"控制音素时间长度相同"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Total time steps: 7061713, Total windows: 214244, Average window length: 32.96\n"
]
}
],
"source": [
"total = 0\n",
"count = 0\n",
"time_distribution = []\n",
"for i in result.values():\n",
" for j in i:\n",
" total += j.shape[0]\n",
" count += 1\n",
" time_distribution.append(j.shape[0])\n",
"print(f\"Total time steps: {total}, Total windows: {count}, Average window length: {total/count:.2f}\")\n"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAA/8AAAIjCAYAAABViau2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAACU4ElEQVR4nOzdeZyNdf/H8fd1ZjmzGQazkDEmW8gSFSOFksGkhfbIWnFToVQkkcqdst1RU7+ydMddtN+UJVvRaFFSlDtiJIYpyyxmP9fvD82VY5jlzHDM5fV8PObROd/rc33P51zfc04+1/W9rsswTdMUAAAAAACwLYe3EwAAAAAAAGcWxT8AAAAAADZH8Q8AAAAAgM1R/AMAAAAAYHMU/wAAAAAA2BzFPwAAAAAANkfxDwAAAACAzVH8AwAAAABgcxT/AAAAAADYHMU/AOCMmTBhggzDOCuv1alTJ3Xq1Ml6vnbtWhmGoXfeeeesvH7//v1Vr169s/JansrIyNDgwYMVFRUlwzA0YsSIcvW3e/duGYahefPmVUh+54IzMY6V4bNxLps3b54Mw9A333zj7VQAoFKj+AcAlErhP8AL/wICAlS7dm3Fx8frX//6l9LT0yvkdfbt26cJEyZo8+bNFdJfRTqXcyuNZ599VvPmzdPQoUP173//W3379i0SU7jDpqS/E3e0nCt69OihsLAwmabp1v7dd9/JMAzFxMQUWWf16tUyDEOvvvrq2UrTawzD0PDhw72dxmm99NJLttqRBADnGl9vJwAAqFyeeuopxcbGKi8vTykpKVq7dq1GjBihadOm6aOPPlKLFi2s2HHjxumxxx4rU//79u3TxIkTVa9ePbVq1arU661YsaJMr+OJ4nL7v//7P7lcrjOeQ3msXr1a7dq105NPPnnamF69eqlBgwbW84yMDA0dOlQ33XSTevXqZbVHRkYqJiZGWVlZ8vPzO6N5l1aHDh30ySef6Mcff1Tz5s2t9g0bNsjX11d79uzR3r17VadOHbdlhetKlWMc7eqll15SzZo11b9/f2+nAgC2RPEPACiT7t2769JLL7WejxkzRqtXr9Z1112n66+/Xj/99JMCAwMlSb6+vvL1PbP/qzl27JiCgoLk7+9/Rl+nJOdKAVycgwcPqmnTpsXGtGjRwm0Hzh9//KGhQ4eqRYsW6tOnT5H4gICACs/TU4UF/Pr164sU/z169NDq1au1fv163X777day9evXq0aNGmrSpImkyjGOAAB4gmn/AIByu/rqq/XEE08oOTlZb775ptV+qnP+V65cqQ4dOqhatWoKCQlR48aNNXbsWEnHz9O/7LLLJEkDBgywppgXTgXu1KmTLr74Ym3atElXXXWVgoKCrHVPPue/UEFBgcaOHauoqCgFBwfr+uuv12+//eYWU69evVMebTyxz5JyO9V53ZmZmXrooYcUHR0tp9Opxo0b64UXXigyLb1wOvYHH3ygiy++WE6nU82aNdOyZctOvcFPcvDgQQ0aNEiRkZEKCAhQy5YtNX/+fGt54fUPdu3apaVLl1q57969u1T9n86pzvnv37+/QkJCtGfPHl133XUKCQnRBRdcoNmzZ0uSfvjhB1199dUKDg5WTEyMFi5cWKTfI0eOaMSIEdZ2a9CggZ577rkSj8hffvnl8vf3t47mF9qwYYOuuuoqXX755W7LXC6XNm7cqPbt21uf05PHsfA9vvDCC3r11VdVv359OZ1OXXbZZfr666+L5FA4hgEBAbr44ov1/vvvnzLX0nw2evXqpdatW7ut17NnTxmGoY8++shq+/LLL2UYhj755JNit09puFwuzZgxQ82aNVNAQIAiIyN133336fDhw25x9erV03XXXaf169fr8ssvV0BAgC688EK98cYbRfrcsmWLOnbsqMDAQNWpU0dPP/205s6d6/YZrFevnrZu3ap169ad9tSSnJwcjRo1SuHh4QoODtZNN92k1NRUt5hvvvlG8fHxqlmzpgIDAxUbG6uBAweWe7sAgB1w5B8AUCH69u2rsWPHasWKFbrnnntOGbN161Zdd911atGihZ566ik5nU7t2LHDKsiaNGmip556SuPHj9e9996rK6+8UpLUvn17q48///xT3bt31+23364+ffooMjKy2LyeeeYZGYahRx99VAcPHtSMGTPUpUsXbd682ZqhUBqlye1Epmnq+uuv15o1azRo0CC1atVKy5cv1+jRo/X7779r+vTpbvHr16/Xe++9p3/84x+qUqWK/vWvf6l3797as2ePatSocdq8srKy1KlTJ+3YsUPDhw9XbGysFi9erP79++vIkSN68MEH1aRJE/373//WyJEjVadOHT300EOSpPDw8FK//7IoKChQ9+7dddVVV2nKlClasGCBhg8fruDgYD3++OO6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I+eyVYTzZVzPR4ytPTGu9sS42lNlHdfs7Gzt2rVLsbGxCggI8HY65xzTNJWfny9fX18ZhuHtdCqF4j5TZalDK8+3CAAAAAAAeITiHwAAAAAAm6P4BwAAAADA5ij+AQAAAACwOYp/AAAAAABsjuIfAAAAAACb48bZALzKx/DTlTXGW48L5RmGDj73nCIiIiR/f2+lBwAAANgCxT8Ar3IYvmoYcl2R9gKHQ+m9eyuifn0vZAUAAADYC9P+AQAAAACwOYp/AF7lMvP127H1+u3YernMfKvdx3QpaM0aaelSKT+/mB4AAABQWaxdu1b+/v46cuSIJGnevHmqVq2aV3M6X1D8A/CqAjNPK1NHaWXqKBWYeVa7n8tUrXvuka67TsrJ8WKGAAAA54f+/fvLMAwNGTKkyLJhw4bJMAz179+/Ql/ztttu0//+978K7bO0rr/+etWtW1cBAQGqVauW+vbtq3379lnL165dqxtuuEG1atVScHCwWrVqpQULFpTY7549e5SQkKCgoCBFRERo9OjRyj/pYNbatWvVunVrOZ1ONWjQQPPmzavot1cExT8AAAAAQJIUHR2tt956S1lZWVZbdna2Fi5cqLp161b46wUGBh6/wLMXdO7cWYsWLdL27dv17rvvaufOnbr55put5V988YVatGihd999V1u2bNGAAQN09913a8mSJafts6CgQAkJCcrNzdUXX3yh+fPna968eRo/frwVs2vXLiUkJKhz587avHmzRowYocGDB2v58uVn9P1S/AMAAADAWZCZm3nav+z87FLHZuVllSrWE61bt1Z0dLTee+89q+29995T3bp1dckll7jFulwuTZ48WbGxsQoMDFTLli31zjvvuMV8/PHHatSokQIDA9W5c2ft3r3bbfnJ0/537typG264QZGRkQoJCdFll12mTz/91G2devXq6dlnn9XAgQNVpUoV1a1bV6+++mqZ3+vIkSPVrl07xcTEqH379nrssce0ceNG5eUdn406duxYTZo0Se3bt1f9+vX14IMPqlu3bm7b5mQrVqzQtm3b9Oabb6pVq1bq3r27Jk2apNmzZys3N1eSlJiYqNjYWE2dOlVNmjTR8OHDdfPNN2v69Ollfg9lQfEPAAAAAGdByOSQ0/71XtTbLTbihYjTxnZf0N0ttt7MeqeM89TAgQM1d+5c6/mcOXM0YMCAInGTJ0/WG2+8ocTERG3dulUjR45Unz59tG7dOknSb7/9pl69eqlnz57avHmzBg8erDFjxhT72hkZGerRo4dWrVql7777Tt26dVPPnj21Z88et7ipU6fq0ksv1Xfffad//OMfGjp0qLZv324t79SpU5lOUTh06JAWLFig9u3by8/P77RxR48eVfXq1U+7PCkpSc2bN1dkZKTVFh8fr7S0NG3dutWK6dKli9t68fHxSkpKKnW+nqD4BwAAAABY+vTpo/Xr1ys5OVnJycnasGGD+vTp4xaTk5OjZ599VnPmzFF8fLwuvPBC9e/fX3369NErr7wiSXr55ZdVv359TZ06VY0bN9Zdd92lfv36FfvaLVu21H333aeLL75YDRs21KRJk1S/fn199NFHbnE9evTQP/7xDzVo0ECPPvqoatasqTVr1ljL69atq1q1apX4Xh999FEFBwerRo0a2rNnjz788MPTxi5atEhff/31KXeEFEpJSXEr/CVZz1NSUoqNSUtLczvdoqL5nrGeAQAAAACWjDEZp13m4/Bxe37w4YOnjXUY7sdwdz+4u1x5nSw8PFwJCQmaN2+eTNNUQkKCatas6RazY8cOHTt2TNdee61be25urnV6wE8//aS2bdu6LY+Liyv2tTMyMjRhwgQtXbpU+/fvV35+vrKysooc+W/RooX12DAMRUVF6eDBv7fZG2+8Uar3Onr0aA0aNEjJycmaOHGidU6/YRhucWvWrNGAAQP0f//3f2rWrFmp+j7XUPwDAAAAwFkQ7B/s9djSGjhwoIYPHy5Jmj17dpHlGRnHd2QsXbpUF1xwgdsyp9Pp8es+/PDDWrlypV544QU1aNBAgYGBuvnmm63z5QudPDXfMAy5XK4yv17NmjVVs2ZNNWrUSE2aNFF0dLQ2btzotpNi3bp16tmzp6ZPn66777672P6ioqL01VdfubUdOHDAWlb438K2E2NCQ0MVGBhY5vdQWhT/ALzKx/BTu+qjrceF8gxDqU8+qfDwcMnf31vpAQAAnJe6deum3NxcGYah+Pj4IsubNm0qp9OpPXv2qGPHjqfso0mTJkWm62/cuLHY192wYYP69++vm266SdLxnQwnXyTwTCnceZBzwm2m165dq+uuu07PPfec7r333hL7iIuL0zPPPKODBw9adzFYuXKlQkND1bRpUyvm448/dltv5cqVJc6KKC/O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iEfF/1tvvaVFixapR48eFZ0PAAAAAACoYB7d6s/f318NGjSo6FwAAAAAAMAZ4NGR/4ceekgzZ87UrFmzmPIPoFx8jQDdUWe59bjQMcPQnaNfUnid+sr1Dzjd6gAAAABKwaPif/369VqzZo0++eQTNWvWTH5+fm7L33vvvQpJDoD9GYahQJ+wUy1QWnCoAkNPsQwAAABAmXhU/FerVk033XRTRecCAAAAAADOAI/O+Z87d26xf6U1efJkXXbZZapSpYoiIiJ04403avv27W4x2dnZGjZsmGrUqKGQkBD17t1bBw4ccIvZs2ePEhISFBQUpIiICI0ePVr5+fluMWvXrlXr1q3ldDrVoEEDzZs3r0g+s2fPVr169RQQEKC2bdvqq6++Kv1GAeCRAjNXX/w5RV/8OUUFZq7V7m+aGrJ0nu769xT55uUW0wMAAACAknhU/EtSfn6+Pv30U73yyitKT0+XJO3bt08ZGRml7mPdunUaNmyYNm7cqJUrVyovL09du3ZVZmamFTNy5Ej997//1eLFi7Vu3Trt27dPvXr1spYXFBQoISFBubm5+uKLLzR//nzNmzdP48ePt2J27dqlhIQEde7cWZs3b9aIESM0ePBgLV++3Ip5++23NWrUKD355JP69ttv1bJlS8XHx+vgwYOebiIApeAyC/Rzxjv6OeMducwCq93XNHXd15/q6tXvyOEqKKYHAAAAACXxaNp/cnKyunXrpj179ignJ0fXXnutqlSpoueee045OTlKTEwsVT/Lli1zez5v3jxFRERo06ZNuuqqq3T06FG9/vrrWrhwoa6++mpJx2cdNGnSRBs3blS7du20YsUKbdu2TZ9++qkiIyPVqlUrTZo0SY8++qgmTJggf39/JSYmKjY2VlOnTpUkNWnSROvXr9f06dMVHx8vSZo2bZruueceDRgwQJKUmJiopUuXas6cOXrsscc82UwAAAAAAJwTPCr+H3zwQV166aX6/vvvVaNGDav9pptu0j333ONxMkePHpUkVa9eXZK0adMm5eXlqUuXLlbMRRddpLp16yopKUnt2rVTUlKSmjdvrsjISCsmPj5eQ4cO1datW3XJJZcoKSnJrY/CmBEjRkiScnNztWnTJo0ZM8Za7nA41KVLFyUlJZ0y15ycHOXk5FjP09LSJEkul0sul8vjbVDYh2ma5e4H55bKMK6macow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",
"text/plain": [
"<Figure size 1200x600 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Statistics:\n",
"Mean: 32.96\n",
"Median: 32.00\n",
"Std: 8.93\n",
"Min: 4\n",
"Max: 147\n"
]
}
],
"source": [
"import numpy as np\n",
"plt.figure(figsize=(12, 6))\n",
"plt.hist(time_distribution, bins=50, alpha=0.7, edgecolor='black')\n",
"plt.xlabel('Window Length (time steps)')\n",
"plt.ylabel('Frequency')\n",
"plt.title('Distribution of Time Window Lengths')\n",
"plt.grid(True, alpha=0.3)\n",
"plt.axvline(np.mean(time_distribution), color='red', linestyle='--', label=f'Mean: {np.mean(time_distribution):.2f}')\n",
"plt.axvline(np.median(time_distribution), color='green', linestyle='--', label=f'Median: {np.median(time_distribution):.2f}')\n",
"plt.legend()\n",
"plt.show()\n",
"\n",
"print(f\"Statistics:\")\n",
"print(f\"Mean: {np.mean(time_distribution):.2f}\")\n",
"print(f\"Median: {np.median(time_distribution):.2f}\")\n",
"print(f\"Std: {np.std(time_distribution):.2f}\")\n",
"print(f\"Min: {np.min(time_distribution)}\")\n",
"print(f\"Max: {np.max(time_distribution)}\")"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Processing time series with kernel warping...\n",
"Target length: 33\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" 2%|▎ | 1/40 [07:56<5:09:34, 476.28s/it]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Label 'IH': 10561 sequences -> 10561 sequences\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" 5%|▌ | 2/40 [17:51<5:46:00, 546.34s/it]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Label 'T': 13049 sequences -> 13049 sequences\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" 8%|▊ | 3/40 [23:15<4:34:19, 444.86s/it]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Label 'S': 7054 sequences -> 7054 sequences\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" 10%|█ | 4/40 [57:12<10:43:53, 1073.16s/it]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Label ' | ': 50645 sequences -> 50645 sequences\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" 12%|█▎ | 5/40 [1:04:27<8:11:55, 843.31s/it]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Label 'N': 9368 sequences -> 9368 sequences\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" 15%|█▌ | 6/40 [1:06:56<5:44:00, 607.09s/it]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Label 'AA': 3403 sequences -> 3403 sequences\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" 18%|█▊ | 7/40 [1:10:08<4:19:11, 471.26s/it]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Label 'AE': 4373 sequences -> 4373 sequences\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" 20%|██ | 8/40 [1:11:48<3:08:26, 353.34s/it]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Label 'AO': 2341 sequences -> 2341 sequences\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" 22%|██▎ | 9/40 [1:16:34<2:51:38, 332.20s/it]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Label 'L': 6429 sequences -> 6429 sequences\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" 25%|██▌ | 10/40 [1:20:02<2:26:51, 293.72s/it]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Label 'EH': 4589 sequences -> 4589 sequences\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" 28%|██▊ | 11/40 [1:24:31<2:18:22, 286.28s/it]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Label 'IY': 6278 sequences -> 6278 sequences\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" 30%|███ | 12/40 [1:25:26<1:40:43, 215.84s/it]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Label 'TH': 1003 sequences -> 1003 sequences\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" 32%|███▎ | 13/40 [1:26:57<1:20:11, 178.19s/it]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Label 'NG': 2073 sequences -> 2073 sequences\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" 35%|███▌ | 14/40 [1:29:44<1:15:39, 174.61s/it]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Label 'W': 4100 sequences -> 4100 sequences\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" 38%|███▊ | 15/40 [1:32:09<1:09:07, 165.90s/it]"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Label 'ER': 3140 sequences -> 3140 sequences\n"
]
},
{
"ename": "",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[1;31mFailed to connect to the remote Jupyter Server 'https://kkb-production.jupyter-proxy.kaggle.net/k/262561952/eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwidHlwIjoiSldUIn0..Z-5dBJsxDcmNtY3nbL--cg.X81XYIlp4QVNiZ4gVT9gUcxppi5S2UXQBk9KWGk7A9goKDSEx-K__SFKdr5hhp1qeJiXDEqit5DY80I1XK1u-mJgkaBynksn-pr-ZVf-Szr1t_E60DYtUl3UncrqosHLQwqrzSya7TlL6WFQ0r9Pd8GTUxTj4XJtU8mA0GzqgQHs1FReFuGy5dtlD-HObbvy0HYNTMisQd95XP3razjLRmWvh5QduVPP2j9KYrkgtr6KfwW-ucHZ9Azowbg0pFRJ.Hga68c_gnSE6o4_ZxFVl1A/proxy'. Verify the server is running and reachable."
]
}
],
"source": [
"# 把时间序列对齐到这个长度上,然后做聚类去异常值\n",
"MEAN_WINDOWS_SIZE = 33\n",
"\n",
"from scipy import interpolate\n",
"import numpy as np\n",
"\n",
"def kernel_time_warp(sequence, target_length=33):\n",
" \"\"\"\n",
" 使用核函数处理时间序列将序列长度标准化到target_length\n",
" - 对于长度 < target_length 的序列:使用插值扩展\n",
" - 对于长度 > target_length 的序列:使用压缩采样\n",
" - 对于长度 = target_length 的序列:直接返回\n",
" \n",
" Args:\n",
" sequence: 输入时间序列 (time_steps, features)\n",
" target_length: 目标长度\n",
" \n",
" Returns:\n",
" warped_sequence: 处理后的时间序列 (target_length, features)\n",
" \"\"\"\n",
" original_length = sequence.shape[0]\n",
" n_features = sequence.shape[1]\n",
" \n",
" # 如果序列长度已经等于目标长度,直接返回\n",
" if original_length == target_length:\n",
" return sequence\n",
" \n",
" # 处理边界情况\n",
" if original_length == 0:\n",
" return np.zeros((target_length, n_features))\n",
" \n",
" if original_length == 1:\n",
" # 如果只有一个时间步,复制到所有目标时间步\n",
" return np.repeat(sequence, target_length, axis=0)\n",
" \n",
" warped_sequence = np.zeros((target_length, n_features))\n",
" \n",
" if original_length > target_length:\n",
" # 压缩:长序列 -> 短序列\n",
" # 使用均匀采样 + 局部平均的方式压缩\n",
" compression_ratio = original_length / target_length\n",
" \n",
" for i in range(target_length):\n",
" # 计算当前目标位置对应的原始序列范围\n",
" start_idx = int(i * compression_ratio)\n",
" end_idx = int((i + 1) * compression_ratio)\n",
" \n",
" # 确保不超出边界\n",
" start_idx = max(0, start_idx)\n",
" end_idx = min(original_length, end_idx)\n",
" \n",
" if start_idx == end_idx:\n",
" # 避免空范围\n",
" end_idx = min(start_idx + 1, original_length)\n",
" \n",
" # 对该范围内的数据取平均(压缩)\n",
" warped_sequence[i] = np.mean(sequence[start_idx:end_idx], axis=0)\n",
" \n",
" else:\n",
" # 扩展:短序列 -> 长序列\n",
" # 使用插值的方式扩展\n",
" original_indices = np.linspace(0, 1, original_length)\n",
" target_indices = np.linspace(0, 1, target_length)\n",
" \n",
" for feature_idx in range(n_features):\n",
" # 根据原始序列长度选择插值方法\n",
" if original_length >= 3:\n",
" # 对于长度>=3的序列使用三次样条插值\n",
" interpolator = interpolate.interp1d(\n",
" original_indices, \n",
" sequence[:, feature_idx], \n",
" kind='cubic', \n",
" bounds_error=False, \n",
" fill_value='extrapolate'\n",
" )\n",
" else:\n",
" # 对于长度=2的序列使用线性插值\n",
" interpolator = interpolate.interp1d(\n",
" original_indices, \n",
" sequence[:, feature_idx], \n",
" kind='linear', \n",
" bounds_error=False, \n",
" fill_value='extrapolate'\n",
" )\n",
" \n",
" warped_sequence[:, feature_idx] = interpolator(target_indices)\n",
" \n",
" return warped_sequence\n",
"\n",
"def gaussian_kernel_weight(x, sigma=0.1):\n",
" \"\"\"\n",
" 高斯核函数权重,用于平滑处理\n",
" \"\"\"\n",
" return np.exp(-0.5 * (x / sigma) ** 2)\n",
"\n",
"def process_result_with_kernel(result_dict, target_length=33):\n",
" \"\"\"\n",
" 使用核函数处理result字典中的所有时间序列\n",
" \n",
" Args:\n",
" result_dict: 包含时间序列的字典\n",
" target_length: 目标长度\n",
" \n",
" Returns:\n",
" processed_result: 处理后的字典\n",
" \"\"\"\n",
" processed_result = {}\n",
" \n",
" print(\"Processing time series with kernel warping...\")\n",
" print(f\"Target length: {target_length}\")\n",
" \n",
" # 统计不同长度的序列\n",
" length_stats = {}\n",
" total_sequences = 0\n",
" \n",
" for label, sequences in tqdm.tqdm(result_dict.items()):\n",
" processed_sequences = []\n",
" \n",
" for seq in sequences:\n",
" original_length = seq.shape[0]\n",
" \n",
" # 统计长度分布\n",
" if original_length not in length_stats:\n",
" length_stats[original_length] = 0\n",
" length_stats[original_length] += 1\n",
" total_sequences += 1\n",
" \n",
" # 应用核函数时间扭曲(包括压缩和插值)\n",
" warped_seq = kernel_time_warp(seq, target_length)\n",
" processed_sequences.append(warped_seq)\n",
" \n",
" processed_result[label] = processed_sequences\n",
" print(f\"Label '{label}': {len(sequences)} sequences -> {len(processed_sequences)} sequences\")\n",
" \n",
" # 打印长度统计信息\n",
" print(f\"\\n原始序列长度分布:\")\n",
" sorted_lengths = sorted(length_stats.items())\n",
" short_count = sum(count for length, count in sorted_lengths if length < target_length)\n",
" equal_count = sum(count for length, count in sorted_lengths if length == target_length)\n",
" long_count = sum(count for length, count in sorted_lengths if length > target_length)\n",
" \n",
" print(f\"短于目标长度({target_length}),需要插值扩展: {short_count} 个序列\")\n",
" print(f\"等于目标长度({target_length}),无需处理: {equal_count} 个序列\")\n",
" print(f\"长于目标长度({target_length}),需要压缩: {long_count} 个序列\")\n",
" print(f\"总序列数: {total_sequences}\")\n",
" \n",
" if len(sorted_lengths) <= 20: # 如果长度种类不多,显示详细分布\n",
" print(\"\\n详细长度分布:\")\n",
" for length, count in sorted_lengths:\n",
" percentage = (count / total_sequences) * 100\n",
" operation = \"\"\n",
" if length < target_length:\n",
" operation = \" (插值扩展)\"\n",
" elif length > target_length:\n",
" operation = \" (压缩)\"\n",
" else:\n",
" operation = \" (无需处理)\"\n",
" print(f\" 长度 {length}: {count} 个 ({percentage:.1f}%){operation}\")\n",
" \n",
" return processed_result\n",
"\n",
"# 处理result字典\n",
"processed_result = process_result_with_kernel(result, MEAN_WINDOWS_SIZE)\n",
"\n",
"# 验证处理结果\n",
"print(\"\\n处理后的统计信息:\")\n",
"total_sequences = 0\n",
"for label, sequences in processed_result.items():\n",
" total_sequences += len(sequences)\n",
" if sequences: # 如果列表不为空\n",
" print(f\"Label '{label}': {len(sequences)} sequences, shape: {sequences[0].shape}\")\n",
"\n",
"print(f\"总共处理了 {total_sequences} 个时间序列,目标长度: {MEAN_WINDOWS_SIZE}\")\n",
"\n",
"# 验证所有序列现在都是目标长度\n",
"all_correct_length = True\n",
"for label, sequences in processed_result.items():\n",
" for seq in sequences:\n",
" if seq.shape[0] != MEAN_WINDOWS_SIZE:\n",
" print(f\"错误: 发现长度不正确的序列 - Label: {label}, Shape: {seq.shape}\")\n",
" all_correct_length = False\n",
" break\n",
" if not all_correct_length:\n",
" break\n",
"\n",
"if all_correct_length:\n",
" print(f\"✅ 验证通过: 所有序列长度都已正确调整为 {MEAN_WINDOWS_SIZE}\")\n",
" print(\" - 长序列已通过压缩(局部平均)缩短\")\n",
" print(\" - 短序列已通过插值扩展\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"去掉异常的标签去除的时候记得保存正常标签的原始索引我们可能不用去除后的来训练模型。而是训练适应多个时间大小窗口的模型通过单独扫描的WER大小来确定权重。再把两个一起扫描按照权重赋值同样用极大值抑制或者CTC来处理。\n",
"建议CTC。毕竟我们多个长度窗口的模型已经和RNN差距不大了。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Caching the list of root modules, please wait!\n",
"(This will only be done once - type '%rehashx' to reset cache!)\n",
"\n",
"\n",
"Caching the list of root modules, please wait!\n",
"(This will only be done once - type '%rehashx' to reset cache!)\n",
"\n"
]
}
],
"source": [
"# import pickle\n",
"# with open('processed_time_series.pkl', 'wb') as f:\n",
"# pickle.dump(processed_result, f)\n",
" \n",
"# with open('time_series_format.pkl', 'wb') as f:\n",
"# pickle.dump(result, f)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"dict_keys(['IH', 'T', 'S', ' | ', 'N', 'AA', 'AE', 'AO', 'L', 'EH', 'IY', 'TH', 'NG', 'W', 'ER', 'K', 'AH', 'B', 'AW', 'DH', 'EY', 'P', 'R', 'M', 'CH', 'G', 'V', 'D', 'HH', 'Z', 'OW', 'AY', 'F', 'SH', 'UW', 'UH', 'JH', 'ZH', 'Y', 'OY'])"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# processed_result.keys()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"ename": "NameError",
"evalue": "name 'processed_result' is not defined",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m/tmp/ipykernel_36/3504102812.py\u001b[0m in \u001b[0;36m<cell line: 0>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;31m# for key, value in processed_result.items():\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0mkey\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'IH'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m \u001b[0mvalue\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mprocessed_result\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 8\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mf\"Label: {key}, Number of sequences: {len(value)}, Shape of first sequence: {value[0].shape if value else 'N/A'}\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mNameError\u001b[0m: name 'processed_result' is not defined"
]
}
],
"source": [
"from sklearn.cluster import KMeans\n",
"from sklearn.metrics import silhouette_score\n",
"from sklearn.metrics import silhouette_samples\n",
"\n",
"# for key, value in processed_result.items():\n",
"key = 'IH'\n",
"value = processed_result[key]\n",
"print(f\"Label: {key}, Number of sequences: {len(value)}, Shape of first sequence: {value[0].shape if value else 'N/A'}\")\n",
"\n",
"# Apply KMeans clustering to the sequences for the selected label\n",
"\n",
"# First, we need to reshape the sequences to 2D for clustering\n",
"# Since all sequences now have the same length (33), we can flatten them\n",
"sequences = value\n",
"flattened_sequences = []\n",
"\n",
"for seq in sequences:\n",
" # Flatten each sequence to 1D\n",
" flattened_seq = seq.flatten()\n",
" flattened_sequences.append(flattened_seq)\n",
"\n",
"flattened_sequences = np.array(flattened_sequences)\n",
"print(f\"Flattened sequences shape: {flattened_sequences.shape}\")\n",
"\n",
"# Perform KMeans clustering\n",
"n_clusters = 5 # You can adjust this number\n",
"kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init=10)\n",
"cluster_labels = kmeans.fit_predict(flattened_sequences)\n",
"\n",
"# Calculate silhouette score to evaluate clustering quality\n",
"silhouette_avg = silhouette_score(flattened_sequences, cluster_labels)\n",
"\n",
"print(f\"Number of clusters: {n_clusters}\")\n",
"print(f\"Silhouette score: {silhouette_avg:.3f}\")\n",
"print(f\"Cluster distribution: {np.bincount(cluster_labels)}\")\n",
"\n",
"# Visualize clustering results\n",
"plt.figure(figsize=(12, 8))\n",
"\n",
"# Plot 1: Cluster distribution\n",
"plt.subplot(2, 2, 1)\n",
"unique_labels, counts = np.unique(cluster_labels, return_counts=True)\n",
"plt.bar(unique_labels, counts)\n",
"plt.xlabel('Cluster')\n",
"plt.ylabel('Number of Sequences')\n",
"plt.title(f'Cluster Distribution for Label \"{key}\"')\n",
"\n",
"# Plot 2: First few dimensions of the data colored by cluster\n",
"plt.subplot(2, 2, 2)\n",
"for i in range(n_clusters):\n",
" mask = cluster_labels == i\n",
" plt.scatter(flattened_sequences[mask, 0], flattened_sequences[mask, 1], \n",
" label=f'Cluster {i}', alpha=0.6)\n",
"plt.xlabel('Feature 0')\n",
"plt.ylabel('Feature 1')\n",
"plt.title('Clusters in Feature Space (First 2 Dimensions)')\n",
"plt.legend()\n",
"\n",
"# Plot 3: Silhouette analysis\n",
"plt.subplot(2, 2, 3)\n",
"silhouette_vals = silhouette_samples(flattened_sequences, cluster_labels)\n",
"y_lower = 10\n",
"for i in range(n_clusters):\n",
" cluster_silhouette_vals = silhouette_vals[cluster_labels == i]\n",
" cluster_silhouette_vals.sort()\n",
" \n",
" size_cluster_i = cluster_silhouette_vals.shape[0]\n",
" y_upper = y_lower + size_cluster_i\n",
" \n",
" color = plt.cm.nipy_spectral(float(i) / n_clusters)\n",
" plt.fill_betweenx(np.arange(y_lower, y_upper), 0, cluster_silhouette_vals,\n",
" facecolor=color, edgecolor=color, alpha=0.7)\n",
" \n",
" plt.text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))\n",
" y_lower = y_upper + 10\n",
"\n",
"plt.axvline(x=silhouette_avg, color=\"red\", linestyle=\"--\")\n",
"plt.xlabel('Silhouette coefficient values')\n",
"plt.ylabel('Cluster label')\n",
"plt.title('Silhouette Analysis')\n",
"\n",
"# Plot 4: Try different numbers of clusters\n",
"plt.subplot(2, 2, 4)\n",
"cluster_range = range(2, min(11, len(sequences)//2))\n",
"silhouette_scores = []\n",
"inertias = []\n",
"\n",
"for n_clust in cluster_range:\n",
" kmeans_temp = KMeans(n_clusters=n_clust, random_state=42, n_init=10)\n",
" cluster_labels_temp = kmeans_temp.fit_predict(flattened_sequences)\n",
" silhouette_scores.append(silhouette_score(flattened_sequences, cluster_labels_temp))\n",
" inertias.append(kmeans_temp.inertia_)\n",
"\n",
"plt.plot(cluster_range, silhouette_scores, 'bo-')\n",
"plt.xlabel('Number of Clusters')\n",
"plt.ylabel('Average Silhouette Score')\n",
"plt.title('Silhouette Score vs Number of Clusters')\n",
"plt.grid(True)\n",
"\n",
"plt.tight_layout()\n",
"plt.show()\n",
"\n",
"# Print cluster centers information\n",
"print(f\"\\nCluster centers shape: {kmeans.cluster_centers_.shape}\")\n",
"print(f\"Each cluster center represents the average pattern for sequences in that cluster\")"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"======================================================================\n",
"余弦距离分析\n",
"======================================================================\n",
"\n",
"计算余弦距离...\n"
]
},
{
"ename": "NameError",
"evalue": "name 'calculate_inter_class_distances' is not defined",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m/tmp/ipykernel_36/1326706423.py\u001b[0m in \u001b[0;36m<cell line: 0>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;31m# 5. 计算余弦距离\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"\\n计算余弦距离...\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 8\u001b[0;31m \u001b[0mcosine_matrix\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mphonemes_cosine\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcalculate_inter_class_distances\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcentroids\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'cosine'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 9\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;31m# 6. 可视化余弦距离\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mNameError\u001b[0m: name 'calculate_inter_class_distances' is not defined"
]
}
],
"source": [
"# 余弦距离分析和距离度量对比\n",
"print(\"\\n\" + \"=\"*70)\n",
"print(\"余弦距离分析\")\n",
"print(\"=\"*70)\n",
"\n",
"# 5. 计算余弦距离\n",
"print(\"\\n计算余弦距离...\")\n",
"cosine_matrix, phonemes_cosine = calculate_inter_class_distances(centroids, 'cosine')\n",
"\n",
"# 6. 可视化余弦距离\n",
"print(\"\\n可视化余弦距离矩阵...\")\n",
"df_cosine, most_sim_cos, most_diff_cos = visualize_distance_matrix(\n",
" cosine_matrix, phonemes_cosine, 'cosine'\n",
")\n",
"\n",
"# 7. 分析相似音素群组(余弦距离)\n",
"similar_pairs_cos, threshold_cos = analyze_phoneme_groups(cosine_matrix, phonemes_cosine)\n",
"\n",
"print(f\"\\n余弦距离分析完成!\")\n",
"print(f\"最相似音素对: {most_sim_cos}\")\n",
"print(f\"最不相似音素对: {most_diff_cos}\")\n",
"\n",
"# 8. 比较两种距离度量\n",
"print(\"\\n\" + \"=\"*70)\n",
"print(\"距离度量对比分析\")\n",
"print(\"=\"*70)\n",
"\n",
"def compare_distance_metrics(euclidean_matrix, cosine_matrix, phonemes):\n",
" \"\"\"\n",
" 比较不同距离度量的结果\n",
" \"\"\"\n",
" # 提取上三角矩阵的距离值\n",
" upper_triangle_indices = np.triu_indices_from(euclidean_matrix, k=1)\n",
" euclidean_distances = euclidean_matrix[upper_triangle_indices]\n",
" cosine_distances = cosine_matrix[upper_triangle_indices]\n",
" \n",
" # 计算相关性\n",
" correlation = np.corrcoef(euclidean_distances, cosine_distances)[0, 1]\n",
" \n",
" # 创建比较图\n",
" fig, axes = plt.subplots(2, 2, figsize=(16, 12))\n",
" \n",
" # 图1: 距离分布对比\n",
" ax1 = axes[0, 0]\n",
" ax1.hist(euclidean_distances, bins=30, alpha=0.6, label='Euclidean Distance', color='blue')\n",
" ax1.hist(cosine_distances, bins=30, alpha=0.6, label='Cosine Distance', color='red')\n",
" ax1.set_xlabel('Distance Value')\n",
" ax1.set_ylabel('Frequency')\n",
" ax1.set_title('Distance Distribution Comparison')\n",
" ax1.legend()\n",
" ax1.grid(True, alpha=0.3)\n",
" \n",
" # 图2: 距离相关性散点图\n",
" ax2 = axes[0, 1]\n",
" ax2.scatter(euclidean_distances, cosine_distances, alpha=0.6, s=10)\n",
" ax2.set_xlabel('Euclidean Distance')\n",
" ax2.set_ylabel('Cosine Distance')\n",
" ax2.set_title(f'Distance Metric Correlation (r={correlation:.3f})')\n",
" ax2.grid(True, alpha=0.3)\n",
" \n",
" # 添加拟合线\n",
" z = np.polyfit(euclidean_distances, cosine_distances, 1)\n",
" p = np.poly1d(z)\n",
" ax2.plot(euclidean_distances, p(euclidean_distances), \"r--\", alpha=0.8)\n",
" \n",
" # 图3: 最相似音素对比较\n",
" ax3 = axes[1, 0]\n",
" ax3.axis('off')\n",
" \n",
" # 获取每种距离度量下的前10对最相似音素\n",
" eucl_top10 = similar_pairs_eucl[:10]\n",
" cos_top10 = similar_pairs_cos[:10]\n",
" \n",
" comparison_text = \"Most Similar Phoneme Pairs Comparison (Top 10)\\n\\n\"\n",
" comparison_text += f\"{'Euclidean Distance':<30} {'Cosine Distance':<30}\\n\"\n",
" comparison_text += \"-\" * 60 + \"\\n\"\n",
" \n",
" for i in range(min(10, len(eucl_top10), len(cos_top10))):\n",
" eucl_pair = f\"{eucl_top10[i][0]}-{eucl_top10[i][1]} ({eucl_top10[i][2]:.3f})\"\n",
" cos_pair = f\"{cos_top10[i][0]}-{cos_top10[i][1]} ({cos_top10[i][2]:.4f})\"\n",
" comparison_text += f\"{eucl_pair:<30} {cos_pair:<30}\\n\"\n",
" \n",
" ax3.text(0.05, 0.95, comparison_text, transform=ax3.transAxes, fontsize=9,\n",
" verticalalignment='top', fontfamily='monospace',\n",
" bbox=dict(boxstyle='round', facecolor='lightyellow', alpha=0.8))\n",
" \n",
" # 图4: 统计对比\n",
" ax4 = axes[1, 1]\n",
" ax4.axis('off')\n",
" \n",
" # 计算统计信息\n",
" eucl_stats = {\n",
" 'mean': np.mean(euclidean_distances),\n",
" 'median': np.median(euclidean_distances),\n",
" 'std': np.std(euclidean_distances),\n",
" 'min': np.min(euclidean_distances),\n",
" 'max': np.max(euclidean_distances)\n",
" }\n",
" \n",
" cos_stats = {\n",
" 'mean': np.mean(cosine_distances),\n",
" 'median': np.median(cosine_distances),\n",
" 'std': np.std(cosine_distances),\n",
" 'min': np.min(cosine_distances),\n",
" 'max': np.max(cosine_distances)\n",
" }\n",
" \n",
" stats_text = f\"\"\"\n",
"Distance Metric Statistics Comparison\n",
"\n",
"Metric Euclidean Cosine\n",
"{'='*45}\n",
"Mean {eucl_stats['mean']:.4f} {cos_stats['mean']:.4f}\n",
"Median {eucl_stats['median']:.4f} {cos_stats['median']:.4f}\n",
"Std Dev {eucl_stats['std']:.4f} {cos_stats['std']:.4f}\n",
"Min {eucl_stats['min']:.4f} {cos_stats['min']:.4f}\n",
"Max {eucl_stats['max']:.4f} {cos_stats['max']:.4f}\n",
"\n",
"Correlation: {correlation:.4f}\n",
"\n",
"Explanation:\n",
"- Euclidean Distance: Measures straight-line distance in feature space\n",
"- Cosine Distance: Measures angular difference between vectors\n",
"- High correlation indicates similar patterns captured by both metrics\n",
"\"\"\"\n",
" \n",
" ax4.text(0.05, 0.95, stats_text, transform=ax4.transAxes, fontsize=9,\n",
" verticalalignment='top', fontfamily='monospace',\n",
" bbox=dict(boxstyle='round', facecolor='lightcyan', alpha=0.8))\n",
" \n",
" plt.tight_layout()\n",
" plt.show()\n",
" \n",
" return correlation, eucl_stats, cos_stats\n",
"\n",
"# 执行距离度量比较\n",
"correlation, eucl_stats, cos_stats = compare_distance_metrics(\n",
" euclidean_matrix, cosine_matrix, phonemes\n",
")\n",
"\n",
"# 9. 音素聚类分析\n",
"print(\"\\n\" + \"=\"*70)\n",
"print(\"基于距离的音素聚类分析\")\n",
"print(\"=\"*70)\n",
"\n",
"def analyze_phoneme_clusters(distance_matrix, phonemes, n_clusters_range=[3, 4, 5, 6]):\n",
" \"\"\"\n",
" 使用不同数量的聚类分析音素群组\n",
" \"\"\"\n",
" from sklearn.cluster import AgglomerativeClustering\n",
" \n",
" results = {}\n",
" \n",
" fig, axes = plt.subplots(2, 2, figsize=(16, 12))\n",
" axes = axes.flatten()\n",
" \n",
" for i, n_clusters in enumerate(n_clusters_range):\n",
" if i >= 4: # 最多显示4个图\n",
" break\n",
" \n",
" # 执行层次聚类\n",
" clustering = AgglomerativeClustering(\n",
" n_clusters=n_clusters, \n",
" metric='precomputed',\n",
" linkage='average'\n",
" )\n",
" \n",
" cluster_labels = clustering.fit_predict(distance_matrix)\n",
" \n",
" # 分析聚类结果\n",
" clusters = {}\n",
" for phoneme, label in zip(phonemes, cluster_labels):\n",
" if label not in clusters:\n",
" clusters[label] = []\n",
" clusters[label].append(phoneme)\n",
" \n",
" results[n_clusters] = clusters\n",
" \n",
" # 可视化聚类结果\n",
" ax = axes[i]\n",
" \n",
" # 创建颜色映射\n",
" colors = plt.cm.Set3(np.linspace(0, 1, n_clusters))\n",
" \n",
" # 为每个音素分配颜色\n",
" phoneme_colors = [colors[cluster_labels[j]] for j in range(len(phonemes))]\n",
" \n",
" # 使用PCA降维可视化使用质心数据\n",
" from sklearn.decomposition import PCA\n",
" \n",
" # 重新获取质心矩阵\n",
" centroid_matrix = np.array([centroids[phoneme] for phoneme in phonemes])\n",
" \n",
" if centroid_matrix.shape[1] > 2:\n",
" pca = PCA(n_components=2)\n",
" pca_result = pca.fit_transform(centroid_matrix)\n",
" else:\n",
" pca_result = centroid_matrix\n",
" \n",
" # 绘制散点图\n",
" for cluster_id in range(n_clusters):\n",
" mask = cluster_labels == cluster_id\n",
" ax.scatter(pca_result[mask, 0], pca_result[mask, 1], \n",
" c=[colors[cluster_id]], label=f'Cluster {cluster_id}', s=50, alpha=0.7)\n",
" \n",
" # 添加音素标签\n",
" for j, phoneme in enumerate(phonemes):\n",
" if cluster_labels[j] == cluster_id:\n",
" ax.annotate(phoneme, (pca_result[j, 0], pca_result[j, 1]), \n",
" xytext=(5, 5), textcoords='offset points', fontsize=8)\n",
" \n",
" ax.set_title(f'{n_clusters} Clusters')\n",
" ax.set_xlabel('PC1')\n",
" ax.set_ylabel('PC2')\n",
" ax.legend()\n",
" ax.grid(True, alpha=0.3)\n",
" \n",
" plt.tight_layout()\n",
" plt.show()\n",
" \n",
" # 打印聚类结果\n",
" for n_clusters, clusters in results.items():\n",
" print(f\"\\n{n_clusters} 个聚类的结果:\")\n",
" for cluster_id, phonemes_in_cluster in clusters.items():\n",
" print(f\" 聚类 {cluster_id}: {', '.join(phonemes_in_cluster)}\")\n",
" \n",
" return results\n",
"\n",
"# 执行音素聚类分析\n",
"clustering_results = analyze_phoneme_clusters(euclidean_matrix, phonemes)\n",
"\n",
"print(f\"\\n音素类间距离分析完成\")\n",
"print(f\"发现了丰富的音素相似性模式和聚类结构。\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"ename": "",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[1;31mFailed to connect to the remote Jupyter Server 'https://kkb-production.jupyter-proxy.kaggle.net/'. Verify the server is running and reachable. (Failed to connect to the remote Jupyter Server 'https://kkb-production.jupyter-proxy.kaggle.net/'. Verify the server is running and reachable. (Invalid response: 404 Not Found).)."
]
}
],
"source": [
"# 优化的DBSCAN异常值检测分析\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from sklearn.cluster import DBSCAN\n",
"from sklearn.preprocessing import StandardScaler\n",
"from sklearn.decomposition import PCA\n",
"from sklearn.metrics import silhouette_score\n",
"import pandas as pd\n",
"\n",
"print(\"=\"*70)\n",
"print(\"优化的DBSCAN异常值检测分析\")\n",
"print(\"=\"*70)\n",
"\n",
"def determine_optimal_pca_components(data, min_variance_ratio=0.80, max_components=500):\n",
" \"\"\"\n",
" 确定最优的PCA组件数保证解释方差比达到要求\n",
" \"\"\"\n",
" print(f\"原始数据维度: {data.shape}\")\n",
" \n",
" # 先用少量组件快速估计\n",
" n_samples, n_features = data.shape\n",
" \n",
" # 确保组件数不超过样本数和特征数的最小值\n",
" max_possible_components = min(n_samples, n_features, max_components)\n",
" \n",
" # 快速测试不同的组件数\n",
" test_components = [50, 100, 200, 300, 400, 500]\n",
" test_components = [c for c in test_components if c <= max_possible_components]\n",
" \n",
" if not test_components:\n",
" test_components = [min(50, max_possible_components)]\n",
" \n",
" print(f\"测试的组件数: {test_components}\")\n",
" \n",
" best_components = test_components[0]\n",
" best_ratio = 0\n",
" \n",
" for n_comp in test_components:\n",
" pca_temp = PCA(n_components=n_comp, random_state=42)\n",
" pca_temp.fit(data)\n",
" variance_ratio = np.sum(pca_temp.explained_variance_ratio_)\n",
" \n",
" print(f\" {n_comp} 组件: 解释方差比 = {variance_ratio:.4f}\")\n",
" \n",
" if variance_ratio >= min_variance_ratio:\n",
" best_components = n_comp\n",
" best_ratio = variance_ratio\n",
" break\n",
" elif variance_ratio > best_ratio:\n",
" best_components = n_comp\n",
" best_ratio = variance_ratio\n",
" \n",
" print(f\"选择 {best_components} 个组件 (解释方差比: {best_ratio:.4f})\")\n",
" return best_components\n",
"\n",
"def smart_dbscan_outlier_detection(processed_result, target_phonemes=None, min_variance_ratio=0.75):\n",
" \"\"\"\n",
" 智能DBSCAN异常值检测使用合理的PCA降维\n",
" \"\"\"\n",
" outlier_results = {}\n",
" \n",
" # 如果没有指定目标音素,选择样本数适中的音素\n",
" if target_phonemes is None:\n",
" phoneme_counts = [(p, len(seqs)) for p, seqs in processed_result.items()]\n",
" # 选择样本数在50-1000之间的音素\n",
" target_phonemes = [p for p, count in phoneme_counts if 50 <= count <= 1000]\n",
" target_phonemes = target_phonemes[:5] # 最多处理5个音素\n",
" \n",
" print(f\"将处理的音素: {target_phonemes}\")\n",
" \n",
" for phoneme in target_phonemes:\n",
" if phoneme not in processed_result:\n",
" continue\n",
" \n",
" sequences = processed_result[phoneme]\n",
" print(f\"\\n\" + \"=\"*50)\n",
" print(f\"分析音素 '{phoneme}' ({len(sequences)} 个样本)\")\n",
" print(\"=\"*50)\n",
" \n",
" # 展平序列数据\n",
" flattened_sequences = []\n",
" for seq in sequences:\n",
" flattened_sequences.append(seq.flatten())\n",
" \n",
" flattened_sequences = np.array(flattened_sequences)\n",
" print(f\"原始数据形状: {flattened_sequences.shape}\")\n",
" \n",
" # 标准化数据\n",
" scaler = StandardScaler()\n",
" scaled_data = scaler.fit_transform(flattened_sequences)\n",
" \n",
" # 智能确定PCA组件数\n",
" optimal_components = determine_optimal_pca_components(\n",
" scaled_data, min_variance_ratio=min_variance_ratio\n",
" )\n",
" \n",
" # 执行PCA降维\n",
" pca = PCA(n_components=optimal_components, random_state=42)\n",
" pca_data = pca.fit_transform(scaled_data)\n",
" variance_explained = np.sum(pca.explained_variance_ratio_)\n",
" \n",
" print(f\"PCA降维结果:\")\n",
" print(f\" 原始维度: {scaled_data.shape[1]}\")\n",
" print(f\" 降维后: {pca_data.shape[1]}\")\n",
" print(f\" 解释方差比: {variance_explained:.4f}\")\n",
" print(f\" 信息保留率: {variance_explained*100:.2f}%\")\n",
" \n",
" # 使用简化的DBSCAN参数搜索\n",
" print(f\"\\n开始DBSCAN参数搜索...\")\n",
" \n",
" # 基于数据估计合理的eps范围\n",
" from sklearn.neighbors import NearestNeighbors\n",
" k = min(10, len(sequences)//10)\n",
" nbrs = NearestNeighbors(n_neighbors=k)\n",
" nbrs.fit(pca_data)\n",
" distances, _ = nbrs.kneighbors(pca_data)\n",
" k_distances = np.sort(distances[:, k-1])\n",
" \n",
" # 选择eps候选值\n",
" eps_candidates = [\n",
" np.percentile(k_distances, 25),\n",
" np.percentile(k_distances, 50),\n",
" np.percentile(k_distances, 75),\n",
" np.percentile(k_distances, 90)\n",
" ]\n",
" \n",
" min_samples_candidates = [5, 10, 15, 20]\n",
" \n",
" print(f\"eps候选值: {[f'{e:.3f}' for e in eps_candidates]}\")\n",
" print(f\"min_samples候选值: {min_samples_candidates}\")\n",
" \n",
" best_score = -1\n",
" best_result = None\n",
" \n",
" for eps in eps_candidates:\n",
" for min_samples in min_samples_candidates:\n",
" if min_samples >= len(sequences) // 5: # min_samples不能太大\n",
" continue\n",
" \n",
" dbscan = DBSCAN(eps=eps, min_samples=min_samples)\n",
" labels = dbscan.fit_predict(pca_data)\n",
" \n",
" n_outliers = np.sum(labels == -1)\n",
" n_clusters = len(set(labels)) - (1 if -1 in labels else 0)\n",
" outlier_ratio = n_outliers / len(labels)\n",
" \n",
" # 计算评分\n",
" if n_clusters > 0 and 0.05 <= outlier_ratio <= 0.40: # 异常值比例在5%-40%之间\n",
" try:\n",
" if len(set(labels[labels != -1])) > 1:\n",
" silhouette = silhouette_score(pca_data[labels != -1], labels[labels != -1])\n",
" else:\n",
" silhouette = 0.5 # 单聚类给中等分数\n",
" except:\n",
" silhouette = 0\n",
" \n",
" # 综合评分:轮廓系数 + 合理的异常值比例奖励\n",
" if 0.1 <= outlier_ratio <= 0.25: # 最理想的异常值比例\n",
" ratio_bonus = 0.2\n",
" else:\n",
" ratio_bonus = 0.1\n",
" \n",
" score = silhouette + ratio_bonus\n",
" \n",
" if score > best_score:\n",
" best_score = score\n",
" best_result = {\n",
" 'eps': eps,\n",
" 'min_samples': min_samples,\n",
" 'labels': labels.copy(),\n",
" 'outliers': np.where(labels == -1)[0],\n",
" 'n_clusters': n_clusters,\n",
" 'outlier_ratio': outlier_ratio,\n",
" 'silhouette': silhouette\n",
" }\n",
" \n",
" print(f\" eps={eps:.3f}, min_samples={min_samples}: \"\n",
" f\"{n_clusters}聚类, {n_outliers}异常值 ({outlier_ratio*100:.1f}%)\")\n",
" \n",
" if best_result is not None:\n",
" outlier_results[phoneme] = {\n",
" **best_result,\n",
" 'pca_data': pca_data,\n",
" 'pca_model': pca,\n",
" 'variance_explained': variance_explained,\n",
" 'original_data': flattened_sequences,\n",
" 'scaled_data': scaled_data\n",
" }\n",
" \n",
" print(f\"\\n✅ 找到最佳参数:\")\n",
" print(f\" eps: {best_result['eps']:.3f}\")\n",
" print(f\" min_samples: {best_result['min_samples']}\")\n",
" print(f\" 聚类数: {best_result['n_clusters']}\")\n",
" print(f\" 异常值: {len(best_result['outliers'])} ({best_result['outlier_ratio']*100:.1f}%)\")\n",
" print(f\" 轮廓系数: {best_result['silhouette']:.3f}\")\n",
" print(f\" 综合评分: {best_score:.3f}\")\n",
" else:\n",
" print(f\"\\n❌ 未找到合适的DBSCAN参数\")\n",
" \n",
" return outlier_results\n",
"\n",
"def visualize_smart_dbscan_results(outlier_results):\n",
" \"\"\"\n",
" 可视化智能DBSCAN结果\n",
" \"\"\"\n",
" if not outlier_results:\n",
" print(\"没有结果可可视化\")\n",
" return\n",
" \n",
" n_phonemes = len(outlier_results)\n",
" fig, axes = plt.subplots(2, n_phonemes, figsize=(6*n_phonemes, 10))\n",
" \n",
" if n_phonemes == 1:\n",
" axes = axes.reshape(2, 1)\n",
" \n",
" for i, (phoneme, result) in enumerate(outlier_results.items()):\n",
" # 上图PCA散点图\n",
" ax1 = axes[0, i]\n",
" pca_data = result['pca_data']\n",
" labels = result['labels']\n",
" \n",
" # 绘制聚类\n",
" unique_labels = set(labels)\n",
" colors = plt.cm.Set3(np.linspace(0, 1, len(unique_labels)))\n",
" \n",
" for j, label in enumerate(unique_labels):\n",
" if label == -1:\n",
" mask = labels == label\n",
" ax1.scatter(pca_data[mask, 0], pca_data[mask, 1], \n",
" c='red', marker='x', s=60, label='Outliers', alpha=0.8)\n",
" else:\n",
" mask = labels == label\n",
" ax1.scatter(pca_data[mask, 0], pca_data[mask, 1], \n",
" c=[colors[j]], label=f'Cluster {label}', alpha=0.7, s=30)\n",
" \n",
" ax1.set_title(f'Phoneme \"{phoneme}\" DBSCAN Results\\n'\n",
" f'{result[\"n_clusters\"]} Clusters, {len(result[\"outliers\"])} Outliers '\n",
" f'({result[\"outlier_ratio\"]*100:.1f}%)')\n",
" ax1.set_xlabel('PC1')\n",
" ax1.set_ylabel('PC2')\n",
" ax1.legend()\n",
" ax1.grid(True, alpha=0.3)\n",
" \n",
" # 下图:方差解释图\n",
" ax2 = axes[1, i]\n",
" pca_model = result['pca_model']\n",
" n_components = len(pca_model.explained_variance_ratio_)\n",
" \n",
" # 绘制累计方差解释比\n",
" cumsum_var = np.cumsum(pca_model.explained_variance_ratio_)\n",
" ax2.plot(range(1, n_components+1), cumsum_var, 'b-', marker='o')\n",
" ax2.axhline(y=0.8, color='r', linestyle='--', label='80% Threshold')\n",
" ax2.axhline(y=0.9, color='g', linestyle='--', label='90% Threshold')\n",
" \n",
" ax2.set_xlabel('Number of Components')\n",
" ax2.set_ylabel('Cumulative Explained Variance')\n",
" ax2.set_title(f'PCA Variance Explained (Total: {result[\"variance_explained\"]:.3f})')\n",
" ax2.legend()\n",
" ax2.grid(True, alpha=0.3)\n",
" ax2.set_ylim(0, 1)\n",
" \n",
" plt.tight_layout()\n",
" plt.show()\n",
"\n",
"def analyze_outliers_detailed(outlier_results):\n",
" \"\"\"\n",
" 详细分析异常值\n",
" \"\"\"\n",
" print(\"\\n\" + \"=\"*70)\n",
" print(\"详细异常值分析报告\")\n",
" print(\"=\"*70)\n",
" \n",
" for phoneme, result in outlier_results.items():\n",
" print(f\"\\n音素 '{phoneme}' 异常值分析:\")\n",
" print(\"-\" * 40)\n",
" \n",
" outlier_indices = result['outliers']\n",
" normal_indices = [i for i in range(len(result['labels'])) if i not in outlier_indices]\n",
" \n",
" print(f\"总样本数: {len(result['labels'])}\")\n",
" print(f\"正常样本: {len(normal_indices)} ({len(normal_indices)/len(result['labels'])*100:.1f}%)\")\n",
" print(f\"异常样本: {len(outlier_indices)} ({len(outlier_indices)/len(result['labels'])*100:.1f}%)\")\n",
" print(f\"聚类数量: {result['n_clusters']}\")\n",
" print(f\"PCA维度: {result['pca_data'].shape[1]}\")\n",
" print(f\"信息保留: {result['variance_explained']*100:.2f}%\")\n",
" \n",
" # 分析异常值的特征\n",
" if len(outlier_indices) > 0:\n",
" outlier_data = result['pca_data'][outlier_indices]\n",
" normal_data = result['pca_data'][normal_indices] if len(normal_indices) > 0 else None\n",
" \n",
" print(f\"\\n异常值特征分析:\")\n",
" print(f\" PC1均值: {np.mean(outlier_data[:, 0]):.3f} ± {np.std(outlier_data[:, 0]):.3f}\")\n",
" print(f\" PC2均值: {np.mean(outlier_data[:, 1]):.3f} ± {np.std(outlier_data[:, 1]):.3f}\")\n",
" \n",
" if normal_data is not None:\n",
" print(f\"正常值特征对比:\")\n",
" print(f\" PC1均值: {np.mean(normal_data[:, 0]):.3f} ± {np.std(normal_data[:, 0]):.3f}\")\n",
" print(f\" PC2均值: {np.mean(normal_data[:, 1]):.3f} ± {np.std(normal_data[:, 1]):.3f}\")\n",
"\n",
"# 执行优化的DBSCAN异常值检测\n",
"print(\"开始智能DBSCAN异常值检测...\")\n",
"\n",
"# 选择几个有代表性的音素进行分析\n",
"target_phonemes = ['IH', 'T', 'S', 'N', 'AH'] # 手动选择一些常见音素\n",
"\n",
"outlier_results = smart_dbscan_outlier_detection(\n",
" processed_result, \n",
" target_phonemes=target_phonemes,\n",
" min_variance_ratio=0.75 # 保留至少75%的方差\n",
")\n",
"\n",
"if outlier_results:\n",
" print(f\"\\n✅ 成功检测到 {len(outlier_results)} 个音素的异常值!\")\n",
" \n",
" # 可视化结果\n",
" visualize_smart_dbscan_results(outlier_results)\n",
" \n",
" # 详细分析\n",
" analyze_outliers_detailed(outlier_results)\n",
" \n",
" print(f\"\\n📊 异常值检测总结:\")\n",
" for phoneme, result in outlier_results.items():\n",
" print(f\" {phoneme}: {len(result['outliers'])}/{len(result['labels'])} \"\n",
" f\"({result['outlier_ratio']*100:.1f}%) 异常值\")\n",
" \n",
"else:\n",
" print(\"❌ 未检测到任何有效的异常值结果\")\n",
"\n",
"print(f\"\\n💡 关键改进:\")\n",
"print(f\"1. 使用自适应PCA降维保留75%以上的方差信息\")\n",
"print(f\"2. 基于数据分布智能选择DBSCAN参数\")\n",
"print(f\"3. 合理的异常值比例范围(5%-40%)\")\n",
"print(f\"4. 综合评分机制平衡聚类质量和异常值检测\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"======================================================================\n",
"类内相似度分析 - 音素分类有效性评估\n",
"======================================================================\n",
"开始类内相似度分析...\n",
"\n",
"1. 计算各音素类内相似度\n",
"使用 cosine 相似度度量\n",
"每个音素最多分析 300 个样本\n",
"--------------------------------------------------\n",
"音素 'IH': 平均相似度=0.0330 ± 0.0322, 中位数=0.0234, 样本数=300\n",
"音素 'T': 平均相似度=0.0317 ± 0.0315, 中位数=0.0216, 样本数=300\n",
"音素 'S': 平均相似度=0.0297 ± 0.0300, 中位数=0.0208, 样本数=300\n",
"音素 ' | ': 平均相似度=0.0346 ± 0.0336, 中位数=0.0236, 样本数=300\n",
"音素 'N': 平均相似度=0.0321 ± 0.0310, 中位数=0.0228, 样本数=300\n",
"音素 'AA': 平均相似度=0.0260 ± 0.0260, 中位数=0.0182, 样本数=300\n",
"音素 'AE': 平均相似度=0.0261 ± 0.0265, 中位数=0.0180, 样本数=300\n",
"音素 'AO': 平均相似度=0.0298 ± 0.0300, 中位数=0.0202, 样本数=300\n",
"音素 'L': 平均相似度=0.0323 ± 0.0333, 中位数=0.0215, 样本数=300\n",
"音素 'EH': 平均相似度=0.0342 ± 0.0298, 中位数=0.0263, 样本数=300\n",
"音素 'IY': 平均相似度=0.0302 ± 0.0298, 中位数=0.0209, 样本数=300\n",
"音素 'TH': 平均相似度=0.0299 ± 0.0321, 中位数=0.0190, 样本数=176\n",
"音素 'NG': 平均相似度=0.0354 ± 0.0365, 中位数=0.0238, 样本数=300\n",
"音素 'W': 平均相似度=0.0329 ± 0.0316, 中位数=0.0227, 样本数=300\n",
"音素 'ER': 平均相似度=0.0327 ± 0.0314, 中位数=0.0231, 样本数=300\n",
"音素 'K': 平均相似度=0.0289 ± 0.0292, 中位数=0.0200, 样本数=300\n",
"音素 'AH': 平均相似度=0.0324 ± 0.0290, 中位数=0.0242, 样本数=300\n",
"音素 'B': 平均相似度=0.0327 ± 0.0318, 中位数=0.0232, 样本数=300\n",
"音素 'AW': 平均相似度=0.0399 ± 0.0331, 中位数=0.0313, 样本数=239\n",
"音素 'DH': 平均相似度=0.0349 ± 0.0310, 中位数=0.0253, 样本数=300\n",
"音素 'EY': 平均相似度=0.0372 ± 0.0320, 中位数=0.0283, 样本数=300\n",
"音素 'P': 平均相似度=0.0305 ± 0.0300, 中位数=0.0217, 样本数=300\n",
"音素 'R': 平均相似度=0.0310 ± 0.0298, 中位数=0.0217, 样本数=300\n",
"音素 'M': 平均相似度=0.0301 ± 0.0294, 中位数=0.0205, 样本数=300\n",
"音素 'CH': 平均相似度=0.0352 ± 0.0340, 中位数=0.0245, 样本数=132\n",
"音素 'G': 平均相似度=0.0266 ± 0.0287, 中位数=0.0176, 样本数=300\n",
"音素 'V': 平均相似度=0.0280 ± 0.0298, 中位数=0.0187, 样本数=300\n",
"音素 'D': 平均相似度=0.0334 ± 0.0314, 中位数=0.0239, 样本数=300\n",
"音素 'HH': 平均相似度=0.0294 ± 0.0279, 中位数=0.0207, 样本数=300\n",
"音素 'Z': 平均相似度=0.0310 ± 0.0309, 中位数=0.0210, 样本数=300\n",
"音素 'OW': 平均相似度=0.0332 ± 0.0321, 中位数=0.0229, 样本数=300\n",
"音素 'AY': 平均相似度=0.0374 ± 0.0302, 中位数=0.0299, 样本数=300\n",
"音素 'F': 平均相似度=0.0275 ± 0.0285, 中位数=0.0189, 样本数=300\n",
"音素 'SH': 平均相似度=0.0401 ± 0.0381, 中位数=0.0268, 样本数=121\n",
"音素 'UW': 平均相似度=0.0264 ± 0.0259, 中位数=0.0189, 样本数=300\n",
"音素 'UH': 平均相似度=0.0243 ± 0.0247, 中位数=0.0167, 样本数=200\n",
"音素 'JH': 平均相似度=0.0319 ± 0.0333, 中位数=0.0213, 样本数=156\n",
"音素 'ZH': 平均相似度=0.0344 ± 0.0309, 中位数=0.0248, 样本数=70\n",
"音素 'Y': 平均相似度=0.0337 ± 0.0330, 中位数=0.0227, 样本数=300\n",
"音素 'OY': 平均相似度=0.0386 ± 0.0375, 中位数=0.0264, 样本数=111\n",
"\n",
"2. 计算全体音素相似度作为基线\n",
"\n",
"计算全体音素相似度 (每个音素采样 30 个)\n",
"--------------------------------------------------\n",
"总共收集了 1200 个序列,来自 40 个音素\n",
"全体音素: 平均相似度=0.0326 ± 0.0310, 中位数=0.0231, 样本数=1200\n",
"\n",
"3. 可视化相似度比较\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 38899 (\\N{CJK UNIFIED IDEOGRAPH-97F3}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 32032 (\\N{CJK UNIFIED IDEOGRAPH-7D20}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 30456 (\\N{CJK UNIFIED IDEOGRAPH-76F8}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 20284 (\\N{CJK UNIFIED IDEOGRAPH-4F3C}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 24230 (\\N{CJK UNIFIED IDEOGRAPH-5EA6}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 21508 (\\N{CJK UNIFIED IDEOGRAPH-5404}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 31867 (\\N{CJK UNIFIED IDEOGRAPH-7C7B}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 20869 (\\N{CJK UNIFIED IDEOGRAPH-5185}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 20840 (\\N{CJK UNIFIED IDEOGRAPH-5168}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 20307 (\\N{CJK UNIFIED IDEOGRAPH-4F53}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 24179 (\\N{CJK UNIFIED IDEOGRAPH-5E73}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 22343 (\\N{CJK UNIFIED IDEOGRAPH-5747}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 33539 (\\N{CJK UNIFIED IDEOGRAPH-8303}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 22260 (\\N{CJK UNIFIED IDEOGRAPH-56F4}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 25552 (\\N{CJK UNIFIED IDEOGRAPH-63D0}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 21319 (\\N{CJK UNIFIED IDEOGRAPH-5347}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 23545 (\\N{CJK UNIFIED IDEOGRAPH-5BF9}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 20110 (\\N{CJK UNIFIED IDEOGRAPH-4E8E}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 20998 (\\N{CJK UNIFIED IDEOGRAPH-5206}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 30340 (\\N{CJK UNIFIED IDEOGRAPH-7684}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 25928 (\\N{CJK UNIFIED IDEOGRAPH-6548}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 26524 (\\N{CJK UNIFIED IDEOGRAPH-679C}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 26679 (\\N{CJK UNIFIED IDEOGRAPH-6837}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 26412 (\\N{CJK UNIFIED IDEOGRAPH-672C}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 25968 (\\N{CJK UNIFIED IDEOGRAPH-6570}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 37327 (\\N{CJK UNIFIED IDEOGRAPH-91CF}) missing from font(s) DejaVu Sans.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 31867 (\\N{CJK UNIFIED IDEOGRAPH-7C7B}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 20869 (\\N{CJK UNIFIED IDEOGRAPH-5185}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 30456 (\\N{CJK UNIFIED IDEOGRAPH-76F8}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 20284 (\\N{CJK UNIFIED IDEOGRAPH-4F3C}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 24230 (\\N{CJK UNIFIED IDEOGRAPH-5EA6}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 20998 (\\N{CJK UNIFIED IDEOGRAPH-5206}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 26512 (\\N{CJK UNIFIED IDEOGRAPH-6790}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 32479 (\\N{CJK UNIFIED IDEOGRAPH-7EDF}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 35745 (\\N{CJK UNIFIED IDEOGRAPH-8BA1}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 25253 (\\N{CJK UNIFIED IDEOGRAPH-62A5}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 21578 (\\N{CJK UNIFIED IDEOGRAPH-544A}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 37327 (\\N{CJK UNIFIED IDEOGRAPH-91CF}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 26041 (\\N{CJK UNIFIED IDEOGRAPH-65B9}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 27861 (\\N{CJK UNIFIED IDEOGRAPH-6CD5}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 20840 (\\N{CJK UNIFIED IDEOGRAPH-5168}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 20307 (\\N{CJK UNIFIED IDEOGRAPH-4F53}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 38899 (\\N{CJK UNIFIED IDEOGRAPH-97F3}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 32032 (\\N{CJK UNIFIED IDEOGRAPH-7D20}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 22522 (\\N{CJK UNIFIED IDEOGRAPH-57FA}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 32447 (\\N{CJK UNIFIED IDEOGRAPH-7EBF}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 24179 (\\N{CJK UNIFIED IDEOGRAPH-5E73}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 22343 (\\N{CJK UNIFIED IDEOGRAPH-5747}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 26679 (\\N{CJK UNIFIED IDEOGRAPH-6837}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 26412 (\\N{CJK UNIFIED IDEOGRAPH-672C}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 24635 (\\N{CJK UNIFIED IDEOGRAPH-603B}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 25968 (\\N{CJK UNIFIED IDEOGRAPH-6570}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 25928 (\\N{CJK UNIFIED IDEOGRAPH-6548}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 26524 (\\N{CJK UNIFIED IDEOGRAPH-679C}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 25552 (\\N{CJK UNIFIED IDEOGRAPH-63D0}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 21319 (\\N{CJK UNIFIED IDEOGRAPH-5347}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 26368 (\\N{CJK UNIFIED IDEOGRAPH-6700}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 22823 (\\N{CJK UNIFIED IDEOGRAPH-5927}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 23567 (\\N{CJK UNIFIED IDEOGRAPH-5C0F}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 19979 (\\N{CJK UNIFIED IDEOGRAPH-4E0B}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 38477 (\\N{CJK UNIFIED IDEOGRAPH-964D}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 32467 (\\N{CJK UNIFIED IDEOGRAPH-7ED3}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 35770 (\\N{CJK UNIFIED IDEOGRAPH-8BBA}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 10060 (\\N{CROSS MARK}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 26377 (\\N{CJK UNIFIED IDEOGRAPH-6709}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 38480 (\\N{CJK UNIFIED IDEOGRAPH-9650}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 21487 (\\N{CJK UNIFIED IDEOGRAPH-53EF}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 33021 (\\N{CJK UNIFIED IDEOGRAPH-80FD}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 38656 (\\N{CJK UNIFIED IDEOGRAPH-9700}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 35201 (\\N{CJK UNIFIED IDEOGRAPH-8981}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 37325 (\\N{CJK UNIFIED IDEOGRAPH-91CD}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 26032 (\\N{CJK UNIFIED IDEOGRAPH-65B0}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 32771 (\\N{CJK UNIFIED IDEOGRAPH-8003}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 34385 (\\N{CJK UNIFIED IDEOGRAPH-8651}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 31574 (\\N{CJK UNIFIED IDEOGRAPH-7B56}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/tmp/ipykernel_331/2550486954.py:262: UserWarning: Glyph 30053 (\\N{CJK UNIFIED IDEOGRAPH-7565}) missing from font(s) DejaVu Sans Mono.\n",
" plt.tight_layout()\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 30456 (\\N{CJK UNIFIED IDEOGRAPH-76F8}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 20284 (\\N{CJK UNIFIED IDEOGRAPH-4F3C}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 24230 (\\N{CJK UNIFIED IDEOGRAPH-5EA6}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 21508 (\\N{CJK UNIFIED IDEOGRAPH-5404}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 38899 (\\N{CJK UNIFIED IDEOGRAPH-97F3}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 32032 (\\N{CJK UNIFIED IDEOGRAPH-7D20}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 31867 (\\N{CJK UNIFIED IDEOGRAPH-7C7B}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 20869 (\\N{CJK UNIFIED IDEOGRAPH-5185}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 20840 (\\N{CJK UNIFIED IDEOGRAPH-5168}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 20307 (\\N{CJK UNIFIED IDEOGRAPH-4F53}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 24179 (\\N{CJK UNIFIED IDEOGRAPH-5E73}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 22343 (\\N{CJK UNIFIED IDEOGRAPH-5747}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 33539 (\\N{CJK UNIFIED IDEOGRAPH-8303}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 22260 (\\N{CJK UNIFIED IDEOGRAPH-56F4}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 25552 (\\N{CJK UNIFIED IDEOGRAPH-63D0}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 21319 (\\N{CJK UNIFIED IDEOGRAPH-5347}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 23545 (\\N{CJK UNIFIED IDEOGRAPH-5BF9}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 20110 (\\N{CJK UNIFIED IDEOGRAPH-4E8E}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 20998 (\\N{CJK UNIFIED IDEOGRAPH-5206}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 30340 (\\N{CJK UNIFIED IDEOGRAPH-7684}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 25928 (\\N{CJK UNIFIED IDEOGRAPH-6548}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 26524 (\\N{CJK UNIFIED IDEOGRAPH-679C}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 26679 (\\N{CJK UNIFIED IDEOGRAPH-6837}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 26412 (\\N{CJK UNIFIED IDEOGRAPH-672C}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 25968 (\\N{CJK UNIFIED IDEOGRAPH-6570}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 37327 (\\N{CJK UNIFIED IDEOGRAPH-91CF}) missing from font(s) DejaVu Sans.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 31867 (\\N{CJK UNIFIED IDEOGRAPH-7C7B}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 20869 (\\N{CJK UNIFIED IDEOGRAPH-5185}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 30456 (\\N{CJK UNIFIED IDEOGRAPH-76F8}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 20284 (\\N{CJK UNIFIED IDEOGRAPH-4F3C}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 24230 (\\N{CJK UNIFIED IDEOGRAPH-5EA6}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 20998 (\\N{CJK UNIFIED IDEOGRAPH-5206}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 26512 (\\N{CJK UNIFIED IDEOGRAPH-6790}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 32479 (\\N{CJK UNIFIED IDEOGRAPH-7EDF}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 35745 (\\N{CJK UNIFIED IDEOGRAPH-8BA1}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 25253 (\\N{CJK UNIFIED IDEOGRAPH-62A5}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 21578 (\\N{CJK UNIFIED IDEOGRAPH-544A}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 37327 (\\N{CJK UNIFIED IDEOGRAPH-91CF}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 26041 (\\N{CJK UNIFIED IDEOGRAPH-65B9}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 27861 (\\N{CJK UNIFIED IDEOGRAPH-6CD5}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 20840 (\\N{CJK UNIFIED IDEOGRAPH-5168}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 20307 (\\N{CJK UNIFIED IDEOGRAPH-4F53}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 38899 (\\N{CJK UNIFIED IDEOGRAPH-97F3}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 32032 (\\N{CJK UNIFIED IDEOGRAPH-7D20}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 22522 (\\N{CJK UNIFIED IDEOGRAPH-57FA}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 32447 (\\N{CJK UNIFIED IDEOGRAPH-7EBF}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 24179 (\\N{CJK UNIFIED IDEOGRAPH-5E73}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 22343 (\\N{CJK UNIFIED IDEOGRAPH-5747}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 26679 (\\N{CJK UNIFIED IDEOGRAPH-6837}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 26412 (\\N{CJK UNIFIED IDEOGRAPH-672C}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 24635 (\\N{CJK UNIFIED IDEOGRAPH-603B}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 25968 (\\N{CJK UNIFIED IDEOGRAPH-6570}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 25928 (\\N{CJK UNIFIED IDEOGRAPH-6548}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 26524 (\\N{CJK UNIFIED IDEOGRAPH-679C}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 25552 (\\N{CJK UNIFIED IDEOGRAPH-63D0}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 21319 (\\N{CJK UNIFIED IDEOGRAPH-5347}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 26368 (\\N{CJK UNIFIED IDEOGRAPH-6700}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 22823 (\\N{CJK UNIFIED IDEOGRAPH-5927}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 23567 (\\N{CJK UNIFIED IDEOGRAPH-5C0F}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 19979 (\\N{CJK UNIFIED IDEOGRAPH-4E0B}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 38477 (\\N{CJK UNIFIED IDEOGRAPH-964D}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 32467 (\\N{CJK UNIFIED IDEOGRAPH-7ED3}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 35770 (\\N{CJK UNIFIED IDEOGRAPH-8BBA}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 10060 (\\N{CROSS MARK}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 26377 (\\N{CJK UNIFIED IDEOGRAPH-6709}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 38480 (\\N{CJK UNIFIED IDEOGRAPH-9650}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 21487 (\\N{CJK UNIFIED IDEOGRAPH-53EF}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 33021 (\\N{CJK UNIFIED IDEOGRAPH-80FD}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 38656 (\\N{CJK UNIFIED IDEOGRAPH-9700}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 35201 (\\N{CJK UNIFIED IDEOGRAPH-8981}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 37325 (\\N{CJK UNIFIED IDEOGRAPH-91CD}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 26032 (\\N{CJK UNIFIED IDEOGRAPH-65B0}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 32771 (\\N{CJK UNIFIED IDEOGRAPH-8003}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 34385 (\\N{CJK UNIFIED IDEOGRAPH-8651}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 31574 (\\N{CJK UNIFIED IDEOGRAPH-7B56}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n",
"/usr/local/lib/python3.11/dist-packages/IPython/core/pylabtools.py:151: UserWarning: Glyph 30053 (\\N{CJK UNIFIED IDEOGRAPH-7565}) missing from font(s) DejaVu Sans Mono.\n",
" fig.canvas.print_figure(bytes_io, **kw)\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAABjUAAASmCAYAAABm7inNAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzs3XlclWX+//HXOciegLIpsohm7groaJqppYbNpDH6a0z8OmklUmoaM5mpiZiTTW64YJKjuWZmTWZZllkoTo5lWqZTbrmzKC6ACAqc8/uDOImAoaxH3k8fPODc9/W57uu6gSP3/bmv6zKYzWYzIiIiIiIiIiIiIiIiNZyxuhsgIiIiIiIiIiIiIiJSFkpqiIiIiIiIiIiIiIiIVVBSQ0RERERERERERERErIKSGiIiIiIiIiIiIiIiYhWU1BAREREREREREREREaugpIaIiIiIiIiIiIiIiFgFJTVERERERERERERERMQqKKkhIiIiIiIiIiIiIiJWQUkNERERERERERERERGxCkpqiIiIiIiIiIiIiIiIVVBSQ0RERERERERERERErEKd6m6AiMid5MCBAwQHB2NnZ1fi/mvXrvHTTz+Rk5OjciWUa9q0aYn7K1NWVhZubm7Y29uXuD83N5dPP/2Uzp0716pyDz74YIn7RURERKT2Ksv1zt69e2v0NYfKlVyuOq7FRERul5IaIiIVyGw206lTJ3bs2FHi/nvvvRez2axypZSrDmazGW9vb06fPl3i/scffxyTyVTryomIiIiI3Kisf9fX5GsOlSu5nIiINdH0UyIiUqOlpqZSp04dYmJiiu07ePAgBoOBhQsXAgWjDGJiYmjWrBkODg64u7vTrVs3tmzZUtXNFhERERERERGRSqCkhoiI1Gje3t706NGDd999t9i+devWYWNjw2OPPQbA1KlTiYmJ4YEHHmDhwoVMmjQJf39/9uzZU9XNFhERERERERGRSqCkhoiI1HiDBg3if//7H/v37y+yfd26dfTo0QNvb28ANm3axB//+EfefPNNnn76aaKionj77bd58cUXq6PZIiIiIiIiIne8jIwMhg0bhpubG87OzvTv37/UKY8BkpKS+POf/8xdd92Fm5sbQ4cOJT093bJ/48aNtGnTBnt7ewIDA4mPj7fs+/nnn+nbty/169fH0dGRli1b8sYbb1Rq/6TmUVJD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Hh7OmjVrOHz4MC1btsTPz48JEyawdOlSvv32Wz7//HPLvPyfffYZffv25f7772f79u1Vfg5EROT2aaSGiIiIiIiIiIhUq6pcaBhg9uzZAPz973+v3I6JiEiF00gNERERERERERERERGxCsbqboCIiIiIiIiIiIiIiEhZaPqp22QymUhKSqJu3bqWeR1FRERERO5EZrOZzMxMfHx8MBr1XFRV0nWHiIiIiNQWZb3uUFLjNiUlJeHn51fdzRARERERqTKnTp3C19e3uptRq+i6Q0RERERqm9+77lBS4zbVrVsXKDjBLi4u1dya35hMJs6dO4enp+dtPUWn+OqNrwltULziFV9742tCGxSveMWX73e4smRkZODn52f5G1iqzp163VERdShe8YpXvN6DFK94xVtjfE1oQ0299ijrdYeSGrepcOi3i4tLjbu4yMnJwcXF5bZ/oBVfffE1oQ2KV7zia298TWiD4hWv+PL9Dlc2TX9U9e7U646KqEPxile84vUepHjFK94a42tCG2r6tcfvXXfUvBaLiIiIiIiIiIiIiIiUQEkNERERERGpFeLi4mjcuDEODg507tyZb7755qbl169fT4sWLXBwcKBt27Z88sknRfabzWamTJlCw4YNcXR0pHfv3hw+fLhImUOHDvHoo4/i4eGBi4sL3bp146uvvqrwvomIiIiI1BZKaoiIiIiIyB1v3bp1REVFER0dzZ49e2jfvj2hoaGcPXu2xPJff/01gwcP5qmnnmLv3r2EhYURFhbG/v37LWVef/115s+fz+LFi9m1axfOzs6EhoaSk5NjKfPII4+Ql5fHl19+yXfffUf79u155JFHSElJqfQ+i4iIiIjcibSmRiXLz88nNze3yo5nMpnIzc0lJyfntudTU3z1xVdFG2xtbbGxsbmttomIiIhYqzlz5jBixAiGDx8OwOLFi9m0aRPLli1jwoQJxcrPmzePvn378sILLwDwyiuvsGXLFhYuXMjixYsxm83ExsYyefJkHn30UQBWrlyJt7c3GzZs4PHHHyctLY3Dhw+zdOlS2rVrB8Brr73GokWL2L9/Pw0aNKii3ouIiIiI3DmU1KgkZrOZlJQULl26VOXHNZlMZGZm3tZCjoqv3viqaoObmxsNGjTQYp8iIiJSK1y7do3vvvuOl156ybLNaDTSu3dvdu7cWWLMzp07iYqKKrIt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iRNxdHRk//79JdbRtm1bAFq2bMm9995b4igHR0dHvLy8ePXVV1m4cGGx/cOGDStzf0VERERERERERETE+iipIQB06dKF3bt3YzabycvLK3H6pM2bN9+0jtGjRzNq1KhS4wF279590zqWLVt20/iAgAAGDBhQanxZpnYSEREREREREeugRYZFRH5fRkYGzz33HBs2bCA3N5devXqxaNEifH19SyyflJTEiBEjSExMpE6dOvTr14+FCxfi6uoKwMaNG5k4cSKHDx/Gx8eHCRMmMHLkSEv8zp07mThxIt988w1Go5EWLVrwxRdfWOIrm6afEhERERERERERERGxAgaDgYSEhCLbxo4dy4oVKwgPD+fFF19k06ZNDB48uNQ6hg4dymeffcbzzz/PsGHDWL16NaNGjQLgyJEjDBw4kKysLObNm4enpyeRkZF88cUXAPz44488+OCD7N27lwkTJjB37lzatm1LXl5epfX5RhqpISIiIiIiIiIiIiJihTIyMli1ahXu7u7ExcVhMBjYvHkzO3bsYO/evQQHBxcpf+DAARISEmjbti0xMTEYjUbWr1/P2rVriY2NJT4+nry8PKKiooiMjKRJkyaEhoayYMECevfuzaxZs8jJyWHhwoUMGTIEOzs7nn766Srts0ZqiIiIiIiIiIiIiIjUUBcvXiQtLY20tDQA0tPTOX/+PGlpaRw5coT8/Hz8/Pws0/kHBAQAcOjQoWJ1HT58GIBGjRpZtvn7+2MymTh69Khlv7+/f4l1FS4vMG/ePJycnHBycmLkyJFVOlJDSQ0RERERERERERERkRoqODgYT09PPD09ARgwYABt2rTB29sbo7H4Lf5bXXf4ZuVv3GdjYwOAm5sbH374IcHBwbz55pvEx8ff0jHLQ9NPiYiIiIiIiIiIiIjUUGvWrCE7OxuAPn36MHPmTPz9/XFzc6NJkybY2Nhw6tQpzGYzBoOBkydPAtCsWTMAcnJyAHBwcLBsO336tKX+kydPYjQaadq0qWX/iRMnLPuur6tZs2b8+OOPhIeH069fP44ePcp///vfEkeFVBYlNarStWtQ2cNwzOaCY9SpA7a2YGdXuccTERERkduWnJxMcnIyACaTiQsXLlC/fn3L01YNGzakYcOG1dlEERERERGpZvfdd1+R1yEhIbRq1QovLy+MRiNDhgxh5cqVjB49Gm9vb3bt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iq+++JrSBhEREREREREREZGaSHc8RURERERERERERETEKiipISIiIiIiIiIiIiIiVkHTT4mI1UtOTiY5ORkomH7rwoUL1K9f3zL9VuGaDyIiIiIiIiIiImLdlNQQEasXHx9PTExMqfujo6OZOnVq1TVIREREREREREREKoWSGiJi9UaOHEn//v3Jzs6mW7duAGzfvh1nZ2cAjdIQERERERERERG5QyipISJWr3B6qaysLMu2oKAg6tatW42tEhERERERERERkYqmhcJFRERERERERERErFRGRgbDhg3Dzc0NZ2dn+vfvz+nTp0stn5SUxPDhw3FxccHNzY2hQ4eSnp5u2b9x40batGmDvb09gYGBxMfHW/ZNnToVGxsbGjZsiI2NDQaDgbCwsMrsnkgxSmqIiIiIiEitEBcXR+PGjXFwcKBz58588803Ny2/fv16WrRogYODA23btuWTTz4pst9sNjNlyhQaNmyIo6MjvXv35vDhw8Xq2bRpE507d8bR0ZF69erpwl9ERERum8FgICEhoci2sWPHsmLFCsLDw3nxxRfZtGkTgwcPLrWOoUOH8tlnn/H8888zbNgwVq9ezahRowA4cuQIAwcOJCsri3nz5uHp6UlkZCRffPFFkTqmT5/OmjVrWLt2LX//+98rvJ8iN6OkhoiIiIiI3PHWrVtHVFQU0dHR7Nmzh/bt2xMaGsrZs2dLLP/1118zePBgnnrqKfbu3UtYWBhhYWHs37/fUub1119n/vz5LF68mF27duHs7ExoaCg5OTmWMu+//z5Dhw5l+PDh/PDDD/znP/8hPDy80vsrIiIitUNGRgarVq3C3d2duLg4pkyZQufOndmxYwd79+4tVv7AgQMkJCTQpk0bYmJiiI2NxcfHh7Vr15KWlkZ8fDx5eXlERUURGRnJ9OnTAViwYEGRenr06EFYWBiPP/64ZX1TkapiFUmNin6iymAwlPgxc+bMyuyGiIiIiIhUkzlz5jBixAiGDx9Oq1atWLx4MU5OTixbtqzE8vPmzaNv37688MILtGzZkldeeYWQkBAWLlwIFIzSiI2NZfLkyTz66KO0a9eOlStXkpSUxIYNGwDIy8tj7NixzJw5k8jISO655x5atWrFX/7yl6rqtoiIiNwBLl68SFpaGmlpaQCkp6dz/vx50tLSOHLkCPn5+fj5+WEwGAAICAgA4NCh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9kdERCpWfHx8iWseFYqOjmbq1KlV16AqpqSOiIiIiEj5zZ8/H7PZzOrVq4sstFyaVatWERERwZw5c4ostAwFIzIKF1oeM2aMZaHlPn36ANC+ffsSF1p2dnaukr6KiFi7Gp/UgIp/ogogIiKCiIiIimieiIhUo5EjR9K/f3+ys7Mti7Bu377dckFwp9/Qr+1JHRERERGRW6WFlkVErJtVJDVERERKUzgS4fpFdoOCgmrcIruVpbYndURERERERESkdlFSQ0RExIrV9qSOiIiIiIiIiNQuGt8mIiIiIiIiIiIiIiJWQSM1pNppkVsRERERERERERERKQslNaTaaZFbERERERERERERESkLJTWk2mmRWxEREREREREREREpCyU1pNppkVsREanNNA2jiIiIiIiISNkpqSEiIiJSjTQNo4iIiIiIiEjZKakhIiIiUo00DaOIiIiIiIhI2SmpISIiIlKNNA2jiIiIiIiISNkZq7sBIiIiIiIiIiIiIiIiZaGkhoiIiIiIiIiIiIiIWAVNPyUiIiIicpuSk5NJTk4GwGQyceHCBerXr4/RWPDsUOH0YiIiIiIiIlIxlNQQEREREblN8fHxxMTElLo/OjqaqVOnVl2DRERERERE7nBKaoiIiIiI3KaRI0fSv39/srOz6datGwDbt2/H2dkZQKM0REREREREKpiSGiIiIiIit6lweqmsrCzLtqCgIOrWrVuNrRIREREREblzKakhIiLVSvPRi4iIiIiIiIhIWSmpISIi1Urz0YuIiIiIiIiISFkpqSFyB9CT7mLNNB+9iIiIiIiIiIiUlZIaIncAPeku1kzz0YuIiIiIiIiISFkpqXEH0FP6oifdRUSqj/4frl7lPf/6/omIiIiIiFgXJTXuAHpKX/Sku4hI9dH/w9WrvOdf3z8RERERERHroqTGHUBP6YuIiDWz9ifl9f9w9Srv+df3T0RERERExLooqXEH0FP6IiJizaz9SXn9P1y9ynv+9f0TERERERGxLkpqiEitZ+1PiZdXbe+/VD89KS8iIiIiIiIiZaWkhojUetb+lHh51fb+S/XTk/IiIiIiIiKVo9/afsW2GTDgZ+PHqfxTmDEX2//R4I+qomkit01JDRGp9cr7lLi1j3TQU/IiIiIiIiIiImItlNQQEau/KV9e5X1K3NpHOugpeRERERERERERsRZKaoiI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cHd3L1GvPiLzwUYNIiIiIiIq1VxcXLBp0yaD8/W9otbW1harVq1Skn19vL29sXPnTqPrMWfOHMyZM8fo5YmIiIgKU3JyMhISEqDRaBAbG4srV64AALy8vABkXNsAwKVLl/TGX05MzFjezg7J//4fAC4lJqJamTIZ8zIN9Ozl5YXbt2/j6tWryvjI8+fPx7x58+Do6IhRo0Zh4cKFbNigPOM3hoiIiIiIiIiIiKiU27x5M9zc3ODh4aH3dZh5HYc4t6Uzl2dvb4+ZM2fi+++/x9dffw1XV1csWbIE69evz9M6iQD21CAiIiIiIiIiIiIq9YKCgrB3715oNBrExcVh69atOH36NG7evIlGjRohPDwcAFCzZk0AGa/oTE9Ph5VaDQuVCjXt7XEsPh43nzxBBQART55kLG9vj5r/jo1x899pABAeHg61Wg0fHx+UL19eeS2VRqPBpUuX8O677+LMmTPFuAeotGCjBhEREREREREREVEpV7FiRVSsWBEajQYxMTFwdXXF999/jzlz5iAqKgpLliyBhYUFxowZAwAYOXIkvtq1C580aIDR3t54rWpVvHT6NN4ODUVHEXweHo6ylpYYVrkyXK2t0cbFBX/dv49Zs2bh4cOHiIqKwsCBA1G+fHmsXbsWf//9N1q0aIHk5GSlh0arVq1MuUvITLFRg4iIiIiIiIiIiOgp8+yzz+LTTz/FBx98gPHjx8PHxwdbtmxBnTp19C4/vHJlRD55gjXh4fjz4EE0KFsWH9atC1drawDARn9/jD13DkuXLoWFhQUGDhyojE/m6+uLDRs2YMeOHUhKSoKXlxdWrlyJF154odi2l0oPNmoQERERERERERERPYVGjRqFUaNG6Z335Zdf4svYWOXfKpUKM2vVwnRfX8RUqQL3iAioM42bUdnODj82bQr89FO2stq2bYu//voLAJSeIu7u7oW8NfS04EDhRERERERERERERERkFtioQUREREREREREREREZoGNGkREREREREREREREZBY4pgYRERERERERERGVPHrGZgAAaDRATAzg7g6o+cw20dOGv3oiIiIiIiIiIiIiIjILbNQgIiIiIiIiIiIiIiKzwEYNIiIiIiIiIiIiIiIyC2zUICIiIiIiIiIiIiIis8BGDSIiIiIiIiIiIiIiMgts1CAiIiIiIiIiIiIiIrPARg0iIiIiIiIi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DsT8+fMxYsQIzJ07F/fu3cOkSZPw0ksvGRwonIiIiIgy+emn7NM0moxxL9zdje6dSKULP3UiIiIiIirVNm7ciNq1a6NDhw7o1q0bWrVqhbVr1yrzU1NTERYWhsePHyvTPvroI/To0QP9+vVDmzZtUKFCBfzvf/9T5ltYWODnn3+GhYUFAgMDMXjwYAwdOhTz5s1TlnFwcMDevXsRFxeHJk2aYNCgQejZsyc+/vjj4tlwIiIiIqJSiD01iIiIiIioVHNxccGmTZsMzq9atSoky/uUbW1tsWrVKqxatcpgnLe3N3bu3JnjumvXro29e/fmrcJERERERGQQe2oQEREREREREREREZFZYKMGERERERERERERERGZBTZqEBERERERERERERGRWWCjBhERERERERERERERmQU2ahARERERERERERERkVmwNHUFiIiIiJ5msfdjcf9BLJJTkpVpV69fgY21LQDApZwrXF1cTVU9IiIiIiIiohKFjRpEREREJvTLnh34ZstXOtMmTn1d+fvg/sMw9MURxV0tIiIiIiIiohKJjRpERFQgfMqcqGC6Bz2HwICWAACBQIN0qGEBFVQAMn5DRET0FPvpJ/3TNRogJgZwdwfUfLM0ERERPT3YqEFERAXCp8yJCsbV5b+GP4EgHWmwgKXSqEFERERERERE/2GjBhERFQifMiciIiLKAXtaEBERERUqNmoQEVGB8ClzIiIiIiIiIiIqLnwchIiIiIiIiIiIiIiIzAIbNYiIiIiIiIiIiIiIyCywUYOIiIiIiIiIiIiIiMwCGzWIiIiIiIiIiIiIiMgssFGDiIiIiIiIiIiIiIjMgqWpK0BERFQQsfdjcf9BLJJTkpVpV69fgY21LQDApZwrXF1cTVU9IiIiIiIiIiIqRGzUICIis/bLnh34ZstXOtMmTn1d+fvg/sMw9MURxV0tIiIiIiIiIiIqAmzUICIis9Y96DkEBrQEAAgEGqRDDQuooAKQ0VODiIiIiIiIiIhKBzZqEBGRWXN1+e/1UgJBOtJgAUulUYOIiIiIiIiIiEoPDhRORERERERERERERERmgT01iIgDLRMREREREREREZFZYKMGEXGgZSIiIiIiIiIiIjILbNQgIg60TCbFnkJERERERERERGQsNmoQEQdaJpNiTyEiIiIiIiIiIjIWGzWIiMik2FOIiIiIiIiI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Ozg4oEaNGoiIiCjm2hIRERERERERERUvNmoQEZUw/fv3x+DBg7F69WoEBQXB2dlZZ37dunXRrl07NG7cGC4uLjh27Bi+++47jBs3zjQVJiIiIiIiIiIiKiZs1CAiKmGee+452NnZISEhAf379882//XXX8eOHTvw66+/Ijk5Gd7e3nj33XcxadIkE9SWiIiIiIiIiIio+LBRg4iohClbtiweP35scP706dMxffr0YqwRERERERERERFRycCBwomIiIiIiIiIiIiIyCywpwYRlUqHDh3KNhaF1qNHj0y+nCncvn3bYN0eP36MV155pUiWIyIiIiIiIiIiKiwqERFTV4KIiIiIiIiIiIiIiCg3fP0UERERERERERERERGZBTZqEBERERERERERERGRWWCjBhERERERERERERERmQUOFJ5PGo0Gt2/fRtmyZaFSqUxdHSIiIiKjiQgSEhLg6ekJtdr0z7gkJSUhJSWlyNdjbW0NW1vbIl8PERERERERFR02auTT7du3UaVKFVNXg4iIiCjfIiIiULlyZZPWISkpCc4e5ZH8MLHI11WhQgVcv36dDRtERERERERmjI0a+VS2bFkAGTcDHB0dTVyb0k+j0eDu3btwc3MrEU+UkvH42Zkvfnbmi5+deSuOz+/hw4eoUqWKcj1jSikpKUh+mIgO746Epa11ka0nLSkF+2Z8hpSUFDZqEBERERERmTE2auST9pVTjo6ObNQoBhqNBklJSXB0dOQNOjPDz8588bMzX/zszFtxfn4l6RWaVnY2sLKzKbLyS9K2EhERERERUf7xTgcREREREREREREREZkF9tQgIiIiItNTqzL+FGX5REREREREZPbYU4OIiIiIiIiIiIiIiMwCe2oQERERkcmpVKoiHfeCY2oQERERERGVDuypQUREREREREREREREZoE9NYiIiIjI5FSqjD9FWT4RERERERGZP/bUICIiIiIiIiIiIiIis8CeGkRERERkeuyqQUREREREREZgTw0iIiIiIiIiIiIiIjIL7KlBRERERCanUqmgKsLeFEVZNhERERERERUf9tQgIiIiIiIiIiIiIiKzwJ4aRERERGRyKnXGn6Isn4iIiIiIiMwf0zsiIiIiIiIiIiIiIjIL7KlBRERERCbHMTWIiIiIiIjIGGzUICoit+Ji8MelE7if+BA2ltbwq1ITTbzq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flwpY//+/dBoNGjWrFlhbyY9RWysrLGwz1iMadMPDjZlEH7/Dq7evYWrd28hOTUFneoEYNWASajnWd3UVSWiYmBpYQG1Sg2N5D5+QbpoYKFWw0Kdc48OotJKpSr6P0RERERERGT+TN6XeOLEiRg2bBiaNGmCgIAALFu2DImJiRgxYgQAYOjQoahUqRIWLFgAAHjjjTfQtm1bLF26FN27d8e3336LY8eOYe3atQAAV1dXuLq66qzDysoKFSpUgK+vLwCgTp066NKlC0aOHIk1a9YgNTUV48aNw4ABA+Dp6VmMW0+lka2VDd5o3x/DA7vj76tncD8xHtaWVvCvUgs13b1yL4CISg17azvUqVAVh26cg6t9zgOAJzxJROt6jfiKHCIiIiIiIiKiHJi8UaN///64e/cuZs2ahejoaPj5+WH37t3KYODh4eE6r0ho0aIFNm3ahBkzZmDatGmoWbMmfvjhB9SvXz9P6924cSPGjRuHDh06QK1Wo1+/fvj4448Lddvo6eZk54Bu9VuYuhpEZEIqlQq9G7XF4Rvn8DglCWWs9Y9jkJD0GFYWlniuYetiriFRCVLU3SnYYEhERERERFQqmLxRAwDGjRuHcePG6Z33xx9/ZJsWHByM4OBgo8u/ceNGtmkuLi7YtGmT0WUQERHlRyffpthZww+/XzoOD0dXlLUpo/TGEBHEP3mEu4/i0LN+K7So1sDEtSUiIiIiIiIiKtlKRKMGERFRaWVjZY0Fz72G2b98hj+vnMKdh/dhY2kNQJCclgp7a1v0adQW04OGF8oA4UTmSqVWQaUuut4URVk2ERERERERFR/ePSEiIipiTnYO+KjfBJyMvIRdof/gUkwEVCqgToWq6F6vJepVrM6xNIiIiIiIiIiIjMBGDSIiomKgUqnwTBVfPFPF19RVISqROKQGERERERERGUOd+yJERERERERERERERESmx54aRERERGRyHFODiIiIiIiIjMGeGkREREREREREREREZBbYU4OIiIiITE+FIh5Uo+iKJiIiIiIiouLDnhpERERERERERERERGQW2FODiIiIiExOpSrijhrsqUFERERERFQqsKcGERERERERERERERGZBfbUICIiIiKTU6lVUKmLrjtFUZZNRERERERExYeNGkRERERERGS004f+xkfT34a1jY3OdI1G0KhZIC6ePonUlORs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PD4gmrsefbLYU1D1jLqO5u07Mv7eO3hg/BQi6tRlz0/bSU1O4sY7htK515UEh9XgpfFPctfI0Rz8/Tc+Xrmc4WMnu9pY98G/ycnJpmWHzlgsFr76eA21GzRydWhkZWaQlpJ8OtokLSWZxIR4LBYr1UNCi5TnnY88wdND+lGnYWO69+5DWkoyP369noi69fi/m/sW65xFREREKgOPdWqEhoZitVqJj493K4+PjyciIiLffSIiIooUX6VKFZo0aUKTJk3o1q0bkZGRLFmyhDFjxrB+/XrWrl3LyZMnXZ0Rr7zyCuvWrWPZsmU8/fTT+R7bZrNhs9nylFssFn1hVEYMw9D1rqB07you3buKS/euYivt+1ce/11YDQNrKQ6nKM22RaRislqtTH/jXZa8+BzTH3uA1ORkatatxz1PjgPA28eHZxctY/4zY7j/uiuoUi2Q6Lvu5Zp+g1xtVKkWwIpX5vLq1AkYhkHzdh15duGbrvov167hxScfcb1+ZfJ4Xpk8nvDadVnx7dYi5XlJj8sYO3chKxbMYemsaVSpFkDzdh3o3OvKkrkQIiIiIhWMxzo1fHx86NixI7GxsURHRwO5TybGxsYyYsSIfPfp3r07sbGxjBw50lW2bt06unfvXuixnE6naz2M9PR0IO+HeYvFovmlRUREREREKpAzC4Wfr6oBgTw65QUenfJCvvVNW7fj5dWfFLh/j//rQ4//61NgfZ/bBtDntgGF5vDPzo389ul17Y30uvbGQtsRERERuVh4dPqpUaNGMXjwYDp16kSXLl2YO3cuaWlpDB06FIC77rqL2rVrM336dAAeffRRevXqxaxZs7juuutYuXIlmzdvZvHixQCkpaXx3HPPceONN1KzZk2OHz/OggULOHz4MH375g7L7d69O0FBQQwePJiJEyfi5+fHa6+9xp9//sl1113nmQshIiIicpGzYGApxdEUFjRSQ0REREREpDLwaKdGv379SEhIYOLEicTFxdG+fXtiYmJci4EfOHDAbURFjx49WLFiBePHj2fs2LFERkayZs0aWrduDeQOH969ezfLli3j+PHjhISE0LlzZ7755htatWoF5E57FRMTw7hx47jyyivJycmhVatWfPjhh7Rr167sL4KIiIiIiEgFUaVaABvXf87G9Z/nqet02RUAVA0I4IEbe+e7v2FYCIuoxaJpk/KtH/jg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zmqmRps2bZg4cSJdunThu+++47XXXgPgzz//JDo6ulQDFBERETln2SLAvykUbgcr+/iG4AZYhUABEAj+DcBe1cuBlgHL9PCeGh7sW0RERERERMrMWSU1pk6dSr9+/ViwYAGPPfaYa/PA//3vf1xyySWlGqCIiIjIOc1e5fgyVIfAPAxWHhgO8KsB/jFgBHo7QhEREREREZFy46ySGi1atGDTpk1Fyl944QXsdvu/DkpERETkvGIEOJMY1ADTBP9D4Ff1/FpySntqlJmcnByefPLJ02qr/TRERERERKS8Oaukxgnr1q1j69atADRt2pSLL764VIISERERERHPeP3118nJyTnt9vHx8R6MRkRERERE5MycVVLj0KFD9OnTh++++47w8HAAUlNTufLKK5k3bx5RUVGlGaOIiIiInPOs44cn+xeAK664wtshiIiIiIiInLWzWtNg2LBhZGZmsnnzZlJSUkhJSeHXX38lPT2d+++/v7RjFBERERERERERERERObuZGkuWLOHrr7+mSZMmrrKmTZsyffp0unbtWmrBiYiIiMh5wjKdhyf7FxEREREREZ93VjM1TNPE39+/SLm/vz+mqV8YRURERERERERERESk9J1VUqNTp0488MADHDhwwFW2f/9+RowYQefOnUstOBEREZHzhWWZWIXHsAoOYzkysM6zmQWWZXr8EBEREREREd93VstPTZs2jeuvv546depQs2ZNAPbu3UuzZs14//33SzVAERERkXOZZZmQtwvydoIjDUwTsuyQ/gdWUD0IqodhnNVHNhEREREREZFzzln9hlyzZk3Wr1/P119/zbZt2wBo0qQJXbp0KdXgRERERM5llmVC1lrI2+0ssAU559HaLHBkQPYGKDiMVakdhlF06c9zimU5D0/2LyIiIiIiIj7vrB/7MwyDq666iquuuqo04xERERE5f+Rsc87SMPzBKoDCY86ZGg5/sPzAFgAF+yC7IgRf5O1oRURERERERLzujPbUWL58OU2bNiU9Pb1IXVpaGhdeeCE//PBDqQUnIiIicq6yrALnklOWAwpTnTMzLAdwfMaCmekstxyQtxvLzPFyxB5mmZ4/RERERERExOedUVJj6tSpDB48mNDQ0CJ1YWFh3HPPPUyePLnUghMRERE5Z+UnHd9D43iywvAHw378sDl/Bme9mQn5B7wXq4iIiIiI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hlzfpUhd3UZNAKhVv0Gx9SfOD4+swtwZU1n43ttF6uN79sUwbORkZxXbR1jlCABia9Vhwn13FnuNNldcCcCq5V+xavlXResvd9aHhIaWGKdh2IiKieX1Z8YXW3/rfcPLzWshIiIiUp4YlmXpN7yzkJ6eTlhYGGlpaYSGhno7nHOeaZocOnSIqlWrYrNp1TRforHzXRo736Wx802WZWEdPYgjN5vDWXlEX9AIu59nnj8pT59jTsSSPGMUoRUCPXednDyi73uuXNyziK+YOHEiP/68iUdemu7tUETOWQ/1vZ6RCfdx2223eTsUERERn6FvOkRERETKAcMwsFWJxR5bD1tYJMb5lpCyyuAQkTNSo0YNkvftJT8v19uhiJyTkvfvIz83lxo1ang7FBEREZ9ynv22LCIiIiIiIqejU6dOmAV5LFv4kbdDETnnmKbJF/83h9DgisTFxXk7HBEREZ+iPTVERERExPtM03l4sn8ROSO1atXinrsG8dqbb/Hbpo00ubgtwSGVwDC8HZqI77Is0o4d5ZdVK0je/QcTJ0wgMNBzyy+KiIici5TUEBERERERkWINGTKE2rVrs2jRIpZ9+B75+fneDknE51WsWJFLOrRn/EPDueSSS7wdjoiIiM9RUkNEREREvM88fniyfxE5Y4Zh0L17d7p37w44l8wRkX/Hdr7tmyUiIlLKlNQQERERERGR06IvY0VERETE25TUEBERERHvMy3n4cn+RURERERExOfpMRsREREREREREREREfEJmqkhIiIiIl5nWRaW5bnZFJ7sW0RERERERMqOZmqIiIiIiIiIiIiIiIhP0EwNEREREfE6y7SwPLjvhSf7FhERERERkbKjpIaIiIhIOWHm5uDIycbMy/V2KCIiIiIiIiLlkpIaIiIiIl5kWRYFv20hZ/X35P2yFsvhID2qGhWioqkY15GApq0wDMPbYXqeefzwZP8iIiIiIiLi85TUEBEREfESy7LI+uIjsr9agJWbixEcghEQABbkrl9B/sY1VOwYT8iNt2HY7d4OV0RERERERMTrlNQQERER8ZLcld+Qtfh/GIFB+MXWBMDCwFYxGP+YmlgZaWQv/xyjUhgh8T28G6yHmZaF6cF9L0xLe2qIiIiIiIicC2zeDkBERETkfGQVFJC9bBEA9rDKxbaxVQrF8A8g5/svMbOzyjI8ERERERER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LJzgyzpimiY5hw7hF1HF2yGVLRMwPfisjQdnaoiIiIiIiEjZ0eObIiIiIiIiIiIiIiLiEzRTQ0RERES8zrQsTA+uiurJvkVERERERKTsaKaGiIiIiIiIiIiIiIj4BM3UEBERERHvMy0P76mhmRoiIiIiIiLnAs3UEBERERERERERERERn6CZGiIiIiLidZbpPDzZv4iIiIiIiPg+zdQQERERERERERERERGfoJkaIiIiIuJ1lmlheXDfC0/2LSIiIiIiImVHSQ0RERER8T7Lch6e7F9ERERERER8npafEhERERERERERERERn6CZGiIiIiLiddooXERERERERE6HZmqIiIiIiIiIiIiIiIhP0EwNEREREfE6bRQuIiIiIiIip0MzNURERERERERERERExCdopoaIiIiIeJ2FhWV5cKYGmqkhIiIiIiJyLtBMDRERERERERERERER8QmaqSEiIiIiXmeazsOT/YuIiIiIiIjv00wNERERERERERERERHxCZqpISIiIiJeZ1nOw5P9i4iIiIiIiO/TTA0REREREREREREREfEJmqkhIiIiIl6nmRoiIiIiIiJyOjRTQ0REREREREREREREfIJmaoiIiIiI15mW8/Bk/yIiIiIiIuL7NFNDRERERERERERERER8gmZqiIiIiIjXaU8NEREREREROR2aqSEiIiIiIiIiIiIiIj5BMzVERERExOssE0zTs/2LiIiIiIiI79NMDRERERERERERERER8QmaqSEiIiIiXqc9NUREREREROR0aKaGiIiIiIiIiIiIiIj4BM3UEBERERGvs0zP7nuhPTVERERERETODZqpISIiIiIiIiIiIiIiPkEzNURERETE60zLeXiyfxEREREREfF9mqkhIiIiIiIiIiIiIiI+QTM1RERERMTrLMt5eLJ/ERERERER8X2aqSEiIiIiIiIiIiIiIj5BMzVERKSIwuwc0rf/SXpGOhWz8qlUryaGYXg7LBE5h5mm8/Bk/yIiIiIiIuL7lNQQERGXvJRUdn/wOfsWfk3O4RTMC6rz++5kIls1oVbvq4npcomSGyIiIiIiIiIi4jVKaoiICAA5Bw+xbvgzHNuwFXtwRQKrRGJGhMPhdA6vWM/RnzZR/+4+NBhyixIbIlLqtKeGiIiIiIiInA4lNUREBMs02Th2Ksc2bCW4Tg1sAf5YhoHl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mUNCQgKdO3fGZrPRs2dPXnnlFVd9QUEB27dvJzs721U2ZcoUV9u8vDzi4+OZMWOGq95ut7No0SKGDBlCXFwcwcHBDBgwgCeffNLV5o477iAjI4Np06bx4IMPEh4eTqdOnXjuuefK5sZFRERERES8wLA0N/2spKenExYWRlpa2mktYSD/jmmaruUXbDZNMPIlGjvfpbHzXRo731YW41eePseciGVxt4EE+wd47DpZBflcs2RWubhnEREREREROXv6pkNERERERERERERERHyClp8SEREREa/z5L4XJ/oXERERERER36ekxlk6sWpXenq6lyM5P5imSUZGBkFBQVpKxcdo7HyXxs53aex8W1mM34nPL+VpFdLswnyf7l9ERERERETKhpIaZykjIwOAmjVrejkSERERkbOTkZFBWFiYV2MICAggJiaG3svmePxaMTExBAR4bt8OERERERER8TxtFH6WTNPkwIEDVKpUCcMwvB3OOS89PZ2aNWuyd+9ebe7pYzR2vktj57s0dr6tLMbPsiwyMjKIjY0tF7N5cnNzyc/3/EyKgIAAgoKCPH4dERERERER8RzN1DhLNpuNGjVqeDuM805oaKi+oPNRGjvfpbHzXRo73+bp8fP2DI2/CwoKUrJBRERERERETov3H80TERERERERERERERE5DUpqiIiIiIiIiIiIiIiIT1BSQ3xCYGAg48ePJzAw0NuhyBnS2PkujZ3v0tj5No2fiIiIiIiISMm0UbiIiIiIiIiIiIiIiPgEzdQQERERERERERERERGfoKSGiIiIiIiIiIiIiIj4BCU1RERERERERERERETEJyipIV7z/fffc9111xEbG4thGCxYsMCt3rIsxo0bR7Vq1ahQoQJdunTht99+c2uTkpJCv379CA0NJTw8nEGDBpGZmVmGd3H+OtX43XHHHRiG4XZ069bNrY3Gr+xNmjSJtm3bUqlSJapWrUqPHj3Yvn27W5vc3FyGDh1KZGQkISEh9OzZk+TkZLc2e/bsoXv37lSsWJGqVavy8MMPU1hYWJa3ct45nbH7z3/+U+R9d++997q10diVvddee40WLVoQGhpKaGgocXFxfPHFF656vedERERERERETp+SGuI1WVlZtGzZkunTpxdb//zzz/PKK68wc+ZMVq9eTXBwMPHx8eTm5rra9OvXj82bN7N06VIWLVrE999/z913311Wt3BeO9X4AXTr1o2DBw+6jg8++MCtXuNX9r777juGDh3KqlWrWLp0KQUFBXTt2pWsrCxXmxEjRvDZZ58xf/58vvvuOw4cOMBNN93kqnc4HHTv3p38/HxWrlzJ7Nmzeffddxk3bpw3bum8cTpjBzB48GC3993zzz/vqtPYeUeNGjV49tlnWbduHWvXrqVTp07ccMMNbN68GdB7TkREREREROSMWCLlAGB98sknrp9N07RiYmKsF154wVWWmppqBQYGWh988IFlWZa1ZcsWC7B++uknV5svvvjCMgzD2r9/f5nFLkXHz7Isa8CAAdYNN9xQ4jkav/Lh0KFDFmB99913lmU532f+/v7W/PnzXW22bt1qAVZiYqJlWZa1ePFiy2azWUlJSa42r732mhUaGmrl5eWV7Q2cx/45dpZlWR07drQeeOCBEs/R2JUflStXtt566y2950RERERERETOkGZqSLn0559/kpSURJcuXVxlYWFhtG/fnsTERAASExMJDw+nTZs2rjZdunTBZrOxevXqMo9Zivr222+pWrUqjRo1YsiQIRw9etRVp/ErH9LS0gCIiIgAYN26dRQUFLi99xo3bkytWrXc3nvNmzcnOjra1SY+Pp709HTXk+fief8cuxPmzJlDlSpVaNasGWPGjCE7O9tVp7HzPofDwbx588jKyiIuLk7vOREREREREZEz5OftAESKk5SUBOD2Bc6Jn0/UJSUlUbVqVbd6Pz8/IiIiXG3Ee7p168ZNN91E3bp1+eOPP3j00Ue5+uqrSUxMxG63a/zKAdM0GT58OJdeeinNmjUDnO+rgIAAwsPD3dr+871X3HvzRJ14XnFjB3DrrbdSu3ZtYmNj+eWXXxg1ahTbt2/n448/BjR23rRp0ybi4uLIzc0lJCSETz75hKZNm7Jhwwa950RERERERETOgJIaIuIRffv2df25efPmtGjRggsuuIBvv/2Wzp07ezEyOWHo0KH8+uuv/Pjjj94ORc5QSWP39z1pmjdvTrVq1ejcuTN//PEHF1xwQVmHKX/TqFEjNmzYQFpaGv/73/8YMGAA3333nbfDEhEREREREfE5Wn5KyqWYmBgAkpOT3cqTk5NddTExMRw6dMitvrCwkJSUFFcbKT/q1atHlSpV+P333wGNn7clJCSwaNEivvnmG2rUqOEqj4mJIT8/n9TUVLf2/3zvFffePFEnnlXS2BWnffv2AG7vO42ddwQEBFC/fn1at27NpEmTaNmyJS+//LLecyIiIiIiIiJnSEkNKZfq1q1LTEwMy5Ytc5Wlp6ezevVq4uLiAIiLiyM1NZV169a52ixfvhzTNF1f5En5sW/fPo4ePUq1atUAjZ+3WJZFQkICn3zyCcuXL6du3bpu9a1bt8bf39/tvbd9+3b27Nnj9t7btGmTW1Jq6dKlhIaG0rRp07K5kfPQqcauOBs2bABwe99p7MoH0zTJy8vTe05ERERERETkDGn5KfGazMxM19PD4NwcfMOGDURERFCrVi2GDx/OxIkTadCgAXXr1uXxxx8nNjaWHj16ANCkSRO6devG4MGDmTlzJgUFBSQkJNC3b19iY2O9dFfnj5ONX0REBBMmTKBnz57ExMTwxx9/8Mgjj1C/fn3i4+MBjZ+3DB06lLlz57Jw4UIqVarkWo8/LCyMChUqEBYWxqBBgxg5ciQRERGEhoYybNgw4uLi6NChAwBdu3aladOm3H777Tz//PMkJSUxduxYhg4dSmBgoDdv75x2qrH7448/mDt3Ltdccw2RkZH88ssvjBgxgiuuuIIWLVoAGjtvGTNmDFdffTW1atUiIyODuXPn8u233/Lll1/qPSciIiIiIiJypiwRL/nmm28soMgxYMAAy7IsyzRN6/HHH7eio6OtwMBAq3Pnztb27dvd+jh69Kh1yy23WCEhIVZoaKg1cOBAKyMjwwt3c/452fhlZ2dbXbt2taKioix/f3+rdu3a1uDBg62kpCS3PjR+Za+4MQOsWbNmudrk5ORY9913n1W5cmWrYsWK1o033mgdPHjQrZ//b++OUVoJwgCOf5GgxkYQ7QQR0tpZBAsNWEhuYG3jAVSQ2HgECw8Q8AA2qexsrSy0D15ARUE04LxOCBF8vOczfr7fr9xhhhmW3eYPu71er7RarVKr1crs7GzZ2dkp/X7/i0/zf/no3t3c3JTV1dUyMzNTJiYmSr1eL3t7e+X+/n5gHffu621tbZWFhYUyPj5e5ubmyvr6ejk7O3sb98wBAADA76uUUspXRhQAAAAAAIA/4Z8aAAAAAABACqIGAAAAAACQgqgBAAAAAACkIGoAAAAAAAApiBoAAAAAAEAKogYAAAAAAJCCqAEAAAAAAKQgagAAAAAAACmIGgAAAAAAQArVUW8A4Kc6Pz+P7e3tmJycHLj++voaa2trcXFxEc/Pz0PzHh8f4/r6Oo6OjuLk5CSq1cFX9cvLSxwcHESj0YhWqxVTU1NDaywuLsbp6ennHggAAAAARkzUAPhHnp6eYnNzMw4PDweu93q92N/fj0qlEpeXl0Pzms1mlFLi9vY2jo+Po9lsDox3Op14eHiIfr8fKysr0el0htZoNBqfdxAAAAAA+CZ8fgoAAAAAAEhB1AAAAAAAAFIQNQAAAAAAgBREDQAAAAAAIAVRAwAAAAAASEHUAAAAAAAAUhA1AAAAAACAFEQNAAAAAAAgBVEDAAAAAABIQdQAAAAAAABSqI56AwA/1fT0dHS73eh2u0NjGxsbcXd3F8vLy+/OHRsbi/n5+djd3X13vN1uR61Wi6urq3fXWFpa+rvNAwAAAMA3VCmllFFvAgAAAAAA4CM+PwUAAAAAAKQgagAAAAAAACmIGgAAAAAAQAqiBgAAAAAAkIKoAQAAAAAApCBqAAAAAAAAKYgaAAAAAABACqIGAAAAAACQgqgBAAAAAACk8Av65jQsvoZlcQAAAABJRU5ErkJggg==",
"text/plain": [
"<Figure size 1600x1200 with 5 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"4. 详细相似度对比表\n",
"phoneme intra_class_similarity similarity_std n_samples overall_baseline absolute_improvement relative_improvement_pct is_better\n",
" SH 0.0401 0.0381 121 0.0326 0.0075 23.0454 True\n",
" AW 0.0399 0.0331 239 0.0326 0.0074 22.5869 True\n",
" OY 0.0386 0.0375 111 0.0326 0.0060 18.4301 True\n",
" AY 0.0374 0.0302 300 0.0326 0.0048 14.8684 True\n",
" EY 0.0372 0.0320 300 0.0326 0.0047 14.3090 True\n",
" NG 0.0354 0.0365 300 0.0326 0.0028 8.6882 True\n",
" CH 0.0352 0.0340 132 0.0326 0.0026 8.0138 True\n",
" DH 0.0349 0.0310 300 0.0326 0.0024 7.3369 True\n",
" | 0.0346 0.0336 300 0.0326 0.0020 6.1968 True\n",
" ZH 0.0344 0.0309 70 0.0326 0.0018 5.5290 True\n",
" EH 0.0342 0.0298 300 0.0326 0.0017 5.1123 True\n",
" Y 0.0337 0.0330 300 0.0326 0.0011 3.5022 True\n",
" D 0.0334 0.0314 300 0.0326 0.0008 2.5196 True\n",
" OW 0.0332 0.0321 300 0.0326 0.0006 1.8920 True\n",
" IH 0.0330 0.0322 300 0.0326 0.0004 1.3307 True\n",
" W 0.0329 0.0316 300 0.0326 0.0004 1.1038 True\n",
" ER 0.0327 0.0314 300 0.0326 0.0002 0.5785 True\n",
" B 0.0327 0.0318 300 0.0326 0.0002 0.5659 True\n",
" AH 0.0324 0.0290 300 0.0326 -0.0002 -0.5848 False\n",
" L 0.0323 0.0333 300 0.0326 -0.0003 -0.9101 False\n",
" N 0.0321 0.0310 300 0.0326 -0.0004 -1.3418 False\n",
" JH 0.0319 0.0333 156 0.0326 -0.0007 -2.0004 False\n",
" T 0.0317 0.0315 300 0.0326 -0.0009 -2.6453 False\n",
" Z 0.0310 0.0309 300 0.0326 -0.0015 -4.6426 False\n",
" R 0.0310 0.0298 300 0.0326 -0.0016 -4.8833 False\n",
" P 0.0305 0.0300 300 0.0326 -0.0021 -6.3031 False\n",
" IY 0.0302 0.0298 300 0.0326 -0.0023 -7.1007 False\n",
" M 0.0301 0.0294 300 0.0326 -0.0024 -7.4350 False\n",
" TH 0.0299 0.0321 176 0.0326 -0.0026 -8.0167 False\n",
" AO 0.0298 0.0300 300 0.0326 -0.0028 -8.6133 False\n",
" S 0.0297 0.0300 300 0.0326 -0.0028 -8.7008 False\n",
" HH 0.0294 0.0279 300 0.0326 -0.0031 -9.5591 False\n",
" K 0.0289 0.0292 300 0.0326 -0.0037 -11.2776 False\n",
" V 0.0280 0.0298 300 0.0326 -0.0045 -13.8742 False\n",
" F 0.0275 0.0285 300 0.0326 -0.0051 -15.6666 False\n",
" G 0.0266 0.0287 300 0.0326 -0.0060 -18.2774 False\n",
" UW 0.0264 0.0259 300 0.0326 -0.0061 -18.8279 False\n",
" AE 0.0261 0.0265 300 0.0326 -0.0065 -19.8566 False\n",
" AA 0.0260 0.0260 300 0.0326 -0.0066 -20.1245 False\n",
" UH 0.0243 0.0247 200 0.0326 -0.0083 -25.4366 False\n",
"\n",
"✅ 类内相似度分析完成!\n",
"这个分析揭示了音素分类对神经信号相似性的影响。\n"
]
}
],
"source": [
"# # 类内相似度分析\n",
"# import numpy as np\n",
"# import matplotlib.pyplot as plt\n",
"# from sklearn.metrics.pairwise import cosine_similarity, euclidean_distances\n",
"# from sklearn.preprocessing import StandardScaler\n",
"# import pandas as pd\n",
"# import seaborn as sns\n",
"\n",
"# print(\"=\"*70)\n",
"# print(\"类内相似度分析 - 音素分类有效性评估\")\n",
"# print(\"=\"*70)\n",
"\n",
"# def calculate_intra_class_similarity(sequences, metric='cosine'):\n",
"# \"\"\"\n",
"# 计算类内相似度\n",
"# \"\"\"\n",
"# if len(sequences) < 2:\n",
"# return np.nan, np.nan, np.nan\n",
" \n",
"# # 展平序列\n",
"# flattened_sequences = []\n",
"# for seq in sequences:\n",
"# flattened_sequences.append(seq.flatten())\n",
" \n",
"# flattened_sequences = np.array(flattened_sequences)\n",
" \n",
"# # 标准化\n",
"# scaler = StandardScaler()\n",
"# scaled_sequences = scaler.fit_transform(flattened_sequences)\n",
" \n",
"# if metric == 'cosine':\n",
"# # 计算余弦相似度\n",
"# similarity_matrix = cosine_similarity(scaled_sequences)\n",
"# # 提取上三角矩阵(排除对角线)\n",
"# upper_tri = np.triu(similarity_matrix, k=1)\n",
"# similarities = upper_tri[upper_tri > 0]\n",
"# elif metric == 'euclidean':\n",
"# # 计算欧氏距离,然后转换为相似度\n",
"# distance_matrix = euclidean_distances(scaled_sequences)\n",
"# # 转换为相似度(距离越小,相似度越高)\n",
"# max_dist = np.max(distance_matrix)\n",
"# similarity_matrix = 1 - (distance_matrix / max_dist)\n",
"# upper_tri = np.triu(similarity_matrix, k=1)\n",
"# similarities = upper_tri[upper_tri > 0]\n",
" \n",
"# mean_similarity = np.mean(similarities)\n",
"# std_similarity = np.std(similarities)\n",
"# median_similarity = np.median(similarities)\n",
" \n",
"# return mean_similarity, std_similarity, median_similarity\n",
"\n",
"# def analyze_phoneme_similarity(processed_result, metric='cosine', sample_limit=500):\n",
"# \"\"\"\n",
"# 分析每个音素的类内相似度\n",
"# \"\"\"\n",
"# print(f\"使用 {metric} 相似度度量\")\n",
"# print(f\"每个音素最多分析 {sample_limit} 个样本\")\n",
"# print(\"-\" * 50)\n",
" \n",
"# phoneme_similarities = {}\n",
" \n",
"# for phoneme, sequences in processed_result.items():\n",
"# if len(sequences) < 5: # 跳过样本数太少的音素\n",
"# print(f\"跳过音素 '{phoneme}' (样本数太少: {len(sequences)})\")\n",
"# continue\n",
" \n",
"# # 如果样本太多,随机采样\n",
"# if len(sequences) > sample_limit:\n",
"# indices = np.random.choice(len(sequences), sample_limit, replace=False)\n",
"# sampled_sequences = [sequences[i] for i in indices]\n",
"# else:\n",
"# sampled_sequences = sequences\n",
" \n",
"# mean_sim, std_sim, median_sim = calculate_intra_class_similarity(\n",
"# sampled_sequences, metric=metric\n",
"# )\n",
" \n",
"# phoneme_similarities[phoneme] = {\n",
"# 'mean': mean_sim,\n",
"# 'std': std_sim,\n",
"# 'median': median_sim,\n",
"# 'n_samples': len(sampled_sequences),\n",
"# 'n_pairs': len(sampled_sequences) * (len(sampled_sequences) - 1) // 2\n",
"# }\n",
" \n",
"# print(f\"音素 '{phoneme}': 平均相似度={mean_sim:.4f} ± {std_sim:.4f}, \"\n",
"# f\"中位数={median_sim:.4f}, 样本数={len(sampled_sequences)}\")\n",
" \n",
"# return phoneme_similarities\n",
"\n",
"# def calculate_overall_similarity(processed_result, metric='cosine', sample_per_phoneme=50):\n",
"# \"\"\"\n",
"# 计算全部音素作为一类的相似度\n",
"# \"\"\"\n",
"# print(f\"\\n计算全体音素相似度 (每个音素采样 {sample_per_phoneme} 个)\")\n",
"# print(\"-\" * 50)\n",
" \n",
"# all_sequences = []\n",
"# phoneme_labels = []\n",
" \n",
"# # 从每个音素中采样一定数量的序列\n",
"# for phoneme, sequences in processed_result.items():\n",
"# if len(sequences) < 5:\n",
"# continue\n",
" \n",
"# n_sample = min(sample_per_phoneme, len(sequences))\n",
"# indices = np.random.choice(len(sequences), n_sample, replace=False)\n",
" \n",
"# for i in indices:\n",
"# all_sequences.append(sequences[i])\n",
"# phoneme_labels.append(phoneme)\n",
" \n",
"# print(f\"总共收集了 {len(all_sequences)} 个序列,来自 {len(set(phoneme_labels))} 个音素\")\n",
" \n",
"# # 计算整体相似度\n",
"# mean_sim, std_sim, median_sim = calculate_intra_class_similarity(\n",
"# all_sequences, metric=metric\n",
"# )\n",
" \n",
"# overall_result = {\n",
"# 'mean': mean_sim,\n",
"# 'std': std_sim,\n",
"# 'median': median_sim,\n",
"# 'n_samples': len(all_sequences),\n",
"# 'n_pairs': len(all_sequences) * (len(all_sequences) - 1) // 2,\n",
"# 'n_phonemes': len(set(phoneme_labels))\n",
"# }\n",
" \n",
"# print(f\"全体音素: 平均相似度={mean_sim:.4f} ± {std_sim:.4f}, \"\n",
"# f\"中位数={median_sim:.4f}, 样本数={len(all_sequences)}\")\n",
" \n",
"# return overall_result, phoneme_labels\n",
"\n",
"# def visualize_similarity_comparison(phoneme_similarities, overall_result, metric='cosine'):\n",
"# \"\"\"\n",
"# 可视化相似度比较\n",
"# \"\"\"\n",
"# fig, axes = plt.subplots(2, 2, figsize=(16, 12))\n",
" \n",
"# # 准备数据\n",
"# phonemes = list(phoneme_similarities.keys())\n",
"# mean_similarities = [phoneme_similarities[p]['mean'] for p in phonemes]\n",
"# std_similarities = [phoneme_similarities[p]['std'] for p in phonemes]\n",
"# sample_counts = [phoneme_similarities[p]['n_samples'] for p in phonemes]\n",
" \n",
"# overall_mean = overall_result['mean']\n",
"# overall_std = overall_result['std']\n",
" \n",
"# # 图1: 每个音素的平均相似度 vs 整体相似度\n",
"# ax1 = axes[0, 0]\n",
"# bars = ax1.bar(range(len(phonemes)), mean_similarities, \n",
"# yerr=std_similarities, capsize=3, alpha=0.7, color='skyblue')\n",
"# ax1.axhline(y=overall_mean, color='red', linestyle='--', linewidth=2, \n",
"# label=f'全体音素平均: {overall_mean:.4f}')\n",
"# ax1.fill_between(range(len(phonemes)), \n",
"# overall_mean - overall_std, \n",
"# overall_mean + overall_std, \n",
"# alpha=0.2, color='red', label=f'全体音素范围: ±{overall_std:.4f}')\n",
" \n",
"# ax1.set_xlabel('音素')\n",
"# ax1.set_ylabel(f'{metric.title()} 相似度')\n",
"# ax1.set_title('各音素类内相似度 vs 全体音素相似度')\n",
"# ax1.set_xticks(range(len(phonemes)))\n",
"# ax1.set_xticklabels(phonemes, rotation=45)\n",
"# ax1.legend()\n",
"# ax1.grid(True, alpha=0.3)\n",
" \n",
"# # 在柱状图上显示数值\n",
"# for i, (bar, mean_val) in enumerate(zip(bars, mean_similarities)):\n",
"# if mean_val > overall_mean:\n",
"# ax1.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.01, \n",
"# f'{mean_val:.3f}', ha='center', va='bottom', fontsize=8, \n",
"# color='green', weight='bold')\n",
"# else:\n",
"# ax1.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.01, \n",
"# f'{mean_val:.3f}', ha='center', va='bottom', fontsize=8, \n",
"# color='red', weight='bold')\n",
" \n",
"# # 图2: 相似度提升程度\n",
"# ax2 = axes[0, 1]\n",
"# improvements = [(sim - overall_mean) for sim in mean_similarities]\n",
"# colors = ['green' if imp > 0 else 'red' for imp in improvements]\n",
" \n",
"# bars2 = ax2.bar(range(len(phonemes)), improvements, color=colors, alpha=0.7)\n",
"# ax2.axhline(y=0, color='black', linestyle='-', linewidth=1)\n",
"# ax2.set_xlabel('音素')\n",
"# ax2.set_ylabel('相似度提升 (相对于全体)')\n",
"# ax2.set_title('音素分类的相似度提升效果')\n",
"# ax2.set_xticks(range(len(phonemes)))\n",
"# ax2.set_xticklabels(phonemes, rotation=45)\n",
"# ax2.grid(True, alpha=0.3)\n",
" \n",
"# # 显示数值\n",
"# for bar, imp in zip(bars2, improvements):\n",
"# ax2.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.001, \n",
"# f'{imp:+.3f}', ha='center', va='bottom' if imp > 0 else 'top', \n",
"# fontsize=8, weight='bold')\n",
" \n",
"# # 图3: 样本数量 vs 相似度\n",
"# ax3 = axes[1, 0]\n",
"# scatter = ax3.scatter(sample_counts, mean_similarities, \n",
"# c=improvements, cmap='RdYlGn', s=60, alpha=0.7)\n",
"# ax3.axhline(y=overall_mean, color='red', linestyle='--', alpha=0.7)\n",
"# ax3.set_xlabel('样本数量')\n",
"# ax3.set_ylabel(f'{metric.title()} 相似度')\n",
"# ax3.set_title('样本数量 vs 相似度')\n",
"# ax3.grid(True, alpha=0.3)\n",
" \n",
"# # 添加颜色条\n",
"# cbar = plt.colorbar(scatter, ax=ax3)\n",
"# cbar.set_label('相似度提升')\n",
" \n",
"# # 图4: 相似度分布统计\n",
"# ax4 = axes[1, 1]\n",
"# ax4.axis('off')\n",
" \n",
"# # 计算统计信息\n",
"# positive_improvements = [imp for imp in improvements if imp > 0]\n",
"# negative_improvements = [imp for imp in improvements if imp <= 0]\n",
" \n",
"# avg_improvement = np.mean(improvements)\n",
"# max_improvement = np.max(improvements)\n",
"# min_improvement = np.min(improvements)\n",
" \n",
"# best_phoneme = phonemes[improvements.index(max_improvement)]\n",
"# worst_phoneme = phonemes[improvements.index(min_improvement)]\n",
" \n",
"# stats_text = f\"\"\"\n",
"# 类内相似度分析统计报告\n",
"\n",
"# 度量方法: {metric.title()} 相似度\n",
"\n",
"# 全体音素基线:\n",
"# - 平均相似度: {overall_mean:.4f} ± {overall_std:.4f}\n",
"# - 样本总数: {overall_result['n_samples']}\n",
"# - 音素数量: {overall_result['n_phonemes']}\n",
"\n",
"# 音素分类效果:\n",
"# - 分析音素数: {len(phonemes)}\n",
"# - 平均提升: {avg_improvement:+.4f}\n",
"# - 最大提升: {max_improvement:+.4f} ({best_phoneme})\n",
"# - 最小提升: {min_improvement:+.4f} ({worst_phoneme})\n",
"\n",
"# 提升统计:\n",
"# - 相似度提升音素: {len(positive_improvements)}/{len(phonemes)} ({len(positive_improvements)/len(phonemes)*100:.1f}%)\n",
"# - 相似度下降音素: {len(negative_improvements)}/{len(phonemes)} ({len(negative_improvements)/len(phonemes)*100:.1f}%)\n",
"\n",
"# 结论:\n",
"# \"\"\"\n",
" \n",
"# if avg_improvement > 0:\n",
"# stats_text += f\"✅ 音素分类整体有效 (平均提升 {avg_improvement:.4f})\\n\"\n",
"# stats_text += f\" 按音素分类比混合所有音素更能保持相似性\"\n",
"# else:\n",
"# stats_text += f\"❌ 音素分类效果有限 (平均下降 {avg_improvement:.4f})\\n\"\n",
"# stats_text += f\" 可能需要重新考虑分类策略\"\n",
" \n",
"# ax4.text(0.05, 0.95, stats_text, transform=ax4.transAxes, fontsize=10,\n",
"# verticalalignment='top', fontfamily='monospace',\n",
"# bbox=dict(boxstyle='round', facecolor='lightblue', alpha=0.8))\n",
" \n",
"# plt.tight_layout()\n",
"# plt.show()\n",
" \n",
"# return improvements\n",
"\n",
"# def create_similarity_dataframe(phoneme_similarities, overall_result):\n",
"# \"\"\"\n",
"# 创建相似度对比的DataFrame\n",
"# \"\"\"\n",
"# data = []\n",
"# overall_mean = overall_result['mean']\n",
" \n",
"# for phoneme, sim_data in phoneme_similarities.items():\n",
"# improvement = sim_data['mean'] - overall_mean\n",
"# relative_improvement = (improvement / overall_mean) * 100\n",
" \n",
"# data.append({\n",
"# 'phoneme': phoneme,\n",
"# 'intra_class_similarity': sim_data['mean'],\n",
"# 'similarity_std': sim_data['std'],\n",
"# 'n_samples': sim_data['n_samples'],\n",
"# 'overall_baseline': overall_mean,\n",
"# 'absolute_improvement': improvement,\n",
"# 'relative_improvement_pct': relative_improvement,\n",
"# 'is_better': improvement > 0\n",
"# })\n",
" \n",
"# df = pd.DataFrame(data)\n",
"# df = df.sort_values('absolute_improvement', ascending=False)\n",
" \n",
"# return df\n",
"\n",
"# # 执行类内相似度分析\n",
"# print(\"开始类内相似度分析...\")\n",
"\n",
"# # 1. 分析每个音素的类内相似度\n",
"# print(\"\\n1. 计算各音素类内相似度\")\n",
"# phoneme_similarities_cosine = analyze_phoneme_similarity(\n",
"# processed_result, metric='cosine', sample_limit=300\n",
"# )\n",
"\n",
"# # 2. 计算全体音素的相似度\n",
"# print(\"\\n2. 计算全体音素相似度作为基线\")\n",
"# overall_result_cosine, all_phoneme_labels = calculate_overall_similarity(\n",
"# processed_result, metric='cosine', sample_per_phoneme=30\n",
"# )\n",
"\n",
"# # 3. 可视化比较\n",
"# print(\"\\n3. 可视化相似度比较\")\n",
"# improvements = visualize_similarity_comparison(\n",
"# phoneme_similarities_cosine, overall_result_cosine, metric='cosine'\n",
"# )\n",
"\n",
"# # 4. 创建详细对比表\n",
"# print(\"\\n4. 详细相似度对比表\")\n",
"# df_similarity = create_similarity_dataframe(phoneme_similarities_cosine, overall_result_cosine)\n",
"# print(df_similarity.to_string(index=False, float_format='%.4f'))\n",
"\n",
"# print(f\"\\n✅ 类内相似度分析完成!\")\n",
"# print(f\"这个分析揭示了音素分类对神经信号相似性的影响。\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 尝试训练模型\n",
"暂时不做异常标签剔除"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Extracting features from sequences...\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"100%|██████████| 40/40 [00:37<00:00, 1.05it/s]\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Dataset shape: (41569, 2561)\n",
"Number of classes: 40\n",
"Class distribution: Counter({' | ': 9855, 'T': 2414, 'AH': 2350, 'IH': 2091, 'N': 1754, 'S': 1406, 'R': 1332, 'L': 1283, 'IY': 1243, 'D': 1124, 'M': 1083, 'DH': 1055, 'K': 1033, 'AY': 1009, 'UW': 937, 'EH': 901, 'Z': 863, 'W': 843, 'AE': 818, 'AA': 646, 'V': 641, 'ER': 632, 'P': 615, 'F': 576, 'EY': 573, 'HH': 536, 'B': 504, 'OW': 490, 'AO': 489, 'Y': 487, 'G': 405, 'NG': 376, 'AW': 239, 'UH': 200, 'TH': 176, 'JH': 156, 'CH': 132, 'SH': 121, 'OY': 111, 'ZH': 70})\n",
"After filtering: (41569, 2561)\n",
"Valid classes: 40\n",
"Training set: (29098, 2561)\n",
"Test set: (12471, 2561)\n"
]
}
],
"source": [
"# Classical Machine Learning for Variable-Length Time Series Classification\n",
"\n",
"import numpy as np\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.ensemble import RandomForestClassifier\n",
"from sklearn.svm import SVC\n",
"from sklearn.metrics import classification_report, accuracy_score\n",
"from sklearn.preprocessing import StandardScaler, LabelEncoder\n",
"from sklearn.linear_model import LogisticRegression\n",
"from collections import Counter\n",
"\n",
"def extract_statistical_features(sequence):\n",
" \"\"\"\n",
" Extract statistical features from variable-length time series\n",
" Features include: mean, std, min, max, skewness, kurtosis for each dimension\n",
" \"\"\"\n",
" if sequence.size == 0:\n",
" return None\n",
" \n",
" features = []\n",
" # Basic statistics for each feature dimension\n",
" features.extend(np.mean(sequence, axis=0)) # Mean\n",
" features.extend(np.std(sequence, axis=0)) # Standard deviation\n",
" features.extend(np.min(sequence, axis=0)) # Minimum\n",
" features.extend(np.max(sequence, axis=0)) # Maximum\n",
" \n",
" # Additional temporal features\n",
" features.append(sequence.shape[0]) # Sequence length\n",
" features.extend(np.mean(np.diff(sequence, axis=0), axis=0)) # Mean derivative\n",
" \n",
" return np.array(features)\n",
"\n",
"def prepare_ml_dataset(group_by_labels):\n",
" \"\"\"\n",
" Prepare dataset for machine learning from grouped labels\n",
" \"\"\"\n",
" X = []\n",
" y = []\n",
" \n",
" print(\"Extracting features from sequences...\")\n",
" for label, sequences in tqdm.tqdm(group_by_labels.items()):\n",
" for seq in sequences:\n",
" features = extract_statistical_features(seq)\n",
" if features is not None:\n",
" X.append(features)\n",
" y.append(label)\n",
" \n",
" X = np.array(X)\n",
" y = np.array(y)\n",
" \n",
" print(f\"Dataset shape: {X.shape}\")\n",
" print(f\"Number of classes: {len(np.unique(y))}\")\n",
" print(f\"Class distribution: {Counter(y)}\")\n",
" \n",
" return X, y\n",
"\n",
"# Prepare the dataset\n",
"X, y = prepare_ml_dataset(result)\n",
"\n",
"# Filter out classes with too few samples (less than 5)\n",
"label_counts = Counter(y)\n",
"valid_labels = [label for label, count in label_counts.items() if count >= 5]\n",
"valid_indices = [i for i, label in enumerate(y) if label in valid_labels]\n",
"\n",
"X_filtered = X[valid_indices]\n",
"y_filtered = y[valid_indices]\n",
"\n",
"print(f\"After filtering: {X_filtered.shape}\")\n",
"print(f\"Valid classes: {len(valid_labels)}\")\n",
"\n",
"# # Memory usage check\n",
"# import psutil\n",
"# import gc\n",
"\n",
"# def check_memory():\n",
"# process = psutil.Process()\n",
"# memory_info = process.memory_info()\n",
"# print(f\"Memory usage: {memory_info.rss / 1024 / 1024:.2f} MB\")\n",
"# return memory_info.rss / 1024 / 1024\n",
"\n",
"# print(f\"Memory before label encoding: {check_memory():.2f} MB\")\n",
"\n",
"# # Force garbage collection\n",
"# gc.collect()\n",
"\n",
"# # Check if dataset is too large\n",
"# if X_filtered.shape[0] > 100000: # More than 100k samples\n",
"# print(\"Warning: Large dataset detected. Consider sampling...\")\n",
"# # Sample a subset for faster processing\n",
"# sample_size = min(50000, X_filtered.shape[0])\n",
"# sample_indices = np.random.choice(X_filtered.shape[0], sample_size, replace=False)\n",
"# X_filtered = X_filtered[sample_indices]\n",
"# y_filtered = y_filtered[sample_indices]\n",
"# print(f\"Sampled to: {X_filtered.shape}\")\n",
"\n",
"# print(f\"Memory after filtering: {check_memory():.2f} MB\")\n",
"\n",
"# Encode labels\n",
"label_encoder = LabelEncoder()\n",
"y_encoded = label_encoder.fit_transform(y_filtered)\n",
"\n",
"# Split the data\n",
"X_train, X_test, y_train, y_test = train_test_split(\n",
" X_filtered, y_encoded, test_size=0.3, random_state=42, stratify=y_encoded\n",
")\n",
"\n",
"# Scale features\n",
"scaler = StandardScaler()\n",
"X_train_scaled = scaler.fit_transform(X_train)\n",
"X_test_scaled = scaler.transform(X_test)\n",
"\n",
"print(f\"Training set: {X_train_scaled.shape}\")\n",
"print(f\"Test set: {X_test_scaled.shape}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"==================================================\n",
"Training Random Forest...\n",
"Train Accuracy: 1.0000\n",
"Test Accuracy: 0.2382\n",
"\n",
"Classification Report for Random Forest:\n",
" precision recall f1-score support\n",
"\n",
" | 0.24 0.99 0.39 2957\n",
" AA 0.00 0.00 0.00 194\n",
" AE 0.00 0.00 0.00 245\n",
" AH 0.12 0.01 0.03 705\n",
" AO 0.00 0.00 0.00 147\n",
" AW 0.00 0.00 0.00 72\n",
" AY 0.25 0.01 0.03 303\n",
" B 1.00 0.01 0.01 151\n",
" CH 0.00 0.00 0.00 40\n",
" D 0.00 0.00 0.00 337\n",
" DH 0.00 0.00 0.00 316\n",
" EH 0.00 0.00 0.00 270\n",
" ER 0.00 0.00 0.00 190\n",
" EY 0.00 0.00 0.00 172\n",
" F 0.00 0.00 0.00 173\n",
" G 0.00 0.00 0.00 121\n",
" HH 0.00 0.00 0.00 161\n",
" IH 0.19 0.01 0.02 627\n",
" IY 0.80 0.01 0.02 373\n",
" JH 0.00 0.00 0.00 47\n",
" K 0.00 0.00 0.00 310\n",
" L 0.00 0.00 0.00 385\n",
" M 0.67 0.01 0.01 325\n",
" N 0.00 0.00 0.00 526\n",
" NG 0.00 0.00 0.00 113\n",
" OW 0.00 0.00 0.00 147\n",
" OY 0.00 0.00 0.00 33\n",
" P 0.00 0.00 0.00 184\n",
" R 0.00 0.00 0.00 400\n",
" S 0.00 0.00 0.00 422\n",
" SH 0.00 0.00 0.00 36\n",
" T 0.10 0.01 0.01 724\n",
" TH 0.00 0.00 0.00 53\n",
" UH 0.00 0.00 0.00 60\n",
" UW 0.00 0.00 0.00 281\n",
" V 0.00 0.00 0.00 192\n",
" W 0.00 0.00 0.00 253\n",
" Y 0.00 0.00 0.00 146\n",
" Z 0.00 0.00 0.00 259\n",
" ZH 0.00 0.00 0.00 21\n",
"\n",
" accuracy 0.24 12471\n",
" macro avg 0.08 0.03 0.01 12471\n",
"weighted avg 0.14 0.24 0.10 12471\n",
"\n",
"\n",
"==================================================\n",
"Training SVM (RBF)...\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/usr/local/lib/python3.11/dist-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
" _warn_prf(average, modifier, f\"{metric.capitalize()} is\", len(result))\n",
"/usr/local/lib/python3.11/dist-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
" _warn_prf(average, modifier, f\"{metric.capitalize()} is\", len(result))\n",
"/usr/local/lib/python3.11/dist-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
" _warn_prf(average, modifier, f\"{metric.capitalize()} is\", len(result))\n"
]
}
],
"source": [
"# # Train Multiple Classical ML Models\n",
"\n",
"# models = {\n",
"# 'Random Forest': RandomForestClassifier(n_estimators=100, random_state=42, n_jobs=-1),\n",
"# # 'SVM (RBF)': SVC(kernel='rbf', random_state=42),\n",
"# # 'SVM (Linear)': SVC(kernel='linear', random_state=42),\n",
"# # 'Logistic Regression': LogisticRegression(random_state=42, max_iter=1000)\n",
"# }\n",
"\n",
"# results = {}\n",
"\n",
"# for model_name, model in models.items():\n",
"# print(f\"\\n{'='*50}\")\n",
"# print(f\"Training {model_name}...\")\n",
" \n",
"# # Train the model\n",
"# model.fit(X_train_scaled, y_train)\n",
" \n",
"# # Make predictions\n",
"# y_pred_train = model.predict(X_train_scaled)\n",
"# y_pred_test = model.predict(X_test_scaled)\n",
" \n",
"# # Calculate accuracies\n",
"# train_acc = accuracy_score(y_train, y_pred_train)\n",
"# test_acc = accuracy_score(y_test, y_pred_test)\n",
" \n",
"# results[model_name] = {\n",
"# 'train_accuracy': train_acc,\n",
"# 'test_accuracy': test_acc,\n",
"# 'predictions': y_pred_test,\n",
"# 'model': model\n",
"# }\n",
" \n",
"# print(f\"Train Accuracy: {train_acc:.4f}\")\n",
"# print(f\"Test Accuracy: {test_acc:.4f}\")\n",
" \n",
"# # Detailed classification report\n",
"# print(f\"\\nClassification Report for {model_name}:\")\n",
"# print(classification_report(y_test, y_pred_test, \n",
"# target_names=label_encoder.classes_[np.unique(y_test)]))\n",
"\n",
"# # Summary of results\n",
"# print(f\"\\n{'='*60}\")\n",
"# print(\"SUMMARY OF RESULTS\")\n",
"# print(f\"{'='*60}\")\n",
"# for model_name, result in results.items():\n",
"# print(f\"{model_name:<20}: Train={result['train_accuracy']:.4f}, Test={result['test_accuracy']:.4f}\")\n",
"\n",
"# # Best model\n",
"# best_model_name = max(results.keys(), key=lambda k: results[k]['test_accuracy'])\n",
"# print(f\"\\nBest model: {best_model_name} with test accuracy: {results[best_model_name]['test_accuracy']:.4f}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"15000"
]
},
"execution_count": 53,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(y_pred_test)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"35000"
]
},
"execution_count": 51,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(y_train)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 🔗 数据集批量处理工作流"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"======================================================================\n",
"🚀 RNN数据批量处理工具 - 新版本\n",
"======================================================================\n",
"🔧 创建RNN数据处理器...\n",
"🔧 初始化RNN数据处理器...\n",
" 模型路径: ../data/t15_pretrained_rnn_baseline\n",
" 数据目录: ../data/hdf5_data_final\n",
" 计算设备: cuda:0\n",
"📋 模型配置:\n",
" Sessions数量: 45\n",
" 神经特征维度: 512\n",
" Patch size: 14\n",
" Patch stride: 4\n",
" 输出类别数: 41\n",
"✅ 模型加载成功\n",
"📊 CSV数据加载完成: 265 条记录\n",
"✅ 初始化完成!\n",
"✅ RNN数据处理器创建成功\n",
"✅ 模型加载成功\n",
"📊 CSV数据加载完成: 265 条记录\n",
"✅ 初始化完成!\n",
"✅ RNN数据处理器创建成功\n"
]
}
],
"source": [
"# 🚀 RNN数据批量处理工具 - 完整版\n",
"import os\n",
"import torch\n",
"import numpy as np\n",
"import pandas as pd\n",
"from omegaconf import OmegaConf\n",
"import time\n",
"from tqdm import tqdm\n",
"import h5py\n",
"from pathlib import Path\n",
"\n",
"# 导入模型相关模块\n",
"import sys\n",
"sys.path.append('../model_training')\n",
"from rnn_model import GRUDecoder\n",
"from evaluate_model_helpers import *\n",
"from data_augmentations import gauss_smooth\n",
"\n",
"print(\"=\"*70)\n",
"print(\"🚀 RNN数据批量处理工具 - 新版本\")\n",
"print(\"=\"*70)\n",
"\n",
"class RNNDataProcessor:\n",
" \"\"\"\n",
" RNN数据批量处理器 - 生成RNN输入输出拼接数据\n",
" \n",
" 核心功能:\n",
" 1. 加载预训练RNN模型\n",
" 2. 处理原始神经数据(高斯平滑 + patch操作\n",
" 3. 获取RNN输出40类置信度分数\n",
" 4. 拼接处理后的输入和输出\n",
" 5. 批量保存所有session数据\n",
" \"\"\"\n",
" \n",
" def __init__(self, model_path, data_dir, csv_path, device='auto'):\n",
" \"\"\"\n",
" 初始化处理器\n",
" \n",
" 参数:\n",
" model_path: 预训练RNN模型路径\n",
" data_dir: 数据目录路径 \n",
" csv_path: 数据描述CSV文件路径\n",
" device: 计算设备 ('auto', 'cpu', 'cuda:0'等)\n",
" \"\"\"\n",
" self.model_path = model_path\n",
" self.data_dir = data_dir\n",
" self.csv_path = csv_path\n",
" \n",
" # 设备选择\n",
" if device == 'auto':\n",
" self.device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')\n",
" else:\n",
" self.device = torch.device(device)\n",
" \n",
" print(f\"🔧 初始化RNN数据处理器...\")\n",
" print(f\" 模型路径: {model_path}\")\n",
" print(f\" 数据目录: {data_dir}\")\n",
" print(f\" 计算设备: {self.device}\")\n",
" \n",
" # 加载配置和模型\n",
" self._load_config()\n",
" self._load_model()\n",
" self._load_csv()\n",
" \n",
" print(f\"✅ 初始化完成!\")\n",
" \n",
" def _load_config(self):\n",
" \"\"\"加载模型配置\"\"\"\n",
" config_path = os.path.join(self.model_path, 'checkpoint/args.yaml')\n",
" if not os.path.exists(config_path):\n",
" raise FileNotFoundError(f\"配置文件不存在: {config_path}\")\n",
" \n",
" self.model_args = OmegaConf.load(config_path)\n",
" \n",
" print(f\"📋 模型配置:\")\n",
" print(f\" Sessions数量: {len(self.model_args['dataset']['sessions'])}\")\n",
" print(f\" 神经特征维度: {self.model_args['model']['n_input_features']}\")\n",
" print(f\" Patch size: {self.model_args['model']['patch_size']}\")\n",
" print(f\" Patch stride: {self.model_args['model']['patch_stride']}\")\n",
" print(f\" 输出类别数: {self.model_args['dataset']['n_classes']}\")\n",
" \n",
" def _load_model(self):\n",
" \"\"\"加载预训练RNN模型\"\"\"\n",
" try:\n",
" # 创建模型\n",
" self.model = GRUDecoder(\n",
" neural_dim=self.model_args['model']['n_input_features'],\n",
" n_units=self.model_args['model']['n_units'], \n",
" n_days=len(self.model_args['dataset']['sessions']),\n",
" n_classes=self.model_args['dataset']['n_classes'],\n",
" rnn_dropout=self.model_args['model']['rnn_dropout'],\n",
" input_dropout=self.model_args['model']['input_network']['input_layer_dropout'],\n",
" n_layers=self.model_args['model']['n_layers'],\n",
" patch_size=self.model_args['model']['patch_size'],\n",
" patch_stride=self.model_args['model']['patch_stride'],\n",
" )\n",
" \n",
" # 加载权重\n",
" checkpoint_path = os.path.join(self.model_path, 'checkpoint/best_checkpoint')\n",
" try:\n",
" checkpoint = torch.load(checkpoint_path, map_location=self.device, weights_only=False)\n",
" except TypeError:\n",
" checkpoint = torch.load(checkpoint_path, map_location=self.device)\n",
" \n",
" # 清理键名\n",
" for key in list(checkpoint['model_state_dict'].keys()):\n",
" checkpoint['model_state_dict'][key.replace(\"module.\", \"\")] = checkpoint['model_state_dict'].pop(key)\n",
" checkpoint['model_state_dict'][key.replace(\"_orig_mod.\", \"\")] = checkpoint['model_state_dict'].pop(key)\n",
" \n",
" self.model.load_state_dict(checkpoint['model_state_dict'])\n",
" self.model.to(self.device)\n",
" self.model.eval()\n",
" \n",
" print(f\"✅ 模型加载成功\")\n",
" \n",
" except Exception as e:\n",
" print(f\"❌ 模型加载失败: {e}\")\n",
" raise\n",
" \n",
" def _load_csv(self):\n",
" \"\"\"加载数据描述文件\"\"\"\n",
" if not os.path.exists(self.csv_path):\n",
" raise FileNotFoundError(f\"CSV文件不存在: {self.csv_path}\")\n",
" \n",
" self.csv_df = pd.read_csv(self.csv_path)\n",
" print(f\"📊 CSV数据加载完成: {len(self.csv_df)} 条记录\")\n",
" \n",
" def _process_single_trial(self, neural_data, session_idx):\n",
" \"\"\"\n",
" 处理单个试验数据\n",
" \n",
" 参数:\n",
" neural_data: 原始神经数据 [time_steps, features]\n",
" session_idx: 会话索引\n",
" \n",
" 返回:\n",
" dict: 包含拼接数据和统计信息\n",
" \"\"\"\n",
" # 添加batch维度\n",
" neural_input = np.expand_dims(neural_data, axis=0)\n",
" neural_tensor = torch.tensor(neural_input, device=self.device, dtype=torch.bfloat16)\n",
" \n",
" # 高斯平滑\n",
" with torch.autocast(device_type=\"cuda\" if self.device.type == \"cuda\" else \"cpu\", \n",
" enabled=self.model_args.get('use_amp', False), dtype=torch.bfloat16):\n",
" \n",
" smoothed_data = gauss_smooth(\n",
" inputs=neural_tensor,\n",
" device=self.device,\n",
" smooth_kernel_std=self.model_args['dataset']['data_transforms']['smooth_kernel_std'],\n",
" smooth_kernel_size=self.model_args['dataset']['data_transforms']['smooth_kernel_size'],\n",
" padding='valid',\n",
" )\n",
" \n",
" # Patch操作复制模型内部逻辑\n",
" processed_data = smoothed_data\n",
" if self.model.patch_size > 0:\n",
" processed_data = processed_data.unsqueeze(1) # [batch, 1, time, features]\n",
" processed_data = processed_data.permute(0, 3, 1, 2) # [batch, features, 1, time]\n",
" \n",
" # 滑动窗口提取\n",
" patches = processed_data.unfold(3, self.model.patch_size, self.model.patch_stride)\n",
" patches = patches.squeeze(2) # [batch, features, patches, patch_size]\n",
" patches = patches.permute(0, 2, 3, 1) # [batch, patches, patch_size, features]\n",
" \n",
" # 展平最后两个维度\n",
" processed_data = patches.reshape(patches.size(0), patches.size(1), -1)\n",
" \n",
" # RNN推理\n",
" with torch.no_grad():\n",
" logits, _ = self.model(\n",
" x=smoothed_data,\n",
" day_idx=torch.tensor([session_idx], device=self.device),\n",
" states=None,\n",
" return_state=True,\n",
" )\n",
" \n",
" # 转换为numpy\n",
" processed_features = processed_data.float().cpu().numpy()[0] # [time_steps, processed_features]\n",
" confidence_scores = logits.float().cpu().numpy()[0] # [time_steps, 40]\n",
" \n",
" # 拼接数据\n",
" concatenated = np.concatenate([processed_features, confidence_scores], axis=1)\n",
" \n",
" return {\n",
" 'concatenated_data': concatenated,\n",
" 'processed_features': processed_features,\n",
" 'confidence_scores': confidence_scores,\n",
" 'original_time_steps': neural_data.shape[0],\n",
" 'processed_time_steps': concatenated.shape[0],\n",
" 'feature_reduction_ratio': concatenated.shape[0] / neural_data.shape[0]\n",
" }\n",
" \n",
" def process_session(self, session_name, data_types=['train', 'val', 'test']):\n",
" \"\"\"\n",
" 处理单个session的数据\n",
" \n",
" 参数:\n",
" session_name: 会话名称\n",
" data_types: 要处理的数据类型列表\n",
" \n",
" 返回:\n",
" dict: 处理结果\n",
" \"\"\"\n",
" print(f\"\\n🔄 处理会话: {session_name}\")\n",
" \n",
" session_idx = self.model_args['dataset']['sessions'].index(session_name)\n",
" session_results = {}\n",
" \n",
" for data_type in data_types:\n",
" data_file = os.path.join(self.data_dir, session_name, f'data_{data_type}.hdf5')\n",
" \n",
" if not os.path.exists(data_file):\n",
" print(f\" ⚠️ {data_type} 数据文件不存在,跳过\")\n",
" continue\n",
" \n",
" print(f\" 📁 处理 {data_type} 数据...\")\n",
" \n",
" try:\n",
" # 加载数据\n",
" data = load_h5py_file(data_file, self.csv_df)\n",
" num_trials = len(data['neural_features'])\n",
" \n",
" if num_trials == 0:\n",
" print(f\" ⚠️ {data_type} 数据为空\")\n",
" continue\n",
" \n",
" # 处理所有试验\n",
" results = {\n",
" 'concatenated_data': [],\n",
" 'processed_features': [],\n",
" 'confidence_scores': [],\n",
" 'trial_metadata': [],\n",
" 'processing_stats': []\n",
" }\n",
" \n",
" for trial_idx in tqdm(range(num_trials), desc=f\" {data_type}\", leave=False):\n",
" neural_data = data['neural_features'][trial_idx]\n",
" \n",
" # 处理单个试验\n",
" trial_result = self._process_single_trial(neural_data, session_idx)\n",
" \n",
" # 保存结果\n",
" results['concatenated_data'].append(trial_result['concatenated_data'])\n",
" results['processed_features'].append(trial_result['processed_features'])\n",
" results['confidence_scores'].append(trial_result['confidence_scores'])\n",
" \n",
" # 保存元数据\n",
" metadata = {\n",
" 'session': session_name,\n",
" 'data_type': data_type,\n",
" 'trial_idx': trial_idx,\n",
" 'block_num': data.get('block_num', [None])[trial_idx],\n",
" 'trial_num': data.get('trial_num', [None])[trial_idx],\n",
" **trial_result\n",
" }\n",
" \n",
" # 添加真实标签(如果可用)\n",
" if data_type in ['train', 'val'] and 'sentence_label' in data:\n",
" metadata.update({\n",
" 'sentence_label': data['sentence_label'][trial_idx],\n",
" 'seq_class_ids': data['seq_class_ids'][trial_idx],\n",
" 'seq_len': data['seq_len'][trial_idx]\n",
" })\n",
" \n",
" results['trial_metadata'].append(metadata)\n",
" results['processing_stats'].append(trial_result)\n",
" \n",
" # 统计信息\n",
" if results['concatenated_data']:\n",
" time_steps = [data.shape[0] for data in results['concatenated_data']]\n",
" feature_dims = [data.shape[1] for data in results['concatenated_data']]\n",
" \n",
" print(f\" ✅ {data_type} 处理完成:\")\n",
" print(f\" 试验数: {len(results['concatenated_data'])}\")\n",
" print(f\" 时间步范围: {min(time_steps)}-{max(time_steps)}\")\n",
" print(f\" 特征维度: {feature_dims[0]} (处理后特征: {feature_dims[0]-40}, 置信度: 40)\")\n",
" \n",
" avg_reduction = np.mean([stat['feature_reduction_ratio'] for stat in results['processing_stats']])\n",
" print(f\" 平均时间压缩比: {avg_reduction:.3f}\")\n",
" \n",
" session_results[data_type] = results\n",
" \n",
" except Exception as e:\n",
" print(f\" ❌ {data_type} 处理失败: {e}\")\n",
" continue\n",
" \n",
" return session_results\n",
" \n",
" def process_all_sessions(self, data_types=['train', 'val', 'test'], save_dir='./rnn_processed_data'):\n",
" \"\"\"\n",
" 批量处理所有sessions\n",
" \n",
" 参数:\n",
" data_types: 要处理的数据类型\n",
" save_dir: 保存目录\n",
" \n",
" 返回:\n",
" dict: 所有处理结果\n",
" \"\"\"\n",
" print(f\"\\n🚀 开始批量处理所有会话...\")\n",
" print(f\" 目标数据类型: {data_types}\")\n",
" print(f\" 保存目录: {save_dir}\")\n",
" \n",
" save_path = Path(save_dir)\n",
" save_path.mkdir(parents=True, exist_ok=True)\n",
" \n",
" all_results = {}\n",
" sessions = self.model_args['dataset']['sessions']\n",
" \n",
" start_time = time.time()\n",
" \n",
" for i, session in enumerate(sessions):\n",
" print(f\"\\n📊 进度: {i+1}/{len(sessions)}\")\n",
" \n",
" try:\n",
" session_results = self.process_session(session, data_types)\n",
" \n",
" if session_results:\n",
" all_results[session] = session_results\n",
" \n",
" # 保存单个session结果\n",
" for data_type, data in session_results.items():\n",
" filename = f\"{session}_{data_type}_rnn_processed.npz\"\n",
" filepath = save_path / filename\n",
" \n",
" save_data = {\n",
" 'concatenated_data': np.array(data['concatenated_data'], dtype=object),\n",
" 'processed_features': np.array(data['processed_features'], dtype=object),\n",
" 'confidence_scores': np.array(data['confidence_scores'], dtype=object),\n",
" 'trial_metadata': np.array(data['trial_metadata'], dtype=object),\n",
" }\n",
" \n",
" np.savez_compressed(str(filepath), **save_data)\n",
" print(f\" 💾 保存: {filename}\")\n",
" \n",
" except Exception as e:\n",
" print(f\"❌ 会话 {session} 处理失败: {e}\")\n",
" continue\n",
" \n",
" # 生成总结\n",
" end_time = time.time()\n",
" processing_time = end_time - start_time\n",
" \n",
" total_trials = sum(\n",
" len(session_data[data_type]['concatenated_data'])\n",
" for session_data in all_results.values()\n",
" for data_type in session_data.keys()\n",
" )\n",
" \n",
" print(f\"\\n🎉 批量处理完成!\")\n",
" print(f\"⏱️ 总耗时: {processing_time/60:.2f} 分钟\")\n",
" print(f\"📊 处理统计:\")\n",
" print(f\" 成功会话: {len(all_results)}/{len(sessions)}\")\n",
" print(f\" 总试验数: {total_trials}\")\n",
" print(f\"💾 数据保存在: {save_dir}\")\n",
" \n",
" # 保存总结信息\n",
" summary = {\n",
" 'processing_time': processing_time,\n",
" 'total_sessions': len(all_results),\n",
" 'total_trials': total_trials,\n",
" 'data_types': data_types,\n",
" 'sessions': list(all_results.keys()),\n",
" 'model_config': {\n",
" 'patch_size': self.model_args['model']['patch_size'],\n",
" 'patch_stride': self.model_args['model']['patch_stride'],\n",
" 'smooth_kernel_size': self.model_args['dataset']['data_transforms']['smooth_kernel_size'],\n",
" 'smooth_kernel_std': self.model_args['dataset']['data_transforms']['smooth_kernel_std'],\n",
" }\n",
" }\n",
" \n",
" import json\n",
" with open(save_path / 'processing_summary.json', 'w') as f:\n",
" json.dump(summary, f, indent=2)\n",
" \n",
" return all_results\n",
"\n",
"# 创建处理器实例\n",
"print(\"🔧 创建RNN数据处理器...\")\n",
"\n",
"try:\n",
" processor = RNNDataProcessor(\n",
" model_path='../data/t15_pretrained_rnn_baseline',\n",
" data_dir='../data/hdf5_data_final',\n",
" csv_path='../data/t15_copyTaskData_description.csv',\n",
" device='auto'\n",
" )\n",
" \n",
" print(f\"✅ RNN数据处理器创建成功\")\n",
" \n",
"except Exception as e:\n",
" print(f\"❌ 处理器创建失败: {e}\")\n",
" processor = None"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"======================================================================\n",
"🎯 RNN数据批量处理 - 使用示例\n",
"======================================================================\n",
"\n",
"📋 可用的处理方法:\n",
"1⃣ 单session处理: processor.process_session('session_name')\n",
"2⃣ 批量处理所有: processor.process_all_sessions()\n",
"\n",
"📊 可用会话数量: 45\n",
"📝 前5个会话: ['t15.2023.08.11', 't15.2023.08.13', 't15.2023.08.18', 't15.2023.08.20', 't15.2023.08.25']\n",
"\n",
"🧪 快速测试: 处理会话 't15.2023.08.13' 的训练数据...\n",
"\n",
"🔄 处理会话: t15.2023.08.13\n",
" 📁 处理 train 数据...\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" "
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" ✅ train 处理完成:\n",
" 试验数: 348\n",
" 时间步范围: 55-352\n",
" 特征维度: 7209 (处理后特征: 7169, 置信度: 40)\n",
" 平均时间压缩比: 0.243\n",
"\n",
"✅ 测试完成!结果概览:\n",
" 处理的试验数: 348\n",
" 第一个试验数据形状: (251, 7209)\n",
" 特征维度详情:\n",
" - 处理后的神经特征: 7168 维\n",
" - RNN置信度分数: 41 维\n",
" - 总拼接特征: 7209 维\n",
" - 时间步数: 251\n",
" 样本元数据:\n",
" - 原始时间步: 1023\n",
" - 处理后时间步: 251\n",
" - 时间压缩比: 0.245\n",
" - 句子标签: Which is most unfortunate because we all lose out.\n",
"\n",
"💡 要批量处理所有数据,运行:\n",
" results = processor.process_all_sessions()\n",
" # 这将处理所有45个sessions的train/val/test数据\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"\r"
]
}
],
"source": [
"# 🎯 使用示例和批量处理\n",
"\n",
"print(\"=\"*70)\n",
"print(\"🎯 RNN数据批量处理 - 使用示例\")\n",
"print(\"=\"*70)\n",
"\n",
"if processor is not None:\n",
" \n",
" # 方法1: 处理单个session (推荐用于测试)\n",
" print(\"\\n📋 可用的处理方法:\")\n",
" print(\"1⃣ 单session处理: processor.process_session('session_name')\")\n",
" print(\"2⃣ 批量处理所有: processor.process_all_sessions()\")\n",
" \n",
" # 显示可用的sessions\n",
" sessions = processor.model_args['dataset']['sessions']\n",
" print(f\"\\n📊 可用会话数量: {len(sessions)}\")\n",
" print(f\"📝 前5个会话: {sessions[:5]}\")\n",
" \n",
" # 快速测试 - 处理第一个session的部分数据\n",
" test_session = sessions[1] # 't15.2023.08.11'\n",
" \n",
" print(f\"\\n🧪 快速测试: 处理会话 '{test_session}' 的训练数据...\")\n",
" \n",
" # 处理单个session仅train数据进行测试\n",
" single_result = processor.process_session(test_session, ['train'])\n",
" \n",
" if single_result and 'train' in single_result:\n",
" train_data = single_result['train']\n",
" \n",
" print(f\"\\n✅ 测试完成!结果概览:\")\n",
" print(f\" 处理的试验数: {len(train_data['concatenated_data'])}\")\n",
" \n",
" if len(train_data['concatenated_data']) > 0:\n",
" sample_data = train_data['concatenated_data'][0]\n",
" print(f\" 第一个试验数据形状: {sample_data.shape}\")\n",
" print(f\" 特征维度详情:\")\n",
" print(f\" - 处理后的神经特征: {sample_data.shape[1] - 41} 维\")\n",
" print(f\" - RNN置信度分数: 41 维\")\n",
" print(f\" - 总拼接特征: {sample_data.shape[1]} 维\")\n",
" print(f\" - 时间步数: {sample_data.shape[0]}\")\n",
" \n",
" # 显示一些样本元数据\n",
" sample_metadata = train_data['trial_metadata'][0]\n",
" print(f\" 样本元数据:\")\n",
" print(f\" - 原始时间步: {sample_metadata['original_time_steps']}\")\n",
" print(f\" - 处理后时间步: {sample_metadata['processed_time_steps']}\")\n",
" print(f\" - 时间压缩比: {sample_metadata['feature_reduction_ratio']:.3f}\")\n",
" \n",
" if 'sentence_label' in sample_metadata:\n",
" print(f\" - 句子标签: {sample_metadata['sentence_label']}\")\n",
" \n",
" print(f\"\\n💡 要批量处理所有数据,运行:\")\n",
" print(f\" results = processor.process_all_sessions()\")\n",
" print(f\" # 这将处理所有45个sessions的train/val/test数据\")\n",
" \n",
"else:\n",
" print(\"❌ 处理器未创建成功,请检查上面的错误信息\")"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"======================================================================\n",
"🚀 批量处理选项\n",
"======================================================================\n",
"📊 批量处理配置:\n",
" 启用批量处理: True\n",
" 保存目录: ./rnn_processed_data\n",
" 数据类型: ['train', 'val', 'test']\n",
" 总会话数: 45\n",
"\n",
"🚀 开始批量处理所有数据...\n",
"⚠️ 这可能需要较长时间预计30-60分钟\n",
"\n",
"🚀 开始批量处理所有会话...\n",
" 目标数据类型: ['train', 'val', 'test']\n",
" 保存目录: ./rnn_processed_data\n",
"\n",
"📊 进度: 1/45\n",
"\n",
"🔄 处理会话: t15.2023.08.11\n",
" 📁 处理 train 数据...\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" "
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" ✅ train 处理完成:\n",
" 试验数: 288\n",
" 时间步范围: 30-251\n",
" 特征维度: 7209 (处理后特征: 7169, 置信度: 40)\n",
" 平均时间压缩比: 0.240\n",
" ⚠️ val 数据文件不存在,跳过\n",
" ⚠️ test 数据文件不存在,跳过\n",
" 💾 保存: t15.2023.08.11_train_rnn_processed.npz\n",
"\n",
"📊 进度: 2/45\n",
"\n",
"🔄 处理会话: t15.2023.08.13\n",
" 📁 处理 train 数据...\n",
" 💾 保存: t15.2023.08.11_train_rnn_processed.npz\n",
"\n",
"📊 进度: 2/45\n",
"\n",
"🔄 处理会话: t15.2023.08.13\n",
" 📁 处理 train 数据...\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" \r"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" ✅ train 处理完成:\n",
" 试验数: 348\n",
" 时间步范围: 55-352\n",
" 特征维度: 7209 (处理后特征: 7169, 置信度: 40)\n",
" 平均时间压缩比: 0.243\n",
" 📁 处理 val 数据...\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" \r"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" ✅ val 处理完成:\n",
" 试验数: 35\n",
" 时间步范围: 90-296\n",
" 特征维度: 7209 (处理后特征: 7169, 置信度: 40)\n",
" 平均时间压缩比: 0.243\n",
" 📁 处理 test 数据...\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" "
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" ✅ test 处理完成:\n",
" 试验数: 35\n",
" 时间步范围: 80-238\n",
" 特征维度: 7209 (处理后特征: 7169, 置信度: 40)\n",
" 平均时间压缩比: 0.242\n",
" 💾 保存: t15.2023.08.13_test_rnn_processed.npz\n",
"\n",
"📊 进度: 3/45\n",
"\n",
"🔄 处理会话: t15.2023.08.18\n",
" 📁 处理 train 数据...\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" "
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" ✅ train 处理完成:\n",
" 试验数: 197\n",
" 时间步范围: 85-402\n",
" 特征维度: 7209 (处理后特征: 7169, 置信度: 40)\n",
" 平均时间压缩比: 0.244\n",
" 📁 处理 val 数据...\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" "
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" ✅ val 处理完成:\n",
" 试验数: 49\n",
" 时间步范围: 86-284\n",
" 特征维度: 7209 (处理后特征: 7169, 置信度: 40)\n",
" 平均时间压缩比: 0.242\n",
" 📁 处理 test 数据...\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
" \r"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" ✅ test 处理完成:\n",
" 试验数: 50\n",
" 时间步范围: 123-319\n",
" 特征维度: 7209 (处理后特征: 7169, 置信度: 40)\n",
" 平均时间压缩比: 0.243\n"
]
},
{
"ename": "KeyboardInterrupt",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m/tmp/ipykernel_186/3974613492.py\u001b[0m in \u001b[0;36m<cell line: 0>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 21\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0;31m# 批量处理\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 23\u001b[0;31m all_results = processor.process_all_sessions(\n\u001b[0m\u001b[1;32m 24\u001b[0m \u001b[0mdata_types\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mDATA_TYPES\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 25\u001b[0m \u001b[0msave_dir\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mSAVE_DIR\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/tmp/ipykernel_186/130448530.py\u001b[0m in \u001b[0;36mprocess_all_sessions\u001b[0;34m(self, data_types, save_dir)\u001b[0m\n\u001b[1;32m 332\u001b[0m }\n\u001b[1;32m 333\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 334\u001b[0;31m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msavez_compressed\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfilepath\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0msave_data\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 335\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mf\" 💾 保存: {filename}\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 336\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/usr/local/lib/python3.11/dist-packages/numpy/lib/npyio.py\u001b[0m in \u001b[0;36msavez_compressed\u001b[0;34m(file, *args, **kwds)\u001b[0m\n\u001b[1;32m 708\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 709\u001b[0m \"\"\"\n\u001b[0;32m--> 710\u001b[0;31m \u001b[0m_savez\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfile\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwds\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 711\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 712\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/usr/local/lib/python3.11/dist-packages/numpy/lib/npyio.py\u001b[0m in \u001b[0;36m_savez\u001b[0;34m(file, args, kwds, compress, allow_pickle, pickle_kwargs)\u001b[0m\n\u001b[1;32m 741\u001b[0m \u001b[0;31m# always force zip64, gh-10776\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 742\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mzipf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mopen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'w'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mforce_zip64\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mfid\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 743\u001b[0;31m format.write_array(fid, val,\n\u001b[0m\u001b[1;32m 744\u001b[0m \u001b[0mallow_pickle\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mallow_pickle\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 745\u001b[0m pickle_kwargs=pickle_kwargs)\n",
"\u001b[0;32m/usr/local/lib/python3.11/dist-packages/numpy/lib/format.py\u001b[0m in \u001b[0;36mwrite_array\u001b[0;34m(fp, array, version, allow_pickle, pickle_kwargs)\u001b[0m\n\u001b[1;32m 717\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mpickle_kwargs\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 718\u001b[0m \u001b[0mpickle_kwargs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 719\u001b[0;31m \u001b[0mpickle\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdump\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mprotocol\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mpickle_kwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 720\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0marray\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mflags\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mf_contiguous\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0marray\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mflags\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mc_contiguous\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 721\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misfileobj\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfp\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/usr/lib/python3.11/zipfile.py\u001b[0m in \u001b[0;36mwrite\u001b[0;34m(self, data)\u001b[0m\n\u001b[1;32m 1176\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_crc\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcrc32\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_crc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1177\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_compressor\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1178\u001b[0;31m \u001b[0mdata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_compressor\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcompress\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1179\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_compress_size\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1180\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_fileobj\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwrite\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mKeyboardInterrupt\u001b[0m: "
]
}
],
"source": [
"# 🚀 批量处理所有数据 (可选择运行)\n",
"\n",
"print(\"=\"*70)\n",
"print(\"🚀 批量处理选项\")\n",
"print(\"=\"*70)\n",
"\n",
"# 设置参数\n",
"ENABLE_FULL_PROCESSING = True # 设为True开始批量处理\n",
"SAVE_DIR = \"./rnn_processed_data\" # 保存目录\n",
"DATA_TYPES = ['train', 'val', 'test'] # 要处理的数据类型\n",
"\n",
"print(f\"📊 批量处理配置:\")\n",
"print(f\" 启用批量处理: {ENABLE_FULL_PROCESSING}\")\n",
"print(f\" 保存目录: {SAVE_DIR}\")\n",
"print(f\" 数据类型: {DATA_TYPES}\")\n",
"print(f\" 总会话数: {len(processor.model_args['dataset']['sessions'])}\")\n",
"\n",
"if ENABLE_FULL_PROCESSING and processor is not None:\n",
" print(f\"\\n🚀 开始批量处理所有数据...\")\n",
" print(f\"⚠️ 这可能需要较长时间预计30-60分钟\")\n",
" \n",
" # 批量处理\n",
" all_results = processor.process_all_sessions(\n",
" data_types=DATA_TYPES,\n",
" save_dir=SAVE_DIR\n",
" )\n",
" \n",
" print(f\"🎉 批量处理完成!结果保存在: {SAVE_DIR}\")\n",
" \n",
"else:\n",
" print(f\"\\n💡 要开始批量处理,请将 ENABLE_FULL_PROCESSING 设为 True\")\n",
" print(f\" 或者手动运行: processor.process_all_sessions()\")\n",
"\n",
"print(f\"\\n📋 数据使用说明:\")\n",
"print(f\"✅ 处理完成后,每个文件包含:\")\n",
"print(f\" - concatenated_data: 拼接后的特征 [神经特征(7168) + 置信度(41)]\")\n",
"print(f\" - processed_features: 仅处理后的神经特征\")\n",
"print(f\" - confidence_scores: 仅RNN输出的41类置信度分数\")\n",
"print(f\" - trial_metadata: 试验元数据(标签、时间步等)\")\n",
"print(f\"\")\n",
"print(f\"🔧 加载保存的数据:\")\n",
"print(f\" data = np.load('session_name_train_rnn_processed.npz', allow_pickle=True)\")\n",
"print(f\" features = data['concatenated_data'] # 用于训练分类器\")\n",
"print(f\" metadata = data['trial_metadata'] # 获取标签和其他信息\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"ename": "NameError",
"evalue": "name 'all_results' is not defined",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m/tmp/ipykernel_186/3056958119.py\u001b[0m in \u001b[0;36m<cell line: 0>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mall_results\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mNameError\u001b[0m: name 'all_results' is not defined"
]
}
],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 模型建立"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"🌲 初始化随机森林回归模型\n",
"🌲 随机森林回归器初始化:\n",
" 时间窗口大小: 30\n",
" 树的数量: 100\n",
" 最大深度: 10\n",
" 并行任务: -1\n",
"\n",
"✅ 随机森林回归器准备完成!\n",
"🔧 下一步: 准备训练数据和开始训练\n"
]
}
],
"source": [
"# 🌲 随机森林多输出回归模型实现\n",
"import numpy as np\n",
"from sklearn.ensemble import RandomForestRegressor\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error\n",
"from sklearn.preprocessing import StandardScaler\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns\n",
"from tqdm import tqdm\n",
"import warnings\n",
"warnings.filterwarnings('ignore')\n",
"\n",
"class TimeWindowRandomForestRegressor:\n",
" \"\"\"\n",
" 基于时间窗口的随机森林多输出回归器\n",
" 用于预测40个音素的概率分布\n",
" \"\"\"\n",
" \n",
" def __init__(self, window_size=30, n_estimators=100, max_depth=10, n_jobs=-1, random_state=42):\n",
" \"\"\"\n",
" 初始化模型\n",
" \n",
" 参数:\n",
" window_size: 时间窗口大小\n",
" n_estimators: 随机森林中树的数量\n",
" max_depth: 树的最大深度\n",
" n_jobs: 并行任务数\n",
" random_state: 随机种子\n",
" \"\"\"\n",
" self.window_size = window_size\n",
" self.n_estimators = n_estimators\n",
" self.max_depth = max_depth\n",
" self.n_jobs = n_jobs\n",
" self.random_state = random_state\n",
" \n",
" # 初始化模型和预处理器\n",
" self.regressor = RandomForestRegressor(\n",
" n_estimators=n_estimators,\n",
" max_depth=max_depth,\n",
" n_jobs=n_jobs,\n",
" random_state=random_state,\n",
" verbose=1\n",
" )\n",
" \n",
" self.scaler = StandardScaler()\n",
" self.is_fitted = False\n",
" \n",
" print(f\"🌲 随机森林回归器初始化:\")\n",
" print(f\" 时间窗口大小: {window_size}\")\n",
" print(f\" 树的数量: {n_estimators}\")\n",
" print(f\" 最大深度: {max_depth}\")\n",
" print(f\" 并行任务: {n_jobs}\")\n",
" \n",
" def create_time_windows(self, neural_features, phoneme_targets=None):\n",
" \"\"\"\n",
" 创建时间窗口特征\n",
" \n",
" 参数:\n",
" neural_features: 神经特征 [time_steps, 512]\n",
" phoneme_targets: 音素目标 [time_steps, 40] (可选)\n",
" \n",
" 返回:\n",
" windowed_features: [samples, window_size * 512]\n",
" windowed_targets: [samples, 40] (如果提供targets)\n",
" \"\"\"\n",
" if len(neural_features) < self.window_size:\n",
" print(f\"⚠️ 数据长度 {len(neural_features)} 小于窗口大小 {self.window_size}\")\n",
" return None, None\n",
" \n",
" n_samples = len(neural_features) - self.window_size + 1\n",
" n_features = neural_features.shape[1]\n",
" \n",
" # 创建时间窗口特征\n",
" windowed_features = np.zeros((n_samples, self.window_size * n_features))\n",
" \n",
" for i in range(n_samples):\n",
" # 展平时间窗口内的所有特征\n",
" window_data = neural_features[i:i+self.window_size].flatten()\n",
" windowed_features[i] = window_data\n",
" \n",
" windowed_targets = None\n",
" if phoneme_targets is not None:\n",
" # 使用窗口中心点的音素概率作为目标\n",
" center_offset = self.window_size // 2\n",
" windowed_targets = phoneme_targets[center_offset:center_offset+n_samples]\n",
" \n",
" return windowed_features, windowed_targets\n",
" \n",
" def prepare_dataset_for_training(self, datasets_list, dataset_type=\"train\"):\n",
" \"\"\"\n",
" 准备训练数据集\n",
" \n",
" 参数:\n",
" datasets_list: DataFrame列表 (train_datasets, val_datasets, etc.)\n",
" dataset_type: 数据集类型名称\n",
" \n",
" 返回:\n",
" X: 特征矩阵 [总样本数, window_size * 512]\n",
" y: 目标矩阵 [总样本数, 40]\n",
" \"\"\"\n",
" print(f\"\\n📊 准备{dataset_type}数据集:\")\n",
" print(f\" 输入数据集数量: {len(datasets_list)}\")\n",
" \n",
" all_X = []\n",
" all_y = []\n",
" \n",
" for i, df in enumerate(tqdm(datasets_list, desc=f\"处理{dataset_type}数据\")):\n",
" # 提取神经特征 (前512列)\n",
" neural_cols = [col for col in df.columns if col.startswith('neural_feat_')]\n",
" neural_features = df[neural_cols].values\n",
" \n",
" # 提取音素目标 (40列音素概率)\n",
" phoneme_cols = [col for col in df.columns if col.startswith('phoneme_')]\n",
" phoneme_targets = df[phoneme_cols].values\n",
" \n",
" # 按trial分组处理\n",
" trials = df['trial_idx'].unique()\n",
" \n",
" for trial_idx in trials:\n",
" trial_mask = df['trial_idx'] == trial_idx\n",
" trial_neural = neural_features[trial_mask]\n",
" trial_phonemes = phoneme_targets[trial_mask]\n",
" \n",
" # 创建时间窗口\n",
" windowed_X, windowed_y = self.create_time_windows(trial_neural, trial_phonemes)\n",
" \n",
" if windowed_X is not None and windowed_y is not None:\n",
" all_X.append(windowed_X)\n",
" all_y.append(windowed_y)\n",
" \n",
" if not all_X:\n",
" print(f\"❌ 没有有效的{dataset_type}数据\")\n",
" return None, None\n",
" \n",
" # 合并所有数据\n",
" X = np.vstack(all_X)\n",
" y = np.vstack(all_y)\n",
" \n",
" print(f\" ✅ {dataset_type}数据准备完成:\")\n",
" print(f\" 特征矩阵形状: {X.shape}\")\n",
" print(f\" 目标矩阵形状: {y.shape}\")\n",
" print(f\" 内存使用: {X.nbytes / 1024**2:.1f} MB (X) + {y.nbytes / 1024**2:.1f} MB (y)\")\n",
" \n",
" return X, y\n",
" \n",
" def fit(self, X_train, y_train, X_val=None, y_val=None):\n",
" \"\"\"\n",
" 训练模型\n",
" \n",
" 参数:\n",
" X_train: 训练特征\n",
" y_train: 训练目标\n",
" X_val: 验证特征 (可选)\n",
" y_val: 验证目标 (可选)\n",
" \"\"\"\n",
" print(f\"\\n🚀 开始训练随机森林回归模型:\")\n",
" print(f\" 训练样本数: {X_train.shape[0]:,}\")\n",
" print(f\" 特征维度: {X_train.shape[1]:,}\")\n",
" print(f\" 目标维度: {y_train.shape[1]}\")\n",
" \n",
" # 标准化特征\n",
" print(\" 🔄 标准化特征...\")\n",
" X_train_scaled = self.scaler.fit_transform(X_train)\n",
" \n",
" # 训练模型\n",
" print(\" 🌲 训练随机森林...\")\n",
" self.regressor.fit(X_train_scaled, y_train)\n",
" \n",
" self.is_fitted = True\n",
" \n",
" # 计算训练集性能\n",
" print(\" 📊 评估训练集性能...\")\n",
" train_predictions = self.regressor.predict(X_train_scaled)\n",
" train_mse = mean_squared_error(y_train, train_predictions)\n",
" train_r2 = r2_score(y_train, train_predictions)\n",
" train_mae = mean_absolute_error(y_train, train_predictions)\n",
" \n",
" print(f\" ✅ 训练完成!\")\n",
" print(f\" 训练集 MSE: {train_mse:.6f}\")\n",
" print(f\" 训练集 R²: {train_r2:.4f}\")\n",
" print(f\" 训练集 MAE: {train_mae:.6f}\")\n",
" \n",
" # 如果有验证集,计算验证集性能\n",
" if X_val is not None and y_val is not None:\n",
" print(\" 📊 评估验证集性能...\")\n",
" X_val_scaled = self.scaler.transform(X_val)\n",
" val_predictions = self.regressor.predict(X_val_scaled)\n",
" val_mse = mean_squared_error(y_val, val_predictions)\n",
" val_r2 = r2_score(y_val, val_predictions)\n",
" val_mae = mean_absolute_error(y_val, val_predictions)\n",
" \n",
" print(f\" 验证集 MSE: {val_mse:.6f}\")\n",
" print(f\" 验证集 R²: {val_r2:.4f}\")\n",
" print(f\" 验证集 MAE: {val_mae:.6f}\")\n",
" \n",
" return {\n",
" 'train_mse': train_mse, 'train_r2': train_r2, 'train_mae': train_mae,\n",
" 'val_mse': val_mse, 'val_r2': val_r2, 'val_mae': val_mae\n",
" }\n",
" \n",
" return {\n",
" 'train_mse': train_mse, 'train_r2': train_r2, 'train_mae': train_mae\n",
" }\n",
" \n",
" def predict(self, X):\n",
" \"\"\"预测\"\"\"\n",
" if not self.is_fitted:\n",
" raise ValueError(\"模型尚未训练请先调用fit()方法\")\n",
" \n",
" X_scaled = self.scaler.transform(X)\n",
" return self.regressor.predict(X_scaled)\n",
" \n",
" def get_feature_importance(self, top_k=20):\n",
" \"\"\"获取特征重要性\"\"\"\n",
" if not self.is_fitted:\n",
" raise ValueError(\"模型尚未训练请先调用fit()方法\")\n",
" \n",
" importances = self.regressor.feature_importances_\n",
" \n",
" # 创建特征名称 (window_timestep_feature)\n",
" feature_names = []\n",
" for t in range(self.window_size):\n",
" for f in range(512):\n",
" feature_names.append(f\"t{t}_feat{f}\")\n",
" \n",
" # 获取top-k重要特征\n",
" top_indices = np.argsort(importances)[::-1][:top_k]\n",
" top_features = [(feature_names[i], importances[i]) for i in top_indices]\n",
" \n",
" return top_features, importances\n",
"\n",
"# 初始化模型\n",
"print(\"🌲 初始化随机森林回归模型\")\n",
"rf_regressor = TimeWindowRandomForestRegressor(\n",
" window_size=30, # 时间窗口大小\n",
" n_estimators=100, # 树的数量\n",
" max_depth=10, # 最大深度 (防止过拟合)\n",
" n_jobs=-1, # 使用所有CPU核心\n",
" random_state=42\n",
")\n",
"\n",
"print(\"\\n✅ 随机森林回归器准备完成!\")\n",
"print(\"🔧 下一步: 准备训练数据和开始训练\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"🚀 开始数据准备和模型训练流程\n",
"============================================================\n"
]
},
{
"ename": "NameError",
"evalue": "name 'train_datasets' is not defined",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m/tmp/ipykernel_37/3627267466.py\u001b[0m in \u001b[0;36m<cell line: 0>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;31m# 检查数据可用性\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mtrain_datasets\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 7\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"❌ 没有可用的训练数据,请先运行数据处理工作流\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mNameError\u001b[0m: name 'train_datasets' is not defined"
]
}
],
"source": [
"# 🚀 准备数据并训练随机森林回归模型\n",
"print(\"🚀 开始数据准备和模型训练流程\")\n",
"print(\"=\"*60)\n",
"\n",
"# 检查数据可用性\n",
"if not train_datasets:\n",
" print(\"❌ 没有可用的训练数据,请先运行数据处理工作流\")\n",
"else:\n",
" print(f\"✅ 检测到数据:\")\n",
" print(f\" 训练数据集: {len(train_datasets)} 个sessions\")\n",
" print(f\" 验证数据集: {len(val_datasets)} 个sessions\")\n",
" print(f\" 测试数据集: {len(test_datasets)} 个sessions\")\n",
"\n",
" # 1. 准备训练数据\n",
" print(f\"\\n📊 第1步: 准备训练数据\")\n",
" X_train, y_train = rf_regressor.prepare_dataset_for_training(train_datasets, \"训练集\")\n",
" \n",
" # 2. 准备验证数据\n",
" print(f\"\\n📊 第2步: 准备验证数据\")\n",
" X_val, y_val = rf_regressor.prepare_dataset_for_training(val_datasets, \"验证集\")\n",
" \n",
" if X_train is not None and y_train is not None:\n",
" print(f\"\\n📈 数据准备完成统计:\")\n",
" print(f\" 训练集: {X_train.shape[0]:,} 样本\")\n",
" print(f\" 验证集: {X_val.shape[0]:,} 样本\" if X_val is not None else \" 验证集: 无\")\n",
" print(f\" 特征维度: {X_train.shape[1]:,} (时间窗口30 × 512特征)\")\n",
" print(f\" 目标维度: {y_train.shape[1]} (40个音素概率)\")\n",
" \n",
" # 检查数据质量\n",
" print(f\"\\n🔍 数据质量检查:\")\n",
" print(f\" 训练特征范围: [{X_train.min():.4f}, {X_train.max():.4f}]\")\n",
" print(f\" 训练目标范围: [{y_train.min():.4f}, {y_train.max():.4f}]\")\n",
" print(f\" 训练特征均值: {X_train.mean():.4f}\")\n",
" print(f\" 训练目标均值: {y_train.mean():.4f}\")\n",
" \n",
" # 检查是否有NaN或无穷值\n",
" nan_count_X = np.isnan(X_train).sum()\n",
" nan_count_y = np.isnan(y_train).sum()\n",
" inf_count_X = np.isinf(X_train).sum()\n",
" inf_count_y = np.isinf(y_train).sum()\n",
" \n",
" print(f\" NaN检查: X有{nan_count_X}个, y有{nan_count_y}个\")\n",
" print(f\" Inf检查: X有{inf_count_X}个, y有{inf_count_y}个\")\n",
" \n",
" if nan_count_X > 0 or nan_count_y > 0 or inf_count_X > 0 or inf_count_y > 0:\n",
" print(\"⚠️ 检测到异常值,将进行清理...\")\n",
" # 清理异常值\n",
" valid_mask = ~(np.isnan(X_train).any(axis=1) | np.isnan(y_train).any(axis=1) | \n",
" np.isinf(X_train).any(axis=1) | np.isinf(y_train).any(axis=1))\n",
" X_train = X_train[valid_mask]\n",
" y_train = y_train[valid_mask]\n",
" \n",
" if X_val is not None and y_val is not None:\n",
" valid_mask_val = ~(np.isnan(X_val).any(axis=1) | np.isnan(y_val).any(axis=1) | \n",
" np.isinf(X_val).any(axis=1) | np.isinf(y_val).any(axis=1))\n",
" X_val = X_val[valid_mask_val]\n",
" y_val = y_val[valid_mask_val]\n",
" \n",
" print(f\"✅ 数据清理完成,剩余训练样本: {X_train.shape[0]:,}\")\n",
" \n",
" # 3. 训练模型\n",
" print(f\"\\n🌲 第3步: 训练随机森林回归模型\")\n",
" training_results = rf_regressor.fit(X_train, y_train, X_val, y_val)\n",
" \n",
" # 4. 分析训练结果\n",
" print(f\"\\n📊 第4步: 训练结果分析\")\n",
" print(\"=\"*50)\n",
" \n",
" for metric, value in training_results.items():\n",
" metric_name = metric.replace('_', ' ').title()\n",
" print(f\" {metric_name}: {value:.6f}\")\n",
" \n",
" # 5. 特征重要性分析\n",
" print(f\"\\n🔍 第5步: 特征重要性分析\")\n",
" top_features, all_importances = rf_regressor.get_feature_importance(top_k=20)\n",
" \n",
" print(f\"\\n🏆 Top 20 重要特征:\")\n",
" print(f\"{'排名':>4} {'特征名称':>15} {'重要性':>10}\")\n",
" print(\"-\" * 35)\n",
" for i, (feature_name, importance) in enumerate(top_features):\n",
" print(f\"{i+1:>4} {feature_name:>15} {importance:>10.6f}\")\n",
" \n",
" # 分析时间窗口内的重要性分布\n",
" print(f\"\\n📈 时间窗口重要性分布:\")\n",
" window_importances = np.zeros(rf_regressor.window_size)\n",
" for i in range(rf_regressor.window_size):\n",
" start_idx = i * 512\n",
" end_idx = (i + 1) * 512\n",
" window_importances[i] = all_importances[start_idx:end_idx].sum()\n",
" \n",
" max_time_step = np.argmax(window_importances)\n",
" print(f\" 最重要的时间步: t{max_time_step} (重要性: {window_importances[max_time_step]:.6f})\")\n",
" print(f\" 窗口中心位置: t{rf_regressor.window_size//2}\")\n",
" print(f\" 重要性分布: 前5个时间步的重要性\")\n",
" for i in range(min(5, len(window_importances))):\n",
" print(f\" t{i}: {window_importances[i]:.6f}\")\n",
" \n",
" print(f\"\\n✅ 随机森林回归模型训练完成!\")\n",
" print(f\"🎯 模型可以预测40个音素的概率分布\")\n",
" print(f\"📊 基于30时间步的神经特征窗口\")\n",
" print(f\"🌲 使用{rf_regressor.n_estimators}棵决策树\")\n",
" \n",
" else:\n",
" print(\"❌ 数据准备失败,无法训练模型\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 📊 模型评估和可视化分析\n",
"def evaluate_phoneme_predictions(rf_model, X_test, y_test, dataset_name=\"测试集\"):\n",
" \"\"\"\n",
" 评估每个音素的预测性能\n",
" \"\"\"\n",
" print(f\"\\n📊 {dataset_name}详细评估\")\n",
" print(\"=\"*50)\n",
" \n",
" # 获取预测结果\n",
" y_pred = rf_model.predict(X_test)\n",
" \n",
" # 计算每个音素的性能指标\n",
" phoneme_metrics = []\n",
" \n",
" for i in range(40): # 40个音素\n",
" phoneme_name = LOGIT_TO_PHONEME[i]\n",
" \n",
" # 计算单个音素的指标\n",
" mse = mean_squared_error(y_test[:, i], y_pred[:, i])\n",
" r2 = r2_score(y_test[:, i], y_pred[:, i])\n",
" mae = mean_absolute_error(y_test[:, i], y_pred[:, i])\n",
" \n",
" # 计算相关系数\n",
" correlation = np.corrcoef(y_test[:, i], y_pred[:, i])[0, 1]\n",
" \n",
" phoneme_metrics.append({\n",
" 'phoneme_id': i,\n",
" 'phoneme_name': phoneme_name,\n",
" 'mse': mse, \n",
" 'r2': r2,\n",
" 'mae': mae,\n",
" 'correlation': correlation if not np.isnan(correlation) else 0.0\n",
" })\n",
" \n",
" # 转换为DataFrame便于分析\n",
" metrics_df = pd.DataFrame(phoneme_metrics)\n",
" \n",
" # 打印总体统计\n",
" print(f\"📈 总体性能指标:\")\n",
" print(f\" 平均 MSE: {metrics_df['mse'].mean():.6f}\")\n",
" print(f\" 平均 R²: {metrics_df['r2'].mean():.4f}\")\n",
" print(f\" 平均 MAE: {metrics_df['mae'].mean():.6f}\")\n",
" print(f\" 平均相关系数: {metrics_df['correlation'].mean():.4f}\")\n",
" \n",
" # 找出最佳和最差预测的音素\n",
" best_r2_idx = metrics_df['r2'].idxmax()\n",
" worst_r2_idx = metrics_df['r2'].idxmin()\n",
" \n",
" print(f\"\\n🏆 最佳预测音素:\")\n",
" best_phoneme = metrics_df.loc[best_r2_idx]\n",
" print(f\" {best_phoneme['phoneme_name']} (ID: {best_phoneme['phoneme_id']})\")\n",
" print(f\" R²: {best_phoneme['r2']:.4f}, MSE: {best_phoneme['mse']:.6f}\")\n",
" \n",
" print(f\"\\n📉 最差预测音素:\")\n",
" worst_phoneme = metrics_df.loc[worst_r2_idx]\n",
" print(f\" {worst_phoneme['phoneme_name']} (ID: {worst_phoneme['phoneme_id']})\")\n",
" print(f\" R²: {worst_phoneme['r2']:.4f}, MSE: {worst_phoneme['mse']:.6f}\")\n",
" \n",
" return metrics_df, y_pred\n",
"\n",
"def visualize_prediction_results(metrics_df, y_true, y_pred, save_plots=False):\n",
" \"\"\"\n",
" 可视化预测结果\n",
" \"\"\"\n",
" print(f\"\\n📊 创建可视化图表...\")\n",
" \n",
" # 设置图表样式\n",
" plt.style.use('default')\n",
" fig = plt.figure(figsize=(20, 12))\n",
" \n",
" # 1. R²分数分布\n",
" plt.subplot(2, 3, 1)\n",
" plt.hist(metrics_df['r2'], bins=20, alpha=0.7, color='skyblue', edgecolor='black')\n",
" plt.axvline(metrics_df['r2'].mean(), color='red', linestyle='--', \n",
" label=f'平均值: {metrics_df[\"r2\"].mean():.4f}')\n",
" plt.xlabel('R² Score')\n",
" plt.ylabel('音素数量')\n",
" plt.title('R² Score 分布')\n",
" plt.legend()\n",
" plt.grid(True, alpha=0.3)\n",
" \n",
" # 2. MSE分布\n",
" plt.subplot(2, 3, 2)\n",
" plt.hist(metrics_df['mse'], bins=20, alpha=0.7, color='lightcoral', edgecolor='black')\n",
" plt.axvline(metrics_df['mse'].mean(), color='red', linestyle='--',\n",
" label=f'平均值: {metrics_df[\"mse\"].mean():.6f}')\n",
" plt.xlabel('Mean Squared Error')\n",
" plt.ylabel('音素数量')\n",
" plt.title('MSE 分布')\n",
" plt.legend()\n",
" plt.grid(True, alpha=0.3)\n",
" \n",
" # 3. 前10个音素的性能对比\n",
" plt.subplot(2, 3, 3)\n",
" top_10 = metrics_df.nlargest(10, 'r2')\n",
" bars = plt.bar(range(10), top_10['r2'], color='lightgreen', alpha=0.7)\n",
" plt.xlabel('音素排名')\n",
" plt.ylabel('R² Score')\n",
" plt.title('Top 10 音素预测性能')\n",
" plt.xticks(range(10), top_10['phoneme_name'], rotation=45)\n",
" plt.grid(True, alpha=0.3)\n",
" \n",
" # 添加数值标签\n",
" for i, bar in enumerate(bars):\n",
" height = bar.get_height()\n",
" plt.text(bar.get_x() + bar.get_width()/2., height + 0.001,\n",
" f'{height:.3f}', ha='center', va='bottom', fontsize=8)\n",
" \n",
" # 4. 真实值 vs 预测值散点图 (选择最佳音素)\n",
" plt.subplot(2, 3, 4)\n",
" best_phoneme_idx = metrics_df['r2'].idxmax()\n",
" phoneme_id = metrics_df.loc[best_phoneme_idx, 'phoneme_id']\n",
" phoneme_name = metrics_df.loc[best_phoneme_idx, 'phoneme_name']\n",
" \n",
" # 随机采样1000个点以避免图表过于密集\n",
" sample_size = min(1000, len(y_true))\n",
" sample_indices = np.random.choice(len(y_true), sample_size, replace=False)\n",
" \n",
" plt.scatter(y_true[sample_indices, phoneme_id], y_pred[sample_indices, phoneme_id], \n",
" alpha=0.6, s=20, color='blue')\n",
" \n",
" # 添加对角线 (完美预测线)\n",
" min_val = min(y_true[:, phoneme_id].min(), y_pred[:, phoneme_id].min())\n",
" max_val = max(y_true[:, phoneme_id].max(), y_pred[:, phoneme_id].max())\n",
" plt.plot([min_val, max_val], [min_val, max_val], 'r--', alpha=0.8, label='完美预测')\n",
" \n",
" plt.xlabel('真实值')\n",
" plt.ylabel('预测值')\n",
" plt.title(f'最佳音素 {phoneme_name} 的预测结果')\n",
" plt.legend()\n",
" plt.grid(True, alpha=0.3)\n",
" \n",
" # 5. 相关系数热力图 (前20个音素)\n",
" plt.subplot(2, 3, 5)\n",
" top_20_correlations = metrics_df.nlargest(20, 'correlation')\n",
" corr_data = top_20_correlations[['phoneme_name', 'correlation']].set_index('phoneme_name')\n",
" \n",
" # 创建热力图数据\n",
" heatmap_data = corr_data.values.reshape(-1, 1)\n",
" im = plt.imshow(heatmap_data.T, cmap='RdYlBu_r', aspect='auto', vmin=0, vmax=1)\n",
" \n",
" plt.colorbar(im, shrink=0.8)\n",
" plt.yticks([0], ['相关系数'])\n",
" plt.xticks(range(len(top_20_correlations)), top_20_correlations['phoneme_name'], \n",
" rotation=45, ha='right')\n",
" plt.title('Top 20 音素相关系数')\n",
" \n",
" # 6. 各音素预测误差箱线图 (前10个音素)\n",
" plt.subplot(2, 3, 6)\n",
" top_10_ids = metrics_df.nlargest(10, 'r2')['phoneme_id'].values\n",
" errors_data = []\n",
" labels = []\n",
" \n",
" for phoneme_id in top_10_ids:\n",
" errors = np.abs(y_true[:, phoneme_id] - y_pred[:, phoneme_id])\n",
" errors_data.append(errors)\n",
" labels.append(LOGIT_TO_PHONEME[phoneme_id])\n",
" \n",
" plt.boxplot(errors_data, labels=labels)\n",
" plt.xlabel('音素')\n",
" plt.ylabel('绝对误差')\n",
" plt.title('Top 10 音素预测误差分布')\n",
" plt.xticks(rotation=45)\n",
" plt.grid(True, alpha=0.3)\n",
" \n",
" plt.tight_layout()\n",
" \n",
" if save_plots:\n",
" plt.savefig('./processed_datasets/rf_regression_results.png', dpi=300, bbox_inches='tight')\n",
" print(\"📁 图表已保存至: ./processed_datasets/rf_regression_results.png\")\n",
" \n",
" plt.show()\n",
"\n",
"# 如果模型训练成功,进行评估\n",
"if 'rf_regressor' in locals() and rf_regressor.is_fitted:\n",
" print(f\"\\n🎯 开始模型评估和可视化\")\n",
" \n",
" # 评估验证集\n",
" if X_val is not None and y_val is not None:\n",
" val_metrics, val_predictions = evaluate_phoneme_predictions(\n",
" rf_regressor, X_val, y_val, \"验证集\"\n",
" )\n",
" \n",
" # 可视化结果\n",
" visualize_prediction_results(val_metrics, y_val, val_predictions, save_plots=True)\n",
" \n",
" # 保存详细结果\n",
" val_metrics.to_csv('./processed_datasets/phoneme_prediction_metrics.csv', index=False)\n",
" print(f\"\\n📁 详细评估结果已保存至: ./processed_datasets/phoneme_prediction_metrics.csv\")\n",
" \n",
" # 准备测试集数据 (如果有)\n",
" if test_datasets:\n",
" print(f\"\\n🔮 准备测试集预测...\")\n",
" X_test, y_test = rf_regressor.prepare_dataset_for_training(test_datasets, \"测试集\")\n",
" \n",
" if X_test is not None:\n",
" test_metrics, test_predictions = evaluate_phoneme_predictions(\n",
" rf_regressor, X_test, y_test, \"测试集\"\n",
" )\n",
" print(f\"\\n✅ 测试集评估完成\")\n",
" else:\n",
" print(f\"⚠️ 测试集数据准备失败\")\n",
" \n",
" print(f\"\\n🎉 随机森林回归模型完整评估完成!\")\n",
" print(f\"📊 生成了详细的性能分析和可视化图表\")\n",
" print(f\"🔧 模型已准备好用于实际预测任务\")\n",
" \n",
"else:\n",
" print(\"⚠️ 模型尚未训练完成,请先运行训练代码\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 🎯 回归结果转分类结果分析\n",
"def regression_to_classification_analysis(y_true_probs, y_pred_probs, show_detailed_metrics=True):\n",
" \"\"\"\n",
" 将回归预测的40个音素概率转换为分类结果并进行分析\n",
" \n",
" 参数:\n",
" y_true_probs: 真实的40个音素概率 [n_samples, 40]\n",
" y_pred_probs: 预测的40个音素概率 [n_samples, 40]\n",
" show_detailed_metrics: 是否显示详细的分类指标\n",
" \n",
" 返回:\n",
" classification_results: 包含分类结果的字典\n",
" \"\"\"\n",
" print(\"🎯 回归结果转分类结果分析\")\n",
" print(\"=\"*60)\n",
" \n",
" # 1. 将概率转换为分类标签\n",
" y_true_classes = np.argmax(y_true_probs, axis=1) # 真实类别\n",
" y_pred_classes = np.argmax(y_pred_probs, axis=1) # 预测类别\n",
" \n",
" # 2. 计算分类准确率\n",
" accuracy = (y_true_classes == y_pred_classes).mean()\n",
" \n",
" print(f\"📊 分类结果概览:\")\n",
" print(f\" 总样本数: {len(y_true_classes):,}\")\n",
" print(f\" 分类准确率: {accuracy:.4f} ({accuracy*100:.2f}%)\")\n",
" print(f\" 正确预测: {(y_true_classes == y_pred_classes).sum():,}\")\n",
" print(f\" 错误预测: {(y_true_classes != y_pred_classes).sum():,}\")\n",
" \n",
" # 3. 分析预测置信度\n",
" pred_confidences = np.max(y_pred_probs, axis=1) # 预测的最大概率\n",
" true_confidences = np.max(y_true_probs, axis=1) # 真实的最大概率\n",
" \n",
" print(f\"\\n🔍 预测置信度分析:\")\n",
" print(f\" 预测置信度均值: {pred_confidences.mean():.4f}\")\n",
" print(f\" 预测置信度标准差: {pred_confidences.std():.4f}\")\n",
" print(f\" 预测置信度范围: [{pred_confidences.min():.4f}, {pred_confidences.max():.4f}]\")\n",
" print(f\" 真实置信度均值: {true_confidences.mean():.4f}\")\n",
" \n",
" # 4. 按置信度分组的准确率分析\n",
" confidence_bins = [0.0, 0.3, 0.5, 0.7, 0.9, 1.0]\n",
" print(f\"\\n📈 按预测置信度分组的准确率:\")\n",
" print(f\"{'置信度区间':>12} {'样本数':>8} {'准确率':>8} {'百分比':>8}\")\n",
" print(\"-\" * 40)\n",
" \n",
" for i in range(len(confidence_bins)-1):\n",
" low, high = confidence_bins[i], confidence_bins[i+1]\n",
" mask = (pred_confidences >= low) & (pred_confidences < high)\n",
" if i == len(confidence_bins)-2: # 最后一个区间包含等号\n",
" mask = (pred_confidences >= low) & (pred_confidences <= high)\n",
" \n",
" if mask.sum() > 0:\n",
" bin_accuracy = (y_true_classes[mask] == y_pred_classes[mask]).mean()\n",
" count = mask.sum()\n",
" percentage = count / len(y_true_classes) * 100\n",
" print(f\"[{low:.1f}, {high:.1f}{')'if i<len(confidence_bins)-2 else ']':>1} {count:>8} {bin_accuracy:>8.4f} {percentage:>7.1f}%\")\n",
" \n",
" # 5. 混淆矩阵分析Top-K音素\n",
" from collections import Counter\n",
" \n",
" # 找出最常见的音素\n",
" true_counter = Counter(y_true_classes)\n",
" pred_counter = Counter(y_pred_classes)\n",
" \n",
" most_common_true = true_counter.most_common(10)\n",
" most_common_pred = pred_counter.most_common(10)\n",
" \n",
" print(f\"\\n🏆 最常见的音素 (真实 vs 预测):\")\n",
" print(f\"{'真实音素':>12} {'次数':>6} {'预测音素':>12} {'次数':>6}\")\n",
" print(\"-\" * 42)\n",
" \n",
" for i in range(min(len(most_common_true), len(most_common_pred))):\n",
" true_id, true_count = most_common_true[i]\n",
" pred_id, pred_count = most_common_pred[i]\n",
" true_name = LOGIT_TO_PHONEME[true_id]\n",
" pred_name = LOGIT_TO_PHONEME[pred_id]\n",
" print(f\"{true_name:>12} {true_count:>6} {pred_name:>12} {pred_count:>6}\")\n",
" \n",
" # 6. 每个音素的分类性能\n",
" if show_detailed_metrics:\n",
" from sklearn.metrics import classification_report, confusion_matrix\n",
" \n",
" print(f\"\\n📋 详细分类报告 (前20个最常见音素):\")\n",
" \n",
" # 获取前20个最常见的音素\n",
" top_20_phonemes = [phoneme_id for phoneme_id, _ in most_common_true[:20]]\n",
" \n",
" # 创建掩码,只包含这些音素\n",
" mask_top20 = np.isin(y_true_classes, top_20_phonemes)\n",
" y_true_top20 = y_true_classes[mask_top20]\n",
" y_pred_top20 = y_pred_classes[mask_top20]\n",
" \n",
" # 生成分类报告\n",
" target_names = [LOGIT_TO_PHONEME[i] for i in top_20_phonemes]\n",
" \n",
" try:\n",
" report = classification_report(\n",
" y_true_top20, y_pred_top20, \n",
" labels=top_20_phonemes,\n",
" target_names=target_names,\n",
" output_dict=True,\n",
" zero_division=0\n",
" )\n",
" \n",
" # 打印格式化的报告\n",
" print(f\"{'音素':>8} {'精确率':>8} {'召回率':>8} {'F1分数':>8} {'支持数':>8}\")\n",
" print(\"-\" * 48)\n",
" \n",
" for phoneme_id in top_20_phonemes:\n",
" phoneme_name = LOGIT_TO_PHONEME[phoneme_id]\n",
" if phoneme_name in report:\n",
" metrics = report[phoneme_name]\n",
" print(f\"{phoneme_name:>8} {metrics['precision']:>8.4f} {metrics['recall']:>8.4f} \"\n",
" f\"{metrics['f1-score']:>8.4f} {int(metrics['support']):>8}\")\n",
" \n",
" # 总体指标\n",
" macro_avg = report['macro avg']\n",
" weighted_avg = report['weighted avg']\n",
" print(\"-\" * 48)\n",
" print(f\"{'宏平均':>8} {macro_avg['precision']:>8.4f} {macro_avg['recall']:>8.4f} \"\n",
" f\"{macro_avg['f1-score']:>8.4f}\")\n",
" print(f\"{'加权平均':>8} {weighted_avg['precision']:>8.4f} {weighted_avg['recall']:>8.4f} \"\n",
" f\"{weighted_avg['f1-score']:>8.4f}\")\n",
" \n",
" except Exception as e:\n",
" print(f\"分类报告生成失败: {e}\")\n",
" \n",
" # 7. Top-K准确率分析\n",
" print(f\"\\n🎯 Top-K 准确率分析:\")\n",
" for k in [1, 3, 5, 10]:\n",
" # 计算Top-K准确率\n",
" top_k_pred = np.argsort(y_pred_probs, axis=1)[:, -k:] # 取概率最高的K个\n",
" top_k_accuracy = np.mean([y_true_classes[i] in top_k_pred[i] for i in range(len(y_true_classes))])\n",
" print(f\" Top-{k} 准确率: {top_k_accuracy:.4f} ({top_k_accuracy*100:.2f}%)\")\n",
" \n",
" # 8. 错误分析 - 最常见的预测错误\n",
" print(f\"\\n❌ 最常见的预测错误:\")\n",
" error_mask = y_true_classes != y_pred_classes\n",
" error_pairs = list(zip(y_true_classes[error_mask], y_pred_classes[error_mask]))\n",
" error_counter = Counter(error_pairs)\n",
" \n",
" print(f\"{'真实音素':>12} {'预测音素':>12} {'错误次数':>8}\")\n",
" print(\"-\" * 36)\n",
" for (true_id, pred_id), count in error_counter.most_common(10):\n",
" true_name = LOGIT_TO_PHONEME[true_id]\n",
" pred_name = LOGIT_TO_PHONEME[pred_id]\n",
" print(f\"{true_name:>12} {pred_name:>12} {count:>8}\")\n",
" \n",
" # 返回结果字典\n",
" classification_results = {\n",
" 'accuracy': accuracy,\n",
" 'y_true_classes': y_true_classes,\n",
" 'y_pred_classes': y_pred_classes,\n",
" 'pred_confidences': pred_confidences,\n",
" 'true_confidences': true_confidences,\n",
" 'most_common_errors': error_counter.most_common(10)\n",
" }\n",
" \n",
" return classification_results\n",
"\n",
"def create_classification_visualizations(y_true_probs, y_pred_probs, classification_results):\n",
" \"\"\"\n",
" 为分类结果创建可视化图表\n",
" \"\"\"\n",
" print(f\"\\n📊 创建分类结果可视化...\")\n",
" \n",
" fig, axes = plt.subplots(2, 3, figsize=(18, 12))\n",
" fig.suptitle('随机森林回归转分类结果分析', fontsize=16, fontweight='bold')\n",
" \n",
" y_true_classes = classification_results['y_true_classes']\n",
" y_pred_classes = classification_results['y_pred_classes']\n",
" pred_confidences = classification_results['pred_confidences']\n",
" \n",
" # 1. 预测置信度分布\n",
" axes[0, 0].hist(pred_confidences, bins=50, alpha=0.7, color='skyblue', edgecolor='black')\n",
" axes[0, 0].axvline(pred_confidences.mean(), color='red', linestyle='--', \n",
" label=f'均值: {pred_confidences.mean():.3f}')\n",
" axes[0, 0].set_xlabel('预测置信度')\n",
" axes[0, 0].set_ylabel('样本数量')\n",
" axes[0, 0].set_title('预测置信度分布')\n",
" axes[0, 0].legend()\n",
" axes[0, 0].grid(True, alpha=0.3)\n",
" \n",
" # 2. 准确率 vs 置信度\n",
" confidence_bins = np.linspace(0, 1, 21)\n",
" bin_centers = (confidence_bins[:-1] + confidence_bins[1:]) / 2\n",
" bin_accuracies = []\n",
" bin_counts = []\n",
" \n",
" for i in range(len(confidence_bins)-1):\n",
" mask = (pred_confidences >= confidence_bins[i]) & (pred_confidences < confidence_bins[i+1])\n",
" if mask.sum() > 0:\n",
" accuracy = (y_true_classes[mask] == y_pred_classes[mask]).mean()\n",
" bin_accuracies.append(accuracy)\n",
" bin_counts.append(mask.sum())\n",
" else:\n",
" bin_accuracies.append(0)\n",
" bin_counts.append(0)\n",
" \n",
" # 只显示有数据的bins\n",
" valid_bins = np.array(bin_counts) > 0\n",
" axes[0, 1].plot(bin_centers[valid_bins], np.array(bin_accuracies)[valid_bins], \n",
" 'bo-', linewidth=2, markersize=6)\n",
" axes[0, 1].set_xlabel('预测置信度')\n",
" axes[0, 1].set_ylabel('准确率')\n",
" axes[0, 1].set_title('准确率 vs 预测置信度')\n",
" axes[0, 1].grid(True, alpha=0.3)\n",
" axes[0, 1].set_ylim(0, 1)\n",
" \n",
" # 3. 最常见音素的预测准确率\n",
" from collections import Counter\n",
" true_counter = Counter(y_true_classes)\n",
" most_common_phonemes = [phoneme_id for phoneme_id, _ in true_counter.most_common(15)]\n",
" \n",
" phoneme_accuracies = []\n",
" phoneme_names = []\n",
" for phoneme_id in most_common_phonemes:\n",
" mask = y_true_classes == phoneme_id\n",
" if mask.sum() > 0:\n",
" accuracy = (y_pred_classes[mask] == phoneme_id).mean()\n",
" phoneme_accuracies.append(accuracy)\n",
" phoneme_names.append(LOGIT_TO_PHONEME[phoneme_id])\n",
" \n",
" bars = axes[0, 2].bar(range(len(phoneme_names)), phoneme_accuracies, \n",
" color='lightgreen', alpha=0.7)\n",
" axes[0, 2].set_xlabel('音素')\n",
" axes[0, 2].set_ylabel('准确率')\n",
" axes[0, 2].set_title('Top 15 音素的分类准确率')\n",
" axes[0, 2].set_xticks(range(len(phoneme_names)))\n",
" axes[0, 2].set_xticklabels(phoneme_names, rotation=45, ha='right')\n",
" axes[0, 2].grid(True, alpha=0.3)\n",
" \n",
" # 添加数值标签\n",
" for bar, acc in zip(bars, phoneme_accuracies):\n",
" height = bar.get_height()\n",
" axes[0, 2].text(bar.get_x() + bar.get_width()/2., height + 0.01,\n",
" f'{acc:.3f}', ha='center', va='bottom', fontsize=8)\n",
" \n",
" # 4. 混淆矩阵前10个最常见音素\n",
" from sklearn.metrics import confusion_matrix\n",
" top_10_phonemes = most_common_phonemes[:10]\n",
" mask_top10 = np.isin(y_true_classes, top_10_phonemes) & np.isin(y_pred_classes, top_10_phonemes)\n",
" \n",
" if mask_top10.sum() > 0:\n",
" cm = confusion_matrix(y_true_classes[mask_top10], y_pred_classes[mask_top10], \n",
" labels=top_10_phonemes)\n",
" \n",
" im = axes[1, 0].imshow(cm, interpolation='nearest', cmap='Blues')\n",
" axes[1, 0].set_title('混淆矩阵 (Top 10 音素)')\n",
" \n",
" # 添加颜色条\n",
" cbar = plt.colorbar(im, ax=axes[1, 0], shrink=0.8)\n",
" cbar.set_label('预测次数')\n",
" \n",
" # 设置标签\n",
" tick_marks = np.arange(len(top_10_phonemes))\n",
" top_10_names = [LOGIT_TO_PHONEME[i] for i in top_10_phonemes]\n",
" axes[1, 0].set_xticks(tick_marks)\n",
" axes[1, 0].set_yticks(tick_marks)\n",
" axes[1, 0].set_xticklabels(top_10_names, rotation=45, ha='right')\n",
" axes[1, 0].set_yticklabels(top_10_names)\n",
" axes[1, 0].set_xlabel('预测音素')\n",
" axes[1, 0].set_ylabel('真实音素')\n",
" \n",
" # 5. Top-K准确率\n",
" k_values = [1, 2, 3, 4, 5, 10, 15, 20]\n",
" top_k_accuracies = []\n",
" \n",
" for k in k_values:\n",
" top_k_pred = np.argsort(y_pred_probs, axis=1)[:, -k:]\n",
" top_k_accuracy = np.mean([y_true_classes[i] in top_k_pred[i] for i in range(len(y_true_classes))])\n",
" top_k_accuracies.append(top_k_accuracy)\n",
" \n",
" axes[1, 1].plot(k_values, top_k_accuracies, 'ro-', linewidth=2, markersize=8)\n",
" axes[1, 1].set_xlabel('K 值')\n",
" axes[1, 1].set_ylabel('Top-K 准确率')\n",
" axes[1, 1].set_title('Top-K 准确率曲线')\n",
" axes[1, 1].grid(True, alpha=0.3)\n",
" axes[1, 1].set_ylim(0, 1)\n",
" \n",
" # 添加数值标签\n",
" for k, acc in zip(k_values, top_k_accuracies):\n",
" axes[1, 1].annotate(f'{acc:.3f}', (k, acc), textcoords=\"offset points\", \n",
" xytext=(0,10), ha='center')\n",
" \n",
" # 6. 错误分析 - 最常见错误的热力图\n",
" error_pairs = classification_results['most_common_errors'][:25] # 前25个最常见错误\n",
" if error_pairs:\n",
" # 创建错误矩阵\n",
" unique_phonemes = list(set([pair[0][0] for pair in error_pairs] + [pair[0][1] for pair in error_pairs]))\n",
" error_matrix = np.zeros((len(unique_phonemes), len(unique_phonemes)))\n",
" \n",
" phoneme_to_idx = {phoneme: i for i, phoneme in enumerate(unique_phonemes)}\n",
" \n",
" for (true_id, pred_id), count in error_pairs:\n",
" if true_id in phoneme_to_idx and pred_id in phoneme_to_idx:\n",
" true_idx = phoneme_to_idx[true_id]\n",
" pred_idx = phoneme_to_idx[pred_id]\n",
" error_matrix[true_idx, pred_idx] = count\n",
" \n",
" im = axes[1, 2].imshow(error_matrix, cmap='Reds', interpolation='nearest')\n",
" axes[1, 2].set_title('最常见错误分布')\n",
" \n",
" # 设置标签\n",
" phoneme_names = [LOGIT_TO_PHONEME[p] for p in unique_phonemes]\n",
" axes[1, 2].set_xticks(range(len(phoneme_names)))\n",
" axes[1, 2].set_yticks(range(len(phoneme_names)))\n",
" axes[1, 2].set_xticklabels(phoneme_names, rotation=45, ha='right')\n",
" axes[1, 2].set_yticklabels(phoneme_names)\n",
" axes[1, 2].set_xlabel('预测音素')\n",
" axes[1, 2].set_ylabel('真实音素')\n",
" \n",
" # 添加颜色条\n",
" cbar = plt.colorbar(im, ax=axes[1, 2], shrink=0.8)\n",
" cbar.set_label('错误次数')\n",
" \n",
" plt.tight_layout()\n",
" plt.savefig('./processed_datasets/classification_analysis.png', dpi=300, bbox_inches='tight')\n",
" print(\"📁 分类分析图表已保存至: ./processed_datasets/classification_analysis.png\")\n",
" plt.show()\n",
"\n",
"print(\"✅ 回归转分类分析功能已创建!\")\n",
"print(\"🎯 主要功能:\")\n",
"print(\"• 将40维概率回归结果转换为分类预测\")\n",
"print(\"• 计算分类准确率和置信度分析\")\n",
"print(\"• 提供Top-K准确率评估\")\n",
"print(\"• 生成详细的混淆矩阵和错误分析\")\n",
"print(\"• 创建全面的可视化图表\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 🎯 完整的回归转分类评估流程\n",
"def complete_regression_classification_evaluation(rf_model, X_test, y_test, dataset_name=\"测试集\"):\n",
" \"\"\"\n",
" 完整的回归模型转分类结果评估流程\n",
" \"\"\"\n",
" print(f\"\\n🎯 {dataset_name}完整评估: 回归 → 分类\")\n",
" print(\"=\"*70)\n",
" \n",
" # 1. 获取回归预测结果\n",
" print(\"📊 第1步: 获取回归预测...\")\n",
" y_pred_probs = rf_model.predict(X_test)\n",
" \n",
" # 确保概率值在合理范围内\n",
" y_pred_probs = np.clip(y_pred_probs, 0, 1)\n",
" \n",
" # 2. 回归性能评估\n",
" print(\"\\n📈 第2步: 回归性能评估...\")\n",
" mse = mean_squared_error(y_test, y_pred_probs) \n",
" mae = mean_absolute_error(y_test, y_pred_probs)\n",
" r2 = r2_score(y_test, y_pred_probs)\n",
" \n",
" print(f\" 回归 MSE: {mse:.6f}\")\n",
" print(f\" 回归 MAE: {mae:.6f}\")\n",
" print(f\" 回归 R²: {r2:.4f}\")\n",
" \n",
" # 3. 概率归一化softmax\n",
" print(\"\\n🔄 第3步: 概率归一化...\")\n",
" def softmax(x, axis=-1):\n",
" exp_x = np.exp(x - np.max(x, axis=axis, keepdims=True))\n",
" return exp_x / np.sum(exp_x, axis=axis, keepdims=True)\n",
" \n",
" # 对预测结果应用softmax使其成为真正的概率分布\n",
" y_pred_probs_normalized = softmax(y_pred_probs)\n",
" y_test_normalized = softmax(y_test) # 也对真实标签归一化\n",
" \n",
" print(f\" 预测概率归一化前: 每行和均值 = {np.mean(np.sum(y_pred_probs, axis=1)):.4f}\")\n",
" print(f\" 预测概率归一化后: 每行和均值 = {np.mean(np.sum(y_pred_probs_normalized, axis=1)):.4f}\")\n",
" \n",
" # 4. 分类结果分析\n",
" print(\"\\n🎯 第4步: 分类结果分析...\")\n",
" classification_results = regression_to_classification_analysis(\n",
" y_test_normalized, y_pred_probs_normalized, show_detailed_metrics=True\n",
" )\n",
" \n",
" # 5. 创建可视化\n",
" print(\"\\n📊 第5步: 创建可视化图表...\")\n",
" create_classification_visualizations(y_test_normalized, y_pred_probs_normalized, classification_results)\n",
" \n",
" # 6. 保存结果\n",
" print(\"\\n💾 第6步: 保存分析结果...\")\n",
" \n",
" # 保存分类结果\n",
" results_df = pd.DataFrame({\n",
" 'true_class': classification_results['y_true_classes'],\n",
" 'pred_class': classification_results['y_pred_classes'],\n",
" 'true_phoneme': [LOGIT_TO_PHONEME[i] for i in classification_results['y_true_classes']],\n",
" 'pred_phoneme': [LOGIT_TO_PHONEME[i] for i in classification_results['y_pred_classes']],\n",
" 'pred_confidence': classification_results['pred_confidences'],\n",
" 'is_correct': classification_results['y_true_classes'] == classification_results['y_pred_classes']\n",
" })\n",
" \n",
" results_df.to_csv('./processed_datasets/classification_results.csv', index=False)\n",
" \n",
" # 保存详细的概率预测\n",
" prob_results_df = pd.DataFrame(y_pred_probs_normalized, \n",
" columns=[f'prob_{LOGIT_TO_PHONEME[i]}' for i in range(40)])\n",
" prob_results_df['true_class'] = classification_results['y_true_classes']\n",
" prob_results_df['pred_class'] = classification_results['y_pred_classes']\n",
" \n",
" prob_results_df.to_csv('./processed_datasets/probability_predictions.csv', index=False)\n",
" \n",
" print(\"📁 结果已保存:\")\n",
" print(\" • ./processed_datasets/classification_results.csv (分类结果)\")\n",
" print(\" • ./processed_datasets/probability_predictions.csv (概率预测)\")\n",
" print(\" • ./processed_datasets/classification_analysis.png (可视化图表)\")\n",
" \n",
" # 7. 总结报告\n",
" print(f\"\\n📋 {dataset_name}评估总结:\")\n",
" print(\"=\"*50)\n",
" print(f\"🔸 回归性能:\")\n",
" print(f\" MSE: {mse:.6f}\")\n",
" print(f\" R²: {r2:.4f}\")\n",
" print(f\"🔸 分类性能:\")\n",
" print(f\" 准确率: {classification_results['accuracy']:.4f} ({classification_results['accuracy']*100:.2f}%)\")\n",
" print(f\" 平均置信度: {classification_results['pred_confidences'].mean():.4f}\")\n",
" \n",
" # 计算Top-K准确率\n",
" for k in [1, 3, 5]:\n",
" top_k_pred = np.argsort(y_pred_probs_normalized, axis=1)[:, -k:]\n",
" top_k_accuracy = np.mean([classification_results['y_true_classes'][i] in top_k_pred[i] \n",
" for i in range(len(classification_results['y_true_classes']))])\n",
" print(f\" Top-{k} 准确率: {top_k_accuracy:.4f} ({top_k_accuracy*100:.2f}%)\")\n",
" \n",
" return {\n",
" 'regression_metrics': {'mse': mse, 'mae': mae, 'r2': r2},\n",
" 'classification_results': classification_results,\n",
" 'normalized_predictions': y_pred_probs_normalized,\n",
" 'normalized_true': y_test_normalized\n",
" }\n",
"\n",
"# 如果模型已训练且有验证数据,执行完整评估\n",
"if 'rf_regressor' in locals() and hasattr(rf_regressor, 'is_fitted') and rf_regressor.is_fitted:\n",
" if 'X_val' in locals() and X_val is not None and 'y_val' in locals() and y_val is not None:\n",
" print(\"🚀 开始完整的回归转分类评估...\")\n",
" \n",
" # 执行完整评估\n",
" evaluation_results = complete_regression_classification_evaluation(\n",
" rf_regressor, X_val, y_val, \"验证集\"\n",
" )\n",
" \n",
" print(f\"\\n🎉 评估完成!\")\n",
" print(f\"✅ 随机森林回归模型成功转换为分类结果\")\n",
" print(f\"📊 生成了详细的性能分析和可视化\")\n",
" print(f\"💾 所有结果已保存到文件\")\n",
" \n",
" # 如果有测试数据,也进行评估\n",
" if 'X_test' in locals() and X_test is not None and 'y_test' in locals() and y_test is not None:\n",
" print(f\"\\n🔮 开始测试集评估...\")\n",
" test_evaluation_results = complete_regression_classification_evaluation(\n",
" rf_regressor, X_test, y_test, \"测试集\"\n",
" )\n",
" else:\n",
" print(\"⚠️ 没有可用的验证数据进行评估\")\n",
"else:\n",
" print(\"⚠️ 随机森林模型尚未训练完成\")\n",
" print(\"💡 请先运行前面的训练代码\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kaggle": {
"accelerator": "tpu1vmV38",
"dataSources": [
{
"databundleVersionId": 13056355,
"sourceId": 106809,
"sourceType": "competition"
}
],
"dockerImageVersionId": 31091,
"isGpuEnabled": false,
"isInternetEnabled": true,
"language": "python",
"sourceType": "notebook"
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}