{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"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,"sourceType":"competition"},{"sourceId":12605355,"sourceType":"datasetVersion","datasetId":7962124},{"sourceId":12730500,"sourceType":"datasetVersion","datasetId":8046582}],"dockerImageVersionId":31089,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"id":"3e73b84f","cell_type":"code","source":"from tqdm import tqdm\nimport pandas as pd\nimport sys\nfolder_path = \"/kaggle/input/cmi-detect-behavior-with-sensor-data\"\n#sys.path.append(folder_path)\nsys.path.append(\"/kaggle/input/utils-010\")\n\nrow_train_demo = pd.read_csv(f\"{folder_path}/train_demographics.csv\")\nrow_train = pd.read_csv(f\"{folder_path}/train.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-11T04:57:08.851200Z","iopub.execute_input":"2025-08-11T04:57:08.852420Z","iopub.status.idle":"2025-08-11T04:57:36.325093Z","shell.execute_reply.started":"2025-08-11T04:57:08.852372Z","shell.execute_reply":"2025-08-11T04:57:36.324234Z"}},"outputs":[],"execution_count":null},{"id":"3198c84a","cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-11T04:57:36.326628Z","iopub.execute_input":"2025-08-11T04:57:36.326868Z","iopub.status.idle":"2025-08-11T04:57:36.330999Z","shell.execute_reply.started":"2025-08-11T04:57:36.326848Z","shell.execute_reply":"2025-08-11T04:57:36.330316Z"}},"outputs":[],"execution_count":null},{"id":"b7a447bd","cell_type":"code","source":"import torch\nimport numpy as np\nimport pandas as pd\nimport random\nimport os\n\ndef set_seed(seed):\n    \"\"\"\n    主要なライブラリの乱数シードを固定する関数。\n    \"\"\"\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    random.seed(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    if torch.cuda.is_available():\n        torch.cuda.manual_seed(seed)\n        torch.cuda.manual_seed_all(seed)  # 複数のGPUを使用する場合\n        # CUDNN関連のシードも固定して、決定論的挙動を保証\n        torch.backends.cudnn.deterministic = True\n        torch.backends.cudnn.benchmark = False\n    \n    print(f\"乱数シードを {seed} に設定しました。\")\n\nSEED = 42\nset_seed(SEED)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-11T04:57:36.331855Z","iopub.execute_input":"2025-08-11T04:57:36.332069Z","iopub.status.idle":"2025-08-11T04:57:36.351468Z","shell.execute_reply.started":"2025-08-11T04:57:36.332046Z","shell.execute_reply":"2025-08-11T04:57:36.350671Z"}},"outputs":[],"execution_count":null},{"id":"e21b5e52","cell_type":"code","source":"train=row_train.copy()\ntrain_demo = row_train_demo.copy()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-11T04:57:36.352485Z","iopub.execute_input":"2025-08-11T04:57:36.352752Z","iopub.status.idle":"2025-08-11T04:57:36.941242Z","shell.execute_reply.started":"2025-08-11T04:57:36.352734Z","shell.execute_reply":"2025-08-11T04:57:36.940362Z"}},"outputs":[],"execution_count":null},{"id":"72044515","cell_type":"code","source":"train = train.iloc[:, :-325]\n#train = train[train[\"behavior\"] == \"Hand at target location\"]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-11T04:57:36.943533Z","iopub.execute_input":"2025-08-11T04:57:36.943765Z","iopub.status.idle":"2025-08-11T04:57:37.014744Z","shell.execute_reply.started":"2025-08-11T04:57:36.943746Z","shell.execute_reply":"2025-08-11T04:57:37.013888Z"}},"outputs":[],"execution_count":null},{"id":"808462be","cell_type":"code","source":"import pandas as pd\nimport numpy as np\n\ndef calculate_dynamic_acceleration(train):\n    \"\"\"\n    クォータニオンから回転行列を導出し、重力ベクトルを減算して動的加速度を計算します。\n    \n    引数:\n        train (pd.DataFrame): 'acc_x', 'acc_y', 'acc_z', 'rot_w', 'rot_x', 'rot_y', 'rot_z'\n                              の各列を含むDataFrame。\n    \n    戻り値:\n        pd.DataFrame: 動的加速度の3軸 ('acc_x_dynamic', 'acc_y_dynamic', 'acc_z_dynamic')\n                      と、回転後の重力ベクトル ('gravity_x', 'gravity_y', 'gravity_z') \n                      を追加したDataFrame。\n    \"\"\"\n    quaternions = train[['rot_w', 'rot_x', 'rot_y', 'rot_z']].values.astype(np.float64)\n    accelerations = train[['acc_x', 'acc_y', 'acc_z']].values.astype(np.float64)\n    \n    # 単位クォータニオンであることを保証するために正規化\n    norms = np.linalg.norm(quaternions, axis=1, keepdims=True)\n    quaternions /= norms\n\n    w, x, y, z = quaternions.T\n\n    R = np.zeros((len(train), 3, 3))\n    R[:, 0, 0] = 1 - 2*y**2 - 2*z**2\n    R[:, 0, 1] = 2*x*y - 2*z*w\n    R[:, 0, 2] = 2*x*z + 2*y*w\n    R[:, 1, 0] = 2*x*y + 2*z*w\n    R[:, 1, 1] = 1 - 2*x**2 - 2*z**2\n    R[:, 1, 2] = 2*y*z - 2*x*w\n    R[:, 2, 0] = 2*x*z - 2*y*w\n    R[:, 2, 1] = 2*y*z + 2*x*w\n    R[:, 2, 2] = 1 - 2*x**2 - 2*y**2\n\n    # Z軸が上方向と仮定\n    gravity_vector = np.array([0, 0, 9.8])\n    \n    rotated_gravity = np.einsum('nij, j->ni', R, gravity_vector)\n\n    dynamic_acceleration = accelerations - rotated_gravity\n    \n    result_df = train.copy()\n    result_df['acc_x_dynamic'] = dynamic_acceleration[:, 0]\n    result_df['acc_y_dynamic'] = dynamic_acceleration[:, 1]\n    result_df['acc_z_dynamic'] = dynamic_acceleration[:, 2]\n\n    result_df['gravity_x'] = rotated_gravity[:, 0]\n    result_df['gravity_y'] = rotated_gravity[:, 1]\n    result_df['gravity_z'] = rotated_gravity[:, 2]\n\n    return result_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-11T04:57:37.015830Z","iopub.execute_input":"2025-08-11T04:57:37.016145Z","iopub.status.idle":"2025-08-11T04:57:37.026521Z","shell.execute_reply.started":"2025-08-11T04:57:37.016116Z","shell.execute_reply":"2025-08-11T04:57:37.025557Z"}},"outputs":[],"execution_count":null},{"id":"93b81b11","cell_type":"code","source":"train = calculate_dynamic_acceleration(train)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-11T04:57:37.027184Z","iopub.execute_input":"2025-08-11T04:57:37.027460Z","iopub.status.idle":"2025-08-11T04:57:37.219549Z","shell.execute_reply.started":"2025-08-11T04:57:37.027436Z","shell.execute_reply":"2025-08-11T04:57:37.218579Z"}},"outputs":[],"execution_count":null},{"id":"e34bcc58","cell_type":"code","source":"def plot_sequence(data):\n    rot_cols = ['rot_w', 'rot_x', 'rot_y', 'rot_z']\n    acc_cols = ['acc_x', 'acc_y', 'acc_z']\n    grav_cols = ['gravity_x', 'gravity_y', 'gravity_z']\n    dynamic_cols = ['acc_x_dynamic', 'acc_y_dynamic', 'acc_z_dynamic']\n\n    unique_behaviors = data['behavior'].unique()\n    bg_colors = plt.cm.get_cmap('Paired', len(unique_behaviors))\n    \n    fig, axes = plt.subplots(4, 1, figsize=(15, 20), sharex=True)\n    ax_acc, ax_rot, ax_grav, ax_dyn = axes.flatten()\n\n    fig.suptitle(\n        f\"Sequence ID: {data['sequence_id'].iloc[0]}, Orientation: {data['orientation'].iloc[0]}, Gesture: {data['gesture'].iloc[0]}, Sequence Type: {data['sequence_type'].iloc[0]}\",\n        fontsize=16\n    )\n\n    for i, (behavior, group) in enumerate(data.groupby('behavior')):\n        ax_acc.axvspan(group['sequence_counter'].min(), group['sequence_counter'].max(), \n                       color=bg_colors(i), alpha=0.2, label=f'Behavior: {behavior}')\n        ax_rot.axvspan(group['sequence_counter'].min(), group['sequence_counter'].max(), \n                       color=bg_colors(i), alpha=0.2)\n        ax_grav.axvspan(group['sequence_counter'].min(), group['sequence_counter'].max(), \n                        color=bg_colors(i), alpha=0.2)\n        ax_dyn.axvspan(group['sequence_counter'].min(), group['sequence_counter'].max(), \n                       color=bg_colors(i), alpha=0.2)\n\n    for col in acc_cols:\n        ax_acc.plot(data['sequence_counter'], data[col], label=col, linestyle='-')\n    ax_acc.set_ylabel('Acceleration (m/s²)')\n    ax_acc.legend(loc='upper left')\n    ax_acc.grid(True, linestyle='--', alpha=0.6)\n\n    for col in rot_cols:\n        ax_rot.plot(data['sequence_counter'], data[col], label=col, linestyle='-')\n    ax_rot.set_ylabel('Rotation (quaternion)')\n    ax_rot.legend(loc='upper left')\n    ax_rot.grid(True, linestyle='--', alpha=0.6)\n\n    for col in grav_cols:\n        ax_grav.plot(data['sequence_counter'], data[col], label=col, linestyle='-')\n    ax_grav.set_ylabel('Gravity Vector (m/s²)')\n    ax_grav.legend(loc='upper left')\n    ax_grav.grid(True, linestyle='--', alpha=0.6)\n\n    for col in dynamic_cols:\n        ax_dyn.plot(data['sequence_counter'], data[col], label=col, linestyle='-')\n    ax_dyn.set_ylabel('Dynamic Acceleration (m/s²)')\n    ax_dyn.legend(loc='upper left')\n    ax_dyn.grid(True, linestyle='--', alpha=0.6)\n    \n    ax_dyn.set_xlabel('sequence_counter')\n    \n    fig.tight_layout(rect=[0, 0, 1, 0.97])\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-11T04:57:37.220331Z","iopub.execute_input":"2025-08-11T04:57:37.220586Z","iopub.status.idle":"2025-08-11T04:57:37.232350Z","shell.execute_reply.started":"2025-08-11T04:57:37.220566Z","shell.execute_reply":"2025-08-11T04:57:37.231519Z"}},"outputs":[],"execution_count":null},{"id":"8747e2fc","cell_type":"code","source":"# DatasetとDataLoaderのインポート\nfrom torch.utils.data import DataLoader\nfrom dataset import SubjectDataset, custom_collate_fn\n\ntrain_dataset = SubjectDataset(train_demo, train, drop_cols=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-11T04:57:37.233220Z","iopub.execute_input":"2025-08-11T04:57:37.233534Z","iopub.status.idle":"2025-08-11T04:57:43.151327Z","shell.execute_reply.started":"2025-08-11T04:57:37.233508Z","shell.execute_reply":"2025-08-11T04:57:43.150585Z"}},"outputs":[],"execution_count":null},{"id":"2966af93","cell_type":"code","source":"count = 0\nfor demo, data, label in train_dataset:\n    if np.random.rand() < 0.5:\n        plot_sequence(data)\n        count += 1\n        if count >=4:\n            break","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-11T04:57:43.152203Z","iopub.execute_input":"2025-08-11T04:57:43.152448Z","iopub.status.idle":"2025-08-11T04:57:48.837526Z","shell.execute_reply.started":"2025-08-11T04:57:43.152431Z","shell.execute_reply":"2025-08-11T04:57:48.836543Z"}},"outputs":[],"execution_count":null},{"id":"74cb2a55","cell_type":"code","source":"train=row_train.copy()\ntrain_demo = row_train_demo.copy()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-11T04:57:48.838414Z","iopub.execute_input":"2025-08-11T04:57:48.838669Z","iopub.status.idle":"2025-08-11T04:57:49.407457Z","shell.execute_reply.started":"2025-08-11T04:57:48.838650Z","shell.execute_reply":"2025-08-11T04:57:49.406655Z"}},"outputs":[],"execution_count":null},{"id":"21a74895","cell_type":"code","source":"train = train.iloc[:, :-325]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-11T04:57:49.408215Z","iopub.execute_input":"2025-08-11T04:57:49.408421Z","iopub.status.idle":"2025-08-11T04:57:49.467187Z","shell.execute_reply.started":"2025-08-11T04:57:49.408405Z","shell.execute_reply":"2025-08-11T04:57:49.466480Z"}},"outputs":[],"execution_count":null},{"id":"208f222a","cell_type":"code","source":"# DatasetとDataLoaderのインポート\nfrom torch.utils.data import DataLoader\nfrom dataset import SubjectDataset, custom_collate_fn\n\ntrain_dataset = SubjectDataset(train_demo, train, drop_cols=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-11T04:57:49.467872Z","iopub.execute_input":"2025-08-11T04:57:49.468101Z","iopub.status.idle":"2025-08-11T04:57:53.545309Z","shell.execute_reply.started":"2025-08-11T04:57:49.468081Z","shell.execute_reply":"2025-08-11T04:57:53.544528Z"}},"outputs":[],"execution_count":null},{"id":"b24bbdac","cell_type":"code","source":"import pandas as pd\nimport numpy as np\nfrom scipy.optimize import minimize_scalar\n\ndef calculate_dynamic_acceleration2(train):\n    quaternions = train[['rot_w', 'rot_x', 'rot_y', 'rot_z']].values.astype(np.float64)\n    accelerations = train[['acc_x', 'acc_y', 'acc_z']].values.astype(np.float64)\n    \n    norms = np.linalg.norm(quaternions, axis=1, keepdims=True)\n    quaternions /= norms\n\n    w, x, y, z = quaternions.T\n\n    R_sensor = np.zeros((len(train), 3, 3))\n    R_sensor[:, 0, 0] = 1 - 2*y**2 - 2*z**2\n    R_sensor[:, 0, 1] = 2*x*y - 2*z*w\n    R_sensor[:, 0, 2] = 2*x*z + 2*y*w\n    R_sensor[:, 1, 0] = 2*x*y + 2*z*w\n    R_sensor[:, 1, 1] = 1 - 2*x**2 - 2*z**2\n    R_sensor[:, 1, 2] = 2*y*z - 2*x*w\n    R_sensor[:, 2, 0] = 2*x*z - 2*y*w\n    R_sensor[:, 2, 1] = 2*y*z + 2*x*w\n    R_sensor[:, 2, 2] = 1 - 2*x**2 - 2*y**2\n    \n    gravity_vector = np.array([0, 0, 9.8])\n    rotated_gravity = np.einsum('nij, j->ni', R_sensor, gravity_vector)\n\n    def objective_function(phi, acc_all, grav_rot_all):\n        n = len(acc_all)\n        trim_size = int(n * 0.3)\n        if trim_size == 0:\n            return 0.0\n            \n        cos_phi, sin_phi = np.cos(phi), np.sin(phi)\n        R_z = np.array([[cos_phi, -sin_phi, 0],\n                        [sin_phi,  cos_phi, 0],\n                        [      0,        0, 1]])\n\n        acc_rotated = np.einsum('ij, kj->ki', R_z, acc_all)\n        dynamic_acc = acc_rotated - grav_rot_all\n        \n        last_30_percent_sum = np.sum(np.abs(dynamic_acc[-trim_size:]))\n        return last_30_percent_sum\n    \n    # ここからループを削除した修正\n    acc_vector = train[['acc_x', 'acc_y', 'acc_z']].values\n    \n    if len(acc_vector) == 0 or len(acc_vector) < 2:\n        return train.copy()\n            \n    optimized_phi = minimize_scalar(\n        objective_function,\n        bounds=(0, 2 * np.pi),\n        args=(acc_vector, rotated_gravity)\n    ).x\n    \n    cos_phi, sin_phi = np.cos(optimized_phi), np.sin(optimized_phi)\n    R_z_opt = np.array([[cos_phi, -sin_phi, 0],\n                        [sin_phi,  cos_phi, 0],\n                        [      0,        0, 1]])\n    \n    acc_rotated = np.einsum('ij, kj->ki', R_z_opt, acc_vector)\n    dynamic_acceleration = acc_rotated - rotated_gravity\n    \n    result_df = train.copy()\n    result_df['acc_x_dynamic'] = dynamic_acceleration[:, 0]\n    result_df['acc_y_dynamic'] = dynamic_acceleration[:, 1]\n    result_df['acc_z_dynamic'] = dynamic_acceleration[:, 2]\n\n    result_df['gravity_x'] = rotated_gravity[:, 0]\n    result_df['gravity_y'] = rotated_gravity[:, 1]\n    result_df['gravity_z'] = rotated_gravity[:, 2]\n\n    return result_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-11T04:57:53.547479Z","iopub.execute_input":"2025-08-11T04:57:53.547710Z","iopub.status.idle":"2025-08-11T04:57:53.992963Z","shell.execute_reply.started":"2025-08-11T04:57:53.547693Z","shell.execute_reply":"2025-08-11T04:57:53.992243Z"}},"outputs":[],"execution_count":null},{"id":"e043535c","cell_type":"code","source":"count = 0\nfor demo, data, label in train_dataset:\n    data = calculate_dynamic_acceleration2(data)\n    if np.random.rand() < 0.5:\n        plot_sequence(data)\n        count += 1\n        if count >= 4:\n            break","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-11T04:57:53.993708Z","iopub.execute_input":"2025-08-11T04:57:53.994066Z","iopub.status.idle":"2025-08-11T04:57:59.855344Z","shell.execute_reply.started":"2025-08-11T04:57:53.994048Z","shell.execute_reply":"2025-08-11T04:57:59.854457Z"}},"outputs":[],"execution_count":null}]}