将Keras模型的部分定义抽象为模型时,我得到的网络表现不佳

问题描述

我正在使用一个公开且众所周知的数据集“钻石”。我创建了一个预测价格(回归)和削减(分类)的NN。该模型的体系结构非常精细-如您在我提供的代码中所见-因此我想到将网络的各个部分抽象为单独的模型,并在整体模型的组成中使用这些模型。

结果是,NN的性能不如原始网络好,但表现不佳。具体来说,第一个模型的auc = 0.91,而第二个模型的auc = 0.88。第一个模型的r2分数= 0.92,而第二个模型的r2分数= 0.94。

我正在寻找这种现象的解释,可能是解决它的一种方法。抽象非常有用,但性能也很重要!

代码如下:

import seaborn as sns

data = sns.load_dataset('diamonds')

mask = (data.cut == 'Ideal')

data['cut'][mask] = 1

data['cut'][~mask] = 0

data['color'] = data['color'].astype('category').cat.codes
data['clarity'] = data['clarity'].astype('category').cat.codes

def f_features_to_dictionary(data):
    
    '''
    
    It takes as input a dataframe and returns a dictionary where each column is a key and each value contains the values of the respective columns of the dataframe 
    
    
    '''
    
    data_dict = {}
    
    for col in data.columns.tolist():
        
        data_dict[col] = data[col].values
        
    return(data_dict)

data = data.sample(frac = 1,random_state = 7)

train = data.iloc[:-4000,:]

dev = data.iloc[-4000 : -2000,:]

test = data.iloc[-2000 :,:]

train_targets = train[['cut','price']]
dev_targets = dev[['cut','price']]
test_targets = test[['cut','price']]

train_features = train[['carat','color','clarity','depth','table','x','y','z']]
dev_features = dev[['carat','z']]
test_features = test[['carat','z']]

scaler = StandardScaler()
train_features[['carat','z']] = scaler.fit_transform(train_features[['carat','z']])
dev_features[['carat','z']] = scaler.transform(dev_features[['carat','z']])
test_features[['carat','z']] = scaler.transform(test_features[['carat','z']])

train_features_dict = f_features_to_dictionary(train_features)
dev_features_dict = f_features_to_dictionary(dev_features)
test_features_dict = f_features_to_dictionary(test_features)

train_targets_dict = f_features_to_dictionary(train_targets)
dev_targets_dict = f_features_to_dictionary(dev_targets)
test_targets_dict = f_features_to_dictionary(test_targets)

def f_make_features_targets_list_out_of_dictionaries(features_dictionary,targets_dictionary):
    
    '''
   
    
    The function takes as inputs the features_dictionary and targets_dictionary containing features and targets and converts them to lists to be passed to the fit() method of a Keras Model
    
    
    '''
    
    features_list = []
    
    targets_list = []
    
    for key in features_dictionary.keys():
    
        features_list.append(features_dictionary[key].astype('float32'))
        
    for key in targets_dictionary.keys():
        
        targets_list.append(targets_dictionary[key].astype('float32'))
        
    return(features_list,targets_list)

train_features_list,train_targets_list = f_make_features_targets_list_out_of_dictionaries(train_features_dict,train_targets_dict)

dev_features_list,dev_targets_list = f_make_features_targets_list_out_of_dictionaries(dev_features_dict,dev_targets_dict)

test_features_list,test_targets_list = f_make_features_targets_list_out_of_dictionaries(test_features_dict,test_targets_dict)

dense1 = 2**7
dense2 = 2**8
dense3 = 2**9
dropout = 0.8
price_loss = 1
cut_loss = 1
activation= LeakyReLU()
batch_size = 20
threshold = 0.7
#====================================================================

# INPUTS

#====================================================================


#----------------------------------------------------------------

carat = Input(
    shape= (1,),batch_size= batch_size,name= 'carat'
)

#----------------------------------------------------------------

