问题描述
我正在使用一个公开且众所周知的数据集“钻石”。我创建了一个预测价格(回归)和削减(分类)的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 (将#修改为@)