{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","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"}],"dockerImageVersionId":31012,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# ","metadata":{}},{"cell_type":"code","source":"import os","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:23.186716Z","iopub.execute_input":"2025-04-23T11:07:23.186951Z","iopub.status.idle":"2025-04-23T11:07:23.193141Z","shell.execute_reply.started":"2025-04-23T11:07:23.186924Z","shell.execute_reply":"2025-04-23T11:07:23.192515Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nfrom matplotlib import pyplot as plt\nimport cv2\nimport pandas as pd","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:23.194932Z","iopub.execute_input":"2025-04-23T11:07:23.195120Z","iopub.status.idle":"2025-04-23T11:07:25.024280Z","shell.execute_reply.started":"2025-04-23T11:07:23.195103Z","shell.execute_reply":"2025-04-23T11:07:25.023644Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def spectrogram_from_eeg(parquet_path, display=False):\n    \n    # LOAD MIDDLE 50 SECONDS OF EEG SERIES\n    eeg = pd.read_parquet(parquet_path)\n    middle = (len(eeg)-10_000)//2\n    eeg = eeg.iloc[middle:middle+10_000]\n    \n    # VARIABLE TO HOLD SPECTROGRAM\n    img = np.zeros((128,256,4),dtype='float32')\n    \n    if display: plt.figure(figsize=(10,7))\n    signals = []\n    for k in range(4):\n        COLS = FEATS[k]\n        \n        for kk in range(4):\n        \n            # COMPUTE PAIR DIFFERENCES\n            x = eeg[COLS[kk]].values - eeg[COLS[kk+1]].values\n\n            # FILL NANS\n            m = np.nanmean(x)\n            if np.isnan(x).mean()<1: x = np.nan_to_num(x,nan=m)\n            else: x[:] = 0\n\n            # DENOISE\n            if USE_WAVELET:\n                x = denoise(x, wavelet=USE_WAVELET)\n            signals.append(x)\n\n            # RAW SPECTROGRAM\n            mel_spec = librosa.feature.melspectrogram(y=x, sr=200, hop_length=len(x)//256, \n                  n_fft=1024, n_mels=128, fmin=0, fmax=20, win_length=128)\n\n            # LOG TRANSFORM\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            # STANDARDIZE TO -1 TO 1\n            mel_spec_db = (mel_spec_db+40)/40 \n            img[:,:,k] += mel_spec_db\n                \n        # AVERAGE THE 4 MONTAGE DIFFERENCES\n        img[:,:,k] /= 4.0\n        \n        if display:\n            plt.subplot(2,2,k+1)\n            plt.imshow(img[:,:,k],aspect='auto',origin='lower')\n            plt.title(f'EEG {eeg_id} - Spectrogram {NAMES[k]}')\n            \n    if display: \n        plt.show()\n        plt.figure(figsize=(10,5))\n        offset = 0\n        for k in range(4):\n            if k>0: offset -= signals[3-k].min()\n            plt.plot(range(10_000),signals[k]+offset,label=NAMES[3-k])\n            offset += signals[3-k].max()\n        plt.legend()\n        plt.title(f'EEG {eeg_id} Signals')\n        plt.show()\n        print(); print('#'*25); print()\n        \n    return img","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:25.025757Z","iopub.execute_input":"2025-04-23T11:07:25.026058Z","iopub.status.idle":"2025-04-23T11:07:25.035347Z","shell.execute_reply.started":"2025-04-23T11:07:25.026039Z","shell.execute_reply":"2025-04-23T11:07:25.034230Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"BASE_PATH = \"/kaggle/input/hms-harmful-brain-activity-classification\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:25.036544Z","iopub.execute_input":"2025-04-23T11:07:25.036792Z","iopub.status.idle":"2025-04-23T11:07:25.071248Z","shell.execute_reply.started":"2025-04-23T11:07:25.036766Z","shell.execute_reply":"2025-04-23T11:07:25.070524Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"os.listdir(BASE_PATH)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:25.072013Z","iopub.execute_input":"2025-04-23T11:07:25.072563Z","iopub.status.idle":"2025-04-23T11:07:25.091406Z","shell.execute_reply.started":"2025-04-23T11:07:25.072541Z","shell.execute_reply":"2025-04-23T11:07:25.090690Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"NAMES = ['LL','LP','RP','RR']\n\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\nimport pywt\nprint(\"The wavelet functions we can use:\")\nprint(pywt.wavelist())\n\nUSE_WAVELET = None #or \"db8\" or anything below\n\n# DENOISE FUNCTION\ndef maddest(d, axis=None):\n    return np.mean(np.absolute(d - np.mean(d, axis)), axis)\n\ndef denoise(x, wavelet='haar', level=1):    \n    coeff = pywt.wavedec(x, wavelet, mode=\"per\")\n    sigma = (1/0.6745) * maddest(coeff[-level])\n\n    uthresh = sigma * np.sqrt(2*np.log(len(x)))\n    coeff[1:] = (pywt.threshold(i, value=uthresh, mode='hard') for i in coeff[1:])\n\n    ret=pywt.waverec(coeff, wavelet, mode='per')\n    \n    return ret\n\nimport librosa","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:25.092098Z","iopub.execute_input":"2025-04-23T11:07:25.092411Z","iopub.status.idle":"2025-04-23T11:07:25.472298Z","shell.execute_reply.started":"2025-04-23T11:07:25.092389Z","shell.execute_reply":"2025-04-23T11:07:25.471544Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data = spectrogram_from_eeg(BASE_PATH+\"/train_eegs/\"+os.listdir(BASE_PATH+\"/train_eegs/\")[0])\ndata.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:25.472960Z","iopub.execute_input":"2025-04-23T11:07:25.473288Z","iopub.status.idle":"2025-04-23T11:07:38.760464Z","shell.execute_reply.started":"2025-04-23T11:07:25.473265Z","shell.execute_reply":"2025-04-23T11:07:38.759768Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def data_to_2d(data):\n    arr1 = data[:, :, 0]\n    arr2 = data[:, :, 0]\n    arr3 = data[:, :, 0]\n    arr4 = data[:, :, 0]\n        # İlk iki array'i yatay olarak birleştir\n    top_row = np.hstack((arr1, arr2))\n    \n    # Sonraki iki array'i yatay olarak birleştir\n    bottom_row = np.hstack((arr3, arr4))\n    \n    # İki satırı dikey olarak birleştir\n    result = np.vstack((top_row, bottom_row))\n    \n    # Sonuç boyutunu kontrol et\n    # print(result.shape)  # (256, 512)\n    return result","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:38.761294Z","iopub.execute_input":"2025-04-23T11:07:38.762204Z","iopub.status.idle":"2025-04-23T11:07:38.766104Z","shell.execute_reply.started":"2025-04-23T11:07:38.762156Z","shell.execute_reply":"2025-04-23T11:07:38.765505Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def np_array_from_eeg_id(eeg_id):\n    data = spectrogram_from_eeg(BASE_PATH+\"/train_eegs/\"+str(eeg_id)+\".parquet\")\n    return data_to_2d(data)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:38.768679Z","iopub.execute_input":"2025-04-23T11:07:38.768894Z","iopub.status.idle":"2025-04-23T11:07:38.784504Z","shell.execute_reply.started":"2025-04-23T11:07:38.768878Z","shell.execute_reply":"2025-04-23T11:07:38.783844Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"np_array_from_eeg_id(1628180742).shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:38.785309Z","iopub.execute_input":"2025-04-23T11:07:38.785542Z","iopub.status.idle":"2025-04-23T11:07:38.912287Z","shell.execute_reply.started":"2025-04-23T11:07:38.785521Z","shell.execute_reply":"2025-04-23T11:07:38.911597Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def visualize_eeg(eeg_id):\n    \n    plt.imshow(np_array_from_eeg_id(eeg_id), cmap='viridis', aspect='auto')  # İridis yerine Inferno paleti\n    plt.colorbar()  # Renk barı ekle\n    plt.title(\"Visualized Result Array with Iridis-like Palette\")\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:38.913016Z","iopub.execute_input":"2025-04-23T11:07:38.913259Z","iopub.status.idle":"2025-04-23T11:07:38.917149Z","shell.execute_reply.started":"2025-04-23T11:07:38.913234Z","shell.execute_reply":"2025-04-23T11:07:38.916386Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data_to_2d(data)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:38.917943Z","iopub.execute_input":"2025-04-23T11:07:38.918195Z","iopub.status.idle":"2025-04-23T11:07:38.932673Z","shell.execute_reply.started":"2025-04-23T11:07:38.918157Z","shell.execute_reply":"2025-04-23T11:07:38.932105Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"visualize_eeg(1628180742)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:38.933328Z","iopub.execute_input":"2025-04-23T11:07:38.933506Z","iopub.status.idle":"2025-04-23T11:07:39.388459Z","shell.execute_reply.started":"2025-04-23T11:07:38.933493Z","shell.execute_reply":"2025-04-23T11:07:39.387644Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def save_spectrogram_as_img(path):\n    #data =np.load(\"EEG_Spectrograms/1000913311.npy\")\n    data =np.load(path)\n    # Concatenate the 4 pictures in a 2x2 grid\n    concatenated_image = np.vstack((np.hstack((data[:, :, 0], data[:, :, 1])), \n                                    np.hstack((data[:, :, 2], data[:, :, 3]))))\n\n    # # Display the concatenated image\n    # plt.imshow(concatenated_image, cmap='gray')\n    # plt.axis('off')\n    # plt.show()\n\n    # Save the concatenated image with the same name as the numpy file\n    output_filename = path.split('/')[1].split('.')[0]\n    output_filename = \"images/\"+output_filename+\".jpg\"\n    cv2.imwrite(output_filename, concatenated_image * 255)  # Scale the image to 0-255 before saving","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:39.389208Z","iopub.execute_input":"2025-04-23T11:07:39.389403Z","iopub.status.idle":"2025-04-23T11:07:39.394198Z","shell.execute_reply.started":"2025-04-23T11:07:39.389387Z","shell.execute_reply":"2025-04-23T11:07:39.393402Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_img(id):\n    data = spectrogram_from_eeg(BASE_PATH + \"/train_eegs/\" +  f\"{id}.parquet\")\n    \n    # Concatenate the 4 pictures in a 2x2 grid\n    concatenated_image = np.vstack((\n        np.hstack((data[:, :, 0], data[:, :, 1])),\n        np.hstack((data[:, :, 2], data[:, :, 3]))\n    ))\n    \n    # Normalize to 0-255 and convert to uint8\n    normalized = cv2.normalize(concatenated_image, None, 0, 255, cv2.NORM_MINMAX)\n    normalized_uint8 = normalized.astype(np.uint8)\n    \n    # Apply viridis colormap\n    colored_img = cv2.applyColorMap(normalized_uint8, cv2.COLORMAP_VIRIDIS)\n    \n    return colored_img","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:39.394959Z","iopub.execute_input":"2025-04-23T11:07:39.395146Z","iopub.status.idle":"2025-04-23T11:07:39.410519Z","shell.execute_reply.started":"2025-04-23T11:07:39.395131Z","shell.execute_reply":"2025-04-23T11:07:39.409920Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"get_img(1628180742)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:39.411098Z","iopub.execute_input":"2025-04-23T11:07:39.411307Z","iopub.status.idle":"2025-04-23T11:07:39.546760Z","shell.execute_reply.started":"2025-04-23T11:07:39.411293Z","shell.execute_reply":"2025-04-23T11:07:39.545923Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"csv = pd.read_csv(BASE_PATH+\"/train.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:39.547683Z","iopub.execute_input":"2025-04-23T11:07:39.547975Z","iopub.status.idle":"2025-04-23T11:07:39.756581Z","shell.execute_reply.started":"2025-04-23T11:07:39.547950Z","shell.execute_reply":"2025-04-23T11:07:39.755751Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"unique_eeg_ids_df = csv.drop_duplicates(subset='eeg_id')\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:39.757562Z","iopub.execute_input":"2025-04-23T11:07:39.757797Z","iopub.status.idle":"2025-04-23T11:07:39.769442Z","shell.execute_reply.started":"2025-04-23T11:07:39.757780Z","shell.execute_reply":"2025-04-23T11:07:39.768786Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"unique_eeg_ids_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:39.770343Z","iopub.execute_input":"2025-04-23T11:07:39.770961Z","iopub.status.idle":"2025-04-23T11:07:39.796636Z","shell.execute_reply.started":"2025-04-23T11:07:39.770942Z","shell.execute_reply":"2025-04-23T11:07:39.796089Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"unique_eeg_ids_df = unique_eeg_ids_df[['eeg_id', 'expert_consensus']]\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:39.797267Z","iopub.execute_input":"2025-04-23T11:07:39.797494Z","iopub.status.idle":"2025-04-23T11:07:39.803653Z","shell.execute_reply.started":"2025-04-23T11:07:39.797479Z","shell.execute_reply":"2025-04-23T11:07:39.803128Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"unique_values = unique_eeg_ids_df['expert_consensus'].unique()\nprint(unique_values)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:39.804280Z","iopub.execute_input":"2025-04-23T11:07:39.804501Z","iopub.status.idle":"2025-04-23T11:07:39.821419Z","shell.execute_reply.started":"2025-04-23T11:07:39.804479Z","shell.execute_reply":"2025-04-23T11:07:39.820841Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"labels = {0:\"Seizure\",1:\"GPD\",2:\"LRDA\",3:\"LPD\",4:\"GRDA\",5:\"Other\"}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:39.822138Z","iopub.execute_input":"2025-04-23T11:07:39.822523Z","iopub.status.idle":"2025-04-23T11:07:39.832581Z","shell.execute_reply.started":"2025-04-23T11:07:39.822502Z","shell.execute_reply":"2025-04-23T11:07:39.831883Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.applications import ResNet50\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout, GlobalAveragePooling2D\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras import layers","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:39.833301Z","iopub.execute_input":"2025-04-23T11:07:39.833530Z","iopub.status.idle":"2025-04-23T11:07:52.171617Z","shell.execute_reply.started":"2025-04-23T11:07:39.833510Z","shell.execute_reply":"2025-04-23T11:07:52.171038Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.applications import ResNet50V2\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Dense, Dropout, GlobalAveragePooling2D, Input\nfrom tensorflow.keras.optimizers import Adam\n\n# Temel model\nbase_model = ResNet50V2(weights='imagenet', include_top=False, input_tensor=Input(shape=(256, 512, 3)))\nbase_model.trainable = False\n\n# Global Average Pooling\nx = base_model.output\nx = GlobalAveragePooling2D()(x)\n\n# Fully Connected Layer\nx = Dense(256, activation='relu')(x)\nx = Dropout(0.3)(x)\n\n# Çıkış katmanı (6 sınıf için softmax)\noutput = Dense(6, activation='softmax')(x)\n\n# Modeli oluştur\nmodel = Model(inputs=base_model.input, outputs=output)\n\n# Derleme\noptimizer = Adam(learning_rate=0.0001)\nmodel.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])\n\nmodel.summary()\n\ndef convert_to_rgb(image):\n    # Tek kanal (grayscale) resmi 3 kanallı RGB'ye dönüştürme\n    return tf.image.grayscale_to_rgb(image)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:52.172329Z","iopub.execute_input":"2025-04-23T11:07:52.172761Z","iopub.status.idle":"2025-04-23T11:07:56.648744Z","shell.execute_reply.started":"2025-04-23T11:07:52.172736Z","shell.execute_reply":"2025-04-23T11:07:56.648121Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Invert the labels dictionary to map string labels to their numeric values\nlabel_map = {v: k for k, v in labels.items()}\n\n# Replace the string values in the expert_consensus column with their numeric values\nunique_eeg_ids_df['expert_consensus'] = unique_eeg_ids_df['expert_consensus'].map(label_map)\nunique_eeg_ids_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:56.654873Z","iopub.execute_input":"2025-04-23T11:07:56.655485Z","iopub.status.idle":"2025-04-23T11:07:56.703082Z","shell.execute_reply.started":"2025-04-23T11:07:56.655464Z","shell.execute_reply":"2025-04-23T11:07:56.702424Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:56.706347Z","iopub.execute_input":"2025-04-23T11:07:56.706554Z","iopub.status.idle":"2025-04-23T11:07:56.823581Z","shell.execute_reply.started":"2025-04-23T11:07:56.706540Z","shell.execute_reply":"2025-04-23T11:07:56.822864Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Önce eğitim ve geri kalan verileri (validasyon + test) ayıralım\ntrain_df, rest_df = train_test_split(unique_eeg_ids_df, test_size=0.3, random_state=42) # %30 test + validasyon\n\n# Geri kalan verileri validasyon ve test olarak ayıralım\nval_df, test_df = train_test_split(rest_df, test_size=1/3, random_state=42) # %30'un 1/3'ü test, 2/3'ü validasyon","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:56.824302Z","iopub.execute_input":"2025-04-23T11:07:56.824546Z","iopub.status.idle":"2025-04-23T11:07:56.831152Z","shell.execute_reply.started":"2025-04-23T11:07:56.824526Z","shell.execute_reply":"2025-04-23T11:07:56.830598Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import keras.utils\n\nclass EEGDataGenerator(keras.utils.Sequence):\n    \"\"\"\n    Data generator for EEG spectrograms for Keras.\n    Converts EEG IDs to spectrograms using the provided function and returns batches.\n    \"\"\"\n    \n    def __init__(self, dataframe, spectrogram_function, batch_size=32, \n                 shuffle=True, seed=None, is_test=False):\n        \"\"\"\n        Initialize the data generator.\n        \n        Args:\n            dataframe (pd.DataFrame): DataFrame containing 'eeg_id' and 'expert_consensus' columns\n            spectrogram_function (callable): Function that converts eeg_id to spectrogram array\n            batch_size (int): Size of batches to generate\n            shuffle (bool): Whether to shuffle the data after each epoch\n            seed (int): Random seed for reproducibility\n            is_test (bool): If True, don't return labels (for prediction)\n        \"\"\"\n        self.df = dataframe.copy()\n        self.batch_size = batch_size\n        self.spectrogram_function = spectrogram_function\n        self.shuffle = shuffle\n        self.seed = seed\n        self.is_test = is_test\n        \n        # Generate indices\n        self.indices = np.arange(len(self.df))\n        \n        # Class mapping if needed\n        self.classes = sorted(self.df['expert_consensus'].unique())\n        self.class_indices = {cls: i for i, cls in enumerate(self.classes)}\n        \n        # Initial shuffle\n        if self.shuffle:\n            np.random.seed(self.seed)\n            np.random.shuffle(self.indices)\n    \n    def __len__(self):\n        \"\"\"Denotes the number of batches per epoch\"\"\"\n        return int(np.ceil(len(self.df) / self.batch_size))\n    \n    def __getitem__(self, index):\n        \"\"\"Generate one batch of data\"\"\"\n        # Generate indices of the batch\n        batch_indices = self.indices[index * self.batch_size:(index + 1) * self.batch_size]\n        \n        # Get batch data\n        batch_df = self.df.iloc[batch_indices]\n        \n        # Generate spectrograms\n        batch_x = np.array([\n            self.spectrogram_function(eeg_id) \n            for eeg_id in batch_df['eeg_id']\n        ])\n        \n        if self.is_test:\n            return batch_x\n        \n        # Generate labels (one-hot encoded)\n        batch_y = np.array([\n            self.class_indices[label] \n            for label in batch_df['expert_consensus']\n        ])\n        \n        return batch_x, tf.keras.utils.to_categorical(batch_y, num_classes=len(self.classes))\n    \n    def on_epoch_end(self):\n        \"\"\"Updates indices after each epoch\"\"\"\n        if self.shuffle:\n            np.random.seed(self.seed)\n            np.random.shuffle(self.indices)\n\n\ndef create_eeg_generators(train_df, val_df, test_df, spectrogram_from_eeg, \n                          batch_size=32, seed=42):\n    \"\"\"\n    Create train, validation, and test generators for EEG data.\n    \n    Args:\n        train_df (pd.DataFrame): Training data with 'eeg_id' and 'expert_consensus' columns\n        val_df (pd.DataFrame): Validation data with 'eeg_id' and 'expert_consensus' columns\n        test_df (pd.DataFrame): Test data with 'eeg_id' column\n        spectrogram_from_eeg (callable): Function to convert eeg_id to spectrogram\n        batch_size (int): Batch size for generators\n        seed (int): Random seed for reproducibility\n        \n    Returns:\n        tuple: (train_generator, val_generator, test_generator)\n    \"\"\"\n    # Create generators\n    train_generator = EEGDataGenerator(\n        dataframe=train_df,\n        spectrogram_function=get_img,\n        batch_size=batch_size,\n        shuffle=True,\n        seed=seed,\n        is_test=False\n    )\n    \n    val_generator = EEGDataGenerator(\n        dataframe=val_df,\n        spectrogram_function=get_img,\n        batch_size=batch_size,\n        shuffle=False,\n        seed=seed,\n        is_test=False\n    )\n    \n    test_generator = EEGDataGenerator(\n        dataframe=test_df,\n        spectrogram_function=get_img,\n        batch_size=batch_size,\n        shuffle=False,\n        seed=seed,\n        is_test=True\n    )\n    \n    return train_generator, val_generator, test_generator","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:56.831993Z","iopub.execute_input":"2025-04-23T11:07:56.832297Z","iopub.status.idle":"2025-04-23T11:07:56.845607Z","shell.execute_reply.started":"2025-04-23T11:07:56.832272Z","shell.execute_reply":"2025-04-23T11:07:56.844985Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_generator, val_generator, test_generator = create_eeg_generators(train_df, val_df, test_df, get_img, \n                          batch_size=32, seed=42)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:56.846333Z","iopub.execute_input":"2025-04-23T11:07:56.846515Z","iopub.status.idle":"2025-04-23T11:07:56.862707Z","shell.execute_reply.started":"2025-04-23T11:07:56.846501Z","shell.execute_reply":"2025-04-23T11:07:56.862049Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.optimizers import Adam\n\n# Öğrenme oranını artır\nlearning_rate = 0.0001  # Varsayılan 0.001, bunu artırdık\n\noptimizer = Adam(learning_rate=learning_rate)\n\n# Modeli yeniden derle\nmodel.compile(optimizer=optimizer, loss='categorical_crossentropy',metrics=['accuracy'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:56.863396Z","iopub.execute_input":"2025-04-23T11:07:56.863550Z","iopub.status.idle":"2025-04-23T11:07:56.881669Z","shell.execute_reply.started":"2025-04-23T11:07:56.863538Z","shell.execute_reply":"2025-04-23T11:07:56.881077Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nprint(\"GPU Available:\", tf.config.list_physical_devices('GPU'))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T11:07:56.882337Z","iopub.execute_input":"2025-04-23T11:07:56.882548Z","iopub.status.idle":"2025-04-23T11:07:56.896952Z","shell.execute_reply.started":"2025-04-23T11:07:56.882524Z","shell.execute_reply":"2025-04-23T11:07:56.896262Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Train the model\nhistory = model.fit(\n    train_generator,\n    validation_data=val_generator,\n    epochs=10\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-23T13:52:31.315959Z","iopub.execute_input":"2025-04-23T13:52:31.316221Z","iopub.status.idle":"2025-04-23T13:52:31.382342Z","shell.execute_reply.started":"2025-04-23T13:52:31.316201Z","shell.execute_reply":"2025-04-23T13:52:31.381387Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.save(\"resnet.h5\")","metadata":{"trusted":true,"execution":{"execution_failed":"2025-04-23T13:51:00.203Z"}},"outputs":[],"execution_count":null}]}