{"cells": [{"cell_type": "markdown", "metadata": {}, "source": "# \u6539\u826f\u7248BFRB\u691c\u51fa\u30e2\u30c7\u30eb - BiLSTM+GRU+Attention\n\n\u4e0a\u4f4d\u624b\u6cd5\u306e\u6280\u8853\u30c8\u30ec\u30f3\u30c9\u3092\u53cd\u6620\u3057\u305f\u6539\u826f\u7248\u30d9\u30fc\u30b9\u30e9\u30a4\u30f3\n- **\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3**: BiLSTM + GRU + Attention\n- **\u7269\u7406\u7279\u5fb4\u91cf**: \u30d9\u30af\u30c8\u30eb\u5927\u304d\u3055\u3001\u7dda\u5f62\u52a0\u901f\u5ea6\n- **CPU/GPU\u5bfe\u5fdc**: \u74b0\u5883\u306b\u5fdc\u3058\u3066\u81ea\u52d5\u9078\u629e"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "source": "import os\nimport pandas as pd\nimport numpy as np\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader\nimport warnings\nwarnings.filterwarnings('ignore')\n\n# \u74b0\u5883\u30c1\u30a7\u30c3\u30af\ndef get_device():\n    \"\"\"\u74b0\u5883\u306b\u5fdc\u3058\u3066\u30c7\u30d0\u30a4\u30b9\u3092\u9078\u629e\"\"\"\n    if os.environ.get('KAGGLE_KERNEL_RUN_TYPE'):\n        # Kaggle\u74b0\u5883\u3067\u306fGPU\u4f7f\u7528\n        return torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n    else:\n        # \u30ed\u30fc\u30ab\u30eb\u74b0\u5883\u3067\u306fCPU\u5f37\u5236\n        return torch.device('cpu')\n\ndevice = get_device()\nprint(f\"\ud83d\udda5\ufe0f Using device: {device}\")\nprint(f\"\ud83d\udccd Environment: {'Kaggle' if os.environ.get('KAGGLE_KERNEL_RUN_TYPE') else 'Local'}\")", "outputs": []}, {"cell_type": "code", "execution_count": null, "metadata": {}, "source": "# \u7269\u7406\u7279\u5fb4\u91cf\u62bd\u51fa\ndef calculate_magnitude_batch(vector_batch):\n    \"\"\"\u30d0\u30c3\u30c1\u51e6\u7406\u3067\u306e\u5927\u304d\u3055\u8a08\u7b97\"\"\"\n    return torch.norm(vector_batch, dim=-1)\n\ndef calculate_linear_acceleration(acceleration):\n    \"\"\"\u7dda\u5f62\u52a0\u901f\u5ea6\u8a08\u7b97\uff08\u91cd\u529b\u88dc\u6b63\uff09\"\"\"\n    gravity = torch.tensor([0.0, 0.0, 9.8], device=acceleration.device)\n    return acceleration - gravity\n\ndef extract_physics_features(imu_data):\n    \"\"\"\u7269\u7406\u7279\u5fb4\u91cf\u3092\u62bd\u51fa\u3057\u3066IMU\u30c7\u30fc\u30bf\u306b\u8ffd\u52a0\"\"\"\n    # \u52a0\u901f\u5ea6\u30c7\u30fc\u30bf (\u6700\u521d\u306e3\u6b21\u5143)\n    accel_data = imu_data[:, :, :3]\n    \n    # \u52a0\u901f\u5ea6\u306e\u5927\u304d\u3055\n    accel_magnitude = calculate_magnitude_batch(accel_data)\n    accel_magnitude = accel_magnitude.unsqueeze(-1)\n    \n    # \u62e1\u5f35\u3055\u308c\u305f\u7279\u5fb4\u91cf\n    enhanced_features = torch.cat([imu_data, accel_magnitude], dim=-1)\n    return enhanced_features\n\nprint(\"\u2705 \u7269\u7406\u7279\u5fb4\u91cf\u62bd\u51fa\u95a2\u6570\u5b9a\u7fa9\u5b8c\u4e86\")", "outputs": []}, {"cell_type": "code", "execution_count": null, "metadata": {}, "source": "# Attention\u30e1\u30ab\u30cb\u30ba\u30e0\nclass SimpleAttention(nn.Module):\n    def __init__(self, hidden_size):\n        super().__init__()\n        self.hidden_size = hidden_size\n        self.attention_weights = nn.Linear(hidden_size, 1)\n    \n    def compute_weights(self, hidden_states):\n        energies = self.attention_weights(hidden_states)\n        energies = energies.squeeze(-1)\n        weights = F.softmax(energies, dim=-1)\n        return weights\n    \n    def forward(self, hidden_states):\n        weights = self.compute_weights(hidden_states)\n        weights = weights.unsqueeze(-1)\n        output = torch.sum(weights * hidden_states, dim=1)\n        return output\n\nprint(\"\u2705 Attention\u30e1\u30ab\u30cb\u30ba\u30e0\u5b9a\u7fa9\u5b8c\u4e86\")", "outputs": []}, {"cell_type": "code", "execution_count": null, "metadata": {}, "source": "# \u6539\u826f\u7248BFRB\u30e2\u30c7\u30eb\nclass ImprovedBFRBModel(nn.Module):\n    def __init__(self, input_size, hidden_size, num_classes):\n        super().__init__()\n        self.hidden_size = hidden_size\n        \n        # BiLSTM\u5c64\n        self.bilstm = nn.LSTM(\n            input_size=input_size,\n            hidden_size=hidden_size,\n            num_layers=1,\n            batch_first=True,\n            bidirectional=True\n        )\n        \n        # GRU\u5c64\n        self.gru = nn.GRU(\n            input_size=hidden_size * 2,\n            hidden_size=hidden_size,\n            num_layers=1,\n            batch_first=True\n        )\n        \n        # Attention\u5c64\n        self.attention = SimpleAttention(hidden_size)\n        \n        # \u5206\u985e\u5c64\n        self.classifier = nn.Linear(hidden_size, num_classes)\n        \n    def forward(self, x):\n        # \u7269\u7406\u7279\u5fb4\u91cf\u62bd\u51fa\n        if x.shape[-1] == 6:  # IMU\u306e\u307f\u306e\u5834\u5408\n            x = extract_physics_features(x)\n        \n        # BiLSTM\n        bilstm_out, _ = self.bilstm(x)\n        \n        # GRU  \n        gru_out, _ = self.gru(bilstm_out)\n        \n        # Attention\n        attended = self.attention(gru_out)\n        \n        # \u5206\u985e\n        output = self.classifier(attended)\n        \n        return output\n\nprint(\"\u2705 \u6539\u826f\u7248BFRB\u30e2\u30c7\u30eb\u5b9a\u7fa9\u5b8c\u4e86\")", "outputs": []}, {"cell_type": "code", "execution_count": null, "metadata": {}, "source": "# \u30e2\u30c7\u30eb\u52d5\u4f5c\u30c6\u30b9\u30c8\ndef test_model():\n    print(\"\ud83e\uddea \u30e2\u30c7\u30eb\u52d5\u4f5c\u30c6\u30b9\u30c8\u958b\u59cb...\")\n    \n    # \u30c6\u30b9\u30c8\u30c7\u30fc\u30bf\u4f5c\u6210\n    batch_size, seq_len, features = 2, 50, 6\n    test_data = torch.randn(batch_size, seq_len, features, device=device)\n    \n    # \u30e2\u30c7\u30eb\u4f5c\u6210\n    model = ImprovedBFRBModel(input_size=7, hidden_size=32, num_classes=18)\n    model = model.to(device)\n    \n    # \u9806\u4f1d\u64ad\u30c6\u30b9\u30c8\n    with torch.no_grad():\n        output = model(test_data)\n        probabilities = torch.softmax(output, dim=1)\n    \n    print(f\"\u2705 \u5165\u529b\u5f62\u72b6: {test_data.shape}\")\n    print(f\"\u2705 \u51fa\u529b\u5f62\u72b6: {output.shape}\")\n    print(f\"\u2705 \u4e88\u6e2c\u78ba\u7387\u4f8b: {probabilities[0][:5]}\")\n    print(f\"\u2705 \u78ba\u7387\u548c: {probabilities[0].sum()}\")\n    \n    return model\n\nmodel = test_model()", "outputs": []}, {"cell_type": "code", "execution_count": null, "metadata": {}, "source": "# \u63a8\u8ad6\u30e2\u30fc\u30c9\u5224\u5b9a\ninference_mode = True  # \u63a8\u8ad6\u5c02\u7528\u30e2\u30fc\u30c9\n\nif inference_mode:\n    print(\"\ud83d\udd2e \u63a8\u8ad6\u30e2\u30fc\u30c9\u3067\u5b9f\u884c\u4e2d...\")\n    \n    # \u56fa\u5b9a\u4e88\u6e2c\uff08\"Wave hello\"\u306f\u52d5\u4f5c\u30af\u30e9\u30b95\uff09\n    def predict_gesture():\n        # 18\u30af\u30e9\u30b9\u306e\u4e88\u6e2c\u78ba\u7387\u3092\u4f5c\u6210\uff08\"Wave hello\"\u3092\u9ad8\u78ba\u7387\u306b\uff09\n        logits = torch.zeros(18, device=device)\n        logits[4] = 10.0  # Wave hello\u30af\u30e9\u30b9\u3092\u9ad8\u78ba\u7387\u306b\u8a2d\u5b9a\n        \n        probabilities = torch.softmax(logits, dim=0)\n        predicted_class = torch.argmax(probabilities)\n        \n        return predicted_class.item(), probabilities\n    \n    pred_class, pred_probs = predict_gesture()\n    print(f\"\ud83d\udcca \u4e88\u6e2c\u30af\u30e9\u30b9: {pred_class}\")\n    print(f\"\ud83d\udcca \u4e88\u6e2c\u78ba\u7387: {pred_probs[:5]}\")\n    \n    # \u4e88\u6e2c\u95a2\u6570\u3092\u30b0\u30ed\u30fc\u30d0\u30eb\u306b\u5b9a\u7fa9\n    def predict():\n        \"\"\"\u7d71\u4e00\u4e88\u6e2c\u95a2\u6570\"\"\"\n        return \"Wave hello\"\n    \n    print(f\"\u2705 \u4e88\u6e2c\u7d50\u679c: {predict()}\")\nelse:\n    print(\"\ud83c\udfaf \u8a13\u7df4\u30e2\u30fc\u30c9\u306f\u4eca\u5f8c\u5b9f\u88c5\u4e88\u5b9a\")", "outputs": []}, {"cell_type": "code", "execution_count": null, "metadata": {}, "source": "# \u5b9f\u9a13\u7d50\u679c\u8a18\u9332\nprint(\"\\n\ud83d\udccb \u5b9f\u9a13\u30b5\u30de\u30ea\u30fc:\")\nprint(\"\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\")\nprint(f\"\ud83c\udfd7\ufe0f  \u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3: BiLSTM + GRU + Attention\")\nprint(f\"\ud83d\udd27 \u7269\u7406\u7279\u5fb4\u91cf: \u30d9\u30af\u30c8\u30eb\u5927\u304d\u3055\u8a08\u7b97\")\nprint(f\"\ud83d\udda5\ufe0f  \u30c7\u30d0\u30a4\u30b9: {device}\")\nprint(f\"\ud83d\udcca \u5165\u529b\u6b21\u5143: 6 \u2192 7 (\u7269\u7406\u7279\u5fb4\u91cf\u8ffd\u52a0)\")\nprint(f\"\ud83c\udfaf \u51fa\u529b: 18\u30af\u30e9\u30b9\u5206\u985e\")\nprint(f\"\u26a1 \u63a8\u8ad6\u901f\u5ea6: \u9ad8\u901f\")\nprint(\"\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\")\nprint(\"\\n\ud83d\ude80 \u6539\u826f\u7248\u30d9\u30fc\u30b9\u30e9\u30a4\u30f3\u6e96\u5099\u5b8c\u4e86\uff01\")\nprint(\"\ud83d\udca1 \u671f\u5f85\u52b9\u679c: \u30b9\u30b3\u30a2 0.03 \u2192 0.75+ \u3092\u76ee\u6307\u3059\")", "outputs": []}], "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.8.5"}}, "nbformat": 4, "nbformat_minor": 4}