首页 > 解决方案 > 如何使用交叉验证输出中的最佳模型来使用 keras model.predict()?

问题描述

我有一个这样的 DNA 序列数据框:

Feature         Label
GCTAGATGACAGT   0
TTTTAAAACAG     1
TAGCTATACT      2    
TGGGGCAAAAAAAA  0
AATGTCG         3
AATGTCG         0
AATGTCG         1

其中有一列带有 DNA 序列,并且标签可以是 0、1、2、3(即该 DNA 序列的类别)。我想开发一个 NN 来预测每个序列分类为 1,2 或 3 类别的概率(不是 0,我不关心 0)。每个序列可以在数据框中出现多次,并且每个序列有可能出现在多个(或所有)类别中。所以输出应该是这样的:

GCTAGATGACAGT   (0.9,0.1,0.2)
TTTTAAAACAG     (0.7,0.6,0.3)
TAGCTATACT      (0.3,0.3,0.2)    
TGGGGCAAAAAAAA  (0.1,0.5,0.6)

其中元组中的数字是在类别 1,2 和 3 中找到序列的概率。

这是我的代码:

import numpy
from keras.datasets import imdb
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.layers import Dropout
from keras.layers.embeddings import Embedding
from keras.preprocessing import sequence
from sklearn.model_selection import StratifiedKFold
from keras.callbacks import EarlyStopping, ModelCheckpoint
import matplotlib
from matplotlib import pyplot
import os
from random import random
from numpy import array
from numpy import cumsum
import pandas as pd
from keras.layers import TimeDistributed
from keras.layers import Bidirectional
from keras.preprocessing.text import Tokenizer
from sklearn.preprocessing import LabelEncoder
os.environ['KMP_DUPLICATE_LIB_OK']='True'
%matplotlib
from sklearn.feature_extraction.text import CountVectorizer


# define 10-fold cross validation test harness
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)

#read in the file
df = pd.read_csv('dna_sequences.txt')
X = list(df['dna_sequence'])
y = list(df['class'])


#convert the sequences to integers for learning
tokenizer = Tokenizer(num_words=5,char_level=True)
tokenizer.fit_on_texts(X)
data_encoded = tokenizer.texts_to_matrix(X,mode='count')

kf = kfold.get_n_splits(data_encoded)
cvscores = []

#for each train, test in cross validation sub-set
for train, test in kfold.split(data_encoded, y):

    X_train, X_test = data_encoded[train], data_encoded[test]
    y_train, y_test = data_encoded[train], data_encoded[test]

    #add layers to model
    model = Sequential()
    model.add(Embedding(3000, 32, input_length=5))
    model.add(Dropout(0.2))
    model.add(Bidirectional(LSTM(20, return_sequences=True), input_shape=(5, 1)))
    model.add(LSTM(100))
    model.add(Dropout(0.2))
    model.add(Dense(5, activation='sigmoid'))

    #compile the model
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

    #check the model
    print(model.summary())

    #monitor val accuracy and perform early stopping
    es = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=200)
    mc = ModelCheckpoint('best_model.h5', monitor='val_accuracy', mode='max', verbose=1, save_best_only=True)

    #fit the model
    model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=5, batch_size=64) #change values

    #evaluate the model
    scores = model.evaluate(X_test, y_test, verbose=0)
    print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
    cvscores.append(scores[1] * 100)

#check the accuracy
print("%.2f%% (+/- %.2f%%)" % (numpy.mean(cvscores), numpy.std(cvscores)))



#predict for new set of seqs
pred_list = ['GTGTGCGCT','GGGGGTCGCTCCCCCC','AAATGTTGT','GTGTGTGGG','CCCCTATATA']

#output a probability of sequence being found in each class as described above, and plot accuracy and loss

它运行,并按预期打印准确度(准确度不是很好,62%,但我可以解决这个问题,这是我的第一个 NN,只是想运行一个示例)。

我的问题是专门关于预测的。有人可以向我展示一个从拟合模型(我在上面有)到实际预测的跳跃示例。我认为该算法涉及:

  1. 从交叉验证中找到最佳模型(我试图将其与监视器验证精度部分结合起来)
  2. 预测类别的序列列表在 pred_list 中
  3. 将训练中的最佳模型拟合到 pred_list
  4. 如问题顶部所述的返回概率。

我知道这存在于其他问题(例如这里):

prediction = model.predict(np.array(tk.texts_to_sequences(text)))
print(prediction)

