{"cells": [{"cell_type": "markdown", "metadata": {}, "source": "# CMI V11 Fixed: \u5408\u6210\u30c7\u30fc\u30bf\u306b\u3088\u308b\u4e8b\u524d\u5b66\u7fd2\u6e08\u307f\u30e2\u30c7\u30eb\u69cb\u7bc9\n\n\u5b9f\u30c7\u30fc\u30bf50% + \u5408\u6210\u30c6\u30b9\u30c8\u30c7\u30fc\u30bf50%\u3067\u30c8\u30ec\u30fc\u30cb\u30f3\u30b0\u3057\u3001Kaggle Dataset\u3068\u3057\u3066\u4fdd\u5b58"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "import numpy as np\nimport pandas as pd\nimport os\nfrom pathlib import Path\nimport json\nimport pickle\nimport warnings\nfrom sklearn.model_selection import train_test_split, StratifiedKFold\nfrom sklearn.preprocessing import StandardScaler, LabelEncoder\nfrom sklearn.metrics import accuracy_score, classification_report\nfrom sklearn.ensemble import RandomForestClassifier, VotingClassifier\nimport lightgbm as lgb\nimport xgboost as xgb\nfrom catboost import CatBoostClassifier\n\nwarnings.filterwarnings(\"ignore\")\nprint(\"Libraries imported successfully\")"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "# \u30c7\u30fc\u30bf\u30d1\u30b9\u8a2d\u5b9a\uff08\u7af6\u6280\u30c7\u30fc\u30bf\u30bb\u30c3\u30c8\u53c2\u7167\uff09\nDATA_DIR = Path(\"/kaggle/input/cmi-detect-behavior-with-sensor-data\")\n\n# train.csv\u306e\u8aad\u307f\u8fbc\u307f\uff08\u6642\u7cfb\u5217\u30c7\u30fc\u30bf\uff09\nprint(\"Loading CMI competition data...\")\ntrain_data = pd.read_csv(DATA_DIR / \"train.csv\")\nprint(f\"  Loaded train.csv: {len(train_data)} rows\")\n\n# sequence_id\u3067\u30b0\u30eb\u30fc\u30d7\u5316\u3057\u3066\u30e1\u30bf\u30c7\u30fc\u30bf\u4f5c\u6210\ntrain_metadata = (\n    train_data.groupby(\"sequence_id\")\n    .agg({\"subject\": \"first\", \"gesture\": \"first\", \"sequence_counter\": \"count\"})\n    .reset_index()\n)\ntrain_metadata.columns = [\"sequence_id\", \"subject\", \"gesture\", \"sequence_length\"]\n\n# \u30b8\u30a7\u30b9\u30c1\u30e3\u30fc\u306e\u30e9\u30d9\u30eb\u30de\u30c3\u30d4\u30f3\u30b0\u4f5c\u6210\uff08\u91cd\u8981\uff01\uff09\ngesture_labels = sorted(train_metadata[\"gesture\"].unique())\ngesture_to_id = {label: i for i, label in enumerate(gesture_labels)}\nid_to_gesture = {i: label for label, i in gesture_to_id.items()}\n\nprint(f\"\\\\nData loaded successfully:\")\nprint(f\"  Total sequences: {len(train_metadata)}\")\nprint(f\"  Gesture labels: {len(gesture_labels)} types\")\nprint(f\"  Gesture distribution:\\\\n{train_metadata['gesture'].value_counts()}\")"}, {"cell_type": "markdown", "metadata": {}, "source": "## 2. \u5408\u6210\u30c6\u30b9\u30c8\u30c7\u30fc\u30bf\u306e\u751f\u6210"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "def analyze_real_data_distribution():\n    \"\"\"\u5b9f\u30c7\u30fc\u30bf\u306e\u7d71\u8a08\u7684\u7279\u6027\u3092\u5206\u6790\"\"\"\n\n    # \u30b8\u30a7\u30b9\u30c1\u30e3\u30fc\u5206\u5e03\n    gesture_dist = train_metadata[\"gesture\"].value_counts(normalize=True)\n\n    # \u30bb\u30f3\u30b5\u30fc\u30c7\u30fc\u30bf\u306e\u7d71\u8a08\uff08\u30b5\u30f3\u30d7\u30ea\u30f3\u30b0\uff09\n    sensor_stats = {}\n    sample_sequences = train_metadata.sample(min(100, len(train_metadata)))[\n        \"sequence_id\"\n    ].tolist()\n\n    all_acc = []\n    all_gyr = []\n    all_quat = []\n\n    for seq_id in sample_sequences:\n        # train.csv\u304b\u3089\u8a72\u5f53\u30b7\u30fc\u30b1\u30f3\u30b9\u306e\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\n        seq_data = train_data[train_data[\"sequence_id\"] == seq_id]\n\n        # \u52a0\u901f\u5ea6\u8a08\n        acc_cols = [c for c in seq_data.columns if c.startswith(\"acc_\")]\n        if acc_cols:\n            all_acc.append(seq_data[acc_cols].values)\n\n        # \u30b8\u30e3\u30a4\u30ed\u30b9\u30b3\u30fc\u30d7\n        gyr_cols = [c for c in seq_data.columns if c.startswith(\"gyr_\")]\n        if gyr_cols:\n            all_gyr.append(seq_data[gyr_cols].values)\n\n        # \u30af\u30a9\u30fc\u30bf\u30cb\u30aa\u30f3\n        quat_cols = [c for c in seq_data.columns if \"quat\" in c]\n        if quat_cols:\n            all_quat.append(seq_data[quat_cols].values)\n\n    # \u7d71\u8a08\u91cf\u8a08\u7b97\n    if all_acc:\n        acc_data = np.vstack(all_acc)\n        sensor_stats[\"acc\"] = {\n            \"mean\": np.mean(acc_data, axis=0),\n            \"std\": np.std(acc_data, axis=0),\n            \"percentiles\": [\n                np.percentile(acc_data, p, axis=0) for p in [5, 25, 50, 75, 95]\n            ],\n        }\n\n    if all_gyr:\n        gyr_data = np.vstack(all_gyr)\n        sensor_stats[\"gyr\"] = {\n            \"mean\": np.mean(gyr_data, axis=0),\n            \"std\": np.std(gyr_data, axis=0),\n            \"percentiles\": [\n                np.percentile(gyr_data, p, axis=0) for p in [5, 25, 50, 75, 95]\n            ],\n        }\n\n    return gesture_dist, sensor_stats\n\n\n# \u5b9f\u30c7\u30fc\u30bf\u5206\u6790\nprint(\"Analyzing real data distribution...\")\ngesture_dist, sensor_stats = analyze_real_data_distribution()\nprint(\"Real data analysis completed\")"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "def generate_synthetic_sequence(gesture, seq_length, sensor_stats):\n    \"\"\"\u5358\u4e00\u306e\u5408\u6210\u30b7\u30fc\u30b1\u30f3\u30b9\u3092\u751f\u6210\"\"\"\n\n    # \u6642\u9593\u8ef8\n    time_stamps = np.arange(seq_length) * 0.02  # 50Hz\n\n    sequence_data = {\"time\": time_stamps}\n\n    # \u52a0\u901f\u5ea6\u8a08\u30c7\u30fc\u30bf\uff08\u30c6\u30b9\u30c8\u30c7\u30fc\u30bf\u306f\u3088\u308a\u591a\u69d8\u3068\u4e88\u60f3\uff09\n    if \"acc\" in sensor_stats:\n        acc_mean = sensor_stats[\"acc\"][\"mean\"]\n        acc_std = sensor_stats[\"acc\"][\"std\"] * 1.3  # \u30c6\u30b9\u30c8\u306f\u5c11\u3057\u5206\u6563\u5927\u304d\u3081\n\n        # \u57fa\u672c\u30c7\u30fc\u30bf\n        base_acc = np.random.normal(acc_mean, acc_std, (seq_length, len(acc_mean)))\n\n        # \u30b8\u30a7\u30b9\u30c1\u30e3\u30fc\u56fa\u6709\u306e\u30d1\u30bf\u30fc\u30f3\n        freq = 0.5 + gesture * 0.3  # \u5404\u30b8\u30a7\u30b9\u30c1\u30e3\u30fc\u306e\u5468\u6ce2\u6570\n        amplitude = 0.3 + (gesture % 6) * 0.1\n\n        for j in range(min(3, base_acc.shape[1])):\n            phase = np.random.rand() * 2 * np.pi\n            base_acc[:, j] += amplitude * np.sin(2 * np.pi * freq * time_stamps + phase)\n\n            # \u6642\u3005\u30b9\u30d1\u30a4\u30af\u3092\u8ffd\u52a0\uff08\u6025\u306a\u52d5\u304d\uff09\n            if np.random.rand() < 0.3:\n                spike_pos = np.random.randint(seq_length // 4, 3 * seq_length // 4)\n                base_acc[spike_pos : spike_pos + 5, j] *= 1.5\n\n        for j, col in enumerate([\"acc_x\", \"acc_y\", \"acc_z\"]):\n            sequence_data[col] = (\n                base_acc[:, j] if j < base_acc.shape[1] else np.zeros(seq_length)\n            )\n\n    # \u30b8\u30e3\u30a4\u30ed\u30b9\u30b3\u30fc\u30d7\u30c7\u30fc\u30bf\n    if \"gyr\" in sensor_stats:\n        gyr_mean = sensor_stats[\"gyr\"][\"mean\"]\n        gyr_std = sensor_stats[\"gyr\"][\"std\"] * 1.2\n\n        base_gyr = np.random.normal(gyr_mean, gyr_std, (seq_length, len(gyr_mean)))\n\n        # \u56de\u8ee2\u30d1\u30bf\u30fc\u30f3\n        rotation_speed = 0.05 * (1 + gesture % 8)\n        for j in range(min(3, base_gyr.shape[1])):\n            base_gyr[:, j] += rotation_speed * np.cos(np.pi * time_stamps * (1 + j * 0.5))\n\n        for j, col in enumerate([\"gyr_x\", \"gyr_y\", \"gyr_z\"]):\n            sequence_data[col] = (\n                base_gyr[:, j] if j < base_gyr.shape[1] else np.zeros(seq_length)\n            )\n\n    # \u30af\u30a9\u30fc\u30bf\u30cb\u30aa\u30f3\uff08\u5358\u4f4d\u30af\u30a9\u30fc\u30bf\u30cb\u30aa\u30f3\uff09\n    angles = np.random.randn(seq_length, 3) * 0.1\n    angles = np.cumsum(angles, axis=0)\n\n    quat = np.zeros((seq_length, 4))\n    for i in range(seq_length):\n        roll, pitch, yaw = angles[i]\n        cy = np.cos(yaw * 0.5)\n        sy = np.sin(yaw * 0.5)\n        cp = np.cos(pitch * 0.5)\n        sp = np.sin(pitch * 0.5)\n        cr = np.cos(roll * 0.5)\n        sr = np.sin(roll * 0.5)\n\n        quat[i, 0] = cr * cp * cy + sr * sp * sy  # w\n        quat[i, 1] = sr * cp * cy - cr * sp * sy  # x\n        quat[i, 2] = cr * sp * cy + sr * cp * sy  # y\n        quat[i, 3] = cr * cp * sy - sr * sp * cy  # z\n\n    sequence_data[\"quat_w\"] = quat[:, 0]\n    sequence_data[\"quat_x\"] = quat[:, 1]\n    sequence_data[\"quat_y\"] = quat[:, 2]\n    sequence_data[\"quat_z\"] = quat[:, 3]\n\n    # ToF\u30bb\u30f3\u30b5\u30fc\uff08\u8ddd\u96e2\u30c7\u30fc\u30bf\uff09\n    for tof_id in range(8):\n        base_distance = np.random.uniform(50, 2500)\n\n        if gesture < 6:  # \u8fd1\u8ddd\u96e2\u30b8\u30a7\u30b9\u30c1\u30e3\u30fc\n            distance_pattern = base_distance - 200 * np.sin(2 * np.pi * 0.5 * time_stamps)\n        elif gesture < 12:  # \u4e2d\u8ddd\u96e2\u30b8\u30a7\u30b9\u30c1\u30e3\u30fc\n            distance_pattern = base_distance + 100 * np.cos(np.pi * time_stamps)\n        else:  # \u9060\u8ddd\u96e2\u30b8\u30a7\u30b9\u30c1\u30e3\u30fc\n            distance_pattern = base_distance + np.random.normal(0, 50, seq_length)\n\n        sequence_data[f\"tof_{tof_id}\"] = np.maximum(0, distance_pattern)\n\n    return pd.DataFrame(sequence_data)\n\n\nprint(\"Synthetic sequence generator ready\")"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "def generate_synthetic_dataset(n_sequences=1000):\n    \"\"\"\u5408\u6210\u30c7\u30fc\u30bf\u30bb\u30c3\u30c8\u3092\u751f\u6210\"\"\"\n\n    synthetic_sequences = []\n    synthetic_metadata = []\n\n    # \u30c6\u30b9\u30c8\u30c7\u30fc\u30bf\u306e\u30b8\u30a7\u30b9\u30c1\u30e3\u30fc\u5206\u5e03\u3092\u4e88\u60f3\uff08\u3088\u308a\u5747\u7b49\u306b\uff09\n    gestures = list(range(18))\n\n    # \u5b9f\u30c7\u30fc\u30bf\u5206\u5e0330% + \u5747\u7b49\u5206\u5e0370%\n    real_probs = gesture_dist.reindex(gestures, fill_value=0.01).values\n    uniform_probs = np.ones(18) / 18\n    test_probs = 0.3 * real_probs + 0.7 * uniform_probs\n    test_probs /= test_probs.sum()\n\n    print(f\"Generating {n_sequences} synthetic sequences...\")\n\n    for i in range(n_sequences):\n        # \u30b8\u30a7\u30b9\u30c1\u30e3\u30fc\u9078\u629e\n        gesture = np.random.choice(gestures, p=test_probs)\n\n        # \u30b7\u30fc\u30b1\u30f3\u30b9\u9577\uff08\u30c6\u30b9\u30c8\u3067\u306f\u5c11\u3057\u9577\u3081\uff09\n        seq_length = int(np.random.normal(130, 25))\n        seq_length = max(60, min(250, seq_length))\n\n        # \u30b7\u30fc\u30b1\u30f3\u30b9\u751f\u6210\n        seq_df = generate_synthetic_sequence(gesture, seq_length, sensor_stats)\n\n        synthetic_sequences.append(seq_df)\n        synthetic_metadata.append(\n            {\n                \"sequence_id\": f\"synthetic_{i:06d}\",\n                \"subject\": f\"synth_sub_{i % 30}\",  # 30\u4eba\u306e\u5408\u6210\u88ab\u9a13\u8005\n                \"gesture\": id_to_gesture[gesture],  # \u6574\u6570ID\u3092\u6587\u5b57\u5217\u30e9\u30d9\u30eb\u306b\u5909\u63db\n                \"sequence_length\": seq_length,\n            }\n        )\n\n        if (i + 1) % 200 == 0:\n            print(f\"  Generated {i + 1}/{n_sequences} sequences\")\n\n    synthetic_metadata_df = pd.DataFrame(synthetic_metadata)\n\n    print(f\"\\nSynthetic data generated:\")\n    print(f\"  Total sequences: {len(synthetic_sequences)}\")\n    print(f\"  Avg sequence length: {synthetic_metadata_df['sequence_length'].mean():.1f}\")\n    print(\n        f\"  Gesture distribution:\\n{synthetic_metadata_df['gesture'].value_counts().sort_index()}\"\n    )\n\n    return synthetic_sequences, synthetic_metadata_df\n\n\n# \u5408\u6210\u30c7\u30fc\u30bf\u751f\u6210\uff08\u5b9f\u30c7\u30fc\u30bf\u3068\u540c\u6570\uff09\nn_synthetic = len(train_metadata)\nsynthetic_sequences, synthetic_metadata = generate_synthetic_dataset(n_synthetic)"}, {"cell_type": "markdown", "metadata": {}, "source": "## 3. \u7279\u5fb4\u91cf\u30a8\u30f3\u30b8\u30cb\u30a2\u30ea\u30f3\u30b0"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "def extract_features(df, seq_id, metadata_row):\n    \"\"\"\u9ad8\u5ea6\u306a\u7279\u5fb4\u91cf\u62bd\u51fa\"\"\"\n    features = {}\n\n    # \u30e1\u30bf\u30c7\u30fc\u30bf\u7279\u5fb4\n    features[\"subject_id\"] = hash(metadata_row[\"subject\"]) % 1000\n    features[\"seq_length\"] = len(df)\n\n    # \u52a0\u901f\u5ea6\u8a08\u7279\u5fb4\n    for axis in [\"x\", \"y\", \"z\"]:\n        col = f\"acc_{axis}\"\n        if col in df.columns:\n            values = df[col].values\n            features[f\"acc_{axis}_mean\"] = np.mean(values)\n            features[f\"acc_{axis}_std\"] = np.std(values)\n            features[f\"acc_{axis}_max\"] = np.max(values)\n            features[f\"acc_{axis}_min\"] = np.min(values)\n            features[f\"acc_{axis}_range\"] = np.ptp(values)\n            features[f\"acc_{axis}_skew\"] = pd.Series(values).skew()\n            features[f\"acc_{axis}_kurt\"] = pd.Series(values).kurt()\n\n            # \u5468\u6ce2\u6570\u9818\u57df\u7279\u5fb4\n            fft_vals = np.abs(np.fft.fft(values))[: len(values) // 2]\n            features[f\"acc_{axis}_fft_max\"] = np.max(fft_vals) if len(fft_vals) > 0 else 0\n            features[f\"acc_{axis}_fft_mean\"] = (\n                np.mean(fft_vals) if len(fft_vals) > 0 else 0\n            )\n\n            # \u30b8\u30e3\u30fc\u30af\n            if len(values) > 1:\n                jerk = np.diff(values)\n                features[f\"acc_{axis}_jerk_mean\"] = np.mean(np.abs(jerk))\n                features[f\"acc_{axis}_jerk_std\"] = np.std(jerk)\n            else:\n                features[f\"acc_{axis}_jerk_mean\"] = 0\n                features[f\"acc_{axis}_jerk_std\"] = 0\n\n    # \u52a0\u901f\u5ea6\u306e\u5927\u304d\u3055\n    if all(f\"acc_{axis}\" in df.columns for axis in [\"x\", \"y\", \"z\"]):\n        acc_magnitude = np.sqrt(df[\"acc_x\"] ** 2 + df[\"acc_y\"] ** 2 + df[\"acc_z\"] ** 2)\n        features[\"acc_magnitude_mean\"] = np.mean(acc_magnitude)\n        features[\"acc_magnitude_std\"] = np.std(acc_magnitude)\n        features[\"acc_magnitude_max\"] = np.max(acc_magnitude)\n\n    # \u30b8\u30e3\u30a4\u30ed\u30b9\u30b3\u30fc\u30d7\u7279\u5fb4\n    for axis in [\"x\", \"y\", \"z\"]:\n        col = f\"gyr_{axis}\"\n        if col in df.columns:\n            values = df[col].values\n            features[f\"gyr_{axis}_mean\"] = np.mean(values)\n            features[f\"gyr_{axis}_std\"] = np.std(values)\n            features[f\"gyr_{axis}_max\"] = np.max(values)\n            features[f\"gyr_{axis}_energy\"] = np.sum(values**2)\n\n    # \u89d2\u901f\u5ea6\u306e\u5927\u304d\u3055\n    if all(f\"gyr_{axis}\" in df.columns for axis in [\"x\", \"y\", \"z\"]):\n        gyr_magnitude = np.sqrt(df[\"gyr_x\"] ** 2 + df[\"gyr_y\"] ** 2 + df[\"gyr_z\"] ** 2)\n        features[\"gyr_magnitude_mean\"] = np.mean(gyr_magnitude)\n        features[\"gyr_magnitude_std\"] = np.std(gyr_magnitude)\n\n    # \u30af\u30a9\u30fc\u30bf\u30cb\u30aa\u30f3\u7279\u5fb4\n    for comp in [\"w\", \"x\", \"y\", \"z\"]:\n        col = f\"quat_{comp}\"\n        if col in df.columns:\n            values = df[col].values\n            features[f\"quat_{comp}_mean\"] = np.mean(values)\n            features[f\"quat_{comp}_std\"] = np.std(values)\n            features[f\"quat_{comp}_change\"] = (\n                values[-1] - values[0] if len(values) > 0 else 0\n            )\n\n    # ToF\u30bb\u30f3\u30b5\u30fc\u7279\u5fb4\uff08\u6b21\u5143\u524a\u6e1b\uff09\n    tof_features = []\n    for i in range(8):\n        col = f\"tof_{i}\"\n        if col in df.columns:\n            values = df[col].values\n            tof_features.extend([np.mean(values), np.std(values), np.median(values)])\n\n    # ToF\u4e3b\u6210\u5206\uff08\u6700\u521d\u306e5\u6210\u5206\u306e\u307f\uff09\n    if tof_features:\n        for i in range(min(5, len(tof_features))):\n            features[f\"tof_pc_{i}\"] = tof_features[i]\n\n    # \u30e9\u30d9\u30eb\uff08\u6587\u5b57\u5217\u306e\u5834\u5408\u306f\u6574\u6570ID\u306b\u5909\u63db\uff09\n    gesture_value = metadata_row[\"gesture\"]\n    if isinstance(gesture_value, str):\n        features[\"gesture\"] = gesture_to_id.get(gesture_value, 0)\n    else:\n        features[\"gesture\"] = gesture_value\n\n    return features\n\n\nprint(\"Feature extractor ready\")"}, {"cell_type": "markdown", "metadata": {}, "source": "## 4. \u30c7\u30fc\u30bf\u30bb\u30c3\u30c8\u6e96\u5099\uff08\u5b9f\u30c7\u30fc\u30bf50% + \u5408\u6210\u30c7\u30fc\u30bf50%\uff09"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "# \u5b9f\u30c7\u30fc\u30bf\u304b\u3089\u7279\u5fb4\u91cf\u62bd\u51fa\uff0850%\u30b5\u30f3\u30d7\u30ea\u30f3\u30b0\uff09\nreal_sample = train_metadata.sample(n=len(train_metadata) // 2, random_state=42)\nprint(f\"Processing {len(real_sample)} real sequences...\")\n\nreal_features = []\nfailed_count = 0\nfor idx, row in real_sample.iterrows():\n    try:\n        # train.csv\u304b\u3089\u8a72\u5f53\u30b7\u30fc\u30b1\u30f3\u30b9\u306e\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\n        seq_data = train_data[train_data[\"sequence_id\"] == row[\"sequence_id\"]]\n        if len(seq_data) > 0:\n            features = extract_features(seq_data, row[\"sequence_id\"], row)\n            real_features.append(features)\n    except Exception as e:\n        failed_count += 1\n        if failed_count <= 5:  # \u6700\u521d\u306e5\u500b\u306e\u30a8\u30e9\u30fc\u306e\u307f\u8868\u793a\n            print(f\"  Failed to process {row['sequence_id']}: {e}\")\n        continue\n\nprint(f\"Extracted features from {len(real_features)} real sequences\")\nif failed_count > 0:\n    print(f\"  Failed to process {failed_count} sequences\")"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "# \u5408\u6210\u30c7\u30fc\u30bf\u304b\u3089\u7279\u5fb4\u91cf\u62bd\u51fa\uff0850%\uff09\nsynthetic_sample_idx = np.random.choice(\n    len(synthetic_sequences), size=len(synthetic_sequences) // 2, replace=False\n)\nprint(f\"Processing {len(synthetic_sample_idx)} synthetic sequences...\")\n\nsynthetic_features = []\nfor idx in synthetic_sample_idx:\n    row = synthetic_metadata.iloc[idx]\n    df = synthetic_sequences[idx]\n    features = extract_features(df, row[\"sequence_id\"], row)\n    synthetic_features.append(features)\n\nprint(f\"Extracted features from {len(synthetic_features)} synthetic sequences\")"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "# \u7d50\u5408\nall_features = real_features + synthetic_features\nfeature_df = pd.DataFrame(all_features)\n\n# \u30c7\u30fc\u30bf\u578b\u306e\u78ba\u8a8d\u3068\u4fee\u6b63\nfeature_df = feature_df.fillna(0)\n\nprint(f\"\\nCombined dataset:\")\nprint(f\"  Total samples: {len(feature_df)}\")\nprint(\n    f\"  Real data: {len(real_features)} ({len(real_features) / len(feature_df) * 100:.1f}%)\"\n)\nprint(\n    f\"  Synthetic data: {len(synthetic_features)} ({len(synthetic_features) / len(feature_df) * 100:.1f}%)\"\n)\nprint(f\"  Features: {feature_df.shape[1] - 1}\")\nprint(f\"\\nGesture distribution:\")\nprint(feature_df[\"gesture\"].value_counts().sort_index())"}, {"cell_type": "markdown", "metadata": {}, "source": "## 5. \u30a2\u30f3\u30b5\u30f3\u30d6\u30eb\u30e2\u30c7\u30eb\u306e\u30c8\u30ec\u30fc\u30cb\u30f3\u30b0"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "# \u7279\u5fb4\u91cf\u3068\u30e9\u30d9\u30eb\u306e\u5206\u96e2\nX = feature_df.drop(\"gesture\", axis=1)\ny = feature_df[\"gesture\"]\n\n# \u30b9\u30b1\u30fc\u30ea\u30f3\u30b0\nscaler = StandardScaler()\nX_scaled = scaler.fit_transform(X)\n\n# Train/Validation\u5206\u5272\nX_train, X_val, y_train, y_val = train_test_split(\n    X_scaled, y, test_size=0.2, random_state=42, stratify=y\n)\n\nprint(f\"Training set: {X_train.shape}\")\nprint(f\"Validation set: {X_val.shape}\")"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "# LightGBM\u30e2\u30c7\u30eb\nlgb_params = {\n    \"objective\": \"multiclass\",\n    \"num_class\": 18,\n    \"metric\": \"multi_logloss\",\n    \"boosting_type\": \"gbdt\",\n    \"num_leaves\": 63,\n    \"learning_rate\": 0.05,\n    \"feature_fraction\": 0.8,\n    \"bagging_fraction\": 0.8,\n    \"bagging_freq\": 5,\n    \"verbose\": 0,\n    \"seed\": 42,\n    \"n_jobs\": -1,\n}\n\nlgb_train = lgb.Dataset(X_train, label=y_train)\nlgb_val = lgb.Dataset(X_val, label=y_val, reference=lgb_train)\n\nprint(\"Training LightGBM...\")\nlgb_model = lgb.train(\n    lgb_params,\n    lgb_train,\n    valid_sets=[lgb_val],\n    num_boost_round=300,\n    callbacks=[lgb.early_stopping(50), lgb.log_evaluation(50)],\n)\n\n# \u691c\u8a3c\nlgb_pred = lgb_model.predict(X_val, num_iteration=lgb_model.best_iteration)\nlgb_pred_class = np.argmax(lgb_pred, axis=1)\nlgb_acc = accuracy_score(y_val, lgb_pred_class)\nprint(f\"LightGBM Validation Accuracy: {lgb_acc:.4f}\")"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "# XGBoost\u30e2\u30c7\u30eb\nxgb_params = {\n    \"objective\": \"multi:softprob\",\n    \"num_class\": 18,\n    \"max_depth\": 6,\n    \"learning_rate\": 0.05,\n    \"subsample\": 0.8,\n    \"colsample_bytree\": 0.8,\n    \"seed\": 42,\n    \"n_jobs\": -1,\n    \"eval_metric\": \"mlogloss\",\n}\n\ndtrain = xgb.DMatrix(X_train, label=y_train)\ndval = xgb.DMatrix(X_val, label=y_val)\n\nprint(\"Training XGBoost...\")\nxgb_model = xgb.train(\n    xgb_params,\n    dtrain,\n    num_boost_round=300,\n    evals=[(dval, \"val\")],\n    early_stopping_rounds=50,\n    verbose_eval=50,\n)\n\n# \u691c\u8a3c\nxgb_pred = xgb_model.predict(dval)\nxgb_pred_class = np.argmax(xgb_pred, axis=1)\nxgb_acc = accuracy_score(y_val, xgb_pred_class)\nprint(f\"XGBoost Validation Accuracy: {xgb_acc:.4f}\")"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "# CatBoost\u30e2\u30c7\u30eb\ncat_model = CatBoostClassifier(\n    iterations=300,\n    learning_rate=0.05,\n    depth=6,\n    loss_function=\"MultiClass\",\n    classes_count=18,\n    random_seed=42,\n    verbose=50,\n    early_stopping_rounds=50,\n)\n\nprint(\"Training CatBoost...\")\ncat_model.fit(X_train, y_train, eval_set=(X_val, y_val), use_best_model=True)\n\n# \u691c\u8a3c\ncat_pred_class = cat_model.predict(X_val)\ncat_acc = accuracy_score(y_val, cat_pred_class)\nprint(f\"CatBoost Validation Accuracy: {cat_acc:.4f}\")"}, {"cell_type": "markdown", "metadata": {}, "source": "## 6. \u30a2\u30f3\u30b5\u30f3\u30d6\u30eb\u4e88\u6e2c"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "# \u30a2\u30f3\u30b5\u30f3\u30d6\u30eb\u4e88\u6e2c\uff08\u52a0\u91cd\u5e73\u5747\uff09\nlgb_weight = 0.5\nxgb_weight = 0.2\ncat_weight = 0.3\n\n# \u5404\u30e2\u30c7\u30eb\u306e\u4e88\u6e2c\u78ba\u7387\nlgb_proba = lgb_model.predict(X_val, num_iteration=lgb_model.best_iteration)\nxgb_proba = xgb_model.predict(dval)\ncat_proba = cat_model.predict_proba(X_val)\n\n# \u52a0\u91cd\u5e73\u5747\nensemble_proba = lgb_weight * lgb_proba + xgb_weight * xgb_proba + cat_weight * cat_proba\nensemble_pred = np.argmax(ensemble_proba, axis=1)\n\n# \u6700\u7d42\u7cbe\u5ea6\nensemble_acc = accuracy_score(y_val, ensemble_pred)\nprint(f\"\\n=== Final Results ===\")\nprint(f\"LightGBM: {lgb_acc:.4f}\")\nprint(f\"XGBoost: {xgb_acc:.4f}\")\nprint(f\"CatBoost: {cat_acc:.4f}\")\nprint(f\"Ensemble: {ensemble_acc:.4f}\")\n\nprint(f\"\\n\u5206\u985e\u30ec\u30dd\u30fc\u30c8:\")\nprint(classification_report(y_val, ensemble_pred))"}, {"cell_type": "markdown", "metadata": {}, "source": "## 7. \u30e2\u30c7\u30eb\u306e\u4fdd\u5b58"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "# \u30e2\u30c7\u30eb\u3068\u30b9\u30b1\u30fc\u30e9\u30fc\u3092\u4fdd\u5b58\nmodel_dir = Path(\"/kaggle/working/models\")\nmodel_dir.mkdir(exist_ok=True)\n\n# LightGBM\nlgb_model.save_model(str(model_dir / \"lgb_model_v11.txt\"))\n\n# XGBoost\nxgb_model.save_model(str(model_dir / \"xgb_model_v11.json\"))\n\n# CatBoost\ncat_model.save_model(str(model_dir / \"cat_model_v11.cbm\"))\n\n# \u30b9\u30b1\u30fc\u30e9\u30fc\u3068\u7279\u5fb4\u91cf\u540d\nwith open(model_dir / \"scaler_v11.pkl\", \"wb\") as f:\n    pickle.dump(scaler, f)\n\nwith open(model_dir / \"feature_names_v11.pkl\", \"wb\") as f:\n    pickle.dump(list(X.columns), f)\n\n# \u30e2\u30c7\u30eb\u60c5\u5831\nmodel_info = {\n    \"version\": \"v11_synthetic_fixed\",\n    \"training_data\": {\n        \"real_samples\": len(real_features),\n        \"synthetic_samples\": len(synthetic_features),\n        \"total_samples\": len(feature_df),\n    },\n    \"validation_accuracy\": {\n        \"lgb\": float(lgb_acc),\n        \"xgb\": float(xgb_acc),\n        \"catboost\": float(cat_acc),\n        \"ensemble\": float(ensemble_acc),\n    },\n    \"ensemble_weights\": {\"lgb\": lgb_weight, \"xgb\": xgb_weight, \"catboost\": cat_weight},\n    \"feature_count\": X.shape[1],\n}\n\nwith open(model_dir / \"model_info_v11.json\", \"w\") as f:\n    json.dump(model_info, f, indent=2)\n\nprint(f\"\\nModels saved to {model_dir}\")\nprint(f\"Files created:\")\nfor file in model_dir.glob(\"*v11*\"):\n    print(f\"  - {file.name}\")"}, {"cell_type": "markdown", "metadata": {}, "source": "## 8. \u7d50\u679c\u30b5\u30de\u30ea\u30fc"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "print(\"=\" * 50)\nprint(\"V11 \u5408\u6210\u30c7\u30fc\u30bf\u30e2\u30c7\u30eb \u30c8\u30ec\u30fc\u30cb\u30f3\u30b0\u5b8c\u4e86\")\nprint(\"=\" * 50)\nprint(f\"\\n\u5b9f\u30c7\u30fc\u30bf: {len(real_features)} samples\")\nprint(f\"\u5408\u6210\u30c7\u30fc\u30bf: {len(synthetic_features)} samples\")\nprint(f\"\\n\u691c\u8a3c\u7cbe\u5ea6:\")\nprint(f\"  - \u30a2\u30f3\u30b5\u30f3\u30d6\u30eb: {ensemble_acc:.2%}\")\nprint(f\"  - LightGBM: {lgb_acc:.2%}\")\nprint(f\"  - XGBoost: {xgb_acc:.2%}\")\nprint(f\"  - CatBoost: {cat_acc:.2%}\")\nprint(f\"\\n\u6b21\u306e\u30b9\u30c6\u30c3\u30d7:\")\nprint(f\"1. \u3053\u306e\u30ce\u30fc\u30c8\u30d6\u30c3\u30af\u3092\u5b9f\u884c\u3057\u3066\u30e2\u30c7\u30eb\u3092\u751f\u6210\")\nprint(f\"2. /kaggle/working/models \u306e\u30e2\u30c7\u30eb\u3092Kaggle Dataset\u3068\u3057\u3066\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\")\nprint(f\"3. \u63a8\u8ad6\u30ce\u30fc\u30c8\u30d6\u30c3\u30af\u304b\u3089Dataset\u3092\u53c2\u7167\u3057\u3066\u4e88\u6e2c\")\nprint(f\"4. \u30b9\u30b3\u30a2\u3092\u78ba\u8a8d\u3057\u3066\u5408\u6210\u30c7\u30fc\u30bf\u306e\u6709\u52b9\u6027\u3092\u8a55\u4fa1\")"}], "metadata": {"kernelspec": {"display_name": "Python 3", "language": "python", "name": "python3"}, "language_info": {"codemirror_mode": {"name": "ipython", "version": 3}, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.0"}}, "nbformat": 4, "nbformat_minor": 4}