Artigo
· Maio 16 9min de leitura

Similaridade e Classificação de DNA por Vector Search e Machine Learning

DNA Similarity and Classification é uma API REST utilizando a tecnologia InterSystems Vector Search para investigar semelhanças genéticas e classificar eficientemente sequências de DNA. Este é um aplicativo que utiliza técnicas de inteligência artificial, como aprendizado de máquina, aprimorado por recursos de pesquisa vetorial, para classificar famílias genéticas e identificar DNAs semelhantes conhecidos a partir de um DNA de entrada desconhecido.

Análise K-mer: Fundamentos em Análise de Sequência de DNA

A fragmentação de uma sequência de DNA em k-mers é uma técnica fundamental no processamento de dados genéticos. Esta abordagem envolve quebrar a sequência de DNA em subsequências menores de tamanho fixo, conhecidas como k-mers. Por exemplo, se tomarmos a sequência "ATCGTAGCTA" e definirmos k como 3, obteremos os seguintes k-mers: "ATC", "TCG", "CGT", "GTA", "TAG", "AGC", "GCT" e "CTA".

Este processo é realizado deslizando uma janela de tamanho k ao longo da sequência, extraindo cada subsequência de tamanho k e registrando-a como um k-mer. A janela então se move para o próximo conjunto de bases, permitindo a sobreposição entre os k-mers. Esta sobreposição é crucial para garantir que nenhuma informação seja perdida durante o processo de fragmentação.

Os k-mers resultantes retêm informações locais cruciais sobre a estrutura da sequência de DNA. Isto é crítico porque muitas informações biologicamente relevantes estão contidas em regiões específicas do DNA. A análise subsequente destes k-mers pode revelar padrões, identificar regiões conservadas ou semelhantes entre diferentes sequências de DNA e auxiliar na investigação de funções e interações genéticas.

Em resumo, Similaridade e Classificação de DNA oferecem uma abordagem para identificar semelhanças genéticas e classificar sequências de DNA.

Aplicativo

O código a seguir inicializa o projeto, realizando a configuração necessária antes da construção:

ClassMethod init()
{
    write "START INIT"
    Do ##class(dc.data.DNAClassification).CreateTheModelML()
    Do ##class(dc.data.HumanDNA).UploadData()
}

O UploadDatamétodo implementado no código é responsável por fragmentar sequências de DNA em k-mers, converter esses k-mers em vetores usando um modelo de codificação específico e, em seguida, armazenar esses vetores no banco de dados.

print("Reading dataset")
human_df = pd.read_table('/opt/irisbuild/data/human_data.txt')
human_df = human_df.sample(n=1500, random_state=42)

Para melhorar o desempenho e reduzir o tempo de processamento durante a fase de construção do projeto, é implementado um processo de amostragem, limitando a leitura aos primeiros 1.500 registros do arquivo. Embora esta estratégia acelere o processo, vale a pena notar que uma análise abrangente do arquivo poderia fornecer uma compreensão mais completa dos dados. Porém, devido ao compromisso com a eficiência e ao ritmo de construção, esta abordagem foi adotada.

def getKmers(sequence, size=6, max_length=5000):
    kmers = [sequence[x:x+size].lower() for x in range(len(sequence) - size + 1)]
    kmers = [kmer for kmer in kmers if len(kmer) > 0]
    if len(kmers) == 0:
        return [sequence]
    return kmers[:max_length]

O parâmetro MAX_LEN em getKmers é usado para limitar o tamanho máximo dos k-mers processados ​​para otimizar o tempo de execução do processo. No entanto, é importante notar que esta abordagem pode não ser ideal em termos de representação completa dos dados de ADN.

 print("Creating K-mers groups")
    human_df['K_mers'] = human_df['sequence'].apply(getKmers)

    print("Combining K-mers into strings")
    human_df['K_mers_str'] = human_df['K_mers'].apply(lambda x: ' '.join(x))

    print("Download stsb-roberta-base-v2 model")
    model = SentenceTransformer('stsb-roberta-base-v2')

    print("Encode K_mers")
    embeddings = model.encode(human_df['K_mers_str'].tolist(), normalize_embeddings=True)

    print("Creating column sequence_vectorized")
    human_df['sequence_vectorized'] = embeddings.tolist()

