我的机器学习(这次是搬轮子)-part(2020-3)
文章目录
前言
0. 以下两点内容与技术无关,关于自我认知而已
1. 越来越清晰的自我定位:桥梁工作
那些造优秀轮子的是大佬,比如搞出BodyPix、StyleTransfer这种的大哥,真心佩服,我估计很难做到。
对于造轮子这个工作,我也算科研过一丢丢吧,没特别大兴趣…
我喜欢的是,学习和理解轮子,去使用、改进、实践,带着他们去制造或者改进产品,让生活更好,万一能影响社会就干的漂亮啦。
首先我喜欢,然后也应该是有能力,去做这么一份桥梁型的工作,连接"抽象"的科研成果与"复杂多变"的实际产品环境。
因为,心态上,我佩服、欣赏优秀的科研成果,能力上,我的智商和才能应该是可以有效理解他们的努力和结果;另一方面,我热爱生活,偏好实践和实战,相对敢想敢做,学习、动手能力比较强,爱琢磨。
2. 所谓经验积累:判断力
随着岁月加持的经验积累或者社会毒打,我理解,对于个人来说应该成长的重要是判断力,或者说,战略性的眼光,否则只是虚假的"成熟",毕竟,选择 >> 努力。
判断力/战略性眼光,目前的理解:
大家都知道,收益大于风险就应该做,但是,收益和风险往往不是两个简单的数字;影响结果最大的就是主要矛盾,次之的是次要矛盾,实际上,这个影响大小也不是相关性分析下简单的数值。
在没法量化指标时的比大小、分主次的能力,就是判断力。能分清主次,就可以有效分配核心资源达到事半功倍之效,对于目标更容易达到。
拿工作举例,一个项目该不该立项、该做到什么程度、是长期还是短期、风险和收益如何评估…
拿生活来说,该不该买房、学区和生活便利取舍、资产应该如何规划、家庭的经济与心理是什么状态、长辈小孩自己的三观和习惯理解与配合…
可以延伸出的就是,在你的专业领域,加强自己的判断,相信自己的判断;在你业余的领域,去学习、参考、信任可靠的、专业的判断。
另外,说到执行力,一两次的得失有偶然的影响,但是长久的收获就是判断力、执行力在时间尺度上的期望,执行的结果去反哺判断进行修正,这里我认为判断力为主。方向对了,结果无非是60、80、100,方向错了可能就是40、20、0。
我觉得,一个家庭的主心骨、一个团队的leader,最重要的是判断力,这是最需要打磨的能力。
说了是打磨,就是实战实践中,摸爬滚打练出来的,所以,比起理论家我更信任战火中打出来的将军,吃屎多、吃亏大的更佳,毕竟样本更丰富得到的决策树 vs 样本单一少的resnet,我还是更倾向前者。
当然好些人连决策树都不是,脑子里是一坨浆糊,就更不用提了,给啥样本都白瞎。
PS:写在轮子的前面,既然是搜刮轮子,都是查资料、实践,更多的都是别人的东西,只是参考总结,消化吸收,版权什么的,我不配,谢谢。
另外,对于经典算法,个人习惯是先大致浏览,得其形意,然后实践中不断体会细节丰富认知。
一、1号轮子-人脸识别相关
上一篇使用到了face_recognition、seetaface,最近看资料的时候还有RetinaFace,工具使用上次也贴过示例,这不难。
好奇原理,去查了下,主要是两种,我也是刚了解,很业余,就是mark一下。感觉现在主要是利用神经网络来encode,对不同目标构建不同损失函数,当然有各种优化后的网络结构。
1.基于特征脸的传统方法
大致的原理:
(1)先对图像进行预处理,比如做直方图均值化(Histogram equalization)。这个的原因好理解,你的图太暗、他的图太亮,需要归一化再去比较,直方图均值化就是一种图像的"归一化"手段,将整体的像素分布"拉平",原理和实现细节上参考https://face2ai.com下面的一篇关于直方图均值化的介绍;
(2)再通过PCA对图像进行降维,然后计算出数据库中K个人脸图像的平均脸和特征脸,https://zhuanlan.zhihu.com/p/26652435这位同学写了细节,数学层面上线代我有点忘了;
(3)于是,任意一张人脸图像都可以被认为是这些特征脸和平均脸的线性组合。当我们要识别一张新的人脸图像时,只需要按照这种方法计算出它的值,然后再从数据库中寻找与其最接近(比如欧氏距离)的即可,以下是特征脸。
一言以蔽之:以主成分分析将每一张脸图encode为一个向量,在给定一组脸图的情况下,特征脸是固定的(PCA的特征"向量"),希望没有理解错…
2.基于深度学习的炼丹
(1) 基于神经网络的对两张不同的图片encode为一个向量,构建损失函数,原则上输入不同人脸loss大,相同人脸loss小,http://www.fanyeong.com/2018/02/04/dl-face-recognition/介绍了一种loss function,三元损失函数
(2)更复杂的目标和损失函数
以比较新的RetinaFace来说,他的目标有4个,损失函数为4个损失的加权:是不是人脸的分类损失、矩形框坐标点的smooth-L1损失、landmark的smooth-L1损失、mesh decoder的loss(超出了我目前的知识范畴,好像图像3D相关,后面有空补补),我就看了个大概,细节参考https://www.jianshu.com/p/d4534ac94a65
这里顺便回顾了下
L
2
−
l
o
s
s
L2-loss
L2−loss、
L
1
−
l
o
s
s
L1-loss
L1−loss的优缺点,参见https://zhuanlan.zhihu.com/p/48426076,
L
2
L2
L2好处是收敛更快,看下公式比L1多一个
f
(
x
)
−
Y
f(x)-Y
f(x)−Y,在这个值大的时候,一步也走得远;同样也看到,缺点就是,离群点对loss的影响太大,误差平方了。于是就有人想到兼顾
L
2
−
l
o
s
s
L2-loss
L2−loss、
L
1
−
l
o
s
s
L1-loss
L1−loss的,也就是
s
m
o
o
t
h
−
L
1
smooth-L1
smooth−L1
与PCA的encode不同,基于神经网络构建不同损失函数优化,更加灵活,PCA本质是信息损失最小的优化。
二、2号轮子-物体检测object dection
1.思路1-RCNN系列
总的思路就是先划分区域,然后进分类模型,这里的R是region的意思吧,算法描述参见https://blog.csdn.net/shenxiaolu1984/article/details/51066975。
我看里面的细节挺多的,怎么划分、怎么合并等等。
原始的RCNN有着明显的效率问题,后面的系列相比是进行各种改进,有空再去细看。
2.思路2-YOLO系列
YOLO(You Only Look Once),现在已经进化到了V5了。与RCNN这个分支两部策略先进行前景识别在进行目标检测不同,它是一步到位进行目标检测。
速度领先,准确稍逊。
细节参考https://www.jianshu.com/p/c021cd311eff。
总体思路就是:CNN提取特征,在损失函数构建上下功夫,损失函数包括物品种类、位置、框大小的损失。
(1)网络结构:
(2)看最后一层:看个大概,其实trick比较多,尤其v2、v3后面。
简单的理解,这个7 * 7 * 30的向量,先不管这个7 * 7,看这个30里面,一部分是物体类别信息,一部分是检测框相关的信息。
(3)target:你计算loss,需要将网络最后一层与样本target生成。
上一步里面没管这个7 * 7,这里就有了,将原图分割为7 * 7,如果某个物体的中心点落在某个小分割框,那么这个分隔框在这个物体的one-hot编码就是1
(4)loss function:看个大概先,坐标的损失、矩形框大小的损失、对象分类误差的损失、是否有物体的损失,果然是only once
(5)总结一下:图像网格分割,配上这种损失函数设计挺有意思的。
(6)标注数据的工具: https://github.com/AlexeyAB/Yolo_mark,感受一下,支持3系统
三、3号轮子 object segmention+皮肤检测
图像语义分割好像还是挺复杂的,我就瞄了下最直观的端对端、像素级的结构,其他太多了,还没时间看,https://www.cnblogs.com/augustone/p/10613048.html这个文章算是比较丰富的。
(1)和物体检测区别:上面的物体检测是个矩形框,这个是要勾画出边缘
(2)一种直观的网络结构:端对端、像素到像素,其他还有很多很复杂的。
反卷积、反池化看看https://blog.csdn.net/quiet_girl/article/details/84579038
(3)我遇到的问题是:检测人裸露皮肤的比例,因为考虑到环境色的影响,方案是人体分割(采用google的tf_bodypix)+肤色检测(网上随便找了一个,大致都是转换像素坐标,然后取个范围值)。
import tensorflow as tf
from tf_bodypix.api import download_model, load_model, BodyPixModelPaths
#人体的segmention,google大法好
bodypix_model = load_model(download_model(BodyPixModelPaths.MOBILENET_RESNET50_FLOAT_STRIDE_16))
image = tf.keras.preprocessing.image.load_img('/Users/xxx.jpg')
image_array = tf.keras.preprocessing.image.img_to_array(image)
result = bodypix_model.predict_single(image_array)
mask = result.get_mask(threshold=0.75)
tf.keras.preprocessing.image.save_img('/Users/xxx_mask.jpg',mask)
colored_mask = result.get_colored_part_mask(mask)
tf.keras.preprocessing.image.save_img('/Users/xxx_mask_2.jpg',colored_mask)
# 肤色检测之一: YCrCb之Cr分量 + OTSU二值化
import cv2
img = cv2.imread('/Users/xxx.jpg', cv2.IMREAD_COLOR)
ycrcb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb) # 把图像转换到YUV色域
(y, cr, cb) = cv2.split(ycrcb) # 图像分割, 分别获取y, cr, br通道图像
# 高斯滤波, cr 是待滤波的源图像数据, (5,5)是值窗口大小, 0 是指根据窗口大小来计算高斯函数标准差
cr1 = cv2.GaussianBlur(cr, (5, 5), 0) # 对cr通道分量进行高斯滤波
# 根据OTSU算法求图像阈值, 对图像进行二值化
_, skin1 = cv2.threshold(cr1, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
#计算肤色像素个数
mask_div1 = mask.cpu().numpy().flatten()
skin1_mask_div1 = skin1.flatten()
mask_skin_div1 = mask_div1 * skin1_mask_div1
import numpy as np
len(skin1_mask_div1)
np.count_nonzero(mask_div1)#人体部分像素个数
np.count_nonzero(mask_skin_div1)#人体部分中,皮肤色像素个数,比值就是皮肤占比
#=========打印皮肤的部分
(x, y, z) = mask.shape.as_list()
mask_arr = mask.cpu().numpy()
for i in range(0, x):
for j in range(0, y):
if skin1[i][j] == 0:
mask_arr[i][j] = [0]
tf.keras.preprocessing.image.save_img('/Users/xxx_mask_skin.jpg',tf.convert_to_tensor(mask_arr, tf.float32))
看看效果:肤色检测那部分还差点意思,整体凑合
(4) web看开发机上面的图片和开发:搜jupyter
后话
本来还看了下:
人体姿态检测Human Activity Recognition,有根据3D陀螺仪的,图片识别的初步形态也可以套用端对端那一套,本来是想判断人是否是站着还是躺着,还没弄好,后面弄好了再说;
场景识别Scene Recognition,有直接图片分类的,更复杂的加入里面的物体语义,但是准确率什么的,还是差点意思,自己物体识别以后写规则也能凑合下下先;
有点忙,后面再说,心情郁闷中,因为贫穷…