....但我不知道如何将其与交叉验证结合起来,并且以某种方式获得我想要的输出(即在训练中分配给类 1,2 或 3 的每个序列的三类概率数据集,其中每个序列可以出现在多个类中)。

编辑1:根据以下评论,我将代码的结尾更改为:

(在交叉验证循环中,所以应该缩进)

#evaluate the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
cvscores.append(scores[1] * 100)

#predict for new set of seqs
pred_list = ['GTGTGCGCT','GGGGGTCGCTCCCCCC','AAATGTTGT','GTGTGTGGG','CCCCTATATA', 'GGGGGGGGGTTTTTTTT']
prediction = model.predict(np.array(tokenizer.texts_to_sequences(pred_list)))
predcvscores.append(prediction)

(超出交叉验证循环)

print(predcvscores)

#check the accuracy
print("%.2f%% (+/- %.2f%%)" % (numpy.mean(cvscores), numpy.std(cvscores)))

我得到错误:

Error when checking input: expected embedding_3_input to have shape (5,) but got array with shape (1,)

我想这是说我不能只读一组像 pred_list 这样的序列?是不可能做到这一点,还是我没有采取正确的方法?另外,我不确定这种方法是否会给我,对于 pred_list 中的每个项目,输出是出现在类别 1,2 或 3 中的概率,但也许我错了,它会。

标签: pythontensorflowmachine-learningkerasdeep-learning

解决方案


你在一个问题中问了太多且完全不相关的事情,并且其中有几个问题。我将尝试解决我认为最严重的问题。

首先,如果您有表格的案例

Feature         Label
AATGTCG         3
AATGTCG         0
AATGTCG         1

即相同的单个特征可以属于 0、1 或 3 类,而没有任何其他特征,那么这里的信息是监督分类可能不适合您手头的问题;为此,您应该使用附加功能。

如您所说,如果您只对第 1、2 和 3 类感兴趣,并且

不是0,我不在乎0

那么在数据准备阶段你应该做的第一件事就是从数据集中删除所有类 0 的实例;目前尚不清楚您是否在这里这样做,即使这样做,也不清楚为什么您仍将 0 级留在讨论中。

其次(假设您的分类问题中确实只剩下 3 个类),您将显示为模型的预期输出:

GCTAGATGACAGT   (0.9,0.1,0.2)
TTTTAAAACAG     (0.7,0.6,0.3)
TAGCTATACT      (0.3,0.3,0.2)    
TGGGGCAAAAAAAA  (0.1,0.5,0.6)

正确;在多类分类中,返回的概率(即此处括号中的数字)必须加起来正好为 1,而此处并非如此。

第三,由于您有一个多类分类问题,您的损失应该是categorical_crossentropy,而不是binary_crossentropy,这仅用于二元分类问题。

第四,再次假设你只剩下 3 个类,你的模型的最后一层应该是

model.add(Dense(3, activation='softmax') # no. of units here should be equal to the no. of classes)

而您的标签y应该是一次性编码的(您可以使用 Keras 函数轻松地做到这一点to_categorical)。

第五,在循环开始时仔细查看数据定义:

X_train, X_test = data_encoded[train], data_encoded[test]
y_train, y_test = data_encoded[train], data_encoded[test]

您可以轻松地看到您将特征作为特征标签传递。我只能猜测这一定是您这边的错字;标签应该是:

y_train, y_test = y[train], y[test]

关于您的预测时间错误

Error when checking input: expected embedding_3_input to have shape (5,) but got array with shape (1,)

这是由于input_length=5嵌入层中的参数。我要在这里承认,我对 Keras 嵌入层一点也不熟悉。您可能需要检查文档以确保此参数和分配的值确实符合您的想法/打算做的事情。

除此之外,关于您的具体问题:

我的问题是专门关于预测的。有人可以向我展示一个从拟合模型(我在上面有)到实际预测的跳跃示例。

您应该在 CV 循环之外重新编译并重新拟合模型(可能使用在 CV 期间发现的“最佳”时期数)与整个数据,然后将其用于预测。


我想现在应该很清楚了,鉴于上述问题,您报告的 62% 的准确度实际上并不意味着什么;无论好坏,如果您尝试做从建模角度来看没有意义的事情(就像我上面提到的大多数事情),Keras 都不会“保护”您,例如在多类问题中使用二元交叉熵,或在回归设置中使用准确性...


推荐阅读