数据专栏

智能大数据搬运工,你想要的我们都有

科技资讯:

科技学院:

科技百科:

科技书籍:

网站大全:

软件大全:

【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
标准的 M / M / c模型



M / M / c型系统和 c 个 M / M / 1 型系统的比较


系统的容量有限制的情形



顾客源为有限的情形

人工智能
2018-12-14 23:54:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
动态规划的基本概念




动态规划的基本思想和基本方程



人工智能
2018-12-09 22:19:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
一年一度的双11购物狂欢节,是全球商家和消费者的盛会,同时也是一场技术的盛会,人脸识别,图片搜索,字符识别,语音识别,8K视频直播,智能推荐,语音助手等最先进的技术手段被广泛使用,为大促的各个环节保驾护航。作为IT基础设施的基石,阿里云ECS为阿里集团双十一业务提供了强有力的计算保障。
阿里云异构计算产品——GPU云服务器和FPGA云服务器,作为ECS产品家族中的一员,今年支撑了集团超过10个BU的双11业务,这当中包括电商业务,新零售业务,视频直播业务以及双11后台支持业务等核心环节。
得益于比传统CPU并行计算更高效率和低延迟的计算性能,异构计算云服务器能够很好的满足人工智能,视频压缩,图片处理等大数据处理相关的计算密集型业务需求。下面就通过几个业务场景,来简单解析一下,异构计算云服务器是如何提升计算效率,节约成本的。
图像搜索。 电商平台上,有超过千万产品的几十亿张图片,用户如果想通过图片搜索一款产品在平台上的商家及价格等情况,云服务器需要通过神经网络技术,对现存数据进行特征提取,建立索引,对用户拍摄的图片进行分类预测,特征提取,比对等计算。通过在最消耗计算力的神经网络运算环节,使用GPU异构计算服务器,相比传统的CPU服务器,可以大大缩减业务处理时间,同时能够减少服务器使用数量,从而缩减成本。
视频直播。 在视频直播应用场景中,实时视频上传到云服务器端,源片经转码处理后,输出不同规格视频再经CDN加速分发,供终端播放。这当中的转码过程,实际上是一个视频解压,视频处理,再进行压缩的过程。无论是对于当前主流的H.264视频,亦或是正在推广中的H.265视频,压缩解压处理都是十分巨大的计算工作量,尤其是需要数十万人,数百万人同时在线观看,直播业务面临的挑战可想而知。
每个GPU云服务器,都集成了若干个编解码引擎,单台GPU云服务器支持的视频路数,是CPU服务器的数倍。在保证了图像质量,保证直播用户体验的同时,大幅减少了服务器的使用数量,节约了整体IT成本的投入。
图片处理。 图片处理,包括图片的格式转换,图片的压缩等,在双十一业务中,大量存在。在客户通过淘宝/天猫App或者网页端浏览商品时,这些图片往往需要以不同格式,不同分辨率呈现的。这些大量的图片的转换,使用的是阿里云FPGA云服务器。
利用FPGA云服务器异构器件强大的并行计算能力,将图片处理的延时缩减到CPU服务器的50%,将吞吐能力提升数倍,在缩减了数千万成本的同时,很好的保证了用户的购买体验。
今年,将有数千张异构卡,数百万个异构计算单元为双十一的计算场景提供支撑,除了超强的计算能力,阿里云异构云服务器的稳定性和弹性能力,也是保障双十一业务的关键核心。
作为云端加速计算的领航者,阿里云异构产品一直秉承安全,稳定,高性能的产品理念,基于阿里集团业务需求,不断做大产品规模,提升产品服务质量,依托于阿里云高可靠的基础架构,阿里云弹性计算整体产品技术能力,为云计算客户,提供最强算力,最高性价比的计算服务。
原文链接
本文为云栖社区原创内容,未经允许不得转载。
人工智能
2018-11-28 14:43:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
众所周知,英文是以词为单位的,词和词之间是靠空格隔开,而中文是以字为单位,句子中所有的字连起来才能描述一个意思。把中文的汉字序列切分成有意义的词,就是中文分词,有些人也称为切词。本文转载自明略研究院的技术经理牟小峰老师讲授的语言处理中的分词问题。
如何界定分词
中文分词指的是将一个汉字序列切分成一个一个单独的词。分词就是将连续的字序列按照一定的规范重新组合成词序列的过程;在英文中,单词之间是以空格作为自然分界符,汉语中词没有一个形式上的分界符。(见百度百科) 正因为缺乏形式上的分界符,导致我们对词的认定会出现很大的偏差。1996 年 Sproat 等通过对 6 个母语为汉语的人进行调研,让这 6 人对同一篇中文文本进行人工切分,文本包括 100 个句子,最后统计认同率,见下表:
图1
不仅普通人有词语认识上的偏差,即使是语言专家,在这个问题上依然有不小的差异,这种差异反映在分词语料库上。不同语料库的数据无法直接拿过来混合训练。
以前曾经出过分词规范 (GB13715),以“结合紧密,使用稳定”作为分词建议,后来发现这个建议弹性太大,不同的人有不同的理解,无法有效实施。
为了统一对词语的认识,现在主要通过“分词规范、词表、分词语料库”来使得词语切分可计算,例如北大的“词语切分与词性标注”规范。基于上述种种工作,可以把词语切分问题变得可操作和标准化,大家在统一的平台上进行实验和比较。
对分词的诉求是什么?
从已有工程经验来看,几乎不存在通用而且效果非常好的分词系统,例如:在人民日报上训练的分词系统,在二次元的魔幻小说上切分效果不佳。每个领域有其独特的词汇表示,这很难通过有限的训练数据捕捉到所有语言现象。
不用使用场景对分词的要求差异很大。在搜索的索引阶段,往往会召回所有可能切分结果,对切分准确率要求不高,但对分词速度有很高的要求,例如某中型搜索系统,每天 4000 万篇文章入库,每秒要处理 500 篇文档,每秒处理的文档字节数约有 50MB;如果分词系统太慢的话,需要开大量线程才能处理这些文档。
在问答系统中,需要对文本实现较为深入的理解,对分词和实体识别的准确性要求很高。
不用的使用场景,对分词提出了不同的要求,不需要片面地追求高准确率。
别家系统的准确率怎么这么高?
在分词系统研发中,最容易产生误解的就是比较系统准确率。系统准确率与训练数据非常相关,脱离数据而谈论准确率无异于“刷流氓”。2003 年 863 分词评测中就出现了 98% 的准确率,2007 年 Sighan 评测中最高准确率是 97%,在最近某司组织的评测中,最高准确率下降到了 94%。所有不同数据下的评测结果都不能直接比较高低。
现在吹嘘分词准确率的公司和单位越来越少了。
分词稳定性很重要
分词稳定性是指分词系统的输出在不同上下文下都比较稳定,不会出现明显被上下文影响的情况。例如,在下面句子中,“黄代恒”有时识别为人名,第二次出现未识别出来:
实战 分享 三 黄代恒 /nr 与 轨道 交通 : 软硬 结合 到 人机 结合 黄代恒 “ 在 不同 的 客户 场景 下 , 我们 用 三 种 技术 实现 轨道 交通 的 数据 洞察
一般纯统计分词系统的稳定性比不上基于词典实现的分词系统。在搜索中,分词稳定性非常重要,否则极容易出现查询不到的情况。
已有分词系统小结
分词大概是投入人力非常大的 NLP 方向,几乎每一家“有追求”的公司都有员工实施过类似的任务,而且反复迭代更新;在 NLP 研究界,这个问题从上个世纪 80 年代就已经开始探索,一直到 ACL 2017 仍然有这方面的论文 (有 4 篇丛神经网络角度探索分词的文章)。
如此多的人力投入到分词理论研发和工程研发中,产生了一批各有特色的分词系统。下面仅仅就本人接触到的系统作说明 (排名无先后),比较“古老”的系统不在此罗列:

IK 系统
该系统采用 JAVA 开发,实现逻辑不复杂,由于对 Lucene 和 ES 支持较好,因而得到了比较普遍的使用。该系统可以实现英文单词、中文单词的切分,OOV 识别能力不强。该系统有几种使用模式,分别对应不同的使用场景,如索引、查询等。
IK 有些功能比较贴心,比如热更新用户词典,支持用户自定义词典非常方面,对搜索工程师比较友好。
IK 的代码实现上优化不够好,甚至能发现 BUG。我们发现的 BUG 会导致 ES 中长 Query 无法实现精准匹配。
对于中小企业的内部应用来说,使用 IK 足够了。在商业系统上使用的话,要非常慎重,参与优化的人员太少了。
Jieba 系统
Jieba 大概是最好用的基于 Python 实现的分词系统了,2-3 行代码就可以实现分词调用和词性标注,速度还不错。基于 HMM 模型实现,可以实现一定程度的未登录词识别。
Jieba 有精确模式、全模式、搜索模式三种。全模式是找到所有可能词语;搜索模式是在精确模式的基础上对长词进行切分,提高召回率。
支持繁体分词;支持自定义词典;支持并行分词,方便实现加速。
在分词速度上,精确模式能达到 400KB/ 秒,全模式下能达到 1.5MB/ 秒。
Jieba 除了 Python 版本外,还有多种语言实现的版本,包括 C++, JAVA, Golang 等。
Java 版本的 Jieba 功能上受限,仅面向搜索使用。明略 SCOPA 产品中使用了 Java 版本的 Jieba 作为分词组件,替换了 IK。
Hanlp 平台
Hanlp 是一个功能非常全面的 NLP 平台,它的分词接口借鉴了 Ansj 的设计,形式上和命名上都非常像。
Hanlp 有“简约版”和“加强版”,简约版的模型参数较小,分词能力还可以;加强版在模型参数上扩大了若干倍,分词能力进一步提升。
Hanlp 支持基于 HMM 模型的分词、支持索引分词、繁体分词、简单匹配分词(极速模式)、基于 CRF 模型的分词、N- 最短路径分词等。实现了不少经典分词方法。
Hanlp 的部分模块做了重要优化,比如双数组,匹配速度很快,可以直接拿过来使用。
Hanlp 做了不少重现经典算法的工作,可以去 GitHub 上看一下!
ICTCLAS 系统
ICTCLAS 大概是“最知名”的分词系统了,从参加 2003 年中文分词评测,一直延续到了现在。现在已经是商业系统了 (改名 NLPIR),需要 License 才能运行。
从未登录词识别准确率上说,ICTCLAS 已经明显落后于基于 CRF 的分词系统了。
尽管如此,它的优点仍然比较明显:很少出现“错得离谱”的切分结果,这在基于 CRF 模型的分词系统上不少见,尤其是迁移到其它领域时;模型和库不大,启动快;基于 C++ 实现,能够很快迁移到其它语言。
从分词稳定性上来说,ICTCLAS 值得信赖,从分词准确率、分词速度等方面来考量,有不少分词系统超过了它;NLPIR 的源代码已经不再开放,这让用户很纠结。
交大分词
所谓“交大分词”,是指上交大赵海老师个人主页上的分词系统。该系统在 2007 年 Sighan 评测中拿到了多项第一。
该系统基于 CRF 模型构建,在模型特征提取上做了大量工作,分词准确率比较高。目前可用版本支持简体、繁体分词,也支持不同分词标准。该系统被常常用来比较分词准确率。
该系统的问题是不开源,只有 Windows 上的可执行文件,C++ 源码需要向作者申请。虽然该系统不开源,但作者的一系列论文基本上揭示了其原理,复制起来并不难。
从工程角度来考虑,该系统只适合做 DEMO 组件,不适合大规模工业化使用。
Stanford 分词
Stanford 分词系统的优点是准确率高,未登录词识别能力比较强;缺点非常明显,模型很大,约 300MB-400MB,启动非常慢,大概需要 10 秒 -20 秒。在所有分词系统中,没有比 Stanford 启动更慢的系统,分词速度也不快。代码优化的空间比较大。
Stanford 系统支持自定义训练,只要用户提供训练数据,该系统可以训练新的模型参数。
Stanford 分词系统只是验证作者论文的一种手段,为了非常微小的分词准确率提升,导致了模型参数膨胀。
在 Demo 环境下可以使用 Stanford 系统,在大规模数据环境下不适合使用该系统。
GPWS 系统
GPWS 是北京语言大学语言信息处理研究所研发的分词系统,2001 年对外发布。该分词系统是 2000 年后唯一一个基于大规模规则 + 统计的分词系统(仅限个人所知),在 2004 年非常低的硬件配置下,分词速度也能达到 3MB-5MB/ 秒,对系统资源的消耗很低。后来授权给了新浪、微软等公司使用,被应用在了信息检索中。
GPWS 可以实现中文人名、外国人名、日本人名的识别,其它分词系统几乎都没有做到这个程度;对通用领域的文本切分效果较好,支持自定义词典;很少出现切分“离谱”的情况。该系统适合大规模数据处理的场景。
上述所有系统几乎都依赖于训练数据,而 GPWS 没有这方面的问题。GPWS 依赖于高质量分词词典和歧义切分机制,采用基于可信度的人名识别方法,不依赖于公开的训练数据。
GPWS 最大的问题在于很难复制,代码没有公开;在分词准确率上,GPWS 已经比不上字本位的分词系统;但从分词稳定性上,GPWS 仍然非常出色,比纯统计分词系统明显要好。
分词的难点在哪里?
歧义
歧义问题与词长非常相关,词语越短,发生歧义的可能性越大,词语越长,发生歧义的可能性越低,很少出现成语与其他词发生歧义的情况。歧义问题在分词中不是罪严重的问题,仅占分词错误数的 10% 左右。歧义分类包括:
交集型歧义
abc -> 可以切分为 ab c 和 a bc,占所有歧义总量的 95%,也就是说歧义问题主要是指交集型歧义
例如:
研究生命的起源 | 研究生 命 的起源
这种环境下 工作 | 这种环境 下工 作
化妆 和 服装 | 化妆 和服 装
这群 山里的娃娃 |这 群山 里的娃娃
进书店 跟 进超市一样 | 进书店 跟进 超市一样
组合型歧义
abc ->可以切分为 abc 和 a bc 或 abc。
组合型歧义一般要通过前后邻接搭配的可能性大小来判断。
他从 马上 下来 | 他从 马 上 下来
这个门 把手 坏了 | 这个门 把 手 坏了
基于马尔科夫模型计算邻接搭配可以消除绝大部分歧义。
通过计算词语搭配的概率估计句子的概率,选择概率最大的结果即可。
分词错误的主要来源
未登录词 - 不在词典中的词,该问题在文本中出现频度远远高于歧义。
未登录词的类型包括:人名、地名、机构名、公司名、数字、日期、专业术语、新词、产品名等。一般把人名、地名、机构名、公司名叫命名实体,例如:

卢靖姗一夜爆红 (人名)
在东四十条站台见面 (地点)
银联的小兄弟网联成立了 (机构名)
公元 2017 年 8 月 24 日发生一件大事(日期)
中国外汇储备达到三点 94 万亿美元(数字)
在明略软件做大数据处理 (公司名)
基于暗网数据买牛股 (专业术语)
招行发布了朝朝盈一号的理财产品(产品名)
让你见识什么叫冻龄 (新词)
不同类型的命名实体还可以细分,比如人名可以分为中文人名、藏族人名、维族人名、日本人名、欧美人名等。
地名可以分为典型地名和非典型地名,典型地名如国、省、市、县、乡、村等;非典型地名还包括路、居委会、大厦商场、门牌单元、图书馆、门面等。理论上,只要是有经纬度坐标的实体,都可以纳入地名识别范畴。在实际工作中,这方面的识别需求非常强烈,比如在公安领域的线索或案情信息,往往涉及到这种非典型地名。
机构和公司的类型也多种多样,除了行政机构外,还有各种社团、NGO 组织、基金会、校友会等等;公司名涉及到公司全称和公司简称的识别,例如:
明略软件系统科技有限公司(全称)
明略软件(简称)
明略数据(简称)
全称识别相对容易一点,简称识别非常困难,比如:小米、滴滴、凡客、OFO 等。
机构公司名与地名之间存在很大的交集。理论上,一个机构或公司往往会有办公地点,有时也会用机构公司名来称呼该地点,这样的话机构公司名也就有了地点属性。例如:
小明在明略软件上班(公司名)
把球踢进了明略软件的门前(看做公司名还是地点?)
在实际工作中,命名实体的关注程度最高,因为这些实体往往是知识图谱的节点。其它未登录词中,专业术语的提取会对文本分类和文本理解有重要帮助。
分词中的语料问题
基于统计模型的分词系统,在分词结果上出现差异的一个原因是对语料的预处理差异导致。相当多的分词系统没有对训练数据进行一致性校验,认为训练数据是无差错的。在实际调查时发现,训练数据包含了不少标注不一致的情况。例如人民日报中的例子:
自认倒霉 | 自 认 倒霉
倒霉 鬼 | 倒霉鬼
除了切分一致性外,词性标注的不一致性更严重一些,如:“自认倒霉”有时标注为 l、有时标注为 lv;“难能可贵”有时标注为 i、有时标注为 iv。
分词语料的选择范围有限,主要包括北大人民日报标注语料、微软标注语料、社科院标注语料、CTB 语料、OntoNotes 语料、城市大学繁体语料、中研院繁体语料等。一般选择一种数据即可,数据需要购买。
分词语料之间在词语颗粒度上有一定差异,一般不混用进行训练,例如:
承租人、承租者 (北大) | 承租 商 (微软)
高 清晰度 彩电 (北大) | 高清晰度电视 (微软)
分词的理论解决方案
分词的理论解决方案是采用统计模型,基于切分语料进行训练。该方案在学术界和工程界都很常见,也是学术界的研究热点。方案的差异主要是模型和特征工程不一样。模型差异非常常见,比如隐马尔科夫模型、最大熵模型、条件随机场模型、结构感知机模型、RNN 模型 等。
特征提取
特征提取的第一步是选择单元:基于字还是基于词。从实践来看,基于字的模型对未登录词识别能力较强,但基于词的模型很少会出现切分“离谱”的情况。采用什么颗粒度单元,取决于具体任务。
特征工程会对最终分词结果产生很大影响。字本位分词的常见分词特征是:
图4
Unigram 是单字特征模板,当前字的前一个字、当前字、后一个字。Bigram 是邻接字组合特征模板,包括前一个字与当前字、当前字与后一个字的组合。Jump 是把前一个字与后一个字组合。
其它特征主要是关于字的属性,如是否数字、标点、字母等。这些特征都是形式上的特征,没有歧义。
每一个特征实例在 CRF 模型中有一个权重。由于特征越多,模型参数越大,在实际工程应用中资源消耗越大,因此在实际任务中会有一定取舍。
理论解决方案的问题
训练数据规模有限
北大人民日报的原始语料的词语数为 2800 万;CTB9.0 词语数为 200 万;国家语委数据为 5000 万字。
标注语料是一个非常消耗人力的事情。北大 1998 年人民日报的标注共持续了 3 年时间才完成。CTB1.0 的标注持续了约 2 年时间。
领域迁移性不佳
其他领域实施时,分词准确率下降很快。由于标注语料的词语使用无法覆盖实际语言现象,因此基于标注语料训练的分词系统在差异较大的领域会出现准确率降低的情况,例如基于北大语料训练的分词系统在微博上的切分准确率就不是很高。
模型越来越大,速度越来越慢
早期使用 HMM 模型训练分词系统,在北大数据上训练大概需要 1-2 分钟,内存消耗很小。现在使用 CRF 模型训练大概需要 3 天左右,内存大概需要十几 G。CRF 模型在训练分词系统时,其参数数量跟特征数量直接相关,训练数据越多,特征数量越大,模型也就越来越大。导致系统调用存在困难,运行速度下降。
如何工程解决?
图5
能用规则解决的,就不要靠模型了
针对文本中有规律的部分,可以利用规则或者正则表达式来识别,例如数字、标点、时间、日期、重叠式等,如笑一笑。
扩大训练语料
扩大训练语料的一种办法是购买更多语料;另外一种办法是利用其它分词系统来切分数据,对数据进行清洗,形成新数据。
这些不同的分词系统依赖的训练数据尽量不要相同,例如 Stanford 系统是基于 CTB 语料,LTP 系统是基于人民日报,这两个系统的切分结果就可以考虑混用。在混用前,要进行一定程度的预处理,比如保持切分一致性。
明略的分词系统通过使用多款不同分词系统的分词结果,扩大训练数据,在人名识别上大幅度提高了召回率。
增加词表
增加词表是提高切分准确率“立竿见影”的办法。在自然语言处理中,只要是封闭集合的词语或实体,可以考虑利用词表来切分,例如成语。该方法简单有效。
在明略分词数据中,集成了全国所有的地名、公交站名、路名等,精确到村和居委会,对国内地名识别上有很高的准确度。对机构名和公司名,集成了经常出现的国内行政机构、上市企业等名字。
在 Bosen 系统的演示中,对公司名识别准确率非常高,例如:“明略数据、明略软件”这种公司简称也能识别出来,即使没有上下文也能识别。这应该跟其后台的公司名数据有关。
最大匹配 + 大词表
从诸多实践来看,最大匹配分词策略 + 大词表的方法非常有效。在《中文分词十年回顾》中作者提到了最大匹配和大词表的效果:
Ftop 行表示没有未登录词的情况下,仅使用最大匹配达到的 F 值(准确率 + 召回率)。
实用的分词系统,都带有大量通用词表和领域词表。
收集整理领域词表,对迁移分词系统至关重要。这对统计分词系统比较困难。
结合深度学习?
ACL 2017 年有 3 篇跟分词相关的文章,都是深度学习 (神经网络) 和分词结合的内容。分别是:
Neural Word Segmentation with Rich Pretraining
Adversarial Multi-Criteria Learning for Chinese Word Segmentation
Fast and Accurate Neural Word Segmentation for Chinese
从明略的实践来看,深度学习应用到分词任务中的优点在于:模型非常小。在约 200MB 的语料上训练得到的模型只有 5MB。分词准确率接近历史上最佳评测结果,但是分词速度太慢。
从最新文献来看,利用神经网络来做分词,训练效率和运行效率都比较低,慢得无法忍受,不适合工程上部署,也不适合做 Demo。
在《Fast and Accurate …… for Chinese》中提供了运行速度对比,测试数据为 170k 左右,2015 和 2016 年的 6 项分词结果中,切分测试数据的时间从 28 秒到 125 秒。在传统方法上,比如基于 CRF 分词,运行时间大概只要 1 秒。
根据个人经验,神经网络在 NLP 上的成功应用的领域往往是准确率不高或者运行效率很低的场合,例如问答系统、机器翻译、句法分析。在准确率比较高或者运行效率不错的场景下,利用深度学习会得不偿失。
人工智能
2018-10-26 11:01:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
在AI技术发展迅猛的今天,很多设备都希望加上人脸识别功能,好像不加上点人脸识别功能感觉不够高大上,都往人脸识别这边靠,手机刷脸解锁,刷脸支付,刷脸开门,刷脸金融,刷脸安防,是不是以后还可以刷脸匹配男女交友?
很多人认为人脸识别直接用opencv做,其实那只是极其基础的识别个人脸,然并卵,好比学C++写了个hello类似。拿到人脸区域图片只是万里长征的第一步,真正能够起作用的是人脸特征值的提取,然后用于搜索和查找人脸,比如两张图片比较相似度,从一堆人脸库中找到最相似的人脸,对当前人脸识别是否是活体等。
对于可以接入外网的设备,可以直接通过在线api的http请求方式获得结果,但是有很多应用场景是离线的,或者说不通外网,只能局域网使用,为了安全性考虑,这个时候就要求所有的人脸处理在本地完成,本篇文章采用的百度离线SDK作为解决方案。可以去官网申请,默认有6个免费的密钥使用三个月,需要与本地设备的指纹信息匹配,感兴趣的同学可以自行去官网下载SDK。
百度离线人脸识别SDK文件比较大,光模型文件就645MB,估计这也许是识别率比较高的一方面原因吧,不断训练得出的模型库,本篇文章只放出Qt封装部分源码。官网对应的使用说明还是非常详细的,只要是学过编程的人就可以看懂。
第一步:初始化SDK
第二步:执行动作,比如查找人脸、图片比对、特征值比对等
头文件代码: #ifndef FACEBAIDULOCAL_H #define FACEBAIDULOCAL_H /** * 百度离线版人脸识别+人脸比对等功能类 作者:feiyangqingyun(QQ:517216493) 2018-8-30 * 1:支持活体检测 * 2:可设置最大队列中的图片数量 * 3:多线程处理,通过type控制当前处理类型 * 4:支持单张图片检索相似度最高的图片 * 5:支持指定目录图片生成特征文件 * 6:支持两张图片比对方式 * 7:可设置是否快速查找 * 8:可设置是否统计用时 */ #include #include #if (QT_VERSION > QT_VERSION_CHECK(5,0,0)) #include #endif #include "baidu_face_api.h" class FaceBaiDuLocal : public QThread { Q_OBJECT public: static FaceBaiDuLocal *Instance(); explicit FaceBaiDuLocal(QObject *parent = 0); ~FaceBaiDuLocal(); protected: void run(); private: static QScopedPointer self; BaiduFaceApi *api; std::vector *faces; QMutex mutex; //锁对象 bool stopped; //线程停止标志位 int maxCount; //最大图片张数 int type; //当前处理类型 int percent; //最小人脸百分比 int delayms; //减去毫秒数,用于造假 bool findFast; //是否快速模式 bool countTime; //统计用时 bool busy; //是否正忙 QList flags; //等待处理的图像队列的名称 QList imgs; //等待处理的图像队列 QList imgs2; //等待处理的比对图像队列 QString sdkPath; //SDK目录 QString imgDir; //图片目录 QImage oneImg; //单张图片比对找出最大特征图像 QList imgNames; //图像队列 QList > features; //特征队列 signals: //人脸区域坐标返回 void receiveFaceRect(const QString &flag, const QRect &rect, int msec); //获取人脸区域坐标失败 void receiveFaceRectFail(const QString &flag); //人脸特征返回 void receiveFaceFeature(const QString &flag, const QList &feature, int msec); //获取人脸特征失败 void receiveFaceFeatureFail(const QString &flag); //人脸比对结果返回 void receiveFaceCompare(const QString &flag, float result, int msec); //人脸比对失败 void receiveFaceCompareFail(const QString &flag); //单张图片检索最大相似度结果返回 void receiveFaceCompareOne(const QString &flag, const QImage &srcImg, const QString &targetName, float result); //所有人脸特征提取完毕 void receiveFaceFeatureFinsh(); //活体检测返回 void receiveFaceLive(const QString &flag, float result, int msec); //活体检测失败 void receiveFaceLiveFail(const QString &flag); public slots: //初始化SDK void init(); //停止处理线程 void stop(); //获取当前是否忙 bool getBusy(); //设置图片队列最大张数 void setMaxCount(int maxCount); //设置当前处理类型 void setType(int type); //设置最小人脸百分比 void setPercent(int percent); //设置减去毫秒数 void setDelayms(int delayms); //设置是否快速模式 void setFindFast(bool findFast); //设置是否统计用时 void setCountTime(bool countTime); //设置是否忙 void setBusy(bool busy); //设置SDK目录 void setSDKPath(const QString &sdkPath); //设置要将图片提取出特征的目录 void setImgDir(const QString &imgDir); //设置单张需要检索的图片 void setOneImg(const QString &flag, const QImage &oneImg); //往队列中追加单张图片等待处理 void append(const QString &flag, const QImage &img); //往队列中追加两张图片等待比对 void append(const QString &flag, const QImage &img, const QImage &img2); //自动加载目录下的所有图片的特征 void getFaceFeatures(const QString &imgDir); //获取人脸区域 bool getFaceRect(const QString &flag, const QImage &img, QRect &rect, int &msec); //活体检测 bool getFaceLive(const QString &flag, const QImage &img, float &result, int &msec); //获取人脸特征 bool getFaceFeature(const QString &flag, const QImage &img, QList &feature, int &msec); //人脸比对,传入两张照片特征 float getFaceCompare(const QString &flag, const QList &feature1, const QList &feature2); //人脸比对,传入两张照片 bool getFaceCompare(const QString &flag, const QImage &img1, const QImage &img2, float &result, int &msec); //从一堆图片中找到最像的一张图片 void getFaceOne(const QString &flag, const QImage &img, QString &targetName, float &result); //指定特征找到照片 void getFaceOne(const QString &flag, const QList &feature, QString &targetName, float &result); //添加人脸 void appendFace(const QString &flag, const QImage &img, const QString &txtFile); //删除人脸 void deleteFace(const QString &flag); }; #endif // FACEBAIDULOCAL_H
实现文件完整代码: #include "facebaidulocal.h" #define TIMEMS qPrintable(QTime::currentTime().toString("HH:mm:ss zzz")) QByteArray getImageData(const QImage &image) { QByteArray imageData; QBuffer buffer(&imageData); image.save(&buffer, "JPG"); imageData = imageData.toBase64(); return imageData; } QScopedPointer FaceBaiDuLocal::self; FaceBaiDuLocal *FaceBaiDuLocal::Instance() { if (self.isNull()) { QMutex mutex; QMutexLocker locker(&mutex); if (self.isNull()) { self.reset(new FaceBaiDuLocal); } } return self.data(); } FaceBaiDuLocal::FaceBaiDuLocal(QObject *parent) : QThread(parent) { //注册信号中未知的数据类型 qRegisterMetaType >("QList"); stopped = false; maxCount = 100; type = 1; percent = 8; delayms = 0; findFast = false; countTime = true; busy = false; sdkPath = qApp->applicationDirPath() + "/facesdk"; imgDir = ""; oneImg = QImage(); api = new BaiduFaceApi; faces = new std::vector(); } FaceBaiDuLocal::~FaceBaiDuLocal() { delete api; this->stop(); this->wait(1000); } void FaceBaiDuLocal::run() { this->init(); while(!stopped) { int count = flags.count(); if (count > 0) { QMutexLocker lock(&mutex); busy = true; if (type == 0) { QString flag = flags.takeFirst(); QImage img = imgs.takeFirst(); QRect rect; int msec; if (getFaceRect(flag, img, rect, msec)) { emit receiveFaceRect(flag, rect, msec); } else { emit receiveFaceRectFail(flag); } } else if (type == 1) { QString flag = flags.takeFirst(); QImage img = imgs.takeFirst(); QList feature; int msec; if (getFaceFeature(flag, img, feature, msec)) { emit receiveFaceFeature(flag, feature, msec); } else { emit receiveFaceFeatureFail(flag); } } else if (type == 2) { QString flag = flags.takeFirst(); QImage img1 = imgs.takeFirst(); QImage img2 = imgs2.takeFirst(); float result; int msec; if (getFaceCompare(flag, img1, img2, result, msec)) { emit receiveFaceCompare(flag, result, msec); } else { emit receiveFaceCompareFail(flag); } } else if (type == 3) { flags.takeFirst(); getFaceFeatures(imgDir); } else if (type == 4) { QString flag = flags.takeFirst(); QString targetName; float result; getFaceOne(flag, oneImg, targetName, result); if (!targetName.isEmpty()) { emit receiveFaceCompareOne(flag, oneImg, targetName, result); } } else if (type == 5) { QString flag = flags.takeFirst(); QImage img = imgs.takeFirst(); float result; int msec; if (getFaceLive(flag, img, result, msec)) { emit receiveFaceLive(flag, result, msec); } else { emit receiveFaceLiveFail(flag); } } } msleep(100); busy = false; } stopped = false; } void FaceBaiDuLocal::init() { int res = api->sdk_init(); res = api->is_auth(); if(res != 1) { qDebug() << TIMEMS << QString("init sdk error: %1").arg(res); return; } else { //设置最小人脸,默认30 api->set_min_face_size(percent); //设置光照阈值,默认40 api->set_illum_thr(20); //设置角度阈值,默认15 //api->set_eulur_angle_thr(30, 30, 30); qDebug() << TIMEMS << "init sdk ok"; } } void FaceBaiDuLocal::stop() { stopped = true; } bool FaceBaiDuLocal::getBusy() { return this->busy; } void FaceBaiDuLocal::setMaxCount(int maxCount) { if (maxCount <= 1000) { this->maxCount = maxCount; } } void FaceBaiDuLocal::setType(int type) { if (this->type != type) { this->type = type; this->flags.clear(); this->imgs.clear(); this->imgs2.clear(); } } void FaceBaiDuLocal::setPercent(int percent) { this->percent = percent; } void FaceBaiDuLocal::setDelayms(int delayms) { this->delayms = delayms; } void FaceBaiDuLocal::setFindFast(bool findFast) { this->findFast = findFast; } void FaceBaiDuLocal::setCountTime(bool countTime) { this->countTime = countTime; } void FaceBaiDuLocal::setBusy(bool busy) { this->busy = busy; } void FaceBaiDuLocal::setSDKPath(const QString &sdkPath) { this->sdkPath = sdkPath; } void FaceBaiDuLocal::setImgDir(const QString &imgDir) { this->imgDir = imgDir; this->flags.clear(); this->flags.append("imgDir"); this->type = 3; } void FaceBaiDuLocal::setOneImg(const QString &flag, const QImage &oneImg) { setType(4); //需要将图片重新拷贝一个,否则当原图像改变之后也会改变 this->oneImg = oneImg.copy(); this->flags.append(flag); } void FaceBaiDuLocal::append(const QString &flag, const QImage &img) { QMutexLocker lock(&mutex); int count = flags.count(); if (count < maxCount) { flags.append(flag); imgs.append(img); } } void FaceBaiDuLocal::append(const QString &flag, const QImage &img, const QImage &img2) { QMutexLocker lock(&mutex); int count = flags.count(); if (count < maxCount) { flags.append(flag); imgs.append(img); imgs2.append(img2); } } void FaceBaiDuLocal::getFaceFeatures(const QString &imgDir) { imgNames.clear(); features.clear(); //载入指定目录图像处理特征 QDir imagePath(imgDir); QStringList filter; filter << "*.jpg" << "*.bmp" << "*.png" << "*.jpeg" << "*.gif"; imgNames.append(imagePath.entryList(filter)); qDebug() << TIMEMS << "getFaceFeatures" << imgNames; //从目录下读取同名的txt文件(存储的特征) //如果存在则从文件读取特征,如果不存在则转码解析出特征 //转码完成后将得到的特征存储到同名txt文件 int count = imgNames.count(); for (int i = 0; i < count; i++) { QList feature; int msec; QString imgName = imgNames.at(i); QStringList list = imgName.split("."); QString txtName = imgDir + "/" + list.at(0) + ".txt"; QFile file(txtName); if (file.exists()) { if (file.open(QFile::ReadOnly)) { QString data = file.readAll(); file.close(); qDebug() << TIMEMS << "readFaceFeature" << txtName; QStringList list = data.split(","); foreach (QString str, list) { if (!str.isEmpty()) { feature.append(str.toFloat()); } } } } else { QImage img(imgDir + "/" + imgName); bool ok = getFaceFeature(imgName, img, feature, msec); if (ok) { emit receiveFaceFeature(imgName, feature, msec); if (file.open(QFile::WriteOnly)) { QStringList list; foreach (float fea, feature) { list.append(QString::number(fea)); } qDebug() << TIMEMS << "writeFaceFeature" << txtName; file.write(list.join(",").toLatin1()); file.close(); } } } features.append(feature); msleep(1); } qDebug() << TIMEMS << "getFaceFeatures finsh"; emit receiveFaceFeatureFinsh(); } bool FaceBaiDuLocal::getFaceRect(const QString &flag, const QImage &img, QRect &rect, int &msec) { //qDebug() << TIMEMS << flag << "getFaceRect"; QTime time; if (countTime) { time.start(); } faces->clear(); QByteArray imageData = getImageData(img); int result = api->track_max_face(faces, imageData.constData(), 1); if (result == 1) { TrackFaceInfo info = faces->at(0); FaceInfo ibox = info.box; float width = ibox.mWidth; float x = ibox.mCenter_x; float y = ibox.mCenter_y; rect = QRect(x - width / 2, y - width / 2, width, width); if (countTime) { msec = time.elapsed() - delayms; } else { msec = delayms; } msec = msec < 0 ? 0 : msec; return true; } else { return false; } return false; } bool FaceBaiDuLocal::getFaceLive(const QString &flag, const QImage &img, float &result, int &msec) { //qDebug() << TIMEMS << flag << "getFaceLive"; QTime time; if (countTime) { time.start(); } result = 0; QByteArray imageData = getImageData(img); std::string value = api->rgb_liveness_check(imageData.constData(), 1); QString data = value.c_str(); data = data.replace("\t", ""); data = data.replace("\"", ""); data = data.replace(" ", ""); int index = -1; QStringList list = data.split("\n"); foreach (QString str, list) { index = str.indexOf("score:"); if (index >= 0) { result = str.mid(6, 4).toFloat(); break; } } if (index >= 0) { if (countTime) { msec = time.elapsed() - delayms; } else { msec = delayms; } msec = msec < 0 ? 0 : msec; return true; } else { return false; } return false; } bool FaceBaiDuLocal::getFaceFeature(const QString &flag, const QImage &img, QList &feature, int &msec) { //qDebug() << TIMEMS << flag << "getFaceFeature" << img.width() << img.height() << img.size(); QTime time; if (countTime) { time.start(); } const float *fea = nullptr; QByteArray imageData = getImageData(img); int result = api->get_face_feature(imageData.constData(), 1, fea); if (result == 512) { feature.clear(); for (int i = 0; i < 512; i++) { feature.append(fea[i]); } if (countTime) { msec = time.elapsed() - delayms; } else { msec = delayms; } msec = msec < 0 ? 0 : msec; return true; } else { return false; } return false; } float FaceBaiDuLocal::getFaceCompare(const QString &flag, const QList &feature1, const QList &feature2) { //qDebug() << TIMEMS << flag << "getFaceCompareXXX"; std::vector fea1, fea2; for (int i = 0; i < 512; i++) { fea1.push_back(feature1.at(i)); fea2.push_back(feature2.at(i)); } float result = api->compare_feature(fea1, fea2); //过滤非法的值 result = result > 100 ? 0 : result; return result; } bool FaceBaiDuLocal::getFaceCompare(const QString &flag, const QImage &img1, const QImage &img2, float &result, int &msec) { //qDebug() << TIMEMS << flag << "getFaceCompare"; result = 0; bool ok1, ok2; QList feature1, feature2; int msec1, msec2; QString flag1, flag2; if (flag.contains("|")) { QStringList list = flag.split("|"); flag1 = list.at(0); flag2 = list.at(1); } else { flag1 = flag; flag2 = flag; } QTime time; if (countTime) { time.start(); } ok1 = getFaceFeature(flag1, img1, feature1, msec1); if (ok1) { emit receiveFaceFeature(flag1, feature1, msec1); } ok2 = getFaceFeature(flag2, img2, feature2, msec2); if (ok2) { emit receiveFaceFeature(flag2, feature2, msec2); } if (ok1 && ok2) { result = getFaceCompare(flag, feature1, feature2); if (countTime) { msec = time.elapsed() - delayms; } else { msec = delayms; } msec = msec < 0 ? 0 : msec; return true; } else { return false; } return false; } void FaceBaiDuLocal::getFaceOne(const QString &flag, const QImage &img, QString &targetName, float &result) { QList feature; int msec; bool ok = getFaceFeature(flag, img, feature, msec); if (ok) { emit receiveFaceFeature(flag, feature, msec); getFaceOne(flag, feature, targetName, result); } } void FaceBaiDuLocal::getFaceOne(const QString &flag, const QList &feature, QString &targetName, float &result) { //用当前图片的特征与特征数据库比对 result = 0; int count = imgNames.count(); for (int i = 0; i < count; i++) { QString imgName = imgNames.at(i); float currentResult = getFaceCompare(flag, feature, features.at(i)); //qDebug() << TIMEMS << "getFaceOne" << imgName << currentResult; if (currentResult > result) { result = currentResult; targetName = imgName; } } qDebug() << TIMEMS << "getFaceOne result" << targetName << result; } void FaceBaiDuLocal::appendFace(const QString &flag, const QImage &img, const QString &txtFile) { QList feature; int msec; QImage image = img; bool ok = getFaceFeature(flag, image, feature, msec); msleep(100); qDebug() << TIMEMS << "getFaceFeature result" << ok << "appendFace" << txtFile; if (ok) { emit receiveFaceFeature(flag, feature, msec); //保存txt文件 QFile file(txtFile); if (file.open(QFile::WriteOnly)) { QStringList list; foreach (float fea, feature) { list.append(QString::number(fea)); } file.write(list.join(",").toLatin1()); file.close(); } //保存图片文件 QString imgName = txtFile; imgName = imgName.replace("txt", "jpg"); image.save(imgName, "jpg"); imgNames.append(QFileInfo(imgName).fileName()); features.append(feature); } } void FaceBaiDuLocal::deleteFace(const QString &flag) { //从图片名称中找到标识符 int index = imgNames.indexOf(flag); if (index >= 0) { imgNames.removeAt(index); features.removeAt(index); //删除图片文件 QString imgFileName = QString("%1/face/%2.jpg").arg(qApp->applicationDirPath()).arg(flag); QFile imgFile(imgFileName); imgFile.remove(); qDebug() << TIMEMS << "delete faceImage" << imgFileName; //删除特征文件 QString txtFileName = QString("%1/face/%2.txt").arg(qApp->applicationDirPath()).arg(flag); QFile txtFile(txtFileName); txtFile.remove(); qDebug() << TIMEMS << "delete faceTxt" << txtFileName; } }
人工智能
2018-09-15 22:52:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
1.检测脸部 def read_im_and_landmarks(fname): if not osp.exists(fname): raise Exception('Cannot find image file: {}'.format(fname)) im = cv2.imread(fname, cv2.IMREAD_COLOR) im = cv2.resize(im, (im.shape[1] * SCALE_FACTOR, im.shape[0] * SCALE_FACTOR)) s = get_landmarks(im) return im, s
2.校正脸部 def calibrate(frame): frame_new = numpy.clip(frame,0,255) frame_new = numpy.uint8(frame_new) frame_new = cv2.cvtColor(frame_new,cv2.COLOR_BGR2RGB) dets = predictor_calibrate(frame_new, 1) num_faces = len(dets) if num_faces == 0: print("Sorry, there were no faces found in current frame") return None faces = dlib.full_object_detections() for detection in dets: faces.append(sp(frame_new, detection)) images = dlib.get_face_chips(frame_new, faces, size=150) return images

