简单说说 iPhone X 的 face id 和传统的人脸识别有啥区别

在微信朋友圈里看到有个做人脸识别的公司蹭热点,说手机的人脸识别判断一年前帮某手机厂商已经做了云云。留言说这不一样啊,当然是不理我,如果不是看在之前是老同学介绍认识的面子上,早就拉黑了。

苹果放出的资料很少,大致来说,iPhone X 的面容识别是基于 iPhone 那个前刘海上的红外线之类的设备扫描人脸,通过30000个点来对人脸进行建模,来比较是否一致,这样的精度、计算时间要求,所以必须依靠专门的设备、A11这样强劲的 CPU 来完成。

一般的人脸识别128点,或者再翻个倍也就够了。所以 Apple 叫做面容 id。Apple 也提到用脸解锁的时候,是有注意力判断的,这样就可以防止很多你在不注意的情况下被动解锁的可能,我猜测这应该是通过复杂的机器学习来识别表情,以及通过瞳孔等等很多判断来完成注意力表情的识别,判断是主管能动还是被动。

没查资料,有些说法可能不规范,先这样简单说说吧,所以不用担心韩国脸之类的问题,这样的建模,Apple 都说了双胞胎都能识别,还担心什么。

为了20年后的梦想

1995年-1996年,写了一本 Visual Basic 3-4的书,想必当时过于年轻,自以为是的文字很幼稚,文字不够代码来凑,其实也不是很负责。也缺乏持续更新的能力和勇气,当时我的编程经验全部来源于自学,做过的项目有几个,但不多,也不复杂。最关键是,对于 Visual Basic 本身的认识还是比较肤浅的。

想起来那时的确是充满了热情,白天也是完全没有办法写作,每天上班前,下班后,周末,几乎一年,花费在上。虽然作品不满意,还算是完成了。

20年后,又开始这样的梦想,前些年,比较空的时候到时也有想过,却不太了解行情,原来,现在出版行业也早就市场化运作了,只是要出书并不是那么难。

和同事们选择了自己相对还比较擅长和有独到体会的 Python 和其用在机器学习方面作为主题。因为外面 Python 的书其实也很多了,实在不想写一本简单的入门级,无疑,这个定位在中等水平的目标,让我们一方面提高很多,一方面也是绞尽脑汁,受累。

而今年工作的忙碌,到了这个岁数的种种事情,都耗用了很多时间和精力。不知道多少个晚上和周末,在看资料、写 demo 程序、组织文字、review 其他同事写的书稿,或许这就是梦想,这就是有梦想的力量吧!

记录一下,也有一些颓废的时候,作为鼓励。

使用 python 基于朴素贝叶斯进行文本分类学习笔记之三:中文内容的倾向性判断初步

在之前程序的基础上,我尝试对中文内容进行倾向性判断,到目前为止我做的都是二元的,非黑即白,我的同事告诉我朴素贝叶斯也完全可以用在多类别的分类上,之后有机会再找应用场景测试一下,目前我们在实际中的应用场景来说,二元的暂时够用了。

中文在文本分类上和英文最大的不同首先要解决分词问题,还好有很多前辈为之付出了很多努力,在 python 下我使用 jieba 来进行中文的分词,https://github.com/fxsjy/jieba,另外,这个 https://github.com/isnowfy/snownlp 看上去也不错,并且还内置了注入倾向性分析等功能,没有使用过,不知道准确率和性能如何。

之前在class 中训练文本是作为类变量的,因此申明类的实例后,可以自己定义训练文本,我们将中文文本分别放在一个 good.txt 文件和一个 bad.txt 文件,然后通过下面的代码读入训练文本与预先设定的分类。

jieba.initialize()

nb.train_doc_list = []
nb.train_doc_sent_vec = []

with open('train/good.txt', 'r') as f:
    train_txt0 = []
    for line in f:
        train_txt0.append(line)

for item in train_txt0:
    s = list(jieba.cut(item))
    nb.train_doc_list.append(s)
    nb.train_doc_sent_vec.append(0)

with open('train/bad.txt', 'r') as f:
    train_txt1 = []
    for line in f:
        train_txt1.append(line)

