zjunlp/OntoProtein

ontoProtein pretrained model

wenyuhaokikika opened this issue · 4 comments

您好,我想使用ontoProtein计算蛋白质的embedding,我在https://huggingface.co/zjukg/OntoProtein/tree/main
上下载了模型保存在本地,但是不同蛋白计算的embedding是一样的,请问这样正常吗?

  • 下载文件到本地
    包括config.json pytorch_model.bin tokenizer_config.json vocab.txt四个文件
  • 计算embedding的脚本
import logging
import os
from dataclasses import dataclass, field
from typing import Dict, List, Optional, Tuple
from torch.utils.data.dataloader import DataLoader
import yaml
import os
import numpy as np
import torch
from tqdm import tqdm
from transformers import (
    AutoConfig,
    AutoTokenizer,
    AutoModel,
)
import argparse
import torch
import pandas as pd
from tqdm import tqdm
tqdm.pandas()
logger = logging.getLogger(__name__)
device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu")
model_name_or_path = '/data/wenyuhao/55/model/ontology'
config = AutoConfig.from_pretrained(model_name_or_path,)
tokenizer = AutoTokenizer.from_pretrained(model_name_or_path,use_fast=False,)
model = AutoModel.from_pretrained(model_name_or_path,config=config,).to(device)
def getArray(seq):
    input_ids = torch.tensor(tokenizer.encode(seq)).unsqueeze(0).to(device)  # Batch size 1
    with  torch.no_grad():
        outputs = model(input_ids)
    return outputs[1].cpu().numpy()
  • 效果
In [14]: a = getArray('VFYLKMKGDYYRYLAEVASGEKKNSVVEASEAAYKEAFEISKEQMQPTHPIRLGLALNFS')
In [15]: b = getArray('YYKMKGDYHRYLAEFATGNDRKEAAENSLVAYKAASDIAMTELPPTHPIRLGLALNFSVF')
In [16]: a
Out[16]: 
array([[-0.11852779,  0.1262154 , -0.11203501, ...,  0.11941278,
         0.11056887, -0.12232994]], dtype=float32)
In [17]: b
Out[17]: 
array([[-0.11852779,  0.1262154 , -0.11203501, ...,  0.11941278,
         0.11056887, -0.12232994]], dtype=float32)
In [18]: Counter(a[0]==b[0])
Out[18]: Counter({True: 1024})

我计算了swissprot的所有蛋白质,发现都是一样的

In [29]: s
Out[29]: 
array([[-0.11852774,  0.12621534, -0.11203495, ...,  0.11941272,
         0.11056883, -0.12232988],
       [-0.11852774,  0.12621534, -0.11203495, ...,  0.11941272,
         0.11056883, -0.12232988],
       [-0.11852774,  0.12621534, -0.11203495, ...,  0.11941272,
         0.11056883, -0.12232988],
       ...,
       [-0.11852774,  0.12621534, -0.11203495, ...,  0.11941272,
         0.11056883, -0.12232988],
       [-0.11852774,  0.12621534, -0.11203495, ...,  0.11941272,
         0.11056883, -0.12232988],
       [-0.11852774,  0.12621534, -0.11203495, ...,  0.11941272,
         0.11056883, -0.12232988]], dtype=float32)

In [30]: s.shape
Out[30]: (20083, 1024)

In [31]: (s==s).all()
Out[31]: True

你的输入sequence需要经过一定处理,正确的输入氨基酸之间是需要有空格间隔的,不然tokenizer会把整个序列都当作是一个UNK。你可以使用如下方式来解决问题,如果你想使用模型生成蛋白质的embedding,建议使用mean pooling。

" ".join(seq)

或者使用

tokenizer(list(seq), is_split_into_words=True)

原来是这样,已经解决了。谢谢您的回复。这里确实是我的问题,因为之前计算ESM和prottrans时其输入是整段氨基酸序列,所以这里想当然了。

还有一个问题就是关于您这句话,“如果你想使用模型生成蛋白质的embedding,建议使用mean pooling”。事实上,我计算ESM 等embedding时,都是对于每个残基计算了embedding之后,然后进行了mean pooling。

但是对于OntoProtein计算每个残基的embedding进行mean pooling还需要请教。

您的意思是对于每个残基embedding后pool吗?如果说对于每个残基计算embedding再进行mean pooling这样是否会丢失残基之间的顺序信息呢?如果两个序列残基计数相同但是残基顺序不同,那是不是embedding就是相同的呢?

期待您的回复谢谢!!!

你好,

关于“如果两个序列残基计数相同但是残基顺序不同,那是不是embedding就是相同的呢?”这个问题,因为像BERT这类语言模型在输入的时候考虑了位置编码,在经过encoder之后,每个残基的表示对应的是他们的上下文信息特征,如果输入序列打乱,是不会得到相同的残基表示的。

关于如何通过现有的预训练语言模型获得比较好的文本(蛋白质)表示是一个非常值得探究的问题。最近也有工作 [1] 认为在仅通过预训练语言模型获得蛋白质表示特征(encoder不进行微调)应用于下游任务,mean pooling也不是一个最好的方式。如果感兴趣可以了解下。

[1] Learning meaningful representations of protein sequences, nature communications, 2022.

好的 非常感谢