3.脸部分割效果:
4.脸部校正效果
人工智能
2018-09-14 23:16:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
BotSharp是一款为方便构建智能对话机器人平台而开发的开源框架,最大的特点是所有模型算法都是基于.NET Core开发实现,甚至最基本的Penn Treebank分词标准,都重新用C#实现了。在机器学习python占绝对优势的时代算是不可多得的项目。该项目涉及自然语言理解,计算机视觉和音频处理技术,旨在促进智能机器人助手在信息系统中的开发和应用。目前里面的NLP部分实现的比较多一些,比如n-gram, TF-IDF, CRF, SVM和Bayes。Chabot所需要的算法都已经有了,大家下载完 源代码 就可以开始搭建Chabot平台了,开箱即用的机器学习算法使.NET程序员能够更快,更轻松地开发对话式人工智能应用程序。
BotSharp的目标是帮助.NET开发者构建自己的流程自动化机器人,以自然语言对话交流的方式让电脑完成一些机械重复的劳动,并加入智能感知进去。让机器人能在声音,图像和语言方面都能与使用者沟通。项目分成几个项目,封装在不同的Dll里,有基本数据算法库,自然语言库,计算机视觉库和语音识别及合成库,最后通过即时通讯通道和使用者进行互动,像Slack和Facebook Messenger这样的可以进行富内容展现的聊天平台。
BotSharp严格按照组件原则,解耦框架中所需的每个部分。因此,您可以选择不同的UI / UX,或选择不同的NLP Tagger,或选择更高级的算法来执行命名实体识别任务。它们都是基于接口进行模块化设计的。NLP流程管道的设计让你可以随意扩充机器人的识别能力。使用了标准的Open API,可以用Swagger进行API调试。使用了Docker容器技术,运行布署都很方便。
下面是一些特性总结: 无需依赖任何其他机器学习算法库,集成调试更容易。 内置多Bot管理,轻松构建Bot即服务平台。 具有生命周期的上下文输入/输出管理,使圣诞流程切换更可控。 使用自然语言处理管道机制轻松使用扩展,并构建自己独特的机器人处理流程。 用C#全面实现NLP基础算法而没有历史问题。 直接支持来自其他bot平台的导出/导入。 支持不同的UI提供商,如Rasa UI和Articulate UI。 支持多种数据请求和响应格式,如Rasa NLU和Dialogflow。 与流行的社交平台集成,如Facebook Messenger,Slack和Telegram。 多核并行计算优化。

项目本身还在不断的迭代中,代码可以在这里 下载 。如果大家觉得这个项目对自己很有帮助,请记得Like一下哦,得到大家的认可是对开源项目贡献者最大的支持。也欢迎大家提出意见和建议,有Pull Request更好了。
人工智能
2018-09-17 11:02:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
韩国央行宣布,计划在2019年上半年推出类似于中国的“支付宝”或“微信支付”这样的移动支付服务,旨在削减银行卡网络为消费者和商家带来的“社会成本”。
韩国银行表示,这种基于智能手机的移动钱包服务将允许消费者和商家之间进行转账,而无需中介机构的介入,例如银行卡网络,后者涉及到卡片公司、支付网关提供商和虚拟账号支付解决方案提供商等。
韩国银行的官员们在新闻发布会上称,将来只需要一款手机App,用户就可以通过扫描二维码的方式,将资金从银行账户中取出并转给商家。当然,手机App应用将内置用户验证系统,包括密码或指纹等。
韩国银行电子金融部门负责人Lee Jong-yeol称:“原本多层次的支付和结算过程将被压缩到最小,从而降低佣金费用。”,他预计,将来商家支付的佣金将低于1%。
人工智能
2018-08-07 13:59:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>

本章是接前两篇《分词工具Hanlp基于感知机的中文分词框架》和《基于结构化感知机的词性标注与命名实体识别框架》的。本系统将同时进行中文分词、词性标注与命名实体识别3个任务的子系统称为“词法分析器”。
加载
对应的类为PerceptronLexicalAnalyzer,其构造方法为递增的3个模型地址: public PerceptronLexicalAnalyzer(String cwsModelFile) throws IOException public PerceptronLexicalAnalyzer(String cwsModelFile, String posModelFile) throws IOException public PerceptronLexicalAnalyzer(String cwsModelFile, String posModelFile, String nerModelFile) throws IOException
用户根据自己要进行的任务,训练3个模型中的任意个数,然后灵活传入此类构造即可。此处假设训练了3个模型,那么传入这3个模型的路径即可构造词法分析器:
public void testCWSandPOSandNER() throws Exception
{
PerceptronLexicalAnalyzer segmenter = new PerceptronLexicalAnalyzer(Config.CWS_MODEL_FILE, Config.POS_MODEL_FILE, Config.NER_MODEL_FILE);
}
分析
词法分析器的分析接口如下:
public static final String SENTENCE = "香港特别行政区的张朝阳说商品和服务是三原县鲁桥食品厂的主营业务";
public void testCWSandPOSandNER() throws Exception
{
PerceptronLexicalAnalyzer segmenter = new PerceptronLexicalAnalyzer(Config.CWS_MODEL_FILE, Config.POS_MODEL_FILE, Config.NER_MODEL_FILE);
Sentence sentence = segmenter.analyze(SENTENCE);
System.out.println(sentence);
}
正常情况下输出:
[香港/ns 特别/a 行政区/n]/ns 的/n 张朝阳/nr 说/v 商品/n 和/c 服务/vn 是/v [三原县/ns 鲁桥/nz 食品厂/n]/nt 的/z 主营/vn 业务/n
Sentence结构是一个对人民日报语料格式的实现,用户可以方便地用for循环去遍历单词,用instanceof来判断单词属于复合词还是简单词。此处演示输出句子中所有复合词内部的简单词:
for (IWord word : sentence)
{
if (word instanceof CompoundWord)
System.out.println(((CompoundWord) word).innerList);
}
结果:
[香港/ns, 特别/a, 行政区/n]
[三原县/ns, 鲁桥/nz, 食品厂/n]
通过此结构,我们可以捕捉语言的复合结构(简单词构成复合词)。此结构输出为文本后满足人民日报2014语料格式,形成了一个语料与文本之间的闭环。
与HanLP旧接口的兼容
本系统依然兼容HanLP的seg接口,与analyze接口比较如下:
System.out.println(segmenter.seg(SENTENCE));
System.out.println(segmenter.analyze(SENTENCE));
输出:
[香港特别行政区/ns, 的/n, 张朝阳/nr, 说/v, 商品/n, 和/c, 服务/vn, 是/v, 三原县鲁桥食品厂/nt, 的/z, 主营/vn, 业务/n]
[香港/ns 特别/a 行政区/n]/ns 的/n 张朝阳/nr 说/v 商品/n 和/c 服务/vn 是/v [三原县/ns 鲁桥/nz 食品厂/n]/nt 的/z 主营/vn 业务/n
注意上面两个结果中的命名实体有着本质的不同,seg接口无法输出层次结构,而analyze接口可以。
在线学习
本框架另一个特色功能是“在线学习”,或称“增量训练”。其适用场景如下: 线上系统的统计模型依然会犯错误,但重新训练的代价过大(比如耗时长,没有语料等等)。本系统支持在线学习新知识,实时修正统计模型的错误。这里举一个分词的例子,人民日报1998年1月份训练出来的模型无法分对“下雨天地面积水”这个句子:
PerceptronSegmenter segmenter = new PerceptronSegmenter(Config.CWS_MODEL_FILE);
System.out.println(segmenter.segment("下雨天地面积水"));
输出:
[下雨, 天地, 面积, 水]
但本系统支持在线学习这个句子的正确分词方式:
segmenter.learn("下雨天 地面 积水");
System.out.println(segmenter.segment("下雨天地面积水"));
通过learn接口,感知机模型学习到了这个句子的正确分词方式,并输出了正确结果:
[下雨天, 地面, 积水]
对于类似的句子,也拥有了举一反三的泛化能力:
System.out.println(segmenter.segment("下雨天地面积累了很多水"));
输出:
[下雨天, 地面, 积累, 了, 很多, 水]
词性标注器和命名实体识别器也有类似的learn接口,用户可举一反三类似地调用,不再赘述。
模型压缩与持久化
在线学习或训练后的模型可以序列化到某个路径,其接口是:
/**
* @param ratio 压缩比c(压缩掉的体积,压缩后体积变为1-c)
* @return
*/
public LinearModel compress(final double ratio)

/**
* 保存到路径
*
* @param modelFile
* @throws IOException
*/
public void save(String modelFile, final double ratio) throws IOException
比如压缩比为0.1,则压缩后的体积为原来的0.9。此处的“体积”指的是特征数量,并不一定等于文件体积。
命令行接口
如上文所述,本框架中的功能可以通过命令行调用:
$ java -cp hanlp.jar com.hankcs.hanlp.model.perceptron.Main
缺少必需参数: -model
用法: com.hankcs.hanlp.model.perceptron.Main
-task [TaskType] 任务类型:CWS|POS|NER (CWS)
-train [flag] 执行训练任务
-test [flag] 执行预测任务
-evaluate [flag] 执行评估任务
-model [String] 模型文件路径
-input [String] 输入文本路径
-result [String] 结果保存路径
-gold [String] 标准分词语料
-reference [String] 训练集
-development [String] 开发集
-iter [Integer] 迭代次数 (5)
-compressRatio [Double] 模型压缩比率 (0.0)
-thread [int] 线程数 (8)
当用户按照上文所述训练了1到3个模型后,可以通过命令行接口交互式地观察效果:
$ java -cp target/hanlp-1.6.0.jar:src/main/resources com.hankcs.hanlp.model.perceptron.Main -test
商品和服务
商品/n 和/c 服务/vn
上海华安工业(集团)公司董事长谭旭光和秘书胡花蕊来到美国纽约现代艺术博物馆参观
[上海/ns 华安/nz 工业/n (/w 集团/n )/w 公司/n]/nt 董事长/n 谭旭光/nr 和/c 秘书/n 胡花蕊/nr 来到/v [美国/ns 纽约/ns 现代/t 艺术/n 博物馆/n]/ns 参观/v 默认加载配置文件指定的模型,可以通过-model your/cws.bin,your/pos.bin,your/ner.bin指定别的模型。 还可以将输入输出重定向到文件,形成一个pipeline。 更多信息,请参考《编译运行》。
未来工作 英文和数字最好要做特殊处理。 与hanlp-lucene-plugin的集成。 集成自定义词典。 索引分词等功能。 重构出新的分词、词性标注与命名实体识别接口,统一所有分词器,并逐步淘汰旧接口。
文章摘自:HanLP: Han Language Processing ——开源自由的汉语言处理包
人工智能
2019-04-10 09:52:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
模型训练与在线预测服务、推荐算法四部曲、机器学习PAI实战、更多精彩,尽在 开发者分会场
【机器学习PAI实战】—— 玩转人工智能之商品价格预测
【机器学习PAI实战】—— 玩转人工智能之你最喜欢哪个男生?
【机器学习PAI实战】—— 玩转人工智能之美食推荐
【机器学习PAI实战】—— 玩转人工智能之利用GAN自动生成二次元头像
绪论
人工智能并非新的术语,这个概念由来已久, 大约从80年代初开始,计算机科学家们开始设计可以学习和模仿人类行为的算法。人工智能的发展曲折向前,伴随着数据量的上涨、计算力的提升,机器学习的火热,以及深度学习的爆发,人工智能迎来快速发展,迅速席卷全球。
人工智能的研究领域也在不断扩大,已经涵盖专家系统、机器学习、进化计算、模糊逻辑、计算机视觉、自然语言处理、推荐系统等多个领域。可以毫不夸张地说,人工智能技术正在像100多年前的电力一样,即将改变每个行业。每个企业都不希望在这次浪潮中掉队,如何才能利用AI帮助自己的 企业进行转型 呢?AI领域著名学者吴恩达在前不久针对该问题,发表了《 AI转型指南 》。
机器学习,作为实现人工智能的一种方法,对于人工智能的发展起着 十分重要 的作用。而深度学习,作为机器学习中的一种技术,更是摧枯拉朽地实现了各种任务,极大推动了各个领域朝着人工智能的方向迈进。下面这张图,非常形象地概况了三者之间的关系。
总之,人工智能、机器学习、深度学习已经深入到企业生产和个人生活的方方面面。能够熟练运用机器学习解决生活生产当中的应用,掌握人工智能技术,对于企业和个人的长远发展变得至关重要。
1. 机器学习算法
机器学习(Machine Learning, ML)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。机器学习算法根据解决的任务类型,可以分为分类算法、回归算法、聚类算法等,深度学习作为机器学习中比较特殊的一类算法,是神经网络算法的延伸和扩展。
机器学习大致可以分为监督学习和非监督学习。监督式学习,由已有的数据包括输入输出,训练模型函数;然后把新的输入数据带入模型函数,预测数据输出。函数的输出如果是一个连续的值,则称为回归分析,如果输出是离散数值,则称作分类。与监督学习相对应的是无监督学习,此时数据没有标注信息,聚类是典型的无监督学习。
阿里云机器学习平台PAI(Platform of Artificial Intelligence) ,为传统机器学习提供上百种算法和大规模分布式计算的服务;为深度学习客户提供单机多卡、多机多卡的高性价比资源服务,支持最新的深度学习开源框架;帮助开发者和企业客户弹性扩缩计算资源,轻松实现在线预测服务。
PAI-Studio封装常用机器学习算法及丰富的 可视化组件 ,用户无需代码基础,通过拖拉拽即可训练模型。
如下图示,在阿里云机器学习平台开通账号之后,进入管理控制台—可视化建模,根据自己的需要新建项目,进入机器学习即可进入到PAI-Studio进行使用。

PAI-Studio上通过拖拽算法组件,构建实验,进行模型训练,训练好的模型可以一键部署到PAI-EAS。机器学习模型在线部署功能可以将您的模型一键部署为Restful API,您可以通过HTTP请求的方式进行调用( 使用说明文档 )。
PAI-DSW(Data science workshop)是专门为算法开发者准备的云端深度学习开发环境,用户可以登录DSW进行代码的开发并运行工作。目前DSW内置了PAI团队深度优化过的Tensorflow框架,同时也可以通过打开console对话窗口自行安装需要的第三方库。
1.1 分类算法
分类算法应用广泛,比如新闻内容分类、商品类目预测、文本情感分析、邮件垃圾过滤、图像分类、异常检测等。常见的分类算法有k近邻、朴素贝叶斯、决策树、SVM、利用adaboost增强弱分类器等。
k近邻算法(kNN),简单地说,是采用测量不同特征值之间距离的方法进行分类。kNN的工作原理是:存在一个样本集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处。最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。
决策树,比较容易理解,以下图为例,根据某个人的特征(年龄、是否学生、信用情况)来进行分类,判断是否可以放贷款给他。生成的决策树如下图示。决策树思想,实际上就是寻找最纯净的划分方法,主要通过决策树的构造和剪枝。
尽管有剪枝等等方法,一棵树的生成肯定还是不如多棵树,因此就有了 随机森林 ,解决决策树泛化能力弱的缺点。根据训练数据,构造m个CART决 策树,这m个CART形成随机森林,通过投票表决结果,决定数据属于哪一类(投票机制有一票否决制、少数服从多数、加权多数),这就是随机森林的方法。
朴素贝叶斯, 其中的朴素一词的来源就是假设各特征之间相互独立。这一假设使得朴素贝叶斯算法变得简单,但有时会牺牲一定的分类准确率。贝叶斯公式定义如下:
公式的右边是总结历史,公式的左边是预知未来,如果把Y看出类别,X看出特征,P(Yk|X)就是在已知特征X的情况下求Yk类别的概率,而对P(Yk|X)的计算又全部转化到类别Yk的特征分布上来。朴素贝叶斯算法逻辑简单,容易实现,计算过程中的时间空间开销也比较小。 朴素贝叶斯假设属性之间相互独立,这种假设在实际过程中往往是不成立的。在属性之间相关性越大,分类误差也就越大。
支持向量机(Support Vector Machine, SVM) 的基本模型是在特征空间上找到最佳的分离超平面使得训练集上正负样本间隔最大。SVM是用来解决二分类问题的有监督学习算法,在引入了核方法之后SVM也可以用来解决非线性问题。 一般SVM有下面三种:(1)硬间隔支持向量机(线性可分支持向量机):当训练数据线性可分时,可通过硬间隔最大化学得一个线性可分支持向量机。(2)软间隔支持向量机:当训练数据近似线性可分时,可通过软间隔最大化学得一个线性支持向量机。(3)非线性支持向量机:当训练数据线性不可分时,可通过核方法以及软间隔最大化学得一个非线性支持向量机。
AdaBoost,每种分类算法都有自己的优缺点,我们把分类效果不是很好的分类器叫做弱分类器,分类效果好的分类器叫做强分类器。Adaboost算法基本原理就是将多个弱分类器(弱分类器一般选用单层决策树)进行合理的结合,使其成为一个强分类器。Adaboost采用迭代的思想,每次迭代只训练一个弱分类器,训练好的弱分类器将参与下一次迭代的使用。也就是说,在第N次迭代中,一共就有N个弱分类器,其中N-1个是以前训练好的,其各种参数都不再改变,本次训练第N个分类器。其中弱分类器的关系是第N个弱分类器更可能分对前N-1个弱分类器没分对的数据,最终分类输出要看这N个分类器的综合效果。
上面依次对常用的分类算法进行了介绍,PAI-Studio中也提供了相应的算法组件,如果想要使用,可以直接拖拽对应组件,配置相关参数即可。
1.2 回归问题
回归与分类的不同,就在于其目标变量是连续数值型。回归分析根据已知数据训练出模型(即回归方程),对新的数据预测时,只需要代入到模型,计算出预测数值。回归几乎可以应用到任何事情,比如预测商品价格、股价趋势预测、预测明日气温、预测某种情况发生概率(可根据概率大小转化为分类问题)、预测广告点击率进行排序等。比较常用的回归方法主要有线性回归和逻辑回归。
线性回归比较简单,描述了自变量和因变量之间的简单线性关系,我们的目标是通过特征的组合来学习到要预测函数式(线性式),我们用X1,X2..Xn 去描述feature里面的分量,我们可以做出一个估计函数:​
​ ,θ在这儿称为参数,在这的意思是调整feature中每个分量的影响力。如果我们令X0 = 1,就可以用向量的方式来表示了: ​
​ , 我们也需要一个机制去评估我们θ是否比较好,所以说需要对我们做出的h函数进行评估,一般这个函数称为损失函数(loss function)或者错误函数(error function),描述h函数不好的程度,在下面,我们称这个函数为J函数,我们要做的就是调整θ以使得J(θ)取得最小值。如下所示:

其中,最常用的方法是梯度下降法。
逻辑回归 ,logistic回归本质上是线性回归,只是在特征到结果的映射中加入了一层函数映射,即先把特征线性求和,然后使用函数g(z)将最为假设函数来预测。g(z)可以将连续值映射到0和1上。logistic回归的假设函数如下,线性回归假设函数只是​
​ ,