for item in train_txt1:
    s = list(jieba.cut(item))
    nb.train_doc_list.append(s)
    nb.train_doc_sent_vec.append(1)

nb.train()
print(nb.p0_v, nb.p1_v, nb.p_ab)

 

运行正常的话,可以得到 p0 和 p1 两个向量矩阵,以及先验概率 0.5。

下面是我用来训练的文本,用的是在京东上随便找的一个手机的好评和差评的第一页内容,各9条,只是测试,这个训练样本以及中文分词还有很大的改进之处,稍后再说。

很不错的手机,手感很好,操作流畅!期待后续表现
用了很久才来评价的,真的很好用。速度很快,海思950真的不错,玩大型游戏也不卡,不发热。专用充电头充电很快,电池也很耐用。看看视频,打电话,上微信,中度用户一天绝对没问题。就是华为预装的软件比较多,要是再简化点就好了。
手机当然是很好的,送货员也是很及时的喽。京东的服务可以说是电商之中最好最及时的。买啥电器产品继续选择京东的了!手机有点大,晚上睡觉不太好用我估计,不沉但是有分量。美腿是我一直用的系列,自己国产的芯片这么牛逼真的要点赞了!!希望华为越来越好,国产不容易,大家都理解。抢购为了更好的排生产计划我们也能理解!!!
很好很强大的手机,京东的速度还是一流的,真的是特别的快。上午下单,下午肯定就能到。这个是其他网站不能比拟的,简直就是快的没道理了。还有就是mate8的指纹怎么那么快呢,一摸就解锁了。这个怎么做到的????这次买mate8 就是赚到了。哈哈,下次给老婆买P9。
帮老弟买的,当时一看这手机就很喜欢,可惜自己已经有水果了,否则也就买这个了
一如既往的好,3079买的。一堆赠品。
东西很好,送的皮套没啥用,其他都挺好
手机不错,老婆喜欢。
很好的手机,媳妇儿非常喜欢

 

用了一个月了,还可以。就是前两天屏幕摔碎了,去换屏幕,拆开后 里面惨目忍睹,机子好像翻新过,零件上的用签字笔写的AB编号到处都是。还是就是这个手机里面的小螺丝,都动过。现在开始质疑网城尤其是京东的产品,心里很不舒服
第一次京东购物,三千大洋买个手机用了不到半个月昨晚花屏了,完全没有预兆出现满屏竖条,有两分钟都不能关机,真心害怕啊,不知道能不能退货,手机现在工作太重要了都不敢再用了
摄像头镜头破了
放第二张卡就不能放扩展卡!为什么没有说明啊!就32g根本就不够用的,不能放卡,这是逼着买贵的啊!差评
昨天收到,今天发现接近屏幕中间横贯屏幕有条绿线,真想骂人
妈的,三网电信4g不可以,只能3g,找客服说要我售后,我才买的新机器就找售后,吃一堑长一智!
价格本来就比其他地方的贵200多,我还在京东买不就是为了放心,省心吗?结果这次大出意料,收到手机后正常出厂带的膜是有个小耳朵好让你撕下来的,结果这个没有就贴着张膜,膜的周边还有好多灰,一看就不是一天形成的,边框耳机孔左边有一个针眼大小的磕碰痕迹,一看什么情况大家心知肚明吧,有点愤怒联系了客服,后来问我朋友,朋友急着用就算了,不换了。但是,这次购物让我对京东有所动摇了,有点寒心,先这样吧,这个差评不是给mate8的,手机无罪,给谁谁明白!!
收到后,手机是坏的,不能发出任何声音,已申请售后,看售后的操作状态再做评价。
这款 手机 我用了16天 电池 就不能用了 花了* 亲 这手机质量令人担忧 我闹心 闹了半个月了 咋回事 * 元 买的 也算是中上等手机了 很无奈 质疑品质 去售后修手机 都要花好几百车费 去了好几趟了 闹心啊

 

然后用下面的代码先收工来测试一下。

while 1:
    test_s = input('input comment:')
    test_list = list(jieba.cut(test_s))
    print(test_list)
    p = nb.testing_nb(test_list)
    if p == 0:
        print('classified as good ')
    else:
        print('classified as bad ')

    print()

 

