3.2# Facial keypoints detection

该题主要任务是检測面部关键点位置

Detect the location of keypoints on face images

问题表述

在本问题中。要求计算面部关键点的位置,即关键点在图片中的百分比坐标。

因此该问题的机理就是 [0, 1] 范围内的数值拟合,当然了,这也是一个多输出的拟合的问题。

给定图片与其相应的 30 个标签的百分比位置,标签信息例如以下:

1 2 3
left_eye_center_x left_eye_center_y right_eye_center_x
right_eye_center_y left_eye_inner_corner_x left_eye_inner_corner_y
left_eye_outer_corner_x left_eye_outer_corner_y right_eye_inner_corner_x
right_eye_inner_corner_y right_eye_outer_corner_x right_eye_outer_corner_y
left_eyebrow_inner_end_x left_eyebrow_inner_end_y left_eyebrow_outer_end_x
left_eyebrow_outer_end_y right_eyebrow_inner_end_x right_eyebrow_inner_end_y
right_eyebrow_outer_end_x right_eyebrow_outer_end_y nose_tip_x
nose_tip_y mouth_left_corner_x mouth_left_corner_y
mouth_right_corner_x mouth_right_corner_y mouth_center_top_lip_x
mouth_center_top_lip_y mouth_center_bottom_lip_x mouth_center_bottom_lip_y

当中标签完整的图片有 2140 张,当中,图片的大小为 96*96 pixels。

求解方案

求解过程例如以下:
Step 1. 选择拟合器 SVR/KernelRidge 以及相应的 kernel
Step 2. 交叉验证实验选择超參数,超參数的选择通过枚举的方法
Step 3. 选定超參数后,用全部训练集训练拟合器
Step 4. 对測试集做预測。并输出结果

实验结果

结果
First idea:

Using 30 fitter to fit 30 labels, then I got 3.48060 RMSE

Second idea
Using 1 fitter to fit 30 labels, then I got 3.43998 RMSE[Better]
Third idea
Adding symmetrical training data, then resulting in abnormal result, such as position was greater then 96.

So, I can see that the result of fitting is only cover [0,96](or [0,1])

备注

超參数选择 gamma

for G in G_para:
scores = list()
for i in range(3):
X1, X2, y1, y2 = train_test_split(train_X, train_y, test_size=0.3, random_state=42)
clf = KernelRidge(kernel='rbf', gamma=G, alpha=1e-2)
pred = clf.fit(X1, y1).predict(X2)
sco = calbais(pred, y2)
scores.append(sco)
print('G:', G, 'Score:', scores)

30 个拟合器超參数调试的方法与结果例如以下:

拟合器 KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2)
0.7:0.3 训练集划分拟合误差:
[0] 0.7792 [10] 0.9744 [20] 1.0985
[1] 0.6383 [11] 0.7451 [21] 1.2300
[2] 0.7714 [12] 0.9513 [22] 1.2636
[3] 0.6482 [13] 0.9299 [23] 1.1784
[4] 0.7355 [14] 1.0870 [24] 1.2469
[5] 0.6005 [15] 1.1898 [25] 1.2440
[6] 0.9636 [16] 0.9012 [26] 0.9444
[7] 0.7063 [17] 0.9462 [27] 1.3718
[8] 0.7214 [18] 1.1349 [28] 0.9961
[9] 0.6089 [19] 1.1669 [29] 1.5076

pandas usage:

数据统计:DataFrame.count()
数据去缺失项:DataFrame.dropna()
字符串切割:Series = Series.apply(lambda im: numpy.fromstring(im, sep=' '))

值得注意的地方:

镜像图片,似乎对本问题採用 kernel ridge 拟合器 的求解没有帮助。

Conclusion

The 30 fitter is replaced by the only 1 fitter. The grade is better.

源代码

