{"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":"gpu","dataSources":[{"sourceId":102335,"databundleVersionId":12518947,"sourceType":"competition"}],"dockerImageVersionId":31041,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nimport random\nimport tensorflow as tf\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import f1_score\nfrom sklearn.preprocessing import LabelEncoder, StandardScaler\nfrom tensorflow.keras import layers, models, optimizers, callbacks\nimport warnings\nwarnings.filterwarnings('ignore')\n\n# Sabitler ve Yapılandırma\nclass Config:\n    SEED = 42\n    N_SPLITS = 5\n    EPOCHS = 100\n    BATCH_SIZE = 64\n    PATIENCE = 15\n    LR = 0.001\n    VERBOSE = 1\n    MAX_SEQ_LEN = 100  # Sabit sekans uzunluğu\n    DROPOUT_RATE = 0.4\n    NUM_HEADS = 4  # Dikkat katmanları için\n\ndef seed_everything(seed=42):\n    random.seed(seed)\n    np.random.seed(seed)\n    tf.random.set_seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n\nseed_everything(Config.SEED)\n\n# GLOBAL INPUT_DIR tanımı\nINPUT_DIR = '/kaggle/input/cmi-detect-behavior-with-sensor-data'\n\n# Veri yükleme\ndef load_data():\n    try:\n        train = pd.read_parquet(f'{INPUT_DIR}/train.parquet')\n        test = pd.read_parquet(f'{INPUT_DIR}/test.parquet')\n        print(\"Parquet dosyaları yüklendi\")\n    except:\n        train = pd.read_csv(f'{INPUT_DIR}/train.csv')\n        test = pd.read_csv(f'{INPUT_DIR}/test.csv')\n        print(\"CSV dosyaları yüklendi\")\n    \n    # Demografik verileri yükle\n    try:\n        train_demo = pd.read_csv(f'{INPUT_DIR}/train_demographics.csv')\n        test_demo = pd.read_csv(f'{INPUT_DIR}/test_demographics.csv')\n        \n        # Demografik verileri birleştir\n        train = train.merge(train_demo, on='subject', how='left')\n        test = test.merge(test_demo, on='subject', how='left')\n        print(\"Demografik veriler birleştirildi\")\n    except Exception as e:\n        print(f\"Demografik veri yükleme hatası: {e}\")\n    \n    return train, test\n\n# Gelişmiş Özellik Mühendisliği\ndef get_feature_columns(df):\n    # IMU özellikleri\n    imu_features = ['acc_x', 'acc_y', 'acc_z', 'rot_w', 'rot_x', 'rot_y', 'rot_z']\n    \n    # Thermopile özellikleri\n    thm_features = [col for col in df.columns if col.startswith('thm_')]\n    \n    # Time-of-flight özellikleri\n    tof_features = [col for col in df.columns if col.startswith('tof_')]\n    \n    # Demografik özellikler\n    demo_features = ['age', 'sex', 'handedness', 'height_cm', \n                    'shoulder_to_wrist_cm', 'elbow_to_wrist_cm']\n    \n    # ToF sensörlerini ayrı ayrı işle\n    tof_sensors = {}\n    for i in range(1, 6):\n        sensor_cols = [col for col in tof_features if col.startswith(f'tof_{i}_')]\n        if sensor_cols:  # Sadece mevcut sensörleri ekle\n            tof_sensors[f'tof_{i}'] = sensor_cols\n    \n    return {\n        'imu': imu_features,\n        'thm': thm_features,\n        'tof': tof_features,\n        'tof_sensors': tof_sensors,\n        'demo': demo_features\n    }\n\n# Gelişmiş Ön İşleme\ndef preprocess_data(df, feature_config):\n    df_processed = df.copy()\n    \n    # IMU işleme\n    for col in feature_config['imu']:\n        if col in df_processed.columns:\n            df_processed[col] = df_processed[col].fillna(df_processed[col].median())\n    \n    # Thermopile işleme\n    for col in feature_config['thm']:\n        if col in df_processed.columns:\n            df_processed[col] = df_processed[col].fillna(df_processed[col].median())\n    \n    # ToF işleme - özel işlem\n    for sensor, cols in feature_config['tof_sensors'].items():\n        sensor_cols = [col for col in cols if col in df_processed.columns]\n        if sensor_cols:\n            # -1 değerlerini NaN ile değiştir\n            df_processed[sensor_cols] = df_processed[sensor_cols].replace(-1, np.nan)\n            # NaN değerleri sensör medyanı ile doldur\n            df_processed[sensor_cols] = df_processed[sensor_cols].fillna(\n                df_processed[sensor_cols].median())\n    \n    # Demografik işleme\n    for col in feature_config['demo']:\n        if col in df_processed.columns:\n            df_processed[col] = df_processed[col].fillna(df_processed[col].median())\n    \n    return df_processed\n\n# Sekans oluşturma (DÜZELTİLDİ - 'behavior' sütunu kontrolü)\ndef create_sequences(df, feature_config, seq_len=Config.MAX_SEQ_LEN):\n    sequences = {\n        'imu': [],\n        'thm': [],\n        'tof': [],\n        'demo': []\n    }\n    sequence_ids = []\n    \n    grouped = df.groupby('sequence_id')\n    \n    for seq_id, group in grouped:\n        # 'behavior' sütunu varsa gesture fazını seç, yoksa tüm veriyi kullan\n        if 'behavior' in group.columns:\n            gesture_data = group[group['behavior'].str.contains('gesture', case=False, na=False)]\n            if len(gesture_data) == 0:\n                gesture_data = group\n        else:\n            gesture_data = group  # Test seti için tüm veriyi kullan\n        \n        # IMU verileri\n        imu_data = gesture_data[feature_config['imu']].values\n        imu_data = pad_or_truncate(imu_data, seq_len)\n        sequences['imu'].append(imu_data)\n        \n        # Thermopile verileri\n        if feature_config['thm']:\n            thm_data = gesture_data[feature_config['thm']].values\n            thm_data = pad_or_truncate(thm_data, seq_len)\n            sequences['thm'].append(thm_data)\n        \n        # ToF verileri - uzamsal format (8x8 grid)\n        if feature_config['tof_sensors']:\n            tof_data = []\n            for sensor, cols in feature_config['tof_sensors'].items():\n                sensor_cols = [col for col in cols if col in gesture_data.columns]\n                if sensor_cols:\n                    # Her zaman adımı için 8x8 grid oluştur\n                    sensor_values = gesture_data[sensor_cols].values\n                    sensor_values = pad_or_truncate(sensor_values, seq_len)\n                    \n                    # 8x8 grid haline getir (zaman_adimi, 64) -> (zaman_adimi, 8, 8)\n                    sensor_values = sensor_values.reshape(-1, 8, 8)\n                    tof_data.append(sensor_values)\n            \n            if tof_data:\n                # Sensörleri kanal boyutunda birleştir\n                tof_data = np.stack(tof_data, axis=-1)  # Şekil: (seq_len, 8, 8, num_sensors)\n                sequences['tof'].append(tof_data)\n        \n        # Demografik veriler (tüm zaman adımları için tekrarla)\n        if feature_config['demo'] and gesture_data[feature_config['demo']].size > 0:\n            demo_data = gesture_data[feature_config['demo']].values\n            demo_data = demo_data[0]  # İlk satırı al (hepsi aynı)\n            demo_data = np.tile(demo_data, (seq_len, 1))\n            sequences['demo'].append(demo_data)\n        \n        sequence_ids.append(seq_id)\n    \n    # Numpy dizilerine dönüştür\n    for key in sequences:\n        if sequences[key]:\n            sequences[key] = np.array(sequences[key])\n        else:\n            sequences[key] = None  # Yoksa None olarak ayarla\n    \n    return sequences, sequence_ids\n\ndef pad_or_truncate(data, target_length):\n    if len(data) < target_length:\n        # Doldurma\n        pad_length = target_length - len(data)\n        padded_data = np.pad(data, ((0, pad_length), (0, 0)), mode='constant', constant_values=0)\n        return padded_data\n    else:\n        # Kırpma\n        return data[:target_length]\n\n# Gelişmiş Çok Modlu Model Mimarisi\ndef create_advanced_model(feature_config, num_classes):\n    # Girdi katmanları\n    inputs = {}\n    \n    # IMU dalı - zamansal işleme\n    imu_input = layers.Input(shape=(Config.MAX_SEQ_LEN, len(feature_config['imu'])), name='imu_input')\n    inputs['imu'] = imu_input\n    \n    # IMU işleme + dikkat mekanizması\n    x_imu = layers.Conv1D(128, 5, activation='relu', padding='same')(imu_input)\n    x_imu = layers.BatchNormalization()(x_imu)\n    x_imu = layers.Conv1D(128, 5, activation='relu', padding='same')(x_imu)\n    x_imu = layers.MaxPooling1D(2)(x_imu)\n    x_imu = layers.Dropout(Config.DROPOUT_RATE)(x_imu)\n    \n    # Çok kafalı öz-dikkat\n    query = layers.Dense(128)(x_imu)\n    key = layers.Dense(128)(x_imu)\n    value = layers.Dense(128)(x_imu)\n    attention = layers.Attention(use_scale=True)([query, key, value])\n    x_imu = layers.Concatenate()([x_imu, attention])\n    \n    x_imu = layers.Bidirectional(layers.LSTM(128, return_sequences=True))(x_imu)\n    x_imu = layers.GlobalAveragePooling1D()(x_imu)\n    \n    # Thermopile dalı (mevcutsa)\n    if feature_config['thm']:\n        thm_input = layers.Input(shape=(Config.MAX_SEQ_LEN, len(feature_config['thm'])), name='thm_input')\n        inputs['thm'] = thm_input\n        \n        x_thm = layers.Conv1D(64, 3, activation='relu', padding='same')(thm_input)\n        x_thm = layers.BatchNormalization()(x_thm)\n        x_thm = layers.LSTM(64, return_sequences=False)(x_thm)\n    else:\n        x_thm = None\n    \n    # ToF dalı (mevcutsa) - uzamsal işleme\n    if feature_config['tof_sensors']:\n        tof_input = layers.Input(\n            shape=(Config.MAX_SEQ_LEN, 8, 8, len(feature_config['tof_sensors'])), \n            name='tof_input')\n        inputs['tof'] = tof_input\n        \n        # CNN ile her zaman adımını işle\n        x_tof = layers.TimeDistributed(\n            layers.Conv2D(32, (3, 3), activation='relu', padding='same'))(tof_input)\n        x_tof = layers.TimeDistributed(layers.MaxPooling2D((2, 2)))(x_tof)\n        x_tof = layers.TimeDistributed(layers.Flatten())(x_tof)\n        x_tof = layers.LSTM(64, return_sequences=False)(x_tof)\n    else:\n        x_tof = None\n    \n    # Demografik dal\n    if feature_config['demo']:\n        demo_input = layers.Input(shape=(Config.MAX_SEQ_LEN, len(feature_config['demo'])), name='demo_input')\n        inputs['demo'] = demo_input\n        x_demo = layers.Dense(32, activation='relu')(demo_input[:, 0, :])  # Sadece ilk zaman adımı\n    else:\n        # Demografik veri yoksa sıfır vektörü\n        demo_input = layers.Input(shape=(Config.MAX_SEQ_LEN, 1), name='demo_input')\n        inputs['demo'] = demo_input\n        x_demo = layers.Lambda(lambda x: tf.zeros((tf.shape(x)[0], 1)))(demo_input)\n    \n    # Dalları birleştir\n    combined = [x_imu, x_demo]\n    if x_thm is not None:\n        combined.append(x_thm)\n    if x_tof is not None:\n        combined.append(x_tof)\n    \n    x = layers.Concatenate()(combined)\n    x = layers.Dense(256, activation='relu')(x)\n    x = layers.Dropout(Config.DROPOUT_RATE)(x)\n    x = layers.Dense(128, activation='relu')(x)\n    x = layers.Dropout(Config.DROPOUT_RATE/2)(x)\n    \n    # Çıktılar\n    binary_output = layers.Dense(1, activation='sigmoid', name='binary_output')(x)\n    multi_output = layers.Dense(num_classes, activation='softmax', name='multi_output')(x)\n    \n    return models.Model(inputs=inputs, outputs=[binary_output, multi_output])\n\n# Ana Fonksiyon (DÜZELTİLDİ)\ndef main():\n    # Veri yükleme\n    train_df, test_df = load_data()\n    \n    # Özellik yapılandırması\n    feature_config = get_feature_columns(train_df)\n    print(\"Özellik yapılandırması oluşturuldu\")\n    \n    # Veri ön işleme\n    train_df = preprocess_data(train_df, feature_config)\n    test_df = preprocess_data(test_df, feature_config)\n    print(\"Veri ön işlendi\")\n    \n    # Hedef değişkenler (sadece eğitim seti için)\n    if 'sequence_type' in train_df.columns:\n        train_df['binary_target'] = (train_df['sequence_type'] == 'Target').astype(int)\n    else:\n        # Test seti için geçici değerler\n        train_df['binary_target'] = 0\n    \n    if 'gesture' in train_df.columns:\n        le = LabelEncoder()\n        train_df['gesture_encoded'] = le.fit_transform(train_df['gesture'])\n        num_classes = len(le.classes_)\n        print(f\"Sınıf sayısı: {num_classes}\")\n        print(f\"Sınıflar: {le.classes_}\")\n    else:\n        # Test seti için geçici değerler\n        train_df['gesture_encoded'] = 0\n        num_classes = 1\n        le = None\n    \n    # Sekansları oluştur\n    print(\"Eğitim sekansları oluşturuluyor...\")\n    train_sequences, train_seq_ids = create_sequences(train_df, feature_config)\n    print(\"Test sekansları oluşturuluyor...\")\n    test_sequences, test_seq_ids = create_sequences(test_df, feature_config)\n    \n    # Hedef değişkenleri hazırla (sadece eğitim seti için)\n    if 'sequence_id' in train_df.columns and 'binary_target' in train_df.columns:\n        train_meta = train_df.drop_duplicates('sequence_id').set_index('sequence_id')\n        train_meta = train_meta.loc[train_seq_ids]\n        y_binary = train_meta['binary_target'].values\n        y_multi = train_meta['gesture_encoded'].values\n    else:\n        # Test seti için geçici değerler\n        y_binary = np.zeros(len(train_seq_ids))\n        y_multi = np.zeros(len(train_seq_ids))\n    \n    # Normalizasyon\n    scalers = {}\n    for key in ['imu', 'thm', 'demo']:\n        if train_sequences[key] is not None and len(train_sequences[key]) > 0:\n            # Ölçeklendirme için yeniden şekillendir\n            orig_shape = train_sequences[key].shape\n            flattened = train_sequences[key].reshape(-1, orig_shape[-1])\n            \n            scaler = StandardScaler()\n            scaled = scaler.fit_transform(flattened)\n            train_sequences[key] = scaled.reshape(orig_shape)\n            \n            if test_sequences[key] is not None and len(test_sequences[key]) > 0:\n                orig_shape_test = test_sequences[key].shape\n                flattened_test = test_sequences[key].reshape(-1, orig_shape_test[-1])\n                scaled_test = scaler.transform(flattened_test)\n                test_sequences[key] = scaled_test.reshape(orig_shape_test)\n            \n            scalers[key] = scaler\n    \n    # Çapraz doğrulama (sadece eğitim verisi varsa)\n    if len(y_binary) > 0 and num_classes > 1:\n        skf = StratifiedKFold(n_splits=Config.N_SPLITS, shuffle=True, random_state=Config.SEED)\n        \n        oof_binary = np.zeros(len(train_seq_ids))\n        oof_multi = np.zeros((len(train_seq_ids), num_classes))\n        \n        test_pred_binary = np.zeros(len(test_seq_ids))\n        test_pred_multi = np.zeros((len(test_seq_ids), num_classes))\n        \n        for fold, (train_idx, val_idx) in enumerate(skf.split(train_sequences['imu'], y_binary)):\n            print(f\"\\n=== Fold {fold + 1} ===\")\n            \n            # Girdileri hazırla\n            train_input = {'imu': train_sequences['imu'][train_idx]}\n            val_input = {'imu': train_sequences['imu'][val_idx]}\n            test_input = {'imu': test_sequences['imu']}\n            \n            # Diğer modaliteleri ekle (mevcutsa)\n            for modality in ['thm', 'tof', 'demo']:\n                if modality in train_sequences and train_sequences[modality] is not None:\n                    train_input[modality] = train_sequences[modality][train_idx]\n                    val_input[modality] = train_sequences[modality][val_idx]\n                    if modality in test_sequences and test_sequences[modality] is not None:\n                        test_input[modality] = test_sequences[modality]\n            \n            # Model oluştur\n            model = create_advanced_model(feature_config, num_classes)\n            \n            # Modeli derle\n            model.compile(\n                optimizer=optimizers.Adam(learning_rate=Config.LR),\n                loss={\n                    'binary_output': 'binary_crossentropy',\n                    'multi_output': 'sparse_categorical_crossentropy'\n                },\n                loss_weights={'binary_output': 1.0, 'multi_output': 1.0},\n                metrics={\n                    'binary_output': ['accuracy'],\n                    'multi_output': ['accuracy']\n                }\n            )\n            \n            # Callbacks\n            callbacks_list = [\n                callbacks.EarlyStopping(\n                    monitor='val_loss', patience=Config.PATIENCE, \n                    restore_best_weights=True, verbose=1\n                ),\n                callbacks.ReduceLROnPlateau(\n                    monitor='val_loss', factor=0.5, patience=7, \n                    min_lr=1e-7, verbose=1\n                )\n            ]\n            \n            # Eğitim\n            history = model.fit(\n                train_input,\n                {'binary_output': y_binary[train_idx], 'multi_output': y_multi[train_idx]},\n                validation_data=(\n                    val_input,\n                    {'binary_output': y_binary[val_idx], 'multi_output': y_multi[val_idx]}\n                ),\n                epochs=Config.EPOCHS,\n                batch_size=Config.BATCH_SIZE,\n                callbacks=callbacks_list,\n                verbose=Config.VERBOSE\n            )\n            \n            # Tahmin\n            val_pred = model.predict(val_input, verbose=0)\n            oof_binary[val_idx] = val_pred[0].flatten()\n            oof_multi[val_idx] = val_pred[1]\n            \n            test_pred = model.predict(test_input, verbose=0)\n            test_pred_binary += test_pred[0].flatten() / Config.N_SPLITS\n            test_pred_multi += test_pred[1] / Config.N_SPLITS\n            \n            # Belleği temizle\n            del model\n            tf.keras.backend.clear_session()\n        \n        # Değerlendirme\n        oof_binary_class = (oof_binary > 0.5).astype(int)\n        oof_multi_class = np.argmax(oof_multi, axis=1)\n        \n        binary_f1 = f1_score(y_binary, oof_binary_class)\n        multi_f1 = f1_score(y_multi, oof_multi_class, average='macro')\n        final_score = (binary_f1 + multi_f1) / 2\n        \n        print(f\"\\n=== Sonuçlar ===\")\n        print(f\"Binary F1: {binary_f1:.4f}\")\n        print(f\"Multi F1: {multi_f1:.4f}\")\n        print(f\"Final Skor: {final_score:.4f}\")\n    else:\n        # Sadece test seti için tahmin yap\n        test_pred_binary = np.zeros(len(test_seq_ids))\n        test_pred_multi = np.zeros((len(test_seq_ids), num_classes))\n    \n    # Submission dosyası hazırlama\n    if le is not None:\n        test_binary_class = (test_pred_binary > 0.5).astype(int)\n        test_multi_class = np.argmax(test_pred_multi, axis=1)\n        \n        submission_preds = []\n        for i in range(len(test_binary_class)):\n            if test_binary_class[i] == 0:\n                submission_preds.append('non_target')\n            else:\n                submission_preds.append(le.inverse_transform([test_multi_class[i]])[0])\n        \n        submission = pd.DataFrame({\n            'sequence_id': test_seq_ids,\n            'gesture': submission_preds\n        })\n        \n        submission.to_csv('submission.csv', index=False)\n        print(\"Submission dosyası kaydedildi!\")\n    else:\n        print(\"LabelEncoder bulunamadı, submission oluşturulamadı\")\n\nif __name__ == \"__main__\":\n    main()","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-06-14T13:23:49.098341Z","iopub.execute_input":"2025-06-14T13:23:49.098621Z","iopub.status.idle":"2025-06-14T14:39:06.036634Z","shell.execute_reply.started":"2025-06-14T13:23:49.098599Z","shell.execute_reply":"2025-06-14T14:39:06.035815Z"}},"outputs":[],"execution_count":null}]}