Upload folder using huggingface_hub
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitignore +12 -0
- .ms_upload_cache +1 -0
- LICENSE +21 -0
- README.md +215 -0
- conf/README_upstream.rst +52 -0
- conf/config.json +12 -0
- conf/data/smoke.fasta +2 -0
- conf/data/test_sequences.fasta +0 -0
- conf/environment.yml +10 -0
- conf/environment_upstream.yml +25 -0
- conf/legacy/P2PXML_dataset/.DS_Store +0 -0
- conf/legacy/P2PXML_dataset/P2PXML-Seq/README.md +66 -0
- conf/legacy/P2PXML_dataset/P2PXML_Structure/.DS_Store +0 -0
- conf/legacy/P2PXML_dataset/P2PXML_Structure/README.md +61 -0
- conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antibodies_0.5γ.pt +3 -0
- conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antibodies_10-1074.pt +3 -0
- conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_0013095_2_11.pt +3 -0
- conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_0815_V3_C3.pt +3 -0
- conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_6535_3.pt +3 -0
- conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_AC10_29.pt +3 -0
- conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_JRFL.pt +3 -0
- conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_PVO_4.pt +0 -0
- conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_QH0692_42.pt +3 -0
- conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_REJO4541_67.pt +3 -0
- conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_RHPA4259_7.pt +3 -0
- conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_WITO4160_33.pt +3 -0
- conf/legacy/__MACOSX/P2PXML_dataset/._.DS_Store +0 -0
- conf/legacy/__MACOSX/P2PXML_dataset/._P2PXML_Structure +0 -0
- conf/legacy/__MACOSX/P2PXML_dataset/P2PXML-Seq/._README.md +0 -0
- conf/legacy/__MACOSX/P2PXML_dataset/P2PXML_Structure/._.DS_Store +0 -0
- conf/legacy/__MACOSX/P2PXML_dataset/P2PXML_Structure/._README.md +0 -0
- conf/legacy/incomplete_transfers/ESM1v-SVR.partial.pkl +3 -0
- conf/legacy/python_cache/ephod/__init__.cpython-310.pyc +0 -0
- conf/legacy/python_cache/ephod/__init__.cpython-311.pyc +0 -0
- conf/legacy/python_cache/model/__init__.cpython-310.pyc +0 -0
- conf/legacy/python_cache/training/__init__.cpython-310.pyc +0 -0
- conf/legacy/python_cache/training/__init__.cpython-311.pyc +0 -0
- conf/legacy/python_cache/training/nn_models.cpython-311.pyc +0 -0
- conf/legacy/torch_cache/hub/checkpoints/ESM1v-RLATtr.pt +3 -0
- conf/legacy/torch_cache/hub/checkpoints/esm1v_t33_650M_UR90S_1.pt +3 -0
- configuration.json +15 -0
- model/__init__.py +1 -0
- model/__pycache__/__init__.cpython-311.pyc +0 -0
- model/ephod/__init__.py +9 -0
- model/ephod/__pycache__/__init__.cpython-311.pyc +0 -0
- model/ephod/training/__init__.py +0 -0
- model/ephod/training/__pycache__/__init__.cpython-311.pyc +0 -0
- model/ephod/training/__pycache__/nn_models.cpython-311.pyc +0 -0
- model/ephod/training/nn_models.py +659 -0
- model/ephod/training/trainutils.py +165 -0
.gitignore
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
**/.DS_store
|
| 2 |
+
**/*~
|
| 3 |
+
**/.ipynb_checkpoints
|
| 4 |
+
**/__pycache__/
|
| 5 |
+
*.raysync.downloading
|
| 6 |
+
conf/legacy/
|
| 7 |
+
*.csv
|
| 8 |
+
*.ipynb
|
| 9 |
+
backup
|
| 10 |
+
env
|
| 11 |
+
gitcommands.sh
|
| 12 |
+
run_ephod.sh
|
.ms_upload_cache
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"version": 3, "repo_id": "OneScience/EpHod", "files": {"LICENSE|1745926779.0|1113": {"hash": "7088340822ab1d59337486f42582157f21e9c01d631a72378ef2b0f5df35bf47", "size": 1113, "status": "c"}, ".gitignore|1788505890.0|145": {"hash": "2e08a2109129a673065d4e6c278c1799f3eda4e5b4fb4a46a6313866ea96ddbc", "size": 145, "status": "c"}, "README.md|1788509463.0|5489": {"hash": "f21262ef5644f23873bfee8a48c488fc3424a713ecd678fef2e88bb239a2afb2", "size": 5489, "status": "c"}, "conf/README_upstream.rst|1745926779.0|2192": {"hash": "8f20109be8d078549478fc9d78391bf1c5688b283ba9c71d6de9c3393cfb3d8e", "size": 2192, "status": "c"}, "conf/data/smoke.fasta|1785314913.0|478": {"hash": "3f51b4e6e0539b9c2cf12187079347eeab7b6b576d8e540748bc38b788707149", "size": 478, "status": "c"}, "conf/environment.yml|1788505779.0|319": {"hash": "7905dabc117ac4470028ac081032ba1d80a1220d5d60cb0d0184867168013ca6", "size": 319, "status": "c"}, "conf/config.json|1788509352.0|401": {"hash": "f7f882853f9894dc50b8ff6d28b271d1e33476039ba4aa1783268ed65465e556", "size": 401, "status": "c"}, "conf/environment_upstream.yml|1745926779.0|377": {"hash": "7f96c08d7f0847c56eb304c995d8039352ce2dc551821dc217b6fc090cb37b9f", "size": 377, "status": "c"}, "conf/legacy/P2PXML_dataset/.DS_Store|1718042675.0|10244": {"hash": "6ef986c0eb217beff0ddde6a2d0e5d8e6e7d2b551fdb0bbadf3057a90e2d97da", "size": 10244, "status": "c"}, "conf/data/test_sequences.fasta|1745926779.0|952751": {"hash": "ce370ce7e28bb980c54d95b0e047353161b14d372ec56ad66c66ad20d8e0b6db", "size": 952751, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML-Seq/README.md|1718042430.0|7641": {"hash": "2ffeab6133e1b7ae185376e46a0325f4a50b9663a3429faf2943655f20edc7fa", "size": 7641, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML_Structure/.DS_Store|1718042683.0|14340": {"hash": "4bcefc3ae092c4bc279d20dddcd25275ded26e64b93c1ac23502a6b924c54f2a", "size": 14340, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML_Structure/README.md|1718042468.0|5144": {"hash": "8867f3ce2f69d9ea1c937db9dc20bbb6a943a57e1891fe6d2b0488d41c8b92d1", "size": 5144, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML_Structure/P2PXML_structure.csv|1715691738.0|307194": {"hash": "cb0d5c4da7506cebaaecdd2893c22ceed4b073d37c5aaabddab6ca97530d9ee4", "size": 307194, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antibodies_0.5γ.pt|1785382868.0|806844": {"hash": "93ef94df9521ab9fbf988d5c47007e46297325a02c78e24c99fc990d4d610a9d", "size": 806844, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_AC10_29.pt.raysync.downloading|1788504346.0|0": {"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "size": 0, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_AC10_29.pt|1785383395.0|65536": {"hash": "c389b1f225c783bb7e3dc99fc0ca2612709fff29c348228a5a2536b92a509296", "size": 65536, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antibodies_10-1074.pt|1785382861.0|1587531": {"hash": "d4f91d4681b79ec48f23f7888e6cb15a59db7ff68da879355ae3b0dee7295b50", "size": 1587531, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_0815_V3_C3.pt|1785382984.0|2013784": {"hash": "970fe055e85973b871814101bf5e136f0ebed848816ad9c7a3a7e202da4203b0", "size": 2013784, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_0013095_2_11.pt|1785383207.0|2016242": {"hash": "ac2432509e5dec3f719fcbe459845a99cd148f97ff2be0007cc986f6e9aa7a60", "size": 2016242, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_6535_3.pt|1785383057.0|2020324": {"hash": "8686544b6804f247e5333438b947f627a2c44e20b0915f4c7353ac4e8ced528f", "size": 2020324, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_JRFL.pt|1785383245.0|2009226": {"hash": "b765659c9a03c6fe870a233ad754a08633bb0366011271c605d0c209fef4c188", "size": 2009226, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML-Seq/P2PXML_seq_dataset.csv|1715518479.0|48192766": {"hash": "30f560849e7ce3de50c00f3e2e8db9b62062415099286ba7a18119062644be36", "size": 48192766, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_PVO_4.pt|1785383020.0|0": {"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "size": 0, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_PVO_4.pt.raysync.downloading|1788504346.0|0": {"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "size": 0, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_QH0692_42.pt|1785382905.0|2013515": {"hash": "f270e2661f8e79b1e9355cbc253271adbbc2ad7f8801412ec04250fd7e9307d1", "size": 2013515, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_REJO4541_67.pt|1785383356.0|1638400": {"hash": "d2485678396d8d4312c4afbf415548fd238cdedd952778ea4623f8c81c9aa06b", "size": 1638400, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_REJO4541_67.pt.raysync.downloading|1788504346.0|0": {"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "size": 0, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_RHPA4259_7.pt|1785382948.0|2016280": {"hash": "67ef316708b16aa7638b78839110234f3d2806b19a831fff61bd61a3b5e2a578", "size": 2016280, "status": "c"}, "conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_WITO4160_33.pt|1785383170.0|2018213": {"hash": "3f9e20fbe89397f45a86378d92a48edd995e342a2abe99ff94c8234c39f6ec4d", "size": 2018213, "status": "c"}, "conf/legacy/__MACOSX/P2PXML_dataset/._.DS_Store|1718042675.0|120": {"hash": "2f380f4a3d05a8d90c2106f50da75064e9ce57a598599dc5404f8f69a0223aa9", "size": 120, "status": "c"}, "conf/legacy/__MACOSX/P2PXML_dataset/._P2PXML_Structure|1718042684.0|220": {"hash": "a29f0c4c35897cd46dffd9fa873543b1703137fd5156e5857a7c991581e9f073", "size": 220, "status": "c"}, "conf/legacy/__MACOSX/P2PXML_dataset/P2PXML-Seq/._P2PXML_seq_dataset.csv|1715518479.0|332": {"hash": "0198d50e52c224afb5e1d07e9ab6a29c0373102434e3457e717f57919eb6e904", "size": 332, "status": "c"}, "conf/legacy/__MACOSX/P2PXML_dataset/P2PXML-Seq/._README.md|1718042430.0|476": {"hash": "aa78b13f28a4a239a8ca75ead6026d6c54144cf571577e3f7b3fb76dd7e33978", "size": 476, "status": "c"}, "conf/legacy/__MACOSX/P2PXML_dataset/P2PXML_Structure/._.DS_Store|1718042683.0|120": {"hash": "2f380f4a3d05a8d90c2106f50da75064e9ce57a598599dc5404f8f69a0223aa9", "size": 120, "status": "c"}, "conf/legacy/__MACOSX/P2PXML_dataset/P2PXML_Structure/._P2PXML_structure.csv|1715691738.0|332": {"hash": "77635c3e6c6e066eb3feca5e03cd62b1b56f263f017ef1dc41ac27c530ac4d7a", "size": 332, "status": "c"}, "conf/legacy/__MACOSX/P2PXML_dataset/P2PXML_Structure/._README.md|1718042468.0|476": {"hash": "b503f826be7493b5b062a03b046218e41ce1586725f8b9df05f3984e86086af6", "size": 476, "status": "c"}, "conf/legacy/incomplete_transfers/ESM1v-SVR.pkl.raysync.downloading|1788504333.0|0": {"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "size": 0, "status": "c"}, "conf/legacy/incomplete_transfers/checkpoint_markers/ESM1v-RLATtr.pt.raysync.downloading|1788504333.0|0": {"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "size": 0, "status": "c"}, "conf/legacy/incomplete_transfers/checkpoint_markers/esm1v_t33_650M_UR90S_1.pt.raysync.downloading|1788504332.0|0": {"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "size": 0, "status": "c"}, "conf/legacy/python_cache/ephod/__init__.cpython-310.pyc|1788505655.0|281": {"hash": "37fbf003861a9d145a91702d485fce4516db22084bcab88e146dc93bb32d31da", "size": 281, "status": "c"}, "conf/legacy/python_cache/ephod/__init__.cpython-311.pyc|1785314929.0|327": {"hash": "697fbf112d24aebb04eed7058a22839e88bbc119a1c2acb94a1728189e5ee3a1", "size": 327, "status": "c"}, "conf/legacy/python_cache/model/__init__.cpython-310.pyc|1788505655.0|173": {"hash": "5c0858ec07fac50f5fdfdd3504dba8f4c0d634e9f44435841114a431e7270500", "size": 173, "status": "c"}, "conf/legacy/python_cache/training/__init__.cpython-310.pyc|1788505655.0|149": {"hash": "7e97bde86f4bda71b6fa9599e3fc45a43a99b99961f2a68e362159829d89708b", "size": 149, "status": "c"}, "conf/legacy/python_cache/training/__init__.cpython-311.pyc|1785314929.0|179": {"hash": "efa2f7b9665a0fbca86e1898e394363e6e222c4d90391f169132329082771e3c", "size": 179, "status": "c"}, "conf/legacy/python_cache/training/nn_models.cpython-311.pyc|1785314929.0|30534": {"hash": "a19872f5876ba92a0c995f785cfb70ce2fb11e02972c4bd657ed5ad5a68f28bf", "size": 30534, "status": "c"}, "conf/legacy/torch_cache/hub/checkpoints/ESM1v-RLATtr.pt.raysync.downloading|1788504339.0|0": {"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "size": 0, "status": "c"}, "conf/legacy/torch_cache/hub/checkpoints/esm1v_t33_650M_UR90S_1.pt|1624653201.0|12058624": {"hash": "f3d7c4c868045cbea65b47debb9764d8f55dcaea63854a169c7442a5d084df2b", "size": 12058624, "status": "c"}, "conf/legacy/torch_cache/hub/checkpoints/ESM1v-RLATtr.pt|1785314088.0|19726336": {"hash": "5a8d2ce39e4d0e8c584172301cc1fd7942f919994266cb4875feeb3e165f6b89", "size": 19726336, "status": "c"}, "conf/legacy/incomplete_transfers/ESM1v-SVR.partial.pkl|1745926779.0|45678592": {"hash": "6a6022211516ca9375e3266fbee9f6639e16bb4c0f8d3977f1f8fcb219bfefdd", "size": 45678592, "status": "c"}, "conf/legacy/torch_cache/hub/checkpoints/esm1v_t33_650M_UR90S_1.pt.raysync.downloading|1788504339.0|0": {"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "size": 0, "status": "c"}, "configuration.json|1788505517.0|424": {"hash": "86c89c44bfbc9cf0f437c66648625c1af3cf7ccfbb34a57e0d12328572cb7a42", "size": 424, "status": "c"}, "model/__init__.py|1788505512.0|34": {"hash": "e4ceae57dace284d2b2513bdb2494eef6f3b0a381d7cc81ec4456df999526623", "size": 34, "status": "c"}, "model/__pycache__/__init__.cpython-311.pyc|1788508905.0|202": {"hash": "bc03c11bb12db0bab0d8601d1c11868beeb41fc42188a8691a456d5cb5f5740e", "size": 202, "status": "c"}, "model/ephod/__init__.py|1745926779.0|124": {"hash": "40f97e8cfcc7db2837669605c964c0f0eb03621da2dfb26f5f7afae9e1b6acbf", "size": 124, "status": "c"}, "model/ephod/__pycache__/__init__.cpython-311.pyc|1788508905.0|324": {"hash": "5003481c57668c0717ebf6811676e9101154b833c7165cd2f78c771eceac93cd", "size": 324, "status": "c"}, "model/ephod/training/__init__.py|1745926779.0|0": {"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "size": 0, "status": "c"}, "model/ephod/training/__pycache__/__init__.cpython-311.pyc|1788508905.0|176": {"hash": "e4eaa4a80e0221902c83f563bf6be756dac142281e775b30792986818d752f64", "size": 176, "status": "c"}, "model/ephod/training/__pycache__/nn_models.cpython-311.pyc|1788508905.0|30531": {"hash": "646013618ac14c439dc07951ee7f27d452a2553b6db6a6ef40f738fdff6f1846", "size": 30531, "status": "c"}, "model/ephod/training/nn_models.py|1745926779.0|22876": {"hash": "7301be27ea56a7bd46068223abb8569c9e20bb3b3a6b52acd01dee3ff757f427", "size": 22876, "status": "c"}, "model/ephod/training/trainutils.py|1745926779.0|6515": {"hash": "ea7f1ef9397f5bde90b374ddb2b0e30ac0fbb3c6417125db30a39bb4623d0cc5", "size": 6515, "status": "c"}, "requirements.txt|1788505519.0|915": {"hash": "40ef350e0c0ca26d67591e2841b4a181e319698dcb0fac104009995dcc01d568", "size": 915, "status": "c"}, "scripts/inference.py|1788509363.0|11853": {"hash": "2f55e15e9191fa97646a739c1ec1e17951bed77f5220bf0298594c828699e8cf", "size": 11853, "status": "c"}, "scripts/train_ml_models.py|1788505801.0|6687": {"hash": "561602f5daf2a371fe629a2a4191aaa5514f1a022a40a4e4cd1a1f9c3fd6c357", "size": 6687, "status": "c"}, "scripts/train_nnmodels.py|1788505507.0|17738": {"hash": "2bdfcce38c4f64bac61ba3c5d80dbf7a2a131956e91db04c398171ee00af51ad", "size": 17738, "status": "c"}, "weight/ESM1v-SVR.pkl|1788507694.0|62751459": {"hash": "629723a22b3691d8b177abb8d8c8c36d8e36b4a16d2bf7eec616ea2afef16bdb", "size": 62751459, "status": "c"}, "weight/ESM1v-RLATtr.pt|1788507542.0|196888312": {"hash": "dd46a328e0d3ccba1fb0515dbffbe014247a6752a21b30d6432f604bbb658b9c", "size": 196888312, "status": "c"}, "weight/smoke_training/rla_smoke_model.pt|1785380632.0|146564": {"hash": "c0654eca82f57b8ca06d99376724543b1ba83ce362292049b77f2ccd4b338778", "size": 146564, "status": "c"}, "weight/smoke_training/svr_smoke_model.pkl|1785380693.0|186051": {"hash": "a11e9a7e2156c4cbdbc157fa1d469ef495d7a483333f1dc5b5d6881fd2aa14cc", "size": 186051, "status": "c"}, "weight/esm1v_t33_650M_UR90S_1.pt|1788507559.0|7828635339": {"hash": "9519ee60f1cddad3c101afb1f42612499e188534969c3f682e94850870f70433", "size": 7828635339, "status": "c"}}}
|
LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
The MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2023, Japheth Gado, National Renewable Energy Laboratory.
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in
|
| 13 |
+
all copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
| 21 |
+
THE SOFTWARE.
|
README.md
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
frameworks:
|
| 3 |
+
- PyTorch
|
| 4 |
+
language:
|
| 5 |
+
- en
|
| 6 |
+
license: mit
|
| 7 |
+
tags:
|
| 8 |
+
- OneScience
|
| 9 |
+
- bioscience
|
| 10 |
+
- enzyme-optimum-pH-prediction
|
| 11 |
+
- protein-language-model
|
| 12 |
+
- EpHod
|
| 13 |
+
tasks:
|
| 14 |
+
- regression
|
| 15 |
+
---
|
| 16 |
+
|
| 17 |
+
<p align="center">
|
| 18 |
+
<strong>
|
| 19 |
+
<span style="font-size: 30px;">EpHod</span>
|
| 20 |
+
</strong>
|
| 21 |
+
</p>
|
| 22 |
+
|
| 23 |
+
# Model Introduction
|
| 24 |
+
|
| 25 |
+
EpHod is an ensemble model for predicting the catalytic optimum pH (`pHopt`) of enzymes.
|
| 26 |
+
|
| 27 |
+
The model first uses ESM-1v to encode amino acid sequences into protein representations and then combines predictions from a Residual Lightweight Attention network (RLATtr) and a Support Vector Regression model (SVR).
|
| 28 |
+
|
| 29 |
+
Paper: [Machine learning prediction of enzyme optimum pH](https://doi.org/10.1038/s42256-025-01026-6)
|
| 30 |
+
|
| 31 |
+
# Model Description
|
| 32 |
+
|
| 33 |
+
The EpHod inference pipeline contains three main prediction components:
|
| 34 |
+
|
| 35 |
+
- **ESM-1v:** Encodes enzyme sequences into 1280-dimensional residue-level protein representations;
|
| 36 |
+
- **RLATtr:** Uses a residual lightweight attention network to predict `pHopt` and can optionally output residue-level attention weights and a 2560-dimensional EpHod protein representation;
|
| 37 |
+
- **SVR:** Performs support vector regression using pooled and standardized ESM-1v representations;
|
| 38 |
+
- **Ensemble:** Uses the average of the RLATtr and SVR predictions as the final `pHopt` prediction.
|
| 39 |
+
|
| 40 |
+
The official RLATtr model was first pretrained on approximately 1.9 million proteins labeled with optimum environmental pH (`pHenv`) and was then fine-tuned on 9,855 enzymes labeled with catalytic optimum pH (`pHopt`).
|
| 41 |
+
|
| 42 |
+
Input sequences longer than 1022 residues are truncated.
|
| 43 |
+
|
| 44 |
+
To avoid pooling-related bias, the current inference entry point uses a fixed batch size of 1.
|
| 45 |
+
|
| 46 |
+
# Use Cases
|
| 47 |
+
|
| 48 |
+
| Use Case | Description |
|
| 49 |
+
| --- | --- |
|
| 50 |
+
| Enzyme optimum pH prediction | Predict catalytic optimum pH from an enzyme amino acid sequence. |
|
| 51 |
+
| Enzyme candidate screening | Compare multiple candidate enzyme sequences based on predicted optimum pH. |
|
| 52 |
+
| Attention analysis | Optionally save residue-level RLATtr attention weights. |
|
| 53 |
+
| Protein representation extraction | Optionally save the final 2560-dimensional RLATtr protein representation. |
|
| 54 |
+
|
| 55 |
+
# Usage
|
| 56 |
+
|
| 57 |
+
## 1. OneCode
|
| 58 |
+
|
| 59 |
+
You can use the OneCode online environment for an intelligent one-click AI4S programming experience:
|
| 60 |
+
|
| 61 |
+
[Try OneCode for AI4S Programming](https://web-2069360198568017922-iaaj.ksai.scnet.cn:58043/home)
|
| 62 |
+
|
| 63 |
+
## 2. Manual Installation
|
| 64 |
+
|
| 65 |
+
### Hardware Requirements
|
| 66 |
+
|
| 67 |
+
- Supports CPU and accelerator devices supported by PyTorch;
|
| 68 |
+
- GPU or SCNet DCU is recommended for ESM-1v inference;
|
| 69 |
+
- CPU execution is supported but is significantly slower;
|
| 70 |
+
- ESM-1v contains approximately 650 million parameters;
|
| 71 |
+
- Device memory usage depends on sequence length. If device memory is insufficient, reduce the input sequence length or process sequences individually.
|
| 72 |
+
|
| 73 |
+
### Download the Model Package
|
| 74 |
+
|
| 75 |
+
Install the Hugging Face command-line tool and download the model repository:
|
| 76 |
+
|
| 77 |
+
```bash
|
| 78 |
+
|
| 79 |
+
python -m pip install -U huggingface_hub
|
| 80 |
+
|
| 81 |
+
hf download OneScience-Group/EpHod --local-dir ./EpHod
|
| 82 |
+
cd EpHod
|
| 83 |
+
```
|
| 84 |
+
|
| 85 |
+
### Install the Runtime Environment
|
| 86 |
+
|
| 87 |
+
**DCU Environment**
|
| 88 |
+
|
| 89 |
+
```bash
|
| 90 |
+
# Activate DTK and Conda first
|
| 91 |
+
conda create -n onescience311 python=3.11 -y
|
| 92 |
+
conda activate onescience311
|
| 93 |
+
|
| 94 |
+
python -m pip install "onescience[bio-dcu]" \
|
| 95 |
+
-i http://mirrors.onescience.ai:3141/pypi/simple/ \
|
| 96 |
+
--trusted-host mirrors.onescience.ai
|
| 97 |
+
```
|
| 98 |
+
**GPU Environment**
|
| 99 |
+
|
| 100 |
+
```bash
|
| 101 |
+
# Activate Conda first
|
| 102 |
+
conda create -n onescience311 python=3.11 -y
|
| 103 |
+
conda activate onescience311
|
| 104 |
+
|
| 105 |
+
python -m pip install "onescience[bio-gpu]" \
|
| 106 |
+
-i http://mirrors.onescience.ai:3141/pypi/simple/ \
|
| 107 |
+
--trusted-host mirrors.onescience.ai
|
| 108 |
+
```
|
| 109 |
+
|
| 110 |
+
Install the additional dependencies required by EpHod:
|
| 111 |
+
|
| 112 |
+
```bash
|
| 113 |
+
python -m pip install --no-deps -r requirements.txt
|
| 114 |
+
```
|
| 115 |
+
|
| 116 |
+
### Weight Preparation
|
| 117 |
+
|
| 118 |
+
Inference requires all three of the following assets:
|
| 119 |
+
|
| 120 |
+
| Asset | Relative Path | Purpose |
|
| 121 |
+
| --- | --- | --- |
|
| 122 |
+
| ESM-1v 650M weights | `weight/esm1v_t33_650M_UR90S_1.pt` | Generate residue-level protein representations |
|
| 123 |
+
| RLATtr weights | `weight/ESM1v-RLATtr.pt` | Neural-network prediction branch |
|
| 124 |
+
| SVR model and normalization statistics | `weight/ESM1v-SVR.pkl` | Support Vector Regression prediction branch |
|
| 125 |
+
|
| 126 |
+
Official sources:
|
| 127 |
+
|
| 128 |
+
- [ESM-1v main checkpoint](https://dl.fbaipublicfiles.com/fair-esm/models/esm1v_t33_650M_UR90S_1.pt)
|
| 129 |
+
- [EpHod RLATtr weights and training data](https://doi.org/10.5281/zenodo.14252615)
|
| 130 |
+
- `ESM1v-SVR.pkl` is distributed with the official EpHod repository.
|
| 131 |
+
|
| 132 |
+
### Quick Inference
|
| 133 |
+
|
| 134 |
+
The following command uses a validated smoke-test sequence:
|
| 135 |
+
|
| 136 |
+
```bash
|
| 137 |
+
python scripts/inference.py \
|
| 138 |
+
--fasta_path conf/data/smoke.fasta \
|
| 139 |
+
--output_path output/smoke/prediction.csv \
|
| 140 |
+
--verbose 1 \
|
| 141 |
+
--save_attention_weights 0 \
|
| 142 |
+
--save_embeddings 0
|
| 143 |
+
```
|
| 144 |
+
|
| 145 |
+
A complete example using the provided test sequences:
|
| 146 |
+
|
| 147 |
+
```bash
|
| 148 |
+
python scripts/inference.py \
|
| 149 |
+
--fasta_path conf/data/test_sequences.fasta \
|
| 150 |
+
--output_path output/inference/prediction.csv \
|
| 151 |
+
--verbose 1 \
|
| 152 |
+
--save_attention_weights 0 \
|
| 153 |
+
--save_embeddings 0
|
| 154 |
+
```
|
| 155 |
+
|
| 156 |
+
The output CSV contains three prediction columns:
|
| 157 |
+
|
| 158 |
+
```text
|
| 159 |
+
RLATtr,SVR,Ensemble
|
| 160 |
+
```
|
| 161 |
+
|
| 162 |
+
Their meanings are:
|
| 163 |
+
|
| 164 |
+
- `RLATtr`: optimum-pH prediction from the neural-network branch;
|
| 165 |
+
- `SVR`: optimum-pH prediction from the support vector regression branch;
|
| 166 |
+
- `Ensemble`: arithmetic mean of the RLATtr and SVR predictions and the recommended final EpHod prediction.
|
| 167 |
+
|
| 168 |
+
The `--output_path` argument directly specifies the complete output CSV path and automatically creates its parent directory when required.
|
| 169 |
+
|
| 170 |
+
The original `--save_dir` and `--csv_name` options remain available.
|
| 171 |
+
|
| 172 |
+
If `--output_path` is not specified, the output path is generated from `--save_dir` and `--csv_name`.
|
| 173 |
+
|
| 174 |
+
### Save Attention Weights and Protein Representations
|
| 175 |
+
|
| 176 |
+
Set the corresponding options to `1`:
|
| 177 |
+
|
| 178 |
+
```bash
|
| 179 |
+
python scripts/inference.py \
|
| 180 |
+
--fasta_path conf/data/smoke.fasta \
|
| 181 |
+
--output_path output/features/prediction.csv \
|
| 182 |
+
--save_attention_weights 1 \
|
| 183 |
+
--save_embeddings 1
|
| 184 |
+
```
|
| 185 |
+
|
| 186 |
+
The output includes:
|
| 187 |
+
|
| 188 |
+
```text
|
| 189 |
+
output/features/
|
| 190 |
+
├── attention_weights/
|
| 191 |
+
├── embeddings.csv
|
| 192 |
+
└── prediction.csv
|
| 193 |
+
```
|
| 194 |
+
|
| 195 |
+
`attention_weights/` stores residue-level RLATtr attention information.
|
| 196 |
+
|
| 197 |
+
`embeddings.csv` stores the extracted EpHod protein representations.
|
| 198 |
+
|
| 199 |
+
`prediction.csv` stores the RLATtr, SVR, and ensemble optimum-pH predictions.
|
| 200 |
+
|
| 201 |
+
# OneScience Official Resources
|
| 202 |
+
|
| 203 |
+
| Platform | OneScience Main Repository | Skills Repository |
|
| 204 |
+
| --- | --- | --- |
|
| 205 |
+
| Gitee | https://gitee.com/onescience-ai/onescience | https://gitee.com/onescience-ai/oneskills |
|
| 206 |
+
| GitHub | https://github.com/onescience-ai/OneScience | https://github.com/onescience-ai/oneskills |
|
| 207 |
+
|
| 208 |
+
# Citation and License
|
| 209 |
+
|
| 210 |
+
- EpHod paper: [Machine learning prediction of enzyme optimum pH](https://doi.org/10.1038/s42256-025-01026-6)
|
| 211 |
+
- Official implementation: https://github.com/jafetgado/EpHod
|
| 212 |
+
- EpHod model and data: [Machine learning prediction of enzyme optimal pH](https://doi.org/10.5281/zenodo.14252615)
|
| 213 |
+
- The upstream EpHod implementation is distributed under the MIT License.
|
| 214 |
+
- This model package provides SCNet/DCU runtime adaptation and directory organization based on the official implementation.
|
| 215 |
+
- The adaptation does not modify the copyright status, licenses, or terms of use of the original paper, source code, model weights, datasets, ESM-1v assets, or other third-party resources.
|
conf/README_upstream.rst
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
**EpHod**
|
| 2 |
+
===============
|
| 3 |
+
|
| 4 |
+
.. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.15015124.svg
|
| 5 |
+
:target: https://doi.org/10.5281/zenodo.15015124
|
| 6 |
+
:alt: DOI
|
| 7 |
+
|
| 8 |
+
EpHod is a deep-learning model to predict the optimum pH of enzymes (pHopt). The model is of an ensemble of a neural network (residual light attention or RLAT) and a support vector regression (SVR) model both trained on top of ESM-1v embeddings. The neural network (RLATtr) was first pretrained using 1.9 million proteins with optimal environment pH (pHenv) labels, followed by fine tuning using 9,855 enzyme with catalytic optimum pH labels (pHopt).
|
| 9 |
+
|
| 10 |
+
We recommend using a conda environment. Dependencies are in `env.yml`. The code was successfully run with PyTorch v1.7.0 and CUDA v 11.7.
|
| 11 |
+
Weights of EpHod model and training datasets are available at `Zenodo <https://doi.org/10.5281/zenodo.14252615>`__.
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
Usage
|
| 16 |
+
-------------
|
| 17 |
+
|
| 18 |
+
1. Clone repository and install conda environment. Installation with the
|
| 19 |
+
required environment takes roughly four minutes.
|
| 20 |
+
|
| 21 |
+
.. code:: shell-session
|
| 22 |
+
|
| 23 |
+
git clone https://github.com/jafetgado/EpHod.git
|
| 24 |
+
cd EpHod
|
| 25 |
+
conda env create -f ./env.yml -p ./env
|
| 26 |
+
conda activate ./env
|
| 27 |
+
..
|
| 28 |
+
|
| 29 |
+
2. Predict pHopt with EpHod. Predicted pHopt values, and attention weights from the RLATtr model, as well as the embeddings from the final RLATtr layer (2560-dim) are saved in ``./example/``. Pass 0 to ``--save_attention_weights``
|
| 30 |
+
and ``--save_embeddings`` to avoid writing the weights and embeddings output.
|
| 31 |
+
Besides downloading model weights, which may take several minutues, with a batch size of 1, prediction takes ~7 seconds/sequence on a CPU and ~0.1 seconds/sequence on a GPU.
|
| 32 |
+
|
| 33 |
+
.. code:: shell-session
|
| 34 |
+
|
| 35 |
+
python ./ephod/run.py \
|
| 36 |
+
--fasta_path "./example/test_sequences.fasta" \
|
| 37 |
+
--save_dir ./example \
|
| 38 |
+
--csv_name prediction.csv \
|
| 39 |
+
--verbose 1 \
|
| 40 |
+
--save_attention_weights 0 \
|
| 41 |
+
--save_embeddings 0
|
| 42 |
+
..
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
Citation
|
| 48 |
+
----------
|
| 49 |
+
If you find EpHod useful, please cite the following:
|
| 50 |
+
|
| 51 |
+
Gado J.E., Knotts M., Shaw A.Y., et al, 2025. "Machine learning prediction of enzyme optimum pH". `Nature Machine Intelligence <https://doi.org/10.1038/s42256-025-01026-6>`__.
|
| 52 |
+
|
conf/config.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"input_fasta": "conf/data/test_sequences.fasta",
|
| 3 |
+
"smoke_fasta": "conf/data/smoke.fasta",
|
| 4 |
+
"output_dir": "scripts/output",
|
| 5 |
+
"output_path": "scripts/output/prediction.csv",
|
| 6 |
+
"esm1v_checkpoint": "weight/esm1v_t33_650M_UR90S_1.pt",
|
| 7 |
+
"rlattr_checkpoint": "weight/ESM1v-RLATtr.pt",
|
| 8 |
+
"svr_checkpoint": "weight/ESM1v-SVR.pkl",
|
| 9 |
+
"max_sequence_length": 1022,
|
| 10 |
+
"batch_size": 1,
|
| 11 |
+
"device": "auto"
|
| 12 |
+
}
|
conf/data/smoke.fasta
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
>Q2YPV0 | Brucella abortus | 4.2.1.11 | 8.5 | 0.366
|
| 2 |
+
MTAIIDIVGREILDSRGNPTVEVDVVLEDGSFGRAAVPSGASTGAHEAVELRDGGSRYLGKGVEKAVEVVNGKIFDAIAGMDAESQLLIDQTLIDLDGSANKGNLGANAILGVSLAVAKAAAQASGLPLYRYVGGTNAHVLPVPMMNIINGGAHADNPIDFQEFMILPVGATSIREAVRYGSEVFHTLKKRLKDAGHNTNVGDEGGFAPNLKNAQAALDFIMESIEKAGFKPGEDIALGLDCAATEFFKDGNYVYEGERKTRDPKAQAKYLAKLASDYPIVTIEDGMAEDDWEGWKYLTDLIGNKCQLVGDDLFVTNSARLRDGIRLGVANSILVKVNQIGSLSETLDAVETAHKAGYTAVMSHRSGETEDSTIADLAVATNCGQIKTGSLARSDRTAKYNQLIRIEEELGKQARYAGRSALKLL
|
conf/data/test_sequences.fasta
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
conf/environment.yml
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: onescience311
|
| 2 |
+
channels:
|
| 3 |
+
- defaults
|
| 4 |
+
dependencies:
|
| 5 |
+
- python=3.11
|
| 6 |
+
- pip
|
| 7 |
+
|
| 8 |
+
# Install the OneScience DTK/DCU stack first, then install requirements.txt.
|
| 9 |
+
# The upstream Python 3.8 / PyTorch 1.7 environment is preserved separately as
|
| 10 |
+
# conf/environment_upstream.yml and must not replace the OneScience environment.
|
conf/environment_upstream.yml
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: env
|
| 2 |
+
channels:
|
| 3 |
+
- conda-forge
|
| 4 |
+
- bioconda
|
| 5 |
+
- pytorch
|
| 6 |
+
- defaults
|
| 7 |
+
dependencies:
|
| 8 |
+
- python=3.8.8
|
| 9 |
+
- pytorch=1.7.0
|
| 10 |
+
- wget
|
| 11 |
+
- pip
|
| 12 |
+
- pip:
|
| 13 |
+
- fair-esm==1.0.2
|
| 14 |
+
- transformers
|
| 15 |
+
- sentencepiece
|
| 16 |
+
- h5py
|
| 17 |
+
- scikit-learn==0.23.2
|
| 18 |
+
- numpy==1.19.1
|
| 19 |
+
- biopython==1.79
|
| 20 |
+
- pandas==1.1.3
|
| 21 |
+
- xlrd
|
| 22 |
+
- openpyxl
|
| 23 |
+
- matplotlib
|
| 24 |
+
- ipython
|
| 25 |
+
- tqdm
|
conf/legacy/P2PXML_dataset/.DS_Store
ADDED
|
Binary file (10.2 kB). View file
|
|
|
conf/legacy/P2PXML_dataset/P2PXML-Seq/README.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# P2PXML-Seq Dataset
|
| 2 |
+
|
| 3 |
+
To support the development of antibody-antigen binding affinity prediction frameworks, we curated the largest and most generalized datasets for antibody-antigen binding affinity prediction in the literature. To this end, P2PXML-Seq is the curated protein sequence dataset.
|
| 4 |
+
|
| 5 |
+
## Abstract from the accompanied paper [https://www.biorxiv.org/content/early/2024/06/10/2024.06.09.598103](Paper):
|
| 6 |
+
|
| 7 |
+
In the context of drug development, the efficacy of drugs designed using biologics depends on the strength of the interactions between the biologics and the target molecule. In practise, these strengths of the interactions are measured using binding affinity and thus, understanding the binding affinity between an engineered antibody and its target antigen is a critical aspect of antibody engineering as it reflects the overall effectiveness of the antibody in inhibiting the activity of the target antigen. In theory, potential candidate antibodies have a higher binding affinity towards the target antigen. Currently, techniques such as Molecular docking and Molecular dynamics are utilized in quantifying the binding affinity. However, owing to the computational complexity of the aforementioned techniques, running simulations for large antibodies/antigens remains a daunting task. Despite the commendable improvements in deep learning-based binding affinity prediction, such approaches are highly dependent on the quality of the antibody-antigen structures and they tend to overlook the importance of capturing the evolutionary details of proteins upon mutation. Further, most of the existing datasets for the task only include antibody-antigen pairs related to one antigen variant and thus, not suitable for developing comprehensive data-driven approaches. To circumvent the said complexities, we first curate the largest and most generalized datasets for antibody-antigen binding affinity prediction, consisting both protein sequences and structures, in the literature and then propose a deep geometric neural network comprising a structure-based model and a sequence-based model that considers both atomistic and evolutionary details when predicting the binding affinity. The proposed framework exhibited a $10\%$ improvement in mean absolute error compared to the state-of-the-art models while showing a very strong correlation between the predictions and target values. We release the datasets and code publicly [https://drug-discovery-entc.github.io/p2pxml/](web-page) to support the development of antibody-antigen binding affinity prediction frameworks for the benefit of science and society.
|
| 8 |
+
|
| 9 |
+
## Dataset Overview
|
| 10 |
+
|
| 11 |
+
Data include binding affinity values between a diverse sets of antibodies and antigens. To our knowledge, this dataset is the most-generalized publicly-available dataset that contains antibody sequences, antigen sequences and quantitative measurements and provides an opportunity to serve as a benchmark to evaluate generalized and data-driven antibody-antigen binding affinity prediction frameworks.
|
| 12 |
+
|
| 13 |
+
P2PXML-Seq dataset has a csv file with the following columns entries:
|
| 14 |
+
|
| 15 |
+
| **Variable Name** | **Description** |
|
| 16 |
+
| ------------------------ | ------------- |
|
| 17 |
+
| Ab_Sequence | Antibody amino-acid sequence (PS: When the heavy and light chains were given, in the primary data sources, instead of the complete antibody sequence, we concatenate the light and heavy sequences, in that order, to create the complete sequence) |
|
| 18 |
+
| Ag_Sequence | Antigen amino-acid sequence (PS: If the antigen sequence is marked as "0", it refers to the SARS-CoV-2 antigen sequence)* |
|
| 19 |
+
| Pred_Affinity | The retrieved binding affinity between the corresponding antibody and antigen (PS: In this column, the experimental values with different measurement parameters are shown) |
|
| 20 |
+
| Unit_Type | The type of measurement parameter in which the "Pred_Affinity" is expressed: 0 - Kd, 1 - IC50, 2 - ddG|
|
| 21 |
+
| Estimated_Pred_Affinity | The estimated binding affinity between the corresponding antibody and antigen using several assumptions (PS: Refer the accompanied paper for more on this) |
|
| 22 |
+
| Processed | Whether the amino-acid sequences or affinity values from primary data sources have modified or estimated in this dataset: 0 - not modified, 1 - modified |
|
| 23 |
+
| If_not_Ab_heavy | When the complete sequence is not given in the primary data source, the given heavy chain of the amino-acid sequence |
|
| 24 |
+
| If_not_Ab_light | When the complete sequence is not given in the primary data source, the given light chain of the amino-acid sequence |
|
| 25 |
+
| Additional_Info_1 | Additional information such as the corresponding PDB ID |
|
| 26 |
+
| Additional_Info_2 | Additional information such as the corresponding PDB ID |
|
| 27 |
+
| Ag_type | The common name of the antigen variant which the antigen sequence is part of |
|
| 28 |
+
|
| 29 |
+
* Utilized amino-acid sequence for SARS-CoV-2: 'MFVFLVLLPLVSSQCVNLTTRTQLPPAYTNSFTRGVYYPDKVFRSSVLHSTQDLFLPFFSNVTWFHAIHVSGTNGTKRFDNPVLPFNDGVYFASTEKSNIIRGWIFGTTLDSKTQSLLIVNNATNVVIKVCEFQFCNDPFLGVYYHKNNKSWMESEFRVYSSANNCTFEYVSQPFLMDLEGKQGNFKNLREFVFKNIDGYFKIYSKHTPINLVRDLPQGFSALEPLVDLPIGINITRFQTLLALHRSYLTPGDSSSGWTAGAAAYYVGYLQPRTFLLKYNENGTITDAVDCALDPLSETKCTLKSFTVEKGIYQTSNFRVQPTESIVRFPNITNLCPFGEVFNATRFASVYAWNRKRISNCVADYSVLYNSASFSTFKCYGVSPTKLNDLCFTNVYADSFVIRGDEVRQIAPGQTGKIADYNYKLPDDFTGCVIAWNSNNLDSKVGGNYNYLYRLFRKSNLKPFERDISTEIYQAGSTPCNGVEGFNCYFPLQSYGFQPTNGVGYQPYRVVVLSFELLHAPATVCGPKKSTNLVKNKCVNFNFNGLTGTGVLTESNKKFLPFQQFGRDIADTTDAVRDPQTLEILDITPCSFGGVSVITPGTNTSNQVAVLYQDVNCTEVPVAIHADQLTPTWRVYSTGSNVFQTRAGCLIGAEHVNNSYECDIPIGAGICASYQTQTNSPRRARSVASQSIIAYTMSLGAENSVAYSNNSIAIPTNFTISVTTEILPVSMTKTSVDCTMYICGDSTECSNLLLQYGSFCTQLNRALTGIAVEQDKNTQEVFAQVKQIYKTPPIKDFGGFNFSQILPDPSKPSKRSFIEDLLFNKVTLADAGFIKQYGDCLGDIAARDLICAQKFNGLTVLPPLLTDEMIAQYTSALLAGTITSGWTFGAGAALQIPFAMQMAYRFNGIGVTQNVLYENQKLIANQFNSAIGKIQDSLSSTASALGKLQDVVNQNAQALNTLVKQLSSNFGAISSVLNDILSRLDKVEAEVQIDRLITGRLQSLQTYVTQQLIRAAEIRASANLAATKMSECVLGQSKRVDFCGKGYHLMSFPQSAPHGVVFLHVTYVPAQEKNFTTAPAICHDGKAHFPREGVFVSNGTHWFVTQRNFYEPQIITTDNTFVSGNCDVVIGIVNNTVYDPLQPELDSFKEELDKYFKNHTSPDVDLGDISGINASVVNIQKEIDRLNEVAKNLNESLIDLQELGKYEQYIKWPWYIWLGFIAGLIAIVMVTIMLCCMTSCCSCLKGCCSCGSCCKFDEDDSEPVLKGVKLHYT'
|
| 30 |
+
|
| 31 |
+
## Citation
|
| 32 |
+
|
| 33 |
+
@article {Bandara2024.06.09.598103,
|
| 34 |
+
author = {Bandara, Nuwan Sriyantha and Premathilaka, Dasun and Chandanayake, Sachini and Hettiarachchi, Sahan and Varenthirarajah, Vithurshan and Munasinghe, Aravinda and Madhawa, Kaushalya and Charles, Subodha},
|
| 35 |
+
title = {Deep Geometric Framework to Predict Antibody-Antigen Binding Affinity},
|
| 36 |
+
elocation-id = {2024.06.09.598103},
|
| 37 |
+
year = {2024},
|
| 38 |
+
doi = {10.1101/2024.06.09.598103},
|
| 39 |
+
publisher = {Cold Spring Harbor Laboratory},
|
| 40 |
+
URL = {https://www.biorxiv.org/content/early/2024/06/10/2024.06.09.598103},
|
| 41 |
+
eprint = {https://www.biorxiv.org/content/early/2024/06/10/2024.06.09.598103.full.pdf},
|
| 42 |
+
journal = {bioRxiv}
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
## License
|
| 46 |
+
|
| 47 |
+
Shield: [![CC BY-NC-SA 4.0][cc-by-nc-sa-shield]][cc-by-nc-sa]
|
| 48 |
+
|
| 49 |
+
This work is licensed under a
|
| 50 |
+
[Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License][cc-by-nc-sa].
|
| 51 |
+
|
| 52 |
+
[![CC BY-NC-SA 4.0][cc-by-nc-sa-image]][cc-by-nc-sa]
|
| 53 |
+
|
| 54 |
+
[cc-by-nc-sa]: http://creativecommons.org/licenses/by-nc-sa/4.0/
|
| 55 |
+
[cc-by-nc-sa-image]: https://licensebuttons.net/l/by-nc-sa/4.0/88x31.png
|
| 56 |
+
[cc-by-nc-sa-shield]: https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
## Disclaimer
|
| 60 |
+
|
| 61 |
+
DISTRIBUTION STATEMENT A. Approved for public release. Distribution is unlimited.
|
| 62 |
+
|
| 63 |
+
Any opinions, findings, conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the affiliated institutions of the author(s).
|
| 64 |
+
|
| 65 |
+
© 2024 P2PXML Team.
|
| 66 |
+
|
conf/legacy/P2PXML_dataset/P2PXML_Structure/.DS_Store
ADDED
|
Binary file (14.3 kB). View file
|
|
|
conf/legacy/P2PXML_dataset/P2PXML_Structure/README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# P2PXML-PDB Dataset
|
| 2 |
+
|
| 3 |
+
To support the development of antibody-antigen binding affinity prediction frameworks, we curated the largest and most generalized datasets for antibody-antigen binding affinity prediction in the literature. To this end, P2PXML-PDB is the curated protein structure dataset.
|
| 4 |
+
|
| 5 |
+
## Abstract from the accompanied paper [https://www.biorxiv.org/content/early/2024/06/10/2024.06.09.598103](Paper):
|
| 6 |
+
|
| 7 |
+
In the context of drug development, the efficacy of drugs designed using biologics depends on the strength of the interactions between the biologics and the target molecule. In practise, these strengths of the interactions are measured using binding affinity and thus, understanding the binding affinity between an engineered antibody and its target antigen is a critical aspect of antibody engineering as it reflects the overall effectiveness of the antibody in inhibiting the activity of the target antigen. In theory, potential candidate antibodies have a higher binding affinity towards the target antigen. Currently, techniques such as Molecular docking and Molecular dynamics are utilized in quantifying the binding affinity. However, owing to the computational complexity of the aforementioned techniques, running simulations for large antibodies/antigens remains a daunting task. Despite the commendable improvements in deep learning-based binding affinity prediction, such approaches are highly dependent on the quality of the antibody-antigen structures and they tend to overlook the importance of capturing the evolutionary details of proteins upon mutation. Further, most of the existing datasets for the task only include antibody-antigen pairs related to one antigen variant and thus, not suitable for developing comprehensive data-driven approaches. To circumvent the said complexities, we first curate the largest and most generalized datasets for antibody-antigen binding affinity prediction, consisting both protein sequences and structures, in the literature and then propose a deep geometric neural network comprising a structure-based model and a sequence-based model that considers both atomistic and evolutionary details when predicting the binding affinity. The proposed framework exhibited a $10\%$ improvement in mean absolute error compared to the state-of-the-art models while showing a very strong correlation between the predictions and target values. We release the datasets and code publicly [https://drug-discovery-entc.github.io/p2pxml/](web-page) to support the development of antibody-antigen binding affinity prediction frameworks for the benefit of science and society.
|
| 8 |
+
|
| 9 |
+
## Dataset Overview
|
| 10 |
+
|
| 11 |
+
Data include binding affinity values (in terms of IC50 value) between a diverse sets of antibodies and antigens. To our knowledge, this dataset is the largest, publicly-available dataset that contains antibody structures, antigen structures and quantitative measurements and provides an opportunity to serve as a benchmark to evaluate generalized and data-driven antibody-antigen binding affinity prediction frameworks.
|
| 12 |
+
|
| 13 |
+
P2PXML-PDB dataset has two folders, named "antibodies" and "antigens", and a csv file with the following columns entries:
|
| 14 |
+
|
| 15 |
+
| **Variable Name** | **Description** |
|
| 16 |
+
| ------------------------ | ------------- |
|
| 17 |
+
| Ab | Antibody name |
|
| 18 |
+
| Ag | Antigen name |
|
| 19 |
+
| IC50| The binding affinity between the corresponding antibody and antigen |
|
| 20 |
+
| log(IC50) | Logarithmic (to base 10) value of the corresponding IC50 |
|
| 21 |
+
|
| 22 |
+
The antibody and antigen structures (in PDB format), which are corresponding to the names in the "Ab" and "Ag" columns, are in the respective folders.
|
| 23 |
+
|
| 24 |
+
## Citation
|
| 25 |
+
|
| 26 |
+
@article {Bandara2024.06.09.598103,
|
| 27 |
+
author = {Bandara, Nuwan Sriyantha and Premathilaka, Dasun and Chandanayake, Sachini and Hettiarachchi, Sahan and Varenthirarajah, Vithurshan and Munasinghe, Aravinda and Madhawa, Kaushalya and Charles, Subodha},
|
| 28 |
+
title = {Deep Geometric Framework to Predict Antibody-Antigen Binding Affinity},
|
| 29 |
+
elocation-id = {2024.06.09.598103},
|
| 30 |
+
year = {2024},
|
| 31 |
+
doi = {10.1101/2024.06.09.598103},
|
| 32 |
+
publisher = {Cold Spring Harbor Laboratory},
|
| 33 |
+
URL = {https://www.biorxiv.org/content/early/2024/06/10/2024.06.09.598103},
|
| 34 |
+
eprint = {https://www.biorxiv.org/content/early/2024/06/10/2024.06.09.598103.full.pdf},
|
| 35 |
+
journal = {bioRxiv}
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
## License
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
Shield: [![CC BY-NC-SA 4.0][cc-by-nc-sa-shield]][cc-by-nc-sa]
|
| 43 |
+
|
| 44 |
+
This work is licensed under a
|
| 45 |
+
[Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License][cc-by-nc-sa].
|
| 46 |
+
|
| 47 |
+
[![CC BY-NC-SA 4.0][cc-by-nc-sa-image]][cc-by-nc-sa]
|
| 48 |
+
|
| 49 |
+
[cc-by-nc-sa]: http://creativecommons.org/licenses/by-nc-sa/4.0/
|
| 50 |
+
[cc-by-nc-sa-image]: https://licensebuttons.net/l/by-nc-sa/4.0/88x31.png
|
| 51 |
+
[cc-by-nc-sa-shield]: https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
## Disclaimer
|
| 55 |
+
|
| 56 |
+
DISTRIBUTION STATEMENT A. Approved for public release. Distribution is unlimited.
|
| 57 |
+
|
| 58 |
+
Any opinions, findings, conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the affiliated institutions of the author(s).
|
| 59 |
+
|
| 60 |
+
© 2024 P2PXML Team.
|
| 61 |
+
|
conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antibodies_0.5γ.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:93ef94df9521ab9fbf988d5c47007e46297325a02c78e24c99fc990d4d610a9d
|
| 3 |
+
size 806844
|
conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antibodies_10-1074.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d4f91d4681b79ec48f23f7888e6cb15a59db7ff68da879355ae3b0dee7295b50
|
| 3 |
+
size 1587531
|
conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_0013095_2_11.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ac2432509e5dec3f719fcbe459845a99cd148f97ff2be0007cc986f6e9aa7a60
|
| 3 |
+
size 2016242
|
conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_0815_V3_C3.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:970fe055e85973b871814101bf5e136f0ebed848816ad9c7a3a7e202da4203b0
|
| 3 |
+
size 2013784
|
conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_6535_3.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:8686544b6804f247e5333438b947f627a2c44e20b0915f4c7353ac4e8ced528f
|
| 3 |
+
size 2020324
|
conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_AC10_29.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c389b1f225c783bb7e3dc99fc0ca2612709fff29c348228a5a2536b92a509296
|
| 3 |
+
size 65536
|
conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_JRFL.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b765659c9a03c6fe870a233ad754a08633bb0366011271c605d0c209fef4c188
|
| 3 |
+
size 2009226
|
conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_PVO_4.pt
ADDED
|
File without changes
|
conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_QH0692_42.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f270e2661f8e79b1e9355cbc253271adbbc2ad7f8801412ec04250fd7e9307d1
|
| 3 |
+
size 2013515
|
conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_REJO4541_67.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d2485678396d8d4312c4afbf415548fd238cdedd952778ea4623f8c81c9aa06b
|
| 3 |
+
size 1638400
|
conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_RHPA4259_7.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:67ef316708b16aa7638b78839110234f3d2806b19a831fff61bd61a3b5e2a578
|
| 3 |
+
size 2016280
|
conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_WITO4160_33.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:3f9e20fbe89397f45a86378d92a48edd995e342a2abe99ff94c8234c39f6ec4d
|
| 3 |
+
size 2018213
|
conf/legacy/__MACOSX/P2PXML_dataset/._.DS_Store
ADDED
|
Binary file (120 Bytes). View file
|
|
|
conf/legacy/__MACOSX/P2PXML_dataset/._P2PXML_Structure
ADDED
|
Binary file (220 Bytes). View file
|
|
|
conf/legacy/__MACOSX/P2PXML_dataset/P2PXML-Seq/._README.md
ADDED
|
Binary file (476 Bytes). View file
|
|
|
conf/legacy/__MACOSX/P2PXML_dataset/P2PXML_Structure/._.DS_Store
ADDED
|
Binary file (120 Bytes). View file
|
|
|
conf/legacy/__MACOSX/P2PXML_dataset/P2PXML_Structure/._README.md
ADDED
|
Binary file (476 Bytes). View file
|
|
|
conf/legacy/incomplete_transfers/ESM1v-SVR.partial.pkl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6a6022211516ca9375e3266fbee9f6639e16bb4c0f8d3977f1f8fcb219bfefdd
|
| 3 |
+
size 45678592
|
conf/legacy/python_cache/ephod/__init__.cpython-310.pyc
ADDED
|
Binary file (281 Bytes). View file
|
|
|
conf/legacy/python_cache/ephod/__init__.cpython-311.pyc
ADDED
|
Binary file (327 Bytes). View file
|
|
|
conf/legacy/python_cache/model/__init__.cpython-310.pyc
ADDED
|
Binary file (173 Bytes). View file
|
|
|
conf/legacy/python_cache/training/__init__.cpython-310.pyc
ADDED
|
Binary file (149 Bytes). View file
|
|
|
conf/legacy/python_cache/training/__init__.cpython-311.pyc
ADDED
|
Binary file (179 Bytes). View file
|
|
|
conf/legacy/python_cache/training/nn_models.cpython-311.pyc
ADDED
|
Binary file (30.5 kB). View file
|
|
|
conf/legacy/torch_cache/hub/checkpoints/ESM1v-RLATtr.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5a8d2ce39e4d0e8c584172301cc1fd7942f919994266cb4875feeb3e165f6b89
|
| 3 |
+
size 19726336
|
conf/legacy/torch_cache/hub/checkpoints/esm1v_t33_650M_UR90S_1.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f3d7c4c868045cbea65b47debb9764d8f55dcaea63854a169c7442a5d084df2b
|
| 3 |
+
size 12058624
|
configuration.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_name": "EpHod",
|
| 3 |
+
"framework": "PyTorch",
|
| 4 |
+
"task": "enzyme-optimum-ph-prediction",
|
| 5 |
+
"entry_points": {
|
| 6 |
+
"inference": "scripts/inference.py",
|
| 7 |
+
"predict": "scripts/inference.py",
|
| 8 |
+
"train_neural_network": "scripts/train_nnmodels.py",
|
| 9 |
+
"train_machine_learning": "scripts/train_ml_models.py"
|
| 10 |
+
},
|
| 11 |
+
"source_package": "model",
|
| 12 |
+
"config": "conf/config.json",
|
| 13 |
+
"weight_dir": "weight",
|
| 14 |
+
"license": "MIT"
|
| 15 |
+
}
|
model/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
"""EpHod model source package."""
|
model/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (202 Bytes). View file
|
|
|
model/ephod/__init__.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""EpHod: A deep language model to predict enzyme optimum pH
|
| 2 |
+
Author: Japheth Gado
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
__version__ = 1.0
|
| 6 |
+
from . import *
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
|
model/ephod/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (324 Bytes). View file
|
|
|
model/ephod/training/__init__.py
ADDED
|
File without changes
|
model/ephod/training/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (176 Bytes). View file
|
|
|
model/ephod/training/__pycache__/nn_models.cpython-311.pyc
ADDED
|
Binary file (30.5 kB). View file
|
|
|
model/ephod/training/nn_models.py
ADDED
|
@@ -0,0 +1,659 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Neural network models
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
import numpy as np
|
| 7 |
+
import torch
|
| 8 |
+
import torch.nn as nn
|
| 9 |
+
import torch.nn.functional as F
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def torchActivation(activation='elu'):
|
| 15 |
+
'''Return an activation function from torch.nn'''
|
| 16 |
+
|
| 17 |
+
if activation == 'relu':
|
| 18 |
+
return nn.ReLU()
|
| 19 |
+
elif activation == 'leaky_relu':
|
| 20 |
+
return nn.LeakyReLU()
|
| 21 |
+
elif activation == 'elu':
|
| 22 |
+
return nn.ELU()
|
| 23 |
+
elif activation == 'selu':
|
| 24 |
+
return nn.SELU()
|
| 25 |
+
elif activation == 'gelu':
|
| 26 |
+
return nn.GELU()
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def count_parameters(model):
|
| 32 |
+
'''Return a count of parameters and tensor shape of PyTorch model'''
|
| 33 |
+
|
| 34 |
+
counted = {}
|
| 35 |
+
total = 0
|
| 36 |
+
for name, param in model.named_parameters():
|
| 37 |
+
if param.requires_grad:
|
| 38 |
+
count = param.numel()
|
| 39 |
+
total += count
|
| 40 |
+
counted[name] = count
|
| 41 |
+
counted['FULL_MODEL'] = total
|
| 42 |
+
|
| 43 |
+
return counted
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
class ResidualDense(nn.Module):
|
| 49 |
+
'''A single dense layer with residual connection'''
|
| 50 |
+
|
| 51 |
+
def __init__(self, dim=2560, dropout=0.1, activation='elu', random_seed=0):
|
| 52 |
+
|
| 53 |
+
super(ResidualDense, self).__init__()
|
| 54 |
+
_ = torch.manual_seed(random_seed)
|
| 55 |
+
self.dense = nn.Linear(dim, dim)
|
| 56 |
+
self.batchnorm = nn.BatchNorm1d(dim)
|
| 57 |
+
self.activation = torchActivation(activation)
|
| 58 |
+
self.dropout = nn.Dropout(dropout)
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
def forward(self, x):
|
| 62 |
+
|
| 63 |
+
x0 = x
|
| 64 |
+
x = self.dense(x)
|
| 65 |
+
x = self.batchnorm(x)
|
| 66 |
+
x = self.activation(x)
|
| 67 |
+
x = self.dropout(x)
|
| 68 |
+
x = x0 + x
|
| 69 |
+
|
| 70 |
+
return x
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
class LightAttention(nn.Module):
|
| 76 |
+
'''Convolution model with attention to learn pooled representations from embeddings'''
|
| 77 |
+
|
| 78 |
+
def __init__(self, dim=1280, kernel_size=7, random_seed=0):
|
| 79 |
+
|
| 80 |
+
super(LightAttention, self).__init__()
|
| 81 |
+
_ = torch.manual_seed(random_seed)
|
| 82 |
+
samepad = kernel_size // 2
|
| 83 |
+
self.values_conv = nn.Conv1d(dim, dim, kernel_size=kernel_size, padding=samepad)
|
| 84 |
+
self.weights_conv = nn.Conv1d(dim, dim, kernel_size=kernel_size, padding=samepad)
|
| 85 |
+
self.softmax = nn.Softmax(dim=-1)
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
def forward(self, x, mask=None):
|
| 89 |
+
if mask is None:
|
| 90 |
+
mask = torch.ones(x.shape[0], x.shape[2], dtype=torch.int32) # Don't mask out
|
| 91 |
+
values = self.values_conv(x)
|
| 92 |
+
values = values.masked_fill(mask[:,None,:]==0, -1e6)
|
| 93 |
+
weights = self.weights_conv(x)
|
| 94 |
+
weights = weights.masked_fill(mask[:,None,:]==0, -1e6)
|
| 95 |
+
weights = self.softmax(weights)
|
| 96 |
+
x_sum = torch.sum(values * weights, dim=-1) # Attention-weighted pooling
|
| 97 |
+
x_max, _ = torch.max(values, dim=-1) # Max pooling
|
| 98 |
+
x = torch.cat([x_sum, x_max], dim=1)
|
| 99 |
+
|
| 100 |
+
return x, weights
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
class ResidualLightAttention(nn.Module):
|
| 106 |
+
'''Model consisting of light attention followed by residual dense layers'''
|
| 107 |
+
|
| 108 |
+
def __init__(self, dim=1280, kernel_size=9, dropout=0.5,
|
| 109 |
+
activation='relu', res_blocks=4, random_seed=0):
|
| 110 |
+
|
| 111 |
+
super(ResidualLightAttention, self).__init__()
|
| 112 |
+
torch.manual_seed(random_seed)
|
| 113 |
+
self.light_attention = LightAttention(dim, kernel_size, random_seed)
|
| 114 |
+
self.batchnorm = nn.BatchNorm1d(2 * dim)
|
| 115 |
+
self.dropout = nn.Dropout(dropout)
|
| 116 |
+
self.residual_dense = nn.ModuleList()
|
| 117 |
+
for i in range(res_blocks):
|
| 118 |
+
self.residual_dense.append(
|
| 119 |
+
ResidualDense(2 * dim, dropout, activation, random_seed)
|
| 120 |
+
)
|
| 121 |
+
self.output = nn.Linear(2 * dim, 1)
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
def forward(self, x, mask=None):
|
| 125 |
+
|
| 126 |
+
x, weights = self.light_attention(x, mask)
|
| 127 |
+
x = self.batchnorm(x)
|
| 128 |
+
x = self.dropout(x)
|
| 129 |
+
for layer in self.residual_dense:
|
| 130 |
+
x = layer(x)
|
| 131 |
+
y = self.output(x).flatten()
|
| 132 |
+
|
| 133 |
+
return [y, x, weights]
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
class FeedForwardNetwork(nn.Module):
|
| 139 |
+
'''A feed-forward neural network (fully-connected)'''
|
| 140 |
+
|
| 141 |
+
def __init__(self, input_dim=1280, hidden_dim=128, num_layers=1, dropout=0.25, activation='relu',
|
| 142 |
+
residual=False):
|
| 143 |
+
|
| 144 |
+
super().__init__()
|
| 145 |
+
self.num_layers = num_layers
|
| 146 |
+
self.residual = residual
|
| 147 |
+
|
| 148 |
+
# First dense layer
|
| 149 |
+
# Separate first dense layer from the other dense layers to allow residual connection
|
| 150 |
+
self.first_dense = nn.ModuleList(
|
| 151 |
+
[
|
| 152 |
+
nn.Linear(input_dim, hidden_dim),
|
| 153 |
+
nn.BatchNorm1d(hidden_dim),
|
| 154 |
+
torchActivation(activation),
|
| 155 |
+
nn.Dropout(dropout) if activation != 'selu' else nn.AlphaDropout(dropout)
|
| 156 |
+
]
|
| 157 |
+
)
|
| 158 |
+
|
| 159 |
+
# Other dense layers after first dense and residual connection
|
| 160 |
+
if num_layers > 1:
|
| 161 |
+
self.other_dense = nn.ModuleList()
|
| 162 |
+
for i in range(1, num_layers):
|
| 163 |
+
self.other_dense.extend(
|
| 164 |
+
[
|
| 165 |
+
nn.Linear(hidden_dim, hidden_dim),
|
| 166 |
+
nn.BatchNorm1d(hidden_dim),
|
| 167 |
+
torchActivation(activation),
|
| 168 |
+
nn.Dropout(dropout) if activation != 'selu' else nn.AlphaDropout(dropout)
|
| 169 |
+
]
|
| 170 |
+
)
|
| 171 |
+
# Output layer
|
| 172 |
+
self.output_layer = nn.Linear(hidden_dim, 1)
|
| 173 |
+
|
| 174 |
+
|
| 175 |
+
def forward(self, x):
|
| 176 |
+
|
| 177 |
+
# First dense layer
|
| 178 |
+
for layer in self.first_dense:
|
| 179 |
+
x = layer(x)
|
| 180 |
+
|
| 181 |
+
# Other dense layers
|
| 182 |
+
if self.num_layers > 1:
|
| 183 |
+
x0 = x
|
| 184 |
+
for layer in self.other_dense:
|
| 185 |
+
x = layer(x)
|
| 186 |
+
# Residual connection
|
| 187 |
+
if self.residual:
|
| 188 |
+
x = x0 + x
|
| 189 |
+
# Output layer
|
| 190 |
+
y = self.output_layer(x).flatten()
|
| 191 |
+
|
| 192 |
+
return y
|
| 193 |
+
|
| 194 |
+
|
| 195 |
+
|
| 196 |
+
|
| 197 |
+
class CNN(nn.Module):
|
| 198 |
+
|
| 199 |
+
def __init__(self, input_channel=20, input_length=1024, start_conv_channel=32, kernel_size=3,
|
| 200 |
+
num_conv_layers=8, conv_dropout=0.25, pooltype='max', dense_dim=128, num_dense_layers=1,
|
| 201 |
+
dense_dropout=0.25, activation='relu'):
|
| 202 |
+
|
| 203 |
+
super().__init__()
|
| 204 |
+
# Conv layers
|
| 205 |
+
self.conv_layers = nn.ModuleList()
|
| 206 |
+
for i in range(num_conv_layers):
|
| 207 |
+
in_channel = input_channel if i==0 else out_channel
|
| 208 |
+
out_channel = start_conv_channel * (2 ** i)
|
| 209 |
+
self.conv_layers.append(nn.Conv1d(in_channel, out_channel, kernel_size=kernel_size,
|
| 210 |
+
padding=(kernel_size // 2)))
|
| 211 |
+
self.conv_layers.append(nn.BatchNorm1d(out_channel))
|
| 212 |
+
self.conv_layers.append(torchActivation(activation))
|
| 213 |
+
if pooltype=='max' and i>0:
|
| 214 |
+
self.conv_layers.append(nn.MaxPool1d(kernel_size=2, stride=2))
|
| 215 |
+
elif pooltype=='average' and i>0:
|
| 216 |
+
self.conv_layers.append(nn.AvgPool1d(kernel_size=2, stride=2))
|
| 217 |
+
self.conv_layers.append(nn.Dropout(conv_dropout))
|
| 218 |
+
# FNN layers
|
| 219 |
+
self.flatsize = start_conv_channel * input_length
|
| 220 |
+
self.fnn = FeedForwardNetwork(input_dim=self.flatsize, hidden_dim=dense_dim, num_layers=num_dense_layers,
|
| 221 |
+
dropout=dense_dropout, activation=activation, residual=True)
|
| 222 |
+
|
| 223 |
+
def forward(self, x):
|
| 224 |
+
|
| 225 |
+
for layer in self.conv_layers:
|
| 226 |
+
x = layer(x)
|
| 227 |
+
x = x.view(-1, self.flatsize)
|
| 228 |
+
y = self.fnn(x)
|
| 229 |
+
|
| 230 |
+
return y
|
| 231 |
+
|
| 232 |
+
|
| 233 |
+
|
| 234 |
+
|
| 235 |
+
class CausalConv1d(nn.Module):
|
| 236 |
+
'''Causal convolution'''
|
| 237 |
+
|
| 238 |
+
def __init__(self, in_channels, out_channels, kernel_size, dilation=1):
|
| 239 |
+
|
| 240 |
+
super().__init__()
|
| 241 |
+
|
| 242 |
+
self.pad = int(np.ceil(dilation * (kernel_size - 1) / 2)) # Padding to ensure causal convolution
|
| 243 |
+
self.conv_layer = nn.Conv1d(in_channels, out_channels, padding=0,kernel_size=kernel_size,
|
| 244 |
+
dilation=dilation)
|
| 245 |
+
|
| 246 |
+
def forward(self, x):
|
| 247 |
+
|
| 248 |
+
len1 = x.shape[-1]
|
| 249 |
+
x = F.pad(x, (self.pad * 2, 0))
|
| 250 |
+
x = self.conv_layer(x)
|
| 251 |
+
len2 = x.shape[-1]
|
| 252 |
+
start = len2 - len1
|
| 253 |
+
x = x[:,:,start:len2]
|
| 254 |
+
|
| 255 |
+
return x
|
| 256 |
+
|
| 257 |
+
|
| 258 |
+
|
| 259 |
+
|
| 260 |
+
class DCNNBlock(nn.Module):
|
| 261 |
+
|
| 262 |
+
def __init__(self,channel_size=32, num_layers=6,dropout=0.5, activation='elu'):
|
| 263 |
+
|
| 264 |
+
super().__init__()
|
| 265 |
+
dilation_rates = (2. ** np.arange(num_layers)).astype(np.int32)
|
| 266 |
+
self.layers = nn.ModuleList()
|
| 267 |
+
for d in dilation_rates:
|
| 268 |
+
self.layers.append(CausalConv1d(channel_size, channel_size, kernel_size=2, dilation=d))
|
| 269 |
+
self.layers.append(nn.BatchNorm1d(channel_size))
|
| 270 |
+
self.layers.append(torchActivation(activation))
|
| 271 |
+
self.layers.append(nn.Dropout(dropout))
|
| 272 |
+
|
| 273 |
+
def forward(self, x):
|
| 274 |
+
|
| 275 |
+
x0 = x
|
| 276 |
+
for layer in self.layers:
|
| 277 |
+
x = layer(x)
|
| 278 |
+
x = x0 + x
|
| 279 |
+
|
| 280 |
+
return x
|
| 281 |
+
|
| 282 |
+
|
| 283 |
+
|
| 284 |
+
|
| 285 |
+
class DCNN(nn.Module):
|
| 286 |
+
|
| 287 |
+
def __init__(self, input_channel=20, conv_channel=48, num_blocks=6, layers_per_block=10,
|
| 288 |
+
block_dropout=0.5, dense_dim=128, num_dense_layers=2, dense_dropout=0.25,
|
| 289 |
+
activation='elu'):
|
| 290 |
+
|
| 291 |
+
super().__init__()
|
| 292 |
+
self.embed_layer = nn.Conv1d(input_channel, conv_channel, kernel_size=1, bias=False)
|
| 293 |
+
|
| 294 |
+
# DCNN blocks
|
| 295 |
+
self.dcnn_blocks = nn.ModuleList()
|
| 296 |
+
for block in range(num_blocks):
|
| 297 |
+
self.dcnn_blocks.append(DCNNBlock(channel_size=conv_channel, num_layers=layers_per_block,
|
| 298 |
+
dropout=block_dropout, activation=activation))
|
| 299 |
+
|
| 300 |
+
self.fnn = FeedForwardNetwork(input_dim=conv_channel, hidden_dim=dense_dim,
|
| 301 |
+
num_layers=num_dense_layers, dropout=dense_dropout,
|
| 302 |
+
activation=activation, residual=True)
|
| 303 |
+
|
| 304 |
+
def forward(self, x, mask=None):
|
| 305 |
+
|
| 306 |
+
x = self.embed_layer(x)
|
| 307 |
+
# Dilated convolutions
|
| 308 |
+
for layer in self.dcnn_blocks:
|
| 309 |
+
x = layer(x)
|
| 310 |
+
if mask is None:
|
| 311 |
+
mask = torch.ones(x.shape[0], x.shape[2], dtype=torch.int32)
|
| 312 |
+
# Average pooling
|
| 313 |
+
x = x.masked_fill(mask[:,None,:] == 0, 0)
|
| 314 |
+
x = torch.divide(torch.sum(x, dim=-1), torch.sum(mask, dim=-1)[:,None])
|
| 315 |
+
|
| 316 |
+
# FNN
|
| 317 |
+
y = self.fnn(x).flatten()
|
| 318 |
+
|
| 319 |
+
return y
|
| 320 |
+
|
| 321 |
+
|
| 322 |
+
|
| 323 |
+
|
| 324 |
+
class RNN(nn.Module):
|
| 325 |
+
|
| 326 |
+
def __init__(self, input_channel=20, input_length=1024, gru_dim=1024, conv_downsample=1,
|
| 327 |
+
conv_dropout=0.25, dense_dim=128, dense_dropout=0.25, activation='relu'):
|
| 328 |
+
|
| 329 |
+
super().__init__()
|
| 330 |
+
|
| 331 |
+
# Convolutional layers to downsample
|
| 332 |
+
self.conv_downsample = conv_downsample
|
| 333 |
+
self.conv_layers = nn.ModuleList()
|
| 334 |
+
pad = (conv_downsample // 2 - 1)
|
| 335 |
+
pad = max(pad, 0)
|
| 336 |
+
self.conv_layers.append(nn.Conv1d(input_channel, gru_dim, kernel_size=conv_downsample,
|
| 337 |
+
stride=conv_downsample, padding=pad))
|
| 338 |
+
self.conv_layers.append(nn.BatchNorm1d(gru_dim))
|
| 339 |
+
self.conv_layers.append(torchActivation(activation))
|
| 340 |
+
self.conv_layers.append(nn.Dropout(conv_dropout))
|
| 341 |
+
|
| 342 |
+
# RNN layer
|
| 343 |
+
self.gru_layer = nn.GRU(gru_dim, gru_dim, batch_first=True, bidirectional=False)
|
| 344 |
+
|
| 345 |
+
# Dense layer
|
| 346 |
+
self.dense_layers = nn.ModuleList()
|
| 347 |
+
self.dense_layers.extend(
|
| 348 |
+
[
|
| 349 |
+
nn.Linear(gru_dim, dense_dim),
|
| 350 |
+
nn.BatchNorm1d(dense_dim),
|
| 351 |
+
torchActivation(activation),
|
| 352 |
+
nn.Dropout(dense_dropout) if activation != 'selu' else nn.AlphaDropout(dense_dropout)
|
| 353 |
+
]
|
| 354 |
+
)
|
| 355 |
+
|
| 356 |
+
# Output layer
|
| 357 |
+
self.output_layer = nn.Linear(dense_dim, 1)
|
| 358 |
+
|
| 359 |
+
|
| 360 |
+
|
| 361 |
+
def forward(self, x, mask=None):
|
| 362 |
+
|
| 363 |
+
if mask is None:
|
| 364 |
+
mask = torch.tensor(np.ones((x.shape[0], x.shape[-1])), dtype=torch.float32)
|
| 365 |
+
|
| 366 |
+
# Downsample with convolution
|
| 367 |
+
for layer in self.conv_layers:
|
| 368 |
+
x = layer(x)
|
| 369 |
+
|
| 370 |
+
# RNN
|
| 371 |
+
x = x.transpose(2, 1) # Transpose from [batch, feat, seqlen] to [batch, sequence, features]
|
| 372 |
+
x = self.gru_layer(x)[0]
|
| 373 |
+
lastind = torch.sum(mask, axis=1, dtype=int) # index of last residue in sequence
|
| 374 |
+
lastind = (lastind // self.conv_downsample) - 1 # index after conv. downsampling
|
| 375 |
+
x = [x[i][lastind[i]] for i in range(len(lastind))] # get hidden state of last residue for each sequence
|
| 376 |
+
x = torch.stack(x)
|
| 377 |
+
|
| 378 |
+
# Dense layer
|
| 379 |
+
for layer in self.dense_layers:
|
| 380 |
+
x = layer(x)
|
| 381 |
+
|
| 382 |
+
# Output layer
|
| 383 |
+
x = self.output_layer(x).flatten()
|
| 384 |
+
|
| 385 |
+
return x
|
| 386 |
+
|
| 387 |
+
|
| 388 |
+
|
| 389 |
+
|
| 390 |
+
class AttentionTopModel(nn.Module):
|
| 391 |
+
'''
|
| 392 |
+
Class to implement a top model based on LAT architecture to predict a property from
|
| 393 |
+
embeddings.
|
| 394 |
+
|
| 395 |
+
Parameters
|
| 396 |
+
-----------
|
| 397 |
+
input_dim : int
|
| 398 |
+
Channel dimension of input embedding, 1280 for ESM-1b
|
| 399 |
+
attention_dim : int
|
| 400 |
+
Channel dimension of transformed values and attention weights
|
| 401 |
+
kernel_size : int
|
| 402 |
+
Kernel size of convolution
|
| 403 |
+
conv_dropout : float
|
| 404 |
+
Dropout applied to values embedding after convolution
|
| 405 |
+
perceptive : bool
|
| 406 |
+
If True, concatenate input embedding with average pooled embedding to derive
|
| 407 |
+
a perceptive embedding.
|
| 408 |
+
dense_dim : int
|
| 409 |
+
Number of units in hidden dense layer
|
| 410 |
+
dense_dropout : float
|
| 411 |
+
Dropout of dense hidden layers.
|
| 412 |
+
activation : str
|
| 413 |
+
Activation function of dense hidden layer.
|
| 414 |
+
random_seed : int
|
| 415 |
+
Random seed for reproducibillity
|
| 416 |
+
|
| 417 |
+
'''
|
| 418 |
+
|
| 419 |
+
|
| 420 |
+
def __init__(self,
|
| 421 |
+
input_dim=1280,
|
| 422 |
+
attention_dim=1280,
|
| 423 |
+
kernel_size=9,
|
| 424 |
+
conv_dropout=0.25,
|
| 425 |
+
perceptive=True,
|
| 426 |
+
dense_dim=512,
|
| 427 |
+
dense_dropout=0.25,
|
| 428 |
+
num_layers=1,
|
| 429 |
+
residual=False,
|
| 430 |
+
activation='relu',
|
| 431 |
+
random_seed=0):
|
| 432 |
+
|
| 433 |
+
|
| 434 |
+
super(AttentionTopModel, self).__init__()
|
| 435 |
+
|
| 436 |
+
|
| 437 |
+
# Initialize class parameters
|
| 438 |
+
self.input_dim = input_dim
|
| 439 |
+
self.attention_dim = attention_dim
|
| 440 |
+
self.kernel_size = kernel_size
|
| 441 |
+
self.conv_dropout = conv_dropout
|
| 442 |
+
self.perceptive = perceptive
|
| 443 |
+
self.dense_dim = dense_dim
|
| 444 |
+
self.dense_dropout = dense_dropout
|
| 445 |
+
self.num_layers = num_layers
|
| 446 |
+
self.residual = residual
|
| 447 |
+
self.activation = activation
|
| 448 |
+
self.random_seed = random_seed
|
| 449 |
+
_ = torch.manual_seed(self.random_seed)
|
| 450 |
+
|
| 451 |
+
|
| 452 |
+
# A convolution layer to learn values from embeddings
|
| 453 |
+
self.values_conv = nn.Conv1d(
|
| 454 |
+
2 * self.input_dim if perceptive else self.input_dim,
|
| 455 |
+
self.attention_dim,
|
| 456 |
+
kernel_size=self.kernel_size,
|
| 457 |
+
stride=1,
|
| 458 |
+
padding=(self.kernel_size // 2)
|
| 459 |
+
)
|
| 460 |
+
self.values_dropout = nn.Dropout(self.conv_dropout)
|
| 461 |
+
|
| 462 |
+
|
| 463 |
+
# A convolution and softmax layer to learn attention weights that sum to 1
|
| 464 |
+
self.attn_conv = nn.Conv1d(
|
| 465 |
+
2 * self.input_dim if perceptive else self.input_dim,
|
| 466 |
+
self.attention_dim,
|
| 467 |
+
kernel_size=self.kernel_size,
|
| 468 |
+
stride=1,
|
| 469 |
+
padding=(self.kernel_size // 2)
|
| 470 |
+
)
|
| 471 |
+
self.attn_softmax = nn.Softmax(dim=-1)
|
| 472 |
+
|
| 473 |
+
# Dense(residual) layers on top of the attention-learned embeddings
|
| 474 |
+
self.dense_layers = FeedForwardNetwork(
|
| 475 |
+
input_dim=(2 * self.attention_dim),
|
| 476 |
+
hidden_dims=[self.dense_dim] * self.num_layers,
|
| 477 |
+
dropout=self.dense_dropout,
|
| 478 |
+
activation=self.activation,
|
| 479 |
+
residual=self.residual,
|
| 480 |
+
random_seed=self.random_seed
|
| 481 |
+
)
|
| 482 |
+
|
| 483 |
+
|
| 484 |
+
def forward(self, x, mask=None):
|
| 485 |
+
'''
|
| 486 |
+
Forward pass of network.
|
| 487 |
+
|
| 488 |
+
Parameters
|
| 489 |
+
------------
|
| 490 |
+
x : torch.Tensor
|
| 491 |
+
Shape is [batch_size, embeddings_dim, seq_len]
|
| 492 |
+
mask : torch.Tensor or None
|
| 493 |
+
Boolean tensor indicating padded (0) and non-padded (1) positions. Shape is
|
| 494 |
+
[batch_size, seq_len]. If mask is None, a tensor of ones is used,
|
| 495 |
+
indicating that padded positions are not masked out in the forward
|
| 496 |
+
computations.
|
| 497 |
+
|
| 498 |
+
Returns
|
| 499 |
+
-------
|
| 500 |
+
output: list
|
| 501 |
+
A list of predicted values (shape is [batch_size, 1]), embedding of the
|
| 502 |
+
hidden layer before the output layer (shape is [batch_size, dense_dim]), and
|
| 503 |
+
the masked attention weights (shape is [batch_size, attention_dim, seq_len])
|
| 504 |
+
'''
|
| 505 |
+
|
| 506 |
+
# Masking for padded positions
|
| 507 |
+
if mask is None:
|
| 508 |
+
# If mask is None, use all positions including padded positions
|
| 509 |
+
mask = torch.ones(x.shape[0], x.shape[2], dtype=torch.int32)
|
| 510 |
+
|
| 511 |
+
# Derive a perceptive tensor by concatenating mean pooled embeddings to the input
|
| 512 |
+
# Output shape of perceptive tensor is [batch_size, 2 * input_dim, seq_length]
|
| 513 |
+
if self.perceptive:
|
| 514 |
+
# Mask out padded positions
|
| 515 |
+
x_perc = x.masked_fill(mask[:,None,:] == 0, 0)
|
| 516 |
+
# Average pooling over unpadded positions
|
| 517 |
+
x_perc = torch.divide(torch.sum(x_perc, dim=-1),
|
| 518 |
+
torch.sum(mask, dim=1)[:,None])
|
| 519 |
+
# Repeat pooled tensor to match sequence length
|
| 520 |
+
x_perc = x_perc[:,:,None].repeat(1,1,x.shape[-1])
|
| 521 |
+
# Concatenate input embeddings and perceptive tensor along feature dimension
|
| 522 |
+
x = torch.cat((x, x_perc), axis=1)
|
| 523 |
+
|
| 524 |
+
# Derive values and attention weights from input embeddings with convolution
|
| 525 |
+
# Output shapes for values/weights is [batch_size, attention_dim, seq_length]
|
| 526 |
+
values = self.values_conv(x)
|
| 527 |
+
values = self.values_dropout(values)
|
| 528 |
+
values = values.masked_fill(mask[:,None,:] == 0, -1e6) # Mask out for max pooling
|
| 529 |
+
|
| 530 |
+
# Attention weights that sum to 1
|
| 531 |
+
attn = self.attn_conv(x)
|
| 532 |
+
attn = attn.masked_fill(mask[:,None,:] == 0, -1e6) # Mask out for average pooling
|
| 533 |
+
attn = self.attn_softmax(attn)
|
| 534 |
+
|
| 535 |
+
# Derive attention-learned embeddings by multiplying values and attention weights
|
| 536 |
+
# Output shape is [batch_size, 2 * attention_dim]
|
| 537 |
+
z_sum = torch.sum(values * attn, dim=-1)
|
| 538 |
+
z_max, _ = torch.max(values, dim=-1)
|
| 539 |
+
z = torch.cat([z_sum, z_max], dim=1)
|
| 540 |
+
|
| 541 |
+
# Dense layers
|
| 542 |
+
y, z = self.dense_layers(z)
|
| 543 |
+
|
| 544 |
+
|
| 545 |
+
return [y, z, attn]
|
| 546 |
+
|
| 547 |
+
|
| 548 |
+
|
| 549 |
+
|
| 550 |
+
class DilatedConvTopModel(nn.Module):
|
| 551 |
+
|
| 552 |
+
def __init__(self,
|
| 553 |
+
input_dim=1280,
|
| 554 |
+
input_len=1024,
|
| 555 |
+
attention_kernel_size=9,
|
| 556 |
+
conv_dim=64,
|
| 557 |
+
conv_kernel_size=3,
|
| 558 |
+
conv_dropout=0.1,
|
| 559 |
+
dilated_layers=9,
|
| 560 |
+
dense_dim=512,
|
| 561 |
+
dense_layers=1,
|
| 562 |
+
dense_dropout=0.25,
|
| 563 |
+
activation='relu',
|
| 564 |
+
random_seed=0):
|
| 565 |
+
|
| 566 |
+
super(DilatedConvTopModel, self).__init__()
|
| 567 |
+
_ = torch.manual_seed(random_seed)
|
| 568 |
+
|
| 569 |
+
# A convolution layer to learn transformed values from embeddings
|
| 570 |
+
self.values_conv_layer = nn.Conv1d(
|
| 571 |
+
input_dim,
|
| 572 |
+
conv_dim,
|
| 573 |
+
kernel_size=attention_kernel_size,
|
| 574 |
+
stride=1,
|
| 575 |
+
dilation=1,
|
| 576 |
+
padding=(attention_kernel_size // 2)
|
| 577 |
+
)
|
| 578 |
+
|
| 579 |
+
|
| 580 |
+
# A convolution and softmax layer to learn attention weights that sum to 1
|
| 581 |
+
# Attention-weighted values are obtained by element-wise multiplication with weights
|
| 582 |
+
self.attention_conv_layer = nn.Conv1d(
|
| 583 |
+
input_dim,
|
| 584 |
+
conv_dim,
|
| 585 |
+
kernel_size=attention_kernel_size,
|
| 586 |
+
stride=1,
|
| 587 |
+
dilation=1,
|
| 588 |
+
padding=(attention_kernel_size // 2)
|
| 589 |
+
)
|
| 590 |
+
self.attention_softmax = nn.Softmax(dim=-1)
|
| 591 |
+
self.conv_dropout_layer = nn.Dropout(conv_dropout) if activation != 'selu' \
|
| 592 |
+
else nn.AlphaDropout(conv_dropout)
|
| 593 |
+
|
| 594 |
+
|
| 595 |
+
# Convolutional layers with increasing dilation rates
|
| 596 |
+
self.dilated_conv_layers = nn.ModuleList()
|
| 597 |
+
dilations = np.power(2, np.arange(dilated_layers))
|
| 598 |
+
|
| 599 |
+
for d in dilations:
|
| 600 |
+
|
| 601 |
+
same_padding = self.get_same_padding_size(conv_kernel_size, d)
|
| 602 |
+
self.dilated_conv_layers.append(nn.Conv1d(conv_dim,
|
| 603 |
+
conv_dim,
|
| 604 |
+
kernel_size=conv_kernel_size,
|
| 605 |
+
padding=same_padding,
|
| 606 |
+
dilation=d)
|
| 607 |
+
)
|
| 608 |
+
self.dilated_conv_layers.append(nn.BatchNorm1d(conv_dim))
|
| 609 |
+
self.dilated_conv_layers.append(torchActivation(activation))
|
| 610 |
+
|
| 611 |
+
|
| 612 |
+
# Dense layers
|
| 613 |
+
self.dense_layers = FeedForwardNetwork(input_dim=(input_len * conv_dim),
|
| 614 |
+
hidden_dims=[dense_dim] * dense_layers,
|
| 615 |
+
dropout=dense_dropout,
|
| 616 |
+
activation=activation,
|
| 617 |
+
residual=(dense_layers > 1),
|
| 618 |
+
random_seed=random_seed)
|
| 619 |
+
|
| 620 |
+
|
| 621 |
+
def get_same_padding_size(self, k, d):
|
| 622 |
+
|
| 623 |
+
padsize = int(
|
| 624 |
+
np.ceil(
|
| 625 |
+
d * (k - 1) / 2
|
| 626 |
+
)
|
| 627 |
+
)
|
| 628 |
+
|
| 629 |
+
return padsize
|
| 630 |
+
|
| 631 |
+
|
| 632 |
+
def forward(self, x, mask=None):
|
| 633 |
+
|
| 634 |
+
# Masking for padded positions
|
| 635 |
+
if mask is None:
|
| 636 |
+
# If mask is None, use all positions including padded positions
|
| 637 |
+
mask = torch.ones(x.shape[0], x.shape[2], dtype=torch.int32)
|
| 638 |
+
|
| 639 |
+
# Derive attention-weighted values from input embeddings
|
| 640 |
+
# Shapes for values/weights is [batch_size, attention_dim, seq_length]
|
| 641 |
+
x_values = self.values_conv_layer(x)
|
| 642 |
+
x_weights = self.attention_conv_layer(x)
|
| 643 |
+
x_weights = x_weights.masked_fill(mask[:,None,:] == 0, -1e6)
|
| 644 |
+
x_weights = self.attention_softmax(x_weights) # Weights sum to 1
|
| 645 |
+
x = (x_values * x_weights)
|
| 646 |
+
x = self.conv_dropout_layer(x)
|
| 647 |
+
|
| 648 |
+
# Dilated convolution layers
|
| 649 |
+
x0 = x
|
| 650 |
+
for layer in self.dilated_conv_layers:
|
| 651 |
+
x = layer(x)
|
| 652 |
+
x = x0 + x # Residual connection
|
| 653 |
+
|
| 654 |
+
# Dense layers
|
| 655 |
+
x = x.flatten(start_dim=1, end_dim=2)
|
| 656 |
+
y, z = self.dense_layers(x)
|
| 657 |
+
|
| 658 |
+
return [y, z, x_weights]
|
| 659 |
+
|
model/ephod/training/trainutils.py
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Utility functions for training
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
import numpy as np
|
| 7 |
+
import pandas as pd
|
| 8 |
+
from scipy.stats import spearmanr, pearsonr
|
| 9 |
+
from scipy.ndimage import convolve1d
|
| 10 |
+
from scipy.ndimage import gaussian_filter1d
|
| 11 |
+
from sklearn import metrics
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def label_distribution_smoothing(y, bins=None, ks=5, sigma=2, normalize=True):
|
| 17 |
+
"""
|
| 18 |
+
Return a smoothed label distribution derived by convolving a symetric kernel
|
| 19 |
+
to the empirical label distribution. If bins is None, split the data (y) into bins
|
| 20 |
+
such that each bin corresponds to 1.0 pH unit. Otherwise if bins is an integer, split
|
| 21 |
+
bins into as many bins as is specified.
|
| 22 |
+
See the paper,
|
| 23 |
+
Yang, Zha, Chen, et al, 2021. Delving into deep imbalanced regression.
|
| 24 |
+
Code adapted from https://github.com/YyzHarry/imbalanced-regression
|
| 25 |
+
"""
|
| 26 |
+
|
| 27 |
+
# First split the data into bins of equal width
|
| 28 |
+
if bins==None:
|
| 29 |
+
bins = int(np.ceil(np.max(y) - np.min(y))) # No. of bins using a width of 1.0 pH units
|
| 30 |
+
bin_freqs, bin_borders = np.histogram(y, range=(min(y), max(y)), bins=bins)
|
| 31 |
+
y_binned = np.zeros(len(y)) # Initialize bin indices to 0s
|
| 32 |
+
for i in range(bins):
|
| 33 |
+
low, high = bin_borders[i], bin_borders[i+1] # Low and high boundaries of bin
|
| 34 |
+
locs = np.logical_and((y >= low), (y<= high)) # Location of values in y within bin
|
| 35 |
+
y_binned[locs] = i
|
| 36 |
+
|
| 37 |
+
# Compute kernel window
|
| 38 |
+
half_ks = (ks - 1) // 2
|
| 39 |
+
base_kernel = [0.] * half_ks + [1.] + [0.] * half_ks
|
| 40 |
+
kernel_window = gaussian_filter1d(base_kernel, sigma=sigma)
|
| 41 |
+
kernel_window /= max(gaussian_filter1d(base_kernel, sigma=sigma))
|
| 42 |
+
|
| 43 |
+
# Derive Kernel estimation
|
| 44 |
+
bin_kde = convolve1d(np.array(bin_freqs), weights=kernel_window, mode='constant')
|
| 45 |
+
y_kde = np.array([bin_kde[int(item)] for item in y_binned])
|
| 46 |
+
|
| 47 |
+
# Normalize KDE
|
| 48 |
+
if normalize:
|
| 49 |
+
y_kde = y_kde / (np.min(y_kde))
|
| 50 |
+
|
| 51 |
+
return y_kde
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def get_sample_weights(ydata, method='bin_inv', bin_borders=[5,9]):
|
| 57 |
+
"""
|
| 58 |
+
Return an array of sample weights computed with different methods.
|
| 59 |
+
Methods:
|
| 60 |
+
'None': No reweighting, weights of ones for all samples
|
| 61 |
+
'bin_inv': Inverse of frequency of three main bins [y<=5, 5<y<9, y>=9]
|
| 62 |
+
'bin_inv_sqrt': Square root of bin_inverse
|
| 63 |
+
'LDS_inv': Inverse of Gaussian kernel density estimate
|
| 64 |
+
(label distribution smoothing) of target data derived with
|
| 65 |
+
kernel size of 5, standard deviation of 2, and 100 equidistant bins.
|
| 66 |
+
'LDS_inv_sqrt': Square root of LDS_inv
|
| 67 |
+
'LDS_extreme': LDS weights are rescaled so that rare values (y<=5, y>=9) are twice
|
| 68 |
+
more likely to be selected than normal values (5<y<9).
|
| 69 |
+
"""
|
| 70 |
+
|
| 71 |
+
assert method in ['None', 'bin_inv', 'bin_inv_sqrt', 'LDS_inv', 'LDS_inv_sqrt',
|
| 72 |
+
'LDS_extreme']
|
| 73 |
+
|
| 74 |
+
if method == 'None':
|
| 75 |
+
# Non-uniform weights (no weighting, use data as is)
|
| 76 |
+
weights = np.ones(len(ydata))
|
| 77 |
+
|
| 78 |
+
elif method in ['bin_inv', 'bin_inv_sqrt']:
|
| 79 |
+
# Inverse frequency weights (1/n)
|
| 80 |
+
y_binned = np.digitize(ydata, bin_borders) # Continuous targets binned into categorical
|
| 81 |
+
bin_class, bin_freqs = np.unique(y_binned, return_counts=True)
|
| 82 |
+
inv_freq_dict = dict(zip(bin_class, 1 / bin_freqs)) # Frequency of each bin as dictionary
|
| 83 |
+
weights = np.array([inv_freq_dict[value] for value in y_binned]) # Inverse of frequency as sample weights
|
| 84 |
+
|
| 85 |
+
elif method in ['LDS_inv', 'LDS_inv_sqrt', 'LDS_extreme']:
|
| 86 |
+
# Label distribution smoothing (LDS) weights, with Gaussian KDE
|
| 87 |
+
effdist = label_distribution_smoothing(ydata, bins=100)
|
| 88 |
+
weights = 1 / effdist
|
| 89 |
+
if method == 'LDS_extreme':
|
| 90 |
+
# Scale weights so rare values have double weights
|
| 91 |
+
relevance = np.logical_or(ydata<=5, ydata>=9).astype(int) # Select rare values
|
| 92 |
+
relevance = relevance * (1 - 0.5) + 0.5 # Values to double rare weights
|
| 93 |
+
weights = weights * relevance
|
| 94 |
+
|
| 95 |
+
if method in ['bin_inv_sqrt', 'LDS_inv_sqrt']:
|
| 96 |
+
weights = np.sqrt(weights)
|
| 97 |
+
|
| 98 |
+
# Normalize so weights have a mean of 1
|
| 99 |
+
weights = weights / np.mean(weights)
|
| 100 |
+
|
| 101 |
+
return weights
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
def sample_hyperparameters(param_space, n=200):
|
| 107 |
+
"""
|
| 108 |
+
Return hyperparmeters randomly sampled from a dictionary, where keys are hyperparameter names
|
| 109 |
+
and values are arrays of possible hyperparameters.
|
| 110 |
+
"""
|
| 111 |
+
|
| 112 |
+
params_list = []
|
| 113 |
+
maxsize = int(np.product([len(item) for item in param_space.values()]))
|
| 114 |
+
|
| 115 |
+
while len(params_list) < min([n, maxsize]):
|
| 116 |
+
sampled_params = {}
|
| 117 |
+
for key,values in param_space.items():
|
| 118 |
+
sampled_params[key] = np.random.choice(values)
|
| 119 |
+
if sampled_params not in params_list:
|
| 120 |
+
params_list.append(sampled_params)
|
| 121 |
+
|
| 122 |
+
return params_list
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
def performance(ytrue, ypred, weights, bins=[5,9]):
|
| 128 |
+
'''Return a dictionary of performance metrics evaluated on predictions'''
|
| 129 |
+
|
| 130 |
+
perf = {}
|
| 131 |
+
ytrue, ypred, weights = np.asarray(ytrue), np.asarray(ypred), np.asarray(weights)
|
| 132 |
+
|
| 133 |
+
# Correlation (use resampled data to capture sparse acidic/alkaline regions)
|
| 134 |
+
p = weights / np.sum(weights)
|
| 135 |
+
usize = len(weights)
|
| 136 |
+
rho, r = 0, 0
|
| 137 |
+
iters = 100
|
| 138 |
+
for _ in range(iters):
|
| 139 |
+
locs = np.random.choice(range(len(ytrue)), size=usize, p=p, replace=True)
|
| 140 |
+
rho += float(spearmanr(ytrue[locs], ypred[locs])[0])
|
| 141 |
+
r += float(pearsonr(ytrue[locs], ypred[locs])[0])
|
| 142 |
+
perf['rho'] = rho / iters
|
| 143 |
+
perf['r'] = r / iters
|
| 144 |
+
|
| 145 |
+
# Sample-weighted metrics
|
| 146 |
+
perf['rmse'] = float(metrics.mean_squared_error(ytrue, ypred, sample_weight=weights, squared=False))
|
| 147 |
+
perf['r2'] = float(metrics.r2_score(ytrue, ypred, sample_weight=weights))
|
| 148 |
+
|
| 149 |
+
# Classification performance of binned data
|
| 150 |
+
ytrue_binned = np.digitize(ytrue, bins)
|
| 151 |
+
ypred_binned = np.digitize(ypred, bins)
|
| 152 |
+
perf['mcc'] = float(metrics.matthews_corrcoef(ytrue_binned, ypred_binned, sample_weight=weights))
|
| 153 |
+
f1score, auc = [], [],
|
| 154 |
+
for val in set(ytrue_binned):
|
| 155 |
+
ytrue_sel = (ytrue_binned==val).astype(int)
|
| 156 |
+
ypred_sel = (ypred_binned==val).astype(int)
|
| 157 |
+
f1score.append(float(metrics.f1_score(ytrue_sel, ypred_sel, sample_weight=weights)))
|
| 158 |
+
auc.append(float(metrics.roc_auc_score(ytrue_sel, ypred_sel, sample_weight=weights)))
|
| 159 |
+
perf['f1score_per_bin'] = f1score
|
| 160 |
+
perf['f1score'] = np.mean(f1score)
|
| 161 |
+
perf['auc_per_bin'] = auc
|
| 162 |
+
perf['auc'] = np.mean(auc)
|
| 163 |
+
|
| 164 |
+
return perf
|
| 165 |
+
|