下面是执行的结果,为了查看分词效果,我把测试文本的分词结果一并显示了出来

input comment:这个手机很好用,我很喜欢
['这个', '手机', '很', '好', '用', ',', '我', '很', '喜欢']
p0: -32.2635265486 p1: -39.1939498346
classified as good 

input comment:这个手机很破,一点也不好用
['这个', '手机', '很破', ',', '一点', '也', '不好', '用']
p0: -17.0641800281 p1: -18.803492389
classified as good 

input comment:这个手机屏幕很大,用起来很舒服
['这个', '手机', '屏幕', '很大', ',', '用', '起来', '很', '舒服']
p0: -28.0011339843 p1: -28.3622382739
classified as good 

input comment:再也不会买了,一点也不好,速度慢
['再也不会', '买', '了', ',', '一点', '也', '不好', ',', '速度慢']
p0: -12.2181082359 p1: -13.7462337788
classified as good 

input comment:破手机
['破', '手机']
p0: -10.3238494833 p1: -9.86890081319
classified as bad 

input comment:大屏幕手机,速度很快
['大屏幕', '手机', ',', '速度', '很快']
p0: -13.9816968282 p1: -16.6954460368
classified as good 

input comment:买来质量有问题,售后不解决,这下麻烦了
['买来', '质量', '有', '问题', ',', '售后', '不', '解决', ',', '这下', '麻烦', '了']
p0: -30.6306218629 p1: -28.9683740775
classified as bad

 

看这个结果还是挺有趣的,在只有非常有限的训练文本情况下,还不错。7条手工测试中,有2条判断错误,其他5条正确。

为了检查之后优化是否有效,首先我们不能用手工测试的方法,这样太麻烦了,接下来准备一个测试文本,并且标注好倾向性,然后程序运行后分别计算出 p0 p1 的正面负面与实际正面负面四个百分比,来衡量算法优化效果。

对于文本分类这里,可以改进的地方还有:

  • 加入停用词功能,去除这些常用词带来的干扰
  • 去除所有标点符号和空格等
  • 增加训练文本内容

使用 python 基于朴素贝叶斯进行文本分类学习笔记之一:开始
使用 python 基于朴素贝叶斯进行文本分类学习笔记之二:将原书程序修改并转换为类
使用 python 基于朴素贝叶斯进行文本分类学习笔记之三:中文内容的倾向性判断初步
使用 python 基于朴素贝叶斯进行文本分类学习笔记之四:增加测试文本和计算正确率
使用 python 基于朴素贝叶斯进行文本分类学习笔记之五:增加停用词

使用 python 基于朴素贝叶斯进行文本分类学习笔记之二:将原书程序修改并转换为类

朴素贝叶斯方法在文本分类中应用广泛,什么是朴素贝叶斯方法呢,wiki 上的定义如下:

在机器学习中,朴素贝叶斯分类器是一系列以假设特征之间强(朴素)独立下运用贝叶斯定理为基础的简单概率分类器。

所有朴素贝叶斯分类器都假定样本每个特征与其他特征都不相关,这是朴素(Naive)说法的由来,也是该算法的成立之本。

数学学得不太好,对于公式的理解有限,有些概念只能囫囵吞枣了,我更加关心的是应用场景和应用方法。

其实简单的想想也会知道,在文本分类中,我们假设词和词之间是不相关的,其实不太正确。

尽管是带着这些朴素思想和过于简单化的假设,但朴素贝叶斯分类器在很多复杂的现实情形中仍能够取得相当好的效果。

想看朴素贝叶斯整套公式推导过程的,可以移步这里,或者机器学习实战这本书上也有,此处就不再赘述了。

网上中文的介绍朴素贝叶斯用于文本分类的文章还是有一些,有兴趣的可以google 一下。

我们的目标是通过书中介绍的程序,来完成文本的倾向性分类,目前先按照两类进行分类,我简单的称之为正面和和负面的。

大致过程就是先进行正面和负面材料训练,计算得到 p0,p1,然后对材料进行测试,获得分类结果。

