{"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,"sourceType":"competition"},{"sourceId":12411879,"sourceType":"datasetVersion","datasetId":7827797,"isSourceIdPinned":false}],"dockerImageVersionId":31089,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os, json, joblib, numpy as np, pandas as pd\nfrom pathlib import Path\nimport warnings \nwarnings.filterwarnings(\"ignore\")\n\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import StandardScaler, LabelEncoder\nfrom sklearn.utils.class_weight import compute_class_weight\n\nfrom tensorflow.keras.utils import Sequence, to_categorical, pad_sequences\nfrom tensorflow.keras.models import Model, load_model\nfrom tensorflow.keras.layers import (\n    Input, Conv1D, BatchNormalization, Activation, add, MaxPooling1D, Dropout,\n    Bidirectional, LSTM, GlobalAveragePooling1D, Dense, Multiply, Reshape,\n    Lambda, Concatenate, GRU, GaussianNoise\n)\nfrom tensorflow.keras.regularizers import l2\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.callbacks import EarlyStopping\nfrom tensorflow.keras import backend as K\nimport tensorflow as tf\nimport polars as pl\nfrom sklearn.model_selection import StratifiedGroupKFold\nfrom scipy.spatial.transform import Rotation as R","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-08-06T10:21:51.464472Z","iopub.execute_input":"2025-08-06T10:21:51.464761Z","iopub.status.idle":"2025-08-06T10:22:11.374559Z","shell.execute_reply.started":"2025-08-06T10:21:51.464737Z","shell.execute_reply":"2025-08-06T10:22:11.373667Z"}},"outputs":[{"name":"stderr","text":"2025-08-06 10:21:54.695840: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:477] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered\nWARNING: All log messages before absl::InitializeLog() is called are written to STDERR\nE0000 00:00:1754475714.953065      36 cuda_dnn.cc:8310] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered\nE0000 00:00:1754475715.028766      36 cuda_blas.cc:1418] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n","output_type":"stream"}],"execution_count":1},{"cell_type":"code","source":"import random\ndef seed_everything(seed):\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    random.seed(seed)\n    np.random.seed(seed)\n    tf.random.set_seed(seed)\n    tf.experimental.numpy.random.seed(seed)\n    os.environ['TF_CUDNN_DETERMINISTIC'] = '1'\n    os.environ['TF_DETERMINISTIC_OPS'] = '1'\nseed_everything(seed=42)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T10:22:11.375926Z","iopub.execute_input":"2025-08-06T10:22:11.376502Z","iopub.status.idle":"2025-08-06T10:22:11.382848Z","shell.execute_reply.started":"2025-08-06T10:22:11.376478Z","shell.execute_reply":"2025-08-06T10:22:11.381645Z"}},"outputs":[],"execution_count":2},{"cell_type":"code","source":"# (Competition metric will only be imported when TRAINing)\nTRAIN = False                     # ← set to True when you want to train\nRAW_DIR = Path(\"/kaggle/input/cmi-detect-behavior-with-sensor-data\")\nPRETRAINED_DIR = Path(\"/kaggle/input/cmi-d-111\")\nEXPORT_DIR = Path(\"./\")                                    # artefacts will be saved here\nBATCH_SIZE = 64\nPAD_PERCENTILE = 95\nLR_INIT = 5e-4\nWD = 3e-3\nMIXUP_ALPHA = 0.4\nEPOCHS = 160\nPATIENCE = 40\n\n\nprint(\"▶ imports ready · tensorflow\", tf.__version__)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T10:22:11.384143Z","iopub.execute_input":"2025-08-06T10:22:11.384720Z","iopub.status.idle":"2025-08-06T10:22:11.538259Z","shell.execute_reply.started":"2025-08-06T10:22:11.384685Z","shell.execute_reply":"2025-08-06T10:22:11.537249Z"}},"outputs":[{"name":"stdout","text":"▶ imports ready · tensorflow 2.18.0\n","output_type":"stream"}],"execution_count":3},{"cell_type":"code","source":"#Tensor Manipulations\ndef time_sum(x):\n    return K.sum(x, axis=1)\n\ndef squeeze_last_axis(x):\n    return tf.squeeze(x, axis=-1)\n\ndef expand_last_axis(x):\n    return tf.expand_dims(x, axis=-1)\n\ndef se_block(x, reduction=8):\n    ch = x.shape[-1]\n    se = GlobalAveragePooling1D()(x)\n    se = Dense(ch // reduction, activation='relu')(se)\n    se = Dense(ch, activation='sigmoid')(se)\n    se = Reshape((1, ch))(se)\n    return Multiply()([x, se])\n\n# Residual CNN Block with SE\ndef residual_se_cnn_block(x, filters, kernel_size, pool_size=2, drop=0.3, wd=1e-4):\n    shortcut = x\n    for _ in range(2):\n        x = Conv1D(filters, kernel_size, padding='same', use_bias=False,\n                   kernel_regularizer=l2(wd))(x)\n        x = BatchNormalization()(x)\n        x = Activation('relu')(x)\n    x = se_block(x)\n    if shortcut.shape[-1] != filters:\n        shortcut = Conv1D(filters, 1, padding='same', use_bias=False,\n                          kernel_regularizer=l2(wd))(shortcut)\n        shortcut = BatchNormalization()(shortcut)\n    x = add([x, shortcut])\n    x = Activation('relu')(x)\n    x = MaxPooling1D(pool_size)(x)\n    x = Dropout(drop)(x)\n    return x\n\ndef attention_layer(inputs):\n    score = Dense(1, activation='tanh')(inputs)\n    score = Lambda(squeeze_last_axis)(score)\n    weights = Activation('softmax')(score)\n    weights = Lambda(expand_last_axis)(weights)\n    context = Multiply()([inputs, weights])\n    context = Lambda(time_sum)(context)\n    return context","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T10:22:11.540265Z","iopub.execute_input":"2025-08-06T10:22:11.540568Z","iopub.status.idle":"2025-08-06T10:22:11.563045Z","shell.execute_reply.started":"2025-08-06T10:22:11.540544Z","shell.execute_reply":"2025-08-06T10:22:11.561897Z"}},"outputs":[],"execution_count":4},{"cell_type":"code","source":"# Normalizes and cleans the time series sequence. \n\ndef preprocess_sequence(df_seq: pd.DataFrame, feature_cols: list[str], scaler: StandardScaler):\n    mat = df_seq[feature_cols].ffill().bfill().fillna(0).values\n    return scaler.transform(mat).astype('float32')\n\n# MixUp the data argumentation in order to regularize the neural network. \n\nclass MixupGenerator(Sequence):\n    def __init__(self, X, y, batch_size, alpha=0.2):\n        self.X, self.y = X, y\n        self.batch = batch_size\n        self.alpha = alpha\n        self.indices = np.arange(len(X))\n    def __len__(self):\n        return int(np.ceil(len(self.X) / self.batch))\n    def __getitem__(self, i):\n        idx = self.indices[i*self.batch:(i+1)*self.batch]\n        Xb, yb = self.X[idx], self.y[idx]\n        lam = np.random.beta(self.alpha, self.alpha)\n        perm = np.random.permutation(len(Xb))\n        X_mix = lam * Xb + (1-lam) * Xb[perm]\n        y_mix = lam * yb + (1-lam) * yb[perm]\n        return X_mix, y_mix\n    def on_epoch_end(self):\n        np.random.shuffle(self.indices)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T10:22:11.563932Z","iopub.execute_input":"2025-08-06T10:22:11.564240Z","iopub.status.idle":"2025-08-06T10:22:11.578880Z","shell.execute_reply.started":"2025-08-06T10:22:11.564212Z","shell.execute_reply":"2025-08-06T10:22:11.578040Z"}},"outputs":[],"execution_count":5},{"cell_type":"code","source":"def remove_gravity_from_acc(acc_data, rot_data):\n\n    if isinstance(acc_data, pd.DataFrame):\n        acc_values = acc_data[['acc_x', 'acc_y', 'acc_z']].values\n    else:\n        acc_values = acc_data\n\n    if isinstance(rot_data, pd.DataFrame):\n        quat_values = rot_data[['rot_x', 'rot_y', 'rot_z', 'rot_w']].values\n    else:\n        quat_values = rot_data\n\n    num_samples = acc_values.shape[0]\n    linear_accel = np.zeros_like(acc_values)\n    \n    gravity_world = np.array([0, 0, 9.81])\n\n    for i in range(num_samples):\n        if np.all(np.isnan(quat_values[i])) or np.all(np.isclose(quat_values[i], 0)):\n            linear_accel[i, :] = acc_values[i, :] \n            continue\n\n        try:\n            rotation = R.from_quat(quat_values[i])\n            gravity_sensor_frame = rotation.apply(gravity_world, inverse=True)\n            linear_accel[i, :] = acc_values[i, :] - gravity_sensor_frame\n        except ValueError:\n             linear_accel[i, :] = acc_values[i, :]\n             \n    return linear_accel\n\ndef calculate_angular_velocity_from_quat(rot_data, time_delta=1/200): # Assuming 200Hz sampling rate\n    if isinstance(rot_data, pd.DataFrame):\n        quat_values = rot_data[['rot_x', 'rot_y', 'rot_z', 'rot_w']].values\n    else:\n        quat_values = rot_data\n\n    num_samples = quat_values.shape[0]\n    angular_vel = np.zeros((num_samples, 3))\n\n    for i in range(num_samples - 1):\n        q_t = quat_values[i]\n        q_t_plus_dt = quat_values[i+1]\n\n        if np.all(np.isnan(q_t)) or np.all(np.isclose(q_t, 0)) or \\\n           np.all(np.isnan(q_t_plus_dt)) or np.all(np.isclose(q_t_plus_dt, 0)):\n            continue\n\n        try:\n            rot_t = R.from_quat(q_t)\n            rot_t_plus_dt = R.from_quat(q_t_plus_dt)\n\n            # Calculate the relative rotation\n            delta_rot = rot_t.inv() * rot_t_plus_dt\n            \n            # Convert delta rotation to angular velocity vector\n            # The rotation vector (Euler axis * angle) scaled by 1/dt\n            # is a good approximation for small delta_rot\n            angular_vel[i, :] = delta_rot.as_rotvec() / time_delta\n        except ValueError:\n            # If quaternion is invalid, angular velocity remains zero\n            pass\n            \n    return angular_vel","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T10:22:11.579969Z","iopub.execute_input":"2025-08-06T10:22:11.580261Z","iopub.status.idle":"2025-08-06T10:22:11.604349Z","shell.execute_reply.started":"2025-08-06T10:22:11.580240Z","shell.execute_reply":"2025-08-06T10:22:11.603267Z"}},"outputs":[],"execution_count":6},{"cell_type":"code","source":"def calculate_angular_distance(rot_data):\n    if isinstance(rot_data, pd.DataFrame):\n        quat_values = rot_data[['rot_x', 'rot_y', 'rot_z', 'rot_w']].values\n    else:\n        quat_values = rot_data\n\n    num_samples = quat_values.shape[0]\n    angular_dist = np.zeros(num_samples)\n\n    for i in range(num_samples - 1):\n        q1 = quat_values[i]\n        q2 = quat_values[i+1]\n\n        if np.all(np.isnan(q1)) or np.all(np.isclose(q1, 0)) or \\\n           np.all(np.isnan(q2)) or np.all(np.isclose(q2, 0)):\n            angular_dist[i] = 0 # Или np.nan, в зависимости от желаемого поведения\n            continue\n        try:\n            # Преобразование кватернионов в объекты Rotation\n            r1 = R.from_quat(q1)\n            r2 = R.from_quat(q2)\n\n            # Вычисление углового расстояния: 2 * arccos(|real(p * q*)|)\n            # где p* - сопряженный кватернион q\n            # В scipy.spatial.transform.Rotation, r1.inv() * r2 дает относительное вращение.\n            # Угол этого относительного вращения - это и есть угловое расстояние.\n            relative_rotation = r1.inv() * r2\n            \n            # Угол rotation vector соответствует угловому расстоянию\n            # Норма rotation vector - это угол в радианах\n            angle = np.linalg.norm(relative_rotation.as_rotvec())\n            angular_dist[i] = angle\n        except ValueError:\n            angular_dist[i] = 0 # В случае недействительных кватернионов\n            pass\n            \n    return angular_dist","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T10:22:11.605467Z","iopub.execute_input":"2025-08-06T10:22:11.605853Z","iopub.status.idle":"2025-08-06T10:22:11.630904Z","shell.execute_reply.started":"2025-08-06T10:22:11.605797Z","shell.execute_reply":"2025-08-06T10:22:11.630009Z"}},"outputs":[],"execution_count":7},{"cell_type":"code","source":"def build_two_branch_model(pad_len, imu_dim, tof_dim, n_classes, wd=1e-4):\n    inp = Input(shape=(pad_len, imu_dim+tof_dim))\n    imu = Lambda(lambda t: t[:, :, :imu_dim])(inp)\n    tof = Lambda(lambda t: t[:, :, imu_dim:])(inp)\n\n    # IMU deep branch\n    x1 = residual_se_cnn_block(imu, 64, 3, drop=0.1, wd=wd)\n    x1 = residual_se_cnn_block(x1, 128, 5, drop=0.1, wd=wd)\n\n    # TOF/Thermal lighter branch\n    x2 = Conv1D(64, 3, padding='same', use_bias=False, kernel_regularizer=l2(wd))(tof)\n    x2 = BatchNormalization()(x2); x2 = Activation('relu')(x2)\n    x2 = MaxPooling1D(2)(x2); x2 = Dropout(0.2)(x2)\n    x2 = Conv1D(128, 3, padding='same', use_bias=False, kernel_regularizer=l2(wd))(x2)\n    x2 = BatchNormalization()(x2); x2 = Activation('relu')(x2)\n    x2 = MaxPooling1D(2)(x2); x2 = Dropout(0.2)(x2)\n\n    merged = Concatenate()([x1, x2])\n\n    xa = Bidirectional(LSTM(128, return_sequences=True, kernel_regularizer=l2(wd)))(merged)\n    xb = Bidirectional(GRU(128, return_sequences=True, kernel_regularizer=l2(wd)))(merged)\n    xc = GaussianNoise(0.09)(merged)\n    xc = Dense(16, activation='elu')(xc)\n    \n    x = Concatenate()([xa, xb, xc])\n    x = Dropout(0.4)(x)\n    x = attention_layer(x)\n\n    for units, drop in [(256, 0.5), (128, 0.3)]:\n        x = Dense(units, use_bias=False, kernel_regularizer=l2(wd))(x)\n        x = BatchNormalization()(x); x = Activation('relu')(x)\n        x = Dropout(drop)(x)\n\n    out = Dense(n_classes, activation='softmax', kernel_regularizer=l2(wd))(x)\n    return Model(inp, out)\n\ntmp_model = build_two_branch_model(127,7,325,18)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T10:22:11.632292Z","iopub.execute_input":"2025-08-06T10:22:11.632891Z","iopub.status.idle":"2025-08-06T10:22:12.168044Z","shell.execute_reply.started":"2025-08-06T10:22:11.632855Z","shell.execute_reply":"2025-08-06T10:22:12.167235Z"}},"outputs":[{"name":"stderr","text":"2025-08-06 10:22:11.686491: E external/local_xla/xla/stream_executor/cuda/cuda_driver.cc:152] failed call to cuInit: INTERNAL: CUDA error: Failed call to cuInit: UNKNOWN ERROR (303)\n","output_type":"stream"}],"execution_count":8},{"cell_type":"code","source":"print(\"▶ INFERENCE MODE – loading artefacts from\", PRETRAINED_DIR)\nfinal_feature_cols = np.load(PRETRAINED_DIR / \"feature_cols.npy\", allow_pickle=True).tolist()\npad_len        = int(np.load(PRETRAINED_DIR / \"sequence_maxlen.npy\"))\nscaler         = joblib.load(PRETRAINED_DIR / \"scaler.pkl\")\ngesture_classes = np.load(PRETRAINED_DIR / \"gesture_classes.npy\", allow_pickle=True)\n\n\ncustom_objs = {\n    'time_sum': time_sum, 'squeeze_last_axis': squeeze_last_axis, 'expand_last_axis': expand_last_axis,\n    'se_block': se_block, 'residual_se_cnn_block': residual_se_cnn_block, 'attention_layer': attention_layer,\n}\n\n# ----------------------------------------------------------------- #\n# Load any Models\n# * is 2 Train Model Load\n# ----------------------------------------------------------------- #\n\nmodels = []\nprint(f\"  Loading models for ensemble inference...\")\nfor fold in range(10):\n    MODEL_DIR = \"/kaggle/input/cmi-d-111\"\n    \n    model_path = f\"{MODEL_DIR}/D-111_{fold}.h5\"\n    print(\">>>LoadModel>>>\",model_path)\n    model = load_model(model_path, compile=False, custom_objects=custom_objs)\n    models.append(model)\nprint(\"-\"*50)\n\nfor fold in range(10):\n    MODEL_DIR = \"/kaggle/input/cmi-d-111\"\n    \n    model_path = f\"{MODEL_DIR}/v0629_{fold}.h5\"\n    print(\">>>LoadModel>>>\",model_path)\n    model = load_model(model_path, compile=False, custom_objects=custom_objs)\n    models.append(model)\nprint(\"-\"*50)\nprint(f\"[INFO]NumUseModels:{len(models)}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T10:22:12.168919Z","iopub.execute_input":"2025-08-06T10:22:12.169188Z","iopub.status.idle":"2025-08-06T10:22:26.037222Z","shell.execute_reply.started":"2025-08-06T10:22:12.169151Z","shell.execute_reply":"2025-08-06T10:22:26.036298Z"}},"outputs":[{"name":"stdout","text":"▶ INFERENCE MODE – loading artefacts from /kaggle/input/cmi-d-111\n  Loading models for ensemble inference...\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_0.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_1.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_2.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_3.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_4.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_5.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_6.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_7.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_8.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_9.h5\n--------------------------------------------------\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_0.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_1.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_2.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_3.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_4.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_5.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_6.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_7.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_8.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_9.h5\n--------------------------------------------------\n[INFO]NumUseModels:20\n","output_type":"stream"}],"execution_count":9},{"cell_type":"code","source":"import kagglehub\nfrom pathlib import Path\n\n# ▼▼▼ 修正点1: kagglehubを使ってデータセットをダウンロードし、パスを取得 ▼▼▼\n# この関数が、必要なファイル群が保存されているディレクトリのパスを返してくれます。\nprint(\"Downloading dataset using kagglehub...\")\ndataset_path = kagglehub.dataset_download(\"hideyukizushi/cmi-d-111\")\nprint(\"Dataset downloaded to:\", dataset_path)\n\n# ▼▼▼ 修正点2: PRETRAINED_DIRとMODEL_DIRを、取得したパスに設定 ▼▼▼\n# これにより、ファイルが見つからないエラーが解消されます。\nPRETRAINED_DIR = Path(dataset_path)\nMODEL_DIR = Path(dataset_path)\n\n# --- 以下は元のコードと同じ ---\n\nprint(\"▶ INFERENCE MODE – loading artefacts from\", PRETRAINED_DIR)\nfinal_feature_cols = np.load(PRETRAINED_DIR / \"feature_cols.npy\", allow_pickle=True).tolist()\npad_len          = int(np.load(PRETRAINED_DIR / \"sequence_maxlen.npy\"))\nscaler           = joblib.load(PRETRAINED_DIR / \"scaler.pkl\")\ngesture_classes  = np.load(PRETRAINED_DIR / \"gesture_classes.npy\", allow_pickle=True)\n\ncustom_objs = {\n    'time_sum': time_sum, 'squeeze_last_axis': squeeze_last_axis, 'expand_last_axis': expand_last_axis,\n    'se_block': se_block, 'residual_se_cnn_block': residual_se_cnn_block, 'attention_layer': attention_layer,\n}\n\n# ----------------------------------------------------------------- #\n# Load any Models\n# * is 2 Train Model Load\n# ----------------------------------------------------------------- #\n\nmodels = []\nprint(f\"  Loading models for ensemble inference...\")\n# 1つ目のモデルセットをロード\nfor fold in range(10):\n    # MODEL_DIRは上で設定済みなので、ここの定義は不要\n    model_path = MODEL_DIR / f\"D-111_{fold}.h5\"\n    print(\">>>LoadModel>>>\", str(model_path))\n    model = load_model(str(model_path), compile=False, custom_objects=custom_objs)\n    models.append(model)\nprint(\"-\"*50)\n\n# 2つ目のモデルセットをロード\nfor fold in range(10):\n    # MODEL_DIRは上で設定済みなので、ここの定義は不要\n    model_path = MODEL_DIR / f\"v0629_{fold}.h5\"\n    print(\">>>LoadModel>>>\", str(model_path))\n    model = load_model(str(model_path), compile=False, custom_objects=custom_objs)\n    models.append(model)\nprint(\"-\"*50)\nprint(f\"[INFO]NumUseModels:{len(models)}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T10:22:26.039222Z","iopub.execute_input":"2025-08-06T10:22:26.039715Z","iopub.status.idle":"2025-08-06T10:22:38.427458Z","shell.execute_reply.started":"2025-08-06T10:22:26.039689Z","shell.execute_reply":"2025-08-06T10:22:38.426239Z"}},"outputs":[{"name":"stdout","text":"Downloading dataset using kagglehub...\nDataset downloaded to: /kaggle/input/cmi-d-111\n▶ INFERENCE MODE – loading artefacts from /kaggle/input/cmi-d-111\n  Loading models for ensemble inference...\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_0.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_1.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_2.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_3.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_4.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_5.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_6.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_7.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_8.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/D-111_9.h5\n--------------------------------------------------\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_0.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_1.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_2.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_3.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_4.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_5.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_6.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_7.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_8.h5\n>>>LoadModel>>> /kaggle/input/cmi-d-111/v0629_9.h5\n--------------------------------------------------\n[INFO]NumUseModels:20\n","output_type":"stream"}],"execution_count":10},{"cell_type":"code","source":"def predict(sequence: pl.DataFrame, demographics: pl.DataFrame) -> str:\n    df_seq = sequence.to_pandas()\n    linear_accel = remove_gravity_from_acc(df_seq, df_seq)\n    df_seq['linear_acc_x'], df_seq['linear_acc_y'], df_seq['linear_acc_z'] = linear_accel[:, 0], linear_accel[:, 1], linear_accel[:, 2]\n    df_seq['linear_acc_mag'] = np.sqrt(df_seq['linear_acc_x']**2 + df_seq['linear_acc_y']**2 + df_seq['linear_acc_z']**2)\n    df_seq['linear_acc_mag_jerk'] = df_seq['linear_acc_mag'].diff().fillna(0)\n    angular_vel = calculate_angular_velocity_from_quat(df_seq)\n    df_seq['angular_vel_x'], df_seq['angular_vel_y'], df_seq['angular_vel_z'] = angular_vel[:, 0], angular_vel[:, 1], angular_vel[:, 2]\n    df_seq['angular_distance'] = calculate_angular_distance(df_seq)\n    \n    for i in range(1, 6):\n        pixel_cols = [f\"tof_{i}_v{p}\" for p in range(64)]; tof_data = df_seq[pixel_cols].replace(-1, np.nan)\n        df_seq[f'tof_{i}_mean'], df_seq[f'tof_{i}_std'], df_seq[f'tof_{i}_min'], df_seq[f'tof_{i}_max'] = tof_data.mean(axis=1), tof_data.std(axis=1), tof_data.min(axis=1), tof_data.max(axis=1)\n        \n    mat_unscaled = df_seq[final_feature_cols].ffill().bfill().fillna(0).values.astype('float32')\n    mat_scaled = scaler.transform(mat_unscaled)\n    pad_input = pad_sequences([mat_scaled], maxlen=pad_len, padding='post', truncating='post', dtype='float32')\n    \n    all_preds = [model.predict(pad_input, verbose=0)[0] for model in models] # 主出力のみ取得\n    avg_pred = np.mean(all_preds, axis=0)\n    return str(gesture_classes[avg_pred.argmax()])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T10:23:37.111482Z","iopub.execute_input":"2025-08-06T10:23:37.111819Z","iopub.status.idle":"2025-08-06T10:23:37.124379Z","shell.execute_reply.started":"2025-08-06T10:23:37.111794Z","shell.execute_reply":"2025-08-06T10:23:37.123475Z"}},"outputs":[],"execution_count":11},{"cell_type":"code","source":"import kaggle_evaluation.cmi_inference_server\ninference_server = kaggle_evaluation.cmi_inference_server.CMIInferenceServer(predict)\n\nif os.getenv('KAGGLE_IS_COMPETITION_RERUN'):\n    inference_server.serve()\nelse:\n    inference_server.run_local_gateway(\n        data_paths=(\n            '/kaggle/input/cmi-detect-behavior-with-sensor-data/test.csv',\n            '/kaggle/input/cmi-detect-behavior-with-sensor-data/test_demographics.csv',\n        )\n    )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T10:24:09.274207Z","iopub.execute_input":"2025-08-06T10:24:09.274540Z","iopub.status.idle":"2025-08-06T10:24:47.312397Z","shell.execute_reply.started":"2025-08-06T10:24:09.274516Z","shell.execute_reply":"2025-08-06T10:24:47.311540Z"}},"outputs":[{"name":"stderr","text":"2025-08-06 10:24:10.784877: E tensorflow/core/framework/node_def_util.cc:676] NodeDef mentions attribute use_unbounded_threadpool which is not in the op definition: Op<name=MapDataset; signature=input_dataset:variant, other_arguments: -> handle:variant; attr=f:func; attr=Targuments:list(type),min=0; attr=output_types:list(type),min=1; attr=output_shapes:list(shape),min=1; attr=use_inter_op_parallelism:bool,default=true; attr=preserve_cardinality:bool,default=false; attr=force_synchronous:bool,default=false; attr=metadata:string,default=\"\"> This may be expected if your graph generating binary is newer  than this binary. Unknown attributes will be ignored. NodeDef: {{node ParallelMapDatasetV2/_14}}\n2025-08-06 10:24:16.091785: E tensorflow/core/framework/node_def_util.cc:676] NodeDef mentions attribute use_unbounded_threadpool which is not in the op definition: Op<name=MapDataset; signature=input_dataset:variant, other_arguments: -> handle:variant; attr=f:func; attr=Targuments:list(type),min=0; attr=output_types:list(type),min=1; attr=output_shapes:list(shape),min=1; attr=use_inter_op_parallelism:bool,default=true; attr=preserve_cardinality:bool,default=false; attr=force_synchronous:bool,default=false; attr=metadata:string,default=\"\"> This may be expected if your graph generating binary is newer  than this binary. Unknown attributes will be ignored. NodeDef: {{node ParallelMapDatasetV2/_14}}\n2025-08-06 10:24:22.879597: E tensorflow/core/framework/node_def_util.cc:676] NodeDef mentions attribute use_unbounded_threadpool which is not in the op definition: Op<name=MapDataset; signature=input_dataset:variant, other_arguments: -> handle:variant; attr=f:func; attr=Targuments:list(type),min=0; attr=output_types:list(type),min=1; attr=output_shapes:list(shape),min=1; attr=use_inter_op_parallelism:bool,default=true; attr=preserve_cardinality:bool,default=false; attr=force_synchronous:bool,default=false; attr=metadata:string,default=\"\"> This may be expected if your graph generating binary is newer  than this binary. Unknown attributes will be ignored. NodeDef: {{node ParallelMapDatasetV2/_14}}\n2025-08-06 10:24:29.221821: E tensorflow/core/framework/node_def_util.cc:676] NodeDef mentions attribute use_unbounded_threadpool which is not in the op definition: Op<name=MapDataset; signature=input_dataset:variant, other_arguments: -> handle:variant; attr=f:func; attr=Targuments:list(type),min=0; attr=output_types:list(type),min=1; attr=output_shapes:list(shape),min=1; attr=use_inter_op_parallelism:bool,default=true; attr=preserve_cardinality:bool,default=false; attr=force_synchronous:bool,default=false; attr=metadata:string,default=\"\"> This may be expected if your graph generating binary is newer  than this binary. Unknown attributes will be ignored. NodeDef: {{node ParallelMapDatasetV2/_14}}\n2025-08-06 10:24:34.443093: E tensorflow/core/framework/node_def_util.cc:676] NodeDef mentions attribute use_unbounded_threadpool which is not in the op definition: Op<name=MapDataset; signature=input_dataset:variant, other_arguments: -> handle:variant; attr=f:func; attr=Targuments:list(type),min=0; attr=output_types:list(type),min=1; attr=output_shapes:list(shape),min=1; attr=use_inter_op_parallelism:bool,default=true; attr=preserve_cardinality:bool,default=false; attr=force_synchronous:bool,default=false; attr=metadata:string,default=\"\"> This may be expected if your graph generating binary is newer  than this binary. Unknown attributes will be ignored. NodeDef: {{node ParallelMapDatasetV2/_14}}\n2025-08-06 10:24:41.351089: E tensorflow/core/framework/node_def_util.cc:676] NodeDef mentions attribute use_unbounded_threadpool which is not in the op definition: Op<name=MapDataset; signature=input_dataset:variant, other_arguments: -> handle:variant; attr=f:func; attr=Targuments:list(type),min=0; attr=output_types:list(type),min=1; attr=output_shapes:list(shape),min=1; attr=use_inter_op_parallelism:bool,default=true; attr=preserve_cardinality:bool,default=false; attr=force_synchronous:bool,default=false; attr=metadata:string,default=\"\"> This may be expected if your graph generating binary is newer  than this binary. Unknown attributes will be ignored. NodeDef: {{node ParallelMapDatasetV2/_14}}\n2025-08-06 10:24:46.401498: E tensorflow/core/framework/node_def_util.cc:676] NodeDef mentions attribute use_unbounded_threadpool which is not in the op definition: Op<name=MapDataset; signature=input_dataset:variant, other_arguments: -> handle:variant; attr=f:func; attr=Targuments:list(type),min=0; attr=output_types:list(type),min=1; attr=output_shapes:list(shape),min=1; attr=use_inter_op_parallelism:bool,default=true; attr=preserve_cardinality:bool,default=false; attr=force_synchronous:bool,default=false; attr=metadata:string,default=\"\"> This may be expected if your graph generating binary is newer  than this binary. Unknown attributes will be ignored. NodeDef: {{node ParallelMapDatasetV2/_14}}\n","output_type":"stream"}],"execution_count":12},{"cell_type":"code","source":"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T10:26:16.396414Z","iopub.execute_input":"2025-08-06T10:26:16.396770Z","iopub.status.idle":"2025-08-06T10:26:16.403680Z","shell.execute_reply.started":"2025-08-06T10:26:16.396745Z","shell.execute_reply":"2025-08-06T10:26:16.402679Z"}},"outputs":[{"execution_count":13,"output_type":"execute_result","data":{"text/plain":"<kaggle_evaluation.cmi_inference_server.CMIInferenceServer at 0x7b3b5be465d0>"},"metadata":{}}],"execution_count":13},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}