Instructions to use OneScience-Group/Antibody_deep_learning with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- TF-Keras
How to use OneScience-Group/Antibody_deep_learning with TF-Keras:
# Note: 'keras<3.x' or 'tf_keras' must be installed (legacy) # See https://github.com/keras-team/tf-keras for more details. from huggingface_hub import from_pretrained_keras model = from_pretrained_keras("OneScience-Group/Antibody_deep_learning") - Notebooks
- Google Colab
- Kaggle
Upload folder using huggingface_hub
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +24 -0
- LICENSE +437 -0
- README.md +412 -0
- conf/config.json +16 -0
- config.json +68 -0
- model/BLOSUM62_with_deletion.Rdata +0 -0
- model/CNN/all_ab_pre_post.txt +0 -0
- model/CNN/c1.RDS +3 -0
- model/CNN/c1_test.RDS +3 -0
- model/CNN/c1_test_y.RDS +0 -0
- model/CNN/c1_train.RDS +3 -0
- model/CNN/c1_train_y.RDS +0 -0
- model/CNN/p1.RDS +3 -0
- model/CNN/p1_test.RDS +3 -0
- model/CNN/p1_test_y.RDS +0 -0
- model/CNN/p1_train.RDS +3 -0
- model/CNN/p1_train_y.RDS +0 -0
- model/GAN/seq_all.RDS +0 -0
- model/GAN/seq_all_encoded.RDS +3 -0
- model/original/antibody_deep_learning.Rmd +621 -0
- model/original/antibody_deep_learning.html +0 -0
- scripts/01_prepare_data_compat.R +110 -0
- scripts/02_cnn_inference.R +67 -0
- scripts/03_gan_inference.R +103 -0
- scripts/04_export_cnn_npz.R +25 -0
- scripts/05_train_cnn.py +83 -0
- scripts/06_export_gan_npz.R +25 -0
- scripts/07_train_gan.py +130 -0
- scripts/08_generate_from_trained_gan.py +138 -0
- scripts/tf_savedmodel_helper.py +11 -0
- weight/CNN/model_c1/saved_model.pb +3 -0
- weight/CNN/model_c1/variables/variables.data-00000-of-00001 +3 -0
- weight/CNN/model_c1/variables/variables.index +0 -0
- weight/CNN/model_p1/saved_model.pb +3 -0
- weight/CNN/model_p1/variables/variables.data-00000-of-00001 +3 -0
- weight/CNN/model_p1/variables/variables.index +0 -0
- weight/GAN/GAN_model_1/saved_model.pb +3 -0
- weight/GAN/GAN_model_1/variables/variables.data-00000-of-00001 +3 -0
- weight/GAN/GAN_model_1/variables/variables.index +0 -0
- weight/GAN/GAN_model_10/saved_model.pb +3 -0
- weight/GAN/GAN_model_10/variables/variables.data-00000-of-00001 +3 -0
- weight/GAN/GAN_model_10/variables/variables.index +0 -0
- weight/GAN/GAN_model_11/saved_model.pb +3 -0
- weight/GAN/GAN_model_11/variables/variables.data-00000-of-00001 +3 -0
- weight/GAN/GAN_model_11/variables/variables.index +0 -0
- weight/GAN/GAN_model_12/saved_model.pb +3 -0
- weight/GAN/GAN_model_12/variables/variables.data-00000-of-00001 +3 -0
- weight/GAN/GAN_model_12/variables/variables.index +0 -0
- weight/GAN/GAN_model_13/saved_model.pb +3 -0
- weight/GAN/GAN_model_13/variables/variables.data-00000-of-00001 +3 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,27 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
model/CNN/c1.RDS filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
model/CNN/c1_test.RDS filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
model/CNN/c1_train.RDS filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
model/CNN/p1.RDS filter=lfs diff=lfs merge=lfs -text
|
| 40 |
+
model/CNN/p1_test.RDS filter=lfs diff=lfs merge=lfs -text
|
| 41 |
+
model/CNN/p1_train.RDS filter=lfs diff=lfs merge=lfs -text
|
| 42 |
+
model/GAN/seq_all_encoded.RDS filter=lfs diff=lfs merge=lfs -text
|
| 43 |
+
weight/CNN/model_c1/variables/variables.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
|
| 44 |
+
weight/CNN/model_p1/variables/variables.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
|
| 45 |
+
weight/GAN/GAN_model_1/variables/variables.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
|
| 46 |
+
weight/GAN/GAN_model_10/variables/variables.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
|
| 47 |
+
weight/GAN/GAN_model_11/variables/variables.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
|
| 48 |
+
weight/GAN/GAN_model_12/variables/variables.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
|
| 49 |
+
weight/GAN/GAN_model_13/variables/variables.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
|
| 50 |
+
weight/GAN/GAN_model_14/variables/variables.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
|
| 51 |
+
weight/GAN/GAN_model_15/variables/variables.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
|
| 52 |
+
weight/GAN/GAN_model_2/variables/variables.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
|
| 53 |
+
weight/GAN/GAN_model_3/variables/variables.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
|
| 54 |
+
weight/GAN/GAN_model_4/variables/variables.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
|
| 55 |
+
weight/GAN/GAN_model_5/variables/variables.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
|
| 56 |
+
weight/GAN/GAN_model_6/variables/variables.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
|
| 57 |
+
weight/GAN/GAN_model_7/variables/variables.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
|
| 58 |
+
weight/GAN/GAN_model_8/variables/variables.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
|
| 59 |
+
weight/GAN/GAN_model_9/variables/variables.data-00000-of-00001 filter=lfs diff=lfs merge=lfs -text
|
LICENSE
ADDED
|
@@ -0,0 +1,437 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Attribution-NonCommercial-ShareAlike 4.0 International
|
| 2 |
+
|
| 3 |
+
=======================================================================
|
| 4 |
+
|
| 5 |
+
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
| 6 |
+
does not provide legal services or legal advice. Distribution of
|
| 7 |
+
Creative Commons public licenses does not create a lawyer-client or
|
| 8 |
+
other relationship. Creative Commons makes its licenses and related
|
| 9 |
+
information available on an "as-is" basis. Creative Commons gives no
|
| 10 |
+
warranties regarding its licenses, any material licensed under their
|
| 11 |
+
terms and conditions, or any related information. Creative Commons
|
| 12 |
+
disclaims all liability for damages resulting from their use to the
|
| 13 |
+
fullest extent possible.
|
| 14 |
+
|
| 15 |
+
Using Creative Commons Public Licenses
|
| 16 |
+
|
| 17 |
+
Creative Commons public licenses provide a standard set of terms and
|
| 18 |
+
conditions that creators and other rights holders may use to share
|
| 19 |
+
original works of authorship and other material subject to copyright
|
| 20 |
+
and certain other rights specified in the public license below. The
|
| 21 |
+
following considerations are for informational purposes only, are not
|
| 22 |
+
exhaustive, and do not form part of our licenses.
|
| 23 |
+
|
| 24 |
+
Considerations for licensors: Our public licenses are
|
| 25 |
+
intended for use by those authorized to give the public
|
| 26 |
+
permission to use material in ways otherwise restricted by
|
| 27 |
+
copyright and certain other rights. Our licenses are
|
| 28 |
+
irrevocable. Licensors should read and understand the terms
|
| 29 |
+
and conditions of the license they choose before applying it.
|
| 30 |
+
Licensors should also secure all rights necessary before
|
| 31 |
+
applying our licenses so that the public can reuse the
|
| 32 |
+
material as expected. Licensors should clearly mark any
|
| 33 |
+
material not subject to the license. This includes other CC-
|
| 34 |
+
licensed material, or material used under an exception or
|
| 35 |
+
limitation to copyright. More considerations for licensors:
|
| 36 |
+
wiki.creativecommons.org/Considerations_for_licensors
|
| 37 |
+
|
| 38 |
+
Considerations for the public: By using one of our public
|
| 39 |
+
licenses, a licensor grants the public permission to use the
|
| 40 |
+
licensed material under specified terms and conditions. If
|
| 41 |
+
the licensor's permission is not necessary for any reason--for
|
| 42 |
+
example, because of any applicable exception or limitation to
|
| 43 |
+
copyright--then that use is not regulated by the license. Our
|
| 44 |
+
licenses grant only permissions under copyright and certain
|
| 45 |
+
other rights that a licensor has authority to grant. Use of
|
| 46 |
+
the licensed material may still be restricted for other
|
| 47 |
+
reasons, including because others have copyright or other
|
| 48 |
+
rights in the material. A licensor may make special requests,
|
| 49 |
+
such as asking that all changes be marked or described.
|
| 50 |
+
Although not required by our licenses, you are encouraged to
|
| 51 |
+
respect those requests where reasonable. More considerations
|
| 52 |
+
for the public:
|
| 53 |
+
wiki.creativecommons.org/Considerations_for_licensees
|
| 54 |
+
|
| 55 |
+
=======================================================================
|
| 56 |
+
|
| 57 |
+
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
|
| 58 |
+
Public License
|
| 59 |
+
|
| 60 |
+
By exercising the Licensed Rights (defined below), You accept and agree
|
| 61 |
+
to be bound by the terms and conditions of this Creative Commons
|
| 62 |
+
Attribution-NonCommercial-ShareAlike 4.0 International Public License
|
| 63 |
+
("Public License"). To the extent this Public License may be
|
| 64 |
+
interpreted as a contract, You are granted the Licensed Rights in
|
| 65 |
+
consideration of Your acceptance of these terms and conditions, and the
|
| 66 |
+
Licensor grants You such rights in consideration of benefits the
|
| 67 |
+
Licensor receives from making the Licensed Material available under
|
| 68 |
+
these terms and conditions.
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
Section 1 -- Definitions.
|
| 72 |
+
|
| 73 |
+
a. Adapted Material means material subject to Copyright and Similar
|
| 74 |
+
Rights that is derived from or based upon the Licensed Material
|
| 75 |
+
and in which the Licensed Material is translated, altered,
|
| 76 |
+
arranged, transformed, or otherwise modified in a manner requiring
|
| 77 |
+
permission under the Copyright and Similar Rights held by the
|
| 78 |
+
Licensor. For purposes of this Public License, where the Licensed
|
| 79 |
+
Material is a musical work, performance, or sound recording,
|
| 80 |
+
Adapted Material is always produced where the Licensed Material is
|
| 81 |
+
synched in timed relation with a moving image.
|
| 82 |
+
|
| 83 |
+
b. Adapter's License means the license You apply to Your Copyright
|
| 84 |
+
and Similar Rights in Your contributions to Adapted Material in
|
| 85 |
+
accordance with the terms and conditions of this Public License.
|
| 86 |
+
|
| 87 |
+
c. BY-NC-SA Compatible License means a license listed at
|
| 88 |
+
creativecommons.org/compatiblelicenses, approved by Creative
|
| 89 |
+
Commons as essentially the equivalent of this Public License.
|
| 90 |
+
|
| 91 |
+
d. Copyright and Similar Rights means copyright and/or similar rights
|
| 92 |
+
closely related to copyright including, without limitation,
|
| 93 |
+
performance, broadcast, sound recording, and Sui Generis Database
|
| 94 |
+
Rights, without regard to how the rights are labeled or
|
| 95 |
+
categorized. For purposes of this Public License, the rights
|
| 96 |
+
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
| 97 |
+
Rights.
|
| 98 |
+
|
| 99 |
+
e. Effective Technological Measures means those measures that, in the
|
| 100 |
+
absence of proper authority, may not be circumvented under laws
|
| 101 |
+
fulfilling obligations under Article 11 of the WIPO Copyright
|
| 102 |
+
Treaty adopted on December 20, 1996, and/or similar international
|
| 103 |
+
agreements.
|
| 104 |
+
|
| 105 |
+
f. Exceptions and Limitations means fair use, fair dealing, and/or
|
| 106 |
+
any other exception or limitation to Copyright and Similar Rights
|
| 107 |
+
that applies to Your use of the Licensed Material.
|
| 108 |
+
|
| 109 |
+
g. License Elements means the license attributes listed in the name
|
| 110 |
+
of a Creative Commons Public License. The License Elements of this
|
| 111 |
+
Public License are Attribution, NonCommercial, and ShareAlike.
|
| 112 |
+
|
| 113 |
+
h. Licensed Material means the artistic or literary work, database,
|
| 114 |
+
or other material to which the Licensor applied this Public
|
| 115 |
+
License.
|
| 116 |
+
|
| 117 |
+
i. Licensed Rights means the rights granted to You subject to the
|
| 118 |
+
terms and conditions of this Public License, which are limited to
|
| 119 |
+
all Copyright and Similar Rights that apply to Your use of the
|
| 120 |
+
Licensed Material and that the Licensor has authority to license.
|
| 121 |
+
|
| 122 |
+
j. Licensor means the individual(s) or entity(ies) granting rights
|
| 123 |
+
under this Public License.
|
| 124 |
+
|
| 125 |
+
k. NonCommercial means not primarily intended for or directed towards
|
| 126 |
+
commercial advantage or monetary compensation. For purposes of
|
| 127 |
+
this Public License, the exchange of the Licensed Material for
|
| 128 |
+
other material subject to Copyright and Similar Rights by digital
|
| 129 |
+
file-sharing or similar means is NonCommercial provided there is
|
| 130 |
+
no payment of monetary compensation in connection with the
|
| 131 |
+
exchange.
|
| 132 |
+
|
| 133 |
+
l. Share means to provide material to the public by any means or
|
| 134 |
+
process that requires permission under the Licensed Rights, such
|
| 135 |
+
as reproduction, public display, public performance, distribution,
|
| 136 |
+
dissemination, communication, or importation, and to make material
|
| 137 |
+
available to the public including in ways that members of the
|
| 138 |
+
public may access the material from a place and at a time
|
| 139 |
+
individually chosen by them.
|
| 140 |
+
|
| 141 |
+
m. Sui Generis Database Rights means rights other than copyright
|
| 142 |
+
resulting from Directive 96/9/EC of the European Parliament and of
|
| 143 |
+
the Council of 11 March 1996 on the legal protection of databases,
|
| 144 |
+
as amended and/or succeeded, as well as other essentially
|
| 145 |
+
equivalent rights anywhere in the world.
|
| 146 |
+
|
| 147 |
+
n. You means the individual or entity exercising the Licensed Rights
|
| 148 |
+
under this Public License. Your has a corresponding meaning.
|
| 149 |
+
|
| 150 |
+
|
| 151 |
+
Section 2 -- Scope.
|
| 152 |
+
|
| 153 |
+
a. License grant.
|
| 154 |
+
|
| 155 |
+
1. Subject to the terms and conditions of this Public License,
|
| 156 |
+
the Licensor hereby grants You a worldwide, royalty-free,
|
| 157 |
+
non-sublicensable, non-exclusive, irrevocable license to
|
| 158 |
+
exercise the Licensed Rights in the Licensed Material to:
|
| 159 |
+
|
| 160 |
+
a. reproduce and Share the Licensed Material, in whole or
|
| 161 |
+
in part, for NonCommercial purposes only; and
|
| 162 |
+
|
| 163 |
+
b. produce, reproduce, and Share Adapted Material for
|
| 164 |
+
NonCommercial purposes only.
|
| 165 |
+
|
| 166 |
+
2. Exceptions and Limitations. For the avoidance of doubt, where
|
| 167 |
+
Exceptions and Limitations apply to Your use, this Public
|
| 168 |
+
License does not apply, and You do not need to comply with
|
| 169 |
+
its terms and conditions.
|
| 170 |
+
|
| 171 |
+
3. Term. The term of this Public License is specified in Section
|
| 172 |
+
6(a).
|
| 173 |
+
|
| 174 |
+
4. Media and formats; technical modifications allowed. The
|
| 175 |
+
Licensor authorizes You to exercise the Licensed Rights in
|
| 176 |
+
all media and formats whether now known or hereafter created,
|
| 177 |
+
and to make technical modifications necessary to do so. The
|
| 178 |
+
Licensor waives and/or agrees not to assert any right or
|
| 179 |
+
authority to forbid You from making technical modifications
|
| 180 |
+
necessary to exercise the Licensed Rights, including
|
| 181 |
+
technical modifications necessary to circumvent Effective
|
| 182 |
+
Technological Measures. For purposes of this Public License,
|
| 183 |
+
simply making modifications authorized by this Section 2(a)
|
| 184 |
+
(4) never produces Adapted Material.
|
| 185 |
+
|
| 186 |
+
5. Downstream recipients.
|
| 187 |
+
|
| 188 |
+
a. Offer from the Licensor -- Licensed Material. Every
|
| 189 |
+
recipient of the Licensed Material automatically
|
| 190 |
+
receives an offer from the Licensor to exercise the
|
| 191 |
+
Licensed Rights under the terms and conditions of this
|
| 192 |
+
Public License.
|
| 193 |
+
|
| 194 |
+
b. Additional offer from the Licensor -- Adapted Material.
|
| 195 |
+
Every recipient of Adapted Material from You
|
| 196 |
+
automatically receives an offer from the Licensor to
|
| 197 |
+
exercise the Licensed Rights in the Adapted Material
|
| 198 |
+
under the conditions of the Adapter's License You apply.
|
| 199 |
+
|
| 200 |
+
c. No downstream restrictions. You may not offer or impose
|
| 201 |
+
any additional or different terms or conditions on, or
|
| 202 |
+
apply any Effective Technological Measures to, the
|
| 203 |
+
Licensed Material if doing so restricts exercise of the
|
| 204 |
+
Licensed Rights by any recipient of the Licensed
|
| 205 |
+
Material.
|
| 206 |
+
|
| 207 |
+
6. No endorsement. Nothing in this Public License constitutes or
|
| 208 |
+
may be construed as permission to assert or imply that You
|
| 209 |
+
are, or that Your use of the Licensed Material is, connected
|
| 210 |
+
with, or sponsored, endorsed, or granted official status by,
|
| 211 |
+
the Licensor or others designated to receive attribution as
|
| 212 |
+
provided in Section 3(a)(1)(A)(i).
|
| 213 |
+
|
| 214 |
+
b. Other rights.
|
| 215 |
+
|
| 216 |
+
1. Moral rights, such as the right of integrity, are not
|
| 217 |
+
licensed under this Public License, nor are publicity,
|
| 218 |
+
privacy, and/or other similar personality rights; however, to
|
| 219 |
+
the extent possible, the Licensor waives and/or agrees not to
|
| 220 |
+
assert any such rights held by the Licensor to the limited
|
| 221 |
+
extent necessary to allow You to exercise the Licensed
|
| 222 |
+
Rights, but not otherwise.
|
| 223 |
+
|
| 224 |
+
2. Patent and trademark rights are not licensed under this
|
| 225 |
+
Public License.
|
| 226 |
+
|
| 227 |
+
3. To the extent possible, the Licensor waives any right to
|
| 228 |
+
collect royalties from You for the exercise of the Licensed
|
| 229 |
+
Rights, whether directly or through a collecting society
|
| 230 |
+
under any voluntary or waivable statutory or compulsory
|
| 231 |
+
licensing scheme. In all other cases the Licensor expressly
|
| 232 |
+
reserves any right to collect such royalties, including when
|
| 233 |
+
the Licensed Material is used other than for NonCommercial
|
| 234 |
+
purposes.
|
| 235 |
+
|
| 236 |
+
|
| 237 |
+
Section 3 -- License Conditions.
|
| 238 |
+
|
| 239 |
+
Your exercise of the Licensed Rights is expressly made subject to the
|
| 240 |
+
following conditions.
|
| 241 |
+
|
| 242 |
+
a. Attribution.
|
| 243 |
+
|
| 244 |
+
1. If You Share the Licensed Material (including in modified
|
| 245 |
+
form), You must:
|
| 246 |
+
|
| 247 |
+
a. retain the following if it is supplied by the Licensor
|
| 248 |
+
with the Licensed Material:
|
| 249 |
+
|
| 250 |
+
i. identification of the creator(s) of the Licensed
|
| 251 |
+
Material and any others designated to receive
|
| 252 |
+
attribution, in any reasonable manner requested by
|
| 253 |
+
the Licensor (including by pseudonym if
|
| 254 |
+
designated);
|
| 255 |
+
|
| 256 |
+
ii. a copyright notice;
|
| 257 |
+
|
| 258 |
+
iii. a notice that refers to this Public License;
|
| 259 |
+
|
| 260 |
+
iv. a notice that refers to the disclaimer of
|
| 261 |
+
warranties;
|
| 262 |
+
|
| 263 |
+
v. a URI or hyperlink to the Licensed Material to the
|
| 264 |
+
extent reasonably practicable;
|
| 265 |
+
|
| 266 |
+
b. indicate if You modified the Licensed Material and
|
| 267 |
+
retain an indication of any previous modifications; and
|
| 268 |
+
|
| 269 |
+
c. indicate the Licensed Material is licensed under this
|
| 270 |
+
Public License, and include the text of, or the URI or
|
| 271 |
+
hyperlink to, this Public License.
|
| 272 |
+
|
| 273 |
+
2. You may satisfy the conditions in Section 3(a)(1) in any
|
| 274 |
+
reasonable manner based on the medium, means, and context in
|
| 275 |
+
which You Share the Licensed Material. For example, it may be
|
| 276 |
+
reasonable to satisfy the conditions by providing a URI or
|
| 277 |
+
hyperlink to a resource that includes the required
|
| 278 |
+
information.
|
| 279 |
+
3. If requested by the Licensor, You must remove any of the
|
| 280 |
+
information required by Section 3(a)(1)(A) to the extent
|
| 281 |
+
reasonably practicable.
|
| 282 |
+
|
| 283 |
+
b. ShareAlike.
|
| 284 |
+
|
| 285 |
+
In addition to the conditions in Section 3(a), if You Share
|
| 286 |
+
Adapted Material You produce, the following conditions also apply.
|
| 287 |
+
|
| 288 |
+
1. The Adapter's License You apply must be a Creative Commons
|
| 289 |
+
license with the same License Elements, this version or
|
| 290 |
+
later, or a BY-NC-SA Compatible License.
|
| 291 |
+
|
| 292 |
+
2. You must include the text of, or the URI or hyperlink to, the
|
| 293 |
+
Adapter's License You apply. You may satisfy this condition
|
| 294 |
+
in any reasonable manner based on the medium, means, and
|
| 295 |
+
context in which You Share Adapted Material.
|
| 296 |
+
|
| 297 |
+
3. You may not offer or impose any additional or different terms
|
| 298 |
+
or conditions on, or apply any Effective Technological
|
| 299 |
+
Measures to, Adapted Material that restrict exercise of the
|
| 300 |
+
rights granted under the Adapter's License You apply.
|
| 301 |
+
|
| 302 |
+
|
| 303 |
+
Section 4 -- Sui Generis Database Rights.
|
| 304 |
+
|
| 305 |
+
Where the Licensed Rights include Sui Generis Database Rights that
|
| 306 |
+
apply to Your use of the Licensed Material:
|
| 307 |
+
|
| 308 |
+
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
| 309 |
+
to extract, reuse, reproduce, and Share all or a substantial
|
| 310 |
+
portion of the contents of the database for NonCommercial purposes
|
| 311 |
+
only;
|
| 312 |
+
|
| 313 |
+
b. if You include all or a substantial portion of the database
|
| 314 |
+
contents in a database in which You have Sui Generis Database
|
| 315 |
+
Rights, then the database in which You have Sui Generis Database
|
| 316 |
+
Rights (but not its individual contents) is Adapted Material,
|
| 317 |
+
including for purposes of Section 3(b); and
|
| 318 |
+
|
| 319 |
+
c. You must comply with the conditions in Section 3(a) if You Share
|
| 320 |
+
all or a substantial portion of the contents of the database.
|
| 321 |
+
|
| 322 |
+
For the avoidance of doubt, this Section 4 supplements and does not
|
| 323 |
+
replace Your obligations under this Public License where the Licensed
|
| 324 |
+
Rights include other Copyright and Similar Rights.
|
| 325 |
+
|
| 326 |
+
|
| 327 |
+
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
| 328 |
+
|
| 329 |
+
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
| 330 |
+
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
| 331 |
+
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
| 332 |
+
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
| 333 |
+
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
| 334 |
+
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
| 335 |
+
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
| 336 |
+
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
| 337 |
+
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
| 338 |
+
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
| 339 |
+
|
| 340 |
+
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
| 341 |
+
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
| 342 |
+
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
| 343 |
+
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
| 344 |
+
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
| 345 |
+
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
| 346 |
+
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
| 347 |
+
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
| 348 |
+
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
| 349 |
+
|
| 350 |
+
c. The disclaimer of warranties and limitation of liability provided
|
| 351 |
+
above shall be interpreted in a manner that, to the extent
|
| 352 |
+
possible, most closely approximates an absolute disclaimer and
|
| 353 |
+
waiver of all liability.
|
| 354 |
+
|
| 355 |
+
|
| 356 |
+
Section 6 -- Term and Termination.
|
| 357 |
+
|
| 358 |
+
a. This Public License applies for the term of the Copyright and
|
| 359 |
+
Similar Rights licensed here. However, if You fail to comply with
|
| 360 |
+
this Public License, then Your rights under this Public License
|
| 361 |
+
terminate automatically.
|
| 362 |
+
|
| 363 |
+
b. Where Your right to use the Licensed Material has terminated under
|
| 364 |
+
Section 6(a), it reinstates:
|
| 365 |
+
|
| 366 |
+
1. automatically as of the date the violation is cured, provided
|
| 367 |
+
it is cured within 30 days of Your discovery of the
|
| 368 |
+
violation; or
|
| 369 |
+
|
| 370 |
+
2. upon express reinstatement by the Licensor.
|
| 371 |
+
|
| 372 |
+
For the avoidance of doubt, this Section 6(b) does not affect any
|
| 373 |
+
right the Licensor may have to seek remedies for Your violations
|
| 374 |
+
of this Public License.
|
| 375 |
+
|
| 376 |
+
c. For the avoidance of doubt, the Licensor may also offer the
|
| 377 |
+
Licensed Material under separate terms or conditions or stop
|
| 378 |
+
distributing the Licensed Material at any time; however, doing so
|
| 379 |
+
will not terminate this Public License.
|
| 380 |
+
|
| 381 |
+
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
| 382 |
+
License.
|
| 383 |
+
|
| 384 |
+
|
| 385 |
+
Section 7 -- Other Terms and Conditions.
|
| 386 |
+
|
| 387 |
+
a. The Licensor shall not be bound by any additional or different
|
| 388 |
+
terms or conditions communicated by You unless expressly agreed.
|
| 389 |
+
|
| 390 |
+
b. Any arrangements, understandings, or agreements regarding the
|
| 391 |
+
Licensed Material not stated herein are separate from and
|
| 392 |
+
independent of the terms and conditions of this Public License.
|
| 393 |
+
|
| 394 |
+
|
| 395 |
+
Section 8 -- Interpretation.
|
| 396 |
+
|
| 397 |
+
a. For the avoidance of doubt, this Public License does not, and
|
| 398 |
+
shall not be interpreted to, reduce, limit, restrict, or impose
|
| 399 |
+
conditions on any use of the Licensed Material that could lawfully
|
| 400 |
+
be made without permission under this Public License.
|
| 401 |
+
|
| 402 |
+
b. To the extent possible, if any provision of this Public License is
|
| 403 |
+
deemed unenforceable, it shall be automatically reformed to the
|
| 404 |
+
minimum extent necessary to make it enforceable. If the provision
|
| 405 |
+
cannot be reformed, it shall be severed from this Public License
|
| 406 |
+
without affecting the enforceability of the remaining terms and
|
| 407 |
+
conditions.
|
| 408 |
+
|
| 409 |
+
c. No term or condition of this Public License will be waived and no
|
| 410 |
+
failure to comply consented to unless expressly agreed to by the
|
| 411 |
+
Licensor.
|
| 412 |
+
|
| 413 |
+
d. Nothing in this Public License constitutes or may be interpreted
|
| 414 |
+
as a limitation upon, or waiver of, any privileges and immunities
|
| 415 |
+
that apply to the Licensor or You, including from the legal
|
| 416 |
+
processes of any jurisdiction or authority.
|
| 417 |
+
|
| 418 |
+
=======================================================================
|
| 419 |
+
|
| 420 |
+
Creative Commons is not a party to its public
|
| 421 |
+
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
| 422 |
+
its public licenses to material it publishes and in those instances
|
| 423 |
+
will be considered the “Licensor.” The text of the Creative Commons
|
| 424 |
+
public licenses is dedicated to the public domain under the CC0 Public
|
| 425 |
+
Domain Dedication. Except for the limited purpose of indicating that
|
| 426 |
+
material is shared under a Creative Commons public license or as
|
| 427 |
+
otherwise permitted by the Creative Commons policies published at
|
| 428 |
+
creativecommons.org/policies, Creative Commons does not authorize the
|
| 429 |
+
use of the trademark "Creative Commons" or any other trademark or logo
|
| 430 |
+
of Creative Commons without its prior written consent including,
|
| 431 |
+
without limitation, in connection with any unauthorized modifications
|
| 432 |
+
to any of its public licenses or any other arrangements,
|
| 433 |
+
understandings, or agreements concerning use of licensed material. For
|
| 434 |
+
the avoidance of doubt, this paragraph does not form part of the
|
| 435 |
+
public licenses.
|
| 436 |
+
|
| 437 |
+
Creative Commons may be contacted at creativecommons.org.
|
README.md
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: cc-by-nc-sa-4.0
|
| 3 |
+
language:
|
| 4 |
+
- en
|
| 5 |
+
tags:
|
| 6 |
+
- OneScience
|
| 7 |
+
- life-science
|
| 8 |
+
- antibody
|
| 9 |
+
- deep-learning
|
| 10 |
+
- CNN
|
| 11 |
+
- GAN
|
| 12 |
+
frameworks: TensorFlow
|
| 13 |
+
---
|
| 14 |
+
|
| 15 |
+
<p align="center">
|
| 16 |
+
<strong>
|
| 17 |
+
<span style="font-size: 30px;">Antibody Deep Learning</span>
|
| 18 |
+
</strong>
|
| 19 |
+
</p>
|
| 20 |
+
|
| 21 |
+
# 模型介绍
|
| 22 |
+
|
| 23 |
+
Antibody Deep Learning 是一个面向抗体 CDR3 序列分析的深度学习复现项目,主要包含两个任务:
|
| 24 |
+
|
| 25 |
+
1. 使用卷积神经网络 CNN 预测 CTLA-4 和 PD-1 抗体序列是否为 binder。
|
| 26 |
+
2. 使用生成对抗网络 GAN 生成面向 CTLA-4 和 PD-1 的合成 CDR3K/CDR3H 序列。
|
| 27 |
+
|
| 28 |
+
原始项目以 RMarkdown 为主入口,通过 R `keras` / `reticulate` 调用 Python TensorFlow 后端。本仓库保留官方数据、官方已训练权重和原始说明,同时在 `scripts/` 目录中提供适配当前 TensorFlow/DCU 环境的等价运行脚本。
|
| 29 |
+
|
| 30 |
+
论文:
|
| 31 |
+
|
| 32 |
+
Predicting antibody binders and generating synthetic antibodies using deep learning
|
| 33 |
+
|
| 34 |
+
https://doi.org/10.1080/19420862.2022.2069075
|
| 35 |
+
|
| 36 |
+
# 模型描述
|
| 37 |
+
|
| 38 |
+
本项目包含两类模型。
|
| 39 |
+
|
| 40 |
+
| 模型 | 任务 | 输入 | 输出 |
|
| 41 |
+
| --- | --- | --- | --- |
|
| 42 |
+
| CNN | 判断 CTLA-4 / PD-1 抗体序列是否为 binder | CDR3K + CDR3H,经 padding 和 BLOSUM62 编码后为 `36 x 22 x 1` | 二分类概率,non-binder / binder |
|
| 43 |
+
| GAN | 生成 CDR3 序列 | 100 维随机噪声 | `32 x 22 x 1` 的氨基酸图像,再解码为 CDR3 序列 |
|
| 44 |
+
|
| 45 |
+
CNN 分别训练两个模型:
|
| 46 |
+
|
| 47 |
+
| 模型路径 | 靶点 | 说明 |
|
| 48 |
+
| --- | --- | --- |
|
| 49 |
+
| `weight/CNN/model_c1` | CTLA-4 | 官方已训练 CNN SavedModel |
|
| 50 |
+
| `weight/CNN/model_p1` | PD-1 | 官方已训练 CNN SavedModel |
|
| 51 |
+
|
| 52 |
+
GAN 共 15 个生成器,对应不同 target / chain / V gene 组合:
|
| 53 |
+
|
| 54 |
+
| 编号 | 官方权重路径 | 分组 |
|
| 55 |
+
| --- | --- | --- |
|
| 56 |
+
| 1 | `weight/GAN/GAN_model_1` | CTLA4 heavy IGHV3-33*01 |
|
| 57 |
+
| 2 | `weight/GAN/GAN_model_2` | CTLA4 heavy IGHV1-18*04 |
|
| 58 |
+
| 3 | `weight/GAN/GAN_model_3` | CTLA4 heavy IGHV3-20*01 |
|
| 59 |
+
| 4 | `weight/GAN/GAN_model_4` | CTLA4 heavy IGHV4-39*01 |
|
| 60 |
+
| 5 | `weight/GAN/GAN_model_5` | CTLA4 light IGKV3-20*01 |
|
| 61 |
+
| 6 | `weight/GAN/GAN_model_6` | CTLA4 light IGKV1D-39*01 |
|
| 62 |
+
| 7 | `weight/GAN/GAN_model_7` | CTLA4 light IGKV1-17*01 |
|
| 63 |
+
| 8 | `weight/GAN/GAN_model_8` | CTLA4 light IGKV1-16*01 |
|
| 64 |
+
| 9 | `weight/GAN/GAN_model_9` | PD1 heavy IGHV4-4*07 |
|
| 65 |
+
| 10 | `weight/GAN/GAN_model_10` | PD1 heavy IGHV3-33*03 |
|
| 66 |
+
| 11 | `weight/GAN/GAN_model_11` | PD1 heavy IGHV1-18*04 |
|
| 67 |
+
| 12 | `weight/GAN/GAN_model_12` | PD1 light IGKV1-17*01 |
|
| 68 |
+
| 13 | `weight/GAN/GAN_model_13` | PD1 light IGKV1-6*02 |
|
| 69 |
+
| 14 | `weight/GAN/GAN_model_14` | PD1 light IGKV3-15*01 |
|
| 70 |
+
| 15 | `weight/GAN/GAN_model_15` | PD1 light IGKV1-9*01 |
|
| 71 |
+
|
| 72 |
+
# 适用场景
|
| 73 |
+
|
| 74 |
+
| 场景 | 说明 |
|
| 75 |
+
| --- | --- |
|
| 76 |
+
| CTLA-4 / PD-1 binder 分类 | 使用仓库内置 CNN 模型,对 CDR3K + CDR3H 序列进行 BLOSUM62 编码后预测 binder / non-binder,可复现论文中的抗体结合分类任务。 |
|
| 77 |
+
| 合成抗体 CDR3 序列生成 | 使用 15 个 GAN generator,按 CTLA-4 / PD-1、heavy / light chain 及 V gene 分组生成合成 CDR3 序列。 |
|
| 78 |
+
| 抗体工程方法复现 | 复现论文中将抗体 CDR3 序列转为二维“抗体图像”、训练 CNN 分类器、使用 GAN 学习序列分布的核心流程。 |
|
| 79 |
+
| 解释性分析和序列优化参考 | 结合原始 RMarkdown 中的模型评估、ROC 分析和 in silico mutagenesis 思路,分析影响 binder 分类的重要 CDR3 位点。 |
|
| 80 |
+
|
| 81 |
+
# 使用说明
|
| 82 |
+
|
| 83 |
+
## 1. OneCode 使用
|
| 84 |
+
|
| 85 |
+
可通过 OneCode 在线环境体验智能化一键式 AI4S 编程:
|
| 86 |
+
|
| 87 |
+
[点击体验智能化一键式 AI4S 编程](https://web-2069360198568017922-iaaj.ksai.scnet.cn:58043/home)
|
| 88 |
+
|
| 89 |
+
## 2. 手动安装使用
|
| 90 |
+
|
| 91 |
+
### 硬件要求
|
| 92 |
+
|
| 93 |
+
- CPU 可用于数据预处理、小规模推理和连通性验证。
|
| 94 |
+
- 推荐使用 GPU/DCU 进行训练和批量推理。
|
| 95 |
+
- DCU 用户需要加载与当前集群匹配的 DTK 模块,并先验证 TensorFlow 基础算子可正常运行。
|
| 96 |
+
|
| 97 |
+
## 安装运行环境
|
| 98 |
+
|
| 99 |
+
### DCU 环境
|
| 100 |
+
|
| 101 |
+
```bash
|
| 102 |
+
# 请首先激活 DTK 及 CONDA
|
| 103 |
+
conda create -n onescience311 python=3.11 -y
|
| 104 |
+
conda activate onescience311
|
| 105 |
+
# 支持uv安装
|
| 106 |
+
pip install onescience[bio] -i http://mirrors.onescience.ai:3141/pypi/simple/ --trusted-host mirrors.onescience.ai
|
| 107 |
+
```
|
| 108 |
+
|
| 109 |
+
### 环境说明
|
| 110 |
+
|
| 111 |
+
- 搭建好 OneScience 基础环境后,用户还需额外准备 R 运行环境和 R 包。安装示例:
|
| 112 |
+
|
| 113 |
+
```bash
|
| 114 |
+
module load R/3.6.3-gcc-7.3.1
|
| 115 |
+
mkdir -p ~/R/library/3.6 ~/tmp
|
| 116 |
+
export R_LIBS_USER=$HOME/R/library/3.6
|
| 117 |
+
```
|
| 118 |
+
|
| 119 |
+
如果集群中的 R 模块路径不是 `/public/software/apps/R-3.6.3/bin`,请先用下面命令确认实际路径,并同步替换后续命令中的 `PATH`:
|
| 120 |
+
|
| 121 |
+
```bash
|
| 122 |
+
which Rscript
|
| 123 |
+
Rscript --version
|
| 124 |
+
```
|
| 125 |
+
由于 R 3.6.3 版本较老,部分 CRAN 最新包不再兼容,建议使用 CRAN 历史快照安装依赖:
|
| 126 |
+
```bash
|
| 127 |
+
env -i \
|
| 128 |
+
HOME=$HOME \
|
| 129 |
+
USER=$USER \
|
| 130 |
+
PATH=/usr/bin:/bin:/public/software/apps/R-3.6.3/bin \
|
| 131 |
+
R_LIBS_USER=$HOME/R/library/3.6 \
|
| 132 |
+
TMPDIR=$HOME/tmp \
|
| 133 |
+
Rscript -e 'options(repos=c(CRAN="https://packagemanager.posit.co/cran/2023-10-20")); install.packages(c("reticulate","dplyr","ggplot2","readr","tidyr","purrr","tibble","stringr","forcats","mltools","caret","pROC","remotes"), type="source")'
|
| 134 |
+
```
|
| 135 |
+
安装完成后验证 R 包可正常加载:
|
| 136 |
+
|
| 137 |
+
```bash
|
| 138 |
+
env -i \
|
| 139 |
+
HOME=$HOME \
|
| 140 |
+
USER=$USER \
|
| 141 |
+
PATH=/usr/bin:/bin:/public/software/apps/R-3.6.3/bin \
|
| 142 |
+
R_LIBS_USER=$HOME/R/library/3.6 \
|
| 143 |
+
TMPDIR=$HOME/tmp \
|
| 144 |
+
Rscript -e 'library(reticulate); library(caret); library(pROC); cat("R packages OK\n")'
|
| 145 |
+
```
|
| 146 |
+
后续运行 R 脚本时仍需显式传入 `R_LIBS_USER=$HOME/R/library/3.6`,否则可能出现 `there is no package called ...` 的报错。
|
| 147 |
+
|
| 148 |
+
- 运行过程中遇到 TensorFlow 相关问题,可以使用平台提供的适配版 TensorFlow wheel,并加载匹配的 DTK 模块。例如:
|
| 149 |
+
|
| 150 |
+
```bash
|
| 151 |
+
# 1. 下载平台 TensorFlow wheel
|
| 152 |
+
wget --content-disposition 'https://download.sourcefind.cn:65024/file/4/tensorflow/DAS1.8/tensorflow-2.13.1+das.opt1.dtk2604-cp311-cp311-manylinux_2_28_x86_64.whl'
|
| 153 |
+
|
| 154 |
+
# 2. 安装 TensorFlow
|
| 155 |
+
pip install tensorflow*
|
| 156 |
+
|
| 157 |
+
# 3. 加载对应 DTK
|
| 158 |
+
module load compiler/dtk/26.04
|
| 159 |
+
```
|
| 160 |
+
|
| 161 |
+
# 快速开始
|
| 162 |
+
|
| 163 |
+
## 1. 下载模型包
|
| 164 |
+
|
| 165 |
+
```bash
|
| 166 |
+
hf download OneScience-Group/Antibody_deep_learning --local-dir ./Antibody_deep_learning
|
| 167 |
+
cd Antibody_deep_learning
|
| 168 |
+
```
|
| 169 |
+
|
| 170 |
+
# 数据和权重说明
|
| 171 |
+
|
| 172 |
+
## 内置数据
|
| 173 |
+
|
| 174 |
+
| 路径 | 说明 |
|
| 175 |
+
| --- | --- |
|
| 176 |
+
| `model/CNN/all_ab_pre_post.txt` | CNN 原始输入表,包含 CDR3K、CDR3H、antigen、pre/post frequency、fold change 等信息。 |
|
| 177 |
+
| `model/BLOSUM62_with_deletion.Rdata` | BLOSUM62 编码矩阵,包含 20 种氨基酸、`X` 和 gap `-`。 |
|
| 178 |
+
| `model/CNN/c1.RDS` / `model/CNN/p1.RDS` | CTLA-4 / PD-1 的 train/test 划分对象。 |
|
| 179 |
+
| `model/CNN/*train*.RDS` / `model/CNN/*test*.RDS` | CNN 训练和测试张量及 one-hot 标签。 |
|
| 180 |
+
| `model/GAN/seq_all.RDS` | GAN 预处理 CDR3 序列,按 target/chain/V gene 分组。 |
|
| 181 |
+
| `model/GAN/seq_all_encoded.RDS` | GAN BLOSUM62 编码后的训练张量列表。 |
|
| 182 |
+
|
| 183 |
+
## 内置权重
|
| 184 |
+
|
| 185 |
+
| 路径 | 说明 |
|
| 186 |
+
| --- | --- |
|
| 187 |
+
| `weight/CNN/model_c1` | 官方 CTLA-4 CNN SavedModel。 |
|
| 188 |
+
| `weight/CNN/model_p1` | 官方 PD-1 CNN SavedModel。 |
|
| 189 |
+
| `weight/GAN/GAN_model_1` 到 `weight/GAN/GAN_model_15` | 官方 15 个 GAN generator SavedModel。 |
|
| 190 |
+
|
| 191 |
+
# 推理示例
|
| 192 |
+
|
| 193 |
+
## 1. CNN 模型推理
|
| 194 |
+
|
| 195 |
+
用途:加载 `weight/CNN/model_c1` 和 `weight/CNN/model_p1`,实现 CTLA-4 / PD-1 binder 分类。
|
| 196 |
+
|
| 197 |
+
```bash
|
| 198 |
+
env -i \
|
| 199 |
+
HOME=$HOME \
|
| 200 |
+
USER=$USER \
|
| 201 |
+
PATH=$PATH:/public/software/apps/R-3.6.3/bin \
|
| 202 |
+
LD_LIBRARY_PATH=$LD_LIBRARY_PATH \
|
| 203 |
+
R_LIBS_USER=$HOME/R/library/3.6 \
|
| 204 |
+
RETICULATE_PYTHON=$(which python) \
|
| 205 |
+
PYTHONNOUSERSITE=1 \
|
| 206 |
+
TMPDIR=$HOME/tmp \
|
| 207 |
+
Rscript scripts/02_cnn_inference.R
|
| 208 |
+
```
|
| 209 |
+
|
| 210 |
+
输出文件:
|
| 211 |
+
|
| 212 |
+
```text
|
| 213 |
+
model/CNN/c1_tf218_inference_result.RDS
|
| 214 |
+
model/CNN/p1_tf218_inference_result.RDS
|
| 215 |
+
```
|
| 216 |
+
|
| 217 |
+
## 2. GAN 模型推理
|
| 218 |
+
|
| 219 |
+
用途:加载 `weight/GAN/GAN_model_1` 到 `weight/GAN/GAN_model_15`,每个模型生成 100 条 CDR3 序列。
|
| 220 |
+
|
| 221 |
+
```bash
|
| 222 |
+
env -i \
|
| 223 |
+
HOME=$HOME \
|
| 224 |
+
USER=$USER \
|
| 225 |
+
PATH=$PATH:/public/software/apps/R-3.6.3/bin \
|
| 226 |
+
LD_LIBRARY_PATH=$LD_LIBRARY_PATH \
|
| 227 |
+
R_LIBS_USER=$HOME/R/library/3.6 \
|
| 228 |
+
RETICULATE_PYTHON=$(which python) \
|
| 229 |
+
PYTHONNOUSERSITE=1 \
|
| 230 |
+
TMPDIR=$HOME/tmp \
|
| 231 |
+
Rscript scripts/03_gan_inference.R
|
| 232 |
+
```
|
| 233 |
+
|
| 234 |
+
输出文件:
|
| 235 |
+
|
| 236 |
+
```text
|
| 237 |
+
model/GAN/gen_seq_tf218.RDS
|
| 238 |
+
model/GAN/gen_seq_tf218.tsv
|
| 239 |
+
```
|
| 240 |
+
|
| 241 |
+
# 训练示例
|
| 242 |
+
|
| 243 |
+
## 1. 数据预处理
|
| 244 |
+
|
| 245 |
+
用途:生成 CNN/GAN 中间训练数据。
|
| 246 |
+
|
| 247 |
+
```bash
|
| 248 |
+
env -i \
|
| 249 |
+
HOME=$HOME \
|
| 250 |
+
USER=$USER \
|
| 251 |
+
PATH=$PATH:/public/software/apps/R-3.6.3/bin \
|
| 252 |
+
R_LIBS_USER=$HOME/R/library/3.6 \
|
| 253 |
+
TMPDIR=$HOME/tmp \
|
| 254 |
+
Rscript scripts/01_prepare_data_compat.R
|
| 255 |
+
```
|
| 256 |
+
|
| 257 |
+
输出包括:
|
| 258 |
+
|
| 259 |
+
```text
|
| 260 |
+
model/CNN/c1_train.RDS
|
| 261 |
+
model/CNN/c1_test.RDS
|
| 262 |
+
model/CNN/p1_train.RDS
|
| 263 |
+
model/CNN/p1_test.RDS
|
| 264 |
+
model/GAN/seq_all_encoded.RDS
|
| 265 |
+
```
|
| 266 |
+
|
| 267 |
+
## 2. CNN 训练
|
| 268 |
+
|
| 269 |
+
先导出 Python 可读数据:
|
| 270 |
+
|
| 271 |
+
```bash
|
| 272 |
+
env -i \
|
| 273 |
+
HOME=$HOME \
|
| 274 |
+
USER=$USER \
|
| 275 |
+
PATH=$PATH:/public/software/apps/R-3.6.3/bin \
|
| 276 |
+
LD_LIBRARY_PATH=$LD_LIBRARY_PATH \
|
| 277 |
+
R_LIBS_USER=$HOME/R/library/3.6 \
|
| 278 |
+
RETICULATE_PYTHON=$(which python) \
|
| 279 |
+
PYTHONNOUSERSITE=1 \
|
| 280 |
+
TMPDIR=$HOME/tmp \
|
| 281 |
+
Rscript scripts/04_export_cnn_npz.R
|
| 282 |
+
```
|
| 283 |
+
|
| 284 |
+
训练:
|
| 285 |
+
|
| 286 |
+
```bash
|
| 287 |
+
python scripts/05_train_cnn.py
|
| 288 |
+
```
|
| 289 |
+
|
| 290 |
+
输出:
|
| 291 |
+
|
| 292 |
+
```text
|
| 293 |
+
weight/CNN/model_c1_dcu
|
| 294 |
+
weight/CNN/model_p1_dcu
|
| 295 |
+
weight/CNN/model_c1_dcu_eval.npz
|
| 296 |
+
weight/CNN/model_p1_dcu_eval.npz
|
| 297 |
+
```
|
| 298 |
+
|
| 299 |
+
## 3. GAN 训练
|
| 300 |
+
|
| 301 |
+
先导出 Python 可读数据:
|
| 302 |
+
|
| 303 |
+
```bash
|
| 304 |
+
env -i \
|
| 305 |
+
HOME=$HOME \
|
| 306 |
+
USER=$USER \
|
| 307 |
+
PATH=$PATH:/public/software/apps/R-3.6.3/bin \
|
| 308 |
+
LD_LIBRARY_PATH=$LD_LIBRARY_PATH \
|
| 309 |
+
R_LIBS_USER=$HOME/R/library/3.6 \
|
| 310 |
+
RETICULATE_PYTHON=$(which python) \
|
| 311 |
+
PYTHONNOUSERSITE=1 \
|
| 312 |
+
TMPDIR=$HOME/tmp \
|
| 313 |
+
Rscript scripts/06_export_gan_npz.R
|
| 314 |
+
```
|
| 315 |
+
|
| 316 |
+
单模型 smoke test:
|
| 317 |
+
|
| 318 |
+
```bash
|
| 319 |
+
python scripts/07_train_gan.py --model-id 1 --rounds 20
|
| 320 |
+
```
|
| 321 |
+
|
| 322 |
+
单模型完整训练:
|
| 323 |
+
|
| 324 |
+
```bash
|
| 325 |
+
python scripts/07_train_gan.py --model-id 1 --rounds 100
|
| 326 |
+
```
|
| 327 |
+
|
| 328 |
+
全量 15 个模型训练:
|
| 329 |
+
|
| 330 |
+
```bash
|
| 331 |
+
for i in $(seq 1 15); do
|
| 332 |
+
echo "===== training GAN model $i ====="
|
| 333 |
+
python scripts/07_train_gan.py --model-id $i --rounds 100
|
| 334 |
+
done
|
| 335 |
+
```
|
| 336 |
+
|
| 337 |
+
输出:
|
| 338 |
+
|
| 339 |
+
```text
|
| 340 |
+
weight/GAN/GAN_model_1_dcu 到 weight/GAN/GAN_model_15_dcu
|
| 341 |
+
weight/GAN/GAN_model_1_dcu_loss.npz 到 weight/GAN/GAN_model_15_dcu_loss.npz
|
| 342 |
+
```
|
| 343 |
+
|
| 344 |
+
## 4. 使用新训练 GAN 模型生成序列
|
| 345 |
+
|
| 346 |
+
单模型:
|
| 347 |
+
|
| 348 |
+
```bash
|
| 349 |
+
python scripts/08_generate_from_trained_gan.py \
|
| 350 |
+
--model-id 1 \
|
| 351 |
+
--n-seq 100 \
|
| 352 |
+
--out-tsv model/GAN/gen_seq_trained_model_1_dcu.tsv
|
| 353 |
+
```
|
| 354 |
+
|
| 355 |
+
全量:
|
| 356 |
+
|
| 357 |
+
```bash
|
| 358 |
+
python scripts/08_generate_from_trained_gan.py \
|
| 359 |
+
--model-id 0 \
|
| 360 |
+
--n-seq 100 \
|
| 361 |
+
--out-tsv model/GAN/gen_seq_trained_all_dcu.tsv
|
| 362 |
+
```
|
| 363 |
+
|
| 364 |
+
生成统计:
|
| 365 |
+
|
| 366 |
+
```bash
|
| 367 |
+
python - <<'PY'
|
| 368 |
+
import pandas as pd
|
| 369 |
+
import re
|
| 370 |
+
|
| 371 |
+
df = pd.read_csv("model/GAN/gen_seq_trained_all_dcu.tsv", sep="\t")
|
| 372 |
+
df["length"] = df["aa"].astype(str).str.len()
|
| 373 |
+
df["valid"] = df["aa"].astype(str).str.fullmatch(r"[ARNDCQEGHILKMFPSTWYV]+")
|
| 374 |
+
|
| 375 |
+
summary = (
|
| 376 |
+
df.groupby(["model_id", "group"])
|
| 377 |
+
.agg(
|
| 378 |
+
n_seq=("aa", "size"),
|
| 379 |
+
n_unique=("aa", "nunique"),
|
| 380 |
+
min_len=("length", "min"),
|
| 381 |
+
median_len=("length", "median"),
|
| 382 |
+
max_len=("length", "max"),
|
| 383 |
+
valid_rate=("valid", "mean"),
|
| 384 |
+
)
|
| 385 |
+
.reset_index()
|
| 386 |
+
)
|
| 387 |
+
|
| 388 |
+
print(summary.to_string(index=False))
|
| 389 |
+
summary.to_csv("model/GAN/gen_seq_trained_all_dcu_summary.tsv", sep="\t", index=False)
|
| 390 |
+
PY
|
| 391 |
+
```
|
| 392 |
+
|
| 393 |
+
|
| 394 |
+
# OneScience 官方信息
|
| 395 |
+
|
| 396 |
+
| 平台 | OneScience 主仓库 | Skills 仓库 |
|
| 397 |
+
| --- | --- | --- |
|
| 398 |
+
| Gitee | https://gitee.com/onescience-ai/onescience | https://gitee.com/onescience-ai/oneskills |
|
| 399 |
+
| GitHub | https://github.com/onescience-ai/OneScience | https://github.com/onescience-ai/oneskills |
|
| 400 |
+
|
| 401 |
+
# 引用与许可证
|
| 402 |
+
|
| 403 |
+
- Antibody Deep Learning 原始论文:[Predicting antibody binders and generating synthetic antibodies using deep learning](https://doi.org/10.1080/19420862.2022.2069075)。
|
| 404 |
+
|
| 405 |
+
- 论文信息:Yoong Wearn Lim, Adam S. Adler, David S. Johnson. *mAbs* 14(1):2069075, 2022. DOI: [10.1080/19420862.2022.2069075](https://doi.org/10.1080/19420862.2022.2069075)。
|
| 406 |
+
|
| 407 |
+
- 原始代码和数据来源:[ywlim/Antibody_deep_learning](https://github.com/ywlim/Antibody_deep_learning)。论文数据可用性说明中给出了该仓库地址。
|
| 408 |
+
|
| 409 |
+
- 相关源码使用 Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International(CC BY-NC-SA 4.0),详见仓库根目录 `LICENSE`。使用、修改和再发布本项目内容时,请遵循署名、非商业使用和相同方式共享等许可要求。
|
| 410 |
+
|
| 411 |
+
- 如果在科研工作中使用本项目,建议同时引用原论文以及 OneScience 相关信息。
|
| 412 |
+
|
conf/config.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"project_root": ".",
|
| 3 |
+
"data_dir": "model",
|
| 4 |
+
"weight_dir": "weight",
|
| 5 |
+
"script_dir": "scripts",
|
| 6 |
+
"cnn": {
|
| 7 |
+
"raw_table": "model/CNN/all_ab_pre_post.txt",
|
| 8 |
+
"ctla4_model": "weight/CNN/model_c1",
|
| 9 |
+
"pd1_model": "weight/CNN/model_p1"
|
| 10 |
+
},
|
| 11 |
+
"gan": {
|
| 12 |
+
"sequence_groups": "model/GAN/seq_all.RDS",
|
| 13 |
+
"encoded_groups": "model/GAN/seq_all_encoded.RDS",
|
| 14 |
+
"pretrained_model_pattern": "weight/GAN/GAN_model_{model_id}"
|
| 15 |
+
}
|
| 16 |
+
}
|
config.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_name": "Antibody Deep Learning",
|
| 3 |
+
"framework": "TensorFlow",
|
| 4 |
+
"task": "antibody-binder-prediction-and-cdr3-generation",
|
| 5 |
+
"description": "Predict CTLA-4 and PD-1 antibody binders with CNN models and generate synthetic CDR3K/CDR3H antibody sequences with GAN models.",
|
| 6 |
+
"entry_points": {
|
| 7 |
+
"prepare_data": "scripts/01_prepare_data_compat.R",
|
| 8 |
+
"cnn_inference": "scripts/02_cnn_inference.R",
|
| 9 |
+
"gan_inference": "scripts/03_gan_inference.R",
|
| 10 |
+
"export_cnn_npz": "scripts/04_export_cnn_npz.R",
|
| 11 |
+
"train_cnn": "scripts/05_train_cnn.py",
|
| 12 |
+
"export_gan_npz": "scripts/06_export_gan_npz.R",
|
| 13 |
+
"train_gan": "scripts/07_train_gan.py",
|
| 14 |
+
"generate_from_trained_gan": "scripts/08_generate_from_trained_gan.py"
|
| 15 |
+
},
|
| 16 |
+
"source_package": "model",
|
| 17 |
+
"config": "conf/config.json",
|
| 18 |
+
"data": {
|
| 19 |
+
"blosum62": "model/BLOSUM62_with_deletion.Rdata",
|
| 20 |
+
"cnn_raw": "model/CNN/all_ab_pre_post.txt",
|
| 21 |
+
"cnn_preprocessed": [
|
| 22 |
+
"model/CNN/c1.RDS",
|
| 23 |
+
"model/CNN/c1_train.RDS",
|
| 24 |
+
"model/CNN/c1_train_y.RDS",
|
| 25 |
+
"model/CNN/c1_test.RDS",
|
| 26 |
+
"model/CNN/c1_test_y.RDS",
|
| 27 |
+
"model/CNN/p1.RDS",
|
| 28 |
+
"model/CNN/p1_train.RDS",
|
| 29 |
+
"model/CNN/p1_train_y.RDS",
|
| 30 |
+
"model/CNN/p1_test.RDS",
|
| 31 |
+
"model/CNN/p1_test_y.RDS"
|
| 32 |
+
],
|
| 33 |
+
"gan_preprocessed": [
|
| 34 |
+
"model/GAN/seq_all.RDS",
|
| 35 |
+
"model/GAN/seq_all_encoded.RDS"
|
| 36 |
+
]
|
| 37 |
+
},
|
| 38 |
+
"weight_dir": {
|
| 39 |
+
"cnn": [
|
| 40 |
+
"weight/CNN/model_c1",
|
| 41 |
+
"weight/CNN/model_p1"
|
| 42 |
+
],
|
| 43 |
+
"gan": [
|
| 44 |
+
"weight/GAN/GAN_model_1",
|
| 45 |
+
"weight/GAN/GAN_model_2",
|
| 46 |
+
"weight/GAN/GAN_model_3",
|
| 47 |
+
"weight/GAN/GAN_model_4",
|
| 48 |
+
"weight/GAN/GAN_model_5",
|
| 49 |
+
"weight/GAN/GAN_model_6",
|
| 50 |
+
"weight/GAN/GAN_model_7",
|
| 51 |
+
"weight/GAN/GAN_model_8",
|
| 52 |
+
"weight/GAN/GAN_model_9",
|
| 53 |
+
"weight/GAN/GAN_model_10",
|
| 54 |
+
"weight/GAN/GAN_model_11",
|
| 55 |
+
"weight/GAN/GAN_model_12",
|
| 56 |
+
"weight/GAN/GAN_model_13",
|
| 57 |
+
"weight/GAN/GAN_model_14",
|
| 58 |
+
"weight/GAN/GAN_model_15"
|
| 59 |
+
]
|
| 60 |
+
},
|
| 61 |
+
"runtime": {
|
| 62 |
+
"python": "3.11",
|
| 63 |
+
"tensorflow": "2.13.1 or compatible TensorFlow/DCU build",
|
| 64 |
+
"r": "3.6.3",
|
| 65 |
+
"dcu_module": "compiler/dtk/26.04"
|
| 66 |
+
},
|
| 67 |
+
"license": "CC-BY-NC-SA-4.0"
|
| 68 |
+
}
|
model/BLOSUM62_with_deletion.Rdata
ADDED
|
Binary file (4.42 kB). View file
|
|
|
model/CNN/all_ab_pre_post.txt
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model/CNN/c1.RDS
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e59c46595666a0994e3e40fbc0c80ee3b2f9122dd53a831fd12630a603497b58
|
| 3 |
+
size 222118
|
model/CNN/c1_test.RDS
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:62a084b2334f59446ef143a66c90eeb3a750321631b01fc746f52363ff599036
|
| 3 |
+
size 341118
|
model/CNN/c1_test_y.RDS
ADDED
|
Binary file (711 Bytes). View file
|
|
|
model/CNN/c1_train.RDS
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:04f38f357ba1966d503426a0df1e1c27eea0f23ca8ddffc41d57e54c815c9600
|
| 3 |
+
size 1272878
|
model/CNN/c1_train_y.RDS
ADDED
|
Binary file (2.15 kB). View file
|
|
|
model/CNN/p1.RDS
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:3d827c02e36783e581fda4a0a5ec73d9208e32babb44ca09a6af634c5fe2925c
|
| 3 |
+
size 229334
|
model/CNN/p1_test.RDS
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4db04aec944c7f994f1d0be1b40c0591cdf03741202b6bd90f174b8e3745ed06
|
| 3 |
+
size 365015
|
model/CNN/p1_test_y.RDS
ADDED
|
Binary file (806 Bytes). View file
|
|
|
model/CNN/p1_train.RDS
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7211b5dbdd331e6d4cc7fca4cc22e5f38bcf6a117487e722ed3f4ca8e8048bd9
|
| 3 |
+
size 1349366
|
model/CNN/p1_train_y.RDS
ADDED
|
Binary file (2.46 kB). View file
|
|
|
model/GAN/seq_all.RDS
ADDED
|
Binary file (3.94 kB). View file
|
|
|
model/GAN/seq_all_encoded.RDS
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:265d5c9a2a08dc4d1e771eb85ff09da910d1efde96f4d60a914963339bb67b22
|
| 3 |
+
size 123418
|
model/original/antibody_deep_learning.Rmd
ADDED
|
@@ -0,0 +1,621 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: "Predicting antibody binders and generating synthetic antibodies using deep learning"
|
| 3 |
+
author: "Yoong Wearn Lim"
|
| 4 |
+
date: "2022/02/18"
|
| 5 |
+
output:
|
| 6 |
+
html_document:
|
| 7 |
+
toc: true
|
| 8 |
+
toc_float:
|
| 9 |
+
collapsed: false
|
| 10 |
+
toc_depth: 5
|
| 11 |
+
code_folding: hide
|
| 12 |
+
theme: united
|
| 13 |
+
---
|
| 14 |
+
|
| 15 |
+
## Goals
|
| 16 |
+
|
| 17 |
+
1. To predict binder and non-binder antibodies to CTLA-4 and PD-1, using Convolutional Neural Network (CNN).
|
| 18 |
+
2. To generate synthetic antibody sequences (CDR3K + CDR3H) to CTLA-4 and PD-1, using Generative Adversarial Network (GAN).
|
| 19 |
+
|
| 20 |
+
## Settings
|
| 21 |
+
|
| 22 |
+
Ensure that python3 and tensorflow version 2.4.0 are used.
|
| 23 |
+
|
| 24 |
+
```{r global_options, message = FALSE}
|
| 25 |
+
knitr::opts_chunk$set(warning=FALSE, message=FALSE)
|
| 26 |
+
|
| 27 |
+
library(reticulate)
|
| 28 |
+
use_virtualenv("py3-virtualenv")
|
| 29 |
+
py_config()
|
| 30 |
+
library(keras)
|
| 31 |
+
library(tidyverse)
|
| 32 |
+
library(PepTools)
|
| 33 |
+
library(mltools)
|
| 34 |
+
library(caret)
|
| 35 |
+
library(pROC)
|
| 36 |
+
|
| 37 |
+
filter = dplyr::filter
|
| 38 |
+
select = dplyr::select
|
| 39 |
+
theme_set(theme_bw())
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
## Predicting binders vs. non-binders (CNN)
|
| 43 |
+
|
| 44 |
+
### Prepare sequences
|
| 45 |
+
|
| 46 |
+
Here we prepare CDR3K + CDR3H amino acid sequences for both targets:
|
| 47 |
+
|
| 48 |
+
1. Load all pre- and post-FACS sorted sequences.
|
| 49 |
+
2. Randomize the order of the sequences.
|
| 50 |
+
3. Pad CDR3K and CDR3H with "-" so all sequences have the same length.
|
| 51 |
+
4. Define binders and non-binders.
|
| 52 |
+
* Binders: post/pre fold change >= 1.8, post-sort frequency >= 0.01
|
| 53 |
+
* Non-binders: post/pre fold change < 1, pre-sort frequency >= 0.01
|
| 54 |
+
5. Split sequences into training and testing sets.
|
| 55 |
+
|
| 56 |
+
```{r}
|
| 57 |
+
all <- read_delim("CNN/all_ab_pre_post.txt", delim = "\t")
|
| 58 |
+
|
| 59 |
+
# shuffle order of data frame
|
| 60 |
+
set.seed(42)
|
| 61 |
+
rows <- sample(nrow(all))
|
| 62 |
+
all <- all[rows, ]
|
| 63 |
+
|
| 64 |
+
# padding
|
| 65 |
+
max_k <- max(nchar(all$CDR3K)) # 11
|
| 66 |
+
max_h <- max(nchar(all$CDR3H)) # 25
|
| 67 |
+
|
| 68 |
+
all$paddedh <- gsub("\\s", "-", format(all$CDR3H, width = max_h))
|
| 69 |
+
all$paddedk <- gsub("\\s", "-", format(all$CDR3K, width = max_k))
|
| 70 |
+
all$lengthh <- nchar(all$CDR3H)
|
| 71 |
+
all$lengthk <- nchar(all$CDR3K)
|
| 72 |
+
all$padded <- paste0(all$paddedk, all$paddedh)
|
| 73 |
+
|
| 74 |
+
# filter for only unique sequences
|
| 75 |
+
all2 <- all %>%
|
| 76 |
+
group_by(padded) %>%
|
| 77 |
+
top_n(1, wt = post)
|
| 78 |
+
all2 <- all2[!duplicated(all2$padded), ]
|
| 79 |
+
|
| 80 |
+
# define binders/non-binders
|
| 81 |
+
all2 <- all2 %>%
|
| 82 |
+
ungroup() %>%
|
| 83 |
+
mutate(enriched = ifelse((fc >= 1.8 & post >= 0.01), 1,
|
| 84 |
+
ifelse(fc < 1 & pre >= 0.01, 0, "ambi")))
|
| 85 |
+
|
| 86 |
+
all2 <- filter(all2, enriched != "ambi")
|
| 87 |
+
|
| 88 |
+
# split test train
|
| 89 |
+
split_train_test <- function(antigenx) {
|
| 90 |
+
mini <- all2 %>% filter(antigen == antigenx)
|
| 91 |
+
set.seed(22)
|
| 92 |
+
trainIndex <- createDataPartition(mini$enriched, p = .8,
|
| 93 |
+
list = FALSE,
|
| 94 |
+
times = 1)
|
| 95 |
+
df_train <- mini[ trainIndex, ]
|
| 96 |
+
df_test <- mini[-trainIndex, ]
|
| 97 |
+
|
| 98 |
+
my_list <- list(train = df_train, test = df_test)
|
| 99 |
+
return(my_list)
|
| 100 |
+
}
|
| 101 |
+
c1 <- split_train_test("CTLA-4")
|
| 102 |
+
p1 <- split_train_test("PD-1")
|
| 103 |
+
|
| 104 |
+
saveRDS(c1, file = "CNN/c1.RDS")
|
| 105 |
+
saveRDS(p1, file = "CNN/p1.RDS")
|
| 106 |
+
```
|
| 107 |
+
|
| 108 |
+
### Visualize test train split
|
| 109 |
+
|
| 110 |
+
```{r, fig.width = 5, fig.height=3}
|
| 111 |
+
c1$train$type <- "Train"
|
| 112 |
+
c1$test$type <- "Test"
|
| 113 |
+
c1_both <- bind_rows(c1$train, c1$test)
|
| 114 |
+
|
| 115 |
+
p1$train$type <- "Train"
|
| 116 |
+
p1$test$type <- "Test"
|
| 117 |
+
p1_both <- bind_rows(p1$train, p1$test)
|
| 118 |
+
|
| 119 |
+
both <- bind_rows(c1_both, p1_both)
|
| 120 |
+
count <- data.frame(table(both$antigen, both$type, both$enriched))
|
| 121 |
+
names(count) <- c("antigen", "type", "binder", "freq")
|
| 122 |
+
count$type <- factor(count$type, levels = c("Train", "Test"))
|
| 123 |
+
|
| 124 |
+
count$binder <- as.numeric(as.character(count$binder))
|
| 125 |
+
count$binder[count$binder == 0] <- "Non-binder"
|
| 126 |
+
count$binder[count$binder == 1] <- "Binder"
|
| 127 |
+
|
| 128 |
+
ggplot(count, aes(x = type, y = freq, fill = binder, label = freq)) +
|
| 129 |
+
facet_wrap(~ antigen, scales = "free_y") +
|
| 130 |
+
geom_col(position = "stack") +
|
| 131 |
+
geom_text(position = position_stack(vjust = .5)) +
|
| 132 |
+
theme_bw() +
|
| 133 |
+
labs(y = "# sequences")
|
| 134 |
+
|
| 135 |
+
```
|
| 136 |
+
|
| 137 |
+
### Encoding
|
| 138 |
+
|
| 139 |
+
Encode sequences into numerical matrices (images) using BLOSUM62 scores.
|
| 140 |
+
|
| 141 |
+
```{r}
|
| 142 |
+
# function to encode peptides
|
| 143 |
+
load(file = "BLOSUM62_with_deletion.Rdata")
|
| 144 |
+
|
| 145 |
+
pep_encode_blosum <- function(pep) {
|
| 146 |
+
bl62_prob <- BLOSUM62
|
| 147 |
+
p_mat <- pep %>% pep_mat
|
| 148 |
+
n_peps <- length(pep)
|
| 149 |
+
l_peps <- nchar(pep[1])
|
| 150 |
+
l_enc <- ncol(bl62_prob)
|
| 151 |
+
o_tensor <- array(data = NA, dim = c(n_peps, l_peps, l_enc))
|
| 152 |
+
for (i in 1:n_peps) {
|
| 153 |
+
pep_i_residues <- p_mat[i, ]
|
| 154 |
+
pep_img <- bl62_prob[pep_i_residues, ]
|
| 155 |
+
o_tensor[i, , ] <- pep_img
|
| 156 |
+
}
|
| 157 |
+
return(o_tensor)
|
| 158 |
+
}
|
| 159 |
+
```
|
| 160 |
+
|
| 161 |
+
|
| 162 |
+
```{r}
|
| 163 |
+
# CTLA-4
|
| 164 |
+
c1_train <- pep_encode_blosum(c1$train$padded)
|
| 165 |
+
c1_test <- pep_encode_blosum(c1$test$padded)
|
| 166 |
+
|
| 167 |
+
# reshape
|
| 168 |
+
c1_train <- array_reshape(c1_train, c(nrow(c1_train), ncol(c1_train), 22, 1))
|
| 169 |
+
c1_test <- array_reshape(c1_test, c(nrow(c1_test), ncol(c1_test), 22, 1))
|
| 170 |
+
|
| 171 |
+
num_classes <- 2
|
| 172 |
+
|
| 173 |
+
c1_train_y <- c1$train %>% pull(enriched) %>% array %>% keras::to_categorical(num_classes = num_classes)
|
| 174 |
+
c1_test_y <- c1$test %>% pull(enriched) %>% array %>% keras::to_categorical(num_classes = num_classes)
|
| 175 |
+
|
| 176 |
+
# PD-1
|
| 177 |
+
p1_train <- pep_encode_blosum(p1$train$padded)
|
| 178 |
+
p1_test <- pep_encode_blosum(p1$test$padded)
|
| 179 |
+
|
| 180 |
+
# reshape
|
| 181 |
+
p1_train <- array_reshape(p1_train, c(nrow(p1_train), ncol(p1_train), 22, 1))
|
| 182 |
+
p1_test <- array_reshape(p1_test, c(nrow(p1_test), ncol(p1_test), 22, 1))
|
| 183 |
+
|
| 184 |
+
num_classes <- 2
|
| 185 |
+
|
| 186 |
+
p1_train_y <- p1$train %>% pull(enriched) %>% array %>% keras::to_categorical(num_classes = num_classes)
|
| 187 |
+
p1_test_y <- p1$test %>% pull(enriched) %>% array %>% keras::to_categorical(num_classes = num_classes)
|
| 188 |
+
|
| 189 |
+
saveRDS(p1_train, file = "CNN/p1_train.RDS")
|
| 190 |
+
saveRDS(p1_test, file = "CNN/p1_test.RDS")
|
| 191 |
+
saveRDS(p1_train_y, file = "CNN/p1_train_y.RDS")
|
| 192 |
+
saveRDS(p1_test_y, file = "CNN/p1_test_y.RDS")
|
| 193 |
+
saveRDS(c1_train, file = "CNN/c1_train.RDS")
|
| 194 |
+
saveRDS(c1_test, file = "CNN/c1_test.RDS")
|
| 195 |
+
saveRDS(c1_train_y, file = "CNN/c1_train_y.RDS")
|
| 196 |
+
saveRDS(c1_test_y, file = "CNN/c1_test_y.RDS")
|
| 197 |
+
```
|
| 198 |
+
|
| 199 |
+
### CNN models
|
| 200 |
+
|
| 201 |
+
Here we build CNN models to predict binders vs. non-binders. We train the CTLA-4 model and PD-1 model separately.
|
| 202 |
+
|
| 203 |
+
```{r}
|
| 204 |
+
model <- keras_model_sequential() %>%
|
| 205 |
+
layer_conv_2d(filters = 64, kernel_size = c(3, 3),
|
| 206 |
+
activation = "relu", input_shape = c(36, 22, 1), padding = "same") %>%
|
| 207 |
+
layer_dropout(rate = 0.5) %>%
|
| 208 |
+
layer_max_pooling_2d(pool_size = c(2, 2), padding = "same") %>%
|
| 209 |
+
layer_conv_2d(filters = 32, kernel_size = c(3, 4),
|
| 210 |
+
activation = "relu", padding = "same") %>%
|
| 211 |
+
layer_dropout(rate = 0.4) %>%
|
| 212 |
+
layer_max_pooling_2d(pool_size = c(2, 2), padding = "same") %>%
|
| 213 |
+
layer_conv_2d(filters = 32, kernel_size = c(4, 4),
|
| 214 |
+
activation = "relu", padding = "same") %>%
|
| 215 |
+
layer_dropout(rate = 0.3) %>%
|
| 216 |
+
layer_flatten() %>%
|
| 217 |
+
layer_dense(units = 64, activation = "relu") %>%
|
| 218 |
+
layer_dropout(rate = 0.4) %>%
|
| 219 |
+
layer_dense(units = 2, activation = "softmax")
|
| 220 |
+
summary(model)
|
| 221 |
+
|
| 222 |
+
# duplicate model
|
| 223 |
+
# note we have to use "clone_model", can't just do model_c1 <- model (this is just a pointer)
|
| 224 |
+
model_c1 <- clone_model(model)
|
| 225 |
+
model_p1 <- clone_model(model)
|
| 226 |
+
|
| 227 |
+
# need to compile each one separately
|
| 228 |
+
model_c1 %>% compile(
|
| 229 |
+
loss = 'categorical_crossentropy',
|
| 230 |
+
optimizer = 'adam',
|
| 231 |
+
metrics = 'accuracy'
|
| 232 |
+
)
|
| 233 |
+
|
| 234 |
+
model_p1 %>% compile(
|
| 235 |
+
loss = 'categorical_crossentropy',
|
| 236 |
+
optimizer = 'adam',
|
| 237 |
+
metrics = 'accuracy'
|
| 238 |
+
)
|
| 239 |
+
|
| 240 |
+
epochs <- 30
|
| 241 |
+
batch_size <- 50
|
| 242 |
+
validation_split <- 0.2
|
| 243 |
+
|
| 244 |
+
# fit models
|
| 245 |
+
c1_hist <- model_c1 %>% fit(
|
| 246 |
+
c1_train, c1_train_y,
|
| 247 |
+
epochs = epochs,
|
| 248 |
+
batch_size = batch_size,
|
| 249 |
+
validation_split = validation_split)
|
| 250 |
+
|
| 251 |
+
p1_hist <- model_p1 %>% fit(
|
| 252 |
+
p1_train, p1_train_y,
|
| 253 |
+
epochs = epochs,
|
| 254 |
+
batch_size = batch_size,
|
| 255 |
+
validation_split = validation_split)
|
| 256 |
+
|
| 257 |
+
model_c1 %>% save_model_tf("CNN/model_c1")
|
| 258 |
+
model_p1 %>% save_model_tf("CNN/model_p1")
|
| 259 |
+
```
|
| 260 |
+
|
| 261 |
+
### Prediction
|
| 262 |
+
|
| 263 |
+
Now that the models are fully trained, we evaluate them using the reserved 20% test sets.
|
| 264 |
+
|
| 265 |
+
#### CTLA-4 model
|
| 266 |
+
|
| 267 |
+
```{r, fig.width=2.5, fig.height=2.5}
|
| 268 |
+
pred_c1 <- model_c1 %>% predict_proba(c1_test) %>% as.data.frame()
|
| 269 |
+
names(pred_c1) <- c("nb_prob", "b_prob")
|
| 270 |
+
y_real_c1 <- c1_test_y %>% apply(1,function(x){ return( which(x==1) - 1) })
|
| 271 |
+
y_pred_c1 <- model_c1 %>% keras::predict_classes(c1_test)
|
| 272 |
+
|
| 273 |
+
perf_c1 <- model_c1 %>% evaluate(c1_test, c1_test_y)
|
| 274 |
+
acc_c1 <- perf_c1[[2]] %>% round(3) * 100
|
| 275 |
+
mcc_c1 <- mltools::mcc(preds = as.vector(y_pred_c1), actuals = as.vector(y_real_c1)) %>% round(2)
|
| 276 |
+
|
| 277 |
+
results_c1 <- tibble(y_real = y_real_c1,
|
| 278 |
+
y_pred = y_pred_c1,
|
| 279 |
+
b_prob = pred_c1$b_prob)
|
| 280 |
+
|
| 281 |
+
results_c1 <- results_c1 %>%
|
| 282 |
+
mutate(class = ifelse(y_real == 0 & y_pred == 0, "TN",
|
| 283 |
+
ifelse(y_real == 0 & y_pred == 1, "FP",
|
| 284 |
+
ifelse(y_real == 1 & y_pred == 1, "TP",
|
| 285 |
+
ifelse(y_real == 1 & y_pred == 0, "FN", NA)))))
|
| 286 |
+
|
| 287 |
+
res_c1 <- table(results_c1[, 1:2]) %>%
|
| 288 |
+
as.data.frame() %>%
|
| 289 |
+
mutate(y_real = as.character(y_real),
|
| 290 |
+
y_pred = as.character(y_pred))
|
| 291 |
+
|
| 292 |
+
res_c1$y_real[res_c1$y_real == 0] <- "Non-binder"
|
| 293 |
+
res_c1$y_pred[res_c1$y_pred == 0] <- "Non-binder"
|
| 294 |
+
res_c1$y_real[res_c1$y_real == 1] <- "Binder"
|
| 295 |
+
res_c1$y_pred[res_c1$y_pred == 1] <- "Binder"
|
| 296 |
+
res_c1$class <- c("TN", "FN", "FP", "TP")
|
| 297 |
+
|
| 298 |
+
# generate confusion matrix
|
| 299 |
+
ggplot(res_c1, aes(x = y_pred, y = y_real, label = Freq, color = class)) +
|
| 300 |
+
geom_text(size = 7) +
|
| 301 |
+
geom_tile(color = "black", fill = NA) +
|
| 302 |
+
theme(axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1, color = "black"),
|
| 303 |
+
axis.text.y = element_text(color = "black"),
|
| 304 |
+
axis.ticks = element_blank(),
|
| 305 |
+
panel.grid.major = element_blank(),
|
| 306 |
+
panel.grid.minor = element_blank()) +
|
| 307 |
+
labs(y = "Measured (FACS)", x = "Predicted", title = "CTLA-4",
|
| 308 |
+
subtitle = paste0("Accuracy=", acc_c1, "\nMCC=", mcc_c1)) +
|
| 309 |
+
scale_x_discrete(expand = c(0, 0)) +
|
| 310 |
+
scale_y_discrete(expand = c(0, 0)) +
|
| 311 |
+
guides(color = FALSE)
|
| 312 |
+
|
| 313 |
+
# density plot showing binder probabilities
|
| 314 |
+
ggplot(results_c1, aes(x = b_prob, color = class)) +
|
| 315 |
+
geom_density(fill = NA) +
|
| 316 |
+
theme(axis.text = element_text(color = "black"),
|
| 317 |
+
panel.grid.major = element_blank(),
|
| 318 |
+
panel.grid.minor = element_blank()) +
|
| 319 |
+
labs(y = "Density", x = "Binder probability", title = "CTLA-4", color = "Type")
|
| 320 |
+
|
| 321 |
+
# roc curve
|
| 322 |
+
roc_obj_c1 <- roc(y_real_c1, results_c1$b_prob)
|
| 323 |
+
plot.roc(roc_obj_c1, print.auc = TRUE, main = "CTLA-4 ROC curve")
|
| 324 |
+
```
|
| 325 |
+
|
| 326 |
+
#### PD-1 model
|
| 327 |
+
|
| 328 |
+
```{r, fig.width=2.5, fig.height=2.5}
|
| 329 |
+
pred_p1 <- model_p1 %>% predict_proba(p1_test) %>% as.data.frame()
|
| 330 |
+
names(pred_p1) <- c("nb_prob", "b_prob")
|
| 331 |
+
y_real_p1 <- p1_test_y %>% apply(1,function(x){ return( which(x==1) - 1) })
|
| 332 |
+
y_pred_p1 <- model_p1 %>% keras::predict_classes(p1_test)
|
| 333 |
+
|
| 334 |
+
perf_p1 <- model_p1 %>% evaluate(p1_test, p1_test_y)
|
| 335 |
+
acc_p1 <- perf_p1[[2]] %>% round(3) * 100
|
| 336 |
+
mcc_p1 <- mltools::mcc(preds = as.vector(y_pred_p1), actuals = as.vector(y_real_p1)) %>% round(2)
|
| 337 |
+
|
| 338 |
+
results_p1 <- tibble(y_real = y_real_p1,
|
| 339 |
+
y_pred = y_pred_p1,
|
| 340 |
+
b_prob = pred_p1$b_prob)
|
| 341 |
+
|
| 342 |
+
results_p1 <- results_p1 %>%
|
| 343 |
+
mutate(class = ifelse(y_real == 0 & y_pred == 0, "TN",
|
| 344 |
+
ifelse(y_real == 0 & y_pred == 1, "FP",
|
| 345 |
+
ifelse(y_real == 1 & y_pred == 1, "TP",
|
| 346 |
+
ifelse(y_real == 1 & y_pred == 0, "FN", NA)))))
|
| 347 |
+
|
| 348 |
+
res_p1 <- table(results_p1[, 1:2]) %>%
|
| 349 |
+
as.data.frame() %>%
|
| 350 |
+
mutate(y_real = as.character(y_real),
|
| 351 |
+
y_pred = as.character(y_pred))
|
| 352 |
+
|
| 353 |
+
res_p1$y_real[res_p1$y_real == 0] <- "Non-binder"
|
| 354 |
+
res_p1$y_pred[res_p1$y_pred == 0] <- "Non-binder"
|
| 355 |
+
res_p1$y_real[res_p1$y_real == 1] <- "Binder"
|
| 356 |
+
res_p1$y_pred[res_p1$y_pred == 1] <- "Binder"
|
| 357 |
+
res_p1$class <- c("TN", "FN", "FP", "TP")
|
| 358 |
+
|
| 359 |
+
# generate confusion matrix
|
| 360 |
+
ggplot(res_p1, aes(x = y_pred, y = y_real, label = Freq, color = class)) +
|
| 361 |
+
geom_text(size = 7) +
|
| 362 |
+
geom_tile(color = "black", fill = NA) +
|
| 363 |
+
theme(axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1, color = "black"),
|
| 364 |
+
axis.text.y = element_text(color = "black"),
|
| 365 |
+
axis.ticks = element_blank(),
|
| 366 |
+
panel.grid.major = element_blank(),
|
| 367 |
+
panel.grid.minor = element_blank()) +
|
| 368 |
+
labs(y = "Measured (FACS)", x = "Predicted", title = "PD-1",
|
| 369 |
+
subtitle = paste0("Accuracy=", acc_p1, "\nMCC=", mcc_p1)) +
|
| 370 |
+
scale_x_discrete(expand = c(0, 0)) +
|
| 371 |
+
scale_y_discrete(expand = c(0, 0)) +
|
| 372 |
+
guides(color = FALSE)
|
| 373 |
+
|
| 374 |
+
# density plot showing binder probabilities
|
| 375 |
+
ggplot(results_p1, aes(x = b_prob, color = class)) +
|
| 376 |
+
geom_density(fill = NA) +
|
| 377 |
+
theme(axis.text = element_text(color = "black"),
|
| 378 |
+
panel.grid.major = element_blank(),
|
| 379 |
+
panel.grid.minor = element_blank()) +
|
| 380 |
+
labs(y = "Density", x = "Binder probability", title = "PD-1", color = "Type")
|
| 381 |
+
|
| 382 |
+
# roc curve
|
| 383 |
+
roc_obj_p1 <- roc(y_real_p1, results_p1$b_prob)
|
| 384 |
+
plot.roc(roc_obj_p1, print.auc = TRUE, main = "PD-1 ROC curve")
|
| 385 |
+
```
|
| 386 |
+
|
| 387 |
+
## Generating synthetic sequences (GAN)
|
| 388 |
+
|
| 389 |
+
Here we build GAN models to generate anti-CTLA-4 and anti-PD-1 CDR3 sequences. We will train a separate model for each V gene, and we will train light and heavy chain separately. In total, we will train 15 models.
|
| 390 |
+
|
| 391 |
+
### Prepare sequences
|
| 392 |
+
|
| 393 |
+
Previously, we annotated full length light and heavy chain sequences using [ANARCI](http://opig.stats.ox.ac.uk/webapps/newsabdab/sabpred/anarci/).
|
| 394 |
+
|
| 395 |
+
We used the AHo numbering scheme, which is based on the structural alignments of the 3D structures of the antibody variable regions. A quote from https://plueckthun.bioc.uzh.ch/antibody/Numbering/NumFrame.html:
|
| 396 |
+
|
| 397 |
+
> An important difference to the numbering scheme presented here (AHo) is that in the IMGT scheme insertions and deletions "grow" unidirectionally, as in the original Chothia definition (Chothia & Lesk, 1987), while in the AHo scheme, insertions and deletions are placed symmetrically around the key position marked in yellow. Furthermore, length variations in CDR 1 and CDR 2 are represented by a single gap in IMGT and by one or two gaps in AHo.
|
| 398 |
+
|
| 399 |
+
After AHo annotation, the CDR3 regions were extracted from the sequences. All sequences now have the same sequence length.
|
| 400 |
+
|
| 401 |
+
### Encoding
|
| 402 |
+
|
| 403 |
+
Here we encode the pre-processed CDR3 sequences into "images".
|
| 404 |
+
|
| 405 |
+
```{r}
|
| 406 |
+
# pre-processed CDR3 sequences, by target, chain, and V gene
|
| 407 |
+
seq_all <- readRDS(file = "GAN/seq_all.RDS")
|
| 408 |
+
|
| 409 |
+
encoded <- list()
|
| 410 |
+
length(encoded) <- 15
|
| 411 |
+
names(encoded) <- names(seq_all)
|
| 412 |
+
|
| 413 |
+
for (i in 1:15) {
|
| 414 |
+
seq_encoded <- pep_encode_blosum(seq_all[[i]])
|
| 415 |
+
# reshape
|
| 416 |
+
encoded[[i]] <- array_reshape(seq_encoded, c(nrow(seq_encoded), ncol(seq_encoded), 22, 1))
|
| 417 |
+
}
|
| 418 |
+
saveRDS(encoded, file = "GAN/seq_all_encoded.RDS")
|
| 419 |
+
|
| 420 |
+
head(str(encoded))
|
| 421 |
+
# encoded is a list with 15 items
|
| 422 |
+
str(encoded[[1]])
|
| 423 |
+
# num [1:307, 1:32, 1:22, 1] 0.267 0.533 0.533 0.533 0.533 ...
|
| 424 |
+
```
|
| 425 |
+
|
| 426 |
+
### GAN models
|
| 427 |
+
|
| 428 |
+
32 positions (row), 22 possible amino acids (including X and -) (columns).
|
| 429 |
+
|
| 430 |
+
```{r}
|
| 431 |
+
h <- 32; w <- 22; c <- 1; l <- 100
|
| 432 |
+
loss_list <- list()
|
| 433 |
+
|
| 434 |
+
# 1 model for each target/chain/V gene
|
| 435 |
+
# 15 models total
|
| 436 |
+
for (modelx in 1:15) {
|
| 437 |
+
# generator network
|
| 438 |
+
gi <- layer_input(shape = l)
|
| 439 |
+
|
| 440 |
+
go <- gi %>% layer_dense(units = 16 * 11 * 128) %>%
|
| 441 |
+
layer_activation_leaky_relu() %>%
|
| 442 |
+
layer_reshape(target_shape = c(16, 11, 128)) %>%
|
| 443 |
+
layer_conv_2d(filters = 64,
|
| 444 |
+
kernel_size = c(2, 2),
|
| 445 |
+
padding = "same") %>%
|
| 446 |
+
layer_activation_leaky_relu() %>%
|
| 447 |
+
layer_conv_2d_transpose(filters = 32,
|
| 448 |
+
kernel_size = c(2, 2),
|
| 449 |
+
strides = 2,
|
| 450 |
+
padding = "same") %>%
|
| 451 |
+
layer_activation_leaky_relu() %>%
|
| 452 |
+
layer_conv_2d(filters = 128,
|
| 453 |
+
kernel_size = c(5, 6),
|
| 454 |
+
padding = "same") %>%
|
| 455 |
+
layer_activation_leaky_relu() %>%
|
| 456 |
+
layer_conv_2d(filters = 1,
|
| 457 |
+
kernel_size = c(6, 6),
|
| 458 |
+
activation = "tanh",
|
| 459 |
+
padding = "same")
|
| 460 |
+
g <- keras_model(gi, go)
|
| 461 |
+
summary(g)
|
| 462 |
+
|
| 463 |
+
# discriminator network
|
| 464 |
+
di <- layer_input(shape = c(h, w, c))
|
| 465 |
+
|
| 466 |
+
do <- di %>%
|
| 467 |
+
layer_conv_2d(filters = 96, kernel_size = 3) %>%
|
| 468 |
+
layer_activation_leaky_relu() %>%
|
| 469 |
+
layer_flatten() %>%
|
| 470 |
+
layer_dropout(rate = 0.3) %>%
|
| 471 |
+
layer_dense(units = 1, activation = "sigmoid")
|
| 472 |
+
|
| 473 |
+
d <- keras_model(di, do)
|
| 474 |
+
|
| 475 |
+
summary(d)
|
| 476 |
+
|
| 477 |
+
# compile discriminator
|
| 478 |
+
d %>% compile(optimizer = "rmsprop",
|
| 479 |
+
loss = "binary_crossentropy")
|
| 480 |
+
|
| 481 |
+
# freeze weights and compile
|
| 482 |
+
freeze_weights(d)
|
| 483 |
+
|
| 484 |
+
gani <- layer_input(shape = l)
|
| 485 |
+
gano <- gani %>% g %>% d
|
| 486 |
+
gan <- keras_model(gani, gano)
|
| 487 |
+
gan %>% compile(optimizer = "rmsprop",
|
| 488 |
+
loss = "binary_crossentropy")
|
| 489 |
+
summary(gan)
|
| 490 |
+
|
| 491 |
+
start <- 1; dloss <- NULL; gloss <- NULL
|
| 492 |
+
|
| 493 |
+
# use batch size = 20, train 100 rounds
|
| 494 |
+
b <- 20
|
| 495 |
+
for (i in 1:100) {
|
| 496 |
+
# random noise
|
| 497 |
+
noise <- matrix(rnorm(b * l), nrow = b, ncol = l)
|
| 498 |
+
|
| 499 |
+
fake <- g %>% predict(noise)
|
| 500 |
+
|
| 501 |
+
# combine real and fake images
|
| 502 |
+
stop <- start + b - 1
|
| 503 |
+
# 50 random real images
|
| 504 |
+
rowx <- sample(nrow(encoded[[modelx]]), size = b)
|
| 505 |
+
real <- encoded[[modelx]][rowx,,, , drop = FALSE] # no need to reshape since we use drop=FALSE
|
| 506 |
+
|
| 507 |
+
rows <- nrow(real)
|
| 508 |
+
both <- array(0, dim = c(rows * 2, dim(real)[-1]))
|
| 509 |
+
both[1:rows,,,] <- fake
|
| 510 |
+
both[(rows + 1):(rows * 2),,,] <- real
|
| 511 |
+
labels <- rbind(matrix(runif(b, 0.9, 1), nrow = b, ncol = 1),
|
| 512 |
+
matrix(runif(b, 0, 0.1), nrow = b, ncol = 1)) # note the noise in truth labels
|
| 513 |
+
|
| 514 |
+
# train discriminator
|
| 515 |
+
dloss[i] <- d %>% train_on_batch(both, labels)
|
| 516 |
+
|
| 517 |
+
# train generator using gan
|
| 518 |
+
fakeAsReal <- array(runif(b, 0, 0.1), dim = c(b, 1))
|
| 519 |
+
gloss[i] <- gan %>% train_on_batch(noise, fakeAsReal)
|
| 520 |
+
}
|
| 521 |
+
|
| 522 |
+
# save the generator
|
| 523 |
+
save_model_tf(g, filepath = paste0("GAN/GAN_model_", modelx))
|
| 524 |
+
|
| 525 |
+
# monitor loss
|
| 526 |
+
res <- data.frame(iteration = seq(1:100), dloss = dloss, gloss = gloss)
|
| 527 |
+
res <- res %>%
|
| 528 |
+
gather(type, value, 2:3)
|
| 529 |
+
res$id <- modelx
|
| 530 |
+
loss_list[[modelx]] <- res
|
| 531 |
+
}
|
| 532 |
+
```
|
| 533 |
+
|
| 534 |
+
### Generating sequences
|
| 535 |
+
|
| 536 |
+
Use the fully trained GAN models to generate 100 sequences for each model.
|
| 537 |
+
|
| 538 |
+
```{r}
|
| 539 |
+
myseq_all <- list()
|
| 540 |
+
for (j in 1:15) {
|
| 541 |
+
# load previously saved generator
|
| 542 |
+
g <- load_model_tf(paste0("GAN/GAN_model_", j))
|
| 543 |
+
|
| 544 |
+
myseq <- list()
|
| 545 |
+
for (i in 1:100) {
|
| 546 |
+
noise <- matrix(rnorm(b * l), nrow = b, ncol = l)
|
| 547 |
+
|
| 548 |
+
# generate fake image using the generator
|
| 549 |
+
fake <- g %>% predict(noise)
|
| 550 |
+
f <- fake[1,,,]
|
| 551 |
+
dim(f) <- c(32, 22, 1)
|
| 552 |
+
|
| 553 |
+
myseq[[i]] <- f
|
| 554 |
+
}
|
| 555 |
+
myseq_all[[j]] <- myseq
|
| 556 |
+
}
|
| 557 |
+
```
|
| 558 |
+
|
| 559 |
+
### Decode images
|
| 560 |
+
|
| 561 |
+
Here we decode the generated CDR3 images back into amino acid sequences.
|
| 562 |
+
|
| 563 |
+
```{r}
|
| 564 |
+
aa_order <- c("A", "R", "N", "D", "C", "Q", "E", "G", "H", "I", "L", "K", "M", "F", "P", "S", "T", "W", "Y", "V", "X", "-")
|
| 565 |
+
|
| 566 |
+
decode_seq_cdr3 <- function(seq_list) {
|
| 567 |
+
aa_list <- list()
|
| 568 |
+
for (i in 1:length(seq_list)) {
|
| 569 |
+
peptide1 <- as.data.frame(seq_list[[i]])
|
| 570 |
+
colnames(peptide1) <- aa_order
|
| 571 |
+
|
| 572 |
+
# remove column for amino acid X
|
| 573 |
+
# it was previously added for padding so that we have an even shape
|
| 574 |
+
peptide1 <- peptide1 %>% select(-X)
|
| 575 |
+
|
| 576 |
+
# which amino acid has the highest score (decoding)
|
| 577 |
+
aa <- colnames(peptide1)[apply(peptide1, 1, which.max)]
|
| 578 |
+
|
| 579 |
+
# find where the gaps are
|
| 580 |
+
gaps <- which(aa %in% "-")
|
| 581 |
+
# first and last gap in CDR3 region
|
| 582 |
+
gap_first <- gaps[gaps > 1][1]
|
| 583 |
+
gap_last <- gaps[gaps < 32]
|
| 584 |
+
gap_last <- gap_last[length(gap_last)]
|
| 585 |
+
|
| 586 |
+
# replace spurious aa flanked by gaps in CDR3
|
| 587 |
+
aa[gap_first:gap_last] <- "-"
|
| 588 |
+
|
| 589 |
+
aa_string <- paste(aa, collapse = "")
|
| 590 |
+
|
| 591 |
+
# remove gaps
|
| 592 |
+
aa_string <- gsub("-", "", aa_string)
|
| 593 |
+
|
| 594 |
+
aa_list[[i]] <- aa_string
|
| 595 |
+
}
|
| 596 |
+
all_aa <- data.frame(aa = do.call(rbind, aa_list))
|
| 597 |
+
return(all_aa)
|
| 598 |
+
}
|
| 599 |
+
```
|
| 600 |
+
|
| 601 |
+
```{r, fig.width = 25, fig.height=2.5}
|
| 602 |
+
gen_seq <- list()
|
| 603 |
+
|
| 604 |
+
for (i in 1:15) {
|
| 605 |
+
temp <- decode_seq_cdr3(myseq_all[[i]])
|
| 606 |
+
gen_seq[[i]] <- temp$aa
|
| 607 |
+
}
|
| 608 |
+
|
| 609 |
+
names(gen_seq) <- names(seq_all)
|
| 610 |
+
```
|
| 611 |
+
|
| 612 |
+
Example generated sequences:
|
| 613 |
+
|
| 614 |
+
```{r}
|
| 615 |
+
for (i in 1:15) {
|
| 616 |
+
print(names(gen_seq)[i])
|
| 617 |
+
print(gen_seq[[i]][!duplicated(gen_seq[[i]])] %>% head(10))
|
| 618 |
+
}
|
| 619 |
+
```
|
| 620 |
+
|
| 621 |
+
|
model/original/antibody_deep_learning.html
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scripts/01_prepare_data_compat.R
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
args <- commandArgs(trailingOnly = FALSE)
|
| 2 |
+
script_arg <- grep("^--file=", args, value = TRUE)
|
| 3 |
+
if (length(script_arg) > 0) {
|
| 4 |
+
script_path <- normalizePath(sub("^--file=", "", script_arg[1]))
|
| 5 |
+
setwd(normalizePath(file.path(dirname(script_path), "..")))
|
| 6 |
+
}
|
| 7 |
+
|
| 8 |
+
library(caret)
|
| 9 |
+
|
| 10 |
+
pep_mat_local <- function(pep) {
|
| 11 |
+
do.call(rbind, strsplit(as.character(pep), split = ""))
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
one_hot <- function(y, num_classes = 2) {
|
| 15 |
+
y <- as.integer(as.character(y))
|
| 16 |
+
out <- matrix(0, nrow = length(y), ncol = num_classes)
|
| 17 |
+
out[cbind(seq_along(y), y + 1)] <- 1
|
| 18 |
+
out
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
load("model/BLOSUM62_with_deletion.Rdata")
|
| 22 |
+
|
| 23 |
+
pep_encode_blosum <- function(pep) {
|
| 24 |
+
bl62_prob <- BLOSUM62
|
| 25 |
+
p_mat <- pep_mat_local(pep)
|
| 26 |
+
n_peps <- length(pep)
|
| 27 |
+
l_peps <- nchar(pep[1])
|
| 28 |
+
l_enc <- ncol(bl62_prob)
|
| 29 |
+
o_tensor <- array(data = NA, dim = c(n_peps, l_peps, l_enc))
|
| 30 |
+
for (i in 1:n_peps) {
|
| 31 |
+
pep_i_residues <- p_mat[i, ]
|
| 32 |
+
pep_img <- bl62_prob[pep_i_residues, ]
|
| 33 |
+
o_tensor[i, , ] <- pep_img
|
| 34 |
+
}
|
| 35 |
+
o_tensor
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
all <- read.delim("model/CNN/all_ab_pre_post.txt", sep = "\t", header = TRUE, stringsAsFactors = FALSE)
|
| 39 |
+
|
| 40 |
+
set.seed(42)
|
| 41 |
+
all <- all[sample(nrow(all)), ]
|
| 42 |
+
|
| 43 |
+
max_k <- max(nchar(all$CDR3K))
|
| 44 |
+
max_h <- max(nchar(all$CDR3H))
|
| 45 |
+
|
| 46 |
+
all$paddedh <- gsub("\\s", "-", format(all$CDR3H, width = max_h))
|
| 47 |
+
all$paddedk <- gsub("\\s", "-", format(all$CDR3K, width = max_k))
|
| 48 |
+
all$lengthh <- nchar(all$CDR3H)
|
| 49 |
+
all$lengthk <- nchar(all$CDR3K)
|
| 50 |
+
all$padded <- paste0(all$paddedk, all$paddedh)
|
| 51 |
+
|
| 52 |
+
all <- all[order(all$padded, -all$post), ]
|
| 53 |
+
all2 <- all[!duplicated(all$padded), ]
|
| 54 |
+
|
| 55 |
+
all2$enriched <- ifelse((all2$fc >= 1.8 & all2$post >= 0.01), 1,
|
| 56 |
+
ifelse(all2$fc < 1 & all2$pre >= 0.01, 0, "ambi"))
|
| 57 |
+
all2 <- all2[all2$enriched != "ambi", ]
|
| 58 |
+
all2$enriched <- as.integer(all2$enriched)
|
| 59 |
+
|
| 60 |
+
split_train_test <- function(antigenx) {
|
| 61 |
+
mini <- all2[all2$antigen == antigenx, ]
|
| 62 |
+
set.seed(22)
|
| 63 |
+
trainIndex <- createDataPartition(mini$enriched, p = .8, list = FALSE, times = 1)
|
| 64 |
+
list(train = mini[trainIndex, ], test = mini[-trainIndex, ])
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
c1 <- split_train_test("CTLA-4")
|
| 68 |
+
p1 <- split_train_test("PD-1")
|
| 69 |
+
|
| 70 |
+
saveRDS(c1, file = "model/CNN/c1.RDS")
|
| 71 |
+
saveRDS(p1, file = "model/CNN/p1.RDS")
|
| 72 |
+
|
| 73 |
+
c1_train <- pep_encode_blosum(c1$train$padded)
|
| 74 |
+
c1_test <- pep_encode_blosum(c1$test$padded)
|
| 75 |
+
p1_train <- pep_encode_blosum(p1$train$padded)
|
| 76 |
+
p1_test <- pep_encode_blosum(p1$test$padded)
|
| 77 |
+
|
| 78 |
+
c1_train <- array(c1_train, dim = c(dim(c1_train), 1))
|
| 79 |
+
c1_test <- array(c1_test, dim = c(dim(c1_test), 1))
|
| 80 |
+
p1_train <- array(p1_train, dim = c(dim(p1_train), 1))
|
| 81 |
+
p1_test <- array(p1_test, dim = c(dim(p1_test), 1))
|
| 82 |
+
|
| 83 |
+
c1_train_y <- one_hot(c1$train$enriched)
|
| 84 |
+
c1_test_y <- one_hot(c1$test$enriched)
|
| 85 |
+
p1_train_y <- one_hot(p1$train$enriched)
|
| 86 |
+
p1_test_y <- one_hot(p1$test$enriched)
|
| 87 |
+
|
| 88 |
+
saveRDS(p1_train, file = "model/CNN/p1_train.RDS")
|
| 89 |
+
saveRDS(p1_test, file = "model/CNN/p1_test.RDS")
|
| 90 |
+
saveRDS(p1_train_y, file = "model/CNN/p1_train_y.RDS")
|
| 91 |
+
saveRDS(p1_test_y, file = "model/CNN/p1_test_y.RDS")
|
| 92 |
+
saveRDS(c1_train, file = "model/CNN/c1_train.RDS")
|
| 93 |
+
saveRDS(c1_test, file = "model/CNN/c1_test.RDS")
|
| 94 |
+
saveRDS(c1_train_y, file = "model/CNN/c1_train_y.RDS")
|
| 95 |
+
saveRDS(c1_test_y, file = "model/CNN/c1_test_y.RDS")
|
| 96 |
+
|
| 97 |
+
seq_all <- readRDS("model/GAN/seq_all.RDS")
|
| 98 |
+
encoded <- vector("list", 15)
|
| 99 |
+
names(encoded) <- names(seq_all)
|
| 100 |
+
|
| 101 |
+
for (i in 1:15) {
|
| 102 |
+
seq_encoded <- pep_encode_blosum(seq_all[[i]])
|
| 103 |
+
encoded[[i]] <- array(seq_encoded, dim = c(dim(seq_encoded), 1))
|
| 104 |
+
}
|
| 105 |
+
saveRDS(encoded, file = "model/GAN/seq_all_encoded.RDS")
|
| 106 |
+
|
| 107 |
+
print("prepare data OK")
|
| 108 |
+
print(dim(c1_train))
|
| 109 |
+
print(dim(p1_train))
|
| 110 |
+
print(names(encoded))
|
scripts/02_cnn_inference.R
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
args <- commandArgs(trailingOnly = FALSE)
|
| 2 |
+
script_arg <- grep("^--file=", args, value = TRUE)
|
| 3 |
+
if (length(script_arg) > 0) {
|
| 4 |
+
script_path <- normalizePath(sub("^--file=", "", script_arg[1]))
|
| 5 |
+
setwd(normalizePath(file.path(dirname(script_path), "..")))
|
| 6 |
+
}
|
| 7 |
+
|
| 8 |
+
library(reticulate)
|
| 9 |
+
use_python(Sys.getenv("RETICULATE_PYTHON"), required = TRUE)
|
| 10 |
+
|
| 11 |
+
tf <- import("tensorflow", convert = FALSE)
|
| 12 |
+
helper <- import_from_path("tf_savedmodel_helper", path = file.path(getwd(), "scripts"), convert = TRUE)
|
| 13 |
+
|
| 14 |
+
mcc_score <- function(pred, real) {
|
| 15 |
+
tp <- as.numeric(sum(pred == 1 & real == 1))
|
| 16 |
+
tn <- as.numeric(sum(pred == 0 & real == 0))
|
| 17 |
+
fp <- as.numeric(sum(pred == 1 & real == 0))
|
| 18 |
+
fn <- as.numeric(sum(pred == 0 & real == 1))
|
| 19 |
+
denom <- sqrt((tp + fp) * (tp + fn) * (tn + fp) * (tn + fn))
|
| 20 |
+
if (is.na(denom) || denom == 0) return(NA_real_)
|
| 21 |
+
(tp * tn - fp * fn) / denom
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
get_input_name <- function(model_dir) {
|
| 25 |
+
model <- tf$saved_model$load(model_dir)
|
| 26 |
+
serving <- model$signatures$get("serving_default")
|
| 27 |
+
sig_text <- py_str(serving$structured_input_signature)
|
| 28 |
+
out_text <- py_str(serving$structured_outputs)
|
| 29 |
+
|
| 30 |
+
cat("\nModel:", model_dir, "\n")
|
| 31 |
+
cat("Input signature:", sig_text, "\n")
|
| 32 |
+
cat("Output signature:", out_text, "\n")
|
| 33 |
+
|
| 34 |
+
input_name <- sub(".*'([^']+)': TensorSpec.*", "\\1", sig_text)
|
| 35 |
+
cat("Input name:", input_name, "\n")
|
| 36 |
+
input_name
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
run_eval <- function(model_dir, x_file, y_file, label) {
|
| 40 |
+
x <- readRDS(x_file)
|
| 41 |
+
y <- readRDS(y_file)
|
| 42 |
+
|
| 43 |
+
input_name <- get_input_name(model_dir)
|
| 44 |
+
pred_prob <- helper$predict_saved_model(model_dir, input_name, x)
|
| 45 |
+
|
| 46 |
+
y_real <- max.col(y) - 1
|
| 47 |
+
y_pred <- max.col(pred_prob) - 1
|
| 48 |
+
|
| 49 |
+
acc <- mean(y_real == y_pred)
|
| 50 |
+
mcc <- mcc_score(y_pred, y_real)
|
| 51 |
+
|
| 52 |
+
cat("\n====", label, "====\n")
|
| 53 |
+
cat("n_test:", length(y_real), "\n")
|
| 54 |
+
cat("accuracy:", round(acc, 4), "\n")
|
| 55 |
+
cat("mcc:", round(mcc, 4), "\n")
|
| 56 |
+
print(table(real = y_real, pred = y_pred))
|
| 57 |
+
|
| 58 |
+
invisible(list(prob = pred_prob, real = y_real, pred = y_pred))
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
c1_res <- run_eval("weight/CNN/model_c1", "model/CNN/c1_test.RDS", "model/CNN/c1_test_y.RDS", "CTLA-4")
|
| 62 |
+
p1_res <- run_eval("weight/CNN/model_p1", "model/CNN/p1_test.RDS", "model/CNN/p1_test_y.RDS", "PD-1")
|
| 63 |
+
|
| 64 |
+
saveRDS(c1_res, "model/CNN/c1_tf218_inference_result.RDS")
|
| 65 |
+
saveRDS(p1_res, "model/CNN/p1_tf218_inference_result.RDS")
|
| 66 |
+
|
| 67 |
+
cat("\nCNN inference OK\n")
|
scripts/03_gan_inference.R
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
args <- commandArgs(trailingOnly = FALSE)
|
| 2 |
+
script_arg <- grep("^--file=", args, value = TRUE)
|
| 3 |
+
if (length(script_arg) > 0) {
|
| 4 |
+
script_path <- normalizePath(sub("^--file=", "", script_arg[1]))
|
| 5 |
+
setwd(normalizePath(file.path(dirname(script_path), "..")))
|
| 6 |
+
}
|
| 7 |
+
|
| 8 |
+
library(reticulate)
|
| 9 |
+
use_python(Sys.getenv("RETICULATE_PYTHON"), required = TRUE)
|
| 10 |
+
|
| 11 |
+
tf <- import("tensorflow", convert = FALSE)
|
| 12 |
+
helper <- import_from_path("tf_savedmodel_helper", path = file.path(getwd(), "scripts"), convert = TRUE)
|
| 13 |
+
|
| 14 |
+
aa_order <- c("A", "R", "N", "D", "C", "Q", "E", "G", "H", "I",
|
| 15 |
+
"L", "K", "M", "F", "P", "S", "T", "W", "Y", "V", "X", "-")
|
| 16 |
+
|
| 17 |
+
decode_seq_cdr3 <- function(seq_list) {
|
| 18 |
+
aa_list <- list()
|
| 19 |
+
for (i in seq_along(seq_list)) {
|
| 20 |
+
peptide1 <- as.data.frame(seq_list[[i]])
|
| 21 |
+
colnames(peptide1) <- aa_order
|
| 22 |
+
peptide1$X <- NULL
|
| 23 |
+
|
| 24 |
+
aa <- colnames(peptide1)[apply(peptide1, 1, which.max)]
|
| 25 |
+
|
| 26 |
+
gaps <- which(aa %in% "-")
|
| 27 |
+
if (length(gaps) > 0) {
|
| 28 |
+
gap_first <- gaps[gaps > 1][1]
|
| 29 |
+
gap_last_candidates <- gaps[gaps < 32]
|
| 30 |
+
gap_last <- gap_last_candidates[length(gap_last_candidates)]
|
| 31 |
+
if (!is.na(gap_first) && !is.na(gap_last) && gap_first <= gap_last) {
|
| 32 |
+
aa[gap_first:gap_last] <- "-"
|
| 33 |
+
}
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
aa_string <- paste(aa, collapse = "")
|
| 37 |
+
aa_string <- gsub("-", "", aa_string)
|
| 38 |
+
aa_list[[i]] <- aa_string
|
| 39 |
+
}
|
| 40 |
+
data.frame(aa = unlist(aa_list), stringsAsFactors = FALSE)
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
get_input_name <- function(model_dir) {
|
| 44 |
+
model <- tf$saved_model$load(model_dir)
|
| 45 |
+
serving <- model$signatures$get("serving_default")
|
| 46 |
+
sig_text <- py_str(serving$structured_input_signature)
|
| 47 |
+
out_text <- py_str(serving$structured_outputs)
|
| 48 |
+
|
| 49 |
+
cat("\nModel:", model_dir, "\n")
|
| 50 |
+
cat("Input signature:", sig_text, "\n")
|
| 51 |
+
cat("Output signature:", out_text, "\n")
|
| 52 |
+
|
| 53 |
+
input_name <- sub(".*'([^']+)': TensorSpec.*", "\\1", sig_text)
|
| 54 |
+
cat("Input name:", input_name, "\n")
|
| 55 |
+
input_name
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
generate_model <- function(model_id, n_seq = 100, batch_size = 20, latent_dim = 100) {
|
| 59 |
+
model_dir <- paste0("weight/GAN/GAN_model_", model_id)
|
| 60 |
+
input_name <- get_input_name(model_dir)
|
| 61 |
+
|
| 62 |
+
seq_list <- list()
|
| 63 |
+
k <- 1
|
| 64 |
+
|
| 65 |
+
set.seed(1000 + model_id)
|
| 66 |
+
|
| 67 |
+
while (length(seq_list) < n_seq) {
|
| 68 |
+
noise <- matrix(rnorm(batch_size * latent_dim), nrow = batch_size, ncol = latent_dim)
|
| 69 |
+
fake <- helper$predict_saved_model(model_dir, input_name, noise)
|
| 70 |
+
|
| 71 |
+
for (i in seq_len(dim(fake)[1])) {
|
| 72 |
+
f <- fake[i,,,]
|
| 73 |
+
dim(f) <- c(32, 22, 1)
|
| 74 |
+
seq_list[[k]] <- f
|
| 75 |
+
k <- k + 1
|
| 76 |
+
if (length(seq_list) >= n_seq) break
|
| 77 |
+
}
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
decode_seq_cdr3(seq_list)
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
seq_all <- readRDS("model/GAN/seq_all.RDS")
|
| 84 |
+
gen_seq <- list()
|
| 85 |
+
|
| 86 |
+
for (i in 1:15) {
|
| 87 |
+
cat("\nGenerating model", i, names(seq_all)[i], "\n")
|
| 88 |
+
temp <- generate_model(i, n_seq = 100)
|
| 89 |
+
gen_seq[[i]] <- temp$aa
|
| 90 |
+
cat("unique first 10:\n")
|
| 91 |
+
print(head(unique(gen_seq[[i]]), 10))
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
names(gen_seq) <- names(seq_all)
|
| 95 |
+
saveRDS(gen_seq, "model/GAN/gen_seq_tf218.RDS")
|
| 96 |
+
|
| 97 |
+
out <- data.frame()
|
| 98 |
+
for (i in seq_along(gen_seq)) {
|
| 99 |
+
out <- rbind(out, data.frame(model_id = i, group = names(gen_seq)[i], aa = gen_seq[[i]], stringsAsFactors = FALSE))
|
| 100 |
+
}
|
| 101 |
+
write.table(out, "model/GAN/gen_seq_tf218.tsv", sep = "\t", quote = FALSE, row.names = FALSE)
|
| 102 |
+
|
| 103 |
+
cat("\nGAN generation OK\n")
|
scripts/04_export_cnn_npz.R
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
args <- commandArgs(trailingOnly = FALSE)
|
| 2 |
+
script_arg <- grep("^--file=", args, value = TRUE)
|
| 3 |
+
if (length(script_arg) > 0) {
|
| 4 |
+
script_path <- normalizePath(sub("^--file=", "", script_arg[1]))
|
| 5 |
+
setwd(normalizePath(file.path(dirname(script_path), "..")))
|
| 6 |
+
}
|
| 7 |
+
|
| 8 |
+
library(reticulate)
|
| 9 |
+
use_python(Sys.getenv("RETICULATE_PYTHON"), required = TRUE)
|
| 10 |
+
np <- import("numpy", convert = FALSE)
|
| 11 |
+
|
| 12 |
+
save_npz <- function(out_file, x_train, y_train, x_test, y_test) {
|
| 13 |
+
np$savez_compressed(
|
| 14 |
+
out_file,
|
| 15 |
+
x_train = np$array(readRDS(x_train), dtype = "float32"),
|
| 16 |
+
y_train = np$array(readRDS(y_train), dtype = "float32"),
|
| 17 |
+
x_test = np$array(readRDS(x_test), dtype = "float32"),
|
| 18 |
+
y_test = np$array(readRDS(y_test), dtype = "float32")
|
| 19 |
+
)
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
save_npz("model/CNN/c1_data.npz", "model/CNN/c1_train.RDS", "model/CNN/c1_train_y.RDS", "model/CNN/c1_test.RDS", "model/CNN/c1_test_y.RDS")
|
| 23 |
+
save_npz("model/CNN/p1_data.npz", "model/CNN/p1_train.RDS", "model/CNN/p1_train_y.RDS", "model/CNN/p1_test.RDS", "model/CNN/p1_test_y.RDS")
|
| 24 |
+
|
| 25 |
+
cat("export cnn npz OK\n")
|
scripts/05_train_cnn.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import numpy as np
|
| 3 |
+
import tensorflow as tf
|
| 4 |
+
|
| 5 |
+
os.environ.setdefault("TF_FORCE_GPU_ALLOW_GROWTH", "true")
|
| 6 |
+
|
| 7 |
+
def build_model():
|
| 8 |
+
model = tf.keras.Sequential([
|
| 9 |
+
tf.keras.layers.Conv2D(64, (3, 3), activation="relu", input_shape=(36, 22, 1), padding="same"),
|
| 10 |
+
tf.keras.layers.Dropout(0.5),
|
| 11 |
+
tf.keras.layers.MaxPooling2D((2, 2), padding="same"),
|
| 12 |
+
tf.keras.layers.Conv2D(32, (3, 4), activation="relu", padding="same"),
|
| 13 |
+
tf.keras.layers.Dropout(0.4),
|
| 14 |
+
tf.keras.layers.MaxPooling2D((2, 2), padding="same"),
|
| 15 |
+
tf.keras.layers.Conv2D(32, (4, 4), activation="relu", padding="same"),
|
| 16 |
+
tf.keras.layers.Dropout(0.3),
|
| 17 |
+
tf.keras.layers.Flatten(),
|
| 18 |
+
tf.keras.layers.Dense(64, activation="relu"),
|
| 19 |
+
tf.keras.layers.Dropout(0.4),
|
| 20 |
+
tf.keras.layers.Dense(2, activation="softmax"),
|
| 21 |
+
])
|
| 22 |
+
model.compile(
|
| 23 |
+
loss="categorical_crossentropy",
|
| 24 |
+
optimizer="adam",
|
| 25 |
+
metrics=["accuracy"],
|
| 26 |
+
)
|
| 27 |
+
return model
|
| 28 |
+
|
| 29 |
+
def mcc_score(y_pred, y_real):
|
| 30 |
+
y_pred = y_pred.astype(int)
|
| 31 |
+
y_real = y_real.astype(int)
|
| 32 |
+
tp = float(np.sum((y_pred == 1) & (y_real == 1)))
|
| 33 |
+
tn = float(np.sum((y_pred == 0) & (y_real == 0)))
|
| 34 |
+
fp = float(np.sum((y_pred == 1) & (y_real == 0)))
|
| 35 |
+
fn = float(np.sum((y_pred == 0) & (y_real == 1)))
|
| 36 |
+
denom = np.sqrt((tp + fp) * (tp + fn) * (tn + fp) * (tn + fn))
|
| 37 |
+
return np.nan if denom == 0 else (tp * tn - fp * fn) / denom
|
| 38 |
+
|
| 39 |
+
def train_one(name, data_file, out_dir):
|
| 40 |
+
print(f"\n==== training {name} ====")
|
| 41 |
+
data = np.load(data_file)
|
| 42 |
+
x_train = data["x_train"].astype("float32")
|
| 43 |
+
y_train = data["y_train"].astype("float32")
|
| 44 |
+
x_test = data["x_test"].astype("float32")
|
| 45 |
+
y_test = data["y_test"].astype("float32")
|
| 46 |
+
|
| 47 |
+
print("x_train", x_train.shape, "y_train", y_train.shape)
|
| 48 |
+
print("x_test ", x_test.shape, "y_test ", y_test.shape)
|
| 49 |
+
print("GPUs:", tf.config.list_physical_devices("GPU"))
|
| 50 |
+
|
| 51 |
+
with tf.device("/GPU:0"):
|
| 52 |
+
model = build_model()
|
| 53 |
+
model.fit(
|
| 54 |
+
x_train,
|
| 55 |
+
y_train,
|
| 56 |
+
epochs=30,
|
| 57 |
+
batch_size=50,
|
| 58 |
+
validation_split=0.2,
|
| 59 |
+
verbose=2,
|
| 60 |
+
)
|
| 61 |
+
prob = model.predict(x_test, batch_size=128, verbose=0)
|
| 62 |
+
|
| 63 |
+
y_real = np.argmax(y_test, axis=1)
|
| 64 |
+
y_pred = np.argmax(prob, axis=1)
|
| 65 |
+
acc = float(np.mean(y_real == y_pred))
|
| 66 |
+
mcc = float(mcc_score(y_pred, y_real))
|
| 67 |
+
|
| 68 |
+
print(f"\n{name} accuracy: {acc:.4f}")
|
| 69 |
+
print(f"{name} mcc: {mcc:.4f}")
|
| 70 |
+
print("confusion matrix rows=real cols=pred")
|
| 71 |
+
cm = np.zeros((2, 2), dtype=int)
|
| 72 |
+
for r, p in zip(y_real, y_pred):
|
| 73 |
+
cm[r, p] += 1
|
| 74 |
+
print(cm)
|
| 75 |
+
|
| 76 |
+
model.save(out_dir)
|
| 77 |
+
#model.save(out_dir + ".keras")
|
| 78 |
+
np.savez_compressed(out_dir + "_eval.npz", prob=prob, y_real=y_real, y_pred=y_pred, cm=cm, acc=acc, mcc=mcc)
|
| 79 |
+
print("saved", out_dir)
|
| 80 |
+
|
| 81 |
+
train_one("CTLA-4", "model/CNN/c1_data.npz", "weight/CNN/model_c1_dcu")
|
| 82 |
+
train_one("PD-1", "model/CNN/p1_data.npz", "weight/CNN/model_p1_dcu")
|
| 83 |
+
print("\nCNN DCU training OK")
|
scripts/06_export_gan_npz.R
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
args <- commandArgs(trailingOnly = FALSE)
|
| 2 |
+
script_arg <- grep("^--file=", args, value = TRUE)
|
| 3 |
+
if (length(script_arg) > 0) {
|
| 4 |
+
script_path <- normalizePath(sub("^--file=", "", script_arg[1]))
|
| 5 |
+
setwd(normalizePath(file.path(dirname(script_path), "..")))
|
| 6 |
+
}
|
| 7 |
+
|
| 8 |
+
library(reticulate)
|
| 9 |
+
use_python(Sys.getenv("RETICULATE_PYTHON"), required = TRUE)
|
| 10 |
+
np <- import("numpy", convert = FALSE)
|
| 11 |
+
|
| 12 |
+
encoded <- readRDS("model/GAN/seq_all_encoded.RDS")
|
| 13 |
+
names_encoded <- names(encoded)
|
| 14 |
+
|
| 15 |
+
for (i in seq_along(encoded)) {
|
| 16 |
+
out_file <- sprintf("model/GAN/seq_encoded_%02d.npz", i)
|
| 17 |
+
np$savez_compressed(
|
| 18 |
+
out_file,
|
| 19 |
+
x = np$array(encoded[[i]], dtype = "float32"),
|
| 20 |
+
name = names_encoded[[i]]
|
| 21 |
+
)
|
| 22 |
+
cat("saved", out_file, names_encoded[[i]], dim(encoded[[i]]), "\n")
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
cat("export GAN npz OK\n")
|
scripts/07_train_gan.py
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
import os
|
| 3 |
+
import numpy as np
|
| 4 |
+
import tensorflow as tf
|
| 5 |
+
|
| 6 |
+
os.environ.setdefault("TF_FORCE_GPU_ALLOW_GROWTH", "true")
|
| 7 |
+
|
| 8 |
+
def build_generator(latent_dim=100):
|
| 9 |
+
inputs = tf.keras.Input(shape=(latent_dim,))
|
| 10 |
+
x = tf.keras.layers.Dense(16 * 11 * 128)(inputs)
|
| 11 |
+
x = tf.keras.layers.LeakyReLU()(x)
|
| 12 |
+
x = tf.keras.layers.Reshape((16, 11, 128))(x)
|
| 13 |
+
x = tf.keras.layers.Conv2D(64, (2, 2), padding="same")(x)
|
| 14 |
+
x = tf.keras.layers.LeakyReLU()(x)
|
| 15 |
+
x = tf.keras.layers.Conv2DTranspose(32, (2, 2), strides=2, padding="same")(x)
|
| 16 |
+
x = tf.keras.layers.LeakyReLU()(x)
|
| 17 |
+
x = tf.keras.layers.Conv2D(128, (5, 6), padding="same")(x)
|
| 18 |
+
x = tf.keras.layers.LeakyReLU()(x)
|
| 19 |
+
outputs = tf.keras.layers.Conv2D(1, (6, 6), activation="tanh", padding="same")(x)
|
| 20 |
+
return tf.keras.Model(inputs, outputs, name="generator")
|
| 21 |
+
|
| 22 |
+
def build_discriminator():
|
| 23 |
+
inputs = tf.keras.Input(shape=(32, 22, 1))
|
| 24 |
+
x = tf.keras.layers.Conv2D(96, 3)(inputs)
|
| 25 |
+
x = tf.keras.layers.LeakyReLU()(x)
|
| 26 |
+
x = tf.keras.layers.Flatten()(x)
|
| 27 |
+
x = tf.keras.layers.Dropout(0.3)(x)
|
| 28 |
+
outputs = tf.keras.layers.Dense(1, activation="sigmoid")(x)
|
| 29 |
+
return tf.keras.Model(inputs, outputs, name="discriminator")
|
| 30 |
+
|
| 31 |
+
def train_gan(model_id, rounds=100, batch_size=20, latent_dim=100, seed=42):
|
| 32 |
+
np.random.seed(seed + model_id)
|
| 33 |
+
tf.random.set_seed(seed + model_id)
|
| 34 |
+
|
| 35 |
+
data_file = f"model/GAN/seq_encoded_{model_id:02d}.npz"
|
| 36 |
+
data = np.load(data_file, allow_pickle=True)
|
| 37 |
+
real_data = data["x"].astype("float32")
|
| 38 |
+
group_name = str(data["name"])
|
| 39 |
+
|
| 40 |
+
print(f"\n==== GAN model {model_id}: {group_name} ====")
|
| 41 |
+
print("real_data:", real_data.shape)
|
| 42 |
+
print("GPUs:", tf.config.list_physical_devices("GPU"))
|
| 43 |
+
|
| 44 |
+
with tf.device("/GPU:0"):
|
| 45 |
+
generator = build_generator(latent_dim)
|
| 46 |
+
discriminator = build_discriminator()
|
| 47 |
+
|
| 48 |
+
discriminator.compile(
|
| 49 |
+
optimizer=tf.keras.optimizers.RMSprop(),
|
| 50 |
+
loss="binary_crossentropy",
|
| 51 |
+
)
|
| 52 |
+
|
| 53 |
+
discriminator.trainable = False
|
| 54 |
+
gan_input = tf.keras.Input(shape=(latent_dim,))
|
| 55 |
+
gan_output = discriminator(generator(gan_input))
|
| 56 |
+
gan = tf.keras.Model(gan_input, gan_output, name="gan")
|
| 57 |
+
gan.compile(
|
| 58 |
+
optimizer=tf.keras.optimizers.RMSprop(),
|
| 59 |
+
loss="binary_crossentropy",
|
| 60 |
+
)
|
| 61 |
+
|
| 62 |
+
dloss = []
|
| 63 |
+
gloss = []
|
| 64 |
+
|
| 65 |
+
for step in range(1, rounds + 1):
|
| 66 |
+
noise = np.random.normal(size=(batch_size, latent_dim)).astype("float32")
|
| 67 |
+
fake = generator.predict(noise, verbose=0)
|
| 68 |
+
|
| 69 |
+
idx = np.random.choice(real_data.shape[0], size=batch_size, replace=True)
|
| 70 |
+
real = real_data[idx]
|
| 71 |
+
|
| 72 |
+
both = np.concatenate([fake, real], axis=0).astype("float32")
|
| 73 |
+
|
| 74 |
+
labels_fake = np.random.uniform(0.9, 1.0, size=(batch_size, 1)).astype("float32")
|
| 75 |
+
labels_real = np.random.uniform(0.0, 0.1, size=(batch_size, 1)).astype("float32")
|
| 76 |
+
labels = np.concatenate([labels_fake, labels_real], axis=0)
|
| 77 |
+
|
| 78 |
+
discriminator.trainable = True
|
| 79 |
+
d_loss = discriminator.train_on_batch(both, labels)
|
| 80 |
+
|
| 81 |
+
noise = np.random.normal(size=(batch_size, latent_dim)).astype("float32")
|
| 82 |
+
fake_as_real = np.random.uniform(0.0, 0.1, size=(batch_size, 1)).astype("float32")
|
| 83 |
+
|
| 84 |
+
discriminator.trainable = False
|
| 85 |
+
g_loss = gan.train_on_batch(noise, fake_as_real)
|
| 86 |
+
|
| 87 |
+
dloss.append(float(d_loss))
|
| 88 |
+
gloss.append(float(g_loss))
|
| 89 |
+
|
| 90 |
+
if step == 1 or step % 10 == 0 or step == rounds:
|
| 91 |
+
print(f"step {step:03d}/{rounds} dloss={dloss[-1]:.6f} gloss={gloss[-1]:.6f}")
|
| 92 |
+
|
| 93 |
+
out_dir = f"weight/GAN/GAN_model_{model_id}_dcu"
|
| 94 |
+
generator.save(out_dir)
|
| 95 |
+
#generator.save(out_dir + ".keras")
|
| 96 |
+
|
| 97 |
+
loss_file = f"weight/GAN/GAN_model_{model_id}_dcu_loss.npz"
|
| 98 |
+
np.savez_compressed(
|
| 99 |
+
loss_file,
|
| 100 |
+
dloss=np.array(dloss, dtype="float32"),
|
| 101 |
+
gloss=np.array(gloss, dtype="float32"),
|
| 102 |
+
model_id=model_id,
|
| 103 |
+
group_name=group_name,
|
| 104 |
+
)
|
| 105 |
+
|
| 106 |
+
print("saved generator:", out_dir)
|
| 107 |
+
print("saved loss:", loss_file)
|
| 108 |
+
|
| 109 |
+
def main():
|
| 110 |
+
parser = argparse.ArgumentParser()
|
| 111 |
+
parser.add_argument("--model-id", type=int, required=True, help="GAN model id, 1-15")
|
| 112 |
+
parser.add_argument("--rounds", type=int, default=100)
|
| 113 |
+
parser.add_argument("--batch-size", type=int, default=20)
|
| 114 |
+
parser.add_argument("--latent-dim", type=int, default=100)
|
| 115 |
+
parser.add_argument("--seed", type=int, default=42)
|
| 116 |
+
args = parser.parse_args()
|
| 117 |
+
|
| 118 |
+
if args.model_id < 1 or args.model_id > 15:
|
| 119 |
+
raise ValueError("--model-id must be between 1 and 15")
|
| 120 |
+
|
| 121 |
+
train_gan(
|
| 122 |
+
model_id=args.model_id,
|
| 123 |
+
rounds=args.rounds,
|
| 124 |
+
batch_size=args.batch_size,
|
| 125 |
+
latent_dim=args.latent_dim,
|
| 126 |
+
seed=args.seed,
|
| 127 |
+
)
|
| 128 |
+
|
| 129 |
+
if __name__ == "__main__":
|
| 130 |
+
main()
|
scripts/08_generate_from_trained_gan.py
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
import os
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
|
| 5 |
+
import numpy as np
|
| 6 |
+
import tensorflow as tf
|
| 7 |
+
|
| 8 |
+
os.environ.setdefault("TF_FORCE_GPU_ALLOW_GROWTH", "true")
|
| 9 |
+
|
| 10 |
+
AA_ORDER = ["A", "R", "N", "D", "C", "Q", "E", "G", "H", "I",
|
| 11 |
+
"L", "K", "M", "F", "P", "S", "T", "W", "Y", "V", "X", "-"]
|
| 12 |
+
|
| 13 |
+
def decode_one(img):
|
| 14 |
+
arr = np.asarray(img)
|
| 15 |
+
arr = arr.reshape(32, 22)
|
| 16 |
+
|
| 17 |
+
# remove X column, same as README
|
| 18 |
+
arr_no_x = np.delete(arr, 20, axis=1)
|
| 19 |
+
aa_no_x = AA_ORDER[:20] + ["-"]
|
| 20 |
+
|
| 21 |
+
aa_idx = np.argmax(arr_no_x, axis=1)
|
| 22 |
+
aa = np.array([aa_no_x[i] for i in aa_idx], dtype=object)
|
| 23 |
+
|
| 24 |
+
gaps = np.where(aa == "-")[0] + 1 # use 1-based position to mimic R logic
|
| 25 |
+
if len(gaps) > 0:
|
| 26 |
+
gap_first_candidates = gaps[gaps > 1]
|
| 27 |
+
gap_last_candidates = gaps[gaps < 32]
|
| 28 |
+
if len(gap_first_candidates) > 0 and len(gap_last_candidates) > 0:
|
| 29 |
+
gap_first = int(gap_first_candidates[0])
|
| 30 |
+
gap_last = int(gap_last_candidates[-1])
|
| 31 |
+
if gap_first <= gap_last:
|
| 32 |
+
aa[(gap_first - 1):gap_last] = "-"
|
| 33 |
+
|
| 34 |
+
seq = "".join(aa.tolist()).replace("-", "")
|
| 35 |
+
return seq
|
| 36 |
+
|
| 37 |
+
def generate_one(model_id, n_seq=100, batch_size=20, latent_dim=100, seed=2026):
|
| 38 |
+
#model_dir = Path(f"weight/GAN/GAN_model_{model_id}_dcu.keras")
|
| 39 |
+
model_dir = Path(f"weight/GAN/GAN_model_{model_id}_dcu")
|
| 40 |
+
if not model_dir.exists():
|
| 41 |
+
raise FileNotFoundError(f"Missing trained model: {model_dir}")
|
| 42 |
+
|
| 43 |
+
np.random.seed(seed + model_id)
|
| 44 |
+
tf.random.set_seed(seed + model_id)
|
| 45 |
+
|
| 46 |
+
model = tf.keras.models.load_model(str(model_dir), compile=False)
|
| 47 |
+
|
| 48 |
+
seqs = []
|
| 49 |
+
with tf.device("/GPU:0"):
|
| 50 |
+
while len(seqs) < n_seq:
|
| 51 |
+
noise = np.random.normal(size=(batch_size, latent_dim)).astype("float32")
|
| 52 |
+
fake = model(noise, training=False).numpy()
|
| 53 |
+
|
| 54 |
+
for i in range(fake.shape[0]):
|
| 55 |
+
seqs.append(decode_one(fake[i]))
|
| 56 |
+
if len(seqs) >= n_seq:
|
| 57 |
+
break
|
| 58 |
+
|
| 59 |
+
return seqs
|
| 60 |
+
|
| 61 |
+
def load_group_names():
|
| 62 |
+
names = []
|
| 63 |
+
for i in range(1, 16):
|
| 64 |
+
f = Path(f"model/GAN/seq_encoded_{i:02d}.npz")
|
| 65 |
+
if f.exists():
|
| 66 |
+
d = np.load(f, allow_pickle=True)
|
| 67 |
+
names.append(str(d["name"]))
|
| 68 |
+
else:
|
| 69 |
+
names.append(f"GAN_model_{i}")
|
| 70 |
+
return names
|
| 71 |
+
|
| 72 |
+
def main():
|
| 73 |
+
parser = argparse.ArgumentParser()
|
| 74 |
+
parser.add_argument("--model-id", type=int, default=0, help="0 means all models; otherwise 1-15")
|
| 75 |
+
parser.add_argument("--n-seq", type=int, default=100)
|
| 76 |
+
parser.add_argument("--batch-size", type=int, default=20)
|
| 77 |
+
parser.add_argument("--latent-dim", type=int, default=100)
|
| 78 |
+
parser.add_argument("--seed", type=int, default=2026)
|
| 79 |
+
parser.add_argument("--out-tsv", default="model/GAN/gen_seq_trained_dcu.tsv")
|
| 80 |
+
args = parser.parse_args()
|
| 81 |
+
|
| 82 |
+
group_names = load_group_names()
|
| 83 |
+
|
| 84 |
+
if args.model_id == 0:
|
| 85 |
+
model_ids = range(1, 16)
|
| 86 |
+
else:
|
| 87 |
+
if args.model_id < 1 or args.model_id > 15:
|
| 88 |
+
raise ValueError("--model-id must be 0 or 1-15")
|
| 89 |
+
model_ids = [args.model_id]
|
| 90 |
+
|
| 91 |
+
rows = []
|
| 92 |
+
all_seqs = {}
|
| 93 |
+
|
| 94 |
+
for model_id in model_ids:
|
| 95 |
+
group = group_names[model_id - 1]
|
| 96 |
+
print(f"\nGenerating from trained model {model_id}: {group}")
|
| 97 |
+
seqs = generate_one(
|
| 98 |
+
model_id=model_id,
|
| 99 |
+
n_seq=args.n_seq,
|
| 100 |
+
batch_size=args.batch_size,
|
| 101 |
+
latent_dim=args.latent_dim,
|
| 102 |
+
seed=args.seed,
|
| 103 |
+
)
|
| 104 |
+
all_seqs[model_id] = seqs
|
| 105 |
+
|
| 106 |
+
unique = []
|
| 107 |
+
seen = set()
|
| 108 |
+
for s in seqs:
|
| 109 |
+
if s not in seen:
|
| 110 |
+
unique.append(s)
|
| 111 |
+
seen.add(s)
|
| 112 |
+
|
| 113 |
+
print("unique first 10:")
|
| 114 |
+
print(unique[:10])
|
| 115 |
+
print("n_seq:", len(seqs), "n_unique:", len(unique))
|
| 116 |
+
|
| 117 |
+
for rank, seq in enumerate(seqs, start=1):
|
| 118 |
+
rows.append((model_id, group, rank, seq, len(seq)))
|
| 119 |
+
|
| 120 |
+
out_path = Path(args.out_tsv)
|
| 121 |
+
out_path.parent.mkdir(parents=True, exist_ok=True)
|
| 122 |
+
|
| 123 |
+
with out_path.open("w") as f:
|
| 124 |
+
f.write("model_id\tgroup\trank\taa\tlength\n")
|
| 125 |
+
for row in rows:
|
| 126 |
+
f.write("\t".join(map(str, row)) + "\n")
|
| 127 |
+
|
| 128 |
+
np.savez_compressed(
|
| 129 |
+
str(out_path).replace(".tsv", ".npz"),
|
| 130 |
+
**{f"model_{k:02d}": np.array(v, dtype=object) for k, v in all_seqs.items()}
|
| 131 |
+
)
|
| 132 |
+
|
| 133 |
+
print("\nsaved:", out_path)
|
| 134 |
+
print("saved:", str(out_path).replace(".tsv", ".npz"))
|
| 135 |
+
print("GAN trained-model generation OK")
|
| 136 |
+
|
| 137 |
+
if __name__ == "__main__":
|
| 138 |
+
main()
|
scripts/tf_savedmodel_helper.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import tensorflow as tf
|
| 3 |
+
|
| 4 |
+
def predict_saved_model(model_dir, input_name, x):
|
| 5 |
+
model = tf.saved_model.load(model_dir)
|
| 6 |
+
serving = model.signatures["serving_default"]
|
| 7 |
+
x = np.asarray(x, dtype=np.float32)
|
| 8 |
+
with tf.device("/GPU:0"):
|
| 9 |
+
out = serving(**{input_name: tf.constant(x)})
|
| 10 |
+
first_key = list(out.keys())[0]
|
| 11 |
+
return out[first_key].numpy()
|
weight/CNN/model_c1/saved_model.pb
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:3d523365865feb68260c10c78ae9c196aab6149349a97cd7113063aa9f756e3b
|
| 3 |
+
size 206837
|
weight/CNN/model_c1/variables/variables.data-00000-of-00001
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:94e131857bee132a6e8b31363fc04c74c79fc400bbdd2e42b123fedb1beb7c28
|
| 3 |
+
size 1838457
|
weight/CNN/model_c1/variables/variables.index
ADDED
|
Binary file (2.71 kB). View file
|
|
|
weight/CNN/model_p1/saved_model.pb
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ea02f85ba2a2e00306ae2f963523d7fd86e2dd2eae30a252cb634277ce5ae456
|
| 3 |
+
size 206837
|
weight/CNN/model_p1/variables/variables.data-00000-of-00001
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:8f0b16d2906c45128e91dcfadb97a20f21a027d951c18f5f743fedfce32c3caf
|
| 3 |
+
size 1838457
|
weight/CNN/model_p1/variables/variables.index
ADDED
|
Binary file (2.71 kB). View file
|
|
|
weight/GAN/GAN_model_1/saved_model.pb
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c95b33f2869991bff6b84ae7f6911b59b387341d57b33486c28581396396b680
|
| 3 |
+
size 154394
|
weight/GAN/GAN_model_1/variables/variables.data-00000-of-00001
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6dfd9c7f6e57302f30ba8fe94514b6fd2e40ff5a26464a5537ed67841fc19630
|
| 3 |
+
size 9780733
|
weight/GAN/GAN_model_1/variables/variables.index
ADDED
|
Binary file (801 Bytes). View file
|
|
|
weight/GAN/GAN_model_10/saved_model.pb
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e41616ca6f4927130e8587c3392d9f1e2281c036ddf54b1fed7f5dc4499db57a
|
| 3 |
+
size 157107
|
weight/GAN/GAN_model_10/variables/variables.data-00000-of-00001
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c496bb4b9de209573c69ed06db5382dd34d6155e2cea95d7eb82b5be1e815edf
|
| 3 |
+
size 9780745
|
weight/GAN/GAN_model_10/variables/variables.index
ADDED
|
Binary file (801 Bytes). View file
|
|
|
weight/GAN/GAN_model_11/saved_model.pb
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:68d34852fdb40df16545d2f84f2373ff2fcaac12683096dc85fab54afd682f05
|
| 3 |
+
size 157508
|
weight/GAN/GAN_model_11/variables/variables.data-00000-of-00001
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:3efcb4b884e77bcd0ee49d804b344092b6be0a2655e9eee664f87ab3a8fc628c
|
| 3 |
+
size 9780747
|
weight/GAN/GAN_model_11/variables/variables.index
ADDED
|
Binary file (801 Bytes). View file
|
|
|
weight/GAN/GAN_model_12/saved_model.pb
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c4de0b798101b76a383cb444e04e6ce64ef493cdd6fb683b87242241618c2e58
|
| 3 |
+
size 157508
|
weight/GAN/GAN_model_12/variables/variables.data-00000-of-00001
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:133ad21b0d2136d9f17d0afcf9b1a53483906f7744ef3b44a61db11ba603373b
|
| 3 |
+
size 9780747
|
weight/GAN/GAN_model_12/variables/variables.index
ADDED
|
Binary file (801 Bytes). View file
|
|
|
weight/GAN/GAN_model_13/saved_model.pb
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c6faceceafc4015345b43e9b2fdee255b0a1ae5344cdca0e92318f989531e501
|
| 3 |
+
size 157508
|
weight/GAN/GAN_model_13/variables/variables.data-00000-of-00001
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b8dbe2acae91269808165419e97b8916ac1764adfcab2cfdf81e30473bf5b3f3
|
| 3 |
+
size 9780747
|