{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceType":"competition","sourceId":41880,"databundleVersionId":5677426},{"sourceType":"datasetVersion","sourceId":15652414,"datasetId":10020749,"databundleVersionId":16588455}],"dockerImageVersionId":31328,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import kagglehub\nkagglehub.competition_download('tlvmc-parkinsons-freezing-gait-prediction')\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\n\n# ---------------------------------------------------------\n# المحطة الأولى: آلية الانتباه (Attention Mechanism)\n# تستخدم للتركيز على الأجزاء الزمنية الأهم في الإشارة\n# ---------------------------------------------------------\nclass Attention(nn.Module):\n    def __init__(self, hidden_dim):\n        super(Attention, self).__init__()\n        self.attention = nn.Linear(hidden_dim, 1)\n\n    def forward(self, lstm_output):\n        # حساب أوزان الانتباه (أي اللحظات أهم؟) باستخدام Softmax\n        attn_weights = F.softmax(self.attention(lstm_output), dim=1)\n        # استخراج متجه السياق (الخلاصة المركزة)\n        context_vector = torch.sum(attn_weights * lstm_output, dim=1)\n        return context_vector, attn_weights\n\n# ---------------------------------------------------------\n# المحطة الثانية: المعمارية الرئيسية للمودل (HTSAN)\n# ---------------------------------------------------------\nclass HTSAN(nn.Module):\n    def __init__(self, input_channels=6, num_classes=2): \n        # input_channels=6 (3 للتسارع Accelerometer + 3 للجيروسكوب Gyroscope)\n        super(HTSAN, self).__init__()\n        \n        # 1. استخراج الميزات المكانية (1D CNN)\n        self.conv1 = nn.Conv1d(in_channels=input_channels, out_channels=64, kernel_size=3, padding=1)\n        self.bn1 = nn.BatchNorm1d(64)\n        self.relu = nn.ReLU()\n        \n        # 2. النمذجة الزمنية (BiLSTM)\n        # يقرأ الإشارة في الاتجاهين (من البداية للنهاية والعكس)\n        self.lstm = nn.LSTM(input_size=64, hidden_size=64, batch_first=True, bidirectional=True)\n        \n        # 3. آلية الانتباه\n        # الحجم 128 لأن BiLSTM يخرج 64 في كل اتجاه (64 + 64)\n        self.attention = Attention(hidden_dim=128)\n        \n        # 4. طبقة اتخاذ القرار النهائي (Classification)\n        self.fc1 = nn.Linear(128, 64)\n        self.dropout = nn.Dropout(0.5) # لمنع المودل من الحفظ الأعمى (Overfitting)\n        self.fc2 = nn.Linear(64, num_classes) # يخرج احتمالين: تجمد أو مشي طبيعي\n\n    def forward(self, x):\n        # تمرير البيانات عبر طبقة CNN\n        x = self.conv1(x)\n        x = self.bn1(x)\n        x = self.relu(x)\n        \n        # إعادة ترتيب أبعاد المصفوفة لتناسب طبقة الـ LSTM\n        x = x.permute(0, 2, 1)\n        \n        # تمرير البيانات عبر طبقة BiLSTM\n        lstm_out, _ = self.lstm(x)\n        \n        # تطبيق آلية الانتباه لتسليط الضوء على الأجزاء المهمة\n        context_vector, attn_weights = self.attention(lstm_out)\n        \n        # إصدار القرار النهائي للشبكة\n        out = self.fc1(context_vector)\n        out = self.relu(out)\n        out = self.dropout(out)\n        out = self.fc2(out)\n        \n        return out\n\nprint(\"تم بناء معمارية HTSAN بنجاح! 🏭\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-10T20:41:48.066150Z","iopub.execute_input":"2026-04-10T20:41:48.066815Z","iopub.status.idle":"2026-04-10T20:41:52.337817Z","shell.execute_reply.started":"2026-04-10T20:41:48.066768Z","shell.execute_reply":"2026-04-10T20:41:52.336822Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# تهيئة المودل للعمل\nmodel = HTSAN(input_channels=6, num_classes=2)\n\n# إعداد خوارزمية التحسين (Adam) وسرعة التعلم كما في الورقة تماماً\nlearning_rate = 0.001\noptimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)\n\n# إعداد دالة الخسارة لمعرفة مقدار الخطأ أثناء التدريب\ncriterion = nn.CrossEntropyLoss()\n\nprint(\"تم إعداد محرك التدريب جاهز للعمل! 🏎️\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-10T20:45:15.985310Z","iopub.execute_input":"2026-04-10T20:45:15.986373Z","iopub.status.idle":"2026-04-10T20:45:19.479921Z","shell.execute_reply.started":"2026-04-10T20:45:15.986330Z","shell.execute_reply":"2026-04-10T20:45:19.478733Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\nprint(\"📂 المجلدات الموجودة فعلياً داخل Kaggle في هذه اللحظة هي:\")\nprint(os.listdir('/kaggle/input/'))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-10T20:54:53.190388Z","iopub.execute_input":"2026-04-10T20:54:53.190752Z","iopub.status.idle":"2026-04-10T20:54:53.197898Z","shell.execute_reply.started":"2026-04-10T20:54:53.190722Z","shell.execute_reply":"2026-04-10T20:54:53.196424Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport os\n\n# هذا هو المسار الحقيقي 100% بناءً على ما أخبرنا به Kaggle\nmain_path = '/kaggle/input/datasets'\ntarget_file = None\n\nprint(\"🔍 جاري الدخول إلى مجلد datasets للبحث عن بياناتك...\\n\")\n\nfor root, dirs, files in os.walk(main_path):\n    for file in files:\n        if file.endswith('.txt'):\n            target_file = os.path.join(root, file)\n            break\n    if target_file:\n        break\n\nif target_file:\n    print(f\"✅ مبروك! تم العثور على الملف بنجاح:\\n👉 {target_file}\\n\")\n    \n    # قراءة أول 5 صفوف لسرعة الأداء\n    df = pd.read_csv(target_file, sep='\\t', nrows=5)\n    \n    print(\"--- 🎯 أسماء الأعمدة جاهزة للاستخدام 🎯 ---\")\n    print(df.columns.tolist(), \"\\n\")\n    \n    display(df)\nelse:\n    print(\"❌ لا توجد ملفات txt هنا أيضاً! لنتأكد من المجلدات الموجودة داخل datasets:\")\n    print(os.listdir(main_path))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-10T20:56:26.782627Z","iopub.execute_input":"2026-04-10T20:56:26.783096Z","iopub.status.idle":"2026-04-10T20:56:26.879210Z","shell.execute_reply.started":"2026-04-10T20:56:26.783062Z","shell.execute_reply":"2026-04-10T20:56:26.877924Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\n\n# المسار الدقيق الذي اكتشفناه لملفك\ntarget_file = '/kaggle/input/datasets/mennahashraf29/muli-data/Filtered Data/007/task_3.txt'\n\n# قراءة البيانات مع إصلاح مشكلة الفاصلة والـ Header\ndf = pd.read_csv(target_file, sep=',', header=None)\n\nprint(f\"✅ عدد الأعمدة الفعلي في ملفاتك هو: {df.shape[1]} عموداً\\n\")\nprint(\"⏳ شكل الجدول المنظم:\")\ndisplay(df.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-10T20:57:54.591163Z","iopub.execute_input":"2026-04-10T20:57:54.591618Z","iopub.status.idle":"2026-04-10T20:57:55.267583Z","shell.execute_reply.started":"2026-04-10T20:57:54.591587Z","shell.execute_reply":"2026-04-10T20:57:55.266512Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\n\nprint(\"⏳ جاري تقطيع البيانات بناءً على حسابات الورقة البحثية...\")\n\n# 1. استخراج المستشعرات والتصنيفات من الجدول\n# نتجاهل العمود 0 (الترقيم) والعمود 1 (الوقت)\nX_raw = df.iloc[:, 2:60].values  # بيانات الحساسات (58 عمود)\ny_raw = df.iloc[:, 60].values    # عمود التصنيف (Label)\n\n# 2. إعدادات النافذة المنزلقة (كما في الورقة تماماً)\nwindow_size = 1000  # ثانيتان\nstep_size = 500     # تداخل 50%\n\nX_windows = []\ny_windows = []\n\n# عملية التقطيع\nfor i in range(0, len(X_raw) - window_size, step_size):\n    window = X_raw[i : i + window_size]\n    # أخذ التصنيف الأكثر تكراراً في هذه النافذة\n    label = np.bincount(y_raw[i : i + window_size].astype(int)).argmax()\n    \n    X_windows.append(window)\n    y_windows.append(label)\n\nX_windows = np.array(X_windows)\ny_windows = np.array(y_windows)\n\n# 3. تحويل البيانات إلى Tensors لتكون جاهزة لـ PyTorch\nX_tensor = torch.tensor(X_windows, dtype=torch.float32)\ny_tensor = torch.tensor(y_windows, dtype=torch.long)\n\n# يجب تغيير ترتيب الأبعاد ليكون (عدد النوافذ، عدد الحساسات، طول النافذة) لكي يناسب الـ CNN\nX_tensor = X_tensor.permute(0, 2, 1)\n\nprint(\"✅ تم تجهيز البيانات بنجاح!\")\nprint(f\"شكل X الجديد: {X_tensor.shape} (عدد النوافذ، المستشعرات، القراءات الزمنية)\")\nprint(f\"شكل y الجديد: {y_tensor.shape}\\n\")\n\nprint(\"⚙️ جاري بناء مودل HTSAN...\")\n\n# ---------------------------------------------------------\n# بناء مودل HTSAN ليتوافق مع بياناتك\n# ---------------------------------------------------------\nclass Attention(nn.Module):\n    def __init__(self, hidden_dim):\n        super(Attention, self).__init__()\n        self.attention = nn.Linear(hidden_dim, 1)\n\n    def forward(self, lstm_output):\n        attn_weights = F.softmax(self.attention(lstm_output), dim=1)\n        context_vector = torch.sum(attn_weights * lstm_output, dim=1)\n        return context_vector, attn_weights\n\nclass HTSAN(nn.Module):\n    def __init__(self, input_channels, num_classes=2): \n        super(HTSAN, self).__init__()\n        # طبقة الـ CNN المعدلة لتأخذ عدد حساساتك\n        self.conv1 = nn.Conv1d(in_channels=input_channels, out_channels=64, kernel_size=3, padding=1)\n        self.bn1 = nn.BatchNorm1d(64)\n        self.relu = nn.ReLU()\n        \n        # طبقة الـ BiLSTM\n        self.lstm = nn.LSTM(input_size=64, hidden_size=64, batch_first=True, bidirectional=True)\n        \n        # آلية الانتباه\n        self.attention = Attention(hidden_dim=128)\n        \n        # طبقات التصنيف النهائية\n        self.fc1 = nn.Linear(128, 64)\n        self.dropout = nn.Dropout(0.5)\n        self.fc2 = nn.Linear(64, num_classes)\n\n    def forward(self, x):\n        x = self.conv1(x)\n        x = self.bn1(x)\n        x = self.relu(x)\n        x = x.permute(0, 2, 1)\n        lstm_out, _ = self.lstm(x)\n        context_vector, attn_weights = self.attention(lstm_out)\n        out = self.fc1(context_vector)\n        out = self.relu(out)\n        out = self.dropout(out)\n        out = self.fc2(out)\n        return out\n\n# إنشاء المودل وإعطائه عدد المستشعرات الموجودة في بياناتك (الرقم الثاني في الـ shape)\nmodel = HTSAN(input_channels=X_tensor.shape[1], num_classes=2)\n\nprint(\"🏭 تم بناء المصنع (المودل) وتغذيته بالبيانات الجاهزة وهو مستعد للتدريب!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-10T21:01:27.919040Z","iopub.execute_input":"2026-04-10T21:01:27.920203Z","iopub.status.idle":"2026-04-10T21:01:27.995241Z","shell.execute_reply.started":"2026-04-10T21:01:27.920161Z","shell.execute_reply":"2026-04-10T21:01:27.993726Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nfrom torch.utils.data import TensorDataset, DataLoader\n\n# ==========================================\n# 1. تطبيق الـ Z-Score Normalization (كما طلبت الورقة)\n# ==========================================\nprint(\"⚖️ جاري عمل تسوية (Normalization) للـ 58 مستشعراً...\")\n# نحسب المتوسط والانحراف المعياري لكل مستشعر\nmean = X_tensor.mean(dim=(0, 2), keepdim=True)\nstd = X_tensor.std(dim=(0, 2), keepdim=True)\nstd[std == 0] = 1e-5 # لتجنب القسمة على صفر\n\n# المعادلة الأساسية للتسوية\nX_normalized = (X_tensor - mean) / std\nprint(\"✅ تمت التسوية بنجاح!\\n\")\n\n# ==========================================\n# 2. تجهيز البيانات للتدريب\n# ==========================================\n# نضع البيانات في \"عربات\" (Batches) حجمها 16 نافذة كما هو معتاد\ndataset = TensorDataset(X_normalized, y_tensor)\ndataloader = DataLoader(dataset, batch_size=16, shuffle=True)\n\n# إعداد محرك التدريب (Adam) بسرعة 0.001 (بالضبط كما في الورقة)\nlearning_rate = 0.001\noptimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)\ncriterion = nn.CrossEntropyLoss()\n\n# ==========================================\n# 3. بدء التدريب الفعلي (Training Loop)\n# ==========================================\nnum_epochs = 15 # سنجعله يتدرب 15 مرة متتالية\nprint(\"🚀 بدء تدريب مودل HTSAN المطور...\\n\")\n\nfor epoch in range(num_epochs):\n    model.train() # وضع المودل في حالة التعلم\n    total_loss = 0\n    correct_predictions = 0\n    total_samples = 0\n    \n    for batch_X, batch_y in dataloader:\n        optimizer.zero_grad() # تصفير الذاكرة\n        \n        # 1. التوقع\n        outputs = model(batch_X)\n        \n        # 2. حساب نسبة الخطأ\n        loss = criterion(outputs, batch_y)\n        \n        # 3. التعلم وتعديل الأوزان\n        loss.backward()\n        optimizer.step()\n        \n        # حساب الإحصائيات لعرضها\n        total_loss += loss.item()\n        _, predicted = torch.max(outputs.data, 1)\n        total_samples += batch_y.size(0)\n        correct_predictions += (predicted == batch_y).sum().item()\n        \n    # حساب المتوسطات وطباعة النتيجة\n    epoch_loss = total_loss / len(dataloader)\n    epoch_accuracy = (correct_predictions / total_samples) * 100\n    \n    print(f\"الدورة [{epoch+1:02d}/{num_epochs}] | نسبة الخطأ (Loss): {epoch_loss:.4f} | الدقة (Accuracy): {epoch_accuracy:.2f}%\")\n\nprint(\"\\n🏁 مبروك! المودل تدرب بنجاح ويعمل بكفاءة.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-10T21:11:15.409683Z","iopub.execute_input":"2026-04-10T21:11:15.410702Z","iopub.status.idle":"2026-04-10T21:11:32.584429Z","shell.execute_reply.started":"2026-04-10T21:11:15.410660Z","shell.execute_reply":"2026-04-10T21:11:32.583383Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport pandas as pd\nimport numpy as np\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import TensorDataset, DataLoader\n\n# ==========================================\n# 1. استخراج كل البيانات (الـ 12 مريض)\n# ==========================================\nmain_path = '/kaggle/input/datasets/mennahashraf29/muli-data/Filtered Data'\nwindow_size = 1000\nstep_size = 500\n\nall_X = []\nall_y = []\n\nprint(\"⏳ المرحلة 1: جاري البحث في ملفات كل المرضى وجمع البيانات (يرجى الانتظار، قد يستغرق هذا وقتاً)...\\n\")\n\nfor root, dirs, files in os.walk(main_path):\n    for file in files:\n        if file.endswith('.txt'):\n            file_path = os.path.join(root, file)\n            try:\n                # قراءة الملف\n                df = pd.read_csv(file_path, sep=',', header=None)\n                \n                # التأكد من وجود الـ 61 عموداً\n                if df.shape[1] >= 61:\n                    X_raw = df.iloc[:, 2:60].values # المستشعرات الـ 58\n                    y_raw = df.iloc[:, 60].values   # التصنيف\n                    \n                    # تقطيع النافذة المنزلقة\n                    for i in range(0, len(X_raw) - window_size, step_size):\n                        window = X_raw[i : i + window_size]\n                        if len(window) == window_size:\n                            label = np.bincount(y_raw[i : i + window_size].astype(int)).argmax()\n                            all_X.append(window)\n                            all_y.append(label)\n            except Exception as e:\n                pass # تجاهل الملفات المعطوبة إن وجدت بصمت\n\nprint(f\"✅ انتهى التجميع! تم استخراج عدد ضخم من النوافذ: {len(all_X)} نافذة.\")\n\n# ==========================================\n# 2. تحويل البيانات وتطبيق الـ Normalization\n# ==========================================\nprint(\"\\n⚖️ المرحلة 2: جاري تحويل البيانات وتطبيق التسوية (Z-Score Normalization)...\")\nX_tensor = torch.tensor(np.array(all_X), dtype=torch.float32).permute(0, 2, 1)\ny_tensor = torch.tensor(np.array(all_y), dtype=torch.long)\n\nmean = X_tensor.mean(dim=(0, 2), keepdim=True)\nstd = X_tensor.std(dim=(0, 2), keepdim=True)\nstd[std == 0] = 1e-5\n\nX_normalized = (X_tensor - mean) / std\nprint(\"✅ التسوية تمت بنجاح!\")\n\n# ==========================================\n# 3. التدريب الشامل للمودل\n# ==========================================\nprint(\"\\n🚀 المرحلة 3: بدء التدريب الفعلي الشامل...\")\n\n# كبرنا حجم العربة (Batch Size) إلى 64 لأن البيانات أصبحت ضخمة لتسريع التدريب\ndataset = TensorDataset(X_normalized, y_tensor)\ndataloader = DataLoader(dataset, batch_size=64, shuffle=True)\n\nlearning_rate = 0.001\noptimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)\ncriterion = nn.CrossEntropyLoss()\n\nnum_epochs = 15 \n\nfor epoch in range(num_epochs):\n    model.train()\n    total_loss = 0\n    correct_predictions = 0\n    total_samples = 0\n    \n    for batch_X, batch_y in dataloader:\n        optimizer.zero_grad()\n        outputs = model(batch_X)\n        loss = criterion(outputs, batch_y)\n        loss.backward()\n        optimizer.step()\n        \n        total_loss += loss.item()\n        _, predicted = torch.max(outputs.data, 1)\n        total_samples += batch_y.size(0)\n        correct_predictions += (predicted == batch_y).sum().item()\n        \n    epoch_loss = total_loss / len(dataloader)\n    epoch_accuracy = (correct_predictions / total_samples) * 100\n    print(f\"الدورة [{epoch+1:02d}/{num_epochs}] | الخطأ: {epoch_loss:.4f} | الدقة: {epoch_accuracy:.2f}%\")\n\nprint(\"\\n🏆 اكتمل تدريب مودل Multimodal النهائي بنجاح باهر!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-10T21:14:16.401722Z","iopub.execute_input":"2026-04-10T21:14:16.403128Z","iopub.status.idle":"2026-04-10T22:14:55.363491Z","shell.execute_reply.started":"2026-04-10T21:14:16.403083Z","shell.execute_reply":"2026-04-10T22:14:55.359046Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}