O código vetoriza sequências de DNA usando o modelo de codificação stsb-roberta-base-v2 da biblioteca SentenceTransformer. Esta etapa converte sequências de DNA em vetores numéricos, facilitando sua manipulação vetorial e análise computacional. Após a vetorização, os dados são armazenados no banco de dados para uso futuro. Esta etapa é crucial para garantir que os vetores de sequência de DNA estejam disponíveis para consultas e análises adicionais.

Posteriormente, o método findSimilarity é responsável por encontrar as sequências de DNA mais semelhantes com base em uma entrada de sequência de DNA recebida. Ele fragmenta a sequência de DNA em k-mers e consulta o banco de dados para encontrar as cinco sequências de DNA mais próximas.

ClassMethod findSimilarity(pSequence As %String) As %String [ Language = python ]
{
    import iris
    from sentence_transformers import SentenceTransformer

    results = []

    def getKmers(sequence, size=6, max_length=5000):
        kmers = [sequence[x:x+size].lower() for x in range(len(sequence) - size + 1)]
        kmers = [kmer for kmer in kmers if len(kmer) > 0]
        if len(kmers) == 0:
            return [sequence]
        return kmers[:max_length]
        

    model = SentenceTransformer('stsb-roberta-base-v2') 
    kmers = getKmers(pSequence)
    kmers_str = ' '.join(kmers)
    search_vector = model.encode(kmers_str, normalize_embeddings=True).tolist()

    stmt = iris.sql.prepare("SELECT TOP 5 ID FROM dc_data.HumanDNA ORDER BY VECTOR_DOT_PRODUCT(kMersVector, TO_VECTOR(?)) DESC ")
    rs = stmt.execute(str(search_vector))

    class_mapping = {
            0: 'G protein coupled receptors',
            1: 'tyrosine kinase',
            2: 'tyrosine phosphatase',
            3: 'synthetase',
            4: 'synthase',
            5: 'lon channel',
            6: 'transcription factor',
    }

    for idx, row in enumerate(rs):
        humanDNA = iris.cls("dc.data.HumanDNA")._OpenId(row[0])    

        results.append({
            "sequence": humanDNA.sequence,
            "dnaClass": class_mapping[humanDNA.dnaClass]
        })
    return results
}

Esses processos são essenciais para o projeto, pois permitem a análise comparativa de sequências de DNA e a identificação de padrões ou semelhanças entre elas.

Aprendizado de Máquina Aplicado

O aprendizado de máquina tem sido utilizado para realizar a classificação de sequências de DNA. A classe DNAClassification contém métodos para treinar um modelo de classificação multinomial Naive Bayes e para classificar sequências de DNA com base neste modelo.

O método CreateTheModelML é responsável por treinar o modelo de classificação. Primeiramente, as sequências de DNA são pré-processadas, transformadas em k-mers e agrupadas. Em seguida, esses grupos k-mer são convertidos em uma representação numérica utilizando a técnica de vetorização. O modelo multinomial Naive Bayes é então treinado com esses dados vetorizados. Após o treinamento, o desempenho do modelo é avaliado por meio de análises como precisão, recall e pontuação F1.

