如何使用交叉验证输出中的最佳模型来使用keras model.product()



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

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

其中有一列具有DNA序列,并且标签可以是0、1、2、3(即该DNA序列的一个类别)。我想开发一个神经网络,预测每个序列分类为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. 从交叉验证中找到最佳模型(我试图将其与monitor-val准确性部分结合起来)
  2. 预测类的序列列表在predlist中
  3. 从训练到predlist的最佳模型拟合
  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中的概率,但也许我错了,它会的。

你在一个问题中问了太多不相关的问题,其中有几个问题。我会努力解决我认为最严重的问题。

首先,如果您有形式的案例

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都不会"保护"你。。。

最新更新