import pandas as pd
import numpy as np
import csv as csv
import matplotlib.pyplot as plt
from sklearn.utils import shuffle
from sklearn.svm import SVR
from sklearn.kernel_ridge import KernelRidge
from sklearn.cross_validation import cross_val_score, train_test_split train_file = 'training.csv' # 训练集数据
test_file = 'test.csv' # 測试集数据 1783 张图片
test_type = 'IdLookupTable.csv' # 測试集样表 行号, 图编号, 标签名 pd.set_option('chained_assignment',None) # csv 数据读取,返回 df (pandas)
def csvFileRead(filename):
print('Loading', filename)
df = pd.read_csv(filename, header=0, encoding='GBK')
print('Loaded') # 缺失项数据删除
if 'train' in filename:
df = df.dropna()
''' 数据查看
print('\n数据表尺寸: ', df.values.shape)
print('类别统计:\n')
print(df.count(), '\n')
'''
return df # 结果存储
def csvSave(filename, ids, predicted):
with open(filename, 'w') as mycsv:
mywriter = csv.writer(mycsv)
mywriter.writerow(['RowId','Location'])
mywriter.writerows(zip(ids, predicted)) # 训练集数据预处理
def preTrain():
print('-----------------Training reading...-----------------')
df = csvFileRead(train_file) print('Image: str -> narray')
df.Image = df.Image.apply(lambda im: np.fromstring(im, sep=' '))
print('Image transfered.\n') # problem: 7049*9046 MemoryError -> df.dropna()
X = np.vstack(df.Image.values) / 255.
X.astype(np.float32) y = df[df.columns[:-1]].values
y = (y-48)/48.
y = y.astype(np.float32)
'''
# 增加人工镜像图片
print('增加人工镜像图片...')
X, y = imageSym(X, y)
'''
X, y = shuffle(X, y, random_state=42) yd = dict()
for i in range(len(df.columns[:-1].values)):
yd[df.columns[i]] = i return X, y, yd # 预測集数据预处理
def preTest():
print('-----------------Test reading...-----------------')
df = csvFileRead(test_file) print('Image: str -> narray')
df.Image = df.Image.apply(lambda im: np.fromstring(im, sep=' '))
print('Image transfered.\n')
# 測试集图像
X = np.vstack(df.Image.values) / 255.
X.astype(np.float32) # 预測内容:行号, 图编号, 标签名
df = csvFileRead(test_type)
RowId = df.RowId.values
ImageId = df.ImageId.values - 1
FeatureName = df.FeatureName.values return RowId, ImageId, FeatureName, X # 人工特征:镜像图片
def imageSym(X, y):
nX = np.zeros(X.shape)
ny = np.zeros(y.shape)
for i in range(X.shape[0]):
temp = X[i,:].reshape(96, 96)
temp = temp[:,::-1]
nX[i,:] = temp.reshape(-1)
ny[i,0::2] = -y[i,0::2]
ny[i,1::2] = y[i,1::2]
X = np.vstack((X, nX))
y = np.vstack((y, ny))
return X, y # 30 个拟合器进行拟合
def modelfit(train_X, train_y, test_X, yd, ImageId, FeatureName):
#There are fitting codes. # 30 个拟合器相应 1 个位置
n_clf = 30
clfs = [
KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2), KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2),
KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2), KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2),
KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2), KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2),
KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2), KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2),
KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2), KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2),
KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2), KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2),
KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2), KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2),
KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2), KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2),
KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2), KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2),
KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2), KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2),
KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2), KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2),
KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2), KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2),
KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2), KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2),
KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2), KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2),
KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2), KernelRidge(kernel='rbf', gamma=2e-4, alpha=1e-2)] print('-----------------開始训练...------------------') # 超參数
C_para = np.logspace(-2, 4, 7) # SVR.C
G_para = np.logspace(-4, -3, 6) # kernel = 'rbf'.gamma
A_para = np.logspace(-3, 1, 5) # KernelRidge.alpha # 训练
for i in range(n_clf):
print('Training', i, 'clf...')
clfs[i].fit(train_X, train_y[:,i]) # 打印训练误差
predict = np.zeros([train_y.shape[0], 30]).astype(np.float32)
for i in range(n_clf):
predict[:,i] = clfs[i].predict(train_X)
print(calbais(predict, train_y))
print() print('-----------------開始预測...------------------') # 预測
pred = np.zeros([test_X.shape[0], 30]).astype(np.float32)
for i in range(n_clf):
pred[:,i] = clfs[i].predict(test_X)
predicted = np.zeros(len(FeatureName))
for i in range(len(FeatureName)):
if i % 500 == 0:
print('i =', i)
else:
pass
imageID = ImageId[i]
clfID = yd[FeatureName[i]]
predicted[i] = pred[imageID, clfID]
predicted = predicted*48.+48. return predicted # 单一拟合器,同一时候对 30 个标签做拟合
def modelfitOne(train_X, train_y, test_X, yd, ImageId, FeatureName):
n_clf = 1
# 拟合器
clf = KernelRidge(kernel='rbf', gamma=6e-4, alpha=2e-2)
# 训练
print('-----------------開始训练...------------------')
clf.fit(train_X, train_y)
# 预測
print('-----------------開始预測...------------------')
pred = clf.predict(test_X)
predicted = np.zeros(len(FeatureName))
for i in range(len(FeatureName)):
if i % 500 == 0:
print('i =', i)
else:
pass
imageID = ImageId[i]
clfID = yd[FeatureName[i]]
predicted[i] = pred[imageID, clfID]
predicted = predicted*48.+48.
return predicted # 均方根计算方法
def calbais(pred, y2):
y_diff = pred - y2
y_diff = y_diff.reshape(-1)
sco = np.linalg.norm(y_diff)/(len(y2)**0.5)
return sco # 參数选择的调试函数 # 超參数调试 X-y
def testfit(clf, train_X, train_y):
scores = list()
for i in range(3):
X1, X2, y1, y2 = train_test_split(train_X, train_y, test_size=0.3, random_state=42)
pred = clf.fit(X1, y1).predict(X2)
sco = calbais(pred, y2)
scores.append(sco)
print(scores) # 測试图
def plotface(x, y):
img = x.reshape(96, 96)
plt.imshow(img, cmap='gray')
y = y * 48 + 48
plt.scatter(y[0::2], y[1::2], marker='x', s=20)
plt.show() # 训练集数据读取
df = csvFileRead(train_file)
train_X, train_y, yd = preTrain() # 測试集数据读取
RowId, ImageId, FeatureName, test_X = preTest() # 1) 数据拟合: 30 个拟合器
predicted = modelfit(train_X, train_y, test_X, yd, ImageId, FeatureName) # 2) 数据拟合: 1 个拟合器
predicted = modelfitOne(train_X, train_y, test_X, yd, ImageId, FeatureName) # 结果存储
csvSave('KernelRidge.csv', np.linspace(1, len(predicted), len(predicted)).astype(int), predicted)

