предсказать кхмерский с мультиномиальным NB (scikit-Learn) - PullRequest
0 голосов
/ 15 марта 2020

Я пытаюсь создать классификатор с помощью scikit-learn на python, чтобы предсказать, является ли нуклеотидная последовательность вируса потенциально патогенной c для человека. Я идентифицировал некоторую последовательность как патогены c с 0, а не с 1, последовательность дифференцируется от последовательности к классу с помощью табуляции следующим образом: ATCGATCGAATCGGAT C 1 ATCGGGGGATATATAAATTACATATATTGTTGTATG 1 ATCGTAT 0 ATAAATATTGTATTGCG 0 ... По сути, я получил свою работу от Кри sh Наика https://github.com/krishnaik06/DNA-Sequencing-Classifier/blob/master/DNA%20Sequencing%20and%20applying%20Classifier.ipynb, где он пытался предсказать класс белка. Я просто изменил, чтобы соответствовать своей цели, но проблема в том, что я не нахожу никаких решений, чтобы предсказать патогенность новой последовательности. Вы можете найти данные, которые я использовал на моем gitlab https://gitlab.com/MasterBioinformaticBiostatistics/bioinformatic/virusid.git. Вот код Kri sh Naik, который я использовал со своими данными (эта часть, кажется, работает как модель):

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

#Code modified from Krish Naik https://github.com/krishnaik06/DNA-Sequencing-Classifier/blob/master/DNA%20Sequencing%20and%20applying%20Classifier.ipynb
human_data = pd.read_table('final_petit.txt')
human_data.head()

from IPython.display import Image
Image("Capture1.PNG")

# function to convert sequence strings into k-mer words, default size = 6 (hexamer words)
def getKmers(sequence, size=6):
    return [sequence[x:x+size].lower() for x in range(len(sequence) - size + 1)]

human_data['words'] = human_data.apply(lambda x: getKmers(x['sequence']), axis=1)
human_data = human_data.drop('sequence', axis=1)

human_data.head()

human_texts = list(human_data['words'])
for item in range(len(human_texts)):
    human_texts[item] = ' '.join(human_texts[item])
y_data = human_data.iloc[:, 0].values

print(human_texts[2])

y_data

# Creating the Bag of Words model using CountVectorizer()
# This is equivalent to k-mer counting
# The n-gram size of 4 was previously determined by testing
from sklearn.feature_extraction.text import CountVectorizer
cv = CountVectorizer(ngram_range=(4,4))
X = cv.fit_transform(human_texts)


print(X.shape)


human_data['class'].value_counts().sort_index().plot.bar()

# Splitting the human dataset into the training set and test set
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, 
                                                    y_data, 
                                                    test_size = 0.20, 
                                                    random_state=42)

print(X_train.shape)
print(X_test.shape)


### Multinomial Naive Bayes Classifier ###
# The alpha parameter was determined by grid search previously
from sklearn.naive_bayes import MultinomialNB
classifier = MultinomialNB(alpha=0.1)
classifier.fit(X_train, y_train)

y_pred = classifier.predict(X_test)

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))

Чтобы предсказать новую последовательность, я решил следовать тем же методом, получи и посчитай кхмерские слова моей новой последовательности:

#NEW SEQUENCE
new_seq = pd.read_table('sequence.txt')
new_seq.head()

# function to convert sequence strings into k-mer words, default size = 6 (hexamer words)
def getKmers(sequence, size=6):
    return [sequence[x:x+size].lower() for x in range(len(sequence) - size + 1)]

new_seq['words'] = new_seq.apply(lambda x: getKmers(x['sequence']), axis=1)
new_seq = new_seq.drop('sequence', axis=1)

new_seq.head()

new_seqtext = list(new_seq['words'])
for item in range(len(new_seqtext)):
    new_seqtext[item] = ' '.join(new_seqtext[item])
y_data = new_seq.iloc[:, 0].values


y_data

# Creating the Bag of Words model using CountVectorizer()
# This is equivalent to k-mer counting
# The n-gram size of 4 was previously determined by testing
from sklearn.feature_extraction.text import CountVectorizer
cv = CountVectorizer(ngram_range=(4,4))
U = cv.fit_transform(new_seqtext)

u_pred = classifier.predict(U)

Но предсказание с использованием classifier.predict, похоже, не работает так, как хотелось, даже если последовательность была сокращена, счет в кхмере.

Traceback (most recent call last):
  File "Original.py", line 89, in <module>
    new_seq['words'] = new_seq.apply(lambda x: getKmers(x['sequence']), axis=1)
  File "/home/name/.local/lib/python3.8/site-packages/pandas/core/frame.py", line 6878, in apply
    return op.get_result()
  File "/home/name/.local/lib/python3.8/site-packages/pandas/core/apply.py", line 186, in get_result
    return self.apply_standard()
  File "/home/name/.local/lib/python3.8/site-packages/pandas/core/apply.py", line 295, in apply_standard
    result = libreduction.compute_reduction(
  File "pandas/_libs/reduction.pyx", line 618, in pandas._libs.reduction.compute_reduction
  File "pandas/_libs/reduction.pyx", line 128, in pandas._libs.reduction.Reducer.get_result
  File "Original.py", line 89, in <lambda>
    new_seq['words'] = new_seq.apply(lambda x: getKmers(x['sequence']), axis=1)
  File "/home/name/.local/lib/python3.8/site-packages/pandas/core/series.py", line 871, in __getitem__
    result = self.index.get_value(self, key)
  File "/home/name/.local/lib/python3.8/site-packages/pandas/core/indexes/base.py", line 4419, in get_value
    raise e1
  File "/home/name/.local/lib/python3.8/site-packages/pandas/core/indexes/base.py", line 4405, in get_value
    return self._engine.get_value(s, k, tz=getattr(series.dtype, "tz", None))
  File "pandas/_libs/index.pyx", line 80, in pandas._libs.index.IndexEngine.get_value
  File "pandas/_libs/index.pyx", line 90, in pandas._libs.index.IndexEngine.get_value
  File "pandas/_libs/index.pyx", line 138, in pandas._libs.index.IndexEngine.get_loc
  File "pandas/_libs/hashtable_class_helper.pxi", line 1618, in pandas._libs.hashtable.PyObjectHashTable.get_item
  File "pandas/_libs/hashtable_class_helper.pxi", line 1626, in pandas._libs.hashtable.PyObjectHashTable.get_item
KeyError: 'sequence'

Программа, кажется, потерпела крах на этом шаге:

new_seq['words'] = new_seq.apply(lambda x: getKmers(x['sequence']), axis=1)

Не слишком ли мой подход слишком наивен, чтобы получить кхмерский текст новой последовательности?

1 Ответ

0 голосов
/ 15 марта 2020

Решение от товарища по команде найдено: Вместо использования

from sklearn.feature_extraction.text import CountVectorizer
cv = CountVectorizer(ngram_range=(4,4))
U = cv.fit_transform(new_seqtext)

Вы можете использовать это:

U = cv.transform(new_seqtext)

fit_transform используется для построения модели, как я понял до сих пор, и нет необходимости импортировать снова, и cv всегда был объявлен ...

...