acp-classifier 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- acp_classifier-1.0.0/LICENSE +22 -0
- acp_classifier-1.0.0/PKG-INFO +245 -0
- acp_classifier-1.0.0/README.md +213 -0
- acp_classifier-1.0.0/pyproject.toml +57 -0
- acp_classifier-1.0.0/setup.cfg +4 -0
- acp_classifier-1.0.0/src/acp_classifier/__init__.py +20 -0
- acp_classifier-1.0.0/src/acp_classifier/cli.py +92 -0
- acp_classifier-1.0.0/src/acp_classifier/embedder.py +90 -0
- acp_classifier-1.0.0/src/acp_classifier/fasta.py +96 -0
- acp_classifier-1.0.0/src/acp_classifier/modelos/__init__.py +1 -0
- acp_classifier-1.0.0/src/acp_classifier/modelos/acp_esm2_8m_lr.joblib +0 -0
- acp_classifier-1.0.0/src/acp_classifier/predictor.py +121 -0
- acp_classifier-1.0.0/src/acp_classifier.egg-info/PKG-INFO +245 -0
- acp_classifier-1.0.0/src/acp_classifier.egg-info/SOURCES.txt +17 -0
- acp_classifier-1.0.0/src/acp_classifier.egg-info/dependency_links.txt +1 -0
- acp_classifier-1.0.0/src/acp_classifier.egg-info/entry_points.txt +2 -0
- acp_classifier-1.0.0/src/acp_classifier.egg-info/requires.txt +8 -0
- acp_classifier-1.0.0/src/acp_classifier.egg-info/top_level.txt +1 -0
- acp_classifier-1.0.0/tests/test_acp_classifier.py +121 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Brayan Arturo Navarro Sinuco, Ivan Andres Mendoza Oñate
|
|
4
|
+
Universidad Industrial de Santander — Escuela de Ingeniería de Sistemas e Informática
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: acp-classifier
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Clasificación de péptidos anticancerígenos (ACPs) mediante modelos de lenguaje proteico
|
|
5
|
+
Author: Brayan Arturo Navarro Sinuco, Ivan Andres Mendoza Oñate
|
|
6
|
+
Maintainer: Escuela de Ingeniería de Sistemas e Informática, Universidad Industrial de Santander
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/ivan2171977/acp-classifier
|
|
9
|
+
Project-URL: Repository, https://github.com/ivan2171977/acp-classifier
|
|
10
|
+
Project-URL: Issues, https://github.com/ivan2171977/acp-classifier/issues
|
|
11
|
+
Keywords: bioinformatics,anticancer-peptides,acp,protein-language-model,esm2,peptide-classification,machine-learning
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
21
|
+
Requires-Python: >=3.9
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: numpy>=1.21
|
|
25
|
+
Requires-Dist: joblib>=1.1
|
|
26
|
+
Requires-Dist: torch>=1.11
|
|
27
|
+
Requires-Dist: transformers>=4.20
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
30
|
+
Requires-Dist: scikit-learn>=1.0; extra == "dev"
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
# acp-classifier
|
|
34
|
+
|
|
35
|
+
Clasificación de péptidos anticancerígenos (ACPs) a partir de secuencias en formato FASTA,
|
|
36
|
+
mediante representaciones contextuales generadas por el modelo de lenguaje proteico
|
|
37
|
+
**ESM-2** y un clasificador de **Regresión Logística**.
|
|
38
|
+
|
|
39
|
+
Desarrollado como trabajo de grado en la Escuela de Ingeniería de Sistemas e Informática de
|
|
40
|
+
la **Universidad Industrial de Santander**.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Por qué existe
|
|
45
|
+
|
|
46
|
+
Las herramientas de referencia para predicción de ACPs —AntiCP 2.0, MLACP 2.0, mACPpred 2.0,
|
|
47
|
+
ACP-EPC— están disponibles únicamente como servidores web, o como repositorios sin empaquetar.
|
|
48
|
+
Ninguna se instala mediante gestores estándar, lo que dificulta su integración en flujos de
|
|
49
|
+
trabajo bioinformáticos automatizados.
|
|
50
|
+
|
|
51
|
+
`acp-classifier` se instala con `pip`, se ejecuta desde consola y no requiere GPU.
|
|
52
|
+
|
|
53
|
+
## Desempeño
|
|
54
|
+
|
|
55
|
+
Evaluado sobre el **conjunto de prueba independiente oficial** de mACPpred 2.0
|
|
56
|
+
(610 ACPs y 2.760 no-ACPs), sin haber visto ninguna de esas secuencias durante el entrenamiento:
|
|
57
|
+
|
|
58
|
+
| Métrica | Valor |
|
|
59
|
+
|---|---|
|
|
60
|
+
| AUC-ROC | **0.8745** |
|
|
61
|
+
| F1-score | 0.6230 |
|
|
62
|
+
| Exactitud | 0.8362 |
|
|
63
|
+
| MCC | 0.5341 |
|
|
64
|
+
|
|
65
|
+
Como referencia, sobre ese mismo conjunto mACPpred 2.0 reporta un AUC-ROC de 0.887 y
|
|
66
|
+
MLACP 2.0 uno de 0.893. Este paquete no supera a ninguna de las dos, pero sí a las otras
|
|
67
|
+
nueve herramientas con AUC-ROC publicado sobre el conjunto —entre ellas mACPpred (0.842),
|
|
68
|
+
iDACP (0.852) y AntiCP 2.0 en su variante alterna (0.835)—, y lo hace con un modelo de ocho
|
|
69
|
+
millones de parámetros y un clasificador lineal, sin GPU en inferencia.
|
|
70
|
+
|
|
71
|
+
> El conjunto de evaluación está desbalanceado (18,1 % de positivos). Por ese motivo se
|
|
72
|
+
> reporta AUC-ROC como métrica principal, junto con F1 y MCC, y no la exactitud: un
|
|
73
|
+
> clasificador que asignara siempre la clase mayoritaria obtendría un 81,9 % de exactitud
|
|
74
|
+
> sin haber aprendido nada.
|
|
75
|
+
|
|
76
|
+
## Instalación
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pip install acp-classifier
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Desde el código fuente:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
git clone https://github.com/ivan2171977/acp-classifier.git
|
|
86
|
+
cd acp-classifier
|
|
87
|
+
pip install -e .
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Con Conda:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
conda env create -f environment.yml
|
|
94
|
+
conda activate acp-classifier
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Requiere Python 3.9 o superior. La primera ejecución descarga el modelo ESM-2 8M
|
|
98
|
+
(~31 MB) desde HuggingFace y lo deja en caché local.
|
|
99
|
+
|
|
100
|
+
## Uso desde consola
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
# Resultados por pantalla
|
|
104
|
+
acp-classifier -i peptidos.fasta
|
|
105
|
+
|
|
106
|
+
# Resultados a un archivo CSV
|
|
107
|
+
acp-classifier -i peptidos.fasta -o resultados.csv
|
|
108
|
+
|
|
109
|
+
# Umbral de decisión más exigente
|
|
110
|
+
acp-classifier -i peptidos.fasta -o resultados.csv --umbral 0.8
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Opciones:
|
|
114
|
+
|
|
115
|
+
| Opción | Descripción | Por defecto |
|
|
116
|
+
|---|---|---|
|
|
117
|
+
| `-i`, `--input` | Archivo FASTA de entrada (obligatorio) | — |
|
|
118
|
+
| `-o`, `--output` | Archivo CSV de salida | pantalla |
|
|
119
|
+
| `-u`, `--umbral` | Probabilidad mínima para clasificar como ACP | `0.5` |
|
|
120
|
+
| `-b`, `--batch-size` | Secuencias procesadas por lote | `32` |
|
|
121
|
+
| `-m`, `--modelo` | Artefacto `.joblib` alternativo | el incluido |
|
|
122
|
+
| `-q`, `--quiet` | Suprime los mensajes de progreso | — |
|
|
123
|
+
|
|
124
|
+
### Entrada
|
|
125
|
+
|
|
126
|
+
Un archivo FASTA estándar, con una o varias secuencias. Se admiten registros repartidos en
|
|
127
|
+
varias líneas. Los residuos no estándar (`X`, `B`, `Z`, `U`, `O`) se descartan, igual que
|
|
128
|
+
durante el entrenamiento.
|
|
129
|
+
|
|
130
|
+
```fasta
|
|
131
|
+
>peptido_1
|
|
132
|
+
GLFSVVTGVLKAVGKNVAKNVGGSLLEQLKCKKISGGC
|
|
133
|
+
>peptido_2
|
|
134
|
+
NNEQIRRFSQVLLDAGIVTTIRKTRGDDIDA
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Salida
|
|
138
|
+
|
|
139
|
+
```csv
|
|
140
|
+
identificador,secuencia,longitud,probabilidad_acp,prediccion
|
|
141
|
+
peptido_1,GLFSVVTGVLKAVGKNVAKNVGGSLLEQLKCKKISGGC,38,0.7350,ACP
|
|
142
|
+
peptido_2,NNEQIRRFSQVLLDAGIVTTIRKTRGDDIDA,31,0.0643,no-ACP
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Uso desde Python
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
from acp_classifier import AcpClassifier
|
|
149
|
+
|
|
150
|
+
clf = AcpClassifier()
|
|
151
|
+
|
|
152
|
+
# Desde secuencias
|
|
153
|
+
for p in clf.predecir_secuencias(["GIGKFLHSAKKFGKAFVGEIMNS"]):
|
|
154
|
+
print(p.identificador, p.probabilidad_acp, p.prediccion)
|
|
155
|
+
|
|
156
|
+
# Desde un archivo FASTA
|
|
157
|
+
predicciones = clf.predecir_fasta("peptidos.fasta", umbral=0.7)
|
|
158
|
+
|
|
159
|
+
# Solo las probabilidades, como arreglo de NumPy
|
|
160
|
+
probas = clf.probabilidades(["GIGKFLHSAKKFGKAFVGEIMNS", "AAAAAAAAAA"])
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Cómo funciona
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
FASTA → limpieza → ESM-2 8M → mean pooling → StandardScaler → Regresión Logística → CSV
|
|
167
|
+
(20 aa) (320 dim) (C=0.01, saga)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
1. **Lectura y limpieza.** Se conservan únicamente los 20 aminoácidos estándar.
|
|
171
|
+
2. **Embeddings.** `esm2_t6_8M_UR50D` genera un vector de 320 dimensiones por secuencia,
|
|
172
|
+
promediando los estados ocultos de la última capa.
|
|
173
|
+
3. **Normalización.** `StandardScaler` ajustado sobre el conjunto de entrenamiento.
|
|
174
|
+
4. **Clasificación.** Regresión Logística (`C=0.01`, solver `saga`), entrenada sobre las
|
|
175
|
+
2.352 secuencias de `Training.fasta` de mACPpred 2.0.
|
|
176
|
+
|
|
177
|
+
### Por qué el modelo más pequeño
|
|
178
|
+
|
|
179
|
+
Durante el trabajo se evaluaron ESM-2 8M, ESM-2 150M y ProtBERT. **ESM-2 8M obtuvo el mejor
|
|
180
|
+
desempeño**, pese a ser el de menor capacidad. Los péptidos del conjunto de evaluación tienen
|
|
181
|
+
una longitud mediana de 9 residuos: sobre secuencias tan cortas, las representaciones de mayor
|
|
182
|
+
dimensionalidad no aportan poder discriminante y favorecen el sobreajuste.
|
|
183
|
+
|
|
184
|
+
Esto tiene una consecuencia práctica: el modelo con mejor desempeño es también el de menores
|
|
185
|
+
requisitos (31 MB frente a los 1,7 GB de ProtBERT), lo que permite ejecutarlo sin GPU.
|
|
186
|
+
|
|
187
|
+
## Reproducir el entrenamiento
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
python entrenar_modelo.py
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Regenera el artefacto desde los FASTA de mACPpred 2.0, compara las dos estrategias de
|
|
194
|
+
agregación implementadas e imprime las métricas sobre el conjunto de prueba independiente.
|
|
195
|
+
Toma alrededor de un minuto sobre CPU.
|
|
196
|
+
|
|
197
|
+
## Pruebas
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
pip install -e ".[dev]"
|
|
201
|
+
pytest -q
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Limitaciones
|
|
205
|
+
|
|
206
|
+
- La validación es **exclusivamente computacional** (TRL 4). Una predicción positiva es una
|
|
207
|
+
hipótesis a verificar experimentalmente, no una afirmación de actividad biológica.
|
|
208
|
+
- El modelo fue entrenado sobre péptidos de entre 6 y 50 residuos. Su comportamiento fuera de
|
|
209
|
+
ese rango no ha sido caracterizado.
|
|
210
|
+
- Existe un desplazamiento de distribución conocido entre los conjuntos de entrenamiento y
|
|
211
|
+
prueba del benchmark: los ACPs de entrenamiento tienen una longitud mediana de 20 residuos
|
|
212
|
+
frente a 9 en el conjunto de prueba.
|
|
213
|
+
- El desempeño está caracterizado sobre un único benchmark (mACPpred 2.0).
|
|
214
|
+
|
|
215
|
+
## Datos
|
|
216
|
+
|
|
217
|
+
Conjunto de referencia de **mACPpred 2.0** (Sangaraju et al., 2024): 1.176 ACPs y 1.176
|
|
218
|
+
no-ACPs para entrenamiento; 610 ACPs y 2.760 no-ACPs para prueba independiente.
|
|
219
|
+
|
|
220
|
+
## Citación
|
|
221
|
+
|
|
222
|
+
```bibtex
|
|
223
|
+
@software{acp_classifier_2026,
|
|
224
|
+
title = {acp-classifier: clasificación de péptidos anticancerígenos
|
|
225
|
+
mediante modelos de lenguaje proteico},
|
|
226
|
+
author = {Navarro Sinuco, Brayan Arturo and Mendoza Oñate, Ivan Andres},
|
|
227
|
+
year = {2026},
|
|
228
|
+
school = {Universidad Industrial de Santander},
|
|
229
|
+
url = {https://github.com/ivan2171977/acp-classifier}
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Referencias
|
|
234
|
+
|
|
235
|
+
- Lin, Z. et al. (2023). Evolutionary-scale prediction of atomic level protein structure with
|
|
236
|
+
a language model. *Science*, 379(6637), 1123–1130.
|
|
237
|
+
- Sangaraju, V. K. et al. (2024). mACPpred 2.0: Stacked deep learning for anticancer peptide
|
|
238
|
+
prediction. *Journal of Molecular Biology*, 436(17), 168687.
|
|
239
|
+
- Pedregosa, F. et al. (2011). Scikit-learn: Machine learning in Python. *JMLR*, 12, 2825–2830.
|
|
240
|
+
- Wolf, T. et al. (2020). Transformers: State-of-the-art natural language processing. *EMNLP:
|
|
241
|
+
System Demonstrations*, 38–45.
|
|
242
|
+
|
|
243
|
+
## Licencia
|
|
244
|
+
|
|
245
|
+
MIT. Véase [LICENSE](LICENSE).
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# acp-classifier
|
|
2
|
+
|
|
3
|
+
Clasificación de péptidos anticancerígenos (ACPs) a partir de secuencias en formato FASTA,
|
|
4
|
+
mediante representaciones contextuales generadas por el modelo de lenguaje proteico
|
|
5
|
+
**ESM-2** y un clasificador de **Regresión Logística**.
|
|
6
|
+
|
|
7
|
+
Desarrollado como trabajo de grado en la Escuela de Ingeniería de Sistemas e Informática de
|
|
8
|
+
la **Universidad Industrial de Santander**.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Por qué existe
|
|
13
|
+
|
|
14
|
+
Las herramientas de referencia para predicción de ACPs —AntiCP 2.0, MLACP 2.0, mACPpred 2.0,
|
|
15
|
+
ACP-EPC— están disponibles únicamente como servidores web, o como repositorios sin empaquetar.
|
|
16
|
+
Ninguna se instala mediante gestores estándar, lo que dificulta su integración en flujos de
|
|
17
|
+
trabajo bioinformáticos automatizados.
|
|
18
|
+
|
|
19
|
+
`acp-classifier` se instala con `pip`, se ejecuta desde consola y no requiere GPU.
|
|
20
|
+
|
|
21
|
+
## Desempeño
|
|
22
|
+
|
|
23
|
+
Evaluado sobre el **conjunto de prueba independiente oficial** de mACPpred 2.0
|
|
24
|
+
(610 ACPs y 2.760 no-ACPs), sin haber visto ninguna de esas secuencias durante el entrenamiento:
|
|
25
|
+
|
|
26
|
+
| Métrica | Valor |
|
|
27
|
+
|---|---|
|
|
28
|
+
| AUC-ROC | **0.8745** |
|
|
29
|
+
| F1-score | 0.6230 |
|
|
30
|
+
| Exactitud | 0.8362 |
|
|
31
|
+
| MCC | 0.5341 |
|
|
32
|
+
|
|
33
|
+
Como referencia, sobre ese mismo conjunto mACPpred 2.0 reporta un AUC-ROC de 0.887 y
|
|
34
|
+
MLACP 2.0 uno de 0.893. Este paquete no supera a ninguna de las dos, pero sí a las otras
|
|
35
|
+
nueve herramientas con AUC-ROC publicado sobre el conjunto —entre ellas mACPpred (0.842),
|
|
36
|
+
iDACP (0.852) y AntiCP 2.0 en su variante alterna (0.835)—, y lo hace con un modelo de ocho
|
|
37
|
+
millones de parámetros y un clasificador lineal, sin GPU en inferencia.
|
|
38
|
+
|
|
39
|
+
> El conjunto de evaluación está desbalanceado (18,1 % de positivos). Por ese motivo se
|
|
40
|
+
> reporta AUC-ROC como métrica principal, junto con F1 y MCC, y no la exactitud: un
|
|
41
|
+
> clasificador que asignara siempre la clase mayoritaria obtendría un 81,9 % de exactitud
|
|
42
|
+
> sin haber aprendido nada.
|
|
43
|
+
|
|
44
|
+
## Instalación
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install acp-classifier
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Desde el código fuente:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
git clone https://github.com/ivan2171977/acp-classifier.git
|
|
54
|
+
cd acp-classifier
|
|
55
|
+
pip install -e .
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Con Conda:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
conda env create -f environment.yml
|
|
62
|
+
conda activate acp-classifier
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Requiere Python 3.9 o superior. La primera ejecución descarga el modelo ESM-2 8M
|
|
66
|
+
(~31 MB) desde HuggingFace y lo deja en caché local.
|
|
67
|
+
|
|
68
|
+
## Uso desde consola
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Resultados por pantalla
|
|
72
|
+
acp-classifier -i peptidos.fasta
|
|
73
|
+
|
|
74
|
+
# Resultados a un archivo CSV
|
|
75
|
+
acp-classifier -i peptidos.fasta -o resultados.csv
|
|
76
|
+
|
|
77
|
+
# Umbral de decisión más exigente
|
|
78
|
+
acp-classifier -i peptidos.fasta -o resultados.csv --umbral 0.8
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Opciones:
|
|
82
|
+
|
|
83
|
+
| Opción | Descripción | Por defecto |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| `-i`, `--input` | Archivo FASTA de entrada (obligatorio) | — |
|
|
86
|
+
| `-o`, `--output` | Archivo CSV de salida | pantalla |
|
|
87
|
+
| `-u`, `--umbral` | Probabilidad mínima para clasificar como ACP | `0.5` |
|
|
88
|
+
| `-b`, `--batch-size` | Secuencias procesadas por lote | `32` |
|
|
89
|
+
| `-m`, `--modelo` | Artefacto `.joblib` alternativo | el incluido |
|
|
90
|
+
| `-q`, `--quiet` | Suprime los mensajes de progreso | — |
|
|
91
|
+
|
|
92
|
+
### Entrada
|
|
93
|
+
|
|
94
|
+
Un archivo FASTA estándar, con una o varias secuencias. Se admiten registros repartidos en
|
|
95
|
+
varias líneas. Los residuos no estándar (`X`, `B`, `Z`, `U`, `O`) se descartan, igual que
|
|
96
|
+
durante el entrenamiento.
|
|
97
|
+
|
|
98
|
+
```fasta
|
|
99
|
+
>peptido_1
|
|
100
|
+
GLFSVVTGVLKAVGKNVAKNVGGSLLEQLKCKKISGGC
|
|
101
|
+
>peptido_2
|
|
102
|
+
NNEQIRRFSQVLLDAGIVTTIRKTRGDDIDA
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Salida
|
|
106
|
+
|
|
107
|
+
```csv
|
|
108
|
+
identificador,secuencia,longitud,probabilidad_acp,prediccion
|
|
109
|
+
peptido_1,GLFSVVTGVLKAVGKNVAKNVGGSLLEQLKCKKISGGC,38,0.7350,ACP
|
|
110
|
+
peptido_2,NNEQIRRFSQVLLDAGIVTTIRKTRGDDIDA,31,0.0643,no-ACP
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Uso desde Python
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
from acp_classifier import AcpClassifier
|
|
117
|
+
|
|
118
|
+
clf = AcpClassifier()
|
|
119
|
+
|
|
120
|
+
# Desde secuencias
|
|
121
|
+
for p in clf.predecir_secuencias(["GIGKFLHSAKKFGKAFVGEIMNS"]):
|
|
122
|
+
print(p.identificador, p.probabilidad_acp, p.prediccion)
|
|
123
|
+
|
|
124
|
+
# Desde un archivo FASTA
|
|
125
|
+
predicciones = clf.predecir_fasta("peptidos.fasta", umbral=0.7)
|
|
126
|
+
|
|
127
|
+
# Solo las probabilidades, como arreglo de NumPy
|
|
128
|
+
probas = clf.probabilidades(["GIGKFLHSAKKFGKAFVGEIMNS", "AAAAAAAAAA"])
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Cómo funciona
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
FASTA → limpieza → ESM-2 8M → mean pooling → StandardScaler → Regresión Logística → CSV
|
|
135
|
+
(20 aa) (320 dim) (C=0.01, saga)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
1. **Lectura y limpieza.** Se conservan únicamente los 20 aminoácidos estándar.
|
|
139
|
+
2. **Embeddings.** `esm2_t6_8M_UR50D` genera un vector de 320 dimensiones por secuencia,
|
|
140
|
+
promediando los estados ocultos de la última capa.
|
|
141
|
+
3. **Normalización.** `StandardScaler` ajustado sobre el conjunto de entrenamiento.
|
|
142
|
+
4. **Clasificación.** Regresión Logística (`C=0.01`, solver `saga`), entrenada sobre las
|
|
143
|
+
2.352 secuencias de `Training.fasta` de mACPpred 2.0.
|
|
144
|
+
|
|
145
|
+
### Por qué el modelo más pequeño
|
|
146
|
+
|
|
147
|
+
Durante el trabajo se evaluaron ESM-2 8M, ESM-2 150M y ProtBERT. **ESM-2 8M obtuvo el mejor
|
|
148
|
+
desempeño**, pese a ser el de menor capacidad. Los péptidos del conjunto de evaluación tienen
|
|
149
|
+
una longitud mediana de 9 residuos: sobre secuencias tan cortas, las representaciones de mayor
|
|
150
|
+
dimensionalidad no aportan poder discriminante y favorecen el sobreajuste.
|
|
151
|
+
|
|
152
|
+
Esto tiene una consecuencia práctica: el modelo con mejor desempeño es también el de menores
|
|
153
|
+
requisitos (31 MB frente a los 1,7 GB de ProtBERT), lo que permite ejecutarlo sin GPU.
|
|
154
|
+
|
|
155
|
+
## Reproducir el entrenamiento
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
python entrenar_modelo.py
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Regenera el artefacto desde los FASTA de mACPpred 2.0, compara las dos estrategias de
|
|
162
|
+
agregación implementadas e imprime las métricas sobre el conjunto de prueba independiente.
|
|
163
|
+
Toma alrededor de un minuto sobre CPU.
|
|
164
|
+
|
|
165
|
+
## Pruebas
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
pip install -e ".[dev]"
|
|
169
|
+
pytest -q
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Limitaciones
|
|
173
|
+
|
|
174
|
+
- La validación es **exclusivamente computacional** (TRL 4). Una predicción positiva es una
|
|
175
|
+
hipótesis a verificar experimentalmente, no una afirmación de actividad biológica.
|
|
176
|
+
- El modelo fue entrenado sobre péptidos de entre 6 y 50 residuos. Su comportamiento fuera de
|
|
177
|
+
ese rango no ha sido caracterizado.
|
|
178
|
+
- Existe un desplazamiento de distribución conocido entre los conjuntos de entrenamiento y
|
|
179
|
+
prueba del benchmark: los ACPs de entrenamiento tienen una longitud mediana de 20 residuos
|
|
180
|
+
frente a 9 en el conjunto de prueba.
|
|
181
|
+
- El desempeño está caracterizado sobre un único benchmark (mACPpred 2.0).
|
|
182
|
+
|
|
183
|
+
## Datos
|
|
184
|
+
|
|
185
|
+
Conjunto de referencia de **mACPpred 2.0** (Sangaraju et al., 2024): 1.176 ACPs y 1.176
|
|
186
|
+
no-ACPs para entrenamiento; 610 ACPs y 2.760 no-ACPs para prueba independiente.
|
|
187
|
+
|
|
188
|
+
## Citación
|
|
189
|
+
|
|
190
|
+
```bibtex
|
|
191
|
+
@software{acp_classifier_2026,
|
|
192
|
+
title = {acp-classifier: clasificación de péptidos anticancerígenos
|
|
193
|
+
mediante modelos de lenguaje proteico},
|
|
194
|
+
author = {Navarro Sinuco, Brayan Arturo and Mendoza Oñate, Ivan Andres},
|
|
195
|
+
year = {2026},
|
|
196
|
+
school = {Universidad Industrial de Santander},
|
|
197
|
+
url = {https://github.com/ivan2171977/acp-classifier}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Referencias
|
|
202
|
+
|
|
203
|
+
- Lin, Z. et al. (2023). Evolutionary-scale prediction of atomic level protein structure with
|
|
204
|
+
a language model. *Science*, 379(6637), 1123–1130.
|
|
205
|
+
- Sangaraju, V. K. et al. (2024). mACPpred 2.0: Stacked deep learning for anticancer peptide
|
|
206
|
+
prediction. *Journal of Molecular Biology*, 436(17), 168687.
|
|
207
|
+
- Pedregosa, F. et al. (2011). Scikit-learn: Machine learning in Python. *JMLR*, 12, 2825–2830.
|
|
208
|
+
- Wolf, T. et al. (2020). Transformers: State-of-the-art natural language processing. *EMNLP:
|
|
209
|
+
System Demonstrations*, 38–45.
|
|
210
|
+
|
|
211
|
+
## Licencia
|
|
212
|
+
|
|
213
|
+
MIT. Véase [LICENSE](LICENSE).
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "acp-classifier"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Clasificación de péptidos anticancerígenos (ACPs) mediante modelos de lenguaje proteico"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [
|
|
14
|
+
{ name = "Brayan Arturo Navarro Sinuco" },
|
|
15
|
+
{ name = "Ivan Andres Mendoza Oñate" },
|
|
16
|
+
]
|
|
17
|
+
maintainers = [
|
|
18
|
+
{ name = "Escuela de Ingeniería de Sistemas e Informática, Universidad Industrial de Santander" },
|
|
19
|
+
]
|
|
20
|
+
keywords = [
|
|
21
|
+
"bioinformatics", "anticancer-peptides", "acp", "protein-language-model",
|
|
22
|
+
"esm2", "peptide-classification", "machine-learning",
|
|
23
|
+
]
|
|
24
|
+
classifiers = [
|
|
25
|
+
"Development Status :: 4 - Beta",
|
|
26
|
+
"Intended Audience :: Science/Research",
|
|
27
|
+
"Operating System :: OS Independent",
|
|
28
|
+
"Programming Language :: Python :: 3",
|
|
29
|
+
"Programming Language :: Python :: 3.9",
|
|
30
|
+
"Programming Language :: Python :: 3.10",
|
|
31
|
+
"Programming Language :: Python :: 3.11",
|
|
32
|
+
"Programming Language :: Python :: 3.12",
|
|
33
|
+
"Topic :: Scientific/Engineering :: Bio-Informatics",
|
|
34
|
+
]
|
|
35
|
+
dependencies = [
|
|
36
|
+
"numpy>=1.21",
|
|
37
|
+
"joblib>=1.1",
|
|
38
|
+
"torch>=1.11",
|
|
39
|
+
"transformers>=4.20",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[project.optional-dependencies]
|
|
43
|
+
dev = ["pytest>=7.0", "scikit-learn>=1.0"]
|
|
44
|
+
|
|
45
|
+
[project.urls]
|
|
46
|
+
Homepage = "https://github.com/ivan2171977/acp-classifier"
|
|
47
|
+
Repository = "https://github.com/ivan2171977/acp-classifier"
|
|
48
|
+
Issues = "https://github.com/ivan2171977/acp-classifier/issues"
|
|
49
|
+
|
|
50
|
+
[project.scripts]
|
|
51
|
+
acp-classifier = "acp_classifier.cli:main"
|
|
52
|
+
|
|
53
|
+
[tool.setuptools.packages.find]
|
|
54
|
+
where = ["src"]
|
|
55
|
+
|
|
56
|
+
[tool.setuptools.package-data]
|
|
57
|
+
acp_classifier = ["modelos/*.joblib"]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""acp-classifier — clasificación de péptidos anticancerígenos.
|
|
2
|
+
|
|
3
|
+
Universidad Industrial de Santander
|
|
4
|
+
Escuela de Ingeniería de Sistemas e Informática
|
|
5
|
+
Trabajo de grado, 2026
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
__version__ = "1.0.0"
|
|
9
|
+
|
|
10
|
+
from .fasta import ErrorFasta, Peptido, leer_fasta
|
|
11
|
+
from .predictor import AcpClassifier, Prediccion
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"AcpClassifier",
|
|
15
|
+
"Prediccion",
|
|
16
|
+
"Peptido",
|
|
17
|
+
"leer_fasta",
|
|
18
|
+
"ErrorFasta",
|
|
19
|
+
"__version__",
|
|
20
|
+
]
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""Interfaz de línea de comandos de acp-classifier."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import csv
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from . import __version__
|
|
11
|
+
from .fasta import ErrorFasta
|
|
12
|
+
|
|
13
|
+
CAMPOS = ["identificador", "secuencia", "longitud", "probabilidad_acp", "prediccion"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def construir_parser() -> argparse.ArgumentParser:
|
|
17
|
+
p = argparse.ArgumentParser(
|
|
18
|
+
prog="acp-classifier",
|
|
19
|
+
description="Clasificación de péptidos anticancerígenos (ACPs) a partir de "
|
|
20
|
+
"secuencias en formato FASTA, mediante embeddings de ESM-2 y "
|
|
21
|
+
"Regresión Logística.",
|
|
22
|
+
epilog="Ejemplo: acp-classifier -i peptidos.fasta -o resultados.csv",
|
|
23
|
+
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
24
|
+
)
|
|
25
|
+
p.add_argument("-i", "--input", required=True, metavar="FASTA",
|
|
26
|
+
help="archivo FASTA de entrada con una o varias secuencias")
|
|
27
|
+
p.add_argument("-o", "--output", metavar="CSV",
|
|
28
|
+
help="archivo CSV de salida (por defecto se imprime en pantalla)")
|
|
29
|
+
p.add_argument("-u", "--umbral", type=float, default=0.5, metavar="P",
|
|
30
|
+
help="probabilidad mínima para clasificar como ACP")
|
|
31
|
+
p.add_argument("-b", "--batch-size", type=int, default=32, metavar="N",
|
|
32
|
+
help="secuencias procesadas por lote")
|
|
33
|
+
p.add_argument("-m", "--modelo", metavar="RUTA",
|
|
34
|
+
help="artefacto .joblib alternativo (por defecto, el incluido)")
|
|
35
|
+
p.add_argument("-q", "--quiet", action="store_true",
|
|
36
|
+
help="suprime los mensajes de progreso")
|
|
37
|
+
p.add_argument("--version", action="version", version=f"acp-classifier {__version__}")
|
|
38
|
+
return p
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def main(argv: list[str] | None = None) -> int:
|
|
42
|
+
args = construir_parser().parse_args(argv)
|
|
43
|
+
|
|
44
|
+
if not 0.0 < args.umbral < 1.0:
|
|
45
|
+
print("Error: el umbral debe estar entre 0 y 1 (exclusivos).", file=sys.stderr)
|
|
46
|
+
return 2
|
|
47
|
+
|
|
48
|
+
def log(mensaje: str) -> None:
|
|
49
|
+
if not args.quiet:
|
|
50
|
+
print(mensaje, file=sys.stderr)
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
from .predictor import AcpClassifier
|
|
54
|
+
|
|
55
|
+
log("Cargando modelo...")
|
|
56
|
+
clf = AcpClassifier(args.modelo)
|
|
57
|
+
|
|
58
|
+
log(f"Leyendo {args.input}...")
|
|
59
|
+
predicciones = clf.predecir_fasta(args.input, args.umbral, args.batch_size)
|
|
60
|
+
|
|
61
|
+
except ErrorFasta as e:
|
|
62
|
+
print(f"Error de lectura: {e}", file=sys.stderr)
|
|
63
|
+
return 1
|
|
64
|
+
except FileNotFoundError as e:
|
|
65
|
+
print(f"Archivo no encontrado: {e}", file=sys.stderr)
|
|
66
|
+
return 1
|
|
67
|
+
except Exception as e: # noqa: BLE001 - la CLI no debe volcar trazas al usuario
|
|
68
|
+
print(f"Error: {type(e).__name__}: {e}", file=sys.stderr)
|
|
69
|
+
return 1
|
|
70
|
+
|
|
71
|
+
filas = [p.como_dict() for p in predicciones]
|
|
72
|
+
|
|
73
|
+
if args.output:
|
|
74
|
+
destino = Path(args.output)
|
|
75
|
+
destino.parent.mkdir(parents=True, exist_ok=True)
|
|
76
|
+
with destino.open("w", newline="", encoding="utf-8") as fh:
|
|
77
|
+
escritor = csv.DictWriter(fh, fieldnames=CAMPOS)
|
|
78
|
+
escritor.writeheader()
|
|
79
|
+
escritor.writerows(filas)
|
|
80
|
+
log(f"Resultados guardados en {destino}")
|
|
81
|
+
else:
|
|
82
|
+
escritor = csv.DictWriter(sys.stdout, fieldnames=CAMPOS)
|
|
83
|
+
escritor.writeheader()
|
|
84
|
+
escritor.writerows(filas)
|
|
85
|
+
|
|
86
|
+
n_acp = sum(f["prediccion"] == "ACP" for f in filas)
|
|
87
|
+
log(f"\n{len(filas)} secuencias analizadas: {n_acp} ACP, {len(filas) - n_acp} no-ACP")
|
|
88
|
+
return 0
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
if __name__ == "__main__":
|
|
92
|
+
raise SystemExit(main())
|