Facial keypoints detection Kaggle 竞赛系列的更多相关文章

  1. (zhuan) Using convolutional neural nets to detect facial keypoints tutorial

    Using convolutional neural nets to detect facial keypoints tutorial   this blog from: http://danieln ...

  2. Facial landmark detection - 人脸关键点检测

    Facial landmark detection  (Facial keypoints detection) OpenSourceLibrary: DLib Project Home:  http: ...

  3. 如何使用Python在Kaggle竞赛中成为Top15

    如何使用Python在Kaggle竞赛中成为Top15 Kaggle比赛是一个学习数据科学和投资时间的非常的方式,我自己通过Kaggle学习到了很多数据科学的概念和思想,在我学习编程之后的几个月就开始 ...

  4. 初窥Kaggle竞赛

    初窥Kaggle竞赛 原文地址: https://www.dataquest.io/mission/74/getting-started-with-kaggle 1: Kaggle竞赛 我们接下来将要 ...

  5. Facial Landmark Detection

    源地址:http://www.learnopencv.com/facial-landmark-detection/#comment-2471797375 OCTOBER 18, 2015 BY SAT ...

  6. OpenCV Facial Landmark Detection 人脸关键点检测

    Opencv-Facial-Landmark-Detection 利用OpenCV中的LBF算法进行人脸关键点检测(Facial Landmark Detection) Note: OpenCV3.4 ...

  7. 《机器学习及实践--从零开始通往Kaggle竞赛之路》

    <机器学习及实践--从零开始通往Kaggle竞赛之路> 在开始说之前一个很重要的Tip:电脑至少要求是64位的,这是我的痛. 断断续续花了个把月的时间把这本书过了一遍.这是一本非常适合基于 ...

  8. 《Python机器学习及实践:从零开始通往Kaggle竞赛之路》

    <Python 机器学习及实践–从零开始通往kaggle竞赛之路>很基础 主要介绍了Scikit-learn,顺带介绍了pandas.numpy.matplotlib.scipy. 本书代 ...

  9. 由Kaggle竞赛wiki文章流量预测引发的pandas内存优化过程分享

    pandas内存优化分享 缘由 最近在做Kaggle上的wiki文章流量预测项目,这里由于个人电脑配置问题,我一直都是用的Kaggle的kernel,但是我们知道kernel的内存限制是16G,如下: ...

