anzhi2710gmailcom commited on
Commit
fe8e241
·
verified ·
1 Parent(s): 44dcc01

Upload folder using huggingface_hub

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +24 -0
  2. LICENSE +437 -0
  3. README.md +412 -0
  4. conf/config.json +16 -0
  5. config.json +68 -0
  6. model/BLOSUM62_with_deletion.Rdata +0 -0
  7. model/CNN/all_ab_pre_post.txt +0 -0
  8. model/CNN/c1.RDS +3 -0
  9. model/CNN/c1_test.RDS +3 -0
  10. model/CNN/c1_test_y.RDS +0 -0
  11. model/CNN/c1_train.RDS +3 -0
  12. model/CNN/c1_train_y.RDS +0 -0
  13. model/CNN/p1.RDS +3 -0
  14. model/CNN/p1_test.RDS +3 -0
  15. model/CNN/p1_test_y.RDS +0 -0
  16. model/CNN/p1_train.RDS +3 -0
  17. model/CNN/p1_train_y.RDS +0 -0
  18. model/GAN/seq_all.RDS +0 -0
  19. model/GAN/seq_all_encoded.RDS +3 -0
  20. model/original/antibody_deep_learning.Rmd +621 -0
  21. model/original/antibody_deep_learning.html +0 -0
  22. scripts/01_prepare_data_compat.R +110 -0
  23. scripts/02_cnn_inference.R +67 -0
  24. scripts/03_gan_inference.R +103 -0
  25. scripts/04_export_cnn_npz.R +25 -0
  26. scripts/05_train_cnn.py +83 -0
  27. scripts/06_export_gan_npz.R +25 -0
  28. scripts/07_train_gan.py +130 -0
  29. scripts/08_generate_from_trained_gan.py +138 -0
  30. scripts/tf_savedmodel_helper.py +11 -0
  31. weight/CNN/model_c1/saved_model.pb +3 -0
  32. weight/CNN/model_c1/variables/variables.data-00000-of-00001 +3 -0
  33. weight/CNN/model_c1/variables/variables.index +0 -0
  34. weight/CNN/model_p1/saved_model.pb +3 -0
  35. weight/CNN/model_p1/variables/variables.data-00000-of-00001 +3 -0
  36. weight/CNN/model_p1/variables/variables.index +0 -0
  37. weight/GAN/GAN_model_1/saved_model.pb +3 -0
  38. weight/GAN/GAN_model_1/variables/variables.data-00000-of-00001 +3 -0
  39. weight/GAN/GAN_model_1/variables/variables.index +0 -0
  40. weight/GAN/GAN_model_10/saved_model.pb +3 -0
  41. weight/GAN/GAN_model_10/variables/variables.data-00000-of-00001 +3 -0
  42. weight/GAN/GAN_model_10/variables/variables.index +0 -0
  43. weight/GAN/GAN_model_11/saved_model.pb +3 -0
  44. weight/GAN/GAN_model_11/variables/variables.data-00000-of-00001 +3 -0
  45. weight/GAN/GAN_model_11/variables/variables.index +0 -0
  46. weight/GAN/GAN_model_12/saved_model.pb +3 -0
  47. weight/GAN/GAN_model_12/variables/variables.data-00000-of-00001 +3 -0
  48. weight/GAN/GAN_model_12/variables/variables.index +0 -0
  49. weight/GAN/GAN_model_13/saved_model.pb +3 -0
  50. 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