{"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,"isSourceIdPinned":false,"sourceType":"competition"}],"dockerImageVersionId":31089,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# Import necessary libraries\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nimport numpy as np\nimport pandas as pd\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import StandardScaler\nfrom sklearn.metrics import accuracy_score, classification_report, confusion_matrix, ConfusionMatrixDisplay\nimport matplotlib.pyplot as plt\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,"execution":{"iopub.status.busy":"2025-08-10T22:41:22.585906Z","iopub.execute_input":"2025-08-10T22:41:22.586321Z","iopub.status.idle":"2025-08-10T22:41:22.599932Z","shell.execute_reply.started":"2025-08-10T22:41:22.586293Z","shell.execute_reply":"2025-08-10T22:41:22.598165Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# --- 1. Mock Data Generation (for demonstration) ---\n# In a real scenario, you would load data from a file (e.g., CSV).\ndef generate_mock_data(num_samples=1000, sequence_length=50, num_sensors=5):\n    \"\"\"\n    Generates a mock dataset of time-series sensor data.\n    Simulates two distinct behaviors (labels 0 and 1).\n    \"\"\"\n    X = np.random.randn(num_samples, sequence_length, num_sensors)\n    y = np.zeros(num_samples, dtype=int)\n\n    # Introduce a pattern for a specific behavior (e.g., label 1)\n    for i in range(num_samples // 2, num_samples):\n        # Add a sine wave pattern to a few sensors for behavior 1\n        t = np.linspace(0, 2 * np.pi, sequence_length)\n        pattern = np.sin(t) * 2 + np.cos(t * 3)\n        # Add the pattern with some additional random noise to make the problem harder\n        X[i, :, 0] += pattern + np.random.randn(sequence_length) * 0.5\n        y[i] = 1\n\n    return X, y\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-10T22:41:22.602071Z","iopub.execute_input":"2025-08-10T22:41:22.602810Z","iopub.status.idle":"2025-08-10T22:41:22.635225Z","shell.execute_reply.started":"2025-08-10T22:41:22.602768Z","shell.execute_reply":"2025-08-10T22:41:22.633712Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# --- 2. PyTorch Dataset and DataLoader ---\nclass SensorDataset(Dataset):\n    \"\"\"\n    Custom PyTorch Dataset for our sensor data.\n    \"\"\"\n    def __init__(self, features, labels):\n        # Convert numpy arrays to PyTorch tensors\n        self.features = torch.tensor(features, dtype=torch.float32)\n        self.labels = torch.tensor(labels, dtype=torch.long)\n\n    def __len__(self):\n        return len(self.labels)\n\n    def __getitem__(self, idx):\n        return self.features[idx], self.labels[idx]\n\n# --- 3. Neural Network Model Definition ---\nclass BehaviorDetector(nn.Module):\n    \"\"\"\n    A simple neural network for classifying time-series sensor data.\n    This uses a combination of a simple Recurrent Neural Network (RNN) layer\n    to process the sequence and a fully-connected layer for classification.\n    \"\"\"\n    def __init__(self, input_size, hidden_size, num_layers, num_classes):\n        super().__init__()\n        self.hidden_size = hidden_size\n        self.num_layers = num_layers\n        \n        # RNN layer to process the time-series data\n        # batch_first=True means the input tensor has shape (batch, sequence, features)\n        self.rnn = nn.RNN(input_size, hidden_size, num_layers, batch_first=True)\n        \n        # Fully-connected layer for final classification\n        self.fc = nn.Linear(hidden_size, num_classes)\n\n    def forward(self, x):\n        # Initialize hidden state with zeros\n        h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)\n        \n        # Pass the input through the RNN layer\n        out, _ = self.rnn(x, h0)\n        \n        # Get the output of the last time step for classification\n        out = self.fc(out[:, -1, :])\n        return out","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-10T22:41:22.636919Z","iopub.execute_input":"2025-08-10T22:41:22.637279Z","iopub.status.idle":"2025-08-10T22:41:22.668720Z","shell.execute_reply.started":"2025-08-10T22:41:22.637253Z","shell.execute_reply":"2025-08-10T22:41:22.667220Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# --- 4. Main Execution Block ---\nif __name__ == \"__main__\":\n    print(\"Generating mock sensor data...\")\n    X, y = generate_mock_data()\n    \n    # --- Data Visualization: Plotting mock data for different behaviors ---\n    # This helps us understand what the model needs to learn.\n    plt.figure(figsize=(12, 6))\n    \n    # Find indices of a few samples for each behavior\n    behavior_0_idx = np.where(y == 0)[0][:3]\n    behavior_1_idx = np.where(y == 1)[0][:3]\n\n    # Plot the first sensor's data for Behavior 0 samples\n    for i, idx in enumerate(behavior_0_idx):\n        plt.plot(X[idx, :, 0], label=f'Behavior 0 Sample {i+1}', linestyle='--')\n    \n    # Plot the first sensor's data for Behavior 1 samples\n    for i, idx in enumerate(behavior_1_idx):\n        plt.plot(X[idx, :, 0], label=f'Behavior 1 Sample {i+1}', linestyle='-')\n    \n    plt.title('Sample Sensor Data for Two Different Behaviors')\n    plt.xlabel('Time Step')\n    plt.ylabel('Sensor Value')\n    plt.legend()\n    plt.grid(True)\n    plt.show()\n\n    # Split data into training and testing sets\n    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)\n    \n    # Scale the features\n    # This is a critical step for many ML models, especially neural networks.\n    # We fit the scaler on the training data only to avoid data leakage.\n    scaler = StandardScaler()\n    \n    # Reshape the data for scaling\n    X_train_reshaped = X_train.reshape(-1, X_train.shape[-1])\n    X_test_reshaped = X_test.reshape(-1, X_test.shape[-1])\n    \n    X_train_scaled = scaler.fit_transform(X_train_reshaped).reshape(X_train.shape)\n    X_test_scaled = scaler.transform(X_test_reshaped).reshape(X_test.shape)\n    \n    # Create datasets and dataloaders\n    train_dataset = SensorDataset(X_train_scaled, y_train)\n    test_dataset = SensorDataset(X_test_scaled, y_test)\n\n    train_loader = DataLoader(dataset=train_dataset, batch_size=32, shuffle=True)\n    test_loader = DataLoader(dataset=test_dataset, batch_size=32, shuffle=False)\n\n    # Hyperparameters\n    input_size = X.shape[2]\n    hidden_size = 64\n    num_layers = 2\n    num_classes = 2 # Behavior 0 or Behavior 1\n    learning_rate = 0.001\n    num_epochs = 10\n    \n    # Initialize a list to store loss for plotting\n    loss_history = []\n\n    # Initialize model, loss function, and optimizer\n    model = BehaviorDetector(input_size, hidden_size, num_layers, num_classes)\n    criterion = nn.CrossEntropyLoss()\n    optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)\n\n    print(\"\\nStarting model training...\")\n    # Training loop\n    for epoch in range(num_epochs):\n        model.train()\n        for i, (features, labels) in enumerate(train_loader):\n            # Forward pass\n            outputs = model(features)\n            loss = criterion(outputs, labels)\n            \n            # Backward and optimize\n            optimizer.zero_grad()\n            loss.backward()\n            optimizer.step()\n            \n        # Store the final loss for the epoch for visualization\n        loss_history.append(loss.item())\n        print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')\n\n    print(\"\\nTraining complete. Evaluating model on test data...\")\n    # Evaluation loop\n    model.eval()\n    with torch.no_grad():\n        y_true = []\n        y_pred = []\n        for features, labels in test_loader:\n            outputs = model(features)\n            _, predicted = torch.max(outputs.data, 1)\n            \n            y_true.extend(labels.tolist())\n            y_pred.extend(predicted.tolist())\n\n    # Calculate and print final accuracy and classification report\n    final_accuracy = accuracy_score(y_true, y_pred)\n    print(f\"\\nFinal Test Accuracy: {final_accuracy:.4f}\")\n    print(\"\\nClassification Report:\")\n    print(classification_report(y_true, y_pred))\n\n    # --- Data Visualization: Plotting training loss ---\n    plt.figure(figsize=(10, 6))\n    plt.plot(loss_history, marker='o')\n    plt.title('Training Loss over Epochs')\n    plt.xlabel('Epoch')\n    plt.ylabel('Loss')\n    plt.grid(True)\n    plt.show() \n\n    # --- Data Visualization: Plotting the Confusion Matrix ---\n    # This shows the breakdown of correct and incorrect predictions for each class.\n    cm = confusion_matrix(y_true, y_pred)\n    disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=['Behavior 0', 'Behavior 1'])\n    disp.plot(cmap=plt.cm.Blues)\n    plt.title('Confusion Matrix')\n    plt.show()\n ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-10T22:41:22.674195Z","iopub.execute_input":"2025-08-10T22:41:22.677499Z","iopub.status.idle":"2025-08-10T22:41:29.319184Z","shell.execute_reply.started":"2025-08-10T22:41:22.677415Z","shell.execute_reply":"2025-08-10T22:41:29.316714Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}