{"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":3004,"databundleVersionId":861823,"sourceType":"competition"}],"dockerImageVersionId":31153,"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)\nimport torch\nfrom sklearn.model_selection import train_test_split\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,"execution":{"iopub.status.busy":"2025-10-27T19:51:19.487578Z","iopub.execute_input":"2025-10-27T19:51:19.487880Z","iopub.status.idle":"2025-10-27T19:51:20.259509Z","shell.execute_reply.started":"2025-10-27T19:51:19.487857Z","shell.execute_reply":"2025-10-27T19:51:20.258503Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = \"cuda\" if torch.cuda.is_available() else \"cpu\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-27T19:51:20.261337Z","iopub.execute_input":"2025-10-27T19:51:20.261777Z","iopub.status.idle":"2025-10-27T19:51:20.268656Z","shell.execute_reply.started":"2025-10-27T19:51:20.261754Z","shell.execute_reply":"2025-10-27T19:51:20.267325Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.read_csv('/kaggle/input/digit-recognizer/train.csv')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-27T19:51:20.269600Z","iopub.execute_input":"2025-10-27T19:51:20.269857Z","iopub.status.idle":"2025-10-27T19:51:22.654598Z","shell.execute_reply.started":"2025-10-27T19:51:20.269835Z","shell.execute_reply":"2025-10-27T19:51:22.653546Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df, test_df = train_test_split(df, test_size=0.2, random_state=42)\n\ntrain_df = train_df.to_numpy()\ntest_df = test_df.to_numpy()\n\nx_train, y_train = train_df[:, 1:].astype(np.float32), train_df[:, 0].astype(np.int64)\nx_test, y_test = test_df[:, 1:].astype(np.float32), test_df[:, 0].astype(np.int64)\n\nx_train /= 255.0\nx_test /= 255.0\n\nx_train, y_train, x_test, y_test = map(torch.tensor, [x_train, y_train, x_test, y_test])\nx_train, y_train, x_test, y_test = [t.to(device) for t in [x_train, y_train, x_test, y_test]]\n\nprint(\"Training data shape:\", x_train.shape)\nprint(\"Test data shape:\", x_test.shape)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-27T19:51:22.655498Z","iopub.execute_input":"2025-10-27T19:51:22.655728Z","iopub.status.idle":"2025-10-27T19:51:23.105256Z","shell.execute_reply.started":"2025-10-27T19:51:22.655708Z","shell.execute_reply":"2025-10-27T19:51:23.104225Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def relu(x):\n    return x.clamp(min=0)\n\ndef batch_norm(x, gamma):\n    batch_mean = x.mean(dim=0)\n    batch_var = (x - batch_mean).var(dim=0)\n    x_norm = (x - batch_mean) / torch.sqrt(batch_var + eps)\n    return gamma * x_norm\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-27T19:51:23.107656Z","iopub.execute_input":"2025-10-27T19:51:23.107953Z","iopub.status.idle":"2025-10-27T19:51:23.113729Z","shell.execute_reply.started":"2025-10-27T19:51:23.107931Z","shell.execute_reply":"2025-10-27T19:51:23.112683Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"eps = 1e-6\nBATCH_SIZE = 64\nepochs = 50\nlr = 1e-3\nhidden1 = 256\nhidden2 = 128\ninput_dim = 784\noutput_dim = 10\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-27T19:51:23.114805Z","iopub.execute_input":"2025-10-27T19:51:23.115235Z","iopub.status.idle":"2025-10-27T19:51:23.135431Z","shell.execute_reply.started":"2025-10-27T19:51:23.115207Z","shell.execute_reply":"2025-10-27T19:51:23.134405Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def init_params():\n    limit1 = (1.0 / input_dim) ** 0.5\n    w1 = (2 * torch.rand(hidden1, input_dim, device=device) - 1) * limit1\n    b1 = torch.zeros(hidden1, device=device)\n\n    limit2 = (1.0 / hidden1) ** 0.5\n    w2 = (2 * torch.rand(hidden2, hidden1, device=device) - 1) * limit2\n    b2 = torch.zeros(hidden2, device=device)\n\n    limit3 = (1.0 / hidden2) ** 0.5\n    w3 = (2 * torch.rand(output_dim, hidden2, device=device) - 1) * limit3\n    b3 = torch.zeros(output_dim, device=device)\n\n    params = [w1, b1, w2, b2, w3, b3]\n    for p in params:\n        p.requires_grad = True\n    return params\n\nw1, b1, w2, b2, w3, b3 = init_params()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-27T19:51:23.136459Z","iopub.execute_input":"2025-10-27T19:51:23.136809Z","iopub.status.idle":"2025-10-27T19:51:23.216390Z","shell.execute_reply.started":"2025-10-27T19:51:23.136777Z","shell.execute_reply":"2025-10-27T19:51:23.215272Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def model(x):\n    x = relu(x @ w1.T + b1)\n    x = relu(x @ w2.T + b2)\n    x = x @ w3.T + b3\n    return x\n\ndef cross_entropy(y_pred, y_true):\n    logprobs = torch.log_softmax(y_pred, dim=1)\n    loss = -logprobs[torch.arange(len(y_true)), y_true].mean()\n    return loss\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-27T19:51:23.217622Z","iopub.execute_input":"2025-10-27T19:51:23.217942Z","iopub.status.idle":"2025-10-27T19:51:23.224211Z","shell.execute_reply.started":"2025-10-27T19:51:23.217909Z","shell.execute_reply":"2025-10-27T19:51:23.222933Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import TensorDataset, DataLoader\n\ntrain_ds = TensorDataset(x_train, y_train)\ntrain_dl = DataLoader(train_ds, batch_size=BATCH_SIZE, shuffle=True)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-27T19:51:23.224851Z","iopub.execute_input":"2025-10-27T19:51:23.225129Z","iopub.status.idle":"2025-10-27T19:51:23.243131Z","shell.execute_reply.started":"2025-10-27T19:51:23.225109Z","shell.execute_reply":"2025-10-27T19:51:23.242137Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for epoch in range(epochs):\n    total_loss = 0\n    for x_b, y_b in train_dl:\n        y_pred = model(x_b)\n        loss = cross_entropy(y_pred, y_b)\n        loss.backward()\n\n        with torch.no_grad():\n            w1 -= lr * w1.grad\n            b1 -= lr * b1.grad\n            w2 -= lr * w2.grad\n            b2 -= lr * b2.grad\n            w3 -= lr * w3.grad\n            b3 -= lr * b3.grad\n\n            for p in [w1, b1, w2, b2, w3, b3]:\n                p.grad.zero_()\n\n        total_loss += loss.item()\n\n    print(f\"Epoch {epoch+1}/{epochs} - Loss: {total_loss/len(train_dl):.4f}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-27T19:51:23.244253Z","iopub.execute_input":"2025-10-27T19:51:23.244661Z","iopub.status.idle":"2025-10-27T19:53:23.829780Z","shell.execute_reply.started":"2025-10-27T19:51:23.244633Z","shell.execute_reply":"2025-10-27T19:53:23.828729Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with torch.no_grad():\n    preds = model(x_test)\n    acc = (preds.argmax(dim=1) == y_test).float().mean()\n    print(f\"Test Accuracy: {acc.item()*100:.2f}%\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-27T19:53:23.830929Z","iopub.execute_input":"2025-10-27T19:53:23.831397Z","iopub.status.idle":"2025-10-27T19:53:23.880275Z","shell.execute_reply.started":"2025-10-27T19:53:23.831367Z","shell.execute_reply":"2025-10-27T19:53:23.879236Z"}},"outputs":[],"execution_count":null}]}