{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":59093,"databundleVersionId":7469972,"sourceType":"competition"},{"sourceId":160106673,"sourceType":"kernelVersion"}],"dockerImageVersionId":30635,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"#### In the previous notebook<a href=\"https://www.kaggle.com/code/yunsuxiaozi/hms-learn-to-transform-eeg-to-spectrogram-256-256\">HMS Learn to transform eeg to spectrogram(256*256)</a>,I learned how to use eeg data to generate spectrograms. And in this notebook<a href=\"https://www.kaggle.com/code/yunsuxiaozi/hms-eegs-resnet34d-512-512-training-5-folds\">HMS eegs resnet34d(512*512 training 5 folds)</a>, I  use these data to train the model.","metadata":{}},{"cell_type":"markdown","source":"### Import necessary libraries","metadata":{}},{"cell_type":"code","source":"#necessary\nimport pandas as pd#导入csv文件的库\nimport numpy as np#进行矩阵运算的库\nimport torch #一个深度学习的库Pytorch\nimport torch.nn as nn#neural network,神经网络\nimport torch.nn.functional as F#神经网络函数库\nimport torchvision.transforms as transforms#Pytorch下面的图像处理库,用于对图像进行数据增强\n#设置随机种子\nimport random\nimport warnings#避免一些可以忽略的报错\nwarnings.filterwarnings('ignore')#filterwarnings()方法是用于设置警告过滤器的方法，它可以控制警告信息的输出方式和级别。","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-01-23T13:25:37.529929Z","iopub.execute_input":"2024-01-23T13:25:37.530323Z","iopub.status.idle":"2024-01-23T13:25:40.625536Z","shell.execute_reply.started":"2024-01-23T13:25:37.530292Z","shell.execute_reply":"2024-01-23T13:25:40.624475Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Config","metadata":{}},{"cell_type":"code","source":"class Config:\n    seed=2024\n    image_transform=transforms.Resize((512, 512))\n    num_folds=5","metadata":{"execution":{"iopub.status.busy":"2024-01-23T13:25:40.627771Z","iopub.execute_input":"2024-01-23T13:25:40.628400Z","iopub.status.idle":"2024-01-23T13:25:40.633294Z","shell.execute_reply.started":"2024-01-23T13:25:40.628361Z","shell.execute_reply":"2024-01-23T13:25:40.632352Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Set seed","metadata":{}},{"cell_type":"code","source":"def seed_everything(seed):\n    torch.backends.cudnn.deterministic = True#将cuda加速的随机数生成器设为确定性模式\n    torch.backends.cudnn.benchmark = True#关闭CuDNN框架的自动寻找最优卷积算法的功能，以避免不同的算法对结果产生影响\n    torch.manual_seed(seed)#pytorch的随机种子\n    np.random.seed(seed)#numpy的随机种子\n    random.seed(seed)#python内置的随机种子\nseed_everything(Config.seed)","metadata":{"execution":{"iopub.status.busy":"2024-01-23T13:25:40.634476Z","iopub.execute_input":"2024-01-23T13:25:40.634730Z","iopub.status.idle":"2024-01-23T13:25:40.650794Z","shell.execute_reply.started":"2024-01-23T13:25:40.634706Z","shell.execute_reply":"2024-01-23T13:25:40.649732Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### trained_models","metadata":{}},{"cell_type":"code","source":"models=[]\nfor i in range(Config.num_folds):\n    model = torch.load(f\"/kaggle/input/hms-eegs-resnet34d-512-512-training-5-folds/HMS_resnet34d_fold{i}.pth\")\n    models.append(model)\nmodels.append(model)","metadata":{"execution":{"iopub.status.busy":"2024-01-23T13:25:40.653032Z","iopub.execute_input":"2024-01-23T13:25:40.653713Z","iopub.status.idle":"2024-01-23T13:25:46.748537Z","shell.execute_reply.started":"2024-01-23T13:25:40.653680Z","shell.execute_reply":"2024-01-23T13:25:46.747340Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Function to transform eegs to spectrograms","metadata":{}},{"cell_type":"code","source":"import librosa#音频处理和分析的库\n\n#脑电图电极的位置或区域. 'Left Lower','left upper','Right Upper','RightLower'(顺时针) \n#NAMES = ['LL','LP','RP','RR']\n#eeg信号采集的相对位置\nFEATS = [['Fp1','F7','T3','T5','O1'],\n         ['Fp1','F3','C3','P3','O1'],\n         ['Fp2','F8','T4','T6','O2'],\n         ['Fp2','F4','C4','P4','O2']]\n\n#将eeg文件转成spectrogram文件\ndef spectrogram_from_eeg(parquet_path):#parquet_path是eeg文件的路径\n    #根据路径,加载eeg的中间50秒\n    eeg = pd.read_parquet(parquet_path)\n    middle = len(eeg)//2-5000\n    eeg = eeg.iloc[middle:middle+10000]\n    \n    #初始化图片大小\n    img = np.zeros((256,256,4),dtype='float32')\n    \n    for k in range(4):\n        COLS = FEATS[k]#取出FEATS第K行的特征\n        \n        for kk in range(4):\n            #计算电势差(第kk个位置-第KK+1个位置) \n            x = eeg[COLS[kk]].values - eeg[COLS[kk+1]].values\n            \n            #对缺失值填充为均值\n            m = np.nanmean(x)#计算非nan位置数值的平均值\n            if np.isnan(x).mean()<1:#有不是缺失值的数据\n                x = np.nan_to_num(x,nan=m)#将数组x中为nan值替换为均值m\n            else: #np.isnan(x).mean()==1,即全是缺失值\n                x[:] = 0#填充为0\n\n            #计算音频信号的梅尔频谱特征 (n_mels,len(x)//hop_length+1)\n            #y：音频信号的波形数据,sr：音频信号的采样率.\n            # hop_length：帧移（每一帧之间的步长）的长度，通过将原始音频分割成多个短时帧来进行频谱计算。\n            # n_fft：FFT 窗口大小，表示每个帧的长度.\n            # n_mels：梅尔滤波器的数量，决定了梅尔频谱的分辨率.\n            # fmin：梅尔滤波器的最低频率,fmax：梅尔滤波器的最高频率.\n            # win_length：窗口函数的长度.\n            mel_spec = librosa.feature.melspectrogram(y=x, sr=200, hop_length=len(x)//256,\n                  n_fft=1024, n_mels=256,fmin=0, fmax=20, win_length=128)\n\n            \"\"\"\n            对每个元素取以10为底的对数，得到对数功率谱矩阵.\n            根据参考功率ref对对数功率谱矩阵进行平移，使得最大值等于梅尔频谱矩阵的最大值.\n            截断超过width的数据,避免出现噪声或不稳定性导致的误差.取值范围为(- infty,0)\n            \"\"\"\n            #宽度调整\n            width = (mel_spec.shape[1]//32)*32\n            mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max).astype(np.float32)[:,:width]\n\n            #类似归一化的操作\n            mel_spec_db = (mel_spec_db+40)/40 \n            img[:,:,k] += mel_spec_db\n                \n        #4个时刻的差值,故取平均.\n        img[:,:,k] /= 4.0\n    #变成(256,256)\n    img=np.mean(img,axis=2)\n    return img","metadata":{"execution":{"iopub.status.busy":"2024-01-23T13:25:46.749856Z","iopub.execute_input":"2024-01-23T13:25:46.750230Z","iopub.status.idle":"2024-01-23T13:25:46.768029Z","shell.execute_reply.started":"2024-01-23T13:25:46.750198Z","shell.execute_reply":"2024-01-23T13:25:46.766930Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Predict and Submission","metadata":{}},{"cell_type":"code","source":"submission=pd.read_csv(\"/kaggle/input/hms-harmful-brain-activity-classification/sample_submission.csv\")\n#获取训练数据的img\neeg_ids = submission['eeg_id'].values\ntest_preds=[]\nfor eeg_id in eeg_ids:\n    #调用函数获取img\n    data = spectrogram_from_eeg(f'/kaggle/input/hms-harmful-brain-activity-classification/test_eegs/{eeg_id}.parquet')\n    data_tensor = torch.unsqueeze(torch.Tensor(data), dim=0)\n    data=Config.image_transform(data_tensor)\n    test_pred=[]\n    for model in models:\n        model.eval()\n        with torch.no_grad():\n            pred=F.softmax(model(data.unsqueeze(0)))[0]\n            pred=pred.detach().cpu().numpy()\n        test_pred.append(pred)\n    test_pred=np.array(test_pred).mean(axis=0)\n    test_preds.append(test_pred)\ntest_preds=np.array(test_preds)\ntest_preds","metadata":{"execution":{"iopub.status.busy":"2024-01-23T13:25:46.769321Z","iopub.execute_input":"2024-01-23T13:25:46.769573Z","iopub.status.idle":"2024-01-23T13:25:59.131692Z","shell.execute_reply.started":"2024-01-23T13:25:46.769551Z","shell.execute_reply":"2024-01-23T13:25:59.130190Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission=pd.read_csv(\"/kaggle/input/hms-harmful-brain-activity-classification/sample_submission.csv\")\nlabels=['seizure','lpd','gpd','lrda','grda','other']\nfor i in range(len(labels)):\n    submission[f'{labels[i]}_vote']=test_preds[:,i]\nsubmission.to_csv(\"submission.csv\",index=None)\nsubmission.head()","metadata":{"execution":{"iopub.status.busy":"2024-01-23T13:25:59.134156Z","iopub.execute_input":"2024-01-23T13:25:59.134898Z","iopub.status.idle":"2024-01-23T13:25:59.177023Z","shell.execute_reply.started":"2024-01-23T13:25:59.134855Z","shell.execute_reply":"2024-01-23T13:25:59.176141Z"},"trusted":true},"execution_count":null,"outputs":[]}]}