ClassMethod CreateTheModelML()
{
    import pandas as pd

    def getKmers(sequence, size=6):
        kmers = [sequence[x:x+size].lower() for x in range(len(sequence) - size + 1)]
        kmers = [kmer for kmer in kmers if len(kmer) > 0]
        if len(kmers) == 0:
            return [sequence]
        return kmers

    print("Reading dataset")
    human_df = pd.read_table('/opt/irisbuild/data/human_data.txt')

    print("Creating K-mers groups")
    human_df['K_mers'] = human_df['sequence'].apply(getKmers)
    
    human_df['words'] = human_df.apply(lambda x: getKmers(x['sequence']), axis=1)
    human_df = human_df.drop('sequence', axis=1)

    human_texts = list(human_df['words'])
    for item in range(len(human_texts)):
        human_texts[item] = ' '.join(human_texts[item])
    y_data = human_df.iloc[:, 0].values        
    
    from sklearn.feature_extraction.text import CountVectorizer
    cv = CountVectorizer(ngram_range=(4,4))
    X_human_dna = cv.fit_transform(human_texts)

    print(X_human_dna.shape)

    print("PREPARING FIT DATA")
    from sklearn.model_selection import train_test_split
    X_train, X_test, y_train, y_test = train_test_split(X_human_dna, 
                                                        y_data, 
                                                        test_size = 0.20, 
                                                        random_state=42)
    
    print("FIT THE MODEL")
    from sklearn.naive_bayes import MultinomialNB
    classifier = MultinomialNB(alpha=0.1)
    classifier.fit(X_train, y_train)

    y_pred = classifier.predict(X_test)

    print("VALIDATING THE MODEL")

    from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score
    print("Confusion matrix\n")
    print(pd.crosstab(pd.Series(y_test, name='Actual'), pd.Series(y_pred, name='Predicted')))
    def get_metrics(y_test, y_predicted):
        accuracy = accuracy_score(y_test, y_predicted)
        precision = precision_score(y_test, y_predicted, average='weighted')
        recall = recall_score(y_test, y_predicted, average='weighted')
        f1 = f1_score(y_test, y_predicted, average='weighted')
        return accuracy, precision, recall, f1
    accuracy, precision, recall, f1 = get_metrics(y_test, y_pred)
    print("accuracy = %.3f \nprecision = %.3f \nrecall = %.3f \nf1 = %.3f" % (accuracy, precision, recall, f1))


    print("SAVE THE MODEL")
    import joblib
    joblib.dump(classifier, '/opt/irisbuild/data/multinomial_nb_model.pkl')
    joblib.dump(cv, '/opt/irisbuild/data/cv_to_multinomial_nb_model.pkl')
}

Por outro lado, o método ClassifyDnaSequence é responsável por classificar as sequências de DNA recebidas como entrada. Primeiramente, a sequência é pré-processada e transformada em k-mers. Então, esses k-mers são vetorizados usando o mesmo processo usado durante o treinamento do modelo. O modelo treinado é então carregado e usado para prever a classe da sequência de DNA. O resultado da classificação inclui a classe prevista e as probabilidades associadas a cada classe.

ClassMethod ClassifyDnaSequence(sequence As %String) As %Status
{
    import joblib
    from sklearn.feature_extraction.text import CountVectorizer

    classifier = joblib.load('/opt/irisbuild/data/multinomial_nb_model.pkl')
    cv = joblib.load('/opt/irisbuild/data/cv_to_multinomial_nb_model.pkl')

    def getKmers(sequence, size=6):
        kmers = [sequence[x:x+size].lower() for x in range(len(sequence) - size + 1)]
        kmers = [kmer for kmer in kmers if len(kmer) > 0]
        if len(kmers) == 0:
            return [sequence]
        return kmers
    k_mers = getKmers(sequence)

    k_mers_vec = cv.transform([' '.join(k_mers)])

    predicted_class = classifier.predict(k_mers_vec)[0]
    probabilities = classifier.predict_proba(k_mers_vec)[0]

    class_mapping = {
            0: 'G protein coupled receptors',
            1: 'tyrosine kinase',
            2: 'tyrosine phosphatase',
            3: 'synthetase',
            4: 'synthase',
            5: 'lon channel',
            6: 'transcription factor',
    }
    

    result = {
        "Classification": class_mapping[predicted_class],
        "Probabilities": {
            class_mapping[class_index]: float(probability)
            for class_index, probability in enumerate(probabilities)
        }
    }
    
    return result
}

Uso do aplicativo

Os usuários interagem com o sistema enviando sequências de DNA por meio de consultas e podem solicitar uma resposta no formato JSON contendo informações sobre as sequências semelhantes descobertas e suas classificações, simplificando o processo de análise genética.

Abaixo está a API a ser usada: http://localhost:52773/api/dna/find?&dna=<YOUR_DNA>

  • dna: Digite a sequência de DNA que você deseja pesquisar

Exemplo: http://localhost:52773/api/dna/find?&dna=ATGAACTGTCCAGCCCCTGTGGAGATCTCCT...

Usando o Postman para visualizar a resposta da API (pode ser feito usando um navegador ou outros aplicativos como o Insomnia):

Projeto:  GitHub

Votação:  similaridade e classificação de DNA

Discussão (1)2
Entre ou crie uma conta para continuar