{"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":56537,"databundleVersionId":8015876,"sourceType":"competition"}],"dockerImageVersionId":30698,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import random, sys, gc, warnings, math\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom time import time\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras.callbacks import LearningRateScheduler, EarlyStopping\nfrom tensorflow.keras.optimizers.schedules import ExponentialDecay\nfrom tensorflow.keras.layers import Input, Dense, Concatenate, Dropout\nfrom tensorflow.keras.utils import Sequence\n\nt0 = time()\nnp.random.seed(13)\nrandom.seed(13)\nmin_std = 1e-8","metadata":{"execution":{"iopub.status.busy":"2024-04-20T21:39:00.478631Z","iopub.execute_input":"2024-04-20T21:39:00.480154Z","iopub.status.idle":"2024-04-20T21:39:18.761987Z","shell.execute_reply.started":"2024-04-20T21:39:00.480108Z","shell.execute_reply":"2024-04-20T21:39:18.760611Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load train data\ndf = pd.read_csv(\"/kaggle/input/leap-atmospheric-physics-ai-climsim/train.csv\", nrows=1000000)\nx = df.iloc[:,1:557].to_numpy().astype(np.float32)\ny = df.iloc[:,557:].to_numpy().astype(np.float32)","metadata":{"execution":{"iopub.status.busy":"2024-04-20T21:39:18.765197Z","iopub.execute_input":"2024-04-20T21:39:18.766061Z","iopub.status.idle":"2024-04-20T21:47:55.53663Z","shell.execute_reply.started":"2024-04-20T21:39:18.766016Z","shell.execute_reply":"2024-04-20T21:47:55.533721Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# read test\ndf = pd.read_csv(\"/kaggle/input/leap-atmospheric-physics-ai-climsim/test.csv\")\nxt = df.iloc[:,1:557].to_numpy().astype(np.float32)\ndel df\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-04-20T21:47:55.550933Z","iopub.execute_input":"2024-04-20T21:47:55.551337Z","iopub.status.idle":"2024-04-20T21:50:59.616377Z","shell.execute_reply.started":"2024-04-20T21:47:55.551306Z","shell.execute_reply":"2024-04-20T21:50:59.614973Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# norm X\nmx = x.mean(axis=0)\nsx = np.maximum(x.std(axis=0), min_std)\nx = (x - mx.reshape(1,-1)) / sx.reshape(1,-1)\nxt = (xt - mx.reshape(1,-1)) / sx.reshape(1,-1)","metadata":{"execution":{"iopub.status.busy":"2024-04-20T21:50:59.618551Z","iopub.execute_input":"2024-04-20T21:50:59.61982Z","iopub.status.idle":"2024-04-20T21:51:04.427664Z","shell.execute_reply.started":"2024-04-20T21:50:59.619772Z","shell.execute_reply":"2024-04-20T21:51:04.426422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# norm Y\nmy = y.mean(axis=0)\nsy = np.maximum(np.sqrt((y*y).mean(axis=0)), min_std)\ny = (y - my.reshape(1,-1)) / sy.reshape(1,-1)","metadata":{"execution":{"iopub.status.busy":"2024-04-20T21:51:04.429344Z","iopub.execute_input":"2024-04-20T21:51:04.429732Z","iopub.status.idle":"2024-04-20T21:51:06.287722Z","shell.execute_reply.started":"2024-04-20T21:51:04.429699Z","shell.execute_reply":"2024-04-20T21:51:06.28655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# data generator\nclass data_gen(Sequence): # constructor: save all data locally\n    def __init__(self, i1, i2, batch_size):\n        self.i1, self.i2 = i1, i2\n        self.batch_size = batch_size\n        return\n\n    def __len__(self): # returns number of batches\n        return math.ceil((self.i2 - self.i1) / self.batch_size)\n\n    def __getitem__(self, idx): # returns one batch\n        index = np.arange(self.i1 + idx * self.batch_size, min(self.i2, self.i1 + (idx + 1) * self.batch_size))\n        batch_x = x[index]\n        batch_y = y[index]\n        return (batch_x, batch_y)","metadata":{"execution":{"iopub.status.busy":"2024-04-20T21:51:06.289255Z","iopub.execute_input":"2024-04-20T21:51:06.289779Z","iopub.status.idle":"2024-04-20T21:51:06.3004Z","shell.execute_reply.started":"2024-04-20T21:51:06.289746Z","shell.execute_reply":"2024-04-20T21:51:06.298821Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# NN\nBS  = 1024 * 8  # batch size\nD1  = 512       # width\ntr_idx = np.arange(x.shape[0]) < x.shape[0]//2\nva_idx = np.arange(x.shape[0]) >= x.shape[0]//2\nwith tf.device('/GPU:0'):\n    i1 = Input(shape=(x.shape[1],), dtype='float32')\n    d1 = Dense(D1, activation='selu')(i1)\n    o  = Dense(y.shape[1], activation=None)(d1)\n\n    # compile the model\n    model = tf.keras.Model(inputs=i1, outputs=o)\n    model.compile(tf.keras.optimizers.Adam(0.001), loss='MSE')\n    print(model.summary())\n    es = EarlyStopping(monitor='val_loss', min_delta=.0001, patience=5, verbose=0, mode='min', restore_best_weights=True)\n    tr = data_gen(0, x.shape[0]//2, BS)\n    va = data_gen(x.shape[0]//2, x.shape[0], BS)\n    model.fit(x=tr, validation_data=va, epochs=5, callbacks=[es], verbose=2)\n\n    # predict in batches to avoid OOM\n    predt = np.zeros([xt.shape[0], y.shape[1]], dtype=np.float32)\n    i1 = 0\n    BS2 = 1024 * 128\n    for i in range(10000):\n        i2 = np.minimum(i1 + BS2, xt.shape[0])\n        predt[i1:i2,:] = model.predict(xt[i1:i2,:], verbose=0)\n        i1 = i2\n        print(np.round(i2/predt.shape[0], 2)) # pct completion\n        if i2 >= xt.shape[0]:\n            break","metadata":{"execution":{"iopub.status.busy":"2024-04-20T22:04:48.295088Z","iopub.execute_input":"2024-04-20T22:04:48.295628Z","iopub.status.idle":"2024-04-20T22:07:58.645421Z","shell.execute_reply.started":"2024-04-20T22:04:48.29559Z","shell.execute_reply":"2024-04-20T22:07:58.644112Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# submit\n# override constant columns\nfor i in range(sy.shape[0]):\n    if sy[i] < min_std * 1.1:\n        predt[:,i] = 0\n\n# undo y scaling\npredt = predt * sy.reshape(1,-1) + my.reshape(1,-1)\n\nss = pd.read_csv(\"/kaggle/input/leap-atmospheric-physics-ai-climsim/sample_submission.csv\")\nss.iloc[:,1:] *= predt\nss.to_csv(\"submission.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2024-04-20T22:08:08.094045Z","iopub.execute_input":"2024-04-20T22:08:08.094516Z","iopub.status.idle":"2024-04-20T22:18:55.954723Z","shell.execute_reply.started":"2024-04-20T22:08:08.094481Z","shell.execute_reply":"2024-04-20T22:18:55.952915Z"},"trusted":true},"execution_count":null,"outputs":[]}]}