wuxing0105 commited on
Commit
bae5726
·
verified ·
1 Parent(s): 909fb00

Upload folder using huggingface_hub

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitignore +12 -0
  2. .ms_upload_cache +1 -0
  3. LICENSE +21 -0
  4. README.md +215 -0
  5. conf/README_upstream.rst +52 -0
  6. conf/config.json +12 -0
  7. conf/data/smoke.fasta +2 -0
  8. conf/data/test_sequences.fasta +0 -0
  9. conf/environment.yml +10 -0
  10. conf/environment_upstream.yml +25 -0
  11. conf/legacy/P2PXML_dataset/.DS_Store +0 -0
  12. conf/legacy/P2PXML_dataset/P2PXML-Seq/README.md +66 -0
  13. conf/legacy/P2PXML_dataset/P2PXML_Structure/.DS_Store +0 -0
  14. conf/legacy/P2PXML_dataset/P2PXML_Structure/README.md +61 -0
  15. conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antibodies_0.5γ.pt +3 -0
  16. conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antibodies_10-1074.pt +3 -0
  17. conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_0013095_2_11.pt +3 -0
  18. conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_0815_V3_C3.pt +3 -0
  19. conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_6535_3.pt +3 -0
  20. conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_AC10_29.pt +3 -0
  21. conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_JRFL.pt +3 -0
  22. conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_PVO_4.pt +0 -0
  23. conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_QH0692_42.pt +3 -0
  24. conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_REJO4541_67.pt +3 -0
  25. conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_RHPA4259_7.pt +3 -0
  26. conf/legacy/P2PXML_dataset/P2PXML_Structure/graph_data/antigens_WITO4160_33.pt +3 -0
  27. conf/legacy/__MACOSX/P2PXML_dataset/._.DS_Store +0 -0
  28. conf/legacy/__MACOSX/P2PXML_dataset/._P2PXML_Structure +0 -0
  29. conf/legacy/__MACOSX/P2PXML_dataset/P2PXML-Seq/._README.md +0 -0
  30. conf/legacy/__MACOSX/P2PXML_dataset/P2PXML_Structure/._.DS_Store +0 -0
  31. conf/legacy/__MACOSX/P2PXML_dataset/P2PXML_Structure/._README.md +0 -0
  32. conf/legacy/incomplete_transfers/ESM1v-SVR.partial.pkl +3 -0
  33. conf/legacy/python_cache/ephod/__init__.cpython-310.pyc +0 -0
  34. conf/legacy/python_cache/ephod/__init__.cpython-311.pyc +0 -0
  35. conf/legacy/python_cache/model/__init__.cpython-310.pyc +0 -0
  36. conf/legacy/python_cache/training/__init__.cpython-310.pyc +0 -0
  37. conf/legacy/python_cache/training/__init__.cpython-311.pyc +0 -0
  38. conf/legacy/python_cache/training/nn_models.cpython-311.pyc +0 -0
  39. conf/legacy/torch_cache/hub/checkpoints/ESM1v-RLATtr.pt +3 -0
  40. conf/legacy/torch_cache/hub/checkpoints/esm1v_t33_650M_UR90S_1.pt +3 -0
  41. configuration.json +15 -0
  42. model/__init__.py +1 -0
  43. model/__pycache__/__init__.cpython-311.pyc +0 -0
  44. model/ephod/__init__.py +9 -0
  45. model/ephod/__pycache__/__init__.cpython-311.pyc +0 -0
  46. model/ephod/training/__init__.py +0 -0
  47. model/ephod/training/__pycache__/__init__.cpython-311.pyc +0 -0
  48. model/ephod/training/__pycache__/nn_models.cpython-311.pyc +0 -0
  49. model/ephod/training/nn_models.py +659 -0
  50. 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
+