{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":102335,"databundleVersionId":12518947,"isSourceIdPinned":false,"sourceType":"competition"}],"dockerImageVersionId":31089,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport lightgbm as lgb\nfrom sklearn.preprocessing import LabelEncoder\nimport warnings\n\nwarnings.filterwarnings('ignore')\n\n# --- 1. データ読み込み ---\nprint(\"Loading data...\")\n# Colab環境では、APIでダウンロードしたファイルが直下に展開される\ntrain = pd.read_csv(\"/kaggle/input/cmi-detect-behavior-with-sensor-data/train.csv\")\ntest = pd.read_csv(\"/kaggle/input/cmi-detect-behavior-with-sensor-data/test.csv\")\ntrain_demo = pd.read_csv(\"/kaggle/input/cmi-detect-behavior-with-sensor-data/train_demographics.csv\")\ntest_demo = pd.read_csv(\"/kaggle/input/cmi-detect-behavior-with-sensor-data/test_demographics.csv\")\n\n# 属性情報をマージ\ntrain = pd.merge(train, train_demo, on='subject', how='left')\ntest = pd.merge(test, test_demo, on='subject', how='left')\n\nprint(\"Data loaded successfully.\")\nprint(f\"Train shape: {train.shape}\")\nprint(f\"Test shape: {test.shape}\")\n\n# --- 2. 特徴量エンジニアリング ---\ndef create_features(df):\n    \"\"\"\n    シーケンスデータから統計的特徴量を生成する関数\n    \"\"\"\n    sensor_cols = [col for col in df.columns if col.startswith(('acc_', 'rot_', 'thm_', 'tof_'))]\n    df[sensor_cols] = df[sensor_cols].fillna(0)\n    aggregations = {\n        col: ['mean', 'std', 'min', 'max', 'median'] for col in sensor_cols\n    }\n    agg_df = df.groupby('sequence_id').agg(aggregations)\n    agg_df.columns = ['_'.join(col).strip() for col in agg_df.columns.values]\n    demo_cols = ['adult_child', 'age', 'sex', 'handedness', 'height_cm', 'shoulder_to_wrist_cm', 'elbow_to_wrist_cm']\n    demo_df = df.groupby('sequence_id')[demo_cols].first()\n    final_df = pd.concat([agg_df, demo_df], axis=1)\n    return final_df\n\nprint(\"Creating features for training data...\")\nX_train_agg = create_features(train)\n\n# --- ラベル（目的変数）の準備 ---\nlabels_map = train[['sequence_id', 'gesture']].drop_duplicates().set_index('sequence_id')['gesture']\ny_train_series = X_train_agg.index.map(labels_map)\n\nle = LabelEncoder()\ny_train = le.fit_transform(y_train_series)\nlabel_names = le.classes_\n\nX_train = X_train_agg.reset_index(drop=True)\nX_train = X_train.fillna(0)\n\nprint(\"Features created. Training data shape:\", X_train.shape)\n\n# --- 3. モデル学習 ---\nprint(\"Training LightGBM model...\")\n\nparams = {\n    'objective': 'multiclass',\n    'num_class': len(label_names),\n    'metric': 'multi_logloss',\n    'n_estimators': 1000,\n    'learning_rate': 0.05,\n    'feature_fraction': 0.8,\n    'bagging_fraction': 0.8,\n    'bagging_freq': 1,\n    'lambda_l1': 0.1,\n    'lambda_l2': 0.1,\n    'num_leaves': 31,\n    'verbose': -1,\n    'n_jobs': -1,\n    'seed': 42,\n    'boosting_type': 'gbdt',\n}\n\nmodel = lgb.LGBMClassifier(**params)\nmodel.fit(X_train, y_train,\n          eval_set=[(X_train, y_train)],\n          eval_metric='multi_logloss',\n          callbacks=[lgb.early_stopping(100, verbose=False)])\n\nprint(\"Model training completed.\")\n\n# --- 4. 予測 ---\nprint(\"Generating predictions...\")\npredictions = []\ntest_sequence_ids = test['sequence_id'].unique()\n\nfor seq_id in test_sequence_ids:\n    seq_df = test[test['sequence_id'] == seq_id]\n    X_test_seq = create_features(seq_df)\n    \n    X_test_seq = X_test_seq.reset_index(drop=True)\n    X_test_seq = X_test_seq.fillna(0)\n    \n    missing_cols = set(X_train.columns) - set(X_test_seq.columns)\n    for c in missing_cols:\n        X_test_seq[c] = 0\n    X_test_seq = X_test_seq[X_train.columns]\n    \n    pred_label_encoded = model.predict(X_test_seq)\n    pred_label = le.inverse_transform(pred_label_encoded)[0]\n    \n    predictions.append({'sequence_id': seq_id, 'gesture': pred_label})\n\n# --- 5. 提出ファイルの作成 ---\nsubmission_df = pd.DataFrame(predictions)\nsubmission_df.to_parquet('/kaggle/working/submission.parquet', index=False)\n\nprint(\"Submission file created successfully: submission.parquet\")\nprint(submission_df.head())","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-08-14T21:45:15.160683Z","iopub.execute_input":"2025-08-14T21:45:15.160997Z","iopub.status.idle":"2025-08-14T21:55:10.128546Z","shell.execute_reply.started":"2025-08-14T21:45:15.160973Z","shell.execute_reply":"2025-08-14T21:55:10.127701Z"}},"outputs":[],"execution_count":null}]}