{ "cells": [ { "cell_type": "markdown", "id": "2f04eee0-5928-4e74-a754-6dc2e528810c", "metadata": {}, "source": [ "# GrimAge" ] }, { "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:51:36.310880Z", "iopub.status.busy": "2025-04-07T17:51:36.310754Z", "iopub.status.idle": "2025-04-07T17:51:37.649597Z", "shell.execute_reply": "2025-04-07T17:51:37.649235Z" } }, "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\n", "import numpy as np" ] }, { "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:51:37.651368Z", "iopub.status.busy": "2025-04-07T17:51:37.651142Z", "iopub.status.idle": "2025-04-07T17:51:37.661774Z", "shell.execute_reply": "2025-04-07T17:51:37.661501Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "class GrimAge(pyagingModel):\n", " def __init__(self):\n", " super().__init__()\n", "\n", " self.PACKYRS = None\n", " self.ADM = None\n", " self.B2M = None\n", " self.CystatinC = None\n", " self.GDF15 = None\n", " self.Leptin = None\n", " self.PAI1 = None\n", " self.TIMP1 = None\n", "\n", " self.features_PACKYRS = None\n", " self.features_ADM = None\n", " self.features_B2M = None\n", " self.features_CystatinC = None\n", " self.features_GDF15 = None\n", " self.features_Leptin = None\n", " self.features_PAI1 = None\n", " self.features_TIMP1 = None\n", "\n", " def forward(self, x):\n", " Female = x[:, -2].unsqueeze(1)\n", " Age = x[:, -1].unsqueeze(1)\n", "\n", " PACKYRS = self.PACKYRS(x[:, self.features_PACKYRS])\n", " ADM = self.ADM(x[:, self.features_ADM])\n", " B2M = self.B2M(x[:, self.features_B2M])\n", " CystatinC = self.CystatinC(x[:, self.features_CystatinC])\n", " GDF15 = self.GDF15(x[:, self.features_GDF15])\n", " Leptin = self.Leptin(x[:, self.features_Leptin])\n", " PAI1 = self.PAI1(x[:, self.features_PAI1])\n", " TIMP1 = self.TIMP1(x[:, self.features_TIMP1])\n", "\n", " x = torch.concat(\n", " [GDF15, B2M, CystatinC, TIMP1, ADM, PAI1, Leptin, PACKYRS, Age, Female],\n", " dim=1,\n", " )\n", "\n", " x = self.base_model(x)\n", "\n", " x = self.postprocess(x)\n", "\n", " return x\n", "\n", " def preprocess(self, x):\n", " return x\n", "\n", " def postprocess(self, x):\n", " \"\"\"\n", " Converts from a Cox parameter to age in units of years.\n", " \"\"\"\n", " cox_mean = 13.20127\n", " cox_std = 1.086805\n", " age_mean = 59.63951\n", " age_std = 9.049608\n", "\n", " # Normalize\n", " x = (x - cox_mean) / cox_std\n", "\n", " # Scale\n", " x = (x * age_std) + age_mean\n", "\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.GrimAge)" ] }, { "cell_type": "code", "execution_count": 3, "id": "78536494-f1d9-44de-8583-c89a310d2307", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:51:37.663053Z", "iopub.status.busy": "2025-04-07T17:51:37.662967Z", "iopub.status.idle": "2025-04-07T17:51:37.664628Z", "shell.execute_reply": "2025-04-07T17:51:37.664372Z" } }, "outputs": [], "source": [ "model = pya.models.GrimAge()" ] }, { "cell_type": "markdown", "id": "51f8615e-01fa-4aa5-b196-3ee2b35d261c", "metadata": {}, "source": [ "## Define clock metadata" ] }, { "cell_type": "code", "execution_count": 4, "id": "135ce001-03f7-4025-bceb-01a3e2e2b0ef", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:51:37.666005Z", "iopub.status.busy": "2025-04-07T17:51:37.665921Z", "iopub.status.idle": "2025-04-07T17:51:37.667900Z", "shell.execute_reply": "2025-04-07T17:51:37.667659Z" } }, "outputs": [], "source": [ "model.metadata[\"clock_name\"] = \"grimage\"\n", "model.metadata[\"data_type\"] = \"DNA methylation\" # Paper: The study constructs clocks from DNA methylation measurements.\n", "model.metadata[\"species\"] = \"Homo sapiens\" # Paper: The analyzed samples and clock are human.\n", "model.metadata[\"year\"] = 2019\n", "model.metadata[\"approved_by_author\"] = \"⌛\"\n", "model.metadata[\"citation\"] = \"Lu, Ake T., et al. \\\"DNA methylation GrimAge strongly predicts lifespan and healthspan.\\\" Aging (Albany NY) 11 (2019): 303–327.\"\n", "model.metadata[\"doi\"] = \"https://doi.org/10.18632/aging.101684\"\n", "model.metadata[\"notes\"] = \"Age-calibrated mortality-risk estimator built in two stages from DNAm surrogates for plasma proteins and smoking pack-years, chronological age, and sex.\"\n", "model.metadata[\"research_only\"] = True\n", "model.metadata[\"tissue\"] = [\"whole blood\"] # Paper: DNAm GrimAge was trained in Framingham Heart Study blood samples.\n", "model.metadata[\"predicts\"] = [\"mortality risk\"] # Paper: The final predictor is a mortality-risk estimate calibrated to units of years.\n", "model.metadata[\"training_target\"] = [\"mortality\"] # Paper: The second-stage elastic-net Cox model used time-to-death due to all-cause mortality.\n", "model.metadata[\"unit\"] = [\"years\"] # Paper: The mortality-risk linear predictor was transformed into units of years.\n", "model.metadata[\"model_type\"] = \"two-stage elastic net + Cox regression\" # Paper: Stage one fit DNAm surrogates; stage two fit an elastic-net Cox model.\n", "model.metadata[\"platform\"] = [\"Illumina 450K\"] # Paper: Training methylation data in the Framingham cohort were generated on the Illumina 450K array.\n", "model.metadata[\"population\"] = \"adults\" # Paper: The training set comprised 1,731 Framingham participants with mean age 66 years.\n", "model.metadata[\"journal\"] = \"Aging (Albany NY)\"\n", "model.metadata[\"last_author\"] = \"Steve Horvath\"\n", "model.metadata[\"n_features\"] = 1032\n", "model.metadata[\"citations\"] = 2610\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": "969eac49-e51e-4f90-a1d3-f05b706531fd", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:51:37.669252Z", "iopub.status.busy": "2025-04-07T17:51:37.669168Z", "iopub.status.idle": "2025-04-07T17:51:39.201940Z", "shell.execute_reply": "2025-04-07T17:51:39.201399Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "|-----------> Downloading data to ./ElasticNet_DNAmProtein_Vars_model4.csv\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 20.8889%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 41.7778%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 62.6667%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 83.5556%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 104.4445%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 100.0000%\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "|-----------> Downloading data to ./datMiniAnnotation3_Gold.csv\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 1.7208%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 3.4415%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 5.1623%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 6.8831%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 8.6038%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 10.3246%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 12.0454%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 13.7662%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 15.4869%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 17.2077%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 18.9285%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 20.6492%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 22.3700%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 24.0908%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 25.8115%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 27.5323%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 29.2531%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 30.9739%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 32.6946%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 34.4154%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 36.1362%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 37.8569%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 39.5777%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 41.2985%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 43.0192%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 44.7400%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 46.4608%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 48.1816%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 49.9023%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 51.6231%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 53.3439%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 55.0646%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 56.7854%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 58.5062%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 60.2269%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 61.9477%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 63.6685%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 65.3893%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 67.1100%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 68.8308%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 70.5516%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 72.2723%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 73.9931%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 75.7139%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 77.4346%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 79.1554%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 80.8762%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 82.5970%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 84.3177%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 86.0385%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 87.7593%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 89.4800%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 91.2008%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 92.9216%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 94.6423%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 96.3631%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 98.0839%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 99.8046%" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "|-----------> in progress: 100.0000%\n" ] } ], "source": [ "#download PCClock Rdata file from https://yale.app.box.com/s/kq0b0a7lxckxjvaz7x5n4keaug7tewry\n", "logger = pya.logger.Logger()\n", "urls = [\n", " \"https://huggingface.co/lucascamillomd/pyaging-data/resolve/main/supporting_files/ElasticNet_DNAmProtein_Vars_model4.csv\",\n", " \"https://huggingface.co/lucascamillomd/pyaging-data/resolve/main/supporting_files/datMiniAnnotation3_Gold.csv\",\n", "]\n", "dir = \".\"\n", "for url in urls:\n", " pya.utils.download(url, dir, logger, indent_level=1)" ] }, { "cell_type": "markdown", "id": "a14c7fc1-abe5-42a3-8bc9-0987521ddf33", "metadata": {}, "source": [ "## Load features" ] }, { "cell_type": "markdown", "id": "3e737582-3a28-4f55-8da9-3e34125362cc", "metadata": {}, "source": [ "#### From CSV" ] }, { "cell_type": "code", "execution_count": 6, "id": "97e5b47b-0599-4ec3-aab4-dcfe9d3e4515", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:51:39.204770Z", "iopub.status.busy": "2025-04-07T17:51:39.204551Z", "iopub.status.idle": "2025-04-07T17:51:39.213059Z", "shell.execute_reply": "2025-04-07T17:51:39.212532Z" } }, "outputs": [], "source": [ "df = pd.read_csv('ElasticNet_DNAmProtein_Vars_model4.csv')\n", "model.features = np.unique(df['var']).tolist()[2:] + ['female'] + ['age']" ] }, { "cell_type": "markdown", "id": "ee6d8fa0-4767-4c45-9717-eb1c95e2ddc0", "metadata": {}, "source": [ "## Load weights into base model" ] }, { "cell_type": "markdown", "id": "3958ba73-42e8-40a5-94a1-4f4b8ae05dca", "metadata": {}, "source": [ "#### Linear model" ] }, { "cell_type": "code", "execution_count": 7, "id": "321a437c-8888-4e10-96e9-5ed2826a8f74", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:51:39.215696Z", "iopub.status.busy": "2025-04-07T17:51:39.215481Z", "iopub.status.idle": "2025-04-07T17:51:39.288837Z", "shell.execute_reply": "2025-04-07T17:51:39.288511Z" } }, "outputs": [], "source": [ "all_features = np.unique(df['var']).tolist()[2:] + ['Female'] + ['Age']\n", "\n", "model.PACKYRS = pya.models.LinearModel(input_dim=len(np.array(df.loc[df['Y.pred'] == 'DNAmPACKYRS'])))\n", "model.PACKYRS.linear.weight.data = torch.tensor(np.array(df.loc[df['Y.pred'] == 'DNAmPACKYRS', 'beta'][1:])).unsqueeze(0).float()\n", "model.PACKYRS.linear.bias.data = torch.tensor(np.array(df.loc[df['Y.pred'] == 'DNAmPACKYRS', 'beta'].iloc[0])).float()\n", "model.features_PACKYRS = indices = torch.tensor([all_features.index(item) for item in np.array(df.loc[df['Y.pred'] == 'DNAmPACKYRS', 'var']) if item in all_features]).long()\n", "\n", "model.ADM = pya.models.LinearModel(input_dim=len(np.array(df.loc[df['Y.pred'] == 'DNAmadm'])))\n", "model.ADM.linear.weight.data = torch.tensor(np.array(df.loc[df['Y.pred'] == 'DNAmadm', 'beta'][1:])).unsqueeze(0).float()\n", "model.ADM.linear.bias.data = torch.tensor(np.array(df.loc[df['Y.pred'] == 'DNAmadm', 'beta'].iloc[0])).float()\n", "model.features_ADM = indices = torch.tensor([all_features.index(item) for item in np.array(df.loc[df['Y.pred'] == 'DNAmadm', 'var']) if item in all_features]).long()\n", "\n", "model.B2M = pya.models.LinearModel(input_dim=len(np.array(df.loc[df['Y.pred'] == 'DNAmB2M'])))\n", "model.B2M.linear.weight.data = torch.tensor(np.array(df.loc[df['Y.pred'] == 'DNAmB2M', 'beta'][1:])).unsqueeze(0).float()\n", "model.B2M.linear.bias.data = torch.tensor(np.array(df.loc[df['Y.pred'] == 'DNAmB2M', 'beta'].iloc[0])).float()\n", "model.features_B2M = indices = torch.tensor([all_features.index(item) for item in np.array(df.loc[df['Y.pred'] == 'DNAmB2M', 'var']) if item in all_features]).long()\n", "\n", "model.CystatinC = pya.models.LinearModel(input_dim=len(np.array(df.loc[df['Y.pred'] == 'DNAmCystatin_C'])))\n", "model.CystatinC.linear.weight.data = torch.tensor(np.array(df.loc[df['Y.pred'] == 'DNAmCystatin_C', 'beta'][1:])).unsqueeze(0).float()\n", "model.CystatinC.linear.bias.data = torch.tensor(np.array(df.loc[df['Y.pred'] == 'DNAmCystatin_C', 'beta'].iloc[0])).float()\n", "model.features_CystatinC = indices = torch.tensor([all_features.index(item) for item in np.array(df.loc[df['Y.pred'] == 'DNAmCystatin_C', 'var']) if item in all_features]).long()\n", "\n", "model.GDF15 = pya.models.LinearModel(input_dim=len(np.array(df.loc[df['Y.pred'] == 'DNAmGDF_15'])))\n", "model.GDF15.linear.weight.data = torch.tensor(np.array(df.loc[df['Y.pred'] == 'DNAmGDF_15', 'beta'][1:])).unsqueeze(0).float()\n", "model.GDF15.linear.bias.data = torch.tensor(np.array(df.loc[df['Y.pred'] == 'DNAmGDF_15', 'beta'].iloc[0])).float()\n", "model.features_GDF15 = indices = torch.tensor([all_features.index(item) for item in np.array(df.loc[df['Y.pred'] == 'DNAmGDF_15', 'var']) if item in all_features]).long()\n", "\n", "model.Leptin = pya.models.LinearModel(input_dim=len(np.array(df.loc[df['Y.pred'] == 'DNAmleptin'])))\n", "model.Leptin.linear.weight.data = torch.tensor(np.array(df.loc[df['Y.pred'] == 'DNAmleptin', 'beta'][1:])).unsqueeze(0).float()\n", "model.Leptin.linear.bias.data = torch.tensor(np.array(df.loc[df['Y.pred'] == 'DNAmleptin', 'beta'].iloc[0])).float()\n", "model.features_Leptin = indices = torch.tensor([all_features.index(item) for item in np.array(df.loc[df['Y.pred'] == 'DNAmleptin', 'var']) if item in all_features]).long()\n", "\n", "model.PAI1 = pya.models.LinearModel(input_dim=len(np.array(df.loc[df['Y.pred'] == 'DNAmpai_1'])))\n", "model.PAI1.linear.weight.data = torch.tensor(np.array(df.loc[df['Y.pred'] == 'DNAmpai_1', 'beta'][1:])).unsqueeze(0).float()\n", "model.PAI1.linear.bias.data = torch.tensor(np.array(df.loc[df['Y.pred'] == 'DNAmpai_1', 'beta'].iloc[0])).float()\n", "model.features_PAI1 = indices = torch.tensor([all_features.index(item) for item in np.array(df.loc[df['Y.pred'] == 'DNAmpai_1', 'var']) if item in all_features]).long()\n", "\n", "model.TIMP1 = pya.models.LinearModel(input_dim=len(np.array(df.loc[df['Y.pred'] == 'DNAmTIMP_1'])))\n", "model.TIMP1.linear.weight.data = torch.tensor(np.array(df.loc[df['Y.pred'] == 'DNAmTIMP_1', 'beta'][1:])).unsqueeze(0).float()\n", "model.TIMP1.linear.bias.data = torch.tensor(np.array(df.loc[df['Y.pred'] == 'DNAmTIMP_1', 'beta'].iloc[0])).float()\n", "model.features_TIMP1 = indices = torch.tensor([all_features.index(item) for item in np.array(df.loc[df['Y.pred'] == 'DNAmTIMP_1', 'var']) if item in all_features]).long()" ] }, { "cell_type": "markdown", "id": "5742dc16-e063-414f-a38e-9721beb11351", "metadata": {}, "source": [ "#### Linear model" ] }, { "cell_type": "code", "execution_count": 8, "id": "74e50e9c-5d2d-429c-bf3a-493491233089", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:51:39.290372Z", "iopub.status.busy": "2025-04-07T17:51:39.290278Z", "iopub.status.idle": "2025-04-07T17:51:39.292135Z", "shell.execute_reply": "2025-04-07T17:51:39.291839Z" } }, "outputs": [], "source": [ "grimage_weights = [\n", " 0.000348777412272004,\n", " 4.59105969389204e-07,\n", " 3.49816671441537e-06,\n", " 0.000143661105491888,\n", " 0.00790270975255529,\n", " 2.55560382039825e-05,\n", " -7.32066983502079e-06,\n", " 0.0303981613409142,\n", " 0.0300823182194075,\n", " -0.228468475622039\n", "]" ] }, { "cell_type": "code", "execution_count": 9, "id": "c2e54115-c17b-48ce-88f1-de546c90d2b3", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:51:39.293376Z", "iopub.status.busy": "2025-04-07T17:51:39.293276Z", "iopub.status.idle": "2025-04-07T17:51:39.295600Z", "shell.execute_reply": "2025-04-07T17:51:39.295231Z" } }, "outputs": [], "source": [ "base_model = pya.models.LinearModel(input_dim=len(grimage_weights))\n", "\n", "base_model.linear.weight.data = torch.tensor(grimage_weights).unsqueeze(0).float()\n", "base_model.linear.bias.data = torch.tensor([0]).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": 10, "id": "2089b66f-9cc4-4528-9bdc-5e45efc6d06b", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:51:39.296963Z", "iopub.status.busy": "2025-04-07T17:51:39.296863Z", "iopub.status.idle": "2025-04-07T17:51:39.312041Z", "shell.execute_reply": "2025-04-07T17:51:39.311738Z" } }, "outputs": [], "source": [ "reference_df = pd.read_csv('datMiniAnnotation3_Gold.csv', index_col=0)\n", "model.reference_values = reference_df.loc[model.features[:-2]]['gold'].tolist() + [1, 65] # 65 yo F" ] }, { "cell_type": "markdown", "id": "af3bcf7b-74a8-4d21-9ccb-4de0c2b0516b", "metadata": {}, "source": [ "## Load preprocess and postprocess objects" ] }, { "cell_type": "code", "execution_count": 11, "id": "7a22fb20-c605-424d-8efb-7620c2c0755c", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:51:39.313540Z", "iopub.status.busy": "2025-04-07T17:51:39.313445Z", "iopub.status.idle": "2025-04-07T17:51:39.315109Z", "shell.execute_reply": "2025-04-07T17:51:39.314856Z" } }, "outputs": [], "source": [ "model.preprocess_name = None\n", "model.preprocess_dependencies = None" ] }, { "cell_type": "code", "execution_count": 12, "id": "ff4a21cb-cf41-44dc-9ed1-95cf8aa15772", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:51:39.316375Z", "iopub.status.busy": "2025-04-07T17:51:39.316291Z", "iopub.status.idle": "2025-04-07T17:51:39.318178Z", "shell.execute_reply": "2025-04-07T17:51:39.317908Z" } }, "outputs": [], "source": [ "model.postprocess_name = 'cox_to_years'\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": 13, "id": "2168355c-47d9-475d-b816-49f65e74887c", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:51:39.319556Z", "iopub.status.busy": "2025-04-07T17:51:39.319465Z", "iopub.status.idle": "2025-04-07T17:51:39.329943Z", "shell.execute_reply": "2025-04-07T17:51:39.329657Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "%==================================== Model Details ====================================%\n", "Model Attributes:\n", "\n", "training: True\n", "metadata: {'approved_by_author': '⌛',\n", " 'citation': 'Lu, Ake T., et al. \"DNA methylation GrimAge strongly predicts '\n", " 'lifespan and healthspan.\" Aging (albany NY) 11.2 (2019): 303.',\n", " 'clock_name': 'grimage',\n", " 'data_type': 'methylation',\n", " 'doi': 'https://doi.org/10.18632/aging.101684',\n", " 'notes': None,\n", " 'research_only': True,\n", " 'species': 'Homo sapiens',\n", " 'version': None,\n", " 'year': 2019}\n", "reference_values: [0.422480272528644, 0.935109546405548, 0.0162959729801047, 0.502691053893618, 0.910839576323153, 0.710155040209873, 0.479121329208521, 0.905888314944049, 0.279992670790348, 0.117900358329507, 0.940987438881091, 0.761621096809391, 0.0721244934513398, 0.0851830172952001, 0.222068390557704, 0.103705423432714, 0.91516014793103, 0.748331163695382, 0.903928589429489, 0.524090323888757, 0.894685558616447, 0.647988638853782, 0.0581747999131966, 0.830024180811995, 0.209808614636345, 0.324296328128978, 0.118979846374564, 0.545425926051344, 0.92324324492159, 0.328288208993484]... [Total elements: 1032]\n", "preprocess_name: None\n", "preprocess_dependencies: None\n", "postprocess_name: 'cox_to_years'\n", "postprocess_dependencies: None\n", "features: ['cg00036119', 'cg00102512', 'cg00126959', 'cg00161556', 'cg00252095', 'cg00277397', 'cg00332048', 'cg00356999', 'cg00398048', 'cg00412842', 'cg00417288', 'cg00417823', 'cg00456299', 'cg00480331', 'cg00481951', 'cg00497251', 'cg00500789', 'cg00534468', 'cg00543335', 'cg00554421', 'cg00558975', 'cg00564555', 'cg00574958', 'cg00684178', 'cg00684824', 'cg00695391', 'cg00695799', 'cg00706683', 'cg00744433', 'cg00844308']... [Total elements: 1032]\n", "base_model_features: None\n", "features_PACKYRS: [1031, 799, 782, 584, 894, 609, 225, 268, 16, 907, 388, 202, 941, 665, 497, 405, 700, 61, 110, 392, 1001, 598, 200, 252, 297, 1, 287, 680, 27, 298]... [Tensor of shape torch.Size([173])]\n", "features_ADM: [1031, 581, 823, 168, 152, 248, 649, 437, 922, 910, 594, 803, 449, 275, 163, 770, 790, 364, 908, 811, 474, 359, 420, 438, 215, 585, 327, 978, 133, 801]... [Tensor of shape torch.Size([187])]\n", "features_B2M: [1031, 581, 866, 424, 1025, 764, 157, 712, 803, 977, 449, 635, 879, 787, 716, 810, 87, 648, 519, 48, 456, 768, 540, 888, 363, 35, 804, 434, 1015, 450]... [Tensor of shape torch.Size([92])]\n", "features_CystatinC: [1031, 25, 660, 36, 225, 311, 59, 449, 982, 451, 89, 306, 475, 420, 914, 574, 358, 644, 916, 456, 14, 218, 868, 880, 432, 647, 1028, 931, 652, 98]... [Tensor of shape torch.Size([88])]\n", "features_GDF15: [1031, 846, 885, 728, 974, 452, 449, 708, 544, 511, 539, 829, 729, 276, 831, 90, 362, 23, 1023, 186, 648, 286, 951, 962, 626, 189, 804, 532, 480, 67]... [Tensor of shape torch.Size([138])]\n", "features_Leptin: [486, 581, 919, 775, 625, 444, 661, 213, 391, 603, 790, 908, 272, 334, 58, 420, 530, 786, 224, 381, 608, 91, 15, 1013, 683, 309, 1021, 455, 722, 549]... [Tensor of shape torch.Size([187])]\n", "features_PAI1: [429, 330, 714, 421, 33, 636, 582, 12, 226, 558, 953, 509, 629, 766, 607, 824, 594, 774, 670, 789, 56, 792, 958, 571, 122, 991, 965, 191, 926, 970]... [Tensor of shape torch.Size([211])]\n", "features_TIMP1: [1031, 764, 947, 883, 456, 912, 338, 434, 258, 476, 940, 739, 795, 473, 930, 956, 943, 534, 299, 702, 166, 800, 487, 326, 376, 514, 898, 936, 980, 423]... [Tensor of shape torch.Size([43])]\n", "\n", "%==================================== Model Details ====================================%\n", "Model Structure:\n", "\n", "PACKYRS: LinearModel(\n", " (linear): Linear(in_features=174, out_features=1, bias=True)\n", ")\n", "ADM: LinearModel(\n", " (linear): Linear(in_features=188, out_features=1, bias=True)\n", ")\n", "B2M: LinearModel(\n", " (linear): Linear(in_features=93, out_features=1, bias=True)\n", ")\n", "CystatinC: LinearModel(\n", " (linear): Linear(in_features=89, out_features=1, bias=True)\n", ")\n", "GDF15: LinearModel(\n", " (linear): Linear(in_features=139, out_features=1, bias=True)\n", ")\n", "Leptin: LinearModel(\n", " (linear): Linear(in_features=188, out_features=1, bias=True)\n", ")\n", "PAI1: LinearModel(\n", " (linear): Linear(in_features=212, out_features=1, bias=True)\n", ")\n", "TIMP1: LinearModel(\n", " (linear): Linear(in_features=44, out_features=1, bias=True)\n", ")\n", "base_model: LinearModel(\n", " (linear): Linear(in_features=10, out_features=1, bias=True)\n", ")\n", "\n", "%==================================== Model Details ====================================%\n", "Model Parameters and Weights:\n", "\n", "PACKYRS.linear.weight: [0.14214389026165009, 14.697949409484863, 0.4599894881248474, 0.3822956085205078, 7.98643684387207, 1.6803100109100342, 1.0967497825622559, 16.303823471069336, 2.4014580249786377, 0.6859070062637329, 1.6773189306259155, 21.501564025878906, -2.096100330352783, 2.2927305698394775, 0.12879624962806702, 0.5189002752304077, 9.517245292663574, 1.3636956214904785, 1.7754020690917969, 2.1244921684265137, 3.7083091735839844, 3.0460753440856934, 1.3274203538894653, -0.6062915921211243, -1.1171971559524536, -13.956497192382812, 0.36579036712646484, -0.6485168933868408, 4.881432056427002, -24.69486427307129]... [Tensor of shape torch.Size([1, 173])]\n", "PACKYRS.linear.bias: tensor(-31.9970)\n", "ADM.linear.weight: [0.9436950087547302, 4.995108127593994, 5.08618688583374, 28.64090347290039, 6.462732315063477, -118.2184066772461, -2.752854585647583, -55.56800079345703, -0.6833848357200623, 0.8265380263328552, -8.586676597595215, 9.290790557861328, 281.4186706542969, 9.880138397216797, -1.110060691833496, -0.036802105605602264, 202.86256408691406, -114.29457092285156, 248.89732360839844, 5.330321311950684, 4.495867729187012, -4.7390031814575195, 133.71437072753906, -2.2405805587768555, -3.3119983673095703, 19.081783294677734, 2.63143253326416, -24.076101303100586, -8.62603759765625, -32.408607482910156]... [Tensor of shape torch.Size([1, 187])]\n", "ADM.linear.bias: tensor(290.1693)\n", "B2M.linear.weight: [10486.9150390625, 316962.65625, 33927.10546875, -160612.375, 75457.171875, 87985.7421875, 292882.90625, -23280.169921875, 43791.1796875, 302011.96875, 1916187.0, -58500.59375, -126869.8828125, 1506.065185546875, 1417.4544677734375, 44895.46875, 267379.5625, -924930.5625, 69711.0390625, 102607.9921875, 49483.265625, 65359.765625, -13569.71875, -13531.2998046875, -84787.703125, -129131.7265625, 412413.875, -67296.7265625, 28426.35546875, 89744.1875]... [Tensor of shape torch.Size([1, 92])]\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "B2M.linear.bias: tensor(1412953.3750)\n", "CystatinC.linear.weight: [2589.667724609375, -15088.66015625, 36553.1171875, -14194.40234375, 177517.65625, 2264.057861328125, -3639.993896484375, 146477.484375, 11819.2109375, 438.5729064941406, -35147.8515625, -146515.59375, 3482.841796875, 46536.5078125, -19400.65625, 5430.861328125, -2332.132080078125, 28774.947265625, 37130.91796875, 4642.5302734375, 2118.04541015625, 8312.26953125, 1070.0323486328125, 53286.4609375, 6551.3515625, 1233.9503173828125, -2420.194580078125, 3439.35546875, 13203.8330078125, 35212.96875]... [Tensor of shape torch.Size([1, 88])]\n", "CystatinC.linear.bias: tensor(1091528.5000)" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "GDF15.linear.weight: [9.351357460021973, 84.36457824707031, 143.69606018066406, 81.37864685058594, 29.040103912353516, -112.49447631835938, 11.24372673034668, -118.38355255126953, -1980.7607421875, 12.090482711791992, 381.68292236328125, 20.09428596496582, 79.332275390625, 93.16657257080078, -42.04895782470703, -56.21128463745117, 50.33696746826172, -4.690526962280273, 23.865774154663086, 110.17974090576172, -504.0067138671875, 454.8924255371094, 3.939922571182251, 10.757635116577148, -21.75938606262207, 191.6622314453125, 342.773193359375, -183.74392700195312, 297.9110107421875, 50.03202438354492]... [Tensor of shape torch.Size([1, 138])]\n", "GDF15.linear.bias: tensor(1975.7983)\n", "Leptin.linear.weight: [399.8157043457031, 3861.580810546875, 4281.87353515625, 1714.1119384765625, -25588.5390625, 25643.771484375, -3710.89697265625, 1028.21484375, 4559.81591796875, -9729.9609375, 28351.38671875, 60980.60546875, 894.3289184570312, 2256.300537109375, -997.83447265625, 16759.64453125, 637.7293090820312, -14579.912109375, -7351.828125, 37.74680709838867, 5151.525390625, -38035.12890625, -3955.989990234375, -2736.428466796875, 154.31683349609375, -5049.8408203125, 4.860612869262695, -59299.390625, -594.4842529296875, 3549.596435546875]... [Tensor of shape torch.Size([1, 187])]\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Leptin.linear.bias: tensor(7210.0625)\n", "PAI1.linear.weight: [62.57840347290039, 321.195556640625, -476.72576904296875, 6221.58544921875, 7843.1796875, -313.1407775878906, -3855.91650390625, 3294.65234375, 752.2315673828125, -47.931236267089844, 301.0967712402344, -321.5203552246094, 24.402000427246094, -568.0665893554688, -3272.8876953125, 1760.7930908203125, -6259.56103515625, -10119.8154296875, 2037.0191650390625, 2472.403564453125, -3049.89794921875, 4225.28271484375, 982.7288208007812, -152.87660217285156, -356.9750061035156, -4542.0302734375, 433.330810546875, -169.24246215820312, -2095.550537109375, 311.5205078125]... [Tensor of shape torch.Size([1, 211])]\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "PAI1.linear.bias: tensor(-1129.6017)\n", "TIMP1.linear.weight: [127.23798370361328, 576.6142578125, -161.49070739746094, -186.5166778564453, 571.6375732421875, 174.81607055664062, 23.66378402709961, -228.55433654785156, 58.980308532714844, 469.25677490234375, 723.093994140625, 1335.6502685546875, 542.5457153320312, 2160.827880859375, 922.79736328125, 7743.75146484375, -1151.7979736328125, -43.27967834472656, 407.7511901855469, -5735.69287109375, -11.83304500579834, -665.969970703125, 340.971923828125, 207.72994995117188, -32.84348678588867, -1965.6759033203125, 253.16822814941406, 23.78565788269043, 3192.898681640625, 67.02117156982422]... [Tensor of shape torch.Size([1, 43])]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "TIMP1.linear.bias: tensor(15844.5957)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "base_model.linear.weight: tensor([[ 3.4878e-04, 4.5911e-07, 3.4982e-06, 1.4366e-04, 7.9027e-03,\n", " 2.5556e-05, -7.3207e-06, 3.0398e-02, 3.0082e-02, -2.2847e-01]])\n", "base_model.linear.bias: tensor([0.])\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": 14, "id": "936b9877-d076-4ced-99aa-e8d4c58c5caf", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:51:39.331340Z", "iopub.status.busy": "2025-04-07T17:51:39.331246Z", "iopub.status.idle": "2025-04-07T17:51:39.337851Z", "shell.execute_reply": "2025-04-07T17:51:39.337587Z" } }, "outputs": [ { "data": { "text/plain": [ "tensor([[ -8.6124],\n", " [ 66.5366],\n", " [ 49.7812],\n", " [-51.8447],\n", " [ 89.6747],\n", " [-65.7946],\n", " [ 89.6295],\n", " [-60.4899],\n", " [ 69.0053],\n", " [-58.3423]], dtype=torch.float64, grad_fn=)" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "torch.manual_seed(42)\n", "input = torch.randn(10, len(model.features), dtype=float).double()\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": 15, "id": "5ef2fa8d-c80b-4fdd-8555-79c0d541788e", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:51:39.339199Z", "iopub.status.busy": "2025-04-07T17:51:39.339109Z", "iopub.status.idle": "2025-04-07T17:51:39.343838Z", "shell.execute_reply": "2025-04-07T17:51:39.343535Z" } }, "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": 16, "id": "11aeaa70-44c0-42f9-86d7-740e3849a7a6", "metadata": { "execution": { "iopub.execute_input": "2025-04-07T17:51:39.345139Z", "iopub.status.busy": "2025-04-07T17:51:39.345048Z", "iopub.status.idle": "2025-04-07T17:51:39.348518Z", "shell.execute_reply": "2025-04-07T17:51:39.348262Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Deleted file: coefficients.xlsx\n", "Deleted file: datMiniAnnotation3_Gold.csv\n", "Deleted file: ElasticNet_DNAmProtein_Vars_model4.csv\n" ] } ], "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 }