{"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":159333316,"sourceType":"kernelVersion"},{"sourceId":159396114,"sourceType":"kernelVersion"},{"sourceId":160106673,"sourceType":"kernelVersion"},{"sourceId":160346962,"sourceType":"kernelVersion"}],"dockerImageVersionId":30635,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"### Created by yunsuxiaozi","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"markdown","source":"### This is a summary of my current work.\n\n\n### In these three notebooks, I processed spectrograms and trained 6 models with resnet34d, ultimately achieving PL0.45.\n\n<a href=\"https://www.kaggle.com/code/yunsuxiaozi/hms-baseline-resnet34d-512-512-training\">HMS baseline resnet34d 512\\*512 training</a>\n\n<a href=\"https://www.kaggle.com/code/yunsuxiaozi/hms-baseline-resnet34d-512-512-training-5-folds\">HMS baseline_resnet34d(512\\*512 Training 5 folds)</a>\n\n<a href=\"https://www.kaggle.com/code/yunsuxiaozi/hms-baseline-resnet34d-512-512-inference-6-models\">HMS baseline_resnet34d(512\\*512 inference 6 models)</a>\n\n\n###  In these three notebooks, I learn to transform eegs to spectrograms and trained 5 models with resnet34d, ultimately achieving PL0.56.\n\n<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>\n\n\n<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>\n\n<a href=\"https://www.kaggle.com/code/yunsuxiaozi/hms-eegs-resnet34d-512-512-inference-5-folds\">HMS eegs resnet34d(512\\*512 inference 5 folds)</a>\n\n\n<a href=\"https://www.kaggle.com/code/yunsuxiaozi/hms-eeg-efficientnet-b0-512-512-training-5-folds\">HMS eeg efficientnet b0(512*512 training 5 folds)</a>\n\n### In this notebook, I will merge them with weights of 0.6 and 0.4.\n","metadata":{}},{"cell_type":"code","source":"#https://www.kaggle.com/code/ttahara/hms-hbac-resnet34d-baseline-training\n#https://www.kaggle.com/code/ttahara/hms-hbac-resnet34d-baseline-inference\n#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()方法是用于设置警告过滤器的方法，它可以控制警告信息的输出方式和级别\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Config:\n    seed=2024\n    image_transform=transforms.Resize((512, 512))\n    num_folds=5\ndef 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":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"models=[]\nfor i in range(Config.num_folds):\n    model = torch.load(f'/kaggle/input/hms-baseline-resnet34d-512-512-training-5-folds/HMS_resnet_fold{i}.pth')\n    models.append(model)\nmodel = torch.load(\"/kaggle/input/hms-baseline-resnet34d-512-512-training/HMS_resnet.pth\")\nmodels.append(model)\nprint(f\"len(models):{len(models)}\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df=pd.read_csv(\"/kaggle/input/hms-harmful-brain-activity-classification/test.csv\")\nsubmission=pd.read_csv(\"/kaggle/input/hms-harmful-brain-activity-classification/sample_submission.csv\")\nsubmission=submission.merge(test_df,on='eeg_id',how='left')\nsubmission['path']=submission['spectrogram_id'].apply(lambda x: \"/kaggle/input/hms-harmful-brain-activity-classification/test_spectrograms/\"+str(x)+\".parquet\" )\nsubmission.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"paths=submission['path'].values\ntest_preds=[]\nfor path in paths:\n    eps=1e-6\n    data=pd.read_parquet(path)\n    #这里最小值是0,故用-1填充.第一列是时间列,故去掉 ,行是不同列,列是时间\n    data = data.fillna(-1).values[:,1:].T\n    #选取一段时间的数据进行训练\n    data=data[:,0:300]#(400,300)\n    data=np.clip(data,np.exp(-6),np.exp(10))#最大值为89209464.0\n    data= np.log(data)#对数变换\n    #对数据进行归一化\n    data_mean=data.mean(axis=(0,1))\n    data_std=data.std(axis=(0,1))\n    data=(data-data_mean)/(data_std+eps)\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_preds1=np.array(test_preds)\ntest_preds1","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"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)\n    model=torch.load(f\"/kaggle/input/hms-eeg-efficientnet-b0-512-512-training-5-folds/HMS_efficientnet_b0_fold{i}.pth\")\n    models.append(model)\nprint(f\"len(models):{len(models)}\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"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":{"trusted":true},"execution_count":null,"outputs":[]},{"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_preds2=np.array(test_preds)\ntest_preds2","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_preds=0.6*test_preds1+0.4*test_preds2\nsubmission=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":{"trusted":true},"execution_count":null,"outputs":[]}]}