{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":48750,"databundleVersionId":5157702,"sourceType":"competition"},{"sourceId":11355053,"sourceType":"datasetVersion","datasetId":7106048}],"dockerImageVersionId":31012,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import torch\nfrom torch.utils.data import Dataset\nfrom torchvision import datasets\nfrom torchvision.transforms import ToTensor\nimport matplotlib.pyplot as plt\nfrom torch import nn\nimport pandas as pd","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T07:49:56.394560Z","iopub.execute_input":"2025-04-20T07:49:56.394813Z","iopub.status.idle":"2025-04-20T07:50:04.991282Z","shell.execute_reply.started":"2025-04-20T07:49:56.394788Z","shell.execute_reply":"2025-04-20T07:50:04.990732Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nfrom torchvision.io import read_image\nfrom torchvision.transforms import v2\nfrom torchvision import transforms\n\n\nclass ImageDataset(Dataset):\n    def __init__(self, annotations_file, img_dir, transform=None, target_transform=True):\n        self.img_labels = pd.read_csv(annotations_file)\n        self.img_dir = img_dir\n        self.transform=transform\n        self.target_transform=target_transform\n        \n    \n    def __len__(self):\n        return len(self.img_labels)\n\n    def _fill(self, num):\n        n=str(num)\n        return '0'*(6-len(n))+n+'.png'\n            \n        \n    def __getitem__(self, idx):\n        path=self._fill(self.img_labels.iloc[idx, 0])\n        img_path = os.path.join(self.img_dir, path)\n        image = read_image(img_path)[0].float()\n        label = torch.tensor([self.img_labels.iloc[idx, 1]], dtype=torch.float32)\n\n        # normalize\n        image = image/255.0\n        if self.target_transform:\n            label = label/100.0\n      \n        return image, label\n\n\nage_ds=ImageDataset(\"/kaggle/input/spr-x-ray-age/train_age.csv\", \n               \"/kaggle/input/spr-x-ray-age/kaggle/kaggle/train\")\n\ngender_ds=ImageDataset(\"/kaggle/input/x-ray-train-gender/train_gender.csv\", \n               \"/kaggle/input/spr-x-ray-age/kaggle/kaggle/train\", target_transform=False)\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T07:50:09.852174Z","iopub.execute_input":"2025-04-20T07:50:09.852627Z","iopub.status.idle":"2025-04-20T07:50:10.114389Z","shell.execute_reply.started":"2025-04-20T07:50:09.852606Z","shell.execute_reply":"2025-04-20T07:50:10.113873Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\ndef plot(img, label):\n    img*=255.0\n    img = img.numpy().astype(np.uint8)\n    plt.imshow(img, cmap='gray')\n    plt.axis('off')\n    plt.title(f\"{label}\")\n    plt.show()\n\nplot(*age_ds[0])\nplot(*age_ds[341])\nimg, label=age_ds[341]\nprint(img)\nprint(label)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T00:45:32.953585Z","iopub.execute_input":"2025-04-19T00:45:32.954125Z","iopub.status.idle":"2025-04-19T00:45:33.393973Z","shell.execute_reply.started":"2025-04-19T00:45:32.954105Z","shell.execute_reply":"2025-04-19T00:45:33.393349Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Check the Alpha channel, if all 255, we can safely delete alpha channel\n\"\"\" \nl=len(ds)\nfor i in range(l):\n    image,label=ds[i]\n    alpha = image[3].numpy() #tested when there are 4 channels\n    if i%1000==0:\n        print(f\"Processing the {i}th image\")\n    if not np.all(alpha == 255):\n        print(f\"{image} has non-255 alpha values!\")\n        break\n\"\"\"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import DataLoader\nfrom sklearn.model_selection import KFold\nfrom torch.utils.data import Subset\n\ndef generate_dataloader(ds, workers=4, bs=64,val_bs=64): \n    kf = KFold(n_splits=5, shuffle=True, random_state=42)\n    \n    train_idx, val_idx=next(iter(kf.split(ds)))\n    \n    train_subset = Subset(ds, train_idx)\n    val_subset = Subset(ds, val_idx)\n\n    train_loader = DataLoader(train_subset, batch_size=bs, shuffle=True, num_workers=workers, pin_memory=True)\n    val_loader = DataLoader(val_subset, batch_size=val_bs, shuffle=False,num_workers=workers, pin_memory=True)\n    return train_loader, val_loader\n\nage_loader, age_val_loader=generate_dataloader(age_ds)\ngender_loader, gender_val_loader=generate_dataloader(gender_ds)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T07:50:21.235372Z","iopub.execute_input":"2025-04-20T07:50:21.235963Z","iopub.status.idle":"2025-04-20T07:50:21.891950Z","shell.execute_reply.started":"2025-04-20T07:50:21.235939Z","shell.execute_reply":"2025-04-20T07:50:21.891136Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_feature, label=next(iter(age_loader))\nprint(train_feature.size())\nprint(label.size())\nprint(train_feature)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-15T03:25:39.577604Z","iopub.execute_input":"2025-04-15T03:25:39.577949Z","iopub.status.idle":"2025-04-15T03:25:47.852026Z","shell.execute_reply.started":"2025-04-15T03:25:39.577925Z","shell.execute_reply":"2025-04-15T03:25:47.851049Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"net_1_age = nn.Sequential(nn.Flatten(), nn.Linear(1024*1024, 1)) ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T02:44:58.589161Z","iopub.execute_input":"2025-04-20T02:44:58.589420Z","iopub.status.idle":"2025-04-20T02:44:58.603128Z","shell.execute_reply.started":"2025-04-20T02:44:58.589403Z","shell.execute_reply":"2025-04-20T02:44:58.602628Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"x=nn.Flatten()(train_feature)\nx.size()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-14T07:42:20.352162Z","iopub.execute_input":"2025-04-14T07:42:20.352767Z","iopub.status.idle":"2025-04-14T07:42:20.357636Z","shell.execute_reply.started":"2025-04-14T07:42:20.352742Z","shell.execute_reply":"2025-04-14T07:42:20.356916Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch import optim\n\n# def init_weights(l):\n#     if type(l) == nn.Linear:\n#         nn.init.normal_(l.weight, std=0.01)\n\ndef train(ep, model, optimizer, loss_func, data_loader, device, val_loader):\n    \n    model=model.to(device)\n    model.train()\n    # model.apply(init_weights)\n    total=len(data_loader)\n    val_loss=[]\n    train_loss=[]\n    for e in range(ep):\n        for i, batch in enumerate(data_loader):\n            train, label = batch\n            train, label = train.to(device), label.to(device)\n            \n            X=model(train)\n            loss=loss_func(X, label)\n            with torch.no_grad():\n                if i%10==0:\n                    print(f\"Epoch {e+1}/{ep}, Process {i}/{total}th batch, loss: {loss.item()}\")\n                if e>0 and i%50==0:\n                    train_loss.append(loss.item())\n            loss.backward()\n            # torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)\n            optimizer.step()\n            optimizer.zero_grad()\n            \n        total_loss=0\n        with torch.no_grad():\n            for batch in val_loader:\n                inputs, targets = batch\n                inputs, targets=inputs.to(device), targets.to(device)\n                outputs = model(inputs)\n    \n                loss = loss_func(outputs, targets)\n                total_loss += loss.item() * inputs.size(0)\n            val_loss.append(total_loss/len(val_loader.dataset))\n        \n        # scheduler.step()\n        # print(f\"Epoch {e}, LR: {optimizer.param_groups[0]['lr']:.6f}\")\n        \n    fig, ax = plt.subplots()\n    ax.plot(train_loss, 'o-', markeredgewidth=2)\n    ax.plot(val_loss, linewidth=2.0)\n    plt.show()\n    \ndef validate_gender(model, loss_func, data_loader, device):\n    model=model.to(device)\n    model.eval()\n    correct=0\n    total_loss=0\n    total=0\n    with torch.no_grad():\n        for batch in data_loader:\n            inputs, targets = batch\n            inputs, targets=inputs.to(device), targets.to(device)\n            outputs = model(inputs)\n\n            loss = loss_func(outputs, targets)\n            total_loss += loss.item() * inputs.size(0)\n            \n            # change outputs to [0,1]\n            probs = torch.sigmoid(outputs)\n            \n            # preds=0 or 1 \n            preds = (probs > 0.5).float()  \n            \n            correct += (preds == targets).sum().item()\n            total += targets.size(0)\n    \n    avg_loss = total_loss / total\n    accuracy = correct / total\n    print(f\"Accuracy: {accuracy}, Avg Loss:{avg_loss}\")\n            \n  \n\ndef validate_age(model, loss_func, data_loader, device):\n    model=model.to(device)\n    model.eval()\n    losses=0\n    val_loss=[]\n    preds_list=[]\n    labels_list=[]\n    with torch.no_grad():\n        for i, batch in enumerate(data_loader):\n            \n            inputs, targets = batch\n            inputs, targets=inputs.to(device), targets.to(device)\n            outputs = model(inputs)\n            loss=loss_func(outputs, targets)\n            if i%5==0:\n                val_loss.append(loss.item())\n            losses+=loss\n\n            preds_list.append(outputs * 100)  \n            labels_list.append(targets * 100)\n\n    preds_all = torch.cat(preds_list)\n    labels_all = torch.cat(labels_list)\n    mae = torch.mean(torch.abs(preds_all - labels_all))\n    return mae.item()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T02:43:55.569869Z","iopub.execute_input":"2025-04-20T02:43:55.570138Z","iopub.status.idle":"2025-04-20T02:43:55.582197Z","shell.execute_reply.started":"2025-04-20T02:43:55.570117Z","shell.execute_reply":"2025-04-20T02:43:55.581493Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T07:50:32.392029Z","iopub.execute_input":"2025-04-20T07:50:32.392433Z","iopub.status.idle":"2025-04-20T07:50:32.476021Z","shell.execute_reply.started":"2025-04-20T07:50:32.392410Z","shell.execute_reply":"2025-04-20T07:50:32.475066Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.optim import lr_scheduler\ntrain(10, net_1_age, optim.Adam(net_1_age.parameters(), lr=0.001), nn.MSELoss(),age_loader,device, age_val_loader)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T02:45:01.952438Z","iopub.execute_input":"2025-04-20T02:45:01.952744Z","iopub.status.idle":"2025-04-20T03:06:46.495423Z","shell.execute_reply.started":"2025-04-20T02:45:01.952702Z","shell.execute_reply":"2025-04-20T03:06:46.494765Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"feature, label=next(iter(age_val_loader))\nfeature, label=feature.to(device), label.to(device)\nprint(feature.size())\npred=net_1_age.to(device)(feature)\nprint(pred.view(1,-1))\nprint(label.view(1,-1))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T01:35:35.339284Z","iopub.execute_input":"2025-04-19T01:35:35.339865Z","iopub.status.idle":"2025-04-19T01:35:41.650717Z","shell.execute_reply.started":"2025-04-19T01:35:35.339841Z","shell.execute_reply":"2025-04-19T01:35:41.649810Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"validate_age(net_1_age, nn.MSELoss(), age_val_loader,device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T03:09:08.204032Z","iopub.execute_input":"2025-04-20T03:09:08.204691Z","iopub.status.idle":"2025-04-20T03:09:35.256118Z","shell.execute_reply.started":"2025-04-20T03:09:08.204667Z","shell.execute_reply":"2025-04-20T03:09:35.255154Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"del net_1_age\ntorch.cuda.empty_cache()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T02:01:21.861138Z","iopub.execute_input":"2025-04-19T02:01:21.861760Z","iopub.status.idle":"2025-04-19T02:01:21.866246Z","shell.execute_reply.started":"2025-04-19T02:01:21.861730Z","shell.execute_reply":"2025-04-19T02:01:21.865552Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"net_1_gender = nn.Sequential(nn.Flatten(), nn.Linear(1024*1024, 1)) \n# train gender\ntrain(5, net_1_gender, optim.Adam(net_1_gender.parameters(), lr=0.0001), nn.BCEWithLogitsLoss(), gender_loader, device, gender_val_loader)\n\n# validate_gender(net_1_gender, nn.BCELoss(), gender_val_loader)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T03:23:10.478370Z","iopub.execute_input":"2025-04-20T03:23:10.478880Z","iopub.status.idle":"2025-04-20T03:33:47.831403Z","shell.execute_reply.started":"2025-04-20T03:23:10.478855Z","shell.execute_reply":"2025-04-20T03:33:47.830668Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"validate_gender(net_1_gender, nn.BCEWithLogitsLoss(), gender_val_loader, device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T03:36:17.602444Z","iopub.execute_input":"2025-04-20T03:36:17.603295Z","iopub.status.idle":"2025-04-20T03:36:44.015752Z","shell.execute_reply.started":"2025-04-20T03:36:17.603267Z","shell.execute_reply":"2025-04-20T03:36:44.014965Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"del net_1_gender\ntorch.cuda.empty_cache()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T03:37:59.883878Z","iopub.execute_input":"2025-04-20T03:37:59.884554Z","iopub.status.idle":"2025-04-20T03:37:59.891138Z","shell.execute_reply.started":"2025-04-20T03:37:59.884528Z","shell.execute_reply":"2025-04-20T03:37:59.890546Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"**Q2-Single Hidden Layer**","metadata":{}},{"cell_type":"code","source":"class SingleLayerNet(nn.Module):\n    def __init__(self, hidden_dim=128):\n        super().__init__()\n        self.net = nn.Sequential(\n            nn.Flatten(),\n            nn.Linear(1024*1024, hidden_dim),\n            nn.ReLU(),\n            nn.Linear(hidden_dim, 1)\n        )\n\n    def forward(self, x):\n        return self.net(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T03:56:57.556394Z","iopub.execute_input":"2025-04-20T03:56:57.557254Z","iopub.status.idle":"2025-04-20T03:56:57.561855Z","shell.execute_reply.started":"2025-04-20T03:56:57.557228Z","shell.execute_reply":"2025-04-20T03:56:57.561145Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"net_2=SingleLayerNet()\n\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\ntrain(5, net_2, optim.Adam(net_2.parameters(), lr=0.001), nn.MSELoss(), age_loader, device, age_val_loader) ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T02:19:05.948986Z","iopub.execute_input":"2025-04-19T02:19:05.949718Z","iopub.status.idle":"2025-04-19T02:30:05.089022Z","shell.execute_reply.started":"2025-04-19T02:19:05.949693Z","shell.execute_reply":"2025-04-19T02:30:05.088231Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"validate_age(net_2, nn.MSELoss(), age_val_loader,device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T02:30:37.374752Z","iopub.execute_input":"2025-04-19T02:30:37.375531Z","iopub.status.idle":"2025-04-19T02:31:04.908383Z","shell.execute_reply.started":"2025-04-19T02:30:37.375492Z","shell.execute_reply":"2025-04-19T02:31:04.907625Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"feature, label=next(iter(age_val_loader))\nfeature, label=feature.to(device), label.to(device)\nprint(feature.size())\npred=net_2.to(device)(feature)\nprint(pred.view(1,-1))\nprint(label.view(1,-1))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T02:33:06.898403Z","iopub.execute_input":"2025-04-19T02:33:06.899090Z","iopub.status.idle":"2025-04-19T02:33:13.686066Z","shell.execute_reply.started":"2025-04-19T02:33:06.899060Z","shell.execute_reply":"2025-04-19T02:33:13.685283Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"del net_2\ntorch.cuda.empty_cache()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T02:33:31.872228Z","iopub.execute_input":"2025-04-19T02:33:31.873001Z","iopub.status.idle":"2025-04-19T02:33:31.886151Z","shell.execute_reply.started":"2025-04-19T02:33:31.872972Z","shell.execute_reply":"2025-04-19T02:33:31.885449Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"net_2_g=SingleLayerNet()\ntrain(5, net_2_g, optim.Adam(net_2_g.parameters(), lr=0.0001), nn.BCEWithLogitsLoss(), gender_loader, device, gender_val_loader)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T03:57:09.955123Z","iopub.execute_input":"2025-04-20T03:57:09.955403Z","iopub.status.idle":"2025-04-20T04:07:48.925314Z","shell.execute_reply.started":"2025-04-20T03:57:09.955384Z","shell.execute_reply":"2025-04-20T04:07:48.924555Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"validate_gender(net_2_g, nn.BCEWithLogitsLoss(), gender_val_loader,device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T04:09:13.301032Z","iopub.execute_input":"2025-04-20T04:09:13.301431Z","iopub.status.idle":"2025-04-20T04:09:38.915506Z","shell.execute_reply.started":"2025-04-20T04:09:13.301399Z","shell.execute_reply":"2025-04-20T04:09:38.914494Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\ndel net_2_g\ntorch.cuda.empty_cache()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T04:10:22.487517Z","iopub.execute_input":"2025-04-20T04:10:22.487954Z","iopub.status.idle":"2025-04-20T04:10:22.505162Z","shell.execute_reply.started":"2025-04-20T04:10:22.487921Z","shell.execute_reply":"2025-04-20T04:10:22.504625Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# test multiple layer model, separated part\nclass MultipleLayerNet(nn.Module):\n    def __init__(self, hidden_dim=512):\n        super().__init__()\n        self.net = nn.Sequential(\n            nn.Flatten(),\n            nn.Linear(1024*1024, hidden_dim),\n            nn.ReLU(),\n            nn.Linear(hidden_dim, 256),\n            nn.ReLU(),\n            nn.Linear(256, 128),\n            nn.ReLU(),\n            nn.Linear(128, 64),\n            nn.ReLU(),\n            nn.Linear(64, 32),\n            nn.ReLU(),\n            nn.Linear(32, 1)\n        )\n\n    def forward(self, x):\n        return self.net(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T04:42:40.702955Z","iopub.execute_input":"2025-04-20T04:42:40.703659Z","iopub.status.idle":"2025-04-20T04:42:40.708380Z","shell.execute_reply.started":"2025-04-20T04:42:40.703635Z","shell.execute_reply":"2025-04-20T04:42:40.707697Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"MLP=MultipleLayerNet()\ntrain(10, MLP, optim.Adam(MLP.parameters(), lr=0.001), nn.MSELoss(), age_loader, device, age_val_loader) ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T04:42:45.843713Z","iopub.execute_input":"2025-04-20T04:42:45.844496Z","iopub.status.idle":"2025-04-20T05:04:25.800420Z","shell.execute_reply.started":"2025-04-20T04:42:45.844472Z","shell.execute_reply":"2025-04-20T05:04:25.799504Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"validate_age(MLP, nn.MSELoss(), age_val_loader,device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T05:05:22.491235Z","iopub.execute_input":"2025-04-20T05:05:22.492221Z","iopub.status.idle":"2025-04-20T05:05:47.999706Z","shell.execute_reply.started":"2025-04-20T05:05:22.492188Z","shell.execute_reply":"2025-04-20T05:05:47.998663Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"del MLP\ntorch.cuda.empty_cache()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T04:42:14.063693Z","iopub.execute_input":"2025-04-20T04:42:14.064609Z","iopub.status.idle":"2025-04-20T04:42:14.083540Z","shell.execute_reply.started":"2025-04-20T04:42:14.064579Z","shell.execute_reply":"2025-04-20T04:42:14.083032Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"MLP_weight_decay=MultipleLayerNet()\ntrain(5, MLP_weight_decay, optim.Adam(MLP_weight_decay.parameters(), lr=0.001, weight_decay=1e-5), nn.MSELoss(), age_loader, device, age_val_loader) ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T04:27:15.195802Z","iopub.execute_input":"2025-04-19T04:27:15.196698Z","iopub.status.idle":"2025-04-19T04:38:17.992457Z","shell.execute_reply.started":"2025-04-19T04:27:15.196666Z","shell.execute_reply":"2025-04-19T04:38:17.991663Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"validate_age(MLP_weight_decay, nn.MSELoss(), age_val_loader,device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T04:38:26.332725Z","iopub.execute_input":"2025-04-19T04:38:26.333055Z","iopub.status.idle":"2025-04-19T04:38:54.356615Z","shell.execute_reply.started":"2025-04-19T04:38:26.333030Z","shell.execute_reply":"2025-04-19T04:38:54.355719Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"del MLP_weight_decay\ntorch.cuda.empty_cache()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T04:42:22.323733Z","iopub.execute_input":"2025-04-19T04:42:22.324608Z","iopub.status.idle":"2025-04-19T04:42:22.341071Z","shell.execute_reply.started":"2025-04-19T04:42:22.324576Z","shell.execute_reply":"2025-04-19T04:42:22.340538Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"**Q3-CNN**","metadata":{}},{"cell_type":"code","source":"class ImageDatasetJoint(Dataset):\n    def __init__(self, annotations_file, gender_file, img_dir, transform=None, target_transform=None):\n        self.img_labels = pd.read_csv(annotations_file)\n        self.gender_labels = pd.read_csv(gender_file)\n        self.img_dir = img_dir\n        \n        # self.max_label=torch.tensor(self.img_labels['age'].max())\n        # self.min_label=torch.tensor(self.img_labels['age'].min())\n    \n    def __len__(self):\n        return len(self.img_labels)\n\n    def _fill(self, num):\n        n=str(num)\n        return '0'*(6-len(n))+n+'.png'\n            \n        \n    def __getitem__(self, idx):\n        path=self._fill(self.img_labels.iloc[idx, 0])\n        img_path = os.path.join(self.img_dir, path)\n        image = read_image(img_path)[0].float().unsqueeze(0)\n        age = torch.tensor([self.img_labels.iloc[idx, 1]], dtype=torch.float32)\n        gender=torch.tensor([self.gender_labels.iloc[idx, 1]], dtype=torch.float32)\n        # normalize\n        image = image/255.0\n        age = age/100.0\n      \n        return image, (age, gender)\n\n\n\nds=ImageDatasetJoint(\"/kaggle/input/spr-x-ray-age/train_age.csv\", \n                    \"/kaggle/input/x-ray-train-gender/train_gender.csv\",\n               \"/kaggle/input/spr-x-ray-age/kaggle/kaggle/train\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T07:50:48.195584Z","iopub.execute_input":"2025-04-20T07:50:48.195964Z","iopub.status.idle":"2025-04-20T07:50:48.210331Z","shell.execute_reply.started":"2025-04-20T07:50:48.195940Z","shell.execute_reply":"2025-04-20T07:50:48.209574Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tot, val=generate_dataloader(ds,4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T07:50:51.452538Z","iopub.execute_input":"2025-04-20T07:50:51.452836Z","iopub.status.idle":"2025-04-20T07:50:51.458100Z","shell.execute_reply.started":"2025-04-20T07:50:51.452816Z","shell.execute_reply":"2025-04-20T07:50:51.457528Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"feature, label=next(iter(tot))\nage, gender= label\nprint(feature.size())\nprint(age.size())\nprint(gender.size())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T00:41:14.417319Z","iopub.execute_input":"2025-04-19T00:41:14.417993Z","iopub.status.idle":"2025-04-19T00:41:21.336116Z","shell.execute_reply.started":"2025-04-19T00:41:14.417958Z","shell.execute_reply":"2025-04-19T00:41:21.335025Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class CNNet(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.conv=nn.Sequential(\n            nn.Conv2d(1, 16, kernel_size=5, stride=2, padding=2), #16*512*512\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=2, stride=2) , #16*256*256\n            \n            nn.Conv2d(16, 32, kernel_size=5, padding=2), #32*256*256\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=2, stride=2), #32*128*128\n\n            nn.Conv2d(32, 64, kernel_size=3, padding=1),#64*128*128\n            nn.ReLU(),\n            nn.AvgPool2d(kernel_size=2, stride=2), #64*64*64\n\n            nn.Conv2d(64, 128, kernel_size=3, padding=1),#128*64*64\n            nn.ReLU(),\n            nn.AvgPool2d(kernel_size=2, stride=2), #128*32*32\n\n            nn.Conv2d(128, 256, kernel_size=3, padding=1),#256*32*32\n            nn.ReLU(),\n            nn.AvgPool2d(kernel_size=4, stride=4) #256*8*8\n        )\n        self.flat=nn.Flatten()\n        # Regression head for age\n        self.reg_head = nn.Sequential(\n            nn.Linear(256 * 8 * 8, 128),\n            nn.ReLU(),\n            nn.Linear(128, 1)\n        )\n\n        # Classification head for gender\n        self.cls_head = nn.Sequential(\n            nn.Linear(256 * 8 * 8, 128),\n            nn.ReLU(),\n            nn.Linear(128, 1)\n        )\n\n    def forward(self, x):\n        x=self.conv(x)\n        x=self.flat(x)\n        age = self.reg_head(x)\n        gender_logits = self.cls_head(x)\n        return age, gender_logits","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T07:50:55.839581Z","iopub.execute_input":"2025-04-20T07:50:55.840399Z","iopub.status.idle":"2025-04-20T07:50:55.847526Z","shell.execute_reply.started":"2025-04-20T07:50:55.840371Z","shell.execute_reply":"2025-04-20T07:50:55.846677Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model=CNNet()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T06:52:00.584863Z","iopub.execute_input":"2025-04-20T06:52:00.585465Z","iopub.status.idle":"2025-04-20T06:52:00.634748Z","shell.execute_reply.started":"2025-04-20T06:52:00.585442Z","shell.execute_reply":"2025-04-20T06:52:00.633961Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train_3(epoch, model, optimizer, ds, device, val_ds):\n    model.to(device)\n    model.train()\n    age_loss=nn.MSELoss()\n    gender_loss=nn.BCEWithLogitsLoss()\n    length=len(ds)\n    train_loss=[]\n    val_loss=[]\n    for ep in range(epoch):\n        for i, batch in enumerate(tot):\n            train, (age, gender)=batch\n            train, age, gender=train.to(device), age.to(device), gender.to(device)\n            age_o, gender_o=model(train)\n            loss=age_loss(age_o, age)+gender_loss(gender_o, gender)\n            with torch.no_grad():\n                if i%10==0:\n                    print(f\"Epoch {ep+1}/{epoch}, processing {i}/{length}, loss: {loss}\")\n                if i%50==0:\n                    train_loss.append(loss.item())\n            loss.backward()\n            optimizer.step()\n            optimizer.zero_grad()\n            \n        total_loss=0\n        with torch.no_grad():\n            for batch in val_ds:\n                inputs, targets = batch\n                age_label, gender_label=targets\n                inputs, age_label, gender_label=inputs.to(device), age_label.to(device), gender_label.to(device)\n                age_o, gender_o = model(inputs)\n    \n                loss = age_loss(age_o, age_label)+gender_loss(gender_o, gender_label)\n                total_loss += loss.item() * inputs.size(0)\n            val_loss.append(total_loss/len(val_ds.dataset))\n        \n    fig, ax = plt.subplots()\n    ax.plot(train_loss, 'o-', markeredgewidth=2)\n    ax.plot(val_loss, linewidth=2.0)\n    plt.show()\n\ndef valuate(model, data_loader, device):\n    model=model.to(device)\n    model.eval()\n    correct=0\n    total_loss=0\n    total=0\n    losses=0\n    preds_list=[]\n    labels_list=[]\n    age_loss=nn.MSELoss()\n    gender_loss=nn.BCEWithLogitsLoss()\n    \n    with torch.no_grad():\n        for i, batch in enumerate(data_loader):\n            inputs, label = batch\n            age, gender=label\n            inputs, age, gender=inputs.to(device), age.to(device), gender.to(device)\n            age_o, gender_o = model(inputs)\n\n            loss = gender_loss(gender_o, gender)\n            total_loss += loss.item() * inputs.size(0)\n        \n            probs = torch.sigmoid(gender_o)\n            \n            preds = (probs > 0.5).float()  \n            \n            correct += (preds == gender).sum().item()\n            total += gender.size(0)\n       \n            # age\n            loss_a=age_loss(age_o, age)\n            losses+=loss_a.item() * inputs.size(0)\n\n            preds_list.append(age_o * 100)  \n            labels_list.append(age * 100)\n\n    avg_loss = total_loss / total\n    accuracy = correct / total\n    print(f\"Accuracy of gender: {accuracy}, Avg Loss:{avg_loss}\")\n    preds_all = torch.cat(preds_list)\n    labels_all = torch.cat(labels_list)\n    mae = torch.mean(torch.abs(preds_all - labels_all))\n    print(f\"MAE of age: {mae}\")\n    return mae.item()\n    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T07:51:02.366789Z","iopub.execute_input":"2025-04-20T07:51:02.367351Z","iopub.status.idle":"2025-04-20T07:51:02.378570Z","shell.execute_reply.started":"2025-04-20T07:51:02.367329Z","shell.execute_reply":"2025-04-20T07:51:02.377904Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_3(10, model, torch.optim.Adam(model.parameters(), lr=0.001), tot, device, val)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T06:52:36.877499Z","iopub.execute_input":"2025-04-20T06:52:36.877841Z","iopub.status.idle":"2025-04-20T07:18:35.341139Z","shell.execute_reply.started":"2025-04-20T06:52:36.877813Z","shell.execute_reply":"2025-04-20T07:18:35.340018Z"},"collapsed":true,"jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"valuate(model, val, device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T07:18:35.342726Z","iopub.execute_input":"2025-04-20T07:18:35.343046Z","iopub.status.idle":"2025-04-20T07:19:05.602686Z","shell.execute_reply.started":"2025-04-20T07:18:35.343020Z","shell.execute_reply":"2025-04-20T07:19:05.601915Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"feature, label=next(iter(gender_val_loader))\nfeature=feature.unsqueeze(1)\nfeature, label=feature.to(device), label.to(device)\nprint(feature.size())\npred=model.to(device)(feature)\nage_pred, gender_pred=pred\nprobs = torch.sigmoid(gender_pred)\npreds = (probs > 0.5).float()\nprint(preds.view(1,-1))\nprint(label.view(1,-1))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T00:40:00.801602Z","iopub.execute_input":"2025-04-19T00:40:00.801892Z","iopub.status.idle":"2025-04-19T00:40:08.230306Z","shell.execute_reply.started":"2025-04-19T00:40:00.801871Z","shell.execute_reply":"2025-04-19T00:40:08.229327Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# this is a separate model, just to check overfitting \nmodel1=CNNet()\ntrain_3(20, model1, torch.optim.Adam(model1.parameters(), lr=0.001), tot, device, val)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T07:51:24.925147Z","iopub.execute_input":"2025-04-20T07:51:24.925412Z","iopub.status.idle":"2025-04-20T08:38:19.628225Z","shell.execute_reply.started":"2025-04-20T07:51:24.925393Z","shell.execute_reply":"2025-04-20T08:38:19.627500Z"},"collapsed":true,"jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"valuate(model1, val, device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T08:38:41.499116Z","iopub.execute_input":"2025-04-20T08:38:41.499758Z","iopub.status.idle":"2025-04-20T08:39:08.936993Z","shell.execute_reply.started":"2025-04-20T08:38:41.499732Z","shell.execute_reply":"2025-04-20T08:39:08.936129Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Example: Visualize first conv layer's feature map\n\nmodel.eval()\nfeature, label=next(iter(val))\nage, gender= label\nimage = feature[1].unsqueeze(0).to(device)  # shape: [1, 1, 1024, 1024]\nprint(image.size())\nfeature_map=image\nwith torch.no_grad():\n    for i in range(0, 13, 1):\n        feature_map = model.conv[i](feature_map)  # Conv1 output\n        print(feature_map.size())\n       \n        for i in range(min(8, feature_map.shape[1])):\n            plt.subplot(2, 4, i+1)\n            plt.imshow(feature_map[0, i].cpu(), cmap='gray')\n            plt.title(f'Channel {i}')\n            plt.axis('off')\n        plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T07:19:49.417008Z","iopub.execute_input":"2025-04-20T07:19:49.417667Z","iopub.status.idle":"2025-04-20T07:20:01.215440Z","shell.execute_reply.started":"2025-04-20T07:19:49.417639Z","shell.execute_reply":"2025-04-20T07:20:01.214627Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"del model\ntorch.cuda.empty_cache()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-20T07:21:18.225278Z","iopub.execute_input":"2025-04-20T07:21:18.226091Z","iopub.status.idle":"2025-04-20T07:21:18.243286Z","shell.execute_reply.started":"2025-04-20T07:21:18.226061Z","shell.execute_reply":"2025-04-20T07:21:18.242749Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}