logistic回归还可以用来分类0/1问题,也就是预测结果属于0或者1的二值分类问题。
此外,常用的回归方法还有对于线性回归做了约束变化的 岭回归 ,非线性的 树回归 等。
当然,PAI-Studio中也提供了这些算法组件。
1.3 聚类算法
聚类算法是比较典型的非监督学习。聚类算法的应用也是十分广泛的,在新闻热门话题聚类、图像分割、用户画像分析聚类进行个性化推荐、基因工程等多个领域都有很好的应用。聚类算法直观地理解,就是将相似的对象归到同一个簇中,将不相似的对象归到不同簇,簇内的对象越相似,聚类的效果越好。常见的聚类算法有K-means、K-medoids、DBSCAN、层次聚类、谱聚类等。
K-means 聚类是发现给定数据集的k个簇,簇个数k是用户提前设定的超参数,每一个簇通过其质心,即簇中所有点的中心来描述。K-means的工作流程是这样的:1) 随机确定k个初始点作为质心。 2)将数据集中的每个点分配到一个簇中,具体就是为每个点找距其最近的质心,并将其分配给该质心所对应的簇。3)更新每个簇的质心,即更新为该簇所有点的平均值。4)重复步骤2和3,直至收敛,即满足迭代次数或者质心基本不再变化。 K-medoids 算法是K-means算法的变型,其中最主要的不同在于以下两点:第1步骤中Kmedoids选取的质心必须是某些样本点的值,而不是任意值;更新质心的时候需要先计算cluster内所有样本点到其中一个样本点的曼哈顿距离和(绝对误差),然后选出使cluster绝对误差最小的样本点作为质心。
K-medoids聚类 可以理解为K-means聚类的变种,其中K-means的初始簇中心点是随机的,K-medoids的初始中心点必须是样本中的点;K-means在迭代过程中重新计算质心是计算的平均值,而K-medoids则是先计算所有样本点到其中一个样本点的曼哈顿距离之和(绝对误差),然后选择使绝对误差最小的样本点作为质心。此外K-medoids聚类的时间复杂度更高,对于大规模的数据性能更好,最后聚类的簇中心点也一定是样本点中的一个。
DBSCAN聚类 ,英文全写为Density-based spatial clustering of applications with noise,是一种基于数据密度的无监督聚类算法。 在聚类空间中的一定区域内,用给定的半径阈值和数量阈值,筛选出核心点及核心点的领域点,通过密度可达、密度相连的定义,实现数据点的聚类。 在 2014 年,DBSCAN在数据挖掘会议 KDD 上获颁发了 Test of Time award,该奖项是颁发给一些于理论及实际层面均获得持续性的关注的算法。和传统的K-Means算法相比,DBSCAN最大的不同就是不需要输入类别数k,当然它最大的优势是可以发现任意形状的聚类簇,而不是像K-Means,一般仅仅使用于凸的样本集聚类。同时它在聚类的同时还可以找出异常点,这点和BIRCH算法类似。一般来说,如果数据集是稠密的,并且数据集不是凸的,那么用DBSCAN会比K-Means聚类效果好很多。如果数据集不是稠密的,则不推荐用DBSCAN来聚类。
此外,常用的聚类算法还有EM聚类、谱聚类等,其中PAI-Studio提供了常用的聚类算法组件。
1.4 深度学习
神经网络是深度学习的基础,深度学习就是包含多个隐藏层(hidden layer)的深度神经网络。神经网络的基本组成单元叫做神经元(neuron),感知器(perceptron)是一种早期的神经元结构,在上个世纪五六十年代就被提出来了,如下图示,通过下图可以理解神经元的基本结构和原理。
神经网络是多个神经元连接起来构成,如下图示。
深度神经网络比浅层神经网络有更多结构上的优势,能够进行更多层次的抽象,在NLP、图像、语音等领域都有广泛的应用。深度学习是一个框架,每个领域每个具体场景都可以设计相应的网络结构来解决相应的问题。深度学习的算法也非常多,比如CNN、RNN、LSTM等都属于深度学习比较常用的算法框架。最近几年,深度学习发展迅速,各种学习框架层出不穷,其中有很多比较前沿也比较火爆的算法提出,比如GAN(生成对抗网络)、Bert模型等。
在PAI上想实现深度学习的解决方案,有两种方法,一种是利用PAI-Studio提供的框架Tensorflow和Caffee,在该组件上传入相应的python源码并配置相应输入输出和参数,即可利用阿里云背后支撑的资源进行深度学习的训练,如下图。
另外一种深度学习解决方案是利用PAI-DSW(Data science workshop),该方案是专门为算法开发者提供的云端深度学习开发环境,详情及使用可参考 使用文档 。
pai上的深度学习解决方案
1.5 小结
PAI(Platform of Artificial Intelligence: http://pai.alibaba-inc.com )作为阿里巴巴集团的机器学习算法平台, 可以支持客户结合各自业务场景打造专业、高效的智能解决方案。
2. 实战案例
结合上一节介绍,PAI为机器学习提供了高效的解决方案,其中主要可分为PAI-Studio、PAI-EAS、PAI-DSW三个部分,PAI-Studio提供了可视化的机器学习组件,简单拖拽及配置即可构造机器学习解决方案,生成的算法模型可在PAI-EAS部署,提供在线预测服务。PAI-DSW则为开发者提供了整套的云端深度学习开发环境,算法开发者可以非常方便的在该环境进行开发实战。
接下来让我们通过具体的实战案例,来进一步了解机器学习、PAI、实际案例是如何完美结合的。
2.1 文章一: 商品价格预测
某收藏爱好者,欲购买某知名品牌的积木套装。为了了解现在的市场行情,他收集了关于该品牌积木的生成日期,是否为全新的,积木数量,原始价格等特征和已交易的价格。他想要根据这些数据,来预估现在市场上正在出售的积木价格,才可以选择合适的价格购入,但他发现经凭借经验来预测这些价格,往往不够准确,而且繁琐重复的工作相当耗费精力。
利用PAI进行商品价格预测,文章链接: https://yq.aliyun.com/articles/692330?spm=a2c4e.11155435.0.0.198c3312GZLeWS
2.2 文章二:谁最具魅力
单身王女士经常逛某相亲网站,前前后后浏览了1000个男生,并给他们打标了,不喜欢、一般喜欢、很喜欢三个类别。该相亲网站的工程师,决定开发一个算法推荐模型,给王女士依次推荐很喜欢,一般喜欢的男生。并可以将这个算法模型应用到网站,吸引更多的单身青年注册使用,并可以找到自己喜欢的男/女朋友。
文章链接: https://yq.aliyun.com/articles/692343?spm=a2c4e.11153959.0.0.6fd17158ySDeJO
2.3 文章三:手把手实现商品推荐
在生活中,我们经常给朋友推荐一些自己喜欢的东西,也时常接受别人的推荐。怎么能保证推荐的电影或者美食就是朋友喜欢的呢?一般来说,你们两个人经常对同一个电影或者美食感兴趣,那么你喜欢的东西就很大程度上朋友也会比较感兴趣。在大数据的背景下,算法会帮我寻找兴趣相似的那些人,并关注他们喜欢的东西,以此来给我们推荐可能喜欢的事物。
文章链接: https://yq.aliyun.com/articles/692349?spm=a2c4e.11155435.0.0.9ea93312sjbx5D
2.4 文章四:利用GAN自动生成二次元头像
GAN(生成对抗网络)主要的应用是自动生成一些东西,包括图像和文本等,比如随机给一个向量作为输入,通过GAN的Generator生成一张图片,或者生成一串语句。Conditional GAN的应用更多一些,比如数据集是一段文字和图像的数据对,通过训练,GAN可以通过给定一段文字生成对应的图像。
如何利用GAN自动生成二次元头像,文章链接: https://yq.aliyun.com/articles/692342?spm=a2c4e.11153959.0.0.78c47158aCVib7
3. 常见问题
阿里云机器学习平台: https://help.aliyun.com/product/30347.html?spm=a2c4g.11186623
【待补充】
人人用得起的机器学习平台↓↓↓↓

作者:不等_赵振才
原文链接
本文为云栖社区原创内容,未经允许不得转载。
人工智能
2019-03-22 11:21:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
在3月21日的2019阿里云峰会·北京上,阿里云发布新产品SaaS加速器:人工智能、虚拟现实等技术能力被集成为模块,ISV和开发者只要简单拖拽,就可以快速搭建SaaS应用。
“我想试驾一下,怎么办?”
“我们集成了虚拟试驾的功能,您喜欢什么样的驾驶风格?”
“我喜欢在城市道路驾驶。”
“好的,为您找到一条不拥堵的城市驾驶路段。”
发布现场,阿里云智能产品管理部总经理马劲进行简单演示。通过SaaS加速器仅用五天就开发完成了一款智能购车应用,并具备虚拟试驾等功能。过去,搭建这样一个智能购车应用,可能需要几十人的团队耗费一个月才能完成。
马劲表示,阿里云自己不做SaaS,要让大家来做更好的SaaS;要练好“内功”,更广泛、更深度地“被集成”。
实现SaaS业务规模化的关键在于拥有一个稳定强大的平台提供支撑、出色的前台提高开发定制效率,以及可沉淀和复用的中台能力。
此次阿里云推出的SaaS加速器,涵盖商业中心、能力中心、技术中心三大板块,是阿里巴巴商业、能力和技术的一次合力输出:技术能力在这里沉淀为一个个模块,ISV和开发者只要通过简单的操作,写很少的代码、甚至不写代码,就可以快速搭建一个SaaS应用,实现规模化、快速复制。
同时,借助阿里巴巴的丰富生态,ISV和开发者能够快速完成应用发布,向目标用户提供服务,形成从产品研发到部署交付的完整商业闭环。
作者:云学习小组
原文链接
​本文为云栖社区原创内容,未经允许不得转载。
人工智能
2019-03-21 15:02:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
我们知道,AI 技术将在很长一段时间占据互联网技术时代的风口。但是,有代码的地方就有缺陷,提到技术很难不讲安全,那么AI会不会碰到安全问题呢?
AI安全
试想一下,未来的某个早晨,当你像往常一样打开无人驾驶的汽车车门,报出目的地,然后坐在后座上舒舒服服地浏览推送给你的各种新闻,汽车突然失控,在本该停止的红灯前飞驰而过撞向了正在过马路的行人,那将是怎样一场灾难。
人工智能技术给生活带来便利的同时,其自身的安全问题(AI安全)也不容忽视,AI安全问题可以归纳为内外2方面原因: 自身缺陷导致的模型出错:例如,模型结构本身存在缺陷、或者训练数据和真实场景数据之间的偏差,都可能导致模型预测错误。 外部攻击导致的模型风险:例如,来自外部的对抗样本攻击可诱使算法识别出现误判漏判,输出错误结果。
本文,我们会针对第2点的对抗样本技术结合其在阿里巴巴安全领域中的实际应用给大家做展开介绍。
对抗样本技术
对抗样本由 ChristianSzegedy[1]等人提出,他们发现通过深度神经网络训练得到的模型,在输入与输出之间的映射往往不是线性的。这样就存在一个问题: 在输入数据中通过故意添加肉眼不易察觉的细微扰动,可以生成对抗样本,导致AI模型以高置信度给出一个错误的输出。如下图所示:
目前的对抗样本根据是否需要指定攻击的类目可以分为无目标攻击(non-targeted attack)和目标攻击(targeted attack)。前者不指定具体类目,只要让AI识别错误即可。后者不仅需要使AI识别错误,还需要使AI识别到指定的类别。
生成对抗样本,最直接的方法是在给定扰动量的范围内修改样本,使得修改后的样本在AI模型上的损失函数最大化(非定向攻击)或最小化(定向攻击),这样就可以把生成对抗样本的问题归纳为空间搜索的优化问题。基于不同的优化算法,学术界提出了很多对抗样本生成算法,有兴趣的朋友可以自行检索,此处不具体展开。
对抗样本应用场景
对抗样本技术提出后引发了学术界和工业界对于深度学习模型在安全方面的广泛关注,成为目前深度学习领域最火热的研究课题之一,新的对抗攻击方法不断涌现,应用场景从图像分类扩展到目标检测等。
阿里安全一直以来致力于用技术解决社会问题。为了保障整个生态圈中7亿多消费者和千万商家的信息安全,AI技术很早就被应用到了阿里安全体系建设中。安全领域一个重要的特点就是存在很强的对抗性,日常防控中,黑灰产会尝试使用各种对抗样本攻击我们部署的AI防控大坝。对此,一方面,阿里安全图灵实验室的算法专家们提出了若干种提升模型安全性能的方法,强化自身堡垒;另一方面,算法专家们也会以战养战,开展针对对抗样本的攻防研究,利用对抗技术去防御攻击者的模型。下面我们结合实际业务,介绍两种对抗样本的应用场景:
1.人脸识别
人脸识别技术已经在生活的各个场景普遍应用,手机解锁要靠脸、移动支付要靠脸,机场安检要靠脸……一脸走天下的时代逐渐到来。
然而,Bose 和 Aarabi[2]发现通过在原始图像中加入人眼不可区分的微量干扰对人脸识别算法进行攻击后,能够使人脸无法被检测算法定位到。如下图所示,左列为原始图像,检测算法可以准确定位,右列为对抗样本,已经成功绕开了人脸检测算法,而在我们肉眼看来两幅图画基本没有差别。
更进一步,采用对抗样本攻击人脸识别系统,还可以使算法把人脸识别成指定的错误类别[3]。下图第一列为目标类别,第2和第4列为原始样本,对其加入干扰生成的对抗样本在第3和第5列,它们均被算法错误识别为第一列目标类别。
2.对抗验证码
如同网络通信的基础安全设施——防火墙,互联网业务安全也有其基础安全设施——图片验证码和短信验证码。互联网业务广泛使用图形验证码用于区分人类和机器的操作行为,使用短信验证码过滤黑灰产批量账号及提供二次校验功能。现在随着深度学习的门槛越来越低,黑灰产会利用深度学习技术构建模型自动识别验证码,突破算法模型设置的人机识别防线。下图的文本验证码基本都可以被AI模型轻松识别。
针对文本验证码面临的挑战,阿里安全图灵实验室的算法专家们将原始验证码替换成增加扰动后的对抗验证码。为了增加对抗验证码的识别难度,又不影响正常用户的体验,算法专家们又在图像区域和生成方式上进行了组合扩展,最终生成的对抗样验证码有效抵御了黑灰产的批量破解,成为阿里业务安全的一道铜墙铁壁。采用该组合扩展生成的对抗验证码如下图所示:
针对点击式的图文验证与行为辅助验证码,阿里安全图灵实验室的算法专家们首先在验证码中结合了NLP的问答技术,再将全部问答转换成图片,最后利用对抗技术生成对抗问答图片。使用商业的OCR引擎进行对此类对抗问答图片样本进行识别测试,和原始样本的识别率相比,对抗样本的识别率大幅降低,且并没有对用户的体验带来很大的影响,由此可见AI结合安全能为业务带来巨大的价值。
原文链接
人工智能
2019-03-12 12:19:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
0. 前言
Data Lake Analytics 是Serverless化的云上交互式查询分析服务。用户可以使用标准的SQL语句,对存储在OSS、TableStore上的数据无需移动,直接进行查询分析。
目前该产品已经正式登陆阿里云,欢迎大家申请试用,体验更便捷的数据分析服务。
请参考 https://help.aliyun.com/document_detail/70386.html 进行产品开通服务申请。
在上一篇教程中,我们介绍了 如何分析CSV格式的TPC-H数据集 。除了纯文本文件(例如,CSV,TSV等),用户存储在OSS上的其他格式的数据文件,也可以使用Data Lake Analytics进行查询分析,包括ORC, PARQUET, JSON, RCFILE, AVRO甚至ESRI规范的地理JSON数据,还可以用正则表达式匹配的文件等。
本文详细介绍如何根据存储在OSS上的文件格式使用Data Lake Analytics (下文简称 DLA)进行分析。DLA内置了各种处理文件数据的SerDe(Serialize/Deserilize的简称,目的是用于序列化和反序列化)实现,用户无需自己编写程序,基本上能选用DLA中的一款或多款SerDe来匹配您OSS上的数据文件格式。如果还不能满足您特殊文件格式的处理需求,请联系我们,尽快为您实现。
1. 存储格式与SerDe
用户可以依据存储在OSS上的数据文件进行建表,通过STORED AS 指定数据文件的格式。
例如, CREATE EXTERNAL TABLE nation ( N_NATIONKEY INT, N_NAME STRING, N_REGIONKEY INT, N_COMMENT STRING ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '|' STORED AS TEXTFILE LOCATION 'oss://test-bucket-julian-1/tpch_100m/nation';
建表成功后可以使用SHOW CREATE TABLE语句查看原始建表语句。 mysql> show create table nation; +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Result | +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | CREATE EXTERNAL TABLE `nation`( `n_nationkey` int, `n_name` string, `n_regionkey` int, `n_comment` string) ROW FORMAT DELIMITED FIELDS TERMINATED BY '|' STORED AS `TEXTFILE` LOCATION 'oss://test-bucket-julian-1/tpch_100m/nation'| +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (1.81 sec)
下表中列出了目前DLA已经支持的文件格式,当针对下列格式的文件建表时,可以直接使用STORED AS,DLA会选择合适的SERDE/INPUTFORMAT/OUTPUTFORMAT。

存储格式描述 STORED AS TEXTFILE数据文件的存储格式为纯文本文件。默认的文件类型。
文件中的每一行对应表中的一条记录。STORED AS ORC数据文件的存储格式为ORC。STORED AS PARQUET数据文件的存储格式为PARQUET。STORED AS RCFILE数据文件的存储格式为RCFILE。STORED AS AVRO数据文件的存储格式为AVRO。STORED AS JSON数据文件的存储格式为JSON (Esri ArcGIS的地理JSON数据文件 除外 )。
在指定了STORED AS 的同时,还可以根据具体文件的特点,指定SerDe (用于解析数据文件并映射到DLA表),特殊的列分隔符等。
后面的部分会做进一步的讲解。
2. 示例
2.1 CSV文件
CSV文件,本质上还是纯文本文件,可以使用STORED AS TEXTFILE。
列与列之间以逗号分隔,可以通过ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' 表示。
普通CSV文件
例如,数据文件oss://bucket-for-testing/oss/text/cities/city.csv的内容为 Beijing,China,010 ShangHai,China,021 Tianjin,China,022
建表语句可以为 CREATE EXTERNAL TABLE city ( city STRING, country STRING, code INT ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' STORED AS TEXTFILE LOCATION 'oss://bucket-for-testing/oss/text/cities';
使用OpenCSVSerde__处理引号__引用的字段
OpenCSVSerde在使用时需要注意以下几点: 用户可以为行的字段指定字段分隔符、字段内容引用符号和转义字符,例如:WITH SERDEPROPERTIES ("separatorChar" = ",", "quoteChar" = "`", "escapeChar" = "\" ); 不支持字段内嵌入的行分割符; 所有字段定义STRING类型; 其他数据类型的处理,可以在SQL中使用函数进行转换。
例如, CREATE EXTERNAL TABLE test_csv_opencsvserde ( id STRING, name STRING, location STRING, create_date STRING, create_timestamp STRING, longitude STRING, latitude STRING ) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde' with serdeproperties( 'separatorChar'=',', 'quoteChar'='"', 'escapeChar'='\\' ) STORED AS TEXTFILE LOCATION 'oss://test-bucket-julian-1/test_csv_serde_1';
自定义分隔符
需要自定义列分隔符(FIELDS TERMINATED BY),转义字符(ESCAPED BY),行结束符(LINES TERMINATED BY)。
需要在建表语句中指定 ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' ESCAPED BY '\\' LINES TERMINATED BY '\n'
忽略CSV文件中的HEADER
在csv文件中,有时会带有HEADER信息,需要在数据读取时忽略掉这些内容。这时需要在建表语句中定义skip.header.line.count。
例如,数据文件oss://my-bucket/datasets/tpch/nation_csv/nation_header.tbl的内容如下: N_NATIONKEY|N_NAME|N_REGIONKEY|N_COMMENT 0|ALGERIA|0| haggle. carefully final deposits detect slyly agai| 1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon| 2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special | 3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold| 4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d| 5|ETHIOPIA|0|ven packages wake quickly. regu|
相应的建表语句为: CREATE EXTERNAL TABLE nation_header ( N_NATIONKEY INT, N_NAME STRING, N_REGIONKEY INT, N_COMMENT STRING ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '|' STORED AS TEXTFILE LOCATION 'oss://my-bucket/datasets/tpch/nation_csv/nation_header.tbl' TBLPROPERTIES ("skip.header.line.count"="1");
skip.header.line.count的取值x和数据文件的实际行数n有如下关系: 当x<=0时,DLA在读取文件时,不会过滤掉任何信息,即全部读取; 当0 当x>=n时,DLA在读取文件时,会过滤掉所有的文件内容。
2.2 TSV文件
与CSV文件类似,TSV格式的文件也是纯文本文件,列与列之间的分隔符为Tab。
例如,数据文件oss://bucket-for-testing/oss/text/cities/city.tsv的内容为 Beijing China 010 ShangHai China 021 Tianjin China 022
建表语句可以为 CREATE EXTERNAL TABLE city ( city STRING, country STRING, code INT ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' STORED AS TEXTFILE LOCATION 'oss://bucket-for-testing/oss/text/cities';
2.3 多字符数据字段分割符文件
假设您的数据字段的分隔符包含多个字符,可采用如下示例建表语句,其中每行的数据字段分割符为“||”,可以替换为您具体的分割符字符串。 ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.MultiDelimitSerDe' with serdeproperties( "field.delim"="||" )
示例: CREATE EXTERNAL TABLE test_csv_multidelimit ( id STRING, name STRING, location STRING, create_date STRING, create_timestamp STRING, longitude STRING, latitude STRING ) ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.MultiDelimitSerDe' with serdeproperties( "field.delim"="||" ) STORED AS TEXTFILE LOCATION 'oss://bucket-for-testing/oss/text/cities/';
2.4 JSON文件
DLA可以处理的JSON文件通常以纯文本的格式存储,数据文件的编码方式需要是UTF-8。
在JSON文件中,每行必须是一个完整的JSON对象。
例如,下面的文件格式是不被接受的 {"id": 123, "name": "jack", "c3": "2001-02-03 12:34:56"} {"id": 456, "name": "rose", "c3": "1906-04-18 05:12:00"} {"id": 789, "name": "tom", "c3": "2001-02-03 12:34:56"} {"id": 234, "name": "alice", "c3": "1906-04-18 05:12:00"}
需要改写成: {"id": 123, "name": "jack", "c3": "2001-02-03 12:34:56"} {"id": 456, "name": "rose", "c3": "1906-04-18 05:12:00"} {"id": 789, "name": "tom", "c3": "2001-02-03 12:34:56"} {"id": 234, "name": "alice", "c3": "1906-04-18 05:12:00"}
不含嵌套的JSON数据
建表语句可以写 CREATE EXTERNAL TABLE t1 (id int, name string, c3 timestamp) STORED AS JSON LOCATION 'oss://path/to/t1/directory';
含有嵌套的JSON文件
使用struct和array结构定义嵌套的JSON数据。
例如,用户原始数据(注意:无论是否嵌套,一条完整的JSON数据都只能放在一行上,才能被Data Lake Analytics处理): { "DocId": "Alibaba", "User_1": { "Id": 1234, "Username": "bob1234", "Name": "Bob", "ShippingAddress": { "Address1": "969 Wenyi West St.", "Address2": null, "City": "Hangzhou", "Province": "Zhejiang" }, "Orders": [{ "ItemId": 6789, "OrderDate": "11/11/2017" }, { "ItemId": 4352, "OrderDate": "12/12/2017" } ] } }
使用在线JSON格式化工具格式化后,数据内容如下: { "DocId": "Alibaba", "User_1": { "Id": 1234, "Username": "bob1234", "Name": "Bob", "ShippingAddress": { "Address1": "969 Wenyi West St.", "Address2": null, "City": "Hangzhou", "Province": "Zhejiang" }, "Orders": [ { "ItemId": 6789, "OrderDate": "11/11/2017" }, { "ItemId": 4352, "OrderDate": "12/12/2017" } ] } }
则建表语句可以写成如下(注意:LOCATION中指定的路径必须是JSON数据文件所在的目录,该目录下的所有JSON文件都能被识别为该表的数据): CREATE EXTERNAL TABLE json_table_1 ( docid string, user_1 struct< id:INT, username:string, name:string, shippingaddress:struct< address1:string, address2:string, city:string, province:string >, orders:array< struct< itemid:INT, orderdate:string > > > ) STORED AS JSON LOCATION 'oss://xxx/test/json/hcatalog_serde/table_1/';
对该表进行查询: select * from json_table_1; +---------+----------------------------------------------------------------------------------------------------------------+ | docid | user_1 | +---------+----------------------------------------------------------------------------------------------------------------+ | Alibaba | [1234, bob1234, Bob, [969 Wenyi West St., null, Hangzhou, Zhejiang], [[6789, 11/11/2017], [4352, 12/12/2017]]] | +---------+----------------------------------------------------------------------------------------------------------------+
对于struct定义的嵌套结构,可以通过“.”进行层次对象引用,对于array定义的数组结构,可以通过“[数组下标]”(注意:数组下标从1开始)进行对象引用。 select DocId, User_1.Id, User_1.ShippingAddress.Address1, User_1.Orders[1].ItemId from json_table_1 where User_1.Username = 'bob1234' and User_1.Orders[2].OrderDate = '12/12/2017'; +---------+------+--------------------+-------+ | DocId | id | address1 | _col3 | +---------+------+--------------------+-------+ | Alibaba | 1234 | 969 Wenyi West St. | 6789 | +---------+------+--------------------+-------+
使用JSON函数处理数据
例如,把“value_string”的嵌套JSON值作为字符串存储: {"data_key":"com.taobao.vipserver.domains.meta.biz.alibaba.com","ts":1524550275112,"value_string":"{\"appName\":\"\",\"apps\":[],\"checksum\":\"50fa0540b430904ee78dff07c7350e1c\",\"clusterMap\":{\"DEFAULT\":{\"defCkport\":80,\"defIPPort\":80,\"healthCheckTask\":null,\"healthChecker\":{\"checkCode\":200,\"curlHost\":\"\",\"curlPath\":\"/status.taobao\",\"type\":\"HTTP\"},\"name\":\"DEFAULT\",\"nodegroup\":\"\",\"sitegroup\":\"\",\"submask\":\"0.0.0.0/0\",\"syncConfig\":{\"appName\":\"trade-ma\",\"nodegroup\":\"tradema\",\"pubLevel\":\"publish\",\"role\":\"\",\"site\":\"\"},\"useIPPort4Check\":true}},\"disabledSites\":[],\"enableArmoryUnit\":false,\"enableClientBeat\":false,\"enableHealthCheck\":true,\"enabled\":true,\"envAndSites\":\"\",\"invalidThreshold\":0.6,\"ipDeleteTimeout\":1800000,\"lastModifiedMillis\":1524550275107,\"localSiteCall\":true,\"localSiteThreshold\":0.8,\"name\":\"biz.alibaba.com\",\"nodegroup\":\"\",\"owners\":[\"junlan.zx\",\"张三\",\"李四\",\"cui.yuanc\"],\"protectThreshold\":0,\"requireSameEnv\":false,\"resetWeight\":false,\"symmetricCallType\":null,\"symmetricType\":\"warehouse\",\"tagName\":\"ipGroup\",\"tenantId\":\"\",\"tenants\":[],\"token\":\"1cf0ec0c771321bb4177182757a67fb0\",\"useSpecifiedURL\":false}"}
使用在线JSON格式化工具格式化后,数据内容如下: { "data_key": "com.taobao.vipserver.domains.meta.biz.alibaba.com", "ts": 1524550275112, "value_string": "{\"appName\":\"\",\"apps\":[],\"checksum\":\"50fa0540b430904ee78dff07c7350e1c\",\"clusterMap\":{\"DEFAULT\":{\"defCkport\":80,\"defIPPort\":80,\"healthCheckTask\":null,\"healthChecker\":{\"checkCode\":200,\"curlHost\":\"\",\"curlPath\":\"/status.taobao\",\"type\":\"HTTP\"},\"name\":\"DEFAULT\",\"nodegroup\":\"\",\"sitegroup\":\"\",\"submask\":\"0.0.0.0/0\",\"syncConfig\":{\"appName\":\"trade-ma\",\"nodegroup\":\"tradema\",\"pubLevel\":\"publish\",\"role\":\"\",\"site\":\"\"},\"useIPPort4Check\":true}},\"disabledSites\":[],\"enableArmoryUnit\":false,\"enableClientBeat\":false,\"enableHealthCheck\":true,\"enabled\":true,\"envAndSites\":\"\",\"invalidThreshold\":0.6,\"ipDeleteTimeout\":1800000,\"lastModifiedMillis\":1524550275107,\"localSiteCall\":true,\"localSiteThreshold\":0.8,\"name\":\"biz.alibaba.com\",\"nodegroup\":\"\",\"owners\":[\"junlan.zx\",\"张三\",\"李四\",\"cui.yuanc\"],\"protectThreshold\":0,\"requireSameEnv\":false,\"resetWeight\":false,\"symmetricCallType\":null,\"symmetricType\":\"warehouse\",\"tagName\":\"ipGroup\",\"tenantId\":\"\",\"tenants\":[],\"token\":\"1cf0ec0c771321bb4177182757a67fb0\",\"useSpecifiedURL\":false}" }
建表语句为 CREATE external TABLE json_table_2 ( data_key string, ts bigint, value_string string ) STORED AS JSON LOCATION 'oss://xxx/test/json/hcatalog_serde/table_2/';
表建好后,可进行查询: select * from json_table_2; +---------------------------------------------------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | data_key | ts | value_string | +---------------------------------------------------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | com.taobao.vipserver.domains.meta.biz.alibaba.com | 1524550275112 | {"appName":"","apps":[],"checksum":"50fa0540b430904ee78dff07c7350e1c","clusterMap":{"DEFAULT":{"defCkport":80,"defIPPort":80,"healthCheckTask":null,"healthChecker":{"checkCode":200,"curlHost":"","curlPath":"/status.taobao","type":"HTTP"},"name":"DEFAULT","nodegroup":"","sitegroup":"","submask":"0.0.0.0/0","syncConfig":{"appName":"trade-ma","nodegroup":"tradema","pubLevel":"publish","role":"","site":""},"useIPPort4Check":true}},"disabledSites":[],"enableArmoryUnit":false,"enableClientBeat":false,"enableHealthCheck":true,"enabled":true,"envAndSites":"","invalidThreshold":0.6,"ipDeleteTimeout":1800000,"lastModifiedMillis":1524550275107,"localSiteCall":true,"localSiteThreshold":0.8,"name":"biz.alibaba.com","nodegroup":"","owners":["junlan.zx","张三","李四","cui.yuanc"],"protectThreshold":0,"requireSameEnv":false,"resetWeight":false,"symmetricCallType":null,"symmetricType":"warehouse","tagName":"ipGroup","tenantId":"","tenants":[],"token":"1cf0ec0c771321bb4177182757a67fb0","useSpecifiedURL":false} | +---------------------------------------------------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
下面SQL示例json_parse,json_extract_scalar,json_extract等常用JSON函数的使用方式: mysql> select json_extract_scalar(json_parse(value), '$.owners[1]') from json_table_2; +--------+ | _col0 | +--------+ | 张三 | +--------+ mysql> select json_extract_scalar(json_obj.json_col, '$.DEFAULT.submask') from ( select json_extract(json_parse(value), '$.clusterMap') as json_col from json_table_2 ) json_obj where json_extract_scalar(json_obj.json_col, '$.DEFAULT.healthChecker.curlPath') = '/status.taobao'; +-----------+ | _col0 | +-----------+ | 0.0.0.0/0 | +-----------+ mysql> with json_obj as (select json_extract(json_parse(value), '$.clusterMap') as json_col from json_table_2) select json_extract_scalar(json_obj.json_col, '$.DEFAULT.submask') from json_obj where json_extract_scalar(json_obj.json_col, '$.DEFAULT.healthChecker.curlPath') = '/status.taobao'; +-----------+ | _col0 | +-----------+ | 0.0.0.0/0 | +-----------+
2.5 ORC文件
Optimized Row Columnar(ORC)是Apache开源项目Hive支持的一种优化的列存储文件格式。与CSV文件相比,不仅可以节省存储空间,还可以得到更好的查询性能。
对于ORC文件,只需要在建表时指定 STORED AS ORC。
例如, CREATE EXTERNAL TABLE orders_orc_date ( O_ORDERKEY INT, O_CUSTKEY INT, O_ORDERSTATUS STRING, O_TOTALPRICE DOUBLE, O_ORDERDATE DATE, O_ORDERPRIORITY STRING, O_CLERK STRING, O_SHIPPRIORITY INT, O_COMMENT STRING ) STORED AS ORC LOCATION 'oss://bucket-for-testing/datasets/tpch/1x/orc_date/orders_orc';
2.6 PARQUET文件
Parquet是Apache开源项目Hadoop支持的一种列存储的文件格式。
使用DLA建表时,需要指定STORED AS PARQUET即可。
例如, CREATE EXTERNAL TABLE orders_parquet_date ( O_ORDERKEY INT, O_CUSTKEY INT, O_ORDERSTATUS STRING, O_TOTALPRICE DOUBLE, O_ORDERDATE DATE, O_ORDERPRIORITY STRING, O_CLERK STRING, O_SHIPPRIORITY INT, O_COMMENT STRING ) STORED AS PARQUET LOCATION 'oss://bucket-for-testing/datasets/tpch/1x/parquet_date/orders_parquet';
2.7 RCFILE文件
Record Columnar File (RCFile), 列存储文件,可以有效地将关系型表结构存储在分布式系统中,并且可以被高效地读取和处理。
DLA在建表时,需要指定STORED AS RCFILE。
例如, CREATE EXTERNAL TABLE lineitem_rcfile_date ( L_ORDERKEY INT, L_PARTKEY INT, L_SUPPKEY INT, L_LINENUMBER INT, L_QUANTITY DOUBLE, L_EXTENDEDPRICE DOUBLE, L_DISCOUNT DOUBLE, L_TAX DOUBLE, L_RETURNFLAG STRING, L_LINESTATUS STRING, L_SHIPDATE DATE, L_COMMITDATE DATE, L_RECEIPTDATE DATE, L_SHIPINSTRUCT STRING, L_SHIPMODE STRING, L_COMMENT STRING ) STORED AS RCFILE LOCATION 'oss://bucke-for-testing/datasets/tpch/1x/rcfile_date/lineitem_rcfile'
2.8 AVRO文件
DLA针对AVRO文件建表时,需要指定STORED AS AVRO,并且定义的字段需要符合AVRO文件的schema。
如果不确定可以通过使用Avro提供的工具,获得schema,并根据schema建表。
在 Apache Avro官网 下载avro-tools-.jar到本地,执行下面的命令获得Avro文件的schema: java -jar avro-tools-1.8.2.jar getschema /path/to/your/doctors.avro { "type" : "record", "name" : "doctors", "namespace" : "testing.hive.avro.serde", "fields" : [ { "name" : "number", "type" : "int", "doc" : "Order of playing the role" }, { "name" : "first_name", "type" : "string", "doc" : "first name of actor playing role" }, { "name" : "last_name", "type" : "string", "doc" : "last name of actor playing role" } ] }
建表语句如下,其中fields中的name对应表中的列名,type需要参考本文档中的表格转成DLA支持的类型 CREATE EXTERNAL TABLE doctors( number int, first_name string, last_name string) STORED AS AVRO LOCATION 'oss://mybucket-for-testing/directory/to/doctors';
大多数情况下,Avro的类型可以直接转换成DLA中对应的类型。如果该类型在DLA不支持,则会转换成接近的类型。具体请参照下表:
Avro类型对应DLA类型 nullvoidbooleanbooleanintintlongbigintfloatfloatdoubledoublebytesbinarystringstringrecordstructmapmaplistarrayunionunionenumstringfixedbinary
2.9 可以用正则表达式匹配的文件
通常此类型的文件是以纯文本格式存储在OSS上的,每一行代表表中的一条记录,并且每行可以用正则表达式匹配。
例如,Apache WebServer日志文件就是这种类型的文件。
某日志文件的内容为: 127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 127.0.0.1 - - [26/May/2009:00:00:00 +0000] "GET /someurl/?track=Blabla(Main) HTTP/1.1" 200 5864 - "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/1.0.154.65 Safari/525.19"
每行文件可以用下面的正则表达式表示,列之间使用空格分隔: ([^ ]*) ([^ ]*) ([^ ]*) (-|\\[[^\\]]*\\]) ([^ \"]*|\"[^\"]*\") (-|[0-9]*) (-|[0-9]*)(?: ([^ \"]*|\"[^\"]*\") ([^ \"]*|\"[^\"]*\"))?
针对上面的文件格式,建表语句可以表示为: CREATE EXTERNAL TABLE serde_regex( host STRING, identity STRING, userName STRING, time STRING, request STRING, status STRING, size INT, referer STRING, agent STRING) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe' WITH SERDEPROPERTIES ( "input.regex" = "([^ ]*) ([^ ]*) ([^ ]*) (-|\\[[^\\]]*\\]) ([^ \"]*|\"[^\"]*\") (-|[0-9]*) (-|[0-9]*)(?: ([^ \"]*|\"[^\"]*\") ([^ \"]*|\"[^\"]*\"))?" ) STORED AS TEXTFILE LOCATION 'oss://bucket-for-testing/datasets/serde/regex';
查询结果 mysql> select * from serde_regex; +-----------+----------+-------+------------------------------+---------------------------------------------+--------+------+---------+--------------------------------------------------------------------------------------------------------------------------+ | host | identity | userName | time | request | status | size | referer | agent | +-----------+----------+-------+------------------------------+---------------------------------------------+--------+------+---------+--------------------------------------------------------------------------------------------------------------------------+ | 127.0.0.1 | - | frank | [10/Oct/2000:13:55:36 -0700] | "GET /apache_pb.gif HTTP/1.0" | 200 | 2326 | NULL | NULL | | 127.0.0.1 | - | - | [26/May/2009:00:00:00 +0000] | "GET /someurl/?track=Blabla(Main) HTTP/1.1" | 200 | 5864 | - | "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/1.0.154.65 Safari/525.19" | +-----------+----------+-------+------------------------------+---------------------------------------------+--------+------+---------+--------------------------------------------------------------------------------------------------------------------------+
2.10 Esri ArcGIS的地理JSON数据文件
DLA支持Esri ArcGIS的地理JSON数据文件的SerDe处理,关于这种地理JSON数据格式说明,可以参考: https://github.com/Esri/spatial-framework-for-hadoop/wiki/JSON-Formats
示例: CREATE EXTERNAL TABLE IF NOT EXISTS california_counties ( Name string, BoundaryShape binary ) ROW FORMAT SERDE 'com.esri.hadoop.hive.serde.JsonSerde' STORED AS INPUTFORMAT 'com.esri.json.hadoop.EnclosedJsonInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' LOCATION 'oss://test_bucket/datasets/geospatial/california-counties/'
3. 总结
通过以上例子可以看出,DLA可以支持大部分开源存储格式的文件。对于同一份数据,使用不同的存储格式,在OSS中存储文件的大小,DLA的查询分析速度上会有较大的差别。推荐使用ORC格式进行文件的存储和查询。
为了获得更快的查询速度,DLA还在不断的优化中,后续也会支持更多的数据源,为用户带来更好的大数据分析体验。
#阿里云开年Hi购季#幸运抽好礼!
点此抽奖: 【阿里云】开年Hi购季,幸运抽好礼

原文链接
本文为云栖社区原创内容,未经允许不得转载。
人工智能
2019-02-28 17:10:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
自 Spring Cloud 官方宣布 Spring Cloud Netflix 进入维护状态后,我们开始制作 《Spring Cloud Alibaba迁移指南》 系列文章,向开发者提供更多的技术选型方案,并降低迁移过程中的技术难度。
第一篇,我们对Hystrix、Resilience4j 和 Sentinel 三个开源项目进行对比,并探讨如何使用一行代码这种极简的方式,将Hystrix迁移到Sentinel。
Hystrix 自从前段时间 宣布停止维护 之后,社区推荐了 resilience4j 。这 3 款产品各有优劣势,具体的功能差异参考下表(该表来源 Sentinel Wiki ):
SentinelHystrixresilience4j隔离策略信号量隔离(并发线程数限流)线程池隔离/信号量隔离信号量隔离熔断降级策略基于响应时间、异常比率、异常数基于异常比率基于异常比率、响应时间实时统计实现滑动窗口(LeapArray)滑动窗口(基于 RxJava)Ring Bit Buffer动态规则配置支持多种数据源支持多种数据源有限支持扩展性多个扩展点插件的形式接口的形式基于注解的支持支持支持支持限流基于 QPS,支持基于调用关系的限流有限的支持Rate Limiter流量整形支持预热模式、匀速器模式、预热排队模式不支持简单的 Rate Limiter 模式系统自适应保护支持不支持不支持控制台提供开箱即用的控制台,可配置规则、查看秒级监控、机器发现等简单的监控查看不提供控制台,可对接其它监控系统
目前 Sentinel 在 Spring Cloud Alibaba 项目 中已经适配了 Spring Cloud 体系,可以用来完全替代 Hystrix 的功能了。
Spring Cloud Alibaba Sentinel 功能介绍
Spring Cloud Alibaba Sentinel 主要是为了整合 Sentinel 和 Spring Boot/Cloud 技术栈。目前完成了如下功能: 自动适配 Servlet 容器。只需要配置 url-pattern(默认拦截所有请求),即可对拦截的这些 url 进行限流降级操作 整合了 RestTemplate,使用 RestTemplate 进行操作的时候会被限流降级 整合了 Feign,兼容了原先的 Hystrix 支持 Feign 的编程模型 数据源可配置化,只需在配置文件中配置数据源信息,即可动态加载规则 Endpoint 暴露各种元数据,比如配置信息,规则数据 HealthIndicator 检查 Sentinel 健康状态 (整合中) 支持 Spring Cloud Gateway 和 Zuul (整合中)
Spring Cloud Alibaba Sentinel 代替 Hystrix
想要使用 Spring Cloud Alibaba Sentinel,需要加上依赖信息: org.springframework.cloud spring-cloud-alibaba-sentinel 0.2.1.RELEASE
0代码修改兼容 Feign
加上 Feign 的依赖: org.springframework.cloud spring-cloud-starter-openfeign ${latest.version}
把 hystrix 的配置改成 sentinel 的即可使用 Sentinel 的限流降级功能: # feign.hystrix.enabled: true feign.sentinel.enabled: true @FeignClient(name = "service-provider") public interface EchoService { @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET) String echo(@PathVariable("str") String str); @RequestMapping(value = "/echo/save", method = RequestMethod.POST) String save(Foo foo); }
对于这个 EchoService ,echo 方法对应的资源名是 GET:http://service-provider/echo/{str} , save 方法对应的资源名是 POST:http://service-provider/echo/save 。
只需配置这些规则,限流降级操作即可立即生效。
一行代码支持 RestTemplate
Sentinel 还跟 Spring 生态的 RestTemplate 做了整合,可以对 RestTemplate 请求过程进行限流和降级操作,只需要在构造 RestTemplate 的时候加上 @SentinelRestTemplate 注解即可: @Bean @SentinelRestTemplate public RestTemplate restTemplate() { return new RestTemplate(); }
@SentinelRestTemplate 注解还暴露出了对应的属性可进行限流降级后的自定义错误,默认的行为是返回 "RestTemplate request block by sentinel" 信息。

#阿里云开年Hi购季#幸运抽好礼!
点此抽奖: 【阿里云】开年Hi购季,幸运抽好礼

原文链接
本文为云栖社区原创内容,未经允许不得转载。
人工智能
2019-02-27 16:04:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
语料库
本文语料库特指文本分类语料库,对应IDataSet接口。而文本分类语料库包含两个概念:文档和类目。一个文档只属于一个类目,一个类目可能含有多个文档。比如搜狗文本分类语料库迷你版.zip,下载前请先阅读搜狗实验室数据使用许可协议。
用 Map描述
这种关系可以用Java的Map来描述,其key代表类目,value代表该类目下的所有文档。用户可以利用自己的文本读取模块构造一个Map形式的中间语料库,然后利用IDataSet#add(java.util.Map)接口将其加入到训练语料库中。
用文件夹描述

这种树形结构也很适合用文件夹描述,即:

/**
* 加载数据集
*
* @param folderPath 分类语料的根目录.目录必须满足如下结构:

* 根目录

* ├── 分类A

* │ └── 1.txt

* │ └── 2.txt

* │ └── 3.txt

* ├── 分类B

* │ └── 1.txt

* │ └── ...

* └── ...

* 文件不一定需要用数字命名,也不需要以txt作为后缀名,但一定需要是文本文件.
* @param charsetName 文件编码
* @return
* @throws IllegalArgumentException
* @throws IOException
*/
IDataSet load(String folderPath, String charsetName) throws IllegalArgumentException, IOException;
例如:

每个分类里面都是一些文本文档。任何满足此格式的语料库都可以直接加载。

数据集实现
考虑到大规模训练的时候,文本数量达到千万级,无法全部加载到内存中,所以本系统实现了基于文件系统的FileDataSet。同时,在服务器资源许可的情况下,可以使用基于内存的MemoryDataSet,提高加载速度。两者的继承关系如下:

训练
训练指的是,利用给定训练集寻找一个能描述这种语言现象的模型的过程。开发者只需调用train接口即可,但在实现中,有许多细节。

分词
目前,本系统中的分词器接口一共有两种实现:
但文本分类是否一定需要分词?答案是否定的。 ​ 我们可以顺序选取文中相邻的两个字,作为一个“词”(术语叫bigram)。这两个字在数量很多的时候可以反映文章的主题(参考清华大学2016年的一篇论文《Zhipeng Guo, Yu Zhao, Yabin Zheng, Xiance Si, Zhiyuan Liu, Maosong Sun. THUCTC: An Efficient Chinese Text Classifier. 2016》)。这在代码中对应BigramTokenizer. ​ 当然,也可以采用传统的分词器,如HanLPTokenizer。 ​ 另外,用户也可以通过实现ITokenizer来实现自己的分词器,并通过IDataSet#setTokenizer来使其生效。

特征提取
特征提取指的是从所有词中,选取最有助于分类决策的词语。理想状态下所有词语都有助于分类决策,但现实情况是,如果将所有词语都纳入计算,则训练速度将非常慢,内存开销非常大且最终模型的体积非常大。

本系统采取的是卡方检测,通过卡方检测去掉卡方值低于一个阈值的特征,并且限定最终特征数不超过100万。

调参

对于贝叶斯模型,没有超参数需要调节。

训练

本系统实现的训练算法是朴素贝叶斯法,无需用户关心内部细节。另有一个子项目实现了支持向量机文本分类器,可供参考。由于依赖了第三方库,所以没有集成在本项目中。相关性能指标如下表所示:

模型

训练之后,我们就得到了一个模型,可以通过IClassifier#getModel获取到模型的引用。该接口返回一个AbstractModel对象,该对象实现了Serializable接口,可以序列化到任何地方以供部署。 ​ 反序列化后的模型可以通过如下方式加载并构造分类器: ​

NaiveBayesModel model = (NaiveBayesModel) IOUtil.readObjectFrom(MODEL_PATH);
NaiveBayesClassifier naiveBayesClassifier = new NaiveBayesClassifier(model);
分类

通过加载模型,我们可以得到一个分类器,利用该分类器,我们就可以进行文本分类了。

IClassifier classifier = new NaiveBayesClassifier(model);
目前分类器接口中与文本分类有关的接口有如下三种: ​

/**
* 预测分类
*
* @param text 文本
* @return 所有分类对应的分值(或概率, 需要enableProbability)
* @throws IllegalArgumentException 参数错误
* @throws IllegalStateException 未训练模型
*/
Map predict(String text) throws IllegalArgumentException, IllegalStateException;

/**
* 预测分类
* @param document
* @return
*/
Map predict(Document document) throws IllegalArgumentException, IllegalStateException;

/**
* 预测分类
* @param document
* @return
* @throws IllegalArgumentException
* @throws IllegalStateException
*/
double[] categorize(Document document) throws IllegalArgumentException, IllegalStateException;

/**
* 预测最可能的分类
* @param document
* @return
* @throws IllegalArgumentException
* @throws IllegalStateException
*/
int label(Document document) throws IllegalArgumentException, IllegalStateException;

/**
* 预测最可能的分类
* @param text 文本
* @return 最可能的分类
* @throws IllegalArgumentException
* @throws IllegalStateException
*/
String classify(String text) throws IllegalArgumentException, IllegalStateException;

/**
* 预测最可能的分类
* @param document 一个结构化的文档(注意!这是一个底层数据结构,请谨慎操作)
* @return 最可能的分类
* @throws IllegalArgumentException
* @throws IllegalStateException
*/
String classify(Document document) throws IllegalArgumentException, IllegalStateException;
classify方法直接返回最可能的类别的String形式,而predict方法返回所有类别的得分(是一个Map形式,键是类目,值是分数或概率),categorize方法返回所有类目的得分(是一个double数组,分类得分按照分类名称的字典序排列),label方法返回最可能类目的字典序。

线程安全性

类似于HanLP的设计,以效率至上,本系统内部实现没有使用任何线程锁,但任何预测接口都是线程安全的(被设计为不储存中间结果,将所有中间结果放入参数栈中)。

情感分析

可以利用文本分类在情感极性语料上训练的模型做浅层情感分析。目前公开的情感分析语料库有:中文情感挖掘语料-ChnSentiCorp,语料发布者为谭松波。

接口与文本分类完全一致,请参考com.hankcs.demo.DemoSentimentAnalysis。

性能指标

一般来讲,受到语料库质量的约束(部分语料库的分类标注模糊或有重叠),我们评测一个分类器时,必须严谨地注明在哪个语料库以何种比例分割数据集下得到这样的测试结果。

版本库中有一个在搜狗语料库上的测试com.hankcs.demo.DemoTextClassificationFMeasure,含有完整的参数,请自行运行评估。
人工智能
2019-02-20 14:22:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
本篇分享的依然是关于hanlp的分词使用,文章内容分享自 gladosAI 的博客,本篇文章中提出了一个问题,hanlp分词影响了实验判断结果。为何会如此,不妨一起学习一下 gladosAI 的这篇文章。
学习内容
在之前的实验中得到了不在词向量里的词与分词结果,结果有500多个词不在词向量里,解决方案就是重新分词,或再追加训练这些词到词向量里。但后者相对麻烦且目前样本量不大。我跟据词向量的作者[6]所使用的分词工具来分词,会比不同工具(jieba)的效果要好,因为都是同一模式的分词,分出来的词应该都会存在于大型语料库中。实验证明思路是对的,最后结果是只有60几个词不在词向量里,其中大部分为名词,还有些为因语音翻译问题所造成的出错连词,所有这些词也只出现一次,这部分可以考虑最后删去也不会影响结果。改善未出现词是个关键步骤,因为此后模型会用到词向量,如果未出现词过多,会影响词向量效果。
问题:不过最后HANLP分词影响了实验判断结果,准确率从93%(jieba分词,同模型同参数)下降到90%。
实验:使用HanLP分词
1,前期准备,(环境ubuntu,python3)安装JAVA-10[3](hanlp是JAVA开发的,即使使用python调用pyhanlp需要借助java), jpype(python中虚拟java环境),hanlp(开源中文处理工具,不只是分词还有各种工具),hanlp的root路径配置及data数据包放置[4]
2,主要程序[5]
w2v_model = KeyedVectors.load_word2vec_format(w2vpath, binary=False, unicode_errors='ignore') # 加载词向量
hanlppath=\"-Djava.class.path=/media/glados/Learning/project/NLP/hanlp/hanlp-1.6.4.jar:/media/glados/Learning/project/NLP/hanlp/"
jp.startJVM(jp.getDefaultJVMPath(), hanlppath) # , "-Xms1g", "-Xmx1g") # 启动JVM, Xmx1g分配1g内存
jp.JClass('com.hankcs.hanlp.HanLP$Config').ShowTermNature = False # 关闭分词属性显示
HanLP = jp.JClass('com.hankcs.hanlp.HanLP') #普通分词模式
words = str(HanLP.segment(sentence)) #分词将结果转为str
words = re.sub('[反斜杠[反斜杠],\n]', ' ', words) # 这里注意实际程序是单\,在blog里会出问题,所以用反斜杠替代
words = words.split()
words = del_stopword(words)
...
jp.shutdownJVM() # 最后关闭java虚拟环境
使用的是HANLP的普通分词功能,另外需注意,hanlp.segment()不能直接输出或赋值给python,因为其是java环境中数据,所以只有转为str()后,再进行处理,否则会报错#A fatal error。(另外还有其他java与python数据对应问题,在这里没遇到,请参考其他)

词向量选用的是“Mixed-large综合”[6],其包括百度wiki百科、人民日报等,总共1293214个词。

Hanlp的中部份功能没法使用,例如精确分词CRF。另外,要先加载词向量再加载java虚拟环境。#A fatal error has been detected by the Java Runtime Environment

3,实验结果
(模型使用的是特征为tfidf的lsi模型, 参数:num_topics=3, 判断是否相似阀值为0.45,即大于0.45为true相似 )

同模型同参数下,jieba分词结果
jieba分词未出现在词向量的约500多,有些词出现了好几次,而hanlp分词只有60几个未出现,且多数为名词,只出现过一次。
4,分析
在样本中,所有样本分词结果jieba比hanlp要多分出100个词左右。所以推测因hanlp分词细粒度大,分出词少,导致较少的共现词出现(也可能是hanlp分词精度更高,分出很多虚词被停止词表过滤造成),也就是说,lsi+tfidf模型对词细粒度大、分词少的分词器不友好,所以最后hanlp出错率更大。
jieba与hanlp都是很不错的分词器,结巴使用更方便。hanlp准确度要高一些(感觉),而且与文中提到的词向量相匹配。
(我免贵姓AI,jieba:我免/贵姓/AI,hanlp:我/免/贵姓/AI,实际:我/免贵/姓AI)
人工智能
2019-02-18 08:53:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
写在前面:
每当提到损失函数,很多人都有个误解,以为用在GridSearchCV(网格搜索交叉验证“Cross Validation”)里边的scoring就是损失函数,其实并不是。我们使用构造函数构造XGBRegressor的时候,里边的objective参数才是真正的损失函数(loss function)。xgb使用sklearn api的时候需要用到的损失函数,其返回值是一阶导和二阶导,而GridSearchCV使用的scoring函数,返回的是一个float类型的数值评分(或叫准确率、或叫偏差值)。 You should be careful with the notation.
There are 2 levels of optimization here: The loss function optimized when the XGBRegressor is fitted to the data. The scoring function that is optimized during the grid search.
I prefer calling the second scoring function instead of loss function, since loss function usually refers to a term that is subject to optimization during the model fitting process itself.
Scikit-Learn: Custom Loss Function for GridSearchCV
因此,下文对于objective,统一叫“目标函数”;而对scoring,统一叫“评价函数”。


========== 原文分割线 ===================
许多特定的任务需要定制 目标函数 ,来达到更优的效果。这里以xgboost的回归预测为例,介绍一下objective函数的定制过程。一个简单的例子如下: def customObj1(real, predict): grad = predict - real hess = np.power(np.abs(grad), 0.5) return grad, hess
网上有许多教程定义的objective函数中的第一个参数是preds,第二个是dtrain,而本文由于使用xgboost的sklearn API,因此定制的objective函数需要与sklearn的格式相符。调用目标函数的过程如下: model = xgb.XGBRegressor(objective=customObj1, booster="gblinear")
下面是不同迭代次数的动画演示:
我们发现,不同的目标函数对模型的收敛速度影响较大,但最终收敛目标大致相同,如下图:
完整代码如下: # coding=utf-8 import pandas as pd import numpy as np import xgboost as xgb import matplotlib.pyplot as plt plt.rcParams.update({'figure.autolayout': True}) df = pd.DataFrame({'x': [-2.1, -0.9, 0, 1, 2, 2.5, 3, 4], 'y': [ -10, 0, -5, 10, 20, 10, 30, 40]}) X_train = df.drop('y', axis=1) Y_train = df['y'] X_pred = [-4, -3, -2, -1, 0, 0.4, 0.6, 1, 1.4, 1.6, 2, 3, 4, 5, 6, 7, 8] def process_list(list_in): result = map(lambda x: "%8.2f" % round(float(x), 2), list_in) return list(result) def customObj3(real, predict): grad = predict - real hess = np.power(np.abs(grad), 0.1) # print 'predict', process_list(predict.tolist()), type(predict) # print ' real ', process_list(real.tolist()), type(real) # print ' grad ', process_list(grad.tolist()), type(grad) # print ' hess ', process_list(hess.tolist()), type(hess), '\n' return grad, hess def customObj1(real, predict): grad = predict - real hess = np.power(np.abs(grad), 0.5) return grad, hess for n_estimators in range(5, 600, 5): booster_str = "gblinear" model = xgb.XGBRegressor(objective=customObj1, booster=booster_str, n_estimators=n_estimators) model2 = xgb.XGBRegressor(objective="reg:linear", booster=booster_str, n_estimators=n_estimators) model3 = xgb.XGBRegressor(objective=customObj3, booster=booster_str, n_estimators=n_estimators) model.fit(X=X_train, y=Y_train) model2.fit(X=X_train, y=Y_train) model3.fit(X=X_train, y=Y_train) y_pred = model.predict(data=pd.DataFrame({'x': X_pred})) y_pred2 = model2.predict(data=pd.DataFrame({'x': X_pred})) y_pred3 = model3.predict(data=pd.DataFrame({'x': X_pred})) plt.figure(figsize=(6, 5)) plt.axes().set(title='n_estimators='+str(n_estimators)) plt.plot(df['x'], df['y'], marker='o', linestyle=":", label="Real Y") plt.plot(X_pred, y_pred, label="predict - real; |grad|**0.5") plt.plot(X_pred, y_pred3, label="predict - real; |grad|**0.1") plt.plot(X_pred, y_pred2, label="reg:linear") plt.xlim(-4.5, 8.5) plt.ylim(-25, 55) plt.legend() # plt.show() plt.savefig("output/n_estimators_"+str(n_estimators)+".jpg") plt.close() print(n_estimators)
人工智能
2019-01-28 17:31:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>> 本文由云+社区发表 作者:徐汉彬
一、人工智能和新科技革命
2017年围棋界发生了一件比较重要事,Master(Alphago)以60连胜横扫天下,击败各路世界冠军,人工智能以气势如虹的姿态出现在我们人类的面前。围棋曾经一度被称为“人类智慧的堡垒”,如今,这座堡垒也随之成为过去。从2016年三月份AlphaGo击败李世石开始,AI全面进入我们大众的视野,对于它的讨论变得更为火热起来,整个业界普遍认为,它很可能带来下一次科技革命,并且,在未来可预见的10多年里,深刻得改变我们的生活。
其实,AI除了可以做我们熟知的人脸、语音等识别之外,它可以做蛮多有趣的事情。
例如,让AI学习大量古诗之后写古诗,并且可以写出质量非常不错的古诗。
又或者,将两部设计造型不同的汽车进行融合,形成全新一种设计风格的新汽车造型。
还有,之前大家在朋友圈里可能看过的,将相片转换成对应的艺术风格的画作。
当前,人工智能已经在图像、语音等多个领域的技术上,取得了全面的突破。与此同时,另外一个问题随之而来,如果这一轮的AI浪潮真的将会掀起新的科技革命,那么在可预见的未来,我们整个互联网都将发生翻天覆地的变化,深刻影响我们的生活。那么作为普通业务开发工程师的我,又应该以何种态度和方式应对这场时代洪流的冲击呢?
在回答这个问题之前,我们先一起看看上一轮由计算机信息技术引领的科技革命中,过去30多年中国程序员的角色变化:
通过上图可以简总结:编程技术在不断地发展并且走向普及,从最开始掌握在科学家和专家学者手中的技能,逐渐发展为一门大众技能。换而言之,我们公司内很多资深的工程师,如果带着今天对编程和计算机的理解和理念回到1980年,那么他无疑就是那个时代的计算机专家。
如果这一轮AI浪潮真的会带来新的一轮科技革命,那么我们相信,它也会遵循类似的发展轨迹,逐步发展和走向普及。如果基于这个理解,或许,我们可以通过积极学习,争取成为第一代AI工程师。
二、深度学习技术
这一轮AI的技术突破,主要源于深度学习技术,而关于AI和深度学习的发展历史我们这里不重复讲述,可自行查阅。我用了一个多月的业务时间,去了解和学习了深度学习技术,在这里,我尝试以一名业务开发工程师的视角,以尽量容易让大家理解的方式一起探讨下深度学习的原理,尽管,受限于我个人的技术水平和掌握程度,未必完全准确。
1. 人的智能和神经元
人类智能最重要的部分是大脑,大脑虽然复杂,它的组成单元却是相对简单的,大脑皮层以及整个神经系统,是由神经元细胞组成的。而一个神经元细胞,由树突和轴突组成,它们分别代表输入和输出。连在细胞膜上的分叉结构叫树突,是输入,那根长长的“尾巴”叫轴突,是输出。神经元输出的有电信号和化学信号,最主要的是沿着轴突细胞膜表面传播的一个电脉冲。忽略掉各种细节,神经元,就是一个积累了足够的输入,就产生一次输出(兴奋)的相对简单的装置。
树突和轴突都有大量的分支,轴突的末端通常连接到其他细胞的树突上,连接点上是一个叫“突触”的结构。一个神经元的输出通过突触传递给成千上万个下游的神经元,神经元可以调整突触的结合强度,并且,有的突触是促进下游细胞的兴奋,有的是则是抑制。一个神经元有成千上万个上游神经元,积累它们的输入,产生输出。
人脑有1000亿个神经元,1000万亿个突触,它们组成人脑中庞大的神经网络,最终产生的结果即是人的智能。
2. 人工神经元和神经网络
一个神经元的结构相对来说是比较简单的,于是,科学家们就思考,我们的AI是否可以从中获得借鉴?神经元接受激励,输出一个响应的方式,同计算机中的输入输出非常类似,看起来简直就是量身定做的,刚好可以用一个函数来模拟。
通过借鉴和参考神经元的机制,科学家们模拟出了人工神经元和人工神经网络。当然,通过上述这个抽象的描述和图,比较难让大家理解它的机制和原理。我们以“房屋价格测算”作为例子,一起来看看:
一套房子的价格,会受到很多因素的影响,例如地段、朝向、房龄、面积、银行利率等等,这些因素如果细分,可能会有几十个。一般在深度学习模型里,这些影响结果的因素我们称之为特征。我们先假设一种极端的场景,例如影响价格的特征只有一种,就是房子面积。于是我们收集一批相关的数据,例如,50平米50万、93平米95万等一系列样本数据,如果将这些样本数据放到而为坐标里看,则如下图:
然后,正如我们前面所说的,我们尝试用一个“函数”去拟合这个输入(面积x)和输出(价格y),简而言之,我们就是要通过一条直线或者曲线将这些点“拟合”起来。
假设情况也比较极端,这些点刚好可以用一条“直线”拟合(真实情况通常不会是直线),如下图:
那么我们的函数是一个一次元方程f(x) = ax +b,当然,如果是曲线的话,我们得到的将是多次元方程。我们获得这个f(x) = ax +b的函数之后,接下来就可以做房价“预测”,例如,我们可以计算一个我们从未看见的面积案例81.5平方米,它究竟是多少钱?
这个新的样本案例,可以通过直线找到对应的点(黄色的点),如图下:
粗略的理解,上面就是AI的概括性的运作方式。这一切似乎显得过于简单了?当然不会,因为,我们前面提到,影响房价其实远不止一个特征,而是有几十个,这样问题就比较复杂了,接下来,这里则要继续介绍深度学习模型的训练方式。这部分内容相对复杂一点,我尽量以业务工程师的视角来做一个粗略而简单的阐述。
3. 深度学习模型的训练方式
当有好几十个特征共同影响价格的时候,自然就会涉及权重分配的问题,例如有一些对房价是主要正权重的,例如地段、面积等,也有一些是负权重的,例如房龄等。
(1)初始化权重计算
那么,第一个步其实是给这些特征加一个权重值,但是,最开始我们根本不知道这些权重值是多少?怎么办呢?不管那么多了,先给它们随机赋值吧。随机赋值,最终计算出来的估算房价肯定是不准确的,例如,它可能将价值100万的房子,计算成了10万。
(2)损失函数
因为现在模型的估值和实际估值差距比较大,于是,我们需要引入一个评估“不准确”程度的衡量角色,也就是损失(loss)函数,它是衡量模型估算值和真实值差距的标准,损失函数越小,则模型的估算值和真实值的察觉越小,而我们的根本目的,就是降低这个损失函数。让刚刚的房子特征的模型估算值,逼近100万的估算结果。
(3)模型调整
通过梯度下降和反向传播,计算出朝着降低损失函数的方向调整权重参数。举一个不恰当的比喻,我们给面积增加一些权重,然后给房子朝向减少一些权重(实际计算方式,并非针对单个个例特征的调整),然后损失函数就变小了。
(4)循环迭代
调整了模型的权重之后,就可以又重新取一批新的样本数据,重复前面的步骤,经过几十万次甚至更多的训练次数,最终估算模型的估算值逼近了真实值结果,这个模型的则是我们要的“函数”。
为了让大家更容易理解和直观,采用的例子比较粗略,并且讲述深度学习模型的训练过程,中间省略了比较多的细节。讲完了原理,那么我们就开始讲讲如何学习和搭建demo。
三、深度学习环境搭建
在2个月前,人工智能对我来说,只是一个高大上的概念。但是,经过一个多月的业余时间的认真学习,我发现还是能够学到一些东西,并且跑一些demo和应用出来的。
1. 学习的提前准备
(1)部分数学内容的复习,高中数学、概率、线性代数等部分内容。(累计花费了10个小时,挑了关键的点看了下,其实还是不太够,只能让自己看公式的时候,相对没有那么懵)
(2)Python基础语法学习。(花费了3个小时左右,我以前从未写过Python,因为后面Google的TensorFlow框架的使用是基于Python的)
(3)Google的TensorFlow深度学习开源框架。(花费了10多个小时去看)
数学基础好或者前期先不关注原理的同学,数学部分不看也可以开始做,全凭个人选择。
2. Google的TensorFlow开源深度学习框架
深度学习框架,我们可以粗略的理解为是一个“数学函数”集合和AI训练学习的执行框架。通过它,我们能够更好的将AI的模型运行和维护起来。
深度学习的框架有各种各样的版本(Caffe、Torch、Theano等等),我只接触了Google的TensorFlow,因此,后面的内容都是基于TensorFlow展开的,它的详细介绍这里不展开讲述,建议直接进入官网查看。非常令人庆幸的是TensorFlow比较早就有中文社区了,尽管里面的内容有一点老,搭建环境方面有一些坑,但是已经属于为数不多的中文文档了,大家且看且珍惜。
TensorFlow 的中文社区
TensorFlow 的英文社区
3. TensorFlow环境搭建
环境搭建本身并不复杂,主要解决相关的依赖。但是,基础库的依赖可以带来很多问题,因此,建议尽量一步到位,会简单很多。
(1)操作系统
我搭建环境使用的机器是腾讯云上的机器,软件环境如下:
操作系统:CentOS 7.2 64位(GCC 4.8.5)
因为这个框架依赖于python2.7和glibc 2.17。比较旧的版本的CentOS一般都是python2.6以及版本比较低的glibc,会产生比较的多基础库依赖问题。而且,glibc作为Linux的底层库,牵一发动全身,直接对它升级是比较复杂,很可能会带来更多的环境异常问题。
(2)软件环境
我目前安装的Python版本是python-2.7.5,建议可以采用yum install python的方式安装相关的原来软件。然后,再安装 python内的组件包管理器pip,安装好pip之后,接下来的其他软件的安装就相对比较简单了。
例如安装TensorFlow,可通过如下一句命令完成(它会自动帮忙解决一些库依赖问题): pip install -U tensorflow
这里需要特别注意的是,不要按照TensorFlow的中文社区的指引去安装,因为它会安装一个非常老的版本(0.5.0),用这个版本跑很多demo都会遇到问题的。而实际上,目前通过上述提供的命令安装,是tensorflow (1.0.0)的版本了。
Python(2.7.5)下的其他需要安装的关键组件: tensorflow (0.12.1),深度学习的核心框架 image (1.5.5),图像处理相关,部分例子会用到 PIL (1.1.7),图像处理相关,部分例子会用到
除此之后,当然还有另外的一些依赖组件,通过pip list命令可以查看我们安装的python组件: appdirs (1.4.0) backports.ssl-match-hostname (3.4.0.2) chardet (2.2.1) configobj (4.7.2) decorator (3.4.0) Django (1.10.4) funcsigs (1.0.2) image (1.5.5) iniparse (0.4) kitchen (1.1.1) langtable (0.0.31) mock (2.0.0) numpy (1.12.0) packaging (16.8) pbr (1.10.0) perf (0.1) PIL (1.1.7) Pillow (3.4.2) pip (9.0.1) protobuf (3.2.0) pycurl (7.19.0) pygobject (3.14.0) pygpgme (0.3) pyliblzma (0.5.3) pyparsing (2.1.10) python-augeas (0.5.0) python-dmidecode (3.10.13) pyudev (0.15) pyxattr (0.5.1) setuptools (34.2.0) six (1.10.0) slip (0.4.0) slip.dbus (0.4.0) tensorflow (1.0.0) urlgrabber (3.10) wheel (0.29.0) yum-langpacks (0.4.2) yum-metadata-parser (1.1.4)
按照上述提供的来搭建系统,可以规避不少的环境问题。
搭建环境的过程中,我遇到不少问题。例如:在跑官方的例子时的某个报错,AttributeError: 'module' object has no attribute 'gfile',就是因为安装的TensorFlow的版本比较老,缺少gfile模块导致的。而且,还有各种各样的。(不要问我是怎么知道的,说多了都是泪啊~)
更详细的安装说明: Installing TensorFlow on Ubuntu
(3)TensorFlow环境测试运行
测试是否安装成功,可以采用官方的提供的一个短小的例子,demo生成了一些三维数据, 然后用一个平面拟合它们(官网的例子采用的初始化变量的函数是initialize_all_variables,该函数在新版本里已经被废弃了): #!/usr/bin/python #coding=utf-8 import tensorflow as tf import numpy as np # 使用 NumPy 生成假数据(phony data), 总共 100 个点. x_data = np.float32(np.random.rand(2, 100)) # 随机输入 y_data = np.dot([0.100, 0.200], x_data) + 0.300 # 构造一个线性模型 # b = tf.Variable(tf.zeros([1])) W = tf.Variable(tf.random_uniform([1, 2], -1.0, 1.0)) y = tf.matmul(W, x_data) + b # 最小化方差 loss = tf.reduce_mean(tf.square(y - y_data)) optimizer = tf.train.GradientDescentOptimizer(0.5) train = optimizer.minimize(loss) # 初始化变量,旧函数(initialize_all_variables)已经被废弃,替换为新函数 init = tf.global_variables_initializer() # 启动图 (graph) sess = tf.Session() sess.run(init) # 拟合平面 for step in xrange(0, 201): sess.run(train) if step % 20 == 0: print step, sess.run(W), sess.run(b) # 得到最佳拟合结果 W: [[0.100 0.200]], b: [0.300]
运行的结果类似如下:
经过200次的训练,模型的参数逐渐逼近最佳拟合的结果(W: [[0.100 0.200]], b: [0.300]),另外,我们也可以从代码的“风格”中,了解到框架样本训练的基本运行方式。虽然,官方的教程后续会涉及越来越多更复杂的例子,但从整体上看,也是类似的模式。
步骤划分 准备数据:获得有标签的样本数据(带标签的训练数据称为有监督学习); 设置模型:先构建好需要使用的训练模型,可供选择的机器学习方法其实也挺多的,换而言之就是一堆数学函数的集合; 损失函数和优化方式:衡量模型计算结果和真实标签值的差距; 真实训练运算:训练之前构造好的模型,让程序通过循环训练和学习,获得最终我们需要的结果“参数”; 验证结果:采用之前模型没有训练过的测试集数据,去验证模型的准确率。
其中,TensorFlow为了基于python实现高效的数学计算,通常会使用到一些基础的函数库,例如Numpy(采用外部底层语言实现),但是,从外部计算切回到python也是存在开销的,尤其是在几万几十万次的训练过程。因此,Tensorflow不单独地运行单一的函数计算,而是先用图描述一系列可交互的计算操作流程,然后全部一次性提交到外部运行(在其他机器学习的库里,也是类似的实现)。
所以,上述流程图中,蓝色部分都只是设置了“计算操作流程”,而绿色部分开始才是真正的提交数据给到底层库进行实际运算,而且,每次训练一般是批量执行一批数据的。
此文已由腾讯云+社区在各渠道发布
获取更多新鲜技术干货,可以关注我们 腾讯云技术社区-云加社区官方号及知乎机构号
人工智能
2019-01-21 18:35:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
前言
深度学习在移动端的应用是越来越广泛,由于移动端的运算力与服务器相比还是有差距,所以在移动端
部署深度学习模型的难点就在于如何保证模型效果的同时,运行效率也有保证。在实验阶段对于模型结构可以
选择大模型,因为该阶段主要是为了验证方法的有效性。在验证完了之后,开始着手部署到移动端,这时候就
要精简模型的结构了,一般是对训好的大模型进行剪枝,或者参考现有的比如MobileNetV2和ShuffleNetV2
等轻量级的网络重新设计自己的网络模块。而算法层面的优化除了剪枝还有量化,量化就是把浮点数(高精度)
表示的权值和激活值用更低精度的整数来近似表示。低精度的优点有,相比于高精度算术运算,其在单位时间
内能处理更多的数据,而且权值量化之后模型的存储空间能进一步的减少等等[1]。对训练好的网络做量化,
在实践中尝试过TensorRT[5][8]的后训练量化算法,效果还不错。但是如果能在训练过程中去模拟量化的过程,
让网络学习去修正量化带来的误差,那么得到的量化参数应该是更准确的,而且在实际量化推断中模型的性能
损失应该能更小。而本文的内容就是介绍论文[3][4]和复现其过程中的一些细节。
按照惯例,先给出本文实验的代码: TrainQuantization
训练模拟量化
方法介绍
首先来看下量化的具体定义,对于量化激活值到有符号8bit整数,论文中给出的定义如下:

公式中的三角形表示量化的缩放因子,x表示浮点数激活值,首先通过除以缩放因子然后最近邻取整,
然后把范围限制到一个区间内,比如量化到有符号8bit,那么范围就是 [-128, 127]。而对于权值还有一
个小的技巧,就是量化到[-127, 127]:
具体为什么这么做,论文中说了是为了实现上的优化,具体解释可以看论文[3]附录B ARM NEON details
这一小节。
而训练量化说白了就是在forward阶段去模拟量化这个过程,本质就是把权值和激活值量化到8bit再反
量化回有误差的32bit,所以训练还是浮点,backward阶段是对模拟量化之后权值的求梯度,然后用这个
梯度去更新量化前的权值。然后在下个batch继续这个过程,通过这样子能够让网络学会去修正量化带来的
误差。
上面给这个示意图就很直观的表示了模拟量化的过程,比如上面那条线表示的是量化前的范围[rmin, rmax],
然后下面那条线表示的就是量化之后的范围[-128, 127],比如现在要进行模拟量化的forward,先看上面那
条线从左到右数第4个圆点,通过除以缩放因子之后就会映射124到125之间的一个浮点数,然后通过最近邻
取整就取到了125,再通过乘以缩放因子返回上面第五个圆点,最后就用这个有误差的数替换原来的去forward。
forward阶段的模拟量化用公式表示如下:

backward阶段求梯度的公式表示如下:
对于缩放因子的计算,权值和激活值的不一样,权值的计算方法是每次forward直接对权值求绝对值取
最大值,然后缩放因子 weight scale = max(abs(weight)) / 127。然后对于激活值,稍微有些不一样,
激活值的量化范围不是简单的计算最大值,而是通过EMA(exponential moving averages)在训练中
去统计这个量化范围,更新公式如下:
moving_max = moving_max * momenta + max(abs(activation)) * (1- momenta)
公式中的activation表示每个batch的激活值,而论文中说momenta取接近1的数就行了,在实验中
我是取0.95。然后缩放因子 activation scale = moving_max /128。
实现细节
在实现过程中我没有按照论文的方法量化到无符号8bit,而是有符号8bit,第一是因为无符号8bit量化
需要引入额外的零点,增加复杂性,其次在实际应用过程中都是量化到有符号8bit。然后论文中提到,
对于权值的量化分通道进行求缩放因子,然后对于激活值的量化整体求一个缩放因子,这样效果最好。
在实践中发现有些任务权值不分通道量化效果也不错,这个还是看具体任务吧,不过本文给的实验代码
是没分的。
然后对于卷积层之后带batchnorm的网络,因为一般在实际使用阶段,为了优化速度,batchnorm
的参数都会提前融合进卷积层的参数中,所以训练模拟量化的过程也要按照这个流程。首先把batchnorm
的参数与卷积层的参数融合,然后再对这个参数做量化。以下两张图片分别表示的是训练过程与实际应用
过程中对batchnorm层处理的区别:

对于如何融合batchnorm参数进卷积层参数,看以下公式:
公式中的,W和b分别表示卷积层的权值与偏置,x和y分别为卷积层的输入与输出,则根据bn的计算
公式,可以推出融合了batchnorm参数之后的权值与偏置,Wmerge和bmerge。
在实验中我其实是简化了融合batchnorm的流程,要是完全按照论文中的实现要复杂很多,
而且是基于已经训好的网络去做模拟量化实验的,不基于预训练模型训不起来,可能还有坑要踩。
而且在模拟量化训练过程中batchnorm层参数固定,融合batchnorm参数也是用已经训好的移动
均值和方差,而不是用每个batch的均值和方差。
具体实现的时候就是按照论文中的这个模拟量化卷积层示例图去写训练网络结构的。
实验结果
用VGG在Cifar10上做了下实验,效果还可以,因为是为了验证量化训练的有效性,所以训
Cifar10的时候没怎么调过参,数据增强也没做,训出来的模型精确度最高只有0.877,比最好的
结果0.93差不少,然后模拟量化是基于这个0.877的模型去做的,可以得到与普通训练精确度基本
一样的模型,可能是这个分类任务比较简单。然后得到训好的模型与每层的量化因子之后,就可以
模拟真实的量化推断过程,不过因为MXNet的卷积层不支持整型运算,所以模拟的过程也是用浮点
来模拟,具体实现细节可见示例代码。
结束语
以上内容是根据最近的一些工作实践总结得到的一篇博客,对于论文的实现很多地方都是我自己
个人的理解,如果有读者发现哪里有误或者有疑问,也请指出,大家互相交流学习:)。
参考资料
[1] 8-Bit Quantization and TensorFlow Lite: Speeding up mobile inference with low precision
[2] Building a quantization paradigm from first principles
[3] Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference
[4] Quantizing deep convolutional networks for efficient inference: A whitepaper
[5] 8-bit Inference with TensorRT
[6] TensorRT(5)-INT8校准原理
[7] caffe-int8-convert-tool.py
人工智能
2019-01-13 13:26:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>

期望、方差和协方差


人工智能
2019-01-11 21:41:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
在澳门用人工智能预测流感趋势后,阿里巴巴还在继续探索如何用科技保障人类健康,这一次是更准确地测量肝结节。
12月28日消息,在全球LiTS(Liver Tumor Segmentation Challenge,肝脏肿瘤病灶区CT图像分割挑战)上,阿里巴巴从近百支科学家队伍中脱颖而出,已获得两项第一,至今无人超越。
肝病是困扰人类的重大公共卫生威胁,考古显示4500年前的人类骨骼中甚至就有最古老的乙肝病毒。在我国,目前肝癌的死亡率在恶性肿瘤中位居第二,仅次于肺癌。
肝结节尽管不致命,却可能是一些恶性肿瘤的先兆。LiTS由德国慕尼黑理工大学、以色列特拉维夫大学等高校、科研院所与国际顶级医学图像年会MICCA联合举办,希望用创新的算法解决肝脏肿瘤病灶CT图像的自动分割。
对肝结节的准确测量可以辅助医生做出决策和治疗方案。但肝结节形态多样,即使是同一个病人,结节的大小、形状都不一样,从而导致结节间灰度分布差异大、或与周围组织灰度相似,甚至没有清晰的边界。
阿里巴巴通过对CT图像层间信息和层内信息融合的网络结构分析解决肝结节类别多样性的问题,采用到基于原子卷积的空间金字塔池化(Atrous Spatial Pyramid Pooling)、亚像素卷积(Sub Pixel Convolution)及多特征融合等技术。
据了解,这一技术由阿里云人工智能中心研发,下一步是判断肝结节是否为恶性,对临床医疗将有更大的促进作用。
此前这个团队还打破了国际AI检测肺结节准确度的世界纪录,创造了全程无须人工干预的检测方式:机器自动读取病人CT序列,直接输出检测到的肺结节。
负责人华先胜表示,目前研究范围已经覆盖肺、肝、骨、心脏、脑等部位的疾病,涉及影像分析、自然语言处理、设备信号处理等相关技术,部分技术已经落地到实际的医疗诊断中。
华先胜是视觉识别和搜索领域的国际权威学者,曾获国际电气与电子工程协会院士 (IEEE Fellow)、美国计算机协会ACM杰出科学家。
麦肯锡全球研究院曾在报告中指出,将人工智能应用于保护公共健康是可靠的选择。包括阿里巴巴在内,IBM、谷歌等科技公司都在研究如何在医疗领域发挥人工智能的作用。谷歌在今年10月曾公布最新进展,能通过AI检测转移性乳腺癌。
原文链接
人工智能
2018-12-28 15:23:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
引言
我们正处在一个知识爆炸的时代,伴随着信息量的剧增和人工智能的蓬勃发展,互联网公司越发具有强烈的个性化、智能化信息展示的需求。而信息展示个性化的典型应用主要包括搜索列表、推荐列表、广告展示等等。
很多人不知道的是,看似简单的个性化信息展示背后,涉及大量的数据、算法以及工程架构技术,这些足以让大部分互联网公司望而却步。究其根本原因,个性化信息展示背后的技术是排序学习问题(Learning to Rank)。显然,市面上大部分关于排序学习的文章,要么偏算法、要么偏工程。虽然算法方面有一些系统性的介绍文章,但往往对读者的数学能力要求比较高,也偏学术论文,对于非算法同学来说门槛非常高。而大部分工程方面的文章也比较粗糙,基本上停留在Google的Two-Phase Scheme阶段,从工程实施的角度来说,远远还不够具体。
对于那些由系统开发工程师负责在线排序架构的团队来说,本文会采用通俗的例子和类比方式来阐述算法部分,希望能够帮助大家更好地理解和掌握排序学习的核心概念。如果是算法工程师团队的同学,可以忽略算法部分的内容。本文的架构部分阐述了美团点评到店餐饮业务线上运行的系统,可以作为在线排序系统架构设计的参考原型直接使用。该架构在服务治理、分层设计的理念,对于保障在线排序架构的高性能、高可用性、易维护性也具有一定的参考价值。包括很多具体环节的实施方案也可以直接进行借鉴,例如流量分桶、流量分级、特征模型、级联模型等等。
总之,让开发工程师能够理解排序学习算法方面的核心概念,并为在线架构实施提供细颗粒度的参考架构,是本文的重要目标。
算法部分
机器学习涉及优化理论、统计学、数值计算等多个领域。这给那些希望学习机器学习核心概念的系统开发工程师带来了很大的障碍。不过,复杂的概念背后往往蕴藏着朴素的道理。本节将尝试采用通俗的例子和类比方式,来对机器学习和排序学习的一些核心概念进行揭秘。
机器学习
什么是机器学习?
典型的机器学习问题,如下图所示:
机器学习模型或算法(Model/Algorithm)会根据观察到的特征值(Feature)进行预测,给出预测结果或者目标(Prediction/Target)。这就像是一个函数计算过程,对于特定X值(Feature),算法模型就像是函数,最终的预测结果是Y值。不难理解,机器学习的核心问题就是如何得到预测函数。
Wikipedia的对机器学习定义如下:
“Machine learning is a subset of artificial intelligence in the field of computer science that often uses statistical techniques to give computers the ability to learn with data, without being explicitly programmed.”
机器学习的最重要本质是从数据中学习,得到预测函数。人类的思考过程以及判断能力本质上也是一种函数处理。从数据或者经验中学习,对于人类来说是一件再平常不过的事情了。例如人们通过观察太阳照射物体影子的长短而发明了日晷,从而具备了计时和制定节气的能力。古埃及人通过尼罗河水的涨落发明了古埃及历法。
又比如人们通过观察月亮形状的变化而发明了阴历。
如果机器能够像人一样具备从数据中学习的能力,从某种意义上讲,就具备了一定的“智能”。现在需要回答的两个问题就是: 到底什么是“智能”? 如何让机器具备智能?
什么是智能?
在回答这个问题之前,我们先看看传统的编程模式为什么不能称之为“智能”。传统的编程模式如下图所示,它一般要经历如下几个阶段: 人类通过观察数据(Data)总结经验,转化成知识(Knowledge)。 人类将知识转化成规则(Rule)。 工程师将规则转化成计算机程序(Program)。
在这种编程模式下,如果一个问题被规则覆盖,那么计算机程序就能处理。对于规则不能覆盖的问题,只能由人类来重新思考,制定新规则来解决。所以在这里“智能”角色主要由人类来承担。人类负责解决新问题,所以传统的程序本身不能称之为“智能”。
所以,“智能”的一个核心要素就是“举一反三”。
如何让机器具备智能?
在讨论这个问题之前,可以先回顾一下人类是怎么掌握“举一反三”的能力的?基本流程如下: 老师给学生一些题目,指导学生如何解题。学生努力掌握解题思路,尽可能让自己的答案和老师给出的答案一致。 学生需要通过一些考试来证明自己具备“举一反三”的能力。如果通过了这些考试,学生将获得结业证书或者资格从业证书。 学生变成一个从业者之后将会面临并且处理很多之前没有碰到过的新问题。
机器学习专家从人类的学习过程中获得灵感,通过三个阶段让机器具备“举一反三”的能力。这三个阶段是:训练阶段(Training)、测试阶段(Testing)、推导阶段(Inference)。下面逐一进行介绍:
训练阶段
训练阶段如下图所示: 人类给机器学习模型一些训练样本(X,Y),X代表特征,Y代表目标值。这就好比老师教学生解题,X代表题目,Y代表标准答案。 机器学习模型尝试想出一种方法解题。 在训练阶段,机器学习的目标就是让损失函数值最小。类比学生尝试让自己解题的答案和老师给的标准答案差别最小,思路如出一辙。
测试阶段
测试阶段如下图所示: 人类给训练好的模型一批完全不同的测试样本(X,Y)。这就好比学生拿到考试试卷。 模型进行推导。这个过程就像学生正在考试答题。 人类要求测试样本的总损失函数值低于设定的最低目标值。这就像学校要求学生的考试成绩必须及格一样。
推导阶段
推导阶段如下图所示: 在这个阶段机器学习模型只能拿到特征值X,而没有目标值。这就像工作中,人们只是在解决一个个的问题,但不知道正确的结果到底是什么。 在推导阶段,机器学习的目标就是预测,给出目标值。
排序学习
什么是排序学习?
Wikipedia的对排序学习的定义如下:
“Learning to rank is the application of machine learning, typically supervised, semi-supervised or reinforcement learning, in the construction of ranking models for information retrieval systems. Training data consists of lists of items with some partial order specified between items in each list. This order is typically induced by giving a numerical or ordinal score or a binary judgment (e.g. "relevant" or "not relevant") for each item. The ranking model's purpose is to rank, i.e. produce a permutation of items in new, unseen lists in a way which is "similar" to rankings in the training data in some sense.”
排序学习是机器学习在信息检索系统里的应用,其目标是构建一个排序模型用于对列表进行排序。排序学习的典型应用包括搜索列表、推荐列表和广告列表等等。
列表排序的目标是对多个条目进行排序,这就意味着它的目标值是有结构的。与单值回归和单值分类相比,结构化目标要求解决两个被广泛提起的概念: 列表评价指标 列表训练算法
列表评价指标
以关键词搜索返回文章列表为例,这里先分析一下列表评价指标要解决什么挑战。 第一个挑战就是定义文章与关键词之间的相关度,这决定了一篇文章在列表中的位置,相关度越高排序就应该越靠前。 第二个挑战是当列表中某些文章没有排在正确的位置时候,如何给整个列表打分。举个例子来说,假如对于某个关键词,按照相关性的高低正确排序,文档1、2、3、4、5应该依次排在前5位。现在的挑战就是,如何评估“2,1,3,4,5”和“1,2,5,4,3”这两个列表的优劣呢?
列表排序的评价指标体系总来的来说经历了三个阶段,分别是Precision and Recall、Discounted Cumulative Gain(DCG)和Expected Reciprocal Rank(ERR)。我们逐一进行讲解。
Precision and Recall(P-R)
本评价体系通过准确率(Precision)和召回率(Recall)两个指标来共同衡量列表的排序质量。对于一个请求关键词,所有的文档被标记为相关和不相关两种。
Precision的定义如下:
Recall的定义如下:
举个列子来说,对于某个请求关键词,有200篇文章实际相关。某个排序算法只认为100篇文章是相关的,而这100篇文章里面,真正相关的文章只有80篇。按照以上定义: 准确率=80/100=0.8 召回率=80/200=0.4。
Discounted Cumulative Gain(DCG)
P-R的有两个明显缺点: 所有文章只被分为相关和不相关两档,分类显然太粗糙。 没有考虑位置因素。
DCG解决了这两个问题。对于一个关键词,所有的文档可以分为多个相关性级别,这里以rel1,rel2...来表示。文章相关性对整个列表评价指标的贡献随着位置的增加而对数衰减,位置越靠后,衰减越严重。基于DCG评价指标,列表前p个文档的评价指标定义如下:
对于排序引擎而言,不同请求的结果列表长度往往不相同。当比较不同排序引擎的综合排序性能时,不同长度请求之间的DCG指标的可比性不高。目前在工业界常用的是Normalized DCG(nDCG),它假定能够获取到某个请求的前p个位置的完美排序列表,这个完美列表的分值称为Ideal DCG(IDCG),nDCG等于DCG与IDCG比值。所以nDCG是一个在0到1之间的值。
nDCG的定义如下:
IDCG的定义如下:
|REL|代表按照相关性排序好的最多到位置p的结果列表。
Expected Reciprocal Rank(ERR)
与DCG相比,除了考虑位置衰减和允许多种相关级别(以R1,R2,R3...来表示)以外,ERR更进了一步,还考虑了排在文档之前所有文档的相关性。举个例子来说,文档A非常相关,排在第5位。如果排在前面的4个文档相关度都不高,那么文档A对列表的贡献就很大。反过来,如果前面4个文档相关度很大,已经完全解决了用户的搜索需求,用户根本就不会点击第5个位置的文档,那么文档A对列表的贡献就不大。
ERR的定义如下:
列表训练算法
做列表排序的工程师们经常听到诸如Pointwise、Pairwise和Listwise的概念。这些是什么东西呢,背后的原理又是什么呢?这里将逐一解密。
仍然以关键词搜索文章为例,排序学习算法的目标是为给定的关键词对文章列表进行排序。做为类比,假定有一个学者想要对各科学生排名进行预测。各种角色的对应关系如下:
首先我们要告诉学者每个学生的各种属性,这就像我们要告诉排序算法文档特征。对于目标值,我们却有三种方式来告诉学者: 对于每个学科,我们可以告诉学者每个学生的成绩。比较每个学生的成绩,学者当然可以算出每个学生的最终排名。这种训练方法被称为Pointwise。对于Pointwise算法,如果最终预测目标是一个实数值,就是一个回归问题。如果目标是概率预测,这就是一个分类问题,例如CTR预估。 对于每个学科,我们可以告诉学者任意两个学生的相互排名。根据学生之间排名的情况,学者也可以算出每个学生的最终排名。这种训练方法被称为Pairwise。Pairwise算法的目标是减少逆序的数量,所以是个二分类问题。 对于每个学科,我们可以直接告诉学者所有学生的整体排名。这种训练方法被称为Listwise。Listwise算法的目标往往是直接优化nDCG、ERR等评价指标。
这三种方法表面看上去有点像玩文字游戏,但是背后却是工程师和科学家们不断探索的结果。最直观的方案是Pointwise算法,例如对于广告CTR预估,在训练阶段需要标注某个文档的点击概率,这相对来说容易。Pairwise算法一个重要分支是Lambda系列,包括LambdaRank、LambdaMart等,它的核心思想是:很多时候我们很难直接计算损失函数的值,但却很容易计算损失函数梯度(Gradient)。这意味着我们很难计算整个列表的nDCG和ERR等指标,但却很容易知道某个文档应该排的更靠前还是靠后。Listwise算法往往效果最好,但是如何为每个请求对所有文档进行标注是一个巨大的挑战。
在线排序架构
典型的信息检索包含两个阶段:索引阶段和查询阶段。这两个阶段的流程以及相互关系可以用下图来表示:
索引阶段的工作是由索引器(Indexer)读取文档(Documents)构建索引(Index)。
查询阶段读取索引做为召回,然后交给Topn Retriever进行粗排,在粗排后的结果里面将前n个文档传给Reranker进行精排。这样一个召回、粗排、精排的架构最初是由Google提出来的,也被称为“Two-Phase Scheme”。
索引部分属于离线阶段,这里重点讲述在线排序阶段,即查询阶段。
三大挑战
在线排序架构主要面临三方面的挑战:特征、模型和召回。 特征挑战包括特征添加、特征算子、特征归一化、特征离散化、特征获取、特征服务治理等。 模型挑战包括基础模型完备性、级联模型、复合目标、A/B实验支持、模型热加载等。 召回挑战包括关键词召回、LBS召回、推荐召回、粗排召回等。
三大挑战内部包含了非常多更细粒度的挑战,孤立地解决每个挑战显然不是好思路。在线排序作为一个被广泛使用的架构值得采用领域模型进行统一解决。Domain-driven design(DDD)的三个原则分别是:领域聚焦、边界清晰、持续集成。
基于以上分析,我们构建了三个在线排序领域模型:召回治理、特征服务治理和在线排序分层模型。
召回治理
经典的Two-Phase Scheme架构如下图所示,查询阶段应该包含:召回、粗排和精排。但从领域架构设计的角度来讲,粗排对于精排而言也是一种召回。和基于传统的文本搜索不同,美团点评这样的O2O公司需要考虑地理位置和距离等因素,所以基于LBS的召回也是一种召回。与搜索不同,推荐召回往往基于协同过滤来完成的,例如User-Based CF和Item-Based CF。
综上所述,召回总体而言分成四大类: 关键词召回,我们采用Elasticsearch解决方案。 距离召回,我们采用K-D tree的解决方案。 粗排召回。 推荐类召回。
特征服务治理
传统的视角认为特征服务应该分为用户特征(User)、查询特征(Query)和文档特征(Doc),如下图:
这是比较纯粹的业务视角,并不满足DDD的领域架构设计思路。由于特征数量巨大,我们没有办法为每个特征设计一套方案,但是我们可以把特征进行归类,为几类特征分别设计解决方案。每类技术方案需要统一考虑性能、可用性、存储等因素。从领域视角,特征服务包含四大类: 列表类特征。一次请求要求返回实体列表特征,即多个实体,每个实体多个特征。这种特征建议采用内存列表服务,一次性返回所有请求实体的所有特征。避免多次请求,从而导致数量暴增,造成系统雪崩。 实体特征。一次请求返回单实体的多个特征。建议采用Redis、Tair等支持多级的Key-Value服务中间键提供服务。 上下文特征。包括召回静态分、城市、Query特征等。这些特征直接放在请求内存里面。 相似性特征。有些特征是通过计算个体和列表、列表和列表的相似度而得到的。建议提供单独的内存计算服务,避免这类特征的计算影响在线排序性能。本质上这是一种计算转移的设计。
在线排序分层模型
如下图所示,典型的排序流程包含六个步骤:场景分发(Scene Dispatch)、流量分配(Traffic Distribution)、召回(Recall)、特征抽取(Feature Retrieval)、预测(Prediction)、排序(Ranking)等等。
按照DDD的设计原则,我们设计了如下在线排序分层模型,包括:场景分发(Scene Dispatch)、模型分发(Model Distribution)、排序(Ranking)、特征管道(Feature Pipeline)、预测管道(Prediction Pipeline)。我们将逐一进行介绍。
场景分发(Scene Dispatch)
场景分发一般是指业务类型的分发。对于美团点评而言包括:分平台、分列表、分使用场景等。如下图所示:
模型分发(Model Distribution)
模型分发的目标是把在线流量分配给不同的实验模型,具体而言要实现三个功能: 为模型迭代提供在线流量,负责线上效果收集、验证等。 A/B测试,确保不同模型之间流量的稳定、独立和互斥、确保效果归属唯一。 确保与其他层的实验流量的正交性。
流量的定义是模型分发的一个基础问题。典型的流量包括:访问、用户和设备。
如何让一个流量稳定地映射到特定模型上面,流量之间是否有级别?这些是模型分发需要重点解决的问题。
流量分桶原理
采用如下步骤将流量分配到具体模型上面去: 把所有流量分成N个桶。 每个具体的流量Hash到某个桶里面去。 给每个模型一定的配额,也就是每个策略模型占据对应比例的流量桶。 所有策略模型流量配额总和为100%。 当流量和模型落到同一个桶的时候,该模型拥有该流量。
举个例子来说,如上图所示,所有流量分为32个桶,A、B、C三个模型分别拥有37.5%、25%和37.5%的配额。对应的,A、B、C应该占据12、8和12个桶。
为了确保模型和流量的正交性,模型和流量的Hash Key采用不同的前缀。
流量分级
每个团队的模型分级策略并不相同,这里只给出一个建议模型流量分级: 基线流量。本流量用于与其他流量进行对比,以确定新模型的效果是否高于基准线,低于基准线的模型要快速下线。另外,主力流量相对基线流量的效果提升也是衡量算法团队贡献的重要指标。 实验流量。该流量主要用于新实验模型。该流量大小设计要注意两点:第一不能太大而伤害线上效果;第二不能太小,流量太小会导致方差太大,不利于做正确的效果判断。 潜力流量。如果实验流量在一定周期内效果比较好,可以升级到潜力流量。潜力流量主要是要解决实验流量方差大带来的问题。 主力流量。主力流量只有一个,即稳定运行效果最好的流量。如果某个潜力流量长期好于其他潜力流量和主力流量,就可以考虑把这个潜力流量升级为主力流量。
做实验的过程中,需要避免新实验流量对老模型流量的冲击。流量群体对于新模型会有一定的适应期,而适应期相对于稳定期的效果一般会差一点。如果因为新实验的上线而导致整个流量群体的模型都更改了,从统计学的角度讲,模型之间的对比关系没有变化。但这可能会影响整个大盘的效果,成本很高。
为了解决这个问题,我们的流量分桶模型优先为模型列表前面的模型分配流量,实验模型尽量放在列表尾端。这样实验模型的频繁上下线不影响主力和潜力流量的用户群体。当然当发生模型流量升级的时候,很多流量用户的服务模型都会更改。这种情况并不是问题,因为一方面我们在尝试让更多用户使用更好的模型,另一方面固定让一部分用户长期使用实验流量也是不公平的事情。
排序(Ranking)
排序模块是特征模块和预测模块的容器,它的主要职责如下: 获取所有列表实体进行预测所需特征。 将特征交给预测模块进行预测。 对所有列表实体按照预测值进行排序。
特征管道(Feature Pipeline)
特征管道包含特征模型(Feature Model)、表达式(Expression)、原子特征(Atomic Feature)、 特征服务代理(Feature Proxy)、特征服务(Feature Service)。如下图所示:
特征管道要解决两个核心问题: 给定特征名获取对应特征值。这个过程很复杂,要完成特征名->特征服务->特征类->特征值的转化过程。 特征算子问题。模型使用的特征往往是对多个原子特征进行复合运算后的结果。另外,特征离散化、归一化也是特征算子需要解决的问题。
完整的特征获取流程如下图所示,具体的流程如下: Ranking模块从FeatureModel里面读取所有的原始特征名。 Ranking将所有的原始特征名交给Feature Proxy。 Feature Proxy根据特征名的标识去调用对应的Feature Service,并将原始特征值返回给Ranking模块。 Ranking模块通过Expression将原始特征转化成复合特征。 Ranking模块将所有特征交给级联模型做进一步的转换。
特征模型(Feature Model)
我们把所有与特征获取和特征算子的相关信息都放在一个类里面,这个类就是FeatureModel,定义如下: //包含特征获取和特征算子计算所需的meta信息 public class FeatureModel { //这是真正用在Prediction里面的特征名 private String featureName; //通过表达式将多种原子特征组合成复合特征。 private IExpression expression; //这些特征名是真正交给特征服务代理(Feature Proxy)去从服务端获取特征值的特征名集合。 private Set originalFeatureNames; //用于指示特征是否需要被级联模型转换 private boolean isTransformedFeature; //是否为one-hot特征 private boolean isOneHotIdFeature; //不同one-hot特征之间往往共享相同的原始特征,这个变量>用于标识原始特征名。 private String oneHotIdKey; //表明本特征是否需要归一化 private boolean isNormalized; }
表达式(Expression)
表达式的目的是为了将多种原始特征转换成一个新特征,或者对单个原始特征进行运算符转换。我们采用前缀法表达式(Polish Notation)来表示特征算子运算。例如表达式(5-6)*7的前缀表达式为* - 5 6 7。
复合特征需要指定如下分隔符: 复合特征前缀。区别于其他类型特征,我们以“$”表示该特征为复合特征。 表达式各元素之间的分隔符,采用“_”来标识。 用“O”表示运算符前缀。 用“C”表示常数前缀。 用“V”表示变量前缀。
例如:表达式v1 + 14.2 + (2*(v2+v3)) 将被表示为 $O+_O+_Vv1_C14.2_O*_C2_O+_Vv2_Vv3
原子特征(Atomic Feature)
原子特征(或者说原始特征)包含特征名和特征值两个部分。原子特征的读取需要由4种实体类共同完成: POJO用于存储特征原始值。例如DealInfo保存了所有与Deal实体相关的特征值,包括Price、maxMealPerson、minMealPerson等等。 ScoringValue用于存储从POJO中返回的特征值。特征值包含三种基本类型,即数量型(Quantity)、序数型(Ordinal)、类别型(Categorical)。 ScoreEnum实现特征名到特征值的映射。每类原子特征对应于一个ScoreEnum类,特征名通过反射(Reflection)的方式来构建对应的ScoreEnum类。ScoreEnum类和POJO一起共同实现特征值的读取。 FeatureScoreEnumContainer用于保存一个算法模型所需所有特征的ScoreEnum。
一个典型的例子如下图所示: DealInfo是POJO类。 DealInfoScoreEnum是一个ScoreEnum基类。对应于平均用餐人数特征、价格等特征,我们定义了DIAveMealPerson和DIPrice的具体ScoreEnum类。 FeatureScoreEnumContainer用于存储某个模型的所有特征的ScoreEnum。
复杂系统设计需要充分的利用语言特性和设计模式。建议的优化点有三个: 为每个原子特征定义一个ScoreEnum类会导致类数量暴增。优化方式是ScoreEnum基类定义为Enum类型,每个具体特征类为一个枚举值,枚举值继承并实现枚举类的方法。 FeatureScoreEnumContainer采用Build设计模式将一个算法模型的所需特征转换成ScoreEnum集合。 ScoreEnum从POJO类中读取具体特征值采用的是Command模式。
这里稍微介绍一下Command设计模式。Command模式的核心思想是需求方只要求拿到相关信息,不关心谁提供以及怎么提供。具体的提供方接受需求方的需求,负责将结果交给需求方。
在特征读取里面,需求方是模型,模型仅仅提供一个特征名(FeatureName),不关心怎么读取对应的特征值。具体的ScoreEnum类是具体的提供方,具体的ScoreEnum从POJO里面读取特定的特征值,并转换成ScoringValue交给模型。
特征服务代理(Feature Proxy)
特征服务代理负责远程特征获取实施,具体的过程包括: 每一大类特征或者一种特征服务有一个FeatureProxy,具体的FeatureProxy负责向特征服务发起请求并获取POJO类。 所有的FeatureProxy注册到FeatureServiceContainer类。 在具体的一次特征获取中,FeatureServiceContainer根据FeatureName的前缀负责将特征获取分配到不同的FeatureProxy类里面。 FeatureProxy根据指定的实体ID列表和特征名从特征服务中读取POJO列表。只有对应ID的指定特征名(keys)的特征值才会被赋值给POJO。这就最大限度地降低了网络读取的成本。
预测管道(Prediction Pipeline)
预测管道包含:预测(Prediction)、级联模型(Cascade Model)、表达式(Expression)、特征转换(Transform)、计分(Scoring)和原子模型(Atomic Model)。
预测(Prediction)
预测本质上是对模型的封装。它负责将每个列表实体的特征转化成模型需要的输入格式,让模型进行预测。
级联模型(Cascade Model)
我们构建级联模型主要是基于两方面的观察: 基于Facebook的《Practical Lessons from Predicting Clicks on Ads at Facebook》的Xgboost+LR以及最近很热门的Wide&Deep表明,对一些特征,特别是ID类特征通过树模型或者NN模型进行转化,把转化后的值做为特征值交给预测模型进行预测,往往会能实现更好的效果。 有些训练目标是复合目标,每个子目标需要通过不同的模型进行预测。这些子目标之间通过一个简单的表达式计算出最终的预测结果。
举例如下图所示,我们自上而下进行讲解: 该模型有UserId、CityId、UserFeature、POI等特征。 UserId和CityId特征分别通过GBDT和NN模型进行转换(Transform)。 转换后的特征和UserFeature、POI等原始特征一起交给NN和LR模型进行算分(Scoring)。 最终的预测分值通过表达式Prediction Score = α NNScore + β LRScore/(1+γ)来完成。表达式中的 α 、β和γ是事先设置好的值。
原子模型(Atomic Model)
在这里原子模型指的是一种原子计算拓扑结构,比如线性模型、树模型和网络模型。
常用的模型像Logistic Regression和Linear Regression都是线性模型。GBDT、Random Forest都是树模型。MLP、CNN、RNN都是网络模型。
这里定义的原子模型主要的目的是为了工程实施的便利。一个模型被认定为原子模型有如下两个原因: 该模型经常做为独立预测模型被使用。 该模型有比较完整的实现代码。
总结
本文总结了作者在美团点评解决到店餐饮个性化信息展示的相关经验,从算法和架构两方面进行阐述。在算法部分,文章采用通俗的例子和类比方式进行讲解,希望非算法工程师能够理解关键的算法概念。架构部分比较详细地阐述了到店餐饮的排序架构。
根据我们所掌握的知识,特征治理和召回治理的思路是一种全新的视角,这对于架构排序系统设计有很大的帮助。这种思考方式同样也适用于其他领域模型的构建。与Google提供的经典Two-Phase Scheme架构相比,在线排序分层模型提供了更细颗粒度的抽象原型。该原型细致的阐述了包括分流、A/B测试、特征获取、特征算子、级联模型等一系列经典排序架构问题。同时该原型模型由于采用了分层和层内功能聚焦的思路,所以它比较完美地体现了DDD的三大设计原则,即领域聚焦、边界清晰、持续集成。
作者简介
刘丁,曾就职于Amazon、TripAdvisor。2014年加入美团,先后负责美团推荐系统、智能筛选系统架构、美团广告系统的架构和上线、完成美团广告运营平台的搭建。目前负责到店餐饮算法策略方向,推进AI在到店餐饮各领域的应用。
参考文章:
[1]Gamma E, Helm R, Johnson R, et al. Design Patterns-Elements of Reusable Object-Oriented Software. Machinery Industry, 2003.
[2]Wikipedia, Learning to rank .
[3]Wikipedia, Machine learning .
[4]Wikipedia, Precision and recall .
[5]Wikipedia, Discounted cumulative gain .
[6]Wikipedia, Domain-driven design .
[7]Wikipedia, Elasticsearch .
[8]Wikipedia, k-d tree .
[9]百度百科, 太阳历 .
[10]百度百科, 阴历 .
[11]Xinran H, Junfeng P, Ou J, et al. Practical Lessons from Predicting Clicks on Ads at Facebook
[12]Olivier C, Donald M, Ya Z, Pierre G. Expected Reciprocal Rank for Graded Relevance
[13]Heng-Tze C, Levent K, et al. Wide & Deep Learning for Recommender Systems
人工智能
2018-12-24 11:35:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
模型一:不允许缺货,备货时间很短




模型二:不允许缺货,生产需一定时间

模型三:允许缺货,备货时间很短




模型四:允许缺货(需补足缺货)、生产需一定时间


价格有折扣的存储问题


人工智能
2018-12-15 23:10:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
  当下,人工智能(AI)似乎成了一个时髦词,几乎每家公司都声称自己使用了这项技术。然而,AI在游戏中的应用并不新鲜——甚至可以说它是“所有电子游戏的基础”。从最简单的游戏《Pong 乒乓》就在使用AI技术,AI技术创造的游戏体验一直和我们玩家相伴,早期游戏中使用的AI技术给与游戏一种不可预测性,玩家每一次进入游戏都有不同的游戏体验。
  如今,游戏中使用的人工智能比以往任何时候都更加复杂,玩家的游戏体验前所未见。开发者使用的AI工具更加强大,这让游戏更加真实同时还能简化开发过程,我们接下来讨论AI技术如何推动手机游戏的变革与手游开发进程。
  人工智能是如何进入到手机游戏开发中的
  简单来讲,人工智能是机器或软件展示智慧的一种技术。可以体现在语音识别、大数据识别和自动驾驶上。由于人工智能需要复杂的计算,因而主机游戏和PC上面的游戏引领了游戏中人工智能的发展。随着近年来,移动端手机CPU处理能力的提升,AI在智能手机上的应用也在迅速增加。同时流媒体和5G技术将原本只能在主机和PC上使用的AI技术可以在手机端应用。
  手机游戏中使用AI技术制作的游戏最好的例子是谷歌开发的虚拟现实游戏《Artie’s Adventure》,AI角色驱动的互动冒险游戏。围绕着冲浪小狗Artie,它需要你的帮助才能回到海滩,需要使用语音控制与Artie和其他新朋友交谈,协助小狗穿越洛杉矶。这是面向儿童的一款游戏,显示了手机游戏是如何融入人工智能。
  人工智能不仅仅可以提供可供互动的智能角色,还可以生成程序化的内容,例如关卡和不同的角色。这意味着随着玩家的游玩关卡可以一直在创造,这也意味着给与每个玩家不同的游戏体验。《我的世界》就是一个很好的例子,通过程序不断生成内容来保持游戏的新鲜感。
  人工智能对手游开发的影响
  对于游戏开发者来说,AI可以通过分析玩家行为来帮助开发手机游戏。这使得开发者通过分析玩家游戏行为,为他们量身定制游戏体验。Telltale Games工作室收集数据并将其作为体验的一部分。他们的游戏《行尸走肉》,展示了不同玩家的选择差别巨大。
  Telltale Games并没有提供玩家数据给AI,然后去改变游戏玩法,但它却暗示了未来的可能性。想象一个场景,当一个玩家因为某个特定关卡或解谜太难而感到沮丧时,开发人员可以检测到该场景。然后,AI可以提供一些提示来帮助玩家,同时还能让玩家获得通关的满足感。这意味着在游戏开始时,玩家不需要在简单的、普通的或困难中做出选择——游戏会根据玩家游戏技巧作出反应。
  《行尸走肉》
  不仅如此,AI也有能力调整游戏中的要素来提高游戏收入。《Game of whale》使用AI技术在最佳时间来介绍应用内购买或广告等内容。这确保了玩家游戏体验不会被打断,整体体验顺畅进行。AI工具可以帮助开发者和在合适的时间吸引玩家注意力,并且帮助开发者将普通玩家转变为付费客户。
  只是一个开始
  在未来,人工智能将改变游戏行业,开发者和玩家都会置身其中,许多行业巨头已经在提早布局。美国艺电(EA)已经创办了研发部门SEED,以此去探索未来游戏中新技术,其中包括AI。    大连好的妇科医院 mobile.bohaink.com
  纵观整个游戏行业,AI有能力自动完成那些人工密集型的任务,这样允许开发者专注于游戏开发中创造性的部分。而对于小型工作室来讲,,AI可以帮助开发者生成图形、音乐、角色等等,这使得精英小团队能够创造出更具有沉浸感和吸引力的游戏。
  从一开始,人工智能就一直是游戏的基本组成部分,而且这项技术正在迅速发展。虽然PC和主机游戏引领人工智能的发展,但情况可能会发生改变。现在手机是世界上最受欢迎的游戏平台,所以用不了多久或许将由手机来引领AI时代的游戏革命。
人工智能
2019-07-24 15:34:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
RPA和 Excel宏(Macro) 都能自动执行日常办公任务,节约时间成本,提高工作效率。那么,它们之间有何区别?

Excel宏 是什么 ?
Excel中的宏是一种记录任务的功能。它会记住一系列任务步骤,并自动重复执行相同的任务。可以说,与Excel相关的所有操作都可以通过宏实现自动化。
例如,每周一要更新在 Excel 中创建的数据,并将其绘制成图表。执行这项日常任务就可以使用“录制宏”,然后选择数据范围并在图表向导中设置图表格式。录制过一系列操作后,下次只需运行宏,就能自动执行相同的任务了。
此外,还可使用VBA(Visual Basic for Applications)编程语言创建宏,来操作Microsoft Office 产品(如 Word 和 Access)以及其他微软软件。

RPA是什么?
RPA(Robotic Process Automation),即“机器人流程自动化”。它可依据预先设定的程序,由软件机器人代替人工执行大批量、可重复性的操作任务,以实现流程自动化。
只要是电脑上的重复性、标准化操作,RPA几乎都能将其自动化,而不单单局限于 Microsoft Office 产品 。

二者区别
1、即使没有编程知识也能使用RPA
如果只是执行 Excel的基本任务, 那么不需要编程知识,单个宏按钮就可搞定。但若要自动处理更多高级任务,就必须了解和使用VBA编程语言。
RPA不需要编程知识,软件厂商一般会提供内置模板和教程。只需按步骤创建流程图,即使不懂编程也能用RPA自动执行任务。

2、 RPA可以处理大量数据
由于Excel宏在电脑上运行,因此数据处理时间取决于电脑的规格和性能。一次性处理大量数据,电脑负担重,可能会降低处理速度,实际处理的数据量较小。
而RPA适合进行大量数据处理。它可在服务器和云上运行,对电脑规格的依赖性相对较低,可快速处理大量数据(如商品信息和客户信息)。尤其适合于审查、查询、客户数据、库存确认、销售数据等需要大量数据的后台业务。

3、 RPA可以与其他系统协同工作
Excel宏 只能自动执行与Excel相关的任务。即使有VBA语言加持,也仅限于使微软产品中的操作自动化,且必须对这些软件进行修改。
相比之下,RPA的功能要比 Excel宏 强大得多。它 灵活的扩展能力可集成在任何系统上,而且“无侵入性” 。使用RPA,可跨系统跨平台自动执行更多任务,进一步提高办公效率。

了解了RPA和 Excel宏(Macro)的不同, 大家还需根据自身需求和用途来选择自动化工具。



RPA和Excel宏的区别:
RPA和Excel宏的优缺点对比:
人工智能
2019-07-24 13:16:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
  7月11日至12日,由数央网联合众多财经及大众媒体联袂打造的第八届中国财经峰会在北京举行。
  本届峰会主题为:新时代·大变局与新动力,清华大学国家金融研究院院长朱民,中国国际问题研究基金会理事会执行理事长、外交部前部长助理、前驻联合国大使、外交部前发言人沈国放,中国金融学会副秘书长、中国银行业协会原专职副会长杨再平,辉瑞中国国家经理苗天祥,盼盼食品集团总裁蔡金钗,三一集团副总裁周会东等嘉宾出席了本届峰会并作主题分享。
  作为经济领域最具影响力的思想交流平台之一,本届峰会备受瞩目,再次成为各界关注的焦点。活动共举办4场主论坛,13场主题分享与平行对话。超过1000名政商界嘉宾、学界专家和媒体代表汇聚于此,研判发展趋势,探究时代新题。
  本次第八届中国财经峰会由谱时提供全程独家图片直播服务,并获得了由峰会颁发的2019最具创新力企业奖。
  谱时图片直播CEO段毅到场参会,并接受了峰会的独家采访。段毅在采访中表示,谱时从创业初期所希望达到的目的就是能让这个产品改变整个摄影行业,要去改变一个行业无非是两点,一点是改变行业效率,一点是改变行业成本。谱时现在可以实现摄影师按下快门照片数据可以实时传到云端,通过机器学习快速处理发布到用户,把原来线下的工作流程完全搬到线上来做,整个拍摄流程从拍摄到交付,到处理整个流程都是线上化的完成,这套产品的价值能够提高影像行业的效率。    大连妇科医院排名 mobile.62671288.com
  而这套产品能够如此高效高质的出图,背后的人工智能技术是我们最终要的壁垒,谱时在平台上有数万名摄影师、修图师同时在工作,基于百万级数据量作为人工智能神经网络的训练数据,这样得出来的结果和效果是我认为在这个行业精度最高最专业的数据,这也是谱时非常重要的优势。
  谱时自创业之初至今,通过在技术上的不断创新,在服务上的不断提升,目前已签约超过3000名职业摄影师,服务地区超100个,累计拍摄照片超1亿张,营销传播展示超3亿人次,服务超5000家企业,摄影服务被广泛应用于包括活动会议(团建、年会等)、文化演出、体育赛事等在内的多个纪实摄影领域。
  目前5G时代即将到来,我们之后希望做到的一点是,通过人工智能的方式对视频进行自动化剪辑、拼接及后期处理,现在我们已经实现了基于照片内容场景的识别,在未来,只要我们提前预设好整个视频的脚本或主题,通过机器学习的方式就可以得到最终的成片,同时我们也希望可以通过更多其他方式来拍摄,例如可以支持无人机以及其他多媒体拍摄实时的处理和交付,或者可以通过VR呈现出更加现场的效果。
人工智能
2019-07-19 16:32:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
https://blog.csdn.net/weibo1230123/article/details/80506484
1.dma发送流程
1.配置DMA发送中断 - NVIC_Init
2.配置串口中断 - NVIC_Init
3.GPIO配置 - GPIO_Init
4.DMA发送配置
-DMA_Init DMA初始化
-DMA_ITConfig 开启DMA发送中断
5.串口参数初始化 - USART_Init
2.dma接收流程
1.配置串口中断 - NVIC_Init
2.GPIO配置 - GPIO_Init
3.DMA接收配置
-DMA_Init DMA初始化
4.串口参数初始化 - USART_Init
5.开启串口中断
3.DMA发送接收流程
1.配置DMA发送中断 - NVIC_Init
2.配置串口中断 - NVIC_Init
3.GPIO配置 - GPIO_Init
4.DMA发送配置
-DMA_Init DMA初始化
-DMA_ITConfig 开启DMA发送中断
3.DMA接收配置
-DMA_Init DMA初始化
4.串口参数初始化 - USART_Init
5.开启串口中断
总结:
1.DMA接收不需要中断
2.DMA发送完毕触发的是DMA发送中断,DMA接收完成触发的是串口空闲中断,都会触发一个中断标志位,可以判断一下。
人工智能
2019-07-16 22:55:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
全文共2641字,预计学习时长5分钟
图片来源: unsplash.com/@brookelark
“我们的服务以可扩展的微服务架构为基础”,“我们正准备转向微服务架构”……如果你是一名开发人员,肯定经常听到上面两句话。但不少人都会很困惑——微服务架构到底是个啥?别担心!本指南会用现实生活中的例子让你深刻理解微服务架构——比如,7岁的小朋友都能听懂的冰淇淋的例子!
一个大型冰淇淋机——一体化架构
我们暂时先把微服务架构放到一边,回想一下冰淇淋机的四个部分——冰淇淋勺、坚果粉碎机、巧克力漏斗和草莓糖浆漏斗。冰激凌勺的作用是将一勺香草/芒果冰激凌舀到杯子里,坚果粉碎机顾名思义就是将碎坚果撒在舀出的冰激凌上。而巧克力或草莓漏斗的作用就是把美味的糖浆撒到冰淇淋上。可以看出,整个冰淇淋机里勺以外的配料部分都是顾客可以自由选择的。
大型冰淇淋机——一体化构架的应用
现在假设你是冰淇淋店老板,冰淇淋机虽小但五脏俱全,所有的部分都浓缩到一台机器里。幸运的是,顾客非常喜欢你的冰淇淋,生意越做越大。你会怎么做呢?你会买一个更大的冰淇淋机,可以在一定时间内完成更多的冰淇淋订单。一段时间后,你会发现别无选择了,因为机器制造公司造不出更大的冰淇淋机了。
没有更大的冰淇淋机了——扩展性达到极
这就是开发界所说的一体化架构。一开始的应用程序将所有不同的部分合并到一个代码库中。随着资源需求的增加,你会租用更大的机器,但在某个时间点之后,你已经拥有了当前最大的机器,此时就会达到极限。
多买几个(一体化)冰淇淋机
你肯定会想,可以多买几台冰淇淋机解决这个问题。没错!所以你决定不买最大的冰淇淋机了,而是多买几个小的。
这就是所谓的复制,即用多个应用程序来满足用户的需求。
现在,有了老天的眷顾和你的努力,人们越来越喜欢你的冰淇淋了。为了满足顾客需求,你最终还是得把所有的冰淇淋机都升级到最大的型号。
一体化应用程序的多个实例——复制
修理坏掉的机器
当你刚刚开始生意时,雇用了一名技术人员,负责修理或升级机器。一切都很顺利。但是买了多台冰淇淋机后,你觉得需要雇用更多的技术人员,因为你也不想让顾客吃不到冰淇淋。
现在根据顾客的需求,你决定销售一种新口味的冰淇淋:在冰淇淋勺里加入巧克力味冰淇淋。但是,由于每台机器的四个部分都相互依赖,技术人员很难添加新口味的冰淇淋。但通过某种方法技术人员成功了,不过新口味的冰淇淋一加进去,草莓漏斗就停止工作了,因为冰淇淋机的每个部分都是相互依赖的,修改一个部分就破坏了另一个部分。
一个更新破坏了其他部分——黄色代表巧
每台机器只有一个用途——微服务架构
由于扩展性的限制,你决定建立一个新的冰淇淋机结构。你要求机器制造商公司提供四台机器,一台只负责一个部分。一台冰淇淋勺机,一台坚果粉碎机,巧克力和草莓糖浆漏斗机各一台。现在,你将技术人员分配到独立的团队中,每个团队只负责一台机器。
将大型机器、团队分离成独立的零部件机器和各自的技术团队——微服务架构
这就是微服务架构,其中一个大的一体化应用程序被划分为独立的模块,每个模块又是一个单独的应用程序,专门执行特定的任务。
一体化架构VS微服务架构
· 可扩展性:你可能已经注意到了,在购买了最大的冰淇淋机之后,就不能再扩大规模了。而把大型机器划分为多个零部件机器(微服务架构)后,还可以继续为单个零部件机器设立多个微服务机器。
· 维护:由于在一体化冰淇淋机中每个部分都是相互依赖的,因此上述例子中,添加新的口味就会破坏草莓漏斗。例如,如果应用程序的一个模块需要更改数据库模式,那么就可能会破坏应用程序的其他部分。但是,在微服务架构中,你已经为每个零部件机器分配了独立的团队,每个团队负责维护各自的零部件机器功能,由于零部件机器的独立性避免了冲突。这种独立的开发也有助于快速发挥机器的特性,因为相较于大型组织中团体间的沟通,团队内部沟通更加迅速。
· 成本:你可能会想,虽然多个大型冰淇淋机解决了扩展性问题,但是如果只想提高冰淇淋勺的产量而非其他部分该怎么办?在一体化冰淇淋机中,每次都必须买一整台机器,但是如果你选了微服务零部件机器,可以只买多个冰淇淋勺机(复制)。这样就能节省成本,因为你可以根据该服务上的请求负荷,增减单个服务器实例的数量。
· 安装时间:由于一体化冰淇淋机集成了所有部件,只要将其放在正确的位置就能使用了。然而,微服务零部件机器在使用之前需要连接,比如在冰淇淋的例子中就需要传送带。因此,微服务需要更多的时间和专业知识来安装,因为只有每个独立的部分相互交流才能正常运行。
· 测试与部署:测试和部署一体化冰淇淋机非常困难,因为所有的部件都是相互依赖的,只有在每个部件都集成好之后,才可以进行测试和部署。然而,在微服务零部件机器中,每个零部件机器都是独立的,因此测试和部署单个部件会更加容易。
要不要一开始就使用微服务架构?
简而言之,不要!大多数专家建议,如果不需要微服务架构,那就不要用。为什么不先用一体化冰淇淋机留住客户,等到难以维护或规模无法扩大之后再用微服务架构呢?等到这个时候,再把一体化机器分解为独立的微服务零部件机器。
微服务不总是“微”型的
你可能会觉得,如果真到了为冰淇淋店准备微服务零部件机的阶段,那么这些机器肯定会变成小型的零部件机。不是的!每个微服务零部件机器本身就可以是一台大型机器,也可以是多台复制机器同时运行以满足用户需求。比如说,如果大多数顾客只喜欢原味冰淇淋,不加任何调料,那勺子机器可能有20个勺子在同时运行。
同样,微服务架构本身也可以是独立的应用程序,规模绝不小,需要大量的努力来维护和扩展。
总结
目前几家正在使用微服务架构的大型软件公司,都是从使用一体化应用程序开始的。一旦它们达到了可扩展性和可维护性的极限,它们就会将一体化机器分解为独立的部件或服务。
毫无疑问,微服务架构可以让你针对不同的服务使用不同的技术,并更好地扩展和维护机器,但所有这些都具有很大的系统开销和复杂性,需要完备的专业知识。因此,从一个结构良好的一体化冰淇淋机开始,而不是直接从微服务架构开始总是好的,省得让自己陷入“意想不到的复杂性”之中。 留言 点赞 关注
我们一起分享AI学习与发展的干货
欢迎关注全平台AI垂类自媒体 “读芯术”在这里插入图片描述
添加小编微信:dxsxbb
即可进微信交流群
人工智能
2019-07-14 19:47:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
全文共3209字,预计学习时长6分钟
不论是做软件工程师,还是当数据科学家,想找到第一份科技类工作都是一件比较有难度的事情。
毕竟,几乎所有入门级职位的岗位描述上面都要求应聘者具备两到三年的工作经验。可是怎样才能拥有一定工作经验呢?特别是那些没有实习经历、也没有软件工程工作背景的应聘者。
很多人都遇到过这种情况:可能会花费九个月的时间,发送成百上千份简历,参加数十场宣讲会,但是却连场面试的资格都没有,更别说找工作了。
然而,有些朋友却似乎一毕业就都能在大型科技公司找到六位数薪资的工作。
这到底是为什么呢?
真相是,任何一个因素都有可能帮助求职者找到第一份科技领域的工作。说到找工作,每个人都拥有不一样的技能。有的人能够从头到尾独立开发应用程序,有的人擅长撰写使用教程,有的人YouTube视频做得非常好,还有的人善于交际、有能力应付各种宣讲会。
技能组合、时机与勤奋,可以帮助你在科技领域找到第一份工作。即使要花费一年时间(这在现实中确实发生过),也不要泄气。曾经有毫无科技领域背景的求职者仅通过几篇博客文章就得到了大型科技公司的关注,这可能花费了他们九个月的时间,但他们确实成功找到了工作!
不管你是刚刚开始找第一份科技类工作,还是已经找了好几个月了,我们都希望这篇文章能够帮助你了解如何获得公司青睐,也希望能激励各位不懈努力!
目光不要只局限于科技巨头

寻找科技类工作的一大困难之处在于,似乎大多数科技领域的工作岗位都是由大型科技公司提供的,而这些公司在找实习生或者是正式工时,几乎都要求求职者具备至少三年的工作经验。
除了这些巨头,医院、保险公司、银行以及制造商等地方也都能让求职者涉足科技领域,除此之外还有初创公司(只要有薪水)和其他一些企业。的确,很多人都希望能享受在大企业工作所带来的优越感与影响力。比如如果在亚马逊上班,我们就可以向家人和朋友吹嘘自己的工作。但其实,在其他公司上班也是个不错的选择。
另外,只要求职者具备两到三年工作经验,大多数的科技公司就会开始向这些求职者发送面试邀约。因此大家要等待时机,确保自己时刻熟悉数据结构以及技术面试技巧,从而在时机到来时做好准备。
有些求职者可能从来没有想过要去和技术不沾边的公司工作。但建议大家考虑一下这种可能性。像宜家、福特这样的公司并不是人们认知中的“科技”公司,但是所有这些公司都有着非常复杂的商业流程,而这些商业流程就需要优秀的工程师们修正完善。在这些公司可能会需要从底层做起,开发公司框架,也可能没有机会拥有过高的影响力,还不能使用炫酷的新兴生产工具,但还是有机会学习,成长为优秀的工程师。人总要有所权衡,很多岗位都可以让你不断学习。
创建项目/网站/应用程序

如果你有像是游戏产品或者软件服务化产品等等有关应用程序或者网站的想法,那为什么不去着手开发呢?整合网站并将其在线上对公众开放,这能够展示出自己并不是那种只会应付面试问题的求职者。向大家展示自己所拥有的实用技能最终会使自身收益。
这里所说的网站并不是指平淡无奇的老式静态网站,而是说求职者们要真正去开发自己的网站。
花点时间,想想怎么创建一个基础的社交媒体网站。创建这种网站要建数据库、用户账户、身份验证、cookie以及内容传送,开发这些功能看上去很简单,但想做到这些就要掌握许多方面的技能。
一次就做一件事。不要妄想一夜就能设计好一个网站。一定要仔细思考整个流程,这也是准备设计类面试的一个好方法。比起在学校所学的142门课程,以及用C++开发的披萨项目,你需要用一种更加深入的方式思考。
仔细思考所有高级别的方面,同时还要顾及那些低级别的设计特点。这可以帮助求职者很好地准备面试,也可以为其带来一些乐趣。
如果有许多较小的项目,那就可以在Github上创建一个组合。许多公司都想要浏览求职者以往的作品。在被雇佣之前创建Github组合会轻松许多,因为求职者一旦被雇佣就会忙于各种支线项目,而不太可能有时间整理并分享自己的作品。
创建博客
在Wordpress、Medium或者AWS的个人Django网站等平台上创建博客。使用怎样的内容传送系统并不是很重要,重要的是要创造新内容。
写博客不能全面地展示求职者的各种技术能力,但这可以为其增加一些应聘时的谈资,还可以展示出其对科技行业的兴趣与热情!
撰写博客文章也是一种为面试做演练的好方法,可选择和标准技术性面试相关的话题作为文章主题。在此本文列出三个相关话题: 分析数据结构或算法的运行原理 展示Twitter或Uber的设计流程 讨论力扣(Leetcode)问题
这可以帮助求职者展示其软件工程以外的其他技能。
就算性格内向也要参加各种宣讲会


建议求职者偶尔去参加一下各种宣讲会,不要管自己的性格如何,也不要管自己是否已经找到工作。经常参加并受益于宣讲会的人们往往都性格外向,但这并不代表内向的人不能参加宣讲会。参加宣讲会有非常多好处:找工作、与未来的创业伙伴交谈、还可以了解其他公司的工作内容与方式。所以,请求职者一定要试着与他人多多交流。
不要去了宣讲会就在角落里一个人傻站着,然后再到处说参加宣讲会没有用。
如果没有努力和别人交流,那问题就在自己了。不要觉得每个人都有可能为求职者提供工作,事实上,还有很多人至今仍未找到工作。求职者应该大胆上前,结交新朋友,主动与他人沟通。如果在和人事经理交流时觉得这是一个不错的工作机会,那一定要记得找他要邮箱。
也就是说,目前为止,有很多求职者在写了一两篇博客文章之后,就去参加了各种宣讲会,并以自己的博客为谈资,找到了他们的第一份工作。除此之外,求职者以往开发的项目和应用程序,也同样能帮他们在宣讲会中收获工作机会。所以说,不要还没有好好尝试过,就轻易认为参加宣讲会没意义。
联系亲友,进行内推
很多公司都会接受他人推荐来招募新员工。事实上,比起直接到公司官方申请系统投递简历,通过推荐人联系到亚马逊要简单得多。
不要觉得让别人推荐是一件不好的事情。但注意,本文在这里说的是亲友。如果找完全不认识的陌生人来给自己推荐,那就有些尴尬了。
求职者应该去找一些认识的人来为自己推荐,这些人了解求职者的为人和职业道德,也知道他的性格,因此也会更愿意提供帮助。话虽如此,这些亲友能做的也只是帮求职者得到面试的机会。比如在亚马逊,应聘者不在意谁是推荐人,他们关心的是应聘者能否通过面试。所以一定要保证自己充分学习,并为面试做了充足准备。
多管齐下,所有步骤同时进行
将所有行动融合为一个策略。比如,撰写博客文章来描述自己的项目,再附加作品组合,能够方便自己在宣讲会上或是在面试中进行展示。
这么做并不能保证求职者一定能获得面试机会,但是的确有毫无科技背景的求职者全部照做后成功参加了面试!
曾经有一位来宣讲会找工作的“数据科学家”在面试后与面试官去喝咖啡,那时面试官才知道他是学英语的,并没有编程背景。考虑到有运营博客的需求,这位面试官便付钱雇他写文章。几个月后,他又去参加了另外一个宣讲会,并把他写过的这些博客文章给那里的人事经理看了,经理让他去面试,最后他通过了面试,找到了新工作。要注意,这个人是经过了好几个不同的步骤才找到工作的。他参加了两场不同的宣讲会,分别与两位面试官交谈过,也获得过撰写博客文章的机会。正是求职者的这些小行动让他们得到了自己想要的结果!
不断申请,与他人进行交流
简历投递得不到回复却还一直申请岗位是一件让人倍感压力的事情,但各位不能放弃。求职者要不断尝试申请不同公司的岗位,不要放过任何一种角色与可能,因为人们永远也不知道自己最后到底会做什么,可能会在医院工作,也可能去亚马逊上班。但是,要是一直不申请,就永远不可能有面试的机会。
不要失去希望!
真心希望这些小建议能帮助到想在科技行业找到第一份工作的求职者们。具体是什么样的岗位并不重要,最重要的是,不要失去希望。时刻关注申请的岗位、参加过的宣讲会、以及见过面的人,确保自己留下了这些人的联系方式。最后,不要失去希望,在与人们交流或联系时要保持积极的态度。
留言 点赞 关注
我们一起分享AI学习与发展的干货
欢迎关注全平台AI垂类自媒体 “读芯术”
添加小编微信:dxsxbb
即可进入微信交流群
人工智能
2019-07-13 13:00:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
去年,微软在Build大会推出一款开发者专用的深度学习视讯摄影机套件(vision AI developer kit),让开发者可以在上面执行AI推论,但前提是,只有微软Azure云端上训练过的AI或ML模型能用,其他云端环境大多不支持。因为只能在这台摄影机上跑微软的Azure IoT Edge边缘运算软件,并不能执行其他家的边缘运算软件。但在11日举行的亚洲CES活动上,我们也访问到了负责帮微软打造这台AI摄影机的台湾摄影机制造商华晶科技,该公司产品经营小组资深项目经理游志升透露,现在使用亚马逊AWS服务训练完的ML模型,开发者也能够部署到这台摄影机上执行ML推论了。也就是说,以后在AWS训练完的AI模型,直接就能透过AWS Greengrass边缘运算软件,来部署在这台摄影机上执行ML推论,不需要转换成适用Azure云端服务环境的ML模型格式就能用,让开发者可以快速部署,并在摄影机上启用执行,来进行应用的开发及测试。
微软这台深度学习摄影机自去年8~9月推出上市,直到今年5月初,华晶科技才完成对于AWS Greengrass边缘运算服务的支持,待通过AWS认证就能用。虽然该摄影机售价与AWS深度学习摄影机DeepLens相近,但游志升指出,在硬件上,因为使用了高通的AI引擎和芯片技术加速运算,透过这台深度学习相机,一次可以同时侦测40个物体,他们现场也展示了利用这台摄影机来就近侦测多人人脸和身体。不只帮微软代工深度学习摄影机,近来积极抢攻影像AI的华晶科技,另外还自行开发一个AI BOX边缘运算盒,有别于提供单台摄影机所需的AI推论执行能力,透过这台AI BOX,他表示,则是可以提供多台摄影机同样的AI推论能力,只须透过PoE以太网络,将每台摄影机拍摄下来的影像画面传到这台BOX上,就可以直接在上面做运算处理,不需要更换摄影机,就可以进行AI推论。如果在同一个区网内,他表示,目前可以支持最多4路网络摄影机,来提供近端AI影像侦测的使用。现场也展示了利用这个边缘运算盒,来进行人脸、人体轮廓的侦测,同样也支持了微软Azure IoT Edge与AWS Greengrass两大边缘运算服务。该AI BOX边缘运算盒,预计将于今年Q3上市。内文来源: http://www.ai.org.tw/map.asp
人工智能
2019-06-12 17:10:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
本示例应用场景
场景一:云桌面访问外网(internet)
云桌面(Workspace)是一种基于云计算的优于个人电脑(PC)和传统本地虚拟桌面基础设施(VDI)解决方案的桌面服务。提供和PC一样的配置(包括vCPU、GPU、内存、磁盘)以及您所熟悉的Windows操作系统,您可以像使用自己的PC一样使用Workspace。
由于云桌面创建完毕之后并没有公网IP,如需访问外网,即可通过本示例

场景二:多台ECS共享一条带宽上网
在同一vpc下的多台ECS主机,只有一台主机购买了弹性公网IP,由于很多台主机只是偶尔访问外网的需求,所以没有购买公网带宽。则也可以通过配置 squid 代理,来使没有购买公网的服务器通过已购买公网的服务器访问外网。

Squid官方简介
SQUID是支持HTTP、HTTPS、FTP等更多功能的Web缓存代理。它通过缓存和重用频繁请求的网页来减少带宽和改善响应时间.SQUID具有广泛的访问控制,并且提供了一个很好的服务器加速器。它运行在大多数可用的操作系统上,包括Windows,并在GNUGPL下获得许可。
充分利用你的互联网连接
全世界数以百计的互联网提供商使用SQUID为他们的用户提供最好的网络访问。SQUID优化客户端和服务器之间的数据流,以提高性能和缓存频繁使用的内容,以节省带宽。SQUID还可以多种方式将内容请求路由到服务器,从而构建缓存服务器层次结构,从而优化网络吞吐量。

网站内容加速与发布
成千上万的互联网网站使用Squid大幅度增加其内容传递。SQUID可以减少服务器负载,提高客户端的交付速度。SQUID也可以用于提供来自世界各地的内容-只复制正在使用的内容,而不是无效率地复制所有内容。最后,Squid的高级内容路由配置允许您构建内容集群,通过各种Web服务器路由和负载平衡请求。



前提 拥有华为云账号,并且实名认证。
注册账号参考:
https://support.huaweicloud.com/usermanual-account/zh-cn_topic_0069252244.html
实名认证参考:
https://support.huaweicloud.com/usermanual-account/zh-cn_topic_0077914254.html
2、云桌面已开通并且创建完毕,创建云桌面步骤可以参考: 创建云桌面
创建链接: https://www.huaweicloud.com/product/workspace.html ,此处不再赘述创建流程
3、云桌面的VPC与ECS 必须属于 同一 VPC ,并且处于相同的 安全组

基本环境如下:
ECS 服务器一台:
公网IP 114.116.x.x
私网IP 192.168.2.75
VPC名称 vpc_default
业务子网 subnet-2 (192.168.2.0/24)

云桌面一台:
私网IP 192.168.0.90
VPC名称 vpc_default
业务子网 subnet-1 (192.168.0.0/24)



子网如下:

Squid的安装配置
1. 检 查squid 软件包安装其情况
[root@ecs-41d0 ~]# rpm -qa|grep squid

2. 如果未安装,则使用 yum 方式安装
[root@ecs-41d0 ~]# yum -y install squid


3. 设置服务开机自启动(可选)
[root@ecs-41d0 ~]# chkconfig --level 35squid on


4.配置/etc/squid/squid.conf文件
可以先把默认的squid.conf 文件修改个名称,重新创建squid.conf配置文件
[root@ecs-41d0 ~]# mv /etc/squid/squid.conf /etc/squid/squid.conf.bak
[root@ecs-41d0 ~]# vim /etc/squid/squid.conf

配置内容示例参考:


[root@ecs-41d0 ~]# cat /etc/squid/squid.conf
http_port 192.168.2.75:3128 #根据实际情况修改,建议修改默认端口
cache_mem 64 MB
maximum_object_size 4 MB
cache_dir ufs /var/spool/squid 100 16 256
access_log /var/log/squid/access.log
acl localnet src 192.168.0.0/24 #根据实际情况修改
http_access allow localnet
http_access deny all
visible_hostname squid.taotie.dev
cache_mgr jkx@qq.com
5.初始化并 squid
[root@ecs-41d0 ~]# squid –z
[root@ecs-41d0 ~]# /etc/init.d/squid start



测试云桌面代理访问公网是否生效
打开IE 浏览器,菜单栏 > 工具 > Internet 选项 > 连接 > 局域网设置 > 代理服务器,按照以下格式设置:





如测试可以正常访问外网,说明配置成功

下面是华为云客户端浏览器截图


下面是手机端访问截图


探讨: squid默认端口为3128端口,为避免被恶意利用,请更换其他端口使用 本案例用于演示,故防火墙均属于关闭状态,后期可以增加防火墙策略 Squid方案并不是最完美的,其他工具可以考虑使用varnish 其他
购买华为云请点击立即购买
人工智能
2019-06-07 17:28:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
示例代码托管在: http://www.github.com/dashnowords/blogs
博客园地址: 《大史住在大前端》原创博文目录
华为云社区地址: 【你要的前端打怪升级指南】
【带着canvas去流浪(9)】粒子动画一. 粒子特效二. 开发中遇到的问题2.1 卡顿2.2 轨迹2.3 复位2.4 防护层2.5 二维向量类三. 实现讲解3.1 粒子类的 update 方法3.2 粒子群的绘制3.3 爆破层的仿真
一. 粒子特效
粒子特效一般指密集点阵效果,它并不是canvas独有的,这个名词更多出现在 AE , cocos2d , Unity 相关的教程中,并且提供了方便的编辑插件让使用者可以轻松地做出例如烟火,流星,光晕等等动态变化的效果,看起来非常酷炫。如果你接触过 Three.js ,会发现三维空间的点阵效果看起来更生动。粒子特效的本质还是一个逐帧动画,所以我们仍然可以使用上一节中提到的动画编程范式来实现它。本节的教程将实现下面这样一个粒子效果:
这是笔者第5个版本,看起来还挺像回事的吧,本篇中我们将逐步实现这样一个酷炫的粒子动画,也邀请你一起来看看开发过程中那些各种令人哭笑不得的问号黑人脸时刻。
二. 开发中遇到的问题
2.1 卡顿
想实现上面的动画,我们首先要做的是构建一个静态的粒子点阵,构建的过程并不复杂,无非就是 x 和 y 两个方向上以固定间距来画点。如果我们将单个粒子定义为精灵,而不是粒子群,那么按照上一节的开发范式,我们会在逐帧动画的执行函数 step 中按照如下的方式来更新粒子点阵的状态: function step(){ ... particles.map(particle=>{ particle.update(); particle.paint(); }) }
可画面在粒子点阵动起来后就变得巨卡无比,视觉体验很差。事实上,每一个精灵状态的 update( ) 方法仅仅是一些 javascript 中的计算代码,执行速度是非常快的,而 paint( ) 方法中会经历路径绘制和渲染这两个阶段才能绘制出粒子,这个过程的高频执行相对来说就会很耗时,当舞台上的元素数量较少时并不会有什么问题,但在粒子点阵这样一个大量精灵元素的场景下,就很容易达到性能饱和。而解决的方式并不复杂,粒子是平铺在画纸上的,绘制的先后次序并不会导致画面覆盖,我们可以先描绘出所有粒子的路径(一个小半径圆圈),接着再最后调用 context.stroke() 方法一次性将所有粒子的边线绘制出来,卡顿的问题立刻就解决了。就好像SPA框架中先收集变化并对新旧DOM树进行diff操作,然后集中进行DOM更新,以取代独立分散的DOM操作造成的性能损耗。
2.2 轨迹
构建完静态粒子阵列后,我希望从简单的特效还是做起,那就是鼠标移动到某个位置后,就把固定半径内所有的粒子沿径向爆炸开来,粒子将沿鼠标点和初始位置的连线运动。然而效果是上图那样的,虽然看起来还挺酷炫的,但它不是我们期望的效果。这里只是一个低级错误,就是在 step( ) 没有重绘画布, canvas 就像一张画纸,你所绘制的一切都保留在上面直到你用底色块将其覆盖然后重绘,由于基本的视觉暂留,高速的重绘就成了动画。
2.3 复位
当我们能够模拟粒子沿爆炸中心炸开的效果后,就需要考虑如何将其复位。起初笔者试图用 弹簧模型 来模拟粒子行为,但是出现的问题就如同上图那样,有一部分粒子在初始点附近做起了简谐振动,通过设置 最小复位距离 来强制复位也很难做到,如果值太小,总会出现捕获不到的点,如果值太大,又会造成复位效果失真。其实将复位点作为弹簧模型的平衡点是有问题的,因为简谐振动在过中点的时候虽然不受力,但其速度却达到最大,这就使得逐帧动画之间的位移变化很大,所以才会出现上述的 最小复位距离 很难确定的问题。
越贴近真实效果,粒子力场模型就会越复杂,如果感兴趣,你可以自行建立力场模型来进行仿真。本章的示例代码中我们采用一种简化的处理方式,就是在爆炸后,直接将粒子置于一个较远的位置,并以一个线性递减的速度来靠近其初始位置,越靠近初始位置速度就越小,当其距离小于 最小复位距离 时将其归位。
2.4 防护层
当能够实现炸开的粒子复位后,最后要实现的效果就是防护圈,你可以想象一个透明的球体被扔进水里的效果,水在外围运动却无法穿透防护进入球体。
笔者首次建模后得到效果是上图这样的,使用的模型是一个 碰撞衰减 模型,也就是将防护层当做钢体表面,当粒子在复位过程中进入防护层后,就将其速度向量进行反向,并乘以衰减系数,当其离开防护层后再重新将速度方向指向初始位置。那么这个模型有什么问题呢?其实上面的动画中已经能够看出,由于时间间隔的选择问题,粒子在两帧之间所移动的距离可能会非常大,导致粒子会突然穿透防护层;另一方面,当爆炸中心移动后,粒子复位时的速度方向和它与爆炸中心的连线可能并不重合,单纯地将速度沿原方向取反显然是失真的。
实际上在防护层边界的处理上,需要对上述模型进行一些调整。我们换个角度思考一下,假如将防护罩展开成一个平面,那么粒子的运动轨迹就变得清晰了,如果爆炸中心没有移动,那么粒子的复位其实就相当于垂直下落的,如果爆炸中心和复位中心不重合,那么总可以将小球的速度分解为沿爆炸中心径向和沿爆炸中心切向,它的运动表现就和 具有水平初速度和垂直加速度的物体遇到反弹平面 时是一致的,为了简化仿真处理,当小球即将和防护层碰撞时,可以直接将其沿爆炸中心径向的速度清零,只保留切向速度,这样当粒子碰到防护层而无法归位时,就会沿着防护层表面运动,这样粒子就不会穿透防护层了(示例代码中采用了更简化的仿真策略,下文会提及)。
2.5 二维向量类
在图形学的计算中,向量的使用频率是极高的,在计算距离或是判断点线面之间的关系等等场景中都会应用到, canvas 只是一张画布,其中的关系和距离等等都需要通过手动计算才能获得。如果不对常见的向量操作进行封装,代码中就会充斥着各种诸如用 Math.sqrt(A.x * A.x + A.y * A.y) 求模运算这种细节完全暴露的代码,不仅书写起来非常繁琐,阅读和理解的困难也很高,所以我们需要建立一个二维向量类,把向量的求模,反向,相加,相减等常见操作挂载在原型链上,这就使得代码本身更具有意义,下面给出一个常见的二维向量类的实现,你可以根据自己的需求对其进行改造,后面的示例中我们也将直接使用这个类: //二维向量类定义 Vector2 = function(x, y) { this.x = x; this.y = y; }; Vector2.prototype = { copy: function() { return new Vector2(this.x, this.y); }, length: function() { return Math.sqrt(this.x * this.x + this.y * this.y); }, sqrLength: function() { return this.x * this.x + this.y * this.y; }, normalize: function() { var inv = 1 / this.length(); return new Vector2(this.x * inv, this.y * inv); }, negate: function() { return new Vector2(-this.x, -this.y); }, add: function(v) { return new Vector2(this.x + v.x, this.y + v.y); }, subtract: function(v) { return new Vector2(this.x - v.x, this.y - v.y); }, multiply: function(f) { return new Vector2(this.x * f, this.y * f); }, divide: function(f) { var invf = 1 / f; return new Vector2(this.x * invf, this.y * invf); }, dot: function(v) { return this.x * v.x + this.y * v.y; } };
三. 实现讲解
本节中针对重点代码片段进行讲解,完整的示例代码可以从 【我的github仓库】 中获取到。
3.1 粒子类的 update 方法 /*方法中涉及到的位置相关属性都是Vector2这个向量类的实例 *所以可以调用原型链方法进行向量计算 */ update(){ let nextPos;//模拟下一次落点 const disV = this.pos0.subtract(this.pos);//当前位置到回归点的向量 const disL = disV.length();//当前位置和初始点距离 //1.计算速度(设定最小速度避免出现无限接近却无法归位的场景),并模拟下一次落点 this.velocity = disV.multiply(kv * disL < minV ? minV : kv * disL); nextPos = this.pos.add(this.velocity.multiply(dt)); //2.判断下一次落点是否和当前爆破范围保护层碰撞 const disToE = nextPos.subtract(explodeCenter); //从爆破中心指向下一次落点的向量 const disToEL = disToE.length(); const disVnext = this.pos0.subtract(nextPos);//下一次落点指向回归点的向量 const disLnext = disVnext.length(); if (disToEL < explodeR) { //2.1 如果下一次落点会落在当前爆炸中心的范围内则处理 nextPos = explodeCenter.add(disToE.normalize().multiply(explodeR * 1.05)); }else{ //2.2 如果下一次落点距离回归点小于最小回收距离则回收 if (disLnext < resetDistance ) { this.pos = this.pos0; return; } } //3.确认更新位置 this.pos = nextPos; }
上面的位置更新策略的难点在于2.1中的计算方法,也就是粒子回归途中碰到防护层表面时的处理。为了避开复杂的向量计算,示例代码中对碰撞的处理是直接改变其下一个落点的位置,而不是通过速度和受力来计算其位置,具体的做法是从当前爆炸中心向下一次落点位置连线生成向量,然后强制将当前粒子置于1.05倍半径的地方,如下图所示:
3.2 粒子群的绘制
为了节约渲染时的性能消耗,示例中对逐帧动画的模式进行了调整,先统一更新粒子状态,接着绘制所有粒子的路径,最后一次性调用 context.fill 方法将粒子渲染出来。 //绘制粒子 function paintParticles() { ctx.fillStyle = 'white'; ctx.beginPath(); for(let i = 0; i < particles.length; i++){ for(let j =0; j 3.3 爆破层的仿真
粒子是否受到爆破中心的影响相对容易判断,我们只需要计算粒子当前位置距离爆破中心的距离是否小于设定的爆破层半径即可,本例中依旧使用直接计算位移的方式来替代基于爆破冲击力的仿真,当爆破发生时将受到影响的粒子直接沿爆破中心与当前位置连线方向移动至大于爆破半径的随即位置。 //爆炸时某个点的影响 function explodePoint(p,center) { let factor= Math.random() * 10; let dis = new Vector2(p.pos.x - center.x, p.pos.y - center.y).length(); //核心点炸开 if (dis < 0.3 * explodeR) { //初始位置 p.pos = explodeCenter.add(new Vector2(p.pos.x - center.x, p.pos.y -center.y).normalize().multiply(explodeR*(1+Math.random()*6))); } else { //非核心点炸至半径附近 p.pos = explodeCenter.add(new Vector2(p.pos.x - center.x, p.pos.y -center.y).normalize().multiply(explodeR*(1+Math.random()/10))); } }
其余的部分都是一些常规的逐帧动画框架代码,实现难度并不大,本文不再赘述。
购买华为云请点击立即购买
人工智能
2019-06-07 16:33:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
  苹果全球开发者大会(WWDC)终于在万众期待中于美国东部时间2019年6月3日在加州举行,会上苹果发布了包括新版Mac Pro、ARKit3在内的多项新产品。令人稍感失落的是,苹果的5G产品和应用依然没有任何消息。
  此前,彭博曾预告苹果正在开发代号为Azul的iOS14系统,这一版本系统将全面支持5G网络和苹果全新的AR功能。现在看来这一期待又要留到明年。
  而就在同一天,“中国5G牌照本周发放”的消息被刷屏。5G这场竞赛中,中国已经遥遥领先。
  苹果在4月17日刚和纠缠数年的“老冤家”高通和解。按照双方释放的信息,高通将向苹果提供适用5G产品的芯片组,苹果5G手机推出的时间有望从之前预测的2020年,提前至今年底。
  5G和AR,这是两件看似没有关联的事苹果却在同时推进,并将两者紧密联系到一起,作为苹果未来的前进方向,不得不佩服苹果的独到眼光。5G正在重塑未来科技和商业格局,加上新生代芯片的不断推出,智能化科技正在迎来新的可能。而以AR为代表的虚拟现实技术作为最易落地的人工智能应用方向,正在成为巨头争相布局的“战略风口”。
  但在人工智能领域,混合现实(MR)是比AR更先进的技术,如果说AR是在现实的基础上增加虚拟场景,MR则彻底将虚拟和现实融合到了一起,是AR的进化版。
  早前,联合市场研究公司发布的报告显示,混合现实(MR)的全球市场价值越来越受到重视,2024年甚至更早时间,这一细分领域的市场将达到53.62亿美元,这一估计值的复合年增长率从2018年到2024年为71.6%,预计将有大量市场机会。
  MR的竞逐
  作为人工智能领域的应用,过去几年,我们见证了如何通过改变或影响物理现实的技术来增强我们的体验。其中,VR(虚拟现实)和AR(增强现实)是比较常见的两种。有人做过通俗的解释:VR是你看到的一切都是假象,它是把人的视觉和意识带入一个虚拟的世界;AR是你能分清哪个是真的、哪个是假的,它把虚拟的信息带入到现实世界中。
  MR(混合现实)则是微软在这一领域引入的新术语。微软推出的首个MR头显设备 Hololens ,它使用数字信息来增强真实环境,在计算和架构方面更为复杂,并允许用户与在真实世界中一样的方式与数字信息或对象进行交互,从而将环境变得更加丰富且更接近现实。如同美国天气网发布的这段视频,人们通过MR技术,能够看到不可能存在于真实世界的一切。
  气象预报用的MR只是很简单的应用,更复杂的包括远程医疗、军事以及航天等高科技领域。而在日常生活中,社交、远程服务等领域也会随着MR技术的应用,产生颠覆式的变化。
  据坊间分析,苹果与高通多年的专利纠纷案之所以能够得以和解,核心就在于其未来的业务规划绕不开5G芯片:一方面,其即将推出的5G手机,必须要有更先进的芯片支持,此前微软为其提供的芯片仅能支持4G;其二,苹果未来将会在MR上有大的拓展,5G毫无疑问是其中最重要的支撑。
  MR有着如此广泛的场景应用,苹果早就看在眼里。苹果多年来在人工智能领域保持着高强度的探索,其推出的ARKit,聚焦于人工智能的开发和运用。不过ARKit并没有在业界掀起太大的风浪,苹果的AR体验给人的感觉如同昙花一现。而MR却疯传已经进入苹果全力投入的新方向,苹果操作系统IOS也将于2019年正式跟MR芯片绑定,成为MROS。其中不久的将来,苹果最有可能会推出一款头戴式设备,提供混合现实(MR)体验。
  面对苹果迅速抢占C端的势头,MR概念的先驱者微软,似乎会把发展MR的精力放在了B端。微软公开信息称,其新的操作系统将和MR芯片HPU2.0绑定。
  显然,苹果、微软已经在MR领域进行了潜心布局,掌握核心技术的他们会在接下来快速落地,推陈出新。
  面对如此巨大的机遇,中国企业的“卡位”在哪里?会继续在MR领域让位于国际巨头吗?
  答案并没有那么悲观!
  4月16日,在北京举行的一场媒体发布会上,一家名为华捷艾米的公司宣布,其在3D AI/MR领域的自研芯片,即将量产下线。根据介绍,这款自研芯片包含9大核心算法,功耗低、体积小,具备了微软、苹果MR芯片的核心能力,在某些方面,该款芯片的性能甚至更有特色。这意味着,中国企业在MR领域的探索和发展,正在呈现与国际巨头齐头并进的态势。
  目前,华捷艾米已经在MR方向与国内企业合作,腾讯、京东、百度这些国内巨头都已经成为了华捷艾米合作伙伴。华捷艾米董事长李骊甚至表示,要推动3D AI/MR在2019迎来中国市场的“应用元年”。
  华捷的野心
  华捷艾米是一家成立于2014年的AI科技公司,其MR技术的研发最早可追溯到2010年。如果说苹果和微软的各种MR应用级产品和服务像是一座冰山的话,其背后所依托的强大算法和自有芯片就是冰山淹没于海水下的那90%。华捷艾米正是花了9年的时间,才把一般人都看不到的这90%的工作给完成了。
  华捷艾米研发副总裁王行介绍说:“人工智能领域最核心的技术是算法,只有恰当的算法,机器才能根据采集到的信息进行分析处理进而强化学习和深度学习,MR技术的难度也正在此。”9年里,华捷艾米只做了一件事:攻克MR领域九大核心算法,包括3D场景结构化、3D骨架算法、3D建模、3D手势识别、3D SLAM、3D物体识别、3D抠图、3人脸算法、3D音视频协同等,几乎覆盖了MR所有涉及的领域。
  “得芯片者得天下”,人工智能领域这句至理名言是华捷艾米创业多年以来一直奉行的理念。在完成算法体系后,如何芯片化成了公司最大的难题。“通用的手机平台像845、855芯片,我们都用过。但MR所有功能没法在上面跑起来。”王行介绍,骁龙845、855是高通公司研发的上两代芯片,这两种芯片可以解决原始数据成像问题,但不具备分析功能。即使能把MR功能跑起来,也基本上把所有资源占完了,其他应用基本上没法跑了。“只有自主研发的芯片,才能尽快抢占MR的新赛道。”
  此次发布的IMI2280芯片正是华捷艾米自主研发的全新品种。“IMI 2280芯片目前在做内部测试。”王行说,IMI2280芯片能集成人体识别、物体识别、环境识别,并能进行很好的本地化分析。
  在一份公司介绍材料中,华捷艾米将其在芯片上的突破,表述为“打破了微软、苹果在中国人工智能混合现实(AI/MR)领域的市场垄断”。这是一家名不见经传的公司完成的一件意义非凡的创举。
  但是华捷艾米的目标远不止于发明一款芯片这么简单。李骊就明确地表示:“虽然MR时代元年刚刚到来,但是这一技术已经展现了很大的魅力,未来将会是MR的时代。”
  目前,华捷艾米3D视觉和MR解决方案的主要应用场景包括新零售、消费电子、智能家居、智能物流、安防等。其中,最核心的赛道是AIOT和MR。现在华捷艾米跟腾讯和百度有较深度的合作,包括帮腾讯搭建更加安全的人脸支付系统;与百度合作做一些相关的标品。
  MR社交也是华捷艾米产品的方向之一,公司计划提供更多智能终端设备的应用。李骊表示:“在社交和智能家居方面,我们跟一些手机厂商和智能家居的厂商密切合作,如智能电视、投影仪、机顶盒,以及游戏机等。”    大连渤海医院 mobile.39552222.com
  还有更多可开拓的领域,华捷艾米并未透露,但从MR九大算法体系就能够看出,公司的未来目标并非现在这些应用。
  人工智能在国内如火如荼地发展着,有机构统计,获得最多投资的五大人工智能领域分别是计算机视觉、自然语言处理、私人虚拟助理、语音识别和智能机器人,其中计算机视觉(CV)是最热门的赛道,也是商汤、旷世等人工智能企业的主攻方向。
  不难发现,华捷艾米的MR技术几乎能够应用于目前所有的CV领域,包括安防、金融、硬件、营销、驾驶、医疗等。3D MR芯片的下线投产更加为MR后续的应用推广提供了动力。正如美国天气网的视频中呈现的那样,MR几乎无所不能。
  采访中李骊不断向记者表示:“微软、苹果两大巨头已抢在前面,那么剩下的人工智能企业,谁能优先拥有MR核心能力和技术,谁就能成为行业独角兽,引领MR商业热潮,颠覆整个人工智能行业。”
人工智能
2019-06-06 12:55:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
为帮助开发者们提升面试技能、有机会入职阿里, 云栖社区 特别制作了这个专辑——阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的面试真题这一次将陆续放出(面试题官方参考答案将在专辑结束后统一汇总分享, 点此进入答题并围观他人答案 )。并通过这些笔试真题开放阿里巴巴工作机会,让更多的开发者加入到阿里这个大平台。
这一次,不仅是知识的收获,还将间接地与技术大牛们做了直观的沟通,了解他们的出题思路与考察要点,并加以消化吸收,这对自己技术能力本身就是一种极大的提升。走上编程之路,不断丰富自己方能与世接轨,努力做最优秀的自己。
5月21日,我们给开发者的第28道面试题。
28.请评估一下程序的执行结果? public class SynchronousQueueQuiz { public static void main(String[] args) throws Exception { BlockingQueue queue = new SynchronousQueue<>(); System.out.print(queue.offer(1) + " "); System.out.print(queue.offer(2) + " "); System.out.print(queue.offer(3) + " "); System.out.print(queue.take() + " "); System.out.println(queue.size()); } }
• A. true true true 1 3
• B. true true true (阻塞)
• C. false false false null 0
• D. false false false (阻塞)
阿里巴巴出题专家:桃谷
阿里云中间件技术专家, Apache Dubbo PMC ,Spring Cloud Alibaba Architect,具有多年分布式以及中间件架构设计及研发经验,目前负责Apache Dubbo的研发及社区生态。
招聘职位: 阿里中间件技术人才
点击进入聚能聊答题,并围观大家的回答!
5月20日,我们给开发者的第27道面试题。
27.如何用socket编程实现ftp协议?
阿里巴巴出题专家:吴明
阿里云弹性计算创新产品Z工作室资深技术专家,2010年加入阿里云,曾负责过阿里云供应链和公有云IAAS运维团队,14年开始从0到1建立了专有云技术服务团队。目前是阿里云国产化研发负责人和弹性计算产品团队负责人。
招聘职位: 阿里云-GPU虚拟化研发高级专家
点击进入聚能聊答题,并围观大家的回答!
5月19日,我们给开发者的第26道面试题。
26.假如给你一个新产品,你将从哪些方面来保障它的质量?
阿里巴巴出题专家:晨晖
阿里云中间件技术部测试开发专家,从事软件开发和测试工作多年,在软件产品质量保障方面有较丰富的经验。擅长于自动化测试、数据库技术、自动化工具研发,并在相关领域拥有多项发明专利。
招聘职位: 中间件招聘技术人才啦
点击进入聚能聊答题,并围观大家的回答!
5月18日,我们给开发者的第25道面试题。
25.给定一个整数数组和一个整数,返回两个数组的索引,这两个索引指向的数字的加和等于指定的整数。需要最优的算法,分析算法的空间和时间复杂度。
阿里巴巴出题专家:龙欣
阿里云异构计算资深专家
,在系统和异构加速器虚拟化,性能优化,硬件芯片验证设计,异构加速器云化系统架构设计以及服务方面有超过15年的工作经验,曾在美国硅谷就职超过8年的时间,参与开发了屡获殊荣的业界第一个商用全虚拟化的GPU产品,是GPU虚拟化前端和加速协议接口设计的负责人;当下,构建了亚洲区规模最大的公共云GPU服务和FPGA云服务,目前是阿里云异构计算产品线的研发负责人。
招聘职位: 阿里云-GPU虚拟化研发高级专家
点击进入聚能聊答题,并围观大家的回答!
5月17日,我们给开发者的第22道面试题。
24.如果让你来设计一个支持数据库、NOSQL和大数据之间数据实时流动的数据流及处理的系统,你会考虑哪些问题?如何设计?
23.如果让你设计一个通用的、支持各种数据库秒级备份和恢复的系统,你会如何设计?
阿里巴巴出题专家:千震
阿里云数据库产品事业部高级技术专家,2012年加入阿里巴巴,目前负责DTS&DBS团队和研发,在阿里云提供迁移、同步和容灾的服务,支持阿里巴巴、蚂蚁、阿里云等异地多活单元化架构,曾负责阿里全球最大的HBase集群的开发和维护工作,曾先后工作于IBM、Cisco。
招聘职位: 数据库团队诚招技术人才
点击进入聚能聊答题,并围观大家的回答!
5月16日,我们给开发者的第21道面试题。
22.删除链表的倒数第N个节点
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
要求:
只允许对链表进行一次遍历。
21.最大频率栈
实现 FreqStack,模拟类似栈的数据结构的操作的一个类。
FreqStack 有两个函数:
push(int x),将整数 x 推入栈中。
pop(),它移除并返回栈中出现最频繁的元素。
如果最频繁的元素不只一个,则移除并返回最接近栈顶的元素。
示例:
push [5,7,5,7,4,5]
pop() -> 返回 5,因为 5 是出现频率最高的。
栈变成 [5,7,5,7,4]。
pop() -> 返回 7,因为 5 和 7 都是频率最高的,但 7 最接近栈顶。
栈变成 [5,7,5,4]。
pop() -> 返回 5 。
栈变成 [5,7,4]。
pop() -> 返回 4 。
栈变成 [5,7]。
阿里巴巴出题专家:屹平
阿里云视频云边缘计算高级技术专家,长期从事分布式应用网络(P2P)、音视频传输、音视频类应用等方向的设计和研发,目前聚焦在边缘网络的整体架构设计、基于边缘网络的各种业务应用的设计和研发。
招聘职位: 边缘计算团队诚招技术人才
点击进入聚能聊答题,并围观大家的回答!
5月15日,我们给开发者的第20道面试题。
20.在云计算大数据处理场景中,每天运行着成千上万的任务,每个任务都要进行IO读写。存储系统为了更好的服务,经常会保证高优先级的任务优先执行。当多个作业或用户访问存储系统时,如何保证优先级和公平性。
阿里巴巴出题专家:田磊磊
2010年加入阿里云存储团队,专注于分布式存储领域,NFS协议,数据一致性,高性能等;先后参与过分布式存储,kv系统,NFS协议相关的开发;目前为广大公共云用户提供稳定,高可靠,高可用,高性能的文件存储服务(NAS)。
招聘职位: 存储类技术岗位
点击进入聚能聊答题,并围观大家的回答!
5月14日,我们给开发者的第18~19道面试题。
19.你理解常见如阿里,和友商大数据平台的技术体系差异以及发展趋势和技术瓶颈,在存储和计算两个方面进行概述。
18.对大数据平台中的元数据管理是怎么理解的,元数据收集管理体系是怎么样的,会对大数据应用有什么样的影响。
阿里巴巴出题专家:映泉
阿里巴巴高级技术专家,在阿里云智能事业群-计算平台事业部-通用计算平台-生产力与对外输出负责人,负责阿里EB级大规模分布式数据处理平台-MaxCompute整个研发团队的生产力建设,产品发布,产品质量, 产品技术的对外输出等工作。 将阿里大数据平台旗舰产品MaxCompute以产品和技术方案输出的方式应用于数据分析、挖掘、商业智能等领域,已经形成对所有主要行业的输出覆盖并以重点产品支撑一些关键国计民生项目。所负责的领域包括产品技术输出,数据上云,计算开发者支持,部署架构演进,和更多开源系统进行融合,行业解决方案与大数据计算平台的整合,推动MaxCompute向普惠大数据发展,从而使得所有人用的起,用的上大数据计算并让数据发挥出其最大价值,为智能性社会建设做出贡献。诚招技术功底较好,对大数据技术和产品建设有热情,有推动力的优秀人才加盟。
招聘职位: MaxCompute技术岗位
点击进入聚能聊答题,并围观大家的回答!
5月13日,我们给开发者的第17道面试题。
17.请分析MaxCompute产品与分布式技术的关系、当前大数据计算平台类产品的市场现状和发展趋势。
阿里巴巴出题专家:云郎
阿里巴巴大数据计算服务MaxCompute高级产品专家,做为MaxCompute产品和运营团队带头人,和团队共同致力于提供基于阿里云的大数据计算平台,帮助企业构建云数据仓库和数据湖, 满足企业在大数据分析方面日益增长的数据量、计算量成为常态的情况下,对低成本、高性能、稳定、安全可靠和易用方面的要求,促进大数据普惠社会的实现。
招聘职位: MaxCompute高级产品专家
点击进入聚能聊答题,并围观大家的回答!
5月12日,我们给开发者的第16道面试题。
16.一颗现代处理器,每秒大概可以执行多少条简单的MOV指令,有哪些主要的影响因素?
阿里巴巴出题专家:子团
阿里云创新产品虚拟化&稳定性资深技术专家。2013年加入阿里云, 目前在负责创新平台的系统虚拟化业务, 阿里云历次虚拟化架构升级的核心贡献者之一。带领团队构建了一套性能、成本、稳定性都处于业界领先的虚拟化系统,从而完成了阿里云百万规模客户的支撑。 同时也是阿里巴巴电商、金融业务上云、SAP HANA认证等多个重大项目的虚拟化部分负责人。
招聘职位: 阿里云-GPU虚拟化研发高级专家
点击进入聚能聊答题,并围观大家的回答!
5月10日,我们给开发者的第15道面试题。
15.请计算XILINX公司VU9P芯片的算力相当于多少TOPS,给出计算过程与公式。
阿里巴巴出题专家:隐达
FPGA异构计算资深专家,2007年即作为芯片架构师,成功开发两款规模分别超过3500万门的ASIC芯片,达到了当时最先进的45nm工艺的极限。在FPGA/ASIC以及硬件设计领域有超过20年的工作经验,对于超大规模FPGA设计开发、ASIC开发与原型验证以及FPGA在数据中心中的加速价值有着深刻的理解和丰富的经验。
招聘职位: 阿里云-GPU虚拟化研发高级专家
点击进入聚能聊答题,并围观大家的回答!
5月9日,我们给开发者的第14道面试题。
14.关于并行计算的一些基本开放问题 如何定义并行计算,请分别阐述分布式内存到共享内存模式并行编程的区别和实现(例子代码)? 请使用MPI和OpenMP分别实现N个处理器对M个变量的求和? 请说明SIMD指令在循环中使用的限制?向量化优化有哪些手段? 请用Amdahl定律说明什么是并行效率以及并行算法的扩展性?并说明扩展性的性能指标和限制因素,最后请说明在共享内存计算机中,共享内存的限制?OpenMP 是怎样实现共享内存编程环境的?MPI阻塞和非阻塞读写的区别?
阿里巴巴出题专家:何万青
点击进入聚能聊答题,并围观大家的回答!
5月8日,我们给开发者的第13道面试题。
13.如何实现两金额数据相加(最多小数点两位)
阿里巴巴出题专家:御术
数据可视化高级技术专家,从 ECharts 创始人到 AntV 产品架构师、蚂蚁金服数据可视化方向负责人,多年来一直积极推进国内数据可视化技术建设,现任蚂蚁金服-平台数据技术事业群-体验技术部-平台前端技术部 Leader,带领团队维护着 Ant Design、AntV、UmiJS、Dva 等多个领域知名的开源项目,负责着蚂蚁金服核心中台应用以及蚂蚁金融科技产品的前端研发工作。
招聘职位: 资深前端研发工程师
点击进入聚能聊答题,并围观大家的回答!
5月7日,我们给开发者的第10~12道面试题。
12.有一批气象观测站,现需要获取这些站点的观测数据,并存储到Hive中。但是气象局只提供了api查询,每次只能查询单个观测点。那么如果能够方便快速地获取到所有的观测点的数据?
11.现有一批邮件需要发送给订阅顾客,且有一个集群(集群的节点数不定,会动态扩容缩容)来负责具体的邮件发送任务,如何让系统尽快地完成发送?请详述技术方案!
10.解释下为什么鹿晗发布恋情的时候,微博系统会崩溃,如何解决?!
阿里巴巴出题专家:江岚
阿里云数据技术高级技术专家,2010年毕业后加入阿里,一直在数据部门从事数据研发的工作。目前就职于数据技术产品部的数据建设平台,负责Dataphin智能建模的后台研发。
招聘职位: 阿里数据研发工程师
点击进入聚能聊答题,并围观大家的回答!
5月6日,我们给开发者的第9道面试题。
09.输入ping IP后敲回车,发包前会发生什么?
阿里巴巴出题专家:怀虎
阿里云云效平台负责人,DevOps资深专家,译有《微服务设计》。曾在ThoughtWorks任职软件交付和敏捷顾问;对持续集成、自动化测试有丰富经验;目前专注于持续交付SaaS产品的开发,提供精益需求管理、软件设计、敏捷转型相关咨询服务。
招聘职位: 阿里云研发效能研发工程师
点击进入聚能聊答题,并围观大家的回答!
5月5日,我们给开发者的第8道面试题。
08.NFS和SMB是最常见的两种NAS(Network Attached Storage)协议,当把一个文件系统同时通过NFS和SMB协议共享给多个主机访问时,以下哪些说法是错误的:(多选)
A. 不可能有这样的操作,即把一个文件系统同时通过NFS和SMB协议共享给多个主机访问。
B. 主机a的用户通过NFS协议创建的文件或者目录,另一个主机b的用户不能通过SMB协议将其删除。
C. 在同一个目录下,主机a通过NFS协议看到文件file.txt,主机b通过SMB协议也看到文件file.txt,那么它们是同一个文件。
D. 主机a通过NFS协议,以及主机b通过SMB协议,都可以通过主机端的数据缓存,提升文件访问性能。
阿里巴巴出题专家:起影
阿里云文件存储-高级技术专家,清华大学本科和研究生,电子工程系光电子和光通信专业。毕业后在两家光通信公司(Lucent和Sycamore)进行光网络产品的开发。从2011年开始进入存储行业,加入EMC2公司,主要参与文件系统的开发,六年中,参与了企业级中端产品VNX/Unity多项Block和File的特性开发。
2017年2月加入阿里云文件存储团队,参与基于KV系统的文件系统开发,以及NFS/SMB相关协议开发。
招聘职位: 阿里云存储技术专家
点击进入聚能聊答题,并围观大家的回答!
4月28日,我们给开发者的第6~7道面试题。
06. 从innodb的索引结构分析,为什么索引的key长度不能太长
07. MySQL的数据如何恢复到任意时间点
阿里巴巴出题专家:近秋
阿里云数据库产品技术部技术专家,有6年的行业从业经验。2016年加入阿里云,目前负责最流行的开源数据库MySQL在阿里云的商业化的工作。
招聘职位: 阿里云数据库技术专家
点击进入聚能聊答题,并围观大家的回答!
4月26日,我们给开发者的第5道面试题。
05.关于epoll和select的区别,哪些说法是正确的?(多选)
A.
epoll和select都是I/O多路复用的技术,都可以实现同时监听多个I/O事件的状态

B.
epoll相比select效率更高,主要是基于其操作系统支持的I/O事件通知机制,而select是基于轮询机制

C.
epoll支持水平触发和边沿触发两种模式

D.
select能并行支持I/O比较小,且无法修改
阿里巴巴出题专家:寈峰
阿里技术专家,阿里巴巴百年技术大学讲师,Apache RocketMQ Committer,Linux OpenMessaging Advisory Board Member,具有多年分布式消息系统等中间件架构设计及研发经验,对云计算及分布式系统架构有深刻理解。目前负责Apache RocketMQ的研发及社区生态。
招聘职位: 阿里云中间件技术专家
点击进入聚能聊答题,并围观大家的回答!
4月25日,我们给开发者的第2~4道面试题。
02.已知sqrt(2)约等于1.414,要求不用数学库,求sqrt(2)精确到小数点后10位
考察点: 基础算法的灵活应用能力(二分法学过数据结构的同学都知道,但不一定往这个方向考虑;如果学过数值计算的同学,应该还要能想到牛顿迭代法并解释清楚) 退出条件设计
03. 给定一个二叉搜索树(BST),找到树中第K小的节点
考察点: 基础数据结构的理解和编码能力 递归使用
示例
如下图,输入K=3, 输出节点值3
说明
保证输入的K满足1<=K<=(节点数目)
04.LRU缓存机制
设计和实现一个 LRU(最近最少使用)缓存 数据结构,使它应该支持以下操作: get 和 put 。
get(key) ‑ 如果key存在于缓存中,则获取key的value(总是正数),否则返回 ‑1。 put(key,
value) ‑ 如果key不存在,请设置或插入value。当缓存达到其容量时,它应该在插入新项目之前使
最近最少使用的项目作废。
案例:
LRUCache cache = new LRUCache( 2 / 容量 / );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 该操作,会将 key 2 作废
cache.get(2); // 返回 ‑1 (结果不存在)
cache.put(4, 4); // 该操作,会将 key 1 作废
cache.get(1); // 返回 ‑1 (结果不存在)
cache.get(3); // 返回 3
cache.get(4); // 返回 4
测试用例: s = [["put","put","get","put","get","put","get","get","get"],[[1,1],[2,2],[1],[3,3],[2],
[4,4],[1],[3],[4]]]
考察点:
对LRU实现的基本原理和数据结构的理解。
阿里巴巴出题专家:文景
阿里云CDN资深技术专家,浙大硕士,在高性能服务端产品开发、稳定性、服务质量优化及成本优化等各项功能都有10年以上的经验。在网易杭州研究院负责底层开源软件研发,国内最早核心Nginx研发人员之一,曾任tengine研发负责人,热衷于参与开源项目。
现在是CDN技术负责人,连续7年服务双11,保障整个阿里集团95%以上的流量分发稳定性。从2014年开始,从0到1构建阿里云CDN的商业化基础设施,包括点播、直播、动态、安全加速等各项产品线,阿里云CDN现在是中国用户数最多的CDN、也是国内规模最大的CDN。正在将CDN打造成互联网的基础设施,为全球用户提供接入、加速、安全的稳定服务。
招聘职位: 点此进入查看CDN大量职位并投递简历
点击进入聚能聊答题,并围观大家的回答!
4月24日,我们给开发者的第1道面试题。
01. 如何实现一个高效的单向链表逆序输出?
阿里巴巴出题专家:昀龙
阿里云弹性人工智能负责人
,带领团队研发了同时支持Tensorflow、MXNET、PyTorch、Caffe的Perseus加速框架,曾获得Dawnbench推理世界竞赛的性能第一和成本最低双料冠军。曾任阿里云弹性高性能计算、超级计算集群技术架构师,获得过多项专利,拥有10年以上AI技术研发和高性能优化经验。精通针对CPU、GPU、MIC等微架构的计算性能优化以及网络、存储等系统性能优化。曾在英特尔SSG部门工作,并获得过英特尔中国最高成就奖(ICA)。
当人工智能遇上云计算,未来不可限量,欢迎加入阿里云弹性人工智能团队。
招聘职位: 阿里云-GPU虚拟化研发高级专家
点击进入聚能聊答题,并围观大家的回答!
更多面试真题陆续放出,敬请期待!
阅读原文 ​
本文为云栖社区原创内容,未经允许不得转载。
人工智能
2019-05-27 11:49:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
中文分词是中文文本处理的一个基础步骤,也是中文人机自然语言交互的基础模块。不同于英文的是,中文句子中没有词的界限,因此在进行中文自然语言处理时,通常需要先进行分词,分词效果将直接影响词性、句法树等模块的效果。当然分词只是一个工具,场景不同,要求也不同。
在人机自然语言交互中,成熟的中文分词算法能够达到更好的自然语言处理效果,帮助计算机理解复杂的中文语言。竹间智能在构建中文自然语言对话系统时,结合语言学不断优化,训练出了一套具有较好分词效果的算法模型,为机器更好地理解中文自然语言奠定了基础。
在此,对于中文分词方案、当前分词器存在的问题,以及中文分词需要考虑的因素及相关资源,竹间智能 自然语言与深度学习小组 做了些整理和总结,希望能为大家提供一些参考。
中文分词根据实现原理和特点,主要分为以下2个类别: 基于词典分词算法
也称字符串匹配分词算法。该算法是按照一定的策略将待匹配的字符串和一个已建立好的“充分大的”词典中的词进行匹配,若找到某个词条,则说明匹配成功,识别了该词。常见的基于词典的分词算法分为以下几种:正向最大匹配法、逆向最大匹配法和双向匹配分词法等。基于词典的分词算法是应用最广泛、分词速度最快的。很长一段时间内研究者都在对基于字符串匹配方法进行优化,比如最大长度设定、字符串存储和查找方式以及对于词表的组织结构,比如采用TRIE索引树、哈希索引等。
2、基于统计的机器学习算法
这类目前常用的是算法是HMM、CRF、SVM、深度学习等算法,比如stanford、Hanlp分词工具是基于CRF算法。以CRF为例,基本思路是对汉字进行标注训练,不仅考虑了词语出现的频率,还考虑上下文,具备较好的学习能力,因此其对歧义词和未登录词的识别都具有良好的效果。
Nianwen Xue在其论文《Combining Classifiers for Chinese Word Segmentation》中首次提出对每个字符进行标注,通过机器学习算法训练分类器进行分词,在论文《Chinese word segmentation as character tagging》中较为详细地阐述了基于字标注的分词法。
常见的分词器都是使用机器学习算法和词典相结合,一方面能够提高分词准确率,另一方面能够改善领域适应性。
随着深度学习的兴起,也出现了基于神经网络的分词器,例如有人员尝试使用双向LSTM+CRF实现分词器,其本质上是序列标注,所以有通用性,命名实体识别等都可以使用该模型,据报道其分词器字符准确率可高达97.5%。算法框架的思路与论文《Neural Architectures for
Named Entity Recognition》类似,利用该框架可以实现中文分词,如下图所示:
首先对语料进行字符嵌入,将得到的特征输入给双向LSTM,然后加一个CRF就得到标注结果。
分词器当前存在问题:
目前中文分词难点主要有三个: 分词标准:比如人名,在哈工大的标准中姓和名是分开的,但在Hanlp中是合在一起的。这需要根据不同的需求制定不同的分词标准。 歧义:对同一个待切分字符串存在多个分词结果。歧义又分为组合型歧义、交集型歧义和真歧义三种类型。 组合型歧义:分词是有不同的粒度的,指某个词条中的一部分也可以切分为一个独立的词条。比如“中华人民共和国”,粗粒度的分词就是“中华人民共和国”,细粒度的分词可能是“中华/人民/共和国” 交集型歧义:在“郑州天和服装厂”中,“天和”是厂名,是一个专有词,“和服”也是一个词,它们共用了“和”字。 真歧义:本身的语法和语义都没有问题, 即便采用人工切分也会产生同样的歧义,只有通过上下文的语义环境才能给出正确的切分结果。例如:对于句子“美国会通过对台售武法案”,既可以切分成“美国/会/通过对台售武法案”,又可以切分成“美/国会/通过对台售武法案”。
一般在搜索引擎中,构建索引时和查询时会使用不同的分词算法。常用的方案是,在索引的时候使用细粒度的分词以保证召回,在查询的时候使用粗粒度的分词以保证精度。
以 下 部分分词器的简单说明:
哈工大的分词器:主页上给过调用接口,每秒请求的次数有限制。
清华大学THULAC:目前已经有Java、Python和C++版本,并且代码开源
斯坦福分词器:作为众多斯坦福自然语言处理中的一个包,目前最新版本3.7.0, Java实现的CRF算法。可以直接使用训练好的模型,也提供训练模型接口。
Hanlp分词:求解的是最短路径。优点:开源、有人维护、可以解答。原始模型用的训练语料是人民日报的语料,当然如果你有足够的语料也可以自己训练。
结巴分词工具:基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图 (DAG);采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合;对于未登录词,采用了基于汉字成词能力的 HMM 模型,使用了 Viterbi 算法。
字嵌入+Bi-LSTM+CRF分词器:本质上是序列标注,这个分词器用人民日报的80万语料,据说按照字符正确率评估标准能达到97.5%的准确率,各位感兴趣可以去看看。
ZPar分词器:新加坡科技设计大学开发的中文分词器,包括分词、词性标注和Parser,支持多语言,据说效果是公开的分词器中最好的,C++语言编写。
人工智能
2019-05-13 09:44:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
PaddleHub可以便捷地获取PaddlePaddle生态下的预训练模型,完成模型的管理和一键预测。配合使用Fine-tune API,可以基于大规模预训练模型快速完成迁移学习,让预训练模型能更好地服务于用户特定场景的应用。
模型概述
人体解析(Human Parsing)是细粒度的语义分割任务,其旨在识别像素级别的人类图像的组成部分(例如,身体部位和服装)。ACE2P通过融合底层特征,全局上下文信息和边缘细节,端到端地训练学习人体解析任务。该结构针对Intersection over Union指标进行针对性的优化学习,提升准确率。以ACE2P单人人体解析网络为基础的解决方案在CVPR2019第三届LIP挑战赛中赢得了全部三个人体解析任务的第一名。该PaddleHub Module采用ResNet101作为骨干网络,接受输入图片大小为473x473x3。

API
def segmentation(data)
用于人像分割
参数
data:dict类型,key为 image ,str类型;value为待分割的图片路径,list类型。
output_dir:生成图片的保存路径,默认为ace2p_output
返回
result:list类型,每个元素为对应输入图片的预测结果。预测结果为dict类型,有以下字段:
origin 原输入图片路径
processed 分割图片的路径。
调色板

代码与案例
import paddlehub as hub
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
#ace2p
module = hub.Module(name="ace2p")
test_img_path = "./body2.jpg"
# 预测结果展示
img = mpimg.imread(test_img_path)
plt.imshow(img)
plt.axis('off')
plt.show()
# set input dict
input_dict = {"image": [test_img_path]}
# execute predict and print the result
results = module.segmentation(data=input_dict)
for result in results:
print(result)
test_img_path = "./ace2p_output/body2_processed.png"
img = mpimg.imread(test_img_path)
plt.imshow(img)
plt.axis('off')
plt.show()
[2020-01-09 07:10:08,251] [ INFO] - Installing ace2p module
2020-01-09 07:10:08,251-INFO: Installing ace2p module
[2020-01-09 07:10:08,270] [ INFO] - Module ace2p already installed in /home/aistudio/.paddlehub/modules/ace2p
2020-01-09 07:10:08,270-INFO: Module ace2p already installed in /home/aistudio/.paddlehub/modules/ace2p

[2020-01-09 07:10:09,154] [ INFO] - 0 pretrained paramaters loaded by PaddleHub
2020-01-09 07:10:09,154-INFO: 0 pretrained paramaters loaded by PaddleHub
{'origin': './body2.jpg', 'processed': 'ace2p_output/body2_processed.png'}

In[4]
import paddlehub as hub
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
#ace2p
module = hub.Module(name="ace2p")
test_img_path = "./body1.jpg"
# 预测结果展示
img = mpimg.imread(test_img_path)
plt.imshow(img)
plt.axis('off')
plt.show()
# set input dict
input_dict = {"image": [test_img_path]}
# execute predict and print the result
results = module.segmentation(data=input_dict)
for result in results:
print(result)
test_img_path = "./ace2p_output/body1_processed.png"
img = mpimg.imread(test_img_path)
plt.imshow(img)
plt.axis('off')
plt.show()
[2020-01-09 07:12:05,461] [ INFO] - Installing ace2p module
2020-01-09 07:12:05,461-INFO: Installing ace2p module
[2020-01-09 07:12:05,499] [ INFO] - Module ace2p already installed in /home/aistudio/.paddlehub/modules/ace2p
2020-01-09 07:12:05,499-INFO: Module ace2p already installed in /home/aistudio/.paddlehub/modules/ace2p

[2020-01-09 07:12:06,441] [ INFO] - 0 pretrained paramaters loaded by PaddleHub
2020-01-09 07:12:06,441-INFO: 0 pretrained paramaters loaded by PaddleHub
{'origin': './body1.jpg', 'processed': 'ace2p_output/body1_processed.png'}

In[7]
import paddlehub as hub
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
#ace2p
module = hub.Module(name="ace2p")
test_img_path = "./body3.jpg"
# 预测结果展示
img = mpimg.imread(test_img_path)
plt.imshow(img)
plt.axis('off')
plt.show()
# set input dict
input_dict = {"image": [test_img_path]}
# execute predict and print the result
results = module.segmentation(data=input_dict)
for result in results:
print(result)
test_img_path = "./ace2p_output/body3_processed.png"
img = mpimg.imread(test_img_path)
plt.imshow(img)
plt.axis('off')
plt.show()
[2020-01-09 07:13:10,483] [ INFO] - Installing ace2p module
2020-01-09 07:13:10,483-INFO: Installing ace2p module
[2020-01-09 07:13:10,502] [ INFO] - Module ace2p already installed in /home/aistudio/.paddlehub/modules/ace2p
2020-01-09 07:13:10,502-INFO: Module ace2p already installed in /home/aistudio/.paddlehub/modules/ace2p

[2020-01-09 07:13:11,395] [ INFO] - 0 pretrained paramaters loaded by PaddleHub
2020-01-09 07:13:11,395-INFO: 0 pretrained paramaters loaded by PaddleHub
{'origin': './body3.jpg', 'processed': 'ace2p_output/body3_processed.png'}

人工智能
2020-01-10 09:19:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
我们都看过了类似的电影:机器人在这个世界上占据了统治地位。而且,尽管这些类型的电影让我们生活了一个半小时的替代现实,但总有一种不安的想法告诉我们,这实际上可能会在不远的将来发生。
不过,机器人及其驱动的人工智能(AI)并不是一个新概念。 实际上,“人工智能之父”艾伦·图灵(Alan Turing)在1950年代就开始对它嗤之以鼻。 他开发了图灵测试,让评委向机器和人问问题。然后,评委猜测谁才是人类,并且,如果计算机至少在一半的时间内愚弄了评委,则认为它是聪明的。
如今,得益于技术的惊人发展(你好“智能家居”和“智能服装”),人工智能的世界已经发展了很多。但是,它仍然是一个相对较新的研究领域,处于不断变化的状态,并且科学家正在尝试设计出他们可以想到的最佳创新。
基本上,这意味着我们不必担心机械人正在占领整个世界。而且,由于该领域仍然很新鲜,因此该行业中某些术语的定义是不稳定的,并且会不断变化。
例如,虽然我们确实对这两个术语之间的区别有了更好的理解(并且不仅仅是一个附加字母),但一遍又一遍地定义和重新定义了诸如AI和AGI之类的术语。
什么是人工智能(AI)?
当你想到人工智能一词时,你可能会想到诸如《星球大战》中的C-3PO之类的人物,甚至可能是可爱的皮克斯机器人Wall-E。我希望你现在摆脱这些固定式思维图像。因为,尽管好莱坞可能会在你想到AI时让你想到这些机械人物,但这并不完全准确。
实际上,人工智能实际上只是指可以复制人类认知能力的机器-在这里思考诸如解决问题和学习之类的事情。但是这里有一个关键:人必须首先对机器进行编程,以便它可以从过去的模式中学习以创建新信息或解决问题。
以国际象棋为例。一个人将不得不输入有关不同国际象棋动作的数据,然后机器将使用该信息来形成数据驱动的选择,但这就是它所能做的。例如,你无法获取它来分析医学数据,因为该信息不会被编程。
人工智能基本上提供了一种自动的方式来执行人类已经可以执行的任务,但是你无需动用人力来筛选大量数据,而是可以使机器更快地完成任务,同时节省宝贵的时间。简而言之,AI功能是预先编程的。
这就是为什么企业主开始实施AI创新以简化其潜在客户生成流程,客户旅程和付款方式的原因(事实上,超过72%的企业领导者认为AI开发将是其未来成功的重要组成部分)。
什么是通用人工智能(AGI)?
尽管AI被预先编程以执行人类可以但更有效的任务,但是人工智能(AGI)期望机器与人类一样智能。这是我们在大片电影中经常看到的那种AI。
基本上,AGI机器在各个方面都将与人类一样智能,并且能够以相同(或更佳)的成功执行相同的智力任务。
苹果联合创始人史蒂夫·沃兹尼亚克(Steve Wozniak)创建了一项名为“咖啡测试”的任务,该任务有助于确定机器是否为AGI。 它涉及机器人在没有任何特定的预编程帮助的情况下进入房屋并煮咖啡。它必须寻找所需的物品,弄清楚如何使用它们,然后以与人类相同的质量执行任务。 能够做到这一点的机器将被视为AGI的典范。
你知道这与AI有何不同,对吗?
一台AI机器可能能够共享最适量的咖啡,以根据数据制作出最好的杯子,或者按颜色对杯子进行排序,但它无法执行过程的每个步骤。因此,尽管AI机器需要预先编程的数据才能执行由该数据驱动的特定任务, 但AGI的能力与人类一样。
例如,你可以使用未经培训的,未经编程的AGI机器,并教它进行几乎所有的事情,无论是下棋,当医生还是解决犯罪–这一切都是可能的,而无需编程所涉及的知识 在执行任何这些任务中。
到2030年,我们将拥有机器人仆人?
机器人仆人的未来是否在我们眼前?我们能在不久的将来看到带有AGI服务者、商店服务员和礼宾服务的城市吗?
如果AGI机器实际上可以做人类可以做的任何事情,那么这肯定是技术进步的下一个逻辑步骤吗?
在此之前,AI和AGI确实会怀疑我们是否会以单纯的人类方式继续发展,变化和进步。
如何学习AI和开发AI应用? 钛灵AIX是一款集计算机视觉与智能语音交互两大核心功能为一体的迷你人工智能硬件,搭载专业级AI加速计算芯片与多种传感器。钛灵AIX 内置 Model Play 人工智能模型平台 ,各类场景应用AI模型下载即用,极大简化从想法到原型再拓展成完整产品开发过程。
日本领先的AGI研究人员之一山川弘(Hiroshi Yamakawa)博士似乎是这样认为的:“我认为它有可能很快发生,”他说。 “但以平均估计的参与人员数量,我们得出了2030年的数据。”根据这个预测,我们只有十年了。
人工智能
2019-12-23 15:21:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
传感器在人工智能领域的应用很广泛,通过智能传感器将人机连接起来,并结合软件和大数据分析,可以突破物理和材料科学的局限性。下面工采网小编和大家一起来看看传感器未来的发展方向如何?

近年来,国内外传感器机构和技术研究与开发的投入不断增加,传感器技术也取得了飞速的进步。随着传感器技术的不断发展,新型高性能的传感器应用成本将不断降低,应用效果将不断提高,从而带动传感器行业的可持续发展。

通过传感器使得智慧城市建设不断促进公共基础设施和服务体系的完善,有效地聚集资金、人力以及社会各类资源发挥产业带动效应;以重点领域为突破口,瞄准市场需求广、领域带动效果明显的惯性传感器、环境传感器等产品进行重点投入,鼓励企业并购重组,加快进军高端传感器市场;加快建立并落实信息安全保障体制,加强信息保护技术研发,建立安全风险等级评估体系。

因此作为整个物联网的末端,传感器具有最大的潜在需求。国内传感器行业对进口的巨大依赖已成为中国物联网发展的瓶颈。只有国内企业实现传感器的国产化才能提升整个产业的整体实力,才能实现加快物联网产业的飞速发展。

特别是在国家大力加强传感器开发和应用的一系列政策的指导和支持下,中国传感器产业有着良好的发展前景,并有望获得未来的增长空间。许多公司积极构建物联网和传感器共同发展的生态环境,依靠移动互联网,积极整合产业链的所有环节,引导消费者参与,拉近产品与市场的距离。

未来传感器将朝着高性能、低成本、低功耗技术水平发展。关键技术包括新材料新功能传感器、单芯片集成传感器和微处理系统的MEMS芯片、支持微处理器信息处理和存储的智能化传感器、适应各类特殊环境的高精度传感器等技术。今后,随着CAD技术、MEMS技术、信息理论及数据分析算法的继续向前发展,未来的传感器系统必将变得更加微型化、综合化、多功能化、智能化和系统化。
人工智能
2019-12-19 15:44:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
  在实施任何新技术之前,最好对优点和缺点进行彻底的分析总是一件好事,这尤其适用于 RPA。Robotics Process Automation 主要帮助企业业务流程自动化。虽然在使用 RPA 之后,企业与员工都会有很大的方便;但是万事开头难,RPA 的部署与开发前期会面临种种挑战。有些是来自员工自身的,还有些是来自企业不合理的逾期与要求,比如:让 RPA 从事一些需要高分析、高智能的工作。现阶段,RPA 还不能胜任这些工作,只能替代一些高机械化、该频率的工作流程。下面 RPA 小编就给大家简单的讲讲 使用 RPA 时会遇到哪些挑战 ?希望对大家能够够正确使用 RPA 有帮助。
   员工不理智的抵制
  组织中涉及引入新技术的所有变更可能会对公司员工造成压力,因为它们可能是职责上的变更。高层管理人员和公司领导层定期进行持续的沟通,可以使上述员工了解“管理期望”和实施的长期计划,从而克服这一障碍。在企业内部鼓励创新的工作文化肯定会加速新技术的采用。
   选择正确的业务流程
  RPA 的最佳用途,用于基于规则的大量工作,不需要较高程度的认知能力。这可以包括从复制粘贴活动到数据迁移的所有内容。当考虑非标准化的过程并且需要定期的人工输入来执行时,RPA 的实施很困难。这种复杂的任务通常涉及与客户进行实时交互以及掌握人际关系和交互。公司必须明智地决定企业的哪些方面需要 RPA,以便自动化能够平稳运行。推荐阅读: RPA 应用较多的行业
   设定符合现实的期望
  实施 RPA 之类的新技术时,最大的障碍是要实现切合实际的目标并消除那些没有的目标。当企业意识到 RPA 的局限性和范围并在计划实施和执行 RPA 时要牢记这一点,实施将会快得多,并且效率更高。
   克服某些突发挑战
  采用 RPA 时遇到的挑战是不可预估的,适当的规划和考虑将使企业充分利用 RPA 的力量。从整体上考虑,RPA 为企业提供的竞争优势将胜过实施过程中的所有潜在障碍,而这些障碍大多是可以解决的麻烦。大多数调查显示,机器人过程自动化是一种简单的软件技术,易于实施,并且对所投入的投资回报有很大的帮助。
免费下载试用: https://support.i-search.com.cn/
人工智能
2019-12-11 14:24:00
【围观】麒麟芯片遭打压成绝版,华为亿元投入又砸向了哪里?>>>
通过平面进行分割,代码中随机生成z=1平面上的点,修改三个点的z!=1,使用平面分割保留z=1上的点。
http://www.pointclouds.org/documentation/tutorials/planar_segmentation.php#planar-segmentation #include #include #include #include #include #include #include int main (int argc, char** argv) { pcl::PointCloud::Ptr cloud(new pcl::PointCloud); // Fill in the cloud data cloud->width = 15; cloud->height = 1; cloud->points.resize (cloud->width * cloud->height); // 随机产生z=1的平面点 for (std::size_t i = 0; i < cloud->points.size (); ++i) { cloud->points[i].x = 1024 * rand () / (RAND_MAX + 1.0f); cloud->points[i].y = 1024 * rand () / (RAND_MAX + 1.0f); cloud->points[i].z = 1.0; } // 设置其中三个点不在z=1平面上 cloud->points[0].z = 2.0; cloud->points[3].z = -2.0; cloud->points[6].z = 4.0; //创建平面模型 ax+by+cz+d=0 pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients); pcl::PointIndices::Ptr inliers (new pcl::PointIndices); // Create the segmentation object pcl::SACSegmentation seg; // Optional seg.setOptimizeCoefficients (true); // Mandatory seg.setModelType (pcl::SACMODEL_PLANE); seg.setMethodType (pcl::SAC_RANSAC); seg.setDistanceThreshold (0.01); seg.setInputCloud (cloud); seg.segment (*inliers, *coefficients); if (inliers->indices.size () == 0) { PCL_ERROR ("Could not estimate a planar model for the given dataset."); return (-1); } //[0]:a [1]:b [2]:c [3]:d std::cerr << "Model coefficients: " << coefficients->values[0] << " " << coefficients->values[1] << " " << coefficients->values[2] << " " << coefficients->values[3] << std::endl; std::cerr << "Model inliers: " << inliers->indices.size () << std::endl; for (std::size_t i = 0; i < inliers->indices.size (); ++i) std::cerr << inliers->indices[i] << " " << cloud->points[inliers->indices[i]].x << " " << cloud->points[inliers->indices[i]].y << " " << cloud->points[inliers->indices[i]].z << std::endl; return (0); }
人工智能
2019-11-28 21:58:00