【发布时间】:2021-09-12 21:53:37
【问题描述】:
我正在构建一个人脸关键点检测系统。目标是将人脸图像输入模型,然后模型检测图像中的解剖标志(眼睛、鼻子)并输出可见标志的像素坐标。每个地标有三个目标:x、y、可见。 X 和 Y 是像素坐标,可见地标是否在图像中。该计划是首先在预测可见性和真实可见性之间进行二元交叉熵损失。然后,第二个损失是 x,y 坐标和目标之间的回归损失(我使用的是 MAPE)。然而,回归损失只会计算可见的地标。损失看起来像:
#Pseudo-code
def loss(y_true,y_pred):
if y_true[2] == 1
#Probability that landmark is in image
#Compute binary cross entropy loss
#Compute MAPE regression loss
Total_loss = Binary_loss + MAPE_loss
return Total_loss
else:
Total_loss = Binary loss
return Total_loss
一旦编写了损失函数,我将如何在代码中实现它?我知道如何为每个问题创建模型(检查坐标,并分别检查可见性),但我不确定如何将两个头与条件损失函数结合起来。我将如何组合图层(每个头部的 Conv、Flatten、Dense)以获得所需的输出?谢谢!
编辑: 我无法上传数据,但这是它的图像。前 9 列是地标的坐标和可见性。最后一列是已展平的相应图像。 当我加载数据进行训练时,我会执行以下步骤:
###Read in data file
file = "Directory/file.csv"
train_data = pd.read_csv(file)
###Convert each coordinate column to type float64
train_data['xreye'] = train_data['xreye'].astype(np.float64)
...
###Convert image column to string type
train_data['Image'] = train_data['Image'].astype(str)
#Image is feature, other values are labels to predict later
#Image column values are strings, also some missing values, have to split
##string by space and append it and handle missing values
imag = []
for i in range(len(train_data)):
img = train_data['Image'][i].split(' ')
img = ['0' if x == '' else x for x in img]
imag.append(img)
#Reshape and convert to float value
image_list = np.array(imag,dtype = 'uint8')
X_train = image_list.reshape(-1,256,256,1)
####Get pixel coordinates and visibility targets
training = train_data[['xreye','yreye','reyev','xleye','yleye','leyev','xtsept','ytsept','tseptv']]
y_train = []
for i in range(len(train_data)):
y = training.iloc[i,:]
y_train.append(y)
y_train = np.array(y_train, dtype='float')
编辑:模型代码、损失函数和拟合方法。
###Loss function
visuals_mask = [False, False, True] * 3
def loss_func(y_true, y_pred):
visuals_true = tf.boolean_mask(y_true, visuals_mask, axis=1)
visuals_pred = tf.boolean_mask(y_pred, visuals_mask, axis=1)
visuals_loss = tf.keras.losses.BinaryCrossentropy(visuals_true, visuals_pred)
visuals_loss = tf.reduce_mean(visuals_loss)
coords_true = tf.boolean_mask(y_true, ~np.array(visuals_mask), axis=1)
coords_pred = tf.boolean_mask(y_pred, ~np.array(visuals_mask), axis=1)
coords_loss = tf.keras.losses.MeanAbsolutePercentageError(coords_true, coords_pred)
coords_loss = tf.reduce_mean(coords_loss)
return coords_loss + visuals_loss
####Model code
model = Sequential()
model.add(Conv2D(32, (3,3), activation='relu', padding='same', use_bias=False, input_shape=(256,256,1)))
model.add(BatchNormalization())
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Conv2D(64, (3,3), activation='relu', padding='same', use_bias=False))
model.add(BatchNormalization())
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Conv2D(128, (3,3), activation='relu', padding='same', use_bias=False))
model.add(BatchNormalization())
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(64, activation='relu'))
model.add(Dense(32, activation='relu'))
model.add(Dense(16, activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(4, activation='relu'))
model.add(Dense(9, activation='linear'))
model.summary()
model.compile(optimizer='adam', loss=loss_func)
###Model fit
checkpointer = ModelCheckpoint('C:/Users/Cloud/.spyder-py3/x_y_shift/weights/vis_coords_TEST.hdf5', monitor='val_loss', verbose=1, mode = 'min', save_best_only=True)
out = model.fit(X_train,y_train,epochs=5,batch_size=4,validation_split=0.1, verbose=1, callbacks=[checkpointer])
【问题讨论】:
-
您能分享一下您的输入和输出数据的形状吗?这是单输出模型还是多输出模型?
-
当然,输入是形状 (256,256,1) 的图像。输出将是(righteyeX,righteyeY,righteyeVis,lefteyeX,lefteyeY,lefteyeVis,noseX,noseY,noseVis),每个图像输入的输出形状(1,8)。所以我想这将是一个多输出模型。谢谢!
标签: python keras deep-learning conv-neural-network loss-function