书中的源代码可以在这里下载,没有书也可以下载。代码属于第四章,不过书中举例主要还是在命令行环境下进行的,不是一个完整的可运行代码。

我做了如下修改:

  • 修改为 class 方式,方便程序调用
  • 修改为支持 python 3
  • 函数名称、变量名称和写法修改为支持 pep-8 标准

逐一解释一下代码:

下面是 class 类的一些变量,包括默认的训练文本和设定的倾向性。

# 训练 list, 默认内容, 原书中的内容
    train_doc_list = [['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],
                      ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
                      ['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
                      ['stop', 'posting', 'stupid', 'worthless', 'garbage'],
                      ['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],
                      ['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]
    # 倾向性向量, 0:正面 1:负面
    train_doc_sent_vec = [0, 1, 0, 1, 0, 1]

    # 单词列表集合
    word_list = []

    # 正面和负面概率, 先验概率
    p0_v = 0
    p1_v = 0
    p_ab = 0

 

下面是创建单词的集合,也就是将训练文本中所有的词合并到一起,不管出现几次都只保留一次。

    @staticmethod
    def create_word_list(data_list):
        # create empty set
        word_set = set([])
        for document in data_list:
            # union of the two sets
            word_set = word_set | set(document)
        return list(word_set)

 

下面这个函数是将输入的单词列表(需要训练或者测试的)根据上面的单词集合生成向量。

 @staticmethod
    def words_to_vec(word_list, new_word_list):
        vec = [0] * len(word_list)
        for word in new_word_list:
            if word in word_list:
                vec[word_list.index(word)] += 1
            else:
                pass
                # print("the word: %s is not in my Vocabulary!" % word)
        return vec

 

下面这个是朴素贝叶斯的算法,根据训练矩阵数据和预先设定的倾向性,来得到 p0,p1 概率。

@staticmethod
    def train_nb0(train_matrix, train_category):

        num_train_docs = len(train_matrix)
        num_words = len(train_matrix[0])
        p_ab = sum(train_category) / float(num_train_docs)

        # 创建给定长度的填满1的数组
        p0_num = ones(num_words)
        p1_num = ones(num_words)

        p0_d = 2.0
        p1_d = 2.0
        for i in range(num_train_docs):
            if train_category[i] == 1:
                p1_num += train_matrix[i]
                p1_d += sum(train_matrix[i])
            else:
                p0_num += train_matrix[i]
                p0_d += sum(train_matrix[i])

        p1_v = log(p1_num / p1_d)
        p0_v = log(p0_num / p0_d)
        return p0_v, p1_v, p_ab

 

然后是分类函数,根据上面计算得到的 p0,p1 概率,以及先验概率(如果正面和负面训练文本数量一样,就是 0.5),将输入的文本向量得到分类结果

    @staticmethod
    def classify_nb(vec, p0_vec, p1_vec, p_class1):
        # element-wise mult
        p0 = sum(vec * p0_vec) + log(1.0 - p_class1)
        p1 = sum(vec * p1_vec) + log(p_class1)
        print('p0:', p0, 'p1:', p1)
        if p1 > p0:
            return 1
        else:
            return 0

 

将上面的函数组合起来,得到下面这个完整的训练函数,上面大部分都是静态函数,外部不需要访问。

def train(self):
        # 生成单词列表集合
        self.word_list = self.create_word_list(self.train_doc_list)

        # 训练矩阵初始化
        train_matrix = []

        # 根据训练文档进行循环
        for post_in_doc in self.train_doc_list:
            # 构建训练矩阵, 将单词列表转化为向量
            train_matrix.append(self.words_to_vec(self.word_list, post_in_doc))

        # 根据训练矩阵和情感分析向量进行训练,得到
        self.p0_v, self.p1_v, self.p_ab = self.train_nb0(array(train_matrix), array(self.train_doc_sent_vec))

 

训练好了,就是测试函数,这是用来外部调用真正传入需要分类的文档或者校验正确率时候使用的。

 def testing_nb(self, test_word_list):

        # 对输入的内容转化为向量
        this_post_vec = array(self.words_to_vec(self.word_list, test_word_list))

        # 返回分类的值
        return self.classify_nb(this_post_vec, self.p0_v, self.p1_v, self.p_ab)

 

这个 navie bayes 代码会合并到我之前写的 fish_base 包中,代码也会放在 github 上,目前还在整理中。

刚才的 class 代码加上一个头,别忘记

from numpy import *


class ClassNaiveBayes:

 

其中的矩阵相关运算是通过 numpy 进行的,这个 python 下最好的数学计算库,性能不用怀疑。

调用上面 bayes 代码的例子代码,我将书中分散的测试代码合并了,并且通过类的方式调用:

import bayes

nb = bayes.ClassNaiveBayes()

nb.train()

test_list = ['love', 'my', 'dalmation']
print(test_list, 'classified as: ', nb.testing_nb(test_list))

test_list = ['stupid', 'garbage']
print(test_list, 'classified as: ', nb.testing_nb(test_list))

 

应该会得到书中一样的结果:

p0: -7.69484807238 p1: -9.82671449373
['love', 'my', 'dalmation'] classified as:  0
p0: -7.2093402566 p1: -4.70275051433
['stupid', 'garbage'] classified as:  1

 

接下来我尝试修改为针对中文内容进行分类,测试样本考虑用对于一款手机的评价,通过训练来区分是正面和还是负面的评论。

使用 python 基于朴素贝叶斯进行文本分类学习笔记之一:开始
使用 python 基于朴素贝叶斯进行文本分类学习笔记之二:将原书程序修改并转换为类
使用 python 基于朴素贝叶斯进行文本分类学习笔记之三:中文内容的倾向性判断初步
使用 python 基于朴素贝叶斯进行文本分类学习笔记之四:增加测试文本和计算正确率
使用 python 基于朴素贝叶斯进行文本分类学习笔记之五:增加停用词

使用 python 基于朴素贝叶斯进行文本分类学习笔记之一:开始

最近一些项目开始使用机器学习和神经网络,有一个项目是对从搜索引擎抓回来的文字判断倾向性,看文章是正面的还是负面的(抱怨、怀疑、责备),没办法,我们所服务的互联网金融最近就是一个被高度关注的领域。

之前开发小组使用 R 语言基于朴素贝叶斯方法做了一些训练,并得到了一些结果,不过在正式环境运行的程序只是使用了结果,没有进行持续的训练和测试使用。

于是,我们开始研究怎么用 python 来基于贝叶斯方法进行训练和测试,python 世界里,基于 bayes 算法的资料多如牛毛,看的也有点晕。这次我们没有直接用现成的库,而是基于下面这本书:

s26696371

“机器学习实战”,这本书中的内容都是用 python 写的各类机器学习的算法,虽然豆瓣评价一般,给我们入门的确不错。

如豆瓣所说,这本书的代码写得的确比较乱,并且关键是基于 python2,所以我们按照书上的指引,修改了原来的代码,符合 python3语法,并且严格的符合 pep-8 python 命名规范等,并且修改为一个标准的类,便于使用。

同时,书中原来的例子是基于英文的,特别是一些关于网站倾向性和垃圾邮件的例子,不太适合中国国情,反而将程序弄得比较复杂,一并优化了。

大致分以下步骤:

  1. 基于书上的代码,修改 bayes 代码,减少不必要的函数,执行原书中的英文例句分类。
  2. 从京东网站上挑选一个手机的评论,从好评和差评中获得训练文本,引入中文分词,得到评价倾向性的结果。(分类在这里就是得到一个倾向性的判断,0或者1,好或者坏,是某种倾向或者没有没有倾向)
  3. 优化中文处理,引入停用词功能,增加分类判断的准确性。

使用 python 基于朴素贝叶斯进行文本分类学习笔记之一:开始
使用 python 基于朴素贝叶斯进行文本分类学习笔记之二:将原书程序修改并转换为类
使用 python 基于朴素贝叶斯进行文本分类学习笔记之三:中文内容的倾向性判断初步
使用 python 基于朴素贝叶斯进行文本分类学习笔记之四:增加测试文本和计算正确率
使用 python 基于朴素贝叶斯进行文本分类学习笔记之五:增加停用词