{ "cells": [ { "cell_type": "markdown", "id": "2f04eee0-5928-4e74-a754-6dc2e528810c", "metadata": {}, "source": [ "# Lin" ] }, { "cell_type": "markdown", "id": "a3f514a3-772c-4a14-afdf-5a8376851ff4", "metadata": {}, "source": [ "## Index\n", "1. [Instantiate model class](#Instantiate-model-class)\n", "2. [Define clock metadata](#Define-clock-metadata)\n", "3. [Download clock dependencies](#Download-clock-dependencies)\n", "5. [Load features](#Load-features)\n", "6. [Load weights into base model](#Load-weights-into-base-model)\n", "7. [Load reference values](#Load-reference-values)\n", "8. [Load preprocess and postprocess objects](#Load-preprocess-and-postprocess-objects)\n", "10. [Check all clock parameters](#Check-all-clock-parameters)\n", "10. [Basic test](#Basic-test)\n", "11. [Save torch model](#Save-torch-model)\n", "12. [Clear directory](#Clear-directory)" ] }, { "cell_type": "markdown", "id": "d95fafdc-643a-40ea-a689-200bd132e90c", "metadata": {}, "source": [ "Let's first import some packages:" ] }, { "cell_type": "code", "execution_count": 1, "id": "4adfb4de-cd79-4913-a1af-9e23e9e236c9", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:52:22.441900Z", "iopub.status.busy": "2025-04-07T17:52:22.441561Z", "iopub.status.idle": "2025-04-07T17:52:23.935262Z", "shell.execute_reply": "2025-04-07T17:52:23.934947Z" } }, "outputs": [], "source": [ "import os\n", "import inspect\n", "import shutil\n", "import json\n", "import torch\n", "import pandas as pd\n", "import pyaging as pya" ] }, { "cell_type": "markdown", "id": "145082e5-ced4-47ae-88c0-cb69773e3c5a", "metadata": {}, "source": [ "## Instantiate model class" ] }, { "cell_type": "code", "execution_count": 2, "id": "8aa77372-7ed3-4da7-abc9-d30372106139", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:52:23.937017Z", "iopub.status.busy": "2025-04-07T17:52:23.936790Z", "iopub.status.idle": "2025-04-07T17:52:23.944168Z", "shell.execute_reply": "2025-04-07T17:52:23.943860Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "class Lin(pyagingModel):\n", " def __init__(self):\n", " super().__init__()\n", "\n", " def preprocess(self, x):\n", " return x\n", "\n", " def postprocess(self, x):\n", " return x\n", "\n" ] } ], "source": [ "def print_entire_class(cls):\n", " source = inspect.getsource(cls)\n", " print(source)\n", "\n", "print_entire_class(pya.models.Lin)" ] }, { "cell_type": "code", "execution_count": 3, "id": "78536494-f1d9-44de-8583-c89a310d2307", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:52:23.945535Z", "iopub.status.busy": "2025-04-07T17:52:23.945439Z", "iopub.status.idle": "2025-04-07T17:52:23.947164Z", "shell.execute_reply": "2025-04-07T17:52:23.946915Z" } }, "outputs": [], "source": [ "model = pya.models.Lin()" ] }, { "cell_type": "markdown", "id": "51f8615e-01fa-4aa5-b196-3ee2b35d261c", "metadata": {}, "source": [ "## Define clock metadata" ] }, { "cell_type": "code", "execution_count": 4, "id": "6601da9e-8adc-44ee-9308-75e3cd31b816", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:52:23.948516Z", "iopub.status.busy": "2025-04-07T17:52:23.948429Z", "iopub.status.idle": "2025-04-07T17:52:23.950604Z", "shell.execute_reply": "2025-04-07T17:52:23.950271Z" } }, "outputs": [], "source": [ "model.metadata[\"clock_name\"] = \"lin\"\n", "model.metadata[\"data_type\"] = \"DNA methylation\" # Paper: The model uses DNA methylation beta values at age-associated CpGs.\n", "model.metadata[\"species\"] = \"Homo sapiens\" # Paper: Training and evaluation used human blood cohorts.\n", "model.metadata[\"year\"] = 2016\n", "model.metadata[\"approved_by_author\"] = \"⌛\"\n", "model.metadata[\"citation\"] = \"Lin, Q., et al. “DNA methylation levels at individual age-associated CpG sites can be indicative for life expectancy.” Aging 8(2): 394–401 (2016).\"\n", "model.metadata[\"doi\"] = \"https://doi.org/10.18632/aging.100908\"\n", "model.metadata[\"notes\"] = \"Whole-blood 99-CpG multivariate age estimator trained to predict chronological age; age acceleration from the model was secondarily tested for association with all-cause mortality.\"\n", "model.metadata[\"research_only\"] = None\n", "model.metadata[\"tissue\"] = [\"whole blood\"] # Paper: The 99-CpG model was trained on blood DNA methylation profiles.\n", "model.metadata[\"predicts\"] = [\"chronological age\"] # Paper: The model produces predicted age and was validated against chronological age.\n", "model.metadata[\"training_target\"] = [\"chronological age\"] # Paper: The age predictor was trained on donor ages in the Hannum blood dataset.\n", "model.metadata[\"unit\"] = [\"years\"] # Paper: The paper explicitly reports predicted age in years.\n", "model.metadata[\"model_type\"] = \"linear regression\" # Paper: The packaged 99-CpG estimator is a single linear layer with an intercept.\n", "model.metadata[\"platform\"] = [\"Illumina 27K\", \"Illumina 450K\"] # Paper: CpGs were discovered on HumanMethylation27 data and the 99-CpG model was trained/applied using HumanMethylation450 data.\n", "model.metadata[\"population\"] = \"adults\" # Paper: The Hannum training dataset comprised 656 blood profiles with ages 19–101 years.\n", "model.metadata[\"journal\"] = \"Aging\"\n", "model.metadata[\"last_author\"] = \"Wolfgang Wagner\"\n", "model.metadata[\"n_features\"] = 99\n", "model.metadata[\"citations\"] = 256\n", "model.metadata[\"citations_date\"] = \"2026-07-05\"\n" ] }, { "cell_type": "markdown", "id": "74492239-5aae-4026-9d90-6bc9c574c110", "metadata": {}, "source": [ "## Download clock dependencies" ] }, { "cell_type": "code", "execution_count": 5, "id": "8f7143a2-d1d7-4cfc-9231-7c09f7963ae3", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:52:23.952051Z", "iopub.status.busy": "2025-04-07T17:52:23.951955Z", "iopub.status.idle": "2025-04-07T17:52:23.956356Z", "shell.execute_reply": "2025-04-07T17:52:23.956089Z" } }, "outputs": [], "source": [ "# from https://www.aging-us.com/article/100908/text supplement\n", "cpg_sites = [\n", " \"(Intercept)\", \"cg05228408\", \"cg16352283\", \"cg05436231\", \"cg19046959\", \n", " \"cg17791651\", \"cg07388493\", \"cg04036898\", \"cg07810156\", \"cg21448423\", \n", " \"cg18660898\", \"cg25256723\", \"cg21870884\", \"cg25947945\", \"cg09462576\", \n", " \"cg09809672\", \"cg27553955\", \"cg27320127\", \"cg15297650\", \"cg05331214\", \n", " \"cg24178740\", \"cg18182399\", \"cg25431974\", \"cg24768561\", \"cg26614073\", \n", " \"cg23320649\", \"cg12554573\", \"cg04474832\", \"cg17421623\", \"cg22919728\", \n", " \"cg14456683\", \"cg08209133\", \"cg16744741\", \"cg00059225\", \"cg00489401\", \n", " \"cg02844545\", \"cg22736354\", \"cg06493994\", \"cg03340878\", \"cg03958979\", \n", " \"cg15804973\", \"cg13870866\", \"cg00503840\", \"cg25762706\", \"cg25538571\", \n", " \"cg08598221\", \"cg19724470\", \"cg07211259\", \"cg13870494\", \"cg16386080\", \n", " \"cg00563932\", \"cg21120249\", \"cg26581729\", \"cg17431739\", \"cg13129046\", \n", " \"cg01560871\", \"cg06291867\", \"cg26610808\", \"cg07621046\", \"cg13807496\", \n", " \"cg20654468\", \"cg21992250\", \"cg15538427\", \"cg08012287\", \"cg01820374\", \n", " \"cg19722847\", \"cg12883767\", \"cg04123409\", \"cg22580512\", \"cg25268718\", \n", " \"cg21296230\", \"cg21801378\", \"cg10917602\", \"cg15195412\", \"cg20264732\", \n", " \"cg22947000\", \"cg02228185\", \"cg01739167\", \"cg14918082\", \"cg05379350\", \n", " \"cg08468689\", \"cg08090640\", \"cg25809905\", \"cg05294455\", \"cg06638433\", \n", " \"cg20366832\", \"cg19761273\", \"cg26927807\", \"cg17471102\", \"cg02489552\", \n", " \"cg05488632\", \"cg16363586\", \"cg17861230\", \"cg24713204\", \"cg23679724\", \n", " \"cg03224418\", \"cg15379633\", \"cg02994956\", \"cg23124451\", \"cg26394940\"\n", "]\n", "coefficients = [\n", " 12.2169841, 0.47636173, -5.3124138, 17.7305146, -13.367066, 8.72680959, -4.7759575, \n", " 10.162153, 15.3892025, -4.4621797, 13.2543665, -11.802998, 22.9981412, -8.2387336, \n", " 6.3124836, -14.950409, -0.7884001, 48.9368049, -34.306553, 9.83640629, -27.476107, \n", " -4.1527608, -1.048605, -4.5917403, -11.443446, 8.70555476, 1.81880164, -26.556597, \n", " 2.4399993, 0.99214006, 13.1457167, 30.500322, -9.5846721, 36.8195086, 1.98682848, \n", " 0.38022482, 36.9317174, 66.1611861, 5.95485236, -16.016804, -15.214138, -39.104364, \n", " 31.2113275, 1.5340163, 10.2956593, 2.62080161, -5.5537073, -12.424324, 19.7417678, \n", " -29.24993, -3.5009711, -8.6074197, -7.9914389, 8.22589722, -5.1368284, 13.5034883, \n", " 13.0769424, -21.374356, 13.6468199, -8.3931276, 8.14605552, 10.5216611, -19.93487, \n", " -18.989957, -30.896866, -13.06341, 8.45912249, -10.767354, -0.8383178, 4.06576438, \n", " 28.1787443, 44.7163476, -6.0293979, 20.050343, -20.618882, -13.217155, -8.6363427, \n", " 33.8101434, 15.5554908, 17.340667, -16.062905, 8.31318309, -6.0974732, 2.71073045, \n", " 10.6229217, 2.97899616, -16.331359, 16.5195276, -18.063487, 6.09699424, -11.249025, \n", " 13.6452671, 17.5027126, -32.487323, 0.25793126, 8.07556639, 15.4139903, -6.4516149, \n", " -13.361462, 0.89292205\n", "]" ] }, { "cell_type": "markdown", "id": "5035b180-3d1b-4432-8ebe-b9c92bd93a7f", "metadata": {}, "source": [ "## Load features" ] }, { "cell_type": "code", "execution_count": 6, "id": "77face1a-b58f-4f8f-9fe8-1f12037be99a", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:52:23.957648Z", "iopub.status.busy": "2025-04-07T17:52:23.957559Z", "iopub.status.idle": "2025-04-07T17:52:23.959713Z", "shell.execute_reply": "2025-04-07T17:52:23.959453Z" } }, "outputs": [], "source": [ "df = pd.DataFrame({\n", " 'feature': cpg_sites,\n", " 'coefficient': coefficients\n", "})\n", "\n", "model.features = features = df['feature'][1:].tolist()" ] }, { "cell_type": "markdown", "id": "ee6d8fa0-4767-4c45-9717-eb1c95e2ddc0", "metadata": {}, "source": [ "## Load weights into base model" ] }, { "cell_type": "code", "execution_count": 7, "id": "e09b3463-4fd4-41b1-ac21-e63ddd223fe0", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:52:23.961062Z", "iopub.status.busy": "2025-04-07T17:52:23.960971Z", "iopub.status.idle": "2025-04-07T17:52:23.963012Z", "shell.execute_reply": "2025-04-07T17:52:23.962748Z" } }, "outputs": [], "source": [ "weights = torch.tensor(df['coefficient'][1:].tolist()).unsqueeze(0)\n", "intercept = torch.tensor([df['coefficient'][0]])" ] }, { "cell_type": "markdown", "id": "ad261636-5b00-4979-bb1d-67a851f7aa19", "metadata": {}, "source": [ "#### Linear model" ] }, { "cell_type": "code", "execution_count": 8, "id": "d7f43b99-26f2-4622-9a76-316712058877", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:52:23.964406Z", "iopub.status.busy": "2025-04-07T17:52:23.964316Z", "iopub.status.idle": "2025-04-07T17:52:23.966499Z", "shell.execute_reply": "2025-04-07T17:52:23.966246Z" } }, "outputs": [], "source": [ "base_model = pya.models.LinearModel(input_dim=len(model.features))\n", "\n", "base_model.linear.weight.data = weights.float()\n", "base_model.linear.bias.data = intercept.float()\n", "\n", "model.base_model = base_model" ] }, { "cell_type": "markdown", "id": "ad8b4c1d-9d57-48b7-9a30-bcfea7b747b1", "metadata": {}, "source": [ "## Load reference values" ] }, { "cell_type": "code", "execution_count": 9, "id": "ade0f4c9-2298-4fc3-bb72-d200907dd731", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:52:23.967801Z", "iopub.status.busy": "2025-04-07T17:52:23.967713Z", "iopub.status.idle": "2025-04-07T17:52:23.969217Z", "shell.execute_reply": "2025-04-07T17:52:23.968965Z" } }, "outputs": [], "source": [ "model.reference_values = None" ] }, { "cell_type": "markdown", "id": "af3bcf7b-74a8-4d21-9ccb-4de0c2b0516b", "metadata": {}, "source": [ "## Load preprocess and postprocess objects" ] }, { "cell_type": "code", "execution_count": 10, "id": "7a22fb20-c605-424d-8efb-7620c2c0755c", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:52:23.970505Z", "iopub.status.busy": "2025-04-07T17:52:23.970415Z", "iopub.status.idle": "2025-04-07T17:52:23.971791Z", "shell.execute_reply": "2025-04-07T17:52:23.971561Z" } }, "outputs": [], "source": [ "model.preprocess_name = None\n", "model.preprocess_dependencies = None" ] }, { "cell_type": "code", "execution_count": 11, "id": "ff4a21cb-cf41-44dc-9ed1-95cf8aa15772", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:52:23.973000Z", "iopub.status.busy": "2025-04-07T17:52:23.972903Z", "iopub.status.idle": "2025-04-07T17:52:23.974446Z", "shell.execute_reply": "2025-04-07T17:52:23.974118Z" } }, "outputs": [], "source": [ "model.postprocess_name = None\n", "model.postprocess_dependencies = None" ] }, { "cell_type": "markdown", "id": "86e3d6b1-e67e-4f3d-bd39-0ebec5726c3c", "metadata": {}, "source": [ "## Check all clock parameters" ] }, { "cell_type": "code", "execution_count": 12, "id": "2168355c-47d9-475d-b816-49f65e74887c", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:52:23.975774Z", "iopub.status.busy": "2025-04-07T17:52:23.975688Z", "iopub.status.idle": "2025-04-07T17:52:23.979283Z", "shell.execute_reply": "2025-04-07T17:52:23.978962Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "%==================================== Model Details ====================================%\n", "Model Attributes:\n", "\n", "training: True\n", "metadata: {'approved_by_author': '⌛',\n", " 'citation': 'Lin, Qiong, et al. \"DNA methylation levels at individual '\n", " 'age-associated CpG sites can be indicative for life expectancy.\" '\n", " 'Aging (Albany NY) 8.2 (2016): 394.',\n", " 'clock_name': 'lin',\n", " 'data_type': 'methylation',\n", " 'doi': 'https://doi.org/10.18632/aging.100908',\n", " 'notes': None,\n", " 'research_only': None,\n", " 'species': 'Homo sapiens',\n", " 'version': None,\n", " 'year': 2016}\n", "reference_values: None\n", "preprocess_name: None\n", "preprocess_dependencies: None\n", "postprocess_name: None\n", "postprocess_dependencies: None\n", "features: ['cg05228408', 'cg16352283', 'cg05436231', 'cg19046959', 'cg17791651', 'cg07388493', 'cg04036898', 'cg07810156', 'cg21448423', 'cg18660898', 'cg25256723', 'cg21870884', 'cg25947945', 'cg09462576', 'cg09809672', 'cg27553955', 'cg27320127', 'cg15297650', 'cg05331214', 'cg24178740', 'cg18182399', 'cg25431974', 'cg24768561', 'cg26614073', 'cg23320649', 'cg12554573', 'cg04474832', 'cg17421623', 'cg22919728', 'cg14456683']... [Total elements: 99]\n", "base_model_features: None\n", "\n", "%==================================== Model Details ====================================%\n", "Model Structure:\n", "\n", "base_model: LinearModel(\n", " (linear): Linear(in_features=99, out_features=1, bias=True)\n", ")\n", "\n", "%==================================== Model Details ====================================%\n", "Model Parameters and Weights:\n", "\n", "base_model.linear.weight: [0.4763617217540741, -5.312413692474365, 17.730514526367188, -13.367066383361816, 8.72680950164795, -4.7759575843811035, 10.162153244018555, 15.389202117919922, -4.462179660797119, 13.254366874694824, -11.802997589111328, 22.998140335083008, -8.238733291625977, 6.312483787536621, -14.950408935546875, -0.7884001135826111, 48.936805725097656, -34.30655288696289, 9.836406707763672, -27.476106643676758, -4.152760982513428, -1.048604965209961, -4.591740131378174, -11.443446159362793, 8.705554962158203, 1.8188016414642334, -26.556596755981445, 2.4399993419647217, 0.9921400547027588, 13.145716667175293]... [Tensor of shape torch.Size([1, 99])]\n", "base_model.linear.bias: tensor([12.2170])\n", "\n", "%==================================== Model Details ====================================%\n", "\n" ] } ], "source": [ "pya.utils.print_model_details(model)" ] }, { "cell_type": "markdown", "id": "986d0262-e0c7-4036-b687-dee53ba392fb", "metadata": {}, "source": [ "## Basic test" ] }, { "cell_type": "code", "execution_count": 13, "id": "936b9877-d076-4ced-99aa-e8d4c58c5caf", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:52:23.980687Z", "iopub.status.busy": "2025-04-07T17:52:23.980592Z", "iopub.status.idle": "2025-04-07T17:52:23.985365Z", "shell.execute_reply": "2025-04-07T17:52:23.985125Z" } }, "outputs": [ { "data": { "text/plain": [ "tensor([[ 305.0711],\n", " [ 247.5204],\n", " [ 118.7530],\n", " [ 22.4327],\n", " [ -22.3631],\n", " [ 186.0485],\n", " [-195.4503],\n", " [ 222.6908],\n", " [ 25.2435],\n", " [ 281.9471]], dtype=torch.float64, grad_fn=)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "torch.manual_seed(42)\n", "input = torch.randn(10, len(model.features), dtype=float)\n", "model.eval()\n", "model.to(float)\n", "pred = model(input)\n", "pred" ] }, { "cell_type": "markdown", "id": "fe8299d7-9285-4e22-82fd-b664434b4369", "metadata": {}, "source": [ "## Save torch model" ] }, { "cell_type": "code", "execution_count": 14, "id": "5ef2fa8d-c80b-4fdd-8555-79c0d541788e", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:52:23.986611Z", "iopub.status.busy": "2025-04-07T17:52:23.986534Z", "iopub.status.idle": "2025-04-07T17:52:23.990048Z", "shell.execute_reply": "2025-04-07T17:52:23.989794Z" } }, "outputs": [], "source": [ "torch.save(model, f\"../weights/{model.metadata['clock_name']}.pt\")" ] }, { "cell_type": "markdown", "id": "bac6257b-8d08-4a90-8d0b-7f745dc11ac1", "metadata": {}, "source": [ "## Clear directory\n", "" ] }, { "cell_type": "code", "execution_count": 15, "id": "11aeaa70-44c0-42f9-86d7-740e3849a7a6", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:52:23.991309Z", "iopub.status.busy": "2025-04-07T17:52:23.991225Z", "iopub.status.idle": "2025-04-07T17:52:23.993865Z", "shell.execute_reply": "2025-04-07T17:52:23.993619Z" } }, "outputs": [], "source": [ "# Function to remove a folder and all its contents\n", "def remove_folder(path):\n", " try:\n", " shutil.rmtree(path)\n", " print(f\"Deleted folder: {path}\")\n", " except Exception as e:\n", " print(f\"Error deleting folder {path}: {e}\")\n", "\n", "# Get a list of all files and folders in the current directory\n", "all_items = os.listdir('.')\n", "\n", "# Loop through the items\n", "for item in all_items:\n", " # Check if it's a file and does not end with .ipynb\n", " if os.path.isfile(item) and not item.endswith('.ipynb'):\n", " os.remove(item)\n", " print(f\"Deleted file: {item}\")\n", " # Check if it's a folder\n", " elif os.path.isdir(item):\n", " remove_folder(item)" ] } ], "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.9.7" } }, "nbformat": 4, "nbformat_minor": 5 }