{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"# !pip install --no-deps ../input/classification-models/classification_models-1.0.0\n# !pip install --no-deps ../input/keras-applications","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import cv2\nimport gc\nimport numpy as np\nimport os\nimport pandas as pd\nimport pydicom as dicom\nimport random\n\nimport tensorflow as tf\nfrom tensorflow.keras import backend as K\nfrom tensorflow.keras.layers import *\nfrom tensorflow.keras.models import *\nfrom tensorflow.keras.utils import *\nfrom tensorflow.keras.metrics import *\nfrom tensorflow.keras.optimizers import *\nfrom tensorflow.keras.losses import *\nfrom tensorflow.keras.callbacks import *\n\nfrom scipy.ndimage import zoom\n\nfrom sklearn.model_selection import KFold, train_test_split","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"MIN_MAX = {\n    'Weeks': (-5., 133.),\n    'FVC': (827., 6399.),\n    'Percent': (28.877577, 153.145378),\n    'Age': (49., 88.),\n    'typical_fvc': (827., 6399.),\n}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# CONFIGS\nIMG_SIZE = 48\nNUM_OF_SCANS = 48\nBATCH_SIZE = 64\nTEST_DF = pd.read_csv('../input/osic-pulmonary-fibrosis-progression/test.csv')\nSAMPLE_SUBMISSION = pd.read_csv('../input/osic-pulmonary-fibrosis-progression/sample_submission.csv')\nmodel_path = '../input/linear-model-osic-v2'\nmodel_weights = [os.path.join(model_path, x) for x in os.listdir(model_path)]\ntraining_features = ['Weeks', 'min_week', 'min_week_FVC', 'typical_fvc', 'Age', 'Male', 'Female', 'Never smoked', 'Currently smokes', 'Ex-smoker']\nnum_of_features = len(training_features)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Data preprocessing\ndef create_typical_fvc(df):\n    df['typical_fvc'] = df['FVC'] / df['Percent'] * 100.\n    return df\n\ndef normalize(df):\n    for feature, min_max in MIN_MAX.items():\n        df[feature] = (df[feature] - min_max[0]) / (min_max[1] - min_max[0])\n    return df\n\nTEST_DF = create_typical_fvc(TEST_DF)\nTEST_DF['min_week'] = np.zeros(len(TEST_DF), dtype='int')\nTEST_DF['min_week_FVC'] = np.zeros(len(TEST_DF), dtype='int')\n\nTEST_DF['Never smoked'] = (TEST_DF['SmokingStatus'] == 'Never smoked').astype('uint8')\nTEST_DF['Currently smokes'] = (TEST_DF['SmokingStatus'] == 'Currently smokes').astype('uint8')\nTEST_DF['Ex-smoker'] = (TEST_DF['SmokingStatus'] == 'Ex-smoker').astype('uint8')\n\nTEST_DF['Male'] = (TEST_DF['Sex'] == 'Male').astype('uint8')\nTEST_DF['Female'] = (TEST_DF['Sex'] == 'Female').astype('uint8')\n    \nTEST_DF = normalize(TEST_DF)\nfor patient in np.unique(TEST_DF['Patient']):\n    TEST_DF['min_week'][TEST_DF['Patient'] == patient] = TEST_DF['Weeks'][TEST_DF['Patient'] == patient].min()\n    TEST_DF['min_week_FVC'][TEST_DF['Patient'] == patient] = TEST_DF['FVC'][TEST_DF['Patient'] == patient].values[0]\n\nTEST_DF.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_pixels_hu(scan):\n    image = scan.pixel_array\n    image = image.astype(np.int16)\n\n    # Convert to Hounsfield units (HU)\n    slope = scan.RescaleSlope\n    intercept = scan.RescaleIntercept\n    window_center = -200\n    window_width = 2000\n    if slope != 1:\n        image = slope * image.astype(np.float64)\n        image = image.astype(np.int16)\n    image += np.int16(intercept)\n\n    image_min = window_center - window_width//2\n    image_max = window_center + window_width//2\n    image[image < image_min] = image_min\n    image[image > image_max] = image_max\n    \n    image = image.astype(np.float64)\n\n    image = (image - image_min)/(image_max - image_min)*255.\n\n    return image.astype(np.uint8)\n\nvolumes = {}\nfor patient_id in np.unique(TEST_DF['Patient']):\n    image_folder = f'../input/osic-pulmonary-fibrosis-progression/test/{patient_id}'\n    image_files = np.asarray(os.listdir(image_folder))\n    image_files = image_files\n    scans = [dicom.dcmread(os.path.join(image_folder, image_file)) for image_file in image_files]\n    images = np.asarray([cv2.resize(get_pixels_hu(scan), (IMG_SIZE , IMG_SIZE)) for scan in scans], dtype='float32')\n    d, h, w = images.shape\n    d_ratio = NUM_OF_SCANS / d\n    images = zoom(images, (d_ratio, 1., 1.))\n    volumes[patient_id] = images","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"# Data Generator\n\nclass Dataset(Sequence):\n    def __init__(self, batch_size = BATCH_SIZE, mode=0):\n        self.indices = np.arange(0, len(SAMPLE_SUBMISSION), 1)\n        self.batch_size = batch_size\n        self.mode = mode # 0 - Training, 1 - Test\n    \n    def __len__(self):\n        return len(self.indices) // self.batch_size\n        \n    def get_tabular(self, patient, week):\n        week = (float(week) - MIN_MAX['Weeks'][0]) / (MIN_MAX['Weeks'][1] - MIN_MAX['Weeks'][0])\n        tabular = [week]\n        tabular += list(TEST_DF[training_features[1:]][TEST_DF['Patient'] == patient].values[0])\n        return np.asarray(tabular, dtype='float32')\n    \n    def get_volume(self, patient_id):\n        return volumes[patient_id]\n    \n    def __getitem__(self, index):\n        if index == self.__len__() - 1:\n            indices = self.indices[index*self.batch_size:]\n        else:\n            indices = self.indices[index*self.batch_size:(index+1)*self.batch_size]\n        Patient_Week = np.asarray(SAMPLE_SUBMISSION['Patient_Week'][indices])\n        patient = [x.split('_')[0] for x in Patient_Week]\n        week = [x.split('_')[1] for x in Patient_Week]\n        images = np.asarray([self.get_volume(patient_id) for patient_id in patient], dtype=np.float32) / 255.\n        images = np.expand_dims(images, axis=4)\n        tabulars = np.asarray([self.get_tabular(patient[i], week[i]) for i in range(len(patient))], dtype='float32')\n        return [images, tabulars]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Model\ndef swish(x):\n    return x * K.sigmoid(x)\n\ndef residual_block(x, num_of_filters):\n    x1 = Conv3D(num_of_filters, kernel_size=(3, 1, 1), padding='same', kernel_initializer='he_uniform')(x)\n    b1 = BatchNormalization()(x1)\n    a1 = Activation('relu')(b1)\n    x2 = Conv3D(num_of_filters, kernel_size=(1, 3, 3), padding='same', kernel_initializer='he_uniform')(a1)\n    b2 = BatchNormalization()(x2)\n    a2 = Activation('relu')(b2)\n    x3 = Conv3D(num_of_filters, kernel_size=(1, 1, 1), padding='same', kernel_initializer='he_uniform')(a2)\n    b3 = BatchNormalization()(x3)\n    a3 = Activation('relu')(b3)\n    return Add()([a1, a3])\n\ndef dense_block(x, num_of_filters):\n    x1 = residual_block(x, num_of_filters)\n    x2 = residual_block(x1, num_of_filters)\n    return Concatenate()([x1, x2])\n\ndef build_3d_cnn(input_tensor):\n    c1 = Conv3D(64, kernel_size=(5, 7, 7), strides=(1,2,2), padding='same')(input_tensor)\n    b1 = BatchNormalization()(c1)\n    a1 = Activation('relu')(b1)    \n    p1 = MaxPool3D(pool_size=(3,3,3), strides=(1,2,2))(a1)\n    \n    r1 = dense_block(p1, 64)\n    r1 = dense_block(r1, 64)\n    p1 = MaxPool3D(pool_size=(3,3,3), strides=(1,2,2))(r1)\n    \n    r2 = dense_block(p1, 128)\n    r2 = dense_block(r2, 128)\n    p2 = MaxPool3D(pool_size=(3,3,3), strides=(1,2,2))(r2)\n    \n    r3 = dense_block(p2, 256)\n    r3 = dense_block(r3, 256)\n    \n    return r3\n    \n\ndef build_model(weights):\n    input_img = Input(shape=(NUM_OF_SCANS, IMG_SIZE, IMG_SIZE, 1))\n    x_img = build_3d_cnn(input_img)\n    x_img = GlobalAveragePooling3D()(x_img)\n    \n    input_tabular = Input(shape=(num_of_features,))\n    \n    x_concat = Concatenate()([x_img, input_tabular])\n    \n    x_alpha = Dense(100)(x_concat)\n    x_x = Dense(100)(x_concat)\n    x_beta = Dense(100)(x_concat)\n    \n    alpha = Dense(3)(x_alpha)\n    x = Dense(3)(x_x)\n    beta = Dense(3)(x_beta)\n    \n    # alpha * x + beta\n    out = Lambda(lambda x : x[0] * x[1] + x[2])([alpha, x, beta])\n    \n    model = tf.keras.Model(inputs = [input_img, input_tabular], outputs = out)\n    \n    model.load_weights(weights)\n\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"models = [build_model(weights) for weights in model_weights]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_gen = Dataset(mode = 1)\npredictions = np.zeros((len(SAMPLE_SUBMISSION), 3), dtype='float32')\nfor model in models:\n    predictions += model.predict(test_gen, verbose = 1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def denormalize(y):\n    return y * (MIN_MAX['FVC'][1] - MIN_MAX['FVC'][0]) + MIN_MAX['FVC'][0]\n\npredictions = predictions / len(models)\npredictions = denormalize(predictions)\nFVC = predictions[:, 1]\nConfidence = predictions[:, 2] - predictions[:, 0]\nSAMPLE_SUBMISSION['FVC'] = FVC.astype('int')\nSAMPLE_SUBMISSION['Confidence'] = Confidence.astype('int')\nSAMPLE_SUBMISSION.to_csv('submission.csv', index=False)\nSAMPLE_SUBMISSION.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}