随机推荐

  1. 用vue.js的v-for,v-if,computed写一个分页样式

    在学Vue,总想写个分页,先写了一个样式. 主要看思路: 思路简单,得到总页数,判断总页数,循环. 先判断总页数是否需要分页,总页数==1页就不分了. 再判断总页数<11就不用--. 总页数&g ...

  2. LAN8720A网络模块的使用问题

    一.LAN8720A模块驱动电路 最近在调试STM32F4驱动LAN8720A网络模块,在做方案前参考是正点原子的LAN8720A的驱动电路方案,但是从网上买回来的LAN8720A模块用正点原子的例程 ...

  3. phoenixframe自己主动化平台在Linux环境下运行用例的说明

    phoenixframe自己主动化平台支持在Linux环境下使用phantomjs,Firefox.chrome运行測试用例.但有下面几个问题须要注意: 1.若无法启动phantomjs,Firefo ...

  4. 前端面试题(HTML/CSS)

    (前端面试题大全,持续更新) 常用的块级元素和行内元素有哪些?说说他们的特点? 浮动产生的原因?清除浮动? 说说一下盒模型 float和position一起用是什么效果 rem用过吗?做不同手机的适配 ...

  5. VUE笔记 - 插值表达式 v-on: / @ 事件绑定 定时器运用

    <body> <!-- 2. 创建一个要控制的区域 --> <div id="app"> <input type="button ...

  6. 【前端切图】用css画一个卡通形象-小猪佩奇

    最近在腾讯云技术社区遇到了一位奇才,用css画出了一个社会人小猪佩奇,不得不服.研究了一下他的文章https://segmentfault.com/a/1190000014909658,感觉甚是有趣, ...

  7. 如何去掉bootstrap table中表格样式中横线竖线

    修改之前,表格看上去比较拥挤,因为bootstrap table插件中自带斑马线表格样式,有横线和竖线分栏,现在我们不需要这些. 应UI设计的要求,要去掉中间的横线和竖线,使用了修改需求中一种简单粗暴 ...

  8. HTTP网络协议(四)

    确保Web安全的HTTPS HTTP存在三个比较明显的缺点: 通信使用明文(不加密),内容可能会被窃听. 不验证通信方的身份,因此有可能遭遇伪装. 无法证明报文的完整性,所以可能已遭篡改.  尽管HT ...

  9. Altium Designer如何统一改变pcb状态下的原件标号位置

    原创 我用的是Altium Designer16版本 变成 步骤如下: 选中标号 右击 下边一步很重要: 点击应用和确定 在之后弹出的对话框中选则你要改变的位置,我这里是把标号改变到原件的右侧: 等待 ...

  10. Django中pycharm中 报错 ---ValueError: The field admin.LogEntry.user was declared with a lazy reference to 'system.sysuser', bu

    问题是:已经在settings.py文件中注册过app仍旧提示没有安装,并且使用makegirations命令时会抛出如下异常 解决方法: 找到自己的python3.x,进入site-packages ...