{"cells":[{"metadata":{},"cell_type":"markdown","source":"There are several datasets provided only for the train data and not the test data. In other kernels I have shown that imputing the dipole moment and potential energy on the test set marginally improved the LB score over a simple model using only structural information:\nhttps://www.kaggle.com/robertburbidge/imputing-molecular-features\n\nAnd that estimated Mulliken charges can be used to further improve the LB score:\nhttps://www.kaggle.com/robertburbidge/using-estimated-mulliken-charges\n\nIn another notebook I tried to do the same for the magnetic shielding tensor:\nhttps://www.kaggle.com/robertburbidge/imputing-magnetic-shielding-tensor/\n\nHowever, I can't get that kernel to complete on Kaggle compute so I ran it on a VM with 72 CPUs and 144 GB of RAM and found that I couldn't do much better than predicting the median tensor for all atoms. Rather than waste time pursuing this I decided to investigate the relationship between the magnetic shielding tensor of two atoms in a molecule and their scalar coupling constant.\n\nSince I have no idea what the relationship may be, I'm using symbolic regression. It shows no relationship. As a sanity check, I show that symbolic regression correctly identifies the scalar coupling constant contribution `fc` as being predictive."},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# 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 in \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 \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nimport os\nprint(os.listdir(\"../input\"))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","collapsed":true,"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":false},"cell_type":"code","source":"from numpy.random import permutation\nfrom sklearn import metrics\nfrom fastsr.estimators.symbolic_regression import SymbolicRegression","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train = pd.read_csv('../input/train.csv')\nmagnetic_shielding_tensors = pd.read_csv('../input/magnetic_shielding_tensors.csv')\ntrain = pd.merge(train, magnetic_shielding_tensors, how='left',\n              left_on=['molecule_name', 'atom_index_0'],\n              right_on=['molecule_name', 'atom_index'])\n\ntrain.rename(columns = { \"XX\": \"XX_0\", \"YX\": \"YX_0\", \"ZX\": \"ZX_0\",\n                         \"XY\": \"XY_0\", \"YY\": \"YY_0\", \"ZY\": \"ZY_0\",\n                         \"XZ\": \"XZ_0\", \"YZ\": \"YZ_0\", \"ZZ\": \"ZZ_0\" }, inplace=True)\n\ntrain = pd.merge(train, magnetic_shielding_tensors, how='left',\n              left_on=['molecule_name', 'atom_index_1'],\n              right_on=['molecule_name', 'atom_index'])\n\ntrain.rename(columns = { \"XX\": \"XX_1\", \"YX\": \"YX_1\", \"ZX\": \"ZX_1\",\n                         \"XY\": \"XY_1\", \"YY\": \"YY_1\", \"ZY\": \"ZY_1\",\n                         \"XZ\": \"XZ_1\", \"YZ\": \"YZ_1\", \"ZZ\": \"ZZ_1\" }, inplace=True)\ndel magnetic_shielding_tensors","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# one-hot-encode type\ntrain = pd.concat([train, pd.get_dummies(train['type'], prefix='type')], axis=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# features for predicting scalar coupling constant on train set from magnetic shielding tensors\npred_vars = ['type_1JHC', 'type_1JHN', 'type_2JHC', 'type_2JHH', 'type_2JHN',\n             'type_3JHC', 'type_3JHH', 'type_3JHN', 'XX_0', 'YX_0', 'ZX_0', 'XY_0', 'YY_0', 'ZY_0',\n             'XZ_0', 'YZ_0', 'ZZ_0', 'XX_1', 'YX_1', 'ZX_1', 'XY_1',\n             'YY_1', 'ZY_1', 'XZ_1', 'YZ_1', 'ZZ_1']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# train-val split by molecule_name\nmolecule_names = pd.DataFrame(permutation(train['molecule_name'].unique()),columns=['molecule_name'])\nnm = molecule_names.shape[0]\nntrn = int(0.9*nm)\nnval = int(0.1*nm)\n\ntmp_train = pd.merge(train, molecule_names[0:ntrn], how='right', on='molecule_name')\ntmp_val = pd.merge(train, molecule_names[ntrn:nm], how='right', on='molecule_name')\n\nX_train = tmp_train[pred_vars]\nX_val = tmp_val[pred_vars]\ny_train = tmp_train['scalar_coupling_constant']\ny_val = tmp_val['scalar_coupling_constant']\ny_type = tmp_val['type']\ndel tmp_train, tmp_val","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# fit symbolic regression on train\nsr = SymbolicRegression(ngen=100, pop_size=10)\nsr.fit(X_train.values, y_train.values)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# evaluation metric for validation\n# https://www.kaggle.com/abhishek/competition-metric\ndef metric(df, preds):\n    df[\"prediction\"] = preds\n    maes = []\n    for t in df.type.unique():\n        y_true = df[df.type==t].scalar_coupling_constant.values\n        y_pred = df[df.type==t].prediction.values\n        mae = np.log(metrics.mean_absolute_error(y_true, y_pred))\n        maes.append(mae)\n    return np.mean(maes)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# performance on val\npreds = sr.predict(X_val.values)\nmetric(pd.concat([X_val, y_val, y_type], axis=1), preds)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"This suggests that there is no relationship between the magnetic shielding tensors and the scalar coupling constant.\n\nAs a sanity check, in the following I check that symbolic regression can find a relationship when it exists by regressing the scalar coupling constant on its contributions."},{"metadata":{"trusted":true},"cell_type":"code","source":"scc = pd.read_csv('../input/scalar_coupling_contributions.csv')\ntrain = pd.merge(train, scc, how='left',\n                 on=['molecule_name', 'atom_index_0', 'atom_index_1', 'type'])\ndel scc","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# features for predicting scalar coupling constant on train set from its contributions\npred_vars = ['type_1JHC', 'type_1JHN', 'type_2JHC', 'type_2JHH', 'type_2JHN',\n             'type_3JHC', 'type_3JHH', 'type_3JHN', 'fc', 'sd', 'pso', 'dso']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# train-val split by molecule_name\nmolecule_names = pd.DataFrame(permutation(train['molecule_name'].unique()),columns=['molecule_name'])\nnm = molecule_names.shape[0]\nntrn = int(0.9*nm)\nnval = int(0.1*nm)\n\ntmp_train = pd.merge(train, molecule_names[0:ntrn], how='right', on='molecule_name')\ntmp_val = pd.merge(train, molecule_names[ntrn:nm], how='right', on='molecule_name')\n\nX_train = tmp_train[pred_vars]\nX_val = tmp_val[pred_vars]\ny_train = tmp_train['scalar_coupling_constant']\ny_val = tmp_val['scalar_coupling_constant']\ny_type = tmp_val['type']\ndel tmp_train, tmp_val","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# fit symbolic regression on train\nsr = SymbolicRegression(ngen=100, pop_size=10)\nsr.fit(X_train.values, y_train.values)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# performance on val\npreds = sr.predict(X_val.values)\nmetric(pd.concat([X_val, y_val, y_type], axis=1), preds)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Symbolic regression has picked up a strong relationship. Let's see what it is."},{"metadata":{"trusted":true},"cell_type":"code","source":"sr.print_best_individuals()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The best individuals are `fc` with minor random variations (introduced by the stochastic search), which is known to be the major contributing factor.\n\nConclusion: I am not going to bother with the magnetic shielding tensor."}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}