Color = Input(
    shape= (1,name= 'color'
)

#----------------------------------------------------------------

Clarity = Input(
    shape= (1,name= 'clarity'
)

#----------------------------------------------------------------

depth = Input(
    shape= (1,name= 'depth'
)

#----------------------------------------------------------------

table = Input(
    shape= (1,name= 'table'
)

#----------------------------------------------------------------

X = Input(
    shape= (1,name= 'x'
)

#----------------------------------------------------------------

y = Input(
    shape= (1,name= 'y'
)

#----------------------------------------------------------------

z = Input(
    shape= (1,name= 'z'
)

#----------------------------------------------------------------

#====================================================================

# CREATE EMbedDINGS FOR CATEGORICAL FEATURES "COLOR" AND "CLARITY"

#====================================================================


color_add_cut = Embedding(input_dim = 7,output_dim = 1,name = 'color_emb_cut_add')(Color)

color_mult_cut = Embedding(input_dim = 7,name = 'color_emb_cut_mult')(Color)

clarity_add_cut = Embedding(input_dim = 8,name = 'clarity_emb_cut_add')(Clarity)

clarity_mult_cut = Embedding(input_dim = 8,name = 'clarity_emb_cut_mult')(Clarity)

color_add_cut = Flatten()(color_add_cut)

color_mult_cut = Flatten()(color_mult_cut)

clarity_add_cut = Flatten()(clarity_add_cut)

clarity_mult_cut = Flatten()(clarity_mult_cut)



#------------------------------------------------------------------------------------------------

color_add_price = Embedding(input_dim = 7,name = 'color_emb_price_add')(Color)

color_mult_price = Embedding(input_dim = 7,name = 'color_emb_price_mult')(Color)

clarity_add_price = Embedding(input_dim = 8,name = 'clarity_emb_price_add')(Clarity)

clarity_mult_price = Embedding(input_dim = 8,name = 'clarity_emb_price_mult')(Clarity)

color_add_price = Flatten()(color_add_price)

color_mult_price = Flatten()(color_mult_price)

clarity_add_price = Flatten()(clarity_add_price)

clarity_mult_price = Flatten()(clarity_mult_price)



#====================================================================

# CONCATENATE FEATURES

#====================================================================


Y = Concatenate()([carat,depth,table,X,y,z])


#====================================================================

# DENSE NETWORK FOR BOTH PRICE AND CUT

#====================================================================

Y = Dense(dense1,activation = activation)(Y)

Y = Batchnormalization()(Y)

Y = Dense(dense2,activation = activation)(Y)

Y = Batchnormalization()(Y)



#====================================================================

# DENSE NETWORK TO PREDICT CUT

#====================================================================

x = Dense(dense3,activation = activation)(Y)

x = Batchnormalization()(x)

x = Dropout(dropout)(x)

#====================================================================

# PREDICTING CUT USING THE EMbedDINGS AND SKIP CONNECTIONS

# ====================================================================

x = Dense(1)(x)

#-------------------------------------------------------------

# THE EFFECT OF COLOR ON CUT

#-------------------------------------------------------------

cut = Multiply()([color_mult_cut,x])

cut = Add()([color_add_cut,cut])

cut = Dense(1)(cut)

x = Add()([x,cut])  # The Skip connection

#-------------------------------------------------------------

# THE EFFECT OF CLARITY ON CUT

#-------------------------------------------------------------

cut = Multiply()([clarity_mult_cut,x])

cut = Add()([clarity_add_cut,cut])

cut = Dense(1)(cut)

cut = Add()([x,cut])  # The Skip connection

#-------------------------------------------------------------

# THE PREDICTIONS FOR CUT

#-------------------------------------------------------------

cut = Dense(1,activation = 'sigmoid',name = 'cut')(cut)

#------------------------------------------------------------------------


#====================================================================

# PREDICTING PRICE USING THE EMbedDINGS AND SKIP CONNECTIONS

# ====================================================================

#====================================================================

# DENSE NETWORK TO PREDICT CUT

#====================================================================

x = Dense(dense3,activation = activation)(Y)

x = Batchnormalization()(x)

x = Dropout(dropout)(x)

#====================================================================

# PREDICTING CUT USING THE EMbedDINGS AND SKIP CONNECTIONS

# ====================================================================

x = Dense(1)(x)

#-------------------------------------------------------------

# THE EFFECT OF COLOR ON CUT

#-------------------------------------------------------------

price = Multiply()([color_mult_price,x])

price = Add()([color_add_price,price])

price = Dense(1)(price)

price = Add()([x,price])  # The Skip connection

#-------------------------------------------------------------

# THE EFFECT OF CLARITY ON CUT

#-------------------------------------------------------------

price = Multiply()([clarity_mult_price,price])

price = Add()([clarity_add_price,price])  # The Skip connection

#-------------------------------------------------------------

# THE PREDICTIONS FOR CUT

#-------------------------------------------------------------

price = Dense(1,name = 'price')(price)

#------------------------------------------------------------------------


#==========================================================================================================

# DEFINE THE MODEL

# ==========================================================================================================

model = Model(inputs = [carat,Color,Clarity,z],outputs = [cut,price])


model.compile(

        optimizer = 'Adam',loss = {

            "price": "huber_loss","cut": "binary_crossentropy",},loss_weights = [price_loss,cut_loss],metrics = {

            "price": ["mean_absolute_percentage_error"],"cut": [tf.keras.metrics.AUC(),tf.keras.metrics.Precision(thresholds = threshold)],}
    )

callback = tf.keras.callbacks.EarlyStopping(monitor='loss',patience= 3,restore_best_weights= True)

batch_size = 20

%%time

auc_list = []

r2_list = []

models_list = []

for i in tqdm(range(20)):


    history = model.fit(train_features_list,train_targets_list,validation_data = (dev_features_list,dev_targets_list ),epochs= 1000,callbacks=[callback],verbose=1)

    preds_list = model.predict(test_features_list)


    cut_preds = preds_list[0].ravel()

    price_preds = preds_list[1].ravel()

    cut_true = test_targets_list[0]

    price_true = test_targets_list[1]

    auc_list.append(roc_auc_score(cut_true,cut_preds))

    r2_list.append(r2_score(price_true,price_preds))
    
    models_list.append(model)

[![enter image description here][1]][1]

[![enter image description here][2]][2]

接下来,我将把模型的各个部分抽象为单独的模型,并将其用作构建块:

def f_model_embed(cat_input_embed_dim):
    
    x = Input(shape = (1,batch_size = batch_size)
    
    cat_input = Input(shape = (1,batch_size = batch_size)

    cat_input_add = Embedding(input_dim = cat_input_embed_dim,output_dim = 1)(cat_input)

    cat_input_mult = Embedding(input_dim = cat_input_embed_dim,output_dim = 1)(cat_input)

    cat_input_add = Flatten()(cat_input_add)

    cat_input_mult = Flatten()(cat_input_mult)

    X = Multiply()([x,cat_input_mult])

    X = Add()([X,cat_input_add])

    X = Dense(1)(X)

    X = Add()([X,x])

    model_embed = Model(inputs = [x,cat_input],outputs = X)
    
    return(model_embed)

def f_model_dense1(dense1,dense2,batch_size):

    #====================================================================

    # INPUTS

    #====================================================================


    #----------------------------------------------------------------

    carat = Input(
        shape= (1,name= 'carat'
    )



    #----------------------------------------------------------------

    depth = Input(
        shape= (1,name= 'depth'
    )

    #----------------------------------------------------------------

    table = Input(
        shape= (1,name= 'table'
    )

    #----------------------------------------------------------------

    X = Input(
        shape= (1,name= 'x'
    )

    #----------------------------------------------------------------

    y = Input(
        shape= (1,name= 'y'
    )

    #----------------------------------------------------------------

    z = Input(
        shape= (1,name= 'z'
    )

    #----------------------------------------------------------------

    #====================================================================

    # CONCATENATE FEATURES

    #====================================================================


    Y = Concatenate()([carat,z])



    #====================================================================

    # DENSE NETWORK FOR BOTH PRICE AND CUT

    #====================================================================

    Y = Dense(dense1,activation = activation)(Y)

    Y = Batchnormalization()(Y)

    Y = Dense(dense2,activation = activation)(Y)

    Y = Batchnormalization()(Y)


    #===============================================================================================================================================================

    # A MODEL CREATING A DENSE NETWORK PROVIDING FEATURES TO BE USED IN THE PREDICTION OF BOTH OUTPUTS/TARGETS -- CUT AND PRICE

    #===============================================================================================================================================================

    model_dense1 = Model(inputs = [carat,outputs = Y)
    
    
    return(model_dense1)

def f_model_dense2(dense2,dense3,dropout,batch_size):

    #====================================================================

    # DENSE NETWORK TO PREDICT CUT

    #====================================================================

    Y = Input(shape = (dense2,batch_size = batch_size)

    x = Dense(dense3,activation = activation)(Y)

    x = Batchnormalization()(x)

    x = Dropout(dropout)(x)


    x = Dense(1)(x)

    model_dense2 = Model(inputs = Y,outputs = x)

    return(model_dense2)

model_embed_color_cut = f_model_embed(color_embed_dim )

model_embed_clarity_cut = f_model_embed(clarity_embed_dim )

model_embed_color_price = f_model_embed(color_embed_dim )

model_embed_clarity_price = f_model_embed(clarity_embed_dim )

model_dense2_cut = f_model_dense2(dense2,batch_size)

model_dense2_price = f_model_dense2(dense2,batch_size)

model_dense1 = f_model_dense1(dense1,batch_size)

dense1 = 2**7
dense2 = 2**8
dense3 = 2**9
dropout = 0.8
price_loss = 1
cut_loss = 1
activation= LeakyReLU()
batch_size = 20
threshold = 0.7

#====================================================================

# INPUTS

#====================================================================


#----------------------------------------------------------------

carat = Input(
    shape= (1,name= 'z'
)

#----------------------------------------------------------------
#----------------------------------------------------------------

Y = model_dense1([carat,z])

#----------------------------------------------------------------
#----------------------------------------------------------------


cut = model_dense2_cut(Y)

cut = model_embed_color_cut([cut,Color])

cut = model_embed_clarity_cut([cut,Clarity])

#----------------------------------------------------------------

cut = Dense(1,name = 'cut')(cut)

#----------------------------------------------------------------
#----------------------------------------------------------------



price = model_dense2_price(Y)

price = model_embed_color_price([price,Color])

price = model_embed_clarity_cut([price,Clarity])

#----------------------------------------------------------------

price = Dense(1,name = 'price')(price)


model = Model(inputs = [carat,z,Clarity],}
    )

ordered_list_of_features = ['carat','z','clarity']

ordered_list_of_targets = ['cut','price']

def f_make_features_targets_list_out_of_dictionaries(features_dictionary,targets_dictionary,ordered_list_of_features,ordered_list_of_targets):
    
    '''

    
    The function takes as inputs the features_dictionary and targets_dictionary containing features and targets and converts them to lists to be passed to the fit() method of a Keras Model
    
    
    '''
    
    features_list = []
    
    targets_list = []
    
    for key in ordered_list_of_features:
    
        features_list.append(features_dictionary[key].astype('float32'))
        
    for key in ordered_list_of_targets:
        
        targets_list.append(targets_dictionary[key].astype('float32'))
        
    return(features_list,train_targets_dict,ordered_list_of_targets)

dev_features_list,dev_targets_list = f_make_features_targets_list_out_of_dictionaries(train_features_dict,ordered_list_of_targets)

test_features_list,test_targets_list = f_make_features_targets_list_out_of_dictionaries(train_features_dict,ordered_list_of_targets)

callback = tf.keras.callbacks.EarlyStopping(monitor='loss',restore_best_weights= True)

%%time
history = model.fit(train_features_list,verbose=1)

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)