Keras 在同一时期,该LSTM的损耗和精度均降至接近0

Keras 在同一时期,该LSTM的损耗和精度均降至接近0,keras,deep-learning,lstm,Keras,Deep Learning,Lstm,我试图训练一个LSTM,使用前面的N-1标记预测N标记 对于每一个热编码令牌,我尝试预测下一个令牌。经过三层LSTM后,结果被送入密集层(用heTimeDistributedlayer包装器包装),以将结果重新编码为同一个热编码 奇怪的是,经过几个时代之后,准确度(训练和验证)下降到接近0(坏消息),而损失也下降到接近0(好消息?) 为什么会发生这种情况? 我知道,我不能期望损失和准确度总是朝着相反的方向发展(因为损失在所有类别中使用分类交叉熵,而准确度仅使用最佳或k最佳类别),但是——这种行

我试图训练一个LSTM,使用前面的
N-1
标记预测
N
标记

对于每一个热编码令牌,我尝试预测下一个令牌。经过三层LSTM后,结果被送入密集层(用he
TimeDistributed
layer包装器包装),以将结果重新编码为同一个热编码

奇怪的是,经过几个时代之后,准确度(训练和验证)下降到接近0(坏消息),而损失也下降到接近0(好消息?)

为什么会发生这种情况? 我知道,我不能期望损失和准确度总是朝着相反的方向发展(因为损失在所有类别中使用分类交叉熵,而准确度仅使用最佳或k最佳类别),但是——这种行为是非常意外和无法解释的

这是什么原因? 我做错什么了吗? 我应该如何更改代码以使我的网络朝着越来越准确的预测前进

我的代码如下:

import numpy as np
import glob

import keras
from keras.models import Sequential
from keras.layers import LSTM, Dense, TimeDistributed,Lambda, Dropout, Activation
from keras.metrics import top_k_categorical_accuracy
from keras.callbacks import ModelCheckpoint

###
import matplotlib
matplotlib.use('Agg') # prevents it from failing when there is no display
import matplotlib.pyplot as plt
import keras.backend as K
###

name='Try_6'
model_designation=str(name)+'_'

train_val_split=0.2 # portion to be placed in validation


train_control_number=0
val_control_number=0
batch_size = 16

def my_3D_top_5(true, pred):
    features_num=int(list(pred.shape)[-1])

    true = K.reshape(true, (-1, features_num))   
    pred = K.reshape(pred, (-1, features_num))
    return top_k_categorical_accuracy(true, pred, k=5)

def my_3D_top_10(true, pred):
    features_num=int(list(pred.shape)[-1])

    true = K.reshape(true, (-1, features_num))   
    pred = K.reshape(pred, (-1, features_num))
    return top_k_categorical_accuracy(true, pred, k=10)



def basic_LSTM(features_num):
    model = Sequential()
    model.add(LSTM(40, return_sequences=True, input_shape=(None, features_num)))
    model.add(LSTM(40, return_sequences=True))
    model.add(LSTM(40, return_sequences=True))

    model.add(TimeDistributed(Dense(features_num)))
    model.add(Activation('linear')) 

    print(model.summary())
    model.compile(loss='categorical_crossentropy', optimizer='adam',metrics=['accuracy',my_3D_top_5,my_3D_top_10])  
    return (model)


def main ():
    input_files=glob.glob('*npy')
    data_list,dim=loader(input_files)
    train_list,val_list=data_spliter(data_list)

    train_list=group_data(train_list,batch_size)
    val_list=group_data(val_list,batch_size)

    filepath = "saved-model-"+model_designation+"-{epoch:02d}.hdf5"
    checkpoint = ModelCheckpoint(filepath, save_best_only=False)
    callbacks_list=[checkpoint] 


    model=basic_LSTM(dim)
    history=model.fit_generator(train_generator(train_list), steps_per_epoch=len(train_list), epochs=30, verbose=1,validation_data=val_generator(val_list),validation_steps=len(val_list),callbacks=callbacks_list)
    report(history)


def group_data(data_list,size):  # groups data and elongate it to match
    output=[]
    list_of_sizes=[]
    for data in data_list:
        list_of_sizes.append(list(data.shape)[1]) 

    data_list = [x for _, x in sorted(zip(list_of_sizes,data_list), key=lambda pair: pair[0])]

    while len(data_list)>size:
        this=data_list[:size]
        data_list=data_list[size:]
        combined=(elongate_and_combine(this))
        output.append(combined)


    combined=(elongate_and_combine(data_list))
    output.append(combined)


    return (output)

def elongate_and_combine(data_list):

    max_length= (list(data_list[-1].shape)[1]) 
    last_element=list.pop(data_list)
    output=last_element




    stop_codon=last_element[0,(max_length-1),:]
    stop_codon=stop_codon.reshape(1,1,stop_codon.size)

    for data in data_list:
        size_of_data=list(data.shape)[1]
        while size_of_data<max_length:
            data=np.append(data, stop_codon, axis=1)
            size_of_data=list(data.shape)[1]
        output=np.append(output, data, axis=0)


    return (output)


def train_generator(data_list):
    while True:
        global train_control_number
        train_control_number=cycle_throught(len(data_list),train_control_number)
        #print (train_control_number)       
        this=data_list[train_control_number]


        x_train = this [:,:-1,:] # all but the last 1
        y_train = this [:,1:,:] # all but the first 1

        yield (x_train, y_train)




def val_generator(data_list):
    while True:
        global val_control_number
        val_control_number=cycle_throught(len(data_list),val_control_number)
        #print (val_control_number)     
        this=data_list[val_control_number]
        x_train = this [:,:-1,:] # all but the last 1
        y_train = this [:,1:,:] # all but the first 1

        yield (x_train, y_train)



def cycle_throught (total,current):
    current+=1
    if (current==total):
        current=0
    return (current)


def loader(input_files):

    data_list=[]

    for input_file in input_files:
        a=np.load (input_file)
        incoming_shape=list(a.shape)
        requested_shape=[1]+incoming_shape
        a=a.reshape(requested_shape)
        #print (a.shape)
        data_list.append(a)


    return (data_list,incoming_shape[-1])


def data_spliter(input_list):
    val_num=int(len(input_list)*train_val_split)
    validation=input_list[:val_num]
    train=input_list[val_num:]

    return (train,validation)

def report(history) :


    print(history.history.keys())


    acc = history.history['acc']
    val_acc = history.history['val_acc']

    loss = history.history['loss']
    val_loss = history.history['val_loss']

    acc_5=history.history['my_3D_top_5']
    val_acc_5=history.history['val_my_3D_top_5']

    acc_10=history.history['my_3D_top_10']
    val_acc_10=history.history['val_my_3D_top_10']



    epochs = range(1, len(acc) + 1)

    fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10, 6))



    axes[0][0].plot(epochs, acc, 'bo', label='Training acc')
    axes[0][0].plot(epochs, val_acc, 'b', label='Validation acc')
    axes[0][0].set_title('Training and validation accuracy')
    axes[0][0].legend()



    axes[0][1].plot(epochs, loss, 'ro', label='Training loss')
    axes[0][1].plot(epochs, val_loss, 'r', label='Validation loss')
    axes[0][1].set_title('Training and validation loss')
    axes[0][1].legend()

    axes[1][0].plot(epochs, acc_5, 'go', label='Training acc over top 5')
    axes[1][0].plot(epochs, val_acc_5, 'g', label='Validation acc over top 5')
    axes[1][0].set_title('Training and validation accuracy over top 5')
    axes[1][0].legend()

    axes[1][1].plot(epochs, acc_10, 'mo', label='Training acc over top 10')
    axes[1][1].plot(epochs, val_acc_10, 'm', label='Validation acc over top 10')
    axes[1][1].set_title('Training and validation accuracy over top 10')
    axes[1][1].legend()

    fig.tight_layout()
    fig.savefig('fig_'+name+'.png')   # save the figure to file



main()
将numpy导入为np
导入glob
进口干酪
从keras.models导入顺序
从keras.layers导入LSTM、稠密、时间分布、λ、衰减、激活
从keras.metrics导入顶级分类精度
从keras.callbacks导入模型检查点
###
导入matplotlib
matplotlib.use('Agg')#防止在没有显示时失败
将matplotlib.pyplot作为plt导入
将keras.backend作为K导入
###
name='Try_6'
型号名称=str(名称)+“UU”
列值分割=0.2#待进行验证的部分
列车控制号=0
val_控制_编号=0
批量大小=16
def my_3D_top_5(正确,预测):
特性\u num=int(列表(pred.shape)[-1])
真=K.重塑(真,(-1,特征数量))
pred=K.重塑(pred,(-1,特征数量))
返回top_k_分类精度(true,pred,k=5)
def my_3D_top_10(正确,预测):
特性\u num=int(列表(pred.shape)[-1])
真=K.重塑(真,(-1,特征数量))
pred=K.重塑(pred,(-1,特征数量))
返回最高分类精度(真,预测,k=10)
def基本功能(功能数量):
模型=顺序()
添加(LSTM(40,返回序列=True,输入形状=(无,特征数)))
model.add(LSTM(40,返回序列=True))
model.add(LSTM(40,返回序列=True))
添加(时间分布(密集(特征数量)))
model.add(激活('linear'))
打印(model.summary())
编译(loss='classifical\u crossentropy',optimizer='adam',metrics=['accurity',my\u 3D\u top\u 5,my\u 3D\u top\u 10])
退货(型号)
defmain():
input_files=glob.glob(“*npy”)
数据列表,dim=加载器(输入文件)
列列表,值列表=数据拆分器(数据列表)
列车列表=组数据(列车列表、批次大小)
val_列表=组数据(val_列表、批次大小)
filepath=“保存的模型-”+模型名称+“-{epoch:02d}.hdf5”
checkpoint=ModelCheckpoint(filepath,save\u best\u only=False)
回调\u列表=[检查点]
型号=基本尺寸(dim)
历史=模型。拟合生成器(序列生成器(序列列表),每个历元的步数=len(序列列表),历元数=30,详细度=1,验证数据=val生成器(val列表),验证步骤=len(val列表),回调=回调列表)
报告(历史)
def group_数据(数据列表、大小):#对数据进行分组并将其拉长以匹配
输出=[]
大小列表=[]
对于数据列表中的数据:
大小的列表。\u.append(list(data.shape)[1])
data_list=[x代表uuuuuuuux,已排序(zip(大小列表,数据列表),key=lambda pair:pair[0])]
而len(数据列表)>大小:
此=数据列表[:大小]
数据列表=数据列表[大小:]
组合=(拉长_和_组合(此))
output.append(组合)
组合=(拉长和组合(数据列表))
output.append(组合)
返回(输出)
def拉长_和_组合(数据_列表):
最大长度=(列表(数据列表[-1]。形状)[1])
最后一个元素=list.pop(数据列表)
输出=最后一个元素
停止密码子=最后一个元素[0,(最大长度-1),:]
stop_密码子=stop_密码子。重塑(1,1,stop_密码子。大小)
对于数据列表中的数据:
数据的大小=列表(data.shape)[1]

当数据的大小时,图形中的精度和损失下降到0的原因是此时输出变为
nan
。 这也会导致丢失变为
nan
,显然
matplotlib
将其视为0。在这种情况下,准确度当然是零

我的错误是在解码层使用线性而不是softmax激活

更换后

model.add(Activation('linear'))

该模型没有折叠为
nan
,而是提高了精度


小问题:您编写了“在两层LSTM之后,结果将被馈送到一个密集层”,但在您的代码中有三层LSTM。谢谢,您是正确的。我纠正了我的问题。
model.add(Activation('softmax'))