{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":59093,"databundleVersionId":7469972,"sourceType":"competition"},{"sourceId":7392733,"sourceType":"datasetVersion","datasetId":4297749},{"sourceId":7465251,"sourceType":"datasetVersion","datasetId":4317718},{"sourceId":7923839,"sourceType":"datasetVersion","datasetId":4656770}],"dockerImageVersionId":30673,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"<div style=\"background-color: #e0f8e6; padding: 20px; border-radius: 50px; border: 5px solid #ffa76e;\">\n    \n# Import libraries","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport torch\nimport os\nimport pytorch_lightning as pl\nfrom torch.utils.data import Dataset, DataLoader\nfrom sklearn import model_selection\nimport torchvision.transforms as transforms\nimport torchvision.io \nimport librosa\nfrom PIL import Image\nimport albumentations as alb\nimport torch.multiprocessing as mp\nimport warnings\nwarnings.filterwarnings('ignore')\n","metadata":{"execution":{"iopub.status.busy":"2024-03-24T06:38:30.697749Z","iopub.execute_input":"2024-03-24T06:38:30.698580Z","iopub.status.idle":"2024-03-24T06:38:30.705773Z","shell.execute_reply.started":"2024-03-24T06:38:30.698546Z","shell.execute_reply":"2024-03-24T06:38:30.704712Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div style=\"background-color: #e0f8e6; padding: 20px; border-radius: 50px; border: 5px solid #ffa76e;\">\n    \n# Config Class Constructor\n    \n<strong>Do play with these parameters to tune your model, make sure to track the progress<strong>","metadata":{}},{"cell_type":"code","source":"class Config:\n    def __init__(self):\n        self.num_classes = 6\n        self.batch_size = 32\n        self.PRECISION = 16\n        self.num_channels = 8 #8#1\n        self.data_root = \"/kaggle/input/hms-harmful-brain-activity-classification/\"\n        self.raw_eeg_path = \"/kaggle/input/brain-eegs/eegs.npy\"\n        self.cols_interest = ['Fp1', 'C3', 'F7', 'T5', 'Fz', 'Cz', 'Pz', 'Fp2', 'F4', 'C4', 'P4', 'F8', 'T4', 'T6', 'O2', 'EKG']\n        self.processed_train = None\n        self.output_dir = '/kaggle/working/eegnet_submission'\n        self.pretrained = None\nConfig = Config()\n     ","metadata":{"execution":{"iopub.status.busy":"2024-03-24T06:38:30.707798Z","iopub.execute_input":"2024-03-24T06:38:30.708166Z","iopub.status.idle":"2024-03-24T06:38:30.717449Z","shell.execute_reply.started":"2024-03-24T06:38:30.708139Z","shell.execute_reply":"2024-03-24T06:38:30.716289Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#df = pd.read_csv(f'{Config.data_root}train.csv')\ndf_test = pd.read_csv(f'{Config.data_root}test.csv')\ndf_test.shape","metadata":{"execution":{"iopub.status.busy":"2024-03-24T06:38:30.718616Z","iopub.execute_input":"2024-03-24T06:38:30.718926Z","iopub.status.idle":"2024-03-24T06:38:30.734194Z","shell.execute_reply.started":"2024-03-24T06:38:30.718899Z","shell.execute_reply":"2024-03-24T06:38:30.733307Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div style=\"background-color: #e0f8e6; padding: 20px; border-radius: 50px; border: 5px solid #ffa76e;\">\n    \n# Classes distributions","metadata":{}},{"cell_type":"code","source":"# plt.figure(figsize =(15,5))\n# categories = df_test['expert_consensus'].value_counts().index\n# counts = df_test['expert_consensus'].value_counts()\n# plt.bar(categories, counts)\n# plt.xlabel('Categories')\n# plt.ylabel('Count')\n# plt.title('Bar Plot of expert_consensus Value Counts')\n# plt.show()","metadata":{"execution":{"iopub.status.busy":"2024-03-24T06:38:30.735378Z","iopub.execute_input":"2024-03-24T06:38:30.735713Z","iopub.status.idle":"2024-03-24T06:38:30.740661Z","shell.execute_reply.started":"2024-03-24T06:38:30.735687Z","shell.execute_reply":"2024-03-24T06:38:30.739642Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div style=\"background-color: #e0f8e6; padding: 20px; border-radius: 50px; border: 5px solid #ffa76e;\">\n    \n# Data Preprocessing","metadata":{}},{"cell_type":"code","source":"class DataProcessor:\n    def __init__(self, df):\n        self.df = df\n        self.EEG_IDS = self.df['eeg_id'].unique()\n        \n    def process_data(self):\n        # 假设每一个 EEG_ID 对应一条测试记录\n        # 此处我们不做任何正规化或目标列处理\n        processed_df = self.df.loc[self.df.eeg_id.isin(self.EEG_IDS)]\n        print('Processed data shape:', processed_df.shape)\n        return processed_df\n\n# 假设 df_test 是你的测试数据集\ndata_processor = DataProcessor(df_test)\ntest_processed = data_processor.process_data()\n\ndata_processor = DataProcessor(df_test)\ntest= data_processor\n","metadata":{"execution":{"iopub.status.busy":"2024-03-24T06:38:30.743501Z","iopub.execute_input":"2024-03-24T06:38:30.743959Z","iopub.status.idle":"2024-03-24T06:38:30.755796Z","shell.execute_reply.started":"2024-03-24T06:38:30.743930Z","shell.execute_reply":"2024-03-24T06:38:30.754807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\nCREATE_EEGS = True\ndf = pd.read_parquet(f'{Config.data_root}test_eegs/3911565283.parquet')\nFEATS = df.columns\nprint(f'There are {len(FEATS)} raw eeg features')\nprint( list(FEATS) )\n\nif Config.raw_eeg_path is not None:\n    raw_eegs = np.load(Config.raw_eeg_path, allow_pickle=True).item()","metadata":{"execution":{"iopub.status.busy":"2024-03-24T06:38:30.757073Z","iopub.execute_input":"2024-03-24T06:38:30.757378Z","iopub.status.idle":"2024-03-24T06:39:54.407832Z","shell.execute_reply.started":"2024-03-24T06:38:30.757341Z","shell.execute_reply":"2024-03-24T06:39:54.406823Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div style=\"background-color: #e0f8e6; padding: 20px; border-radius: 50px; border: 5px solid #ffa76e;\">\n    \n# Model Builder","metadata":{}},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\n\nclass EEGModel(pl.LightningModule):\n    def __init__(self, num_classes = Config.num_classes, pretrained = Config.pretrained):\n        super().__init__()\n        self.num_classes = num_classes\n        self.backbone = EEGNet(in_channels=Config.num_channels, classes_num=Config.num_classes)\n        self.loss_function = KLDivLossWithLogits()\n        self.validation_step_outputs = []\n        self.lin = nn.Softmax(dim=1)\n    def forward(self,images):\n        logits = self.backbone(images)\n        return logits\n        \n\nclass EEGNet(nn.Module):\n    def __init__(self, in_channels, classes_num):\n        super(EEGNet, self).__init__()\n        self.drop_out = 0.25\n        \n        self.block_1 = nn.Sequential(\n            nn.ZeroPad2d((24, 24, 0, 0)),\n            nn.Conv2d(\n                in_channels=Config.num_channels,  # 使用传入的in_channels参数\n                out_channels=8, \n                kernel_size=(1,64),\n                bias=False\n            ),\n            nn.BatchNorm2d(8)\n        )\n        \n        self.block_2 = nn.Sequential(\n            nn.Conv2d(\n                in_channels=8, \n                out_channels=16, \n                kernel_size=(1,64), \n                groups=8,\n                bias=False\n            ),\n            nn.BatchNorm2d(16), \n            nn.ELU(),\n            nn.AvgPool2d((1, 4)), \n            nn.Dropout(self.drop_out)\n        )\n        \n        self.block_3 = nn.Sequential(\n            nn.ZeroPad2d((7, 8, 0, 0)),\n            nn.Conv2d(\n               in_channels=16, \n               out_channels=16, \n               kernel_size=(1, 16), \n               groups=16,\n               bias=False\n            ),\n            nn.Conv2d(\n                in_channels=16, \n                out_channels=16, \n                kernel_size=(1, 1), \n                bias=False\n            ),\n            nn.BatchNorm2d(16), \n            nn.ELU(),\n            nn.AvgPool2d((1, 8)), \n            nn.Dropout(self.drop_out)\n        )\n        \n        # 假设 block_3 的输出是 (batch_size, 16, 1, T//32)，需要动态计算 T//32\n        # 这里用假设的数值 155 替代 T//32，您需要根据实际情况确定这个值\n        self.flattened_size = 16 * 1 * 155\n        \n        self.out = nn.Linear(4960, classes_num)\n    \n    def forward(self, x):\n        x = self.block_1(x)\n        #print(x.shape)\n        x = self.block_2(x)\n       # print(x.shape)\n        x = self.block_3(x)\n        #print(x.shape)\n        # 打印 x 的形状以验证 flatten 之前的尺寸\n        #print(x.shape)\n        \n        x = x.view(x.size(0), -1)\n        \n        # 确认扁平化后的特征数量\n        print(x.shape)\n        \n        x = self.out(x)\n        \n        return x\n","metadata":{"execution":{"iopub.status.busy":"2024-03-24T06:39:54.409681Z","iopub.execute_input":"2024-03-24T06:39:54.409996Z","iopub.status.idle":"2024-03-24T06:39:54.428952Z","shell.execute_reply.started":"2024-03-24T06:39:54.409969Z","shell.execute_reply":"2024-03-24T06:39:54.427849Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import gc\niot = torch.randn(6, Config.num_channels, 1,10000)#.cuda()\nmodel = EEGNet(in_channels=Config.num_channels,classes_num =6)#.cuda()\noutput = model(iot)\nprint(output.shape)\n\ndel iot, model\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-03-24T06:39:54.430381Z","iopub.execute_input":"2024-03-24T06:39:54.430767Z","iopub.status.idle":"2024-03-24T06:39:54.812708Z","shell.execute_reply.started":"2024-03-24T06:39:54.430734Z","shell.execute_reply":"2024-03-24T06:39:54.811648Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div style=\"background-color: #e0f8e6; padding: 20px; border-radius: 50px; border: 5px solid #ffa76e;\">\n    \n# Signal Processing \n    \n**ML models often require significant computational resources, and reducing the precision of the input data through quantization can lead to more efficient model training and inference. By representing numerical values with fewer bits, the memory requirements are reduced, allowing for faster processing**\n* **You can play with other filters and quantizers as well** ","metadata":{}},{"cell_type":"code","source":"from scipy.signal import cheby1, butter, lfilter\n\ndef quantize_data_linear(data, classes):\n    min_val, max_val = np.min(data), np.max(data)\n    bins = np.linspace(min_val, max_val, classes + 1)\n    quantized = np.digitize(data, bins) - 1\n    return quantized\n\n\ndef chebyshev_lowpass_filter(data, cutoff_freq=20, sampling_rate=200, order=4, rp=0.5):\n    nyquist = 0.5 * sampling_rate\n    normal_cutoff = cutoff_freq / nyquist\n    b, a = cheby1(order, rp, normal_cutoff, btype='low', analog=False)\n    filtered_data = lfilter(b, a, data, axis=0)\n    return filtered_data\nclass Dataset(torch.utils.data.Dataset):\n    def __init__(self, df): \n        self.df = df\n        \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, index):\n        # 使用 .iloc 来根据索引获取DataFrame的一行\n        data = self.df.iloc[index]\n        # ... 然后对这行数据进行进一步处理 ...\n\n        # 以下是您的数据预处理步骤...\n        data = np.clip(data, -1024, 1024)\n        data = np.nan_to_num(data, nan=0) / 32.0\n        data = chebyshev_lowpass_filter(data, order=4, rp=0.5)\n        data = quantize_data_linear(data, 256)\n\n        # 转换为 PyTorch 张量，并调整张量形状...\n        samples = torch.from_numpy(data).float()\n        print(samples.shape)\n        samples = samples.unsqueeze(0)  # 添加一个维度\n        print(samples.shape)\n        samples = samples.permute(2, 1, 0)  # 调整维度顺序以匹配模型的输入要求\n        \n        return samples\n    \n\nclass KLDivLossWithLogits(nn.KLDivLoss):\n\n    def __init__(self):\n        super().__init__(reduction=\"batchmean\")\n\n    def forward(self, y, t):\n        y = nn.functional.log_softmax(y,  dim=1)\n        loss = super().forward(y, t)\n\n        return loss","metadata":{"execution":{"iopub.status.busy":"2024-03-24T07:03:05.327256Z","iopub.execute_input":"2024-03-24T07:03:05.328495Z","iopub.status.idle":"2024-03-24T07:03:05.345695Z","shell.execute_reply.started":"2024-03-24T07:03:05.328321Z","shell.execute_reply":"2024-03-24T07:03:05.344295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\ndef get_test_dl(df_test):\n    # 根据需要操作 df_test\n    test_data = Dataset(df_test)\n    test_dataloader = DataLoader(test_data, batch_size=Config.batch_size, num_workers=2)\n    return test_dataloader","metadata":{"execution":{"iopub.status.busy":"2024-03-24T06:39:54.830934Z","iopub.execute_input":"2024-03-24T06:39:54.831235Z","iopub.status.idle":"2024-03-24T06:39:54.840571Z","shell.execute_reply.started":"2024-03-24T06:39:54.831209Z","shell.execute_reply":"2024-03-24T06:39:54.839678Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#!pip install torchtoolbox","metadata":{"execution":{"iopub.status.busy":"2024-03-24T06:39:54.842004Z","iopub.execute_input":"2024-03-24T06:39:54.842625Z","iopub.status.idle":"2024-03-24T06:39:54.848690Z","shell.execute_reply.started":"2024-03-24T06:39:54.842591Z","shell.execute_reply":"2024-03-24T06:39:54.847658Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#from torchtoolbox.tools import mixup_data, mixup_criterion\nimport torch.nn as nn\nfrom torch.nn.functional import cross_entropy\nimport torchmetrics\nimport timm\nimport sklearn.metrics\nimport sys\n# sys.path.append('/kaggle/input/kaggle-kl-div')\n\n# from kaggle_kl_div import score\n","metadata":{"execution":{"iopub.status.busy":"2024-03-24T06:39:54.852095Z","iopub.execute_input":"2024-03-24T06:39:54.852887Z","iopub.status.idle":"2024-03-24T06:39:54.858402Z","shell.execute_reply.started":"2024-03-24T06:39:54.852850Z","shell.execute_reply":"2024-03-24T06:39:54.857346Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_model(model_path):\n    # 加载整个 checkpoint\n    checkpoint = torch.load(model_path)\n    # 提取 state_dict\n    state_dict = checkpoint['state_dict']\n    \n    # 创建模型实例\n    model = EEGModel(num_classes = Config.num_classes, pretrained = Config.pretrained)\n\n    \n    # 加载 state_dict\n    model.load_state_dict(state_dict)\n    model.eval()\n    return model","metadata":{"execution":{"iopub.status.busy":"2024-03-24T06:39:54.859630Z","iopub.execute_input":"2024-03-24T06:39:54.860226Z","iopub.status.idle":"2024-03-24T06:39:54.869266Z","shell.execute_reply.started":"2024-03-24T06:39:54.860199Z","shell.execute_reply":"2024-03-24T06:39:54.868442Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tqdm import tqdm\ntqdm.pandas()\n\n\ndef predict(data_loader, model):\n    model.to('cuda')\n    model.eval()\n    predictions = []\n    for batch in tqdm(data_loader):\n        with torch.no_grad():\n            x = batch.cuda()\n            outputs = model(x)\n            outputs = nn.Softmax(dim=1)(outputs)\n        predictions.extend(outputs.detach().cpu().numpy())\n    return np.vstack(predictions)\n\n","metadata":{"execution":{"iopub.status.busy":"2024-03-24T06:39:54.872600Z","iopub.execute_input":"2024-03-24T06:39:54.873119Z","iopub.status.idle":"2024-03-24T06:39:54.880535Z","shell.execute_reply.started":"2024-03-24T06:39:54.873092Z","shell.execute_reply":"2024-03-24T06:39:54.879315Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from pytorch_lightning.loggers import WandbLogger\nimport gc\ntorch.set_float32_matmul_precision('high')\n\n\n\ndef run_inference(test_csv_path, model_weights_path, output_file):\n    df_test = pd.read_csv(test_csv_path)\n    model = load_model(model_weights_path)\n    test_dl = get_test_dl(df_test)\n    predictions = predict(test_dl, model)\n    df_test['predictions'] = predictions\n    df_test.to_csv(output_file, index=False)\n    print(f\"result has already been saved in {output_file}\")","metadata":{"execution":{"iopub.status.busy":"2024-03-24T06:39:54.882203Z","iopub.execute_input":"2024-03-24T06:39:54.883108Z","iopub.status.idle":"2024-03-24T06:39:54.890093Z","shell.execute_reply.started":"2024-03-24T06:39:54.883072Z","shell.execute_reply":"2024-03-24T06:39:54.888945Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in range(5):\n    model_weights_path = f'/kaggle/input/eegnet2d-v0/eegnet_best_loss_fold{i}.ckpt'\n    output_file = f'/kaggle/working/test_predictions_in_fold{i}.csv'\n    print(model_weights_path)\n    # 假设 run_inference 是一个你已经定义好的函数\n    run_inference(\n        test_csv_path=f'{Config.data_root}test.csv',\n        model_weights_path=model_weights_path,\n        output_file=output_file\n    )\n# run_inference(\n#     test_csv_path=f'{Config.data_root}test.csv',\n#     model_weights_path='after_train_full_data.pt',\n#     output_file='test_predictions_in_final.csv'\n# )","metadata":{"execution":{"iopub.status.busy":"2024-03-24T07:03:09.045251Z","iopub.execute_input":"2024-03-24T07:03:09.045961Z","iopub.status.idle":"2024-03-24T07:03:09.939772Z","shell.execute_reply.started":"2024-03-24T07:03:09.045928Z","shell.execute_reply":"2024-03-24T07:03:09.937974Z"},"trusted":true},"execution_count":null,"outputs":[]}]}