{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":20604,"databundleVersionId":1357052,"sourceType":"competition"}],"dockerImageVersionId":30646,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfrom tqdm import tqdm\n\n       \nimport numpy as np\nfrom torch.utils.data import Dataset, DataLoader\nfrom sklearn.preprocessing import MinMaxScaler\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport math\nfrom torch.nn import TransformerEncoder, TransformerEncoderLayer\n\nfrom sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score\nfrom sklearn.model_selection import train_test_split","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:30.590828Z","iopub.execute_input":"2024-03-09T19:35:30.591320Z","iopub.status.idle":"2024-03-09T19:35:35.947665Z","shell.execute_reply.started":"2024-03-09T19:35:30.591264Z","shell.execute_reply":"2024-03-09T19:35:35.946263Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Path = \"../input/osic-pulmonary-fibrosis-progression\"\ndf_train= pd.read_csv(f\"{Path}/train.csv\")\ndf_train.drop_duplicates(keep=False, inplace=True,subset=['Patient','Weeks'])\ndf_test= pd.read_csv(f\"{Path}/test.csv\")\nPatient_list= df_train[\"Patient\"].unique()","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:35.952090Z","iopub.execute_input":"2024-03-09T19:35:35.952636Z","iopub.status.idle":"2024-03-09T19:35:36.000508Z","shell.execute_reply.started":"2024-03-09T19:35:35.952594Z","shell.execute_reply":"2024-03-09T19:35:35.998986Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:36.002219Z","iopub.execute_input":"2024-03-09T19:35:36.002994Z","iopub.status.idle":"2024-03-09T19:35:36.026301Z","shell.execute_reply.started":"2024-03-09T19:35:36.002952Z","shell.execute_reply":"2024-03-09T19:35:36.024985Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_test","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:36.029483Z","iopub.execute_input":"2024-03-09T19:35:36.030209Z","iopub.status.idle":"2024-03-09T19:35:36.043562Z","shell.execute_reply.started":"2024-03-09T19:35:36.030167Z","shell.execute_reply":"2024-03-09T19:35:36.042472Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for patient, group in df_train.groupby('Patient'):\n    print(f\"Patient {patient}: Weeks values {group['Weeks'].tolist()}\")","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:36.044973Z","iopub.execute_input":"2024-03-09T19:35:36.045596Z","iopub.status.idle":"2024-03-09T19:35:36.073020Z","shell.execute_reply.started":"2024-03-09T19:35:36.045556Z","shell.execute_reply":"2024-03-09T19:35:36.071889Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train.groupby('Patient').size()","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:36.074188Z","iopub.execute_input":"2024-03-09T19:35:36.074579Z","iopub.status.idle":"2024-03-09T19:35:36.087359Z","shell.execute_reply.started":"2024-03-09T19:35:36.074549Z","shell.execute_reply":"2024-03-09T19:35:36.085979Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"datapoints_per_patient = df_train.groupby('Patient').size()\n\n# Filter to get patients with less than 7 datapoints.\npatients_with_less_than_7 = datapoints_per_patient[datapoints_per_patient < 7]\n\n# Count the number of such patients.\nnumber_of_patients = patients_with_less_than_7.count()\n\nprint(f'Number of patients with less than 7 datapoints: {number_of_patients}')","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:36.088590Z","iopub.execute_input":"2024-03-09T19:35:36.089081Z","iopub.status.idle":"2024-03-09T19:35:36.099746Z","shell.execute_reply.started":"2024-03-09T19:35:36.089053Z","shell.execute_reply":"2024-03-09T19:35:36.098504Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train = df_train.groupby('Patient').filter(lambda x: len(x) >= 7)","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:36.101650Z","iopub.execute_input":"2024-03-09T19:35:36.102012Z","iopub.status.idle":"2024-03-09T19:35:36.118051Z","shell.execute_reply.started":"2024-03-09T19:35:36.101983Z","shell.execute_reply":"2024-03-09T19:35:36.117172Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"datapoints_per_patient = df_train.groupby('Patient').size()\n\n# Filter to get patients with less than 7 datapoints.\npatients_with_less_than_7 = datapoints_per_patient[datapoints_per_patient < 7]\n\n# Count the number of such patients.\nnumber_of_patients = patients_with_less_than_7.count()\n\nprint(f'Number of patients with less than 7 datapoints: {number_of_patients}')","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:36.119095Z","iopub.execute_input":"2024-03-09T19:35:36.120057Z","iopub.status.idle":"2024-03-09T19:35:36.128839Z","shell.execute_reply.started":"2024-03-09T19:35:36.120028Z","shell.execute_reply":"2024-03-09T19:35:36.127697Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def Seven(group):\n    if len(group) > 7:\n        return group.iloc[-7:]  # Selects the last 7 rows\n    return group","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:36.133100Z","iopub.execute_input":"2024-03-09T19:35:36.133862Z","iopub.status.idle":"2024-03-09T19:35:36.140494Z","shell.execute_reply.started":"2024-03-09T19:35:36.133831Z","shell.execute_reply":"2024-03-09T19:35:36.139421Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport itertools\nimport pandas as pd\n\nfrom itertools import combinations\n\ndef select_evenly_spaced_points(df_group, num_points=7):\n    weeks = df_group['Weeks'].tolist()\n    \n    if len(weeks) <= num_points:\n        return df_group\n\n    best_combination = None\n    best_std = float('inf')\n\n    for combination in combinations(weeks, num_points):\n        intervals = np.diff(sorted(combination))\n        std = np.std(intervals)\n\n        if std < best_std:\n            best_std = std\n            best_combination = combination\n\n    # Ensure that best_combination is not None and has unique points\n    if best_combination and len(set(best_combination)) == num_points:\n        return df_group[df_group['Weeks'].isin(best_combination)]\n    else:\n        # Fallback: select points with maximum intervals between them\n        sorted_weeks = sorted(weeks)\n        selected_indices = [0]  # Always include the first point\n        interval = len(sorted_weeks) // (num_points - 1)\n\n        for i in range(1, num_points - 1):\n            selected_indices.append(i * interval)\n        selected_indices.append(len(sorted_weeks) - 1)  # Always include the last point\n\n        return df_group[df_group['Weeks'].isin([sorted_weeks[i] for i in selected_indices])]","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:36.144050Z","iopub.execute_input":"2024-03-09T19:35:36.144399Z","iopub.status.idle":"2024-03-09T19:35:36.155322Z","shell.execute_reply.started":"2024-03-09T19:35:36.144371Z","shell.execute_reply":"2024-03-09T19:35:36.154232Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train = df_train.groupby('Patient').apply(select_evenly_spaced_points).reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:36.156437Z","iopub.execute_input":"2024-03-09T19:35:36.157573Z","iopub.status.idle":"2024-03-09T19:35:36.573614Z","shell.execute_reply.started":"2024-03-09T19:35:36.157514Z","shell.execute_reply":"2024-03-09T19:35:36.572349Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"all_have_seven = all(df_train.groupby('Patient').size() == 7)\nprint(f'Do all patients have exactly 7 datapoints? {all_have_seven}')","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:36.575048Z","iopub.execute_input":"2024-03-09T19:35:36.575386Z","iopub.status.idle":"2024-03-09T19:35:36.582401Z","shell.execute_reply.started":"2024-03-09T19:35:36.575359Z","shell.execute_reply":"2024-03-09T19:35:36.581310Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def process_patient_group(df_group):\n    df_group = df_group.sort_values(by='Weeks')\n    patient_data = {\n        'Patient': df_group['Patient'].iloc[0],\n        'Weeks': ','.join(df_group['Weeks'].astype(str)),\n        'Percent': ','.join(df_group['Percent'].astype(str)),\n        'FVC': ','.join(df_group['FVC'].astype(str)),\n        'Age': df_group['Age'].iloc[0], \n        'Sex': df_group['Sex'].iloc[0],  \n        'SmokingStatus': df_group['SmokingStatus'].iloc[0]  # Assuming smoking status is constant for all rows of the same patient\n    }\n    return pd.Series(patient_data)","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:36.583650Z","iopub.execute_input":"2024-03-09T19:35:36.583969Z","iopub.status.idle":"2024-03-09T19:35:36.591975Z","shell.execute_reply.started":"2024-03-09T19:35:36.583942Z","shell.execute_reply":"2024-03-09T19:35:36.590946Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"processed_df = df_train.groupby('Patient').apply(process_patient_group).reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:36.593269Z","iopub.execute_input":"2024-03-09T19:35:36.593635Z","iopub.status.idle":"2024-03-09T19:35:36.805312Z","shell.execute_reply.started":"2024-03-09T19:35:36.593607Z","shell.execute_reply":"2024-03-09T19:35:36.803246Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Display\nprocessed_df.head(7)","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:36.806608Z","iopub.execute_input":"2024-03-09T19:35:36.807030Z","iopub.status.idle":"2024-03-09T19:35:36.823427Z","shell.execute_reply.started":"2024-03-09T19:35:36.806991Z","shell.execute_reply":"2024-03-09T19:35:36.821936Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Assuming 'processed_df' is your preprocessed DataFrame\npercent_values = processed_df['Percent'].apply(lambda x: np.fromstring(x, dtype=float, sep=','))\nmin_percent_values = percent_values.apply(min)\n\n# Check if any percent value is less than 0\nif (min_percent_values < 0).any():\n    print(\"There are percent values less than 0.\")\nelse:\n    print(\"All percent values are greater than or equal to 0.\")","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:36.824942Z","iopub.execute_input":"2024-03-09T19:35:36.825262Z","iopub.status.idle":"2024-03-09T19:35:36.836431Z","shell.execute_reply.started":"2024-03-09T19:35:36.825235Z","shell.execute_reply":"2024-03-09T19:35:36.835309Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pydicom\nfrom tqdm import tqdm\nfrom PIL import Image\n\ndef preprocess_ct_images(patient_list, data_type=\"train\", image_size=(128, 128), show_first_image=False):\n    x = []\n    for patient in tqdm(patient_list):\n        image_dir = f\"{Path}/{data_type}/{patient}\"\n        week = df_train[df_train[\"Patient\"] == patient][\"Weeks\"]\n        image_count = 0  # Initialize a counter for the number of images\n        for i, w in enumerate(week):\n            try:\n                ds = pydicom.dcmread(os.path.join(image_dir, f\"{w}.dcm\"))\n                im = Image.fromarray(ds.pixel_array)\n                im = im.resize(image_size, resample=Image.NEAREST)\n                im_array = np.array(im).reshape((*image_size, 1))  # Grayscale image\n                im_array = im_array / 255.0  # Normalization\n                x.append(im_array)\n                image_count += 1  # Increment the counter\n                \n            except Exception as e:\n                print(f\"{e}\")\n        print(f\"Patient {patient} has {image_count} images.\")  # Print the total number of images found for each patient\n    return np.array(x)\n\n# Preprocess CT scan images\nx_train = preprocess_ct_images(Patient_list, \"train\", show_first_image=True)","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:36.837834Z","iopub.execute_input":"2024-03-09T19:35:36.838149Z","iopub.status.idle":"2024-03-09T19:35:56.300021Z","shell.execute_reply.started":"2024-03-09T19:35:36.838123Z","shell.execute_reply":"2024-03-09T19:35:56.298906Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras import layers as L\nfrom tensorflow.keras import models as M\n\ndef extract_image_features():\n    ct = L.Input((128, 128, 1), name=\"Ctinput\")\n    x = L.Conv2D(64, (6, 6), activation=\"relu\", name=\"conv1\")(ct)\n    x = L.MaxPooling2D(pool_size=(3, 3), name='pool1')(x)\n    x = L.Conv2D(64, (6, 6), activation=\"relu\", name=\"conv2\")(x)\n    x = L.MaxPooling2D(pool_size=(3, 3), name='pool2')(x)\n    x = L.Conv2D(128, (6, 6), activation=\"relu\", name=\"conv3\")(x)\n    x = L.MaxPooling2D(pool_size=(2, 2), name='pool3')(x)\n    x = L.Flatten(name=\"features\")(x)\n    model = M.Model(ct, x, name=\"ImageFeatureExtractor\")\n    return model\n\n# Instantiate the image feature extractor\nimage_feature_extractor = extract_image_features()\nprint(image_feature_extractor.summary())\n\n# Extract image features from the training data\nimage_features = image_feature_extractor.predict(x_train, batch_size=50, verbose=1)","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:35:56.301336Z","iopub.execute_input":"2024-03-09T19:35:56.301698Z","iopub.status.idle":"2024-03-09T19:36:19.409117Z","shell.execute_reply.started":"2024-03-09T19:35:56.301669Z","shell.execute_reply":"2024-03-09T19:36:19.408201Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(image_feature_extractor.summary())\nprint(image_features.shape)","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:36:19.410698Z","iopub.execute_input":"2024-03-09T19:36:19.411303Z","iopub.status.idle":"2024-03-09T19:36:19.442638Z","shell.execute_reply.started":"2024-03-09T19:36:19.411262Z","shell.execute_reply":"2024-03-09T19:36:19.441823Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Assuming 'processed_df' is your preprocessed DataFrame\nprocessed_df = df_train.groupby('Patient').apply(process_patient_group).reset_index(drop=True)\n\n# Duplicate the dataframe and add a suffix to the patient IDs\nduplicated_df = processed_df.copy()\nduplicated_df['Patient'] = duplicated_df['Patient'] + '_dup'\n\n# Concatenate the original and duplicated dataframes\naugmented_df = pd.concat([processed_df, duplicated_df], ignore_index=True)\n","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:36:19.443814Z","iopub.execute_input":"2024-03-09T19:36:19.444111Z","iopub.status.idle":"2024-03-09T19:36:19.653947Z","shell.execute_reply.started":"2024-03-09T19:36:19.444086Z","shell.execute_reply":"2024-03-09T19:36:19.652876Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.utils.data import Dataset\nimport numpy as np\nimport torch\nfrom sklearn.preprocessing import MinMaxScaler\n\nclass FVCDataset(Dataset):\n    def __init__(self, dataframe):\n        fvc_values = [np.fromstring(row['FVC'], dtype=float, sep=',') for _, row in dataframe.iterrows()]\n        self.scaler = MinMaxScaler()\n        # Reshape to fit the scaler properly\n        self.fvc_values = self.scaler.fit_transform(np.array(fvc_values).reshape(-1, 1)).reshape(-1, 7)\n\n    def __len__(self):\n        return len(self.fvc_values)\n\n    def __getitem__(self, idx):\n        fvc = torch.tensor(self.fvc_values[idx][:5], dtype=torch.float32)  # First 5 FVC values as input\n        target = torch.tensor(self.fvc_values[idx][-2:], dtype=torch.float32)  # Last 2 FVC values as target\n        return fvc, target\n\n    def inverse_transform(self, scaled_fvc):\n        return self.scaler.inverse_transform(scaled_fvc)\n\n# Now you can proceed to create the dataset and split it into training and validation sets\ndataset = FVCDataset(augmented_df)\n","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:36:19.655303Z","iopub.execute_input":"2024-03-09T19:36:19.656142Z","iopub.status.idle":"2024-03-09T19:36:19.697359Z","shell.execute_reply.started":"2024-03-09T19:36:19.656098Z","shell.execute_reply":"2024-03-09T19:36:19.696197Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(processed_df['Age'].unique())\nprint(processed_df['SmokingStatus'].unique())\nprint(processed_df['Sex'].unique())","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:36:19.698984Z","iopub.execute_input":"2024-03-09T19:36:19.699329Z","iopub.status.idle":"2024-03-09T19:36:19.708667Z","shell.execute_reply.started":"2024-03-09T19:36:19.699302Z","shell.execute_reply":"2024-03-09T19:36:19.707570Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Generate indices: an array of integers from 0 to the length of the dataset - 1\ndataset_indices = [i for i in range(len(dataset))]\n\n# Split indices into training and validation sets\ntrain_indices, val_indices, _, _ = train_test_split(dataset_indices, dataset_indices, test_size=0.2, random_state=42)\n\n# Create subsets for training and validation using Subset\nfrom torch.utils.data import Subset\n\ntrain_dataset = Subset(dataset, train_indices)\nval_dataset = Subset(dataset, val_indices)\n\nfrom torch.utils.data import DataLoader\n\ntrain_loader = DataLoader(train_dataset, batch_size=10, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=10, shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:36:19.710609Z","iopub.execute_input":"2024-03-09T19:36:19.711023Z","iopub.status.idle":"2024-03-09T19:36:19.721225Z","shell.execute_reply.started":"2024-03-09T19:36:19.710986Z","shell.execute_reply":"2024-03-09T19:36:19.720308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class PositionalEncoding(nn.Module):\n    def __init__(self, d_model, dropout=0.1, max_len=5000):\n        super(PositionalEncoding, self).__init__()\n        self.dropout = nn.Dropout(p=dropout)\n\n        position = torch.arange(max_len).unsqueeze(1)\n        div_term = torch.exp(torch.arange(0, d_model, 2) * -(math.log(10000.0) / d_model))\n        pe = torch.zeros(max_len, d_model)\n        pe[:, 0::2] = torch.sin(position * div_term)\n        pe[:, 1::2] = torch.cos(position * div_term)\n        pe = pe.unsqueeze(0)\n        self.register_buffer('pe', pe)\n\n    def forward(self, x):\n        x = x + self.pe[:, :x.size(1), :]\n        return self.dropout(x)\n","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:36:19.722687Z","iopub.execute_input":"2024-03-09T19:36:19.723042Z","iopub.status.idle":"2024-03-09T19:36:19.733609Z","shell.execute_reply.started":"2024-03-09T19:36:19.723014Z","shell.execute_reply":"2024-03-09T19:36:19.732443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\n\nclass FVCTransformer(nn.Module):\n    def __init__(self, fvc_input_dim, output_dim):\n        super(FVCTransformer, self).__init__()\n        self.fvc_linear = nn.Linear(fvc_input_dim, 64)\n        self.output_linear = nn.Linear(64, output_dim)\n\n    def forward(self, fvc):\n        fvc_output = self.fvc_linear(fvc)\n        output = self.output_linear(fvc_output)\n        return output\n\nfvc_input_dim = 5  # Only 5 FVC values as input\noutput_dim = 2  # Predicting the last 2 FVC values\nmodel = FVCTransformer(fvc_input_dim, output_dim)\n\n\nfvc_input_dim = 5  # Only 5 FVC values as input\noutput_dim = 2  # Predicting the last 2 FVC values\nmodel = FVCTransformer(fvc_input_dim, output_dim)\n","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:36:19.735149Z","iopub.execute_input":"2024-03-09T19:36:19.735552Z","iopub.status.idle":"2024-03-09T19:36:19.781675Z","shell.execute_reply.started":"2024-03-09T19:36:19.735493Z","shell.execute_reply":"2024-03-09T19:36:19.780753Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''class FVCRNN(nn.Module):\n    def __init__(self, input_dim, hidden_dim, num_layers, output_dim):\n        super(FVCRNN, self).__init__()\n        \n        self.hidden_dim = hidden_dim\n        self.num_layers = num_layers\n        \n        self.rnn = nn.RNN(input_dim, hidden_dim, num_layers, batch_first=True)\n        self.output_linear = nn.Linear(hidden_dim, output_dim)\n        \n    def forward(self, x):\n        h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_dim).to(x.device)\n        out, _ = self.rnn(x, h0)\n        out = self.output_linear(out[:, -2:, :])\n        return out\n\n# Initialize the RNN model\ninput_dim = 8  # Weeks, Percent, FVC, Age, Sex, SmokingStatus\nhidden_dim = 64\nnum_layers = 2\noutput_dim = 1  # Predict FVC value\n\n'''","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:36:19.783142Z","iopub.execute_input":"2024-03-09T19:36:19.783477Z","iopub.status.idle":"2024-03-09T19:36:19.793953Z","shell.execute_reply.started":"2024-03-09T19:36:19.783447Z","shell.execute_reply":"2024-03-09T19:36:19.792674Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_model(model, train_loader, val_loader, criterion, optimizer, num_epochs=20):\n    train_losses = []\n    val_losses = []\n    train_accuracies = []\n    val_accuracies = []\n\n    for epoch in range(num_epochs):\n        model.train()\n        total_train_loss = 0\n        correct_train_predictions = 0\n\n        for inputs, targets in train_loader:\n            optimizer.zero_grad()\n            outputs = model(inputs)\n            loss = criterion(outputs, targets)\n            loss.backward()\n            optimizer.step()\n            total_train_loss += loss.item()\n\n            # Calculate accuracy for training\n            train_accuracy = torch.mean(((torch.abs(targets - outputs) / targets) < 0.15).float()).item()\n            correct_train_predictions += train_accuracy * len(targets)\n\n        avg_train_loss = total_train_loss / len(train_loader)\n        train_losses.append(avg_train_loss)\n        train_accuracies.append(correct_train_predictions / len(train_loader.dataset))\n\n        model.eval()\n        total_val_loss = 0\n        correct_val_predictions = 0\n\n        with torch.no_grad():\n            for inputs, targets in val_loader:\n                outputs = model(inputs)\n                loss = criterion(outputs, targets)\n                total_val_loss += loss.item()\n\n                # Calculate accuracy for validation\n                val_accuracy = torch.mean(((torch.abs(targets - outputs) / targets) < 0.15).float()).item()\n                correct_val_predictions += val_accuracy * len(targets)\n\n        avg_val_loss = total_val_loss / len(val_loader)\n        val_losses.append(avg_val_loss)\n        val_accuracies.append(correct_val_predictions / len(val_loader.dataset))\n\n        print(f'Epoch {epoch+1}, Training Loss: {avg_train_loss}, Validation Loss: {avg_val_loss}, '\n              f'Training Accuracy: {train_accuracies[-1]:.2f}, Validation Accuracy: {val_accuracies[-1]:.2f}')\n\n    # Plot the training and validation losses and accuracies\n    plt.figure(figsize=(12, 5))\n    plt.subplot(1, 2, 1)\n    plt.plot(range(1, num_epochs + 1), train_losses, label='Training Loss')\n    plt.plot(range(1, num_epochs + 1), val_losses, label='Validation Loss')\n    plt.xlabel('Epoch')\n    plt.ylabel('Loss')\n    plt.title('Epoch vs. Loss')\n    plt.legend()\n\n    plt.subplot(1, 2, 2)\n    plt.plot(range(1, num_epochs + 1), train_accuracies, label='Training Accuracy')\n    plt.plot(range(1, num_epochs + 1), val_accuracies, label='Validation Accuracy')\n    plt.xlabel('Epoch')\n    plt.ylabel('Accuracy')\n    plt.title('Epoch vs. Accuracy')\n    plt.legend()\n\n    plt.tight_layout()\n    plt.show()\n\n    return train_losses, val_losses, train_accuracies, val_accuracies\n","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:36:19.800550Z","iopub.execute_input":"2024-03-09T19:36:19.801194Z","iopub.status.idle":"2024-03-09T19:36:19.819011Z","shell.execute_reply.started":"2024-03-09T19:36:19.801164Z","shell.execute_reply":"2024-03-09T19:36:19.817898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch.nn as nn\nimport torch.optim as optim\nimport matplotlib.pyplot as plt\n\ncriterion = nn.MSELoss()\noptimizer = optim.Adam(model.parameters(), lr=0.001)  # Start with a learning rate of 0.001\n\n# You can try different learning rates to see which one works best for your model\n# For example:\n# optimizer = optim.Adam(model.parameters(), lr=0.0001)  # Decrease the learning rate if needed\n\n# Train the model and plot the loss and accuracy\ntrain_losses, val_losses, train_accuracies, val_accuracies = train_model(model, train_loader, val_loader, criterion, optimizer, num_epochs=200)\n","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:36:19.820350Z","iopub.execute_input":"2024-03-09T19:36:19.821220Z","iopub.status.idle":"2024-03-09T19:36:30.421342Z","shell.execute_reply.started":"2024-03-09T19:36:19.821179Z","shell.execute_reply":"2024-03-09T19:36:30.420076Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"from scipy.stats import pearsonr\nfrom sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score\nimport numpy as np\n\ndef evaluate_model(model, dataloader, scaler):\n    model.eval()  # Put the model in evaluation mode\n    \n    predictions, actuals = [], []\n    \n    with torch.no_grad():\n        for inputs, targets in dataloader:\n            outputs = model(inputs)\n            outputs = outputs.squeeze(-1)  # Adjust dimensions if necessary\n            \n            # Select only the last output for comparison\n            predicted_fvc = outputs.detach().cpu().numpy()\n            actual_fvc = targets.detach().cpu().numpy()\n            \n            # Unscale the predictions and actual values\n            predicted_fvc = scaler.inverse_transform(predicted_fvc.reshape(-1, 1)).flatten()\n            actual_fvc = scaler.inverse_transform(actual_fvc.reshape(-1, 1)).flatten()\n            \n            predictions.extend(predicted_fvc)\n            actuals.extend(actual_fvc)\n    \n    predictions = np.array(predictions)\n    actuals = np.array(actuals)\n    \n    # Calculate metrics\n    mae = mean_absolute_error(actuals, predictions)\n    rmse = mean_squared_error(actuals, predictions, squared=False)  # Pass squared=False for RMSE\n    r2 = r2_score(actuals, predictions)\n    pearson_corr = pearsonr(predictions, actuals)[0]\n    \n    return mae, rmse, r2, pearson_corr\n","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:36:30.422808Z","iopub.execute_input":"2024-03-09T19:36:30.423234Z","iopub.status.idle":"2024-03-09T19:36:30.434566Z","shell.execute_reply.started":"2024-03-09T19:36:30.423206Z","shell.execute_reply":"2024-03-09T19:36:30.433230Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"scaler = dataset.scaler  # Assuming 'dataset' is an instance of FVCDataset\nmae, rmse, r2, pearson_corr = evaluate_model(model, val_loader, scaler)\nprint(f\"Validation MAE: {mae}, Validation RMSE: {rmse}, Validation R^2: {r2}, Validation Pearson Correlation: {pearson_corr}\")","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:36:30.436207Z","iopub.execute_input":"2024-03-09T19:36:30.436700Z","iopub.status.idle":"2024-03-09T19:36:30.472463Z","shell.execute_reply.started":"2024-03-09T19:36:30.436670Z","shell.execute_reply":"2024-03-09T19:36:30.471373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''#RNN EVVAL\nrnn_model = FVCRNN(input_dim, hidden_dim, num_layers, output_dim)\n\n# Define the loss function and optimizer for the RNN model\nrnn_criterion = nn.MSELoss()\nrnn_optimizer = optim.Adam(rnn_model.parameters(), lr=0.001)\n\n# Train the RNN model\ntrain_model(rnn_model, train_loader, val_loader, rnn_criterion, rnn_optimizer, num_epochs=3000)\n\n# Evaluate the RNN model\nrnn_mae, rnn_rmse, rnn_r2, rnn_pearson_corr = evaluate_model(rnn_model, val_loader)\nprint(f\"RNN Validation MAE: {rnn_mae}, RNN Validation RMSE: {rnn_rmse}, RNN Validation R^2: {rnn_r2}, RNN Validation Pearson Correlation: {rnn_pearson_corr}\")\n'''","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:36:30.474071Z","iopub.execute_input":"2024-03-09T19:36:30.474449Z","iopub.status.idle":"2024-03-09T19:36:30.481113Z","shell.execute_reply.started":"2024-03-09T19:36:30.474420Z","shell.execute_reply":"2024-03-09T19:36:30.480169Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(torch.__version__)","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:36:30.482488Z","iopub.execute_input":"2024-03-09T19:36:30.482964Z","iopub.status.idle":"2024-03-09T19:36:30.494610Z","shell.execute_reply.started":"2024-03-09T19:36:30.482932Z","shell.execute_reply":"2024-03-09T19:36:30.493337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#USE MSE","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:36:30.496040Z","iopub.execute_input":"2024-03-09T19:36:30.496610Z","iopub.status.idle":"2024-03-09T19:36:30.503680Z","shell.execute_reply.started":"2024-03-09T19:36:30.496563Z","shell.execute_reply":"2024-03-09T19:36:30.502636Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(dir(torch._subclasses))\n","metadata":{"execution":{"iopub.status.busy":"2024-03-09T19:36:30.505363Z","iopub.execute_input":"2024-03-09T19:36:30.505699Z","iopub.status.idle":"2024-03-09T19:36:30.513902Z","shell.execute_reply.started":"2024-03-09T19:36:30.505672Z","shell.execute_reply":"2024-03-09T19:36:30.512997Z"},"trusted":true},"execution_count":null,"outputs":[]}]}