数据专栏

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

科技资讯:

科技学院:

科技百科:

科技书籍:

网站大全:

软件大全:

「深度学习福利」大神带你进阶工程师,立即查看>>>
主题
消息以一种发布/订阅的方式传递。一个节点可以在一个给定的主题中发布消息。一个节点针对某个主题关注与订阅特定类型的数据。可能同时有多个节点发布或者订阅同一个主题的消息。总体上,发布者和订阅者不了解彼此的存在。

$ rostopic -h $ rostopic list -h rostopic echo [topic] rostopic type [topic]
ROS messages ( 消息)
查看消息结构 $ rosmsg show geometry_msgs/Twist
发布消息 rostopic pub [topic] [msg_type] [args]
人工智能
2018-11-14 21:16:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
【一】总述
doc2vec是指将句子、段落或者文章使用向量来表示,这样可以方便的计算句子、文章、段落的相似度。
【二】使用方法介绍
1. 预料准备 def read_corpus(fname, tokens_only=False): with open(fname, encoding="utf-8") as f: for i, line in enumerate(f): if tokens_only: yield gensim.utils.simple_preprocess(line) else: # For training data, add tags # 利用gensim进行doc2vec时,语料库是一个TaggedDocument,其包括原始语料(句子、段落、篇章) # 和对应的id(如句子id,段落id,篇章id)即语料标识 yield gensim.models.doc2vec.TaggedDocument(gensim.utils.simple_preprocess(line), [i])
2. 模型训练
方法一: def train_doc2vec2(): train_file = "E:/nlp_data/in_the_name_of_people/in_the_name_of_people.txt" train_corpus = list(read_corpus(train_file)) model = gensim.models.doc2vec.Doc2Vec(documents=train_corpus,vector_size=50, min_count=2, epochs=10) model.save("doc2vec2.model")
方法二: def train_doc2vec(): train_file = "E:/nlp_data/in_the_name_of_people/in_the_name_of_people.txt" train_corpus = list(read_corpus(train_file)) model = gensim.models.doc2vec.Doc2Vec(vector_size=50, min_count=2, epochs=10) model.build_vocab(train_corpus) model.train(train_corpus,total_examples=model.corpus_count,epochs = model.epochs) model.save("doc2vec.model")
3. 模型使用
3.1 推测句子、段落或者文章的向量表示 model = doc2vec.Doc2Vec.load("doc2vec.model") # 基于已有模型,来推测新文档或者句子或者段落的向量 print(model.infer_vector(["李达康是市委书记"]))
3.2 求解句子或者段落或者文章相似的内容 model = doc2vec.Doc2Vec.load("doc2vec2.model") inferred_vector = model.infer_vector(["沙瑞金是省委书记"]) # 求解句子或者段落或者文章的相似性 sims = model.docvecs.most_similar([inferred_vector], topn=3) train_file = "E:/nlp_data/in_the_name_of_people/in_the_name_of_people.txt" train_corpus = list(read_corpus(train_file)) for docid, sim in sims: print(docid) print(sim) print(train_corpus[docid])
结果如下: 1295 0.4263337254524231 TaggedDocument(['这一来', '陈清泉就撞到枪口上了', '他想保也保不住', '其实他还是想保的', '这位法院副院长人不错', '他没必要得罪', '然而', '李达康要得罪', '他有啥办法', '该查就得查了', '他不查', '李达康既可以换个人来查', '也可以查一查他', '政治斗争就是这么残酷无情', '它不以你个人的感情好恶为转移', '于是', '他代表纪委宣布了违纪事实', '最后做结论说', '有的被群众举报', '有的在网上炒得沸反盈天', '必须严肃处理', '情况就是这样'], [1295]) 1692 0.4215260446071625 TaggedDocument(['孙连城', '地站了起来', '大声说', '李达康', '我辞职'], [1692]) 281 0.41098830103874207 TaggedDocument(['估计有人通风报信了'], [281])
【三】总结
使用gensim的doc2vec进行句子、段落、文章的向量表示时,不需要进行分词。
人工智能
2018-11-14 21:13:00
「深度学习福利」大神带你进阶工程师,立即查看>>> 像人类一样可以思考,可以创造的人工智能会出现吗?
个人认为:会出现。但是出现的时间,取决了于硬件架构,和运算架构实现的时候。原因在于,人类智能可以出现,机器智能为什么不可以呢,不管是人类创造出来,还是来自于宇宙中,我认为出现只是迟早的问题。 人类如何产生的意识?
个人认为:可能理在医学,生物学界也依然未弄明白,但随着科技的进步,我这是早晚的事情。人类大脑中构成的运算架构也依然是个迷,但是人人认为,这可能跟深度学习不谋而合,只是人类大脑的运算架构更通用,而我们现在研究的深度学习计算架构才开始起步而已(相对于人脑) 人类对世界的认知,是产生意识的源头。
个人认为,人类对世界的认知对产生意识的源头,就如新生的孩子,你如果不让看,不让他听,不让它感受,那他也只有动物最原始的本能。 正是因为对世界的感知,视,听,觉,才致于学,其实也就是深度学习,只是人类大脑的运算架构学习效率更高,我觉得这主要得益于大脑本对于感知的抽像能力更强,就如类似于hash算法,只不这,大脑的hash算法,比我们现在所应用于的高级太多。 我们都知道,我们观察一个东西,没有没办将它重现出来,是这因为,大脑将我们观察到的信息,抽象成了感觉,丢失了一些细节 ,但是我们确可以凭感觉和反馈来重现一些场景,如绘画,我们没法闭上眼就真切的提取出某种我们看到的东西,只能想象出大概模样,对比作画,不断加强与感觉的比对,可以重现出基本一样的东西。 也许宇宙中还有更高级的抽象算法,只是我们现的知识和理解水平还达不到,我们科学家还没有发明这种,或以从观察中提取感觉的算法,然后再将感受在类大脑运算架构中持久化,那离我们创造通用人工智能的距离可能就不远了。
人工智能
2018-11-14 18:58:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
Archlinux执行以下指令 $ sudo pacman -S cmake
Ubuntu执行以下指令 $ sudo apt-get install cmake
CentOS或基于CentOS的执行 $ sudo yum install cmake
Windows 安装cmake 官网下载安装包: https://cmake.org/download 安装boost 官网下载下载: http://www.boost.org 执行 bootstrap.bat 执行 b2 install b2编译库文件 (之前你cmake下载的64位这里写64,如果是32位的就把之前的64改成32) b2 -a --with-python address-model=64 toolset=msvc runtime-link=static 设置变量 set BOOST_ROOT=D:\Tools\boost set BOOST_LIBRARYDIR=D:\Tools\boost\stage\lib
人工智能
2018-11-14 14:34:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
【一】整体流程综述
gensim底层封装了Google的Word2Vec的c接口,借此实现了word2vec。使用gensim接口非常方便,整体流程如下:
1. 数据预处理(分词后的数据)
2. 数据读取
3.模型定义与训练
4.模型保存与加载
5.模型使用(相似度计算,词向量获取)
【二】gensim提供的word2vec主要功能
【三】gensim接口使用示例
1. 使用jieba进行分词。
文本数据:《人民的名义》的小说原文作为语料
百度云盘:https://pan.baidu.com/s/1ggA4QwN # -*- coding:utf-8 -*- import jieba def preprocess_in_the_name_of_people(): with open("in_the_name_of_people.txt",mode='rb') as f: doc = f.read() doc_cut = jieba.cut(doc) result = ' '.join(doc_cut) result = result.encode('utf-8') with open("in_the_name_of_people_cut.txt",mode='wb') as f2: f2.write(result)
2. 使用原始text8.zip进行词向量训练 from gensim.models import word2vec # 引入日志配置 import logging logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO) def train_text8(): sent = word2vec.Text8Corpus(fname="text8") model = word2vec.Word2Vec(sentences=sent) model.save("text8.model")
注意。这里是解压后的文件,不是zip包
3. 使用Text8Corpus 接口加载数据 def train_in_the_name_of_people(): sent = word2vec.Text8Corpus(fname="in_the_name_of_people_cut.txt") model = word2vec.Word2Vec(sentences=sent) model.save("in_the_name_of_people.model")
4. 使用 LineSentence 接口加载数据 def train_line_sentence(): with open("in_the_name_of_people_cut.txt", mode='rb') as f: # 传递open的fd sent = word2vec.LineSentence(f) model = word2vec.Word2Vec(sentences=sent) model.save("line_sentnce.model")
5. 使用 PathLineSentences 接口加载数据 def train_PathLineSentences(): # 传递目录,遍历目录下的所有文件 sent = word2vec.PathLineSentences("in_the_name_of_people") model = word2vec.Word2Vec(sentences=sent) model.save("PathLineSentences.model")
6. 数据加载与训练分开 def train_left(): sent = word2vec.Text8Corpus(fname="in_the_name_of_people_cut.txt") # 定义模型 model = word2vec.Word2Vec() # 构造词典 model.build_vocab(sentences=sent) # 模型训练 model.train(sentences=sent,total_examples = model.corpus_count,epochs = model.iter) model.save("left.model")
7. 模型加载与使用 model = word2vec.Word2Vec.load("text8.model") print(model.similarity("eat","food")) print(model.similarity("cat","dog")) print(model.similarity("man","woman")) print(model.most_similar("man")) print(model.wv.most_similar(positive=['woman', 'king'], negative=['man'],topn=1)) model2 = word2vec.Word2Vec.load("in_the_name_of_people.model") print(model2.most_similar("吃饭")) print(model2.similarity("省长","省委书记")) model2 = word2vec.Word2Vec.load("line_sentnce.model") print(model2.similarity("李达康","市委书记")) top3 = model2.wv.similar_by_word(word="李达康",topn=3) print(top3) model2 = word2vec.Word2Vec.load("PathLineSentences.model") print(model2.similarity("李达康","书记")) print(model2.wv.similarity("李达康","书记")) print(model2.wv.doesnt_match(words=["李达康","高育良","赵立春"])) model = word2vec.Word2Vec.load("left.model") print(model.similarity("李达康","书记"))
结果如下: 0.5434648 0.8383337 0.7435267 [('woman', 0.7435266971588135), ('girl', 0.6460582613945007), ('creature', 0.589219868183136), ('person', 0.570125937461853), ('evil', 0.5688984990119934), ('god', 0.5465947389602661), ('boy', 0.544859766960144), ('bride', 0.5401148796081543), ('soul', 0.5365912914276123), ('stranger', 0.531282901763916)] [('queen', 0.7230167388916016)] [('只能', 0.9983761310577393), ('招待所', 0.9983713626861572), ('深深', 0.9983667135238647), ('干警', 0.9983251094818115), ('警察', 0.9983127117156982), ('公安', 0.9983105659484863), ('赵德汉', 0.9982908964157104), ('似乎', 0.9982795715332031), ('一场', 0.9982751607894897), ('才能', 0.9982657432556152)] 0.97394305 0.99191403 [('新', 0.9974302053451538), ('赵立春', 0.9974139928817749), ('谈一谈', 0.9971731901168823)] 0.91472965 0.91472965 高育良 0.88518995
8. 参考链接
https://github.com/RaRe-Technologies/gensim
https://github.com/RaRe-Technologies/gensim/blob/develop/docs/notebooks/word2vec.ipynb
人工智能
2018-11-13 22:56:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
OpenMPI的程序运行必须保持相同的目录,默认情况下,MPI的分布式节点会去~/user目录下面寻找运行的程序,如果找不到该程序,则会报出 -------------------------------------------------------------------------- mpiexec was unable to launch the specified application as it could not change to the specified working directory: Working directory: /home/norse/WorkSpace/uestc-careye/cmake-build-debug/bin Node: node1-ubuntu while attempting to start process rank 10. --------------------------------------------------------------------------
上述错误,所以必须保证运行目录一致,通过下列命令切换运行目录 mpiexec --wdir ~/WorkSpace/uestc-careye/cmake-build-debug/bin -hostfile ./hosts-list -np 3 rc_mpi_test
其他指令请 移步
人工智能
2018-11-10 00:01:00
「深度学习福利」大神带你进阶工程师,立即查看>>> “成长没有什么秘笈,就是坚持不断地一点点突破自己的边界就好。”
这是美团首席科学家、无人配送部总经理夏华夏在刚刚过去的“1024 程序员节”时送给技术同行的一句话。
这也是夏华夏自己的人生写照:从没摸过计算机的山东高考状元到清华计算机系的学霸,从美国名校深造、Google修炼6年到选择回国,从加入当时还很小的美团到负责公司最大业务的总体架构,从架构师转为无人配送这个前沿业务部门的管理者,夏华夏就是在不断突破自己的边界,做出人生的重要抉择,脚踏实地,一步步成长为业界知名的技术领军人物。 本文由美团技术学院基于夏华夏的访谈记录整理而成。
1998年,夏华夏从清华大学远赴美国留学,先后在谷歌、百度担任架构师。2013年受美团创始人王兴和穆荣均的邀请,选择加入当时还很“弱小”的美团,夏华夏回忆,是王兴的一番话让他备受触动。当时,望着五道口下面熙熙攘攘的人流,王兴说:“其实很多做互联网创业的人,很少考虑怎么去帮助这些人,这些普罗大众,这么多的小商家。其实,他们都在努力改变自己的命运,我们美团就要帮助他们,帮助这些普普通通的老百姓。这也是属于我们的机会。”
夏华夏加入美团已有5年的时间,也是一名地地道道的美团“老人”了。他当时并没有料到,如今这家小小的创业公司,已经成功在香港上市,成为市值仅次于BAT的第四大互联网企业;他当时也没有想到,这个曾经很小的技术团队已经迅速成长为一个拥有万人规模的一流研发组织;他也没有料到,5年后这家公司还会在人工智能、无人驾驶这些前沿科技领域不断开疆拓土,他也成为了无人配送项目的负责人。 2013年,美团的主要业务还是团购,夏华夏帮助整个技术团队做了很多技术层面的梳理和重构,并和早期的几位技术团队负责人一起组建了美团技术学院。 2015年,经过前期的孵化和运营,外卖业务已经初具规模,但由于基础系统建设不够牢固,导致当时的外卖系统很不稳定,每周要宕机好几次,而且好几次宕机都是发生在用餐高峰时期。临危受命,夏华夏再次被调任到外卖业务部门,帮助外卖技术团队解决了系统稳定性的问题。顶着巨大的业务压力,夏华夏和美团外卖很多技术骨干天天泡在一个被他们称之为“作战室”的大会议室里,经过了近百个不眠不休的夜晚,不断迭代升级、测试、监控整个系统。终于将系统稳定性就从98%提高到了99.9%,从而保障了外卖业务的飞速增长。美团能够成功上市,外卖团队功不可没。 2017年年底,夏华夏再次踏上了新的技术征程,他陆续交接了手中其他的工作,将全面精力放在美团无人配送项目上,并带领技术团队研发了专属于美团自己的无人车和无人机。目前夏华夏负责的美团无人配送开放平台,集合了政府、高校、企业三方力量,已经吸引包括清华大学、加州伯克利大学、北京智能车联产业创新中心、华夏幸福、Segway等近20家国内国外合作伙伴加入。
大学篇:千里之行,始于足下
对神秘事物充满好奇,误打误撞报考清华计算机专业
1993年6月,夏华夏面临人生的第一次选择——高考。“当时在小县城,几乎没有人会对专业有概念,大家只在意你考上哪所大学。”对年轻的夏华夏来说,报专业纯属瞎报,当时是看哪个专业的名字有趣就选择一个,而选择计算机是完全是“蒙的”,要知道在上世纪90年代的小县城,大家都没有见过计算机,最多只是听过这个概念。“我觉得,计算机是一个非常神秘的东西,越是神秘的东西就越有意思,对我的吸引力也更大。”夏华夏说,当时他的班主任也不知道哪个系好,在班主任看来,有学生能考上清华大学,“KPI”就完成了。所幸在高考中,夏华夏发挥出色,以山东省第一名的成绩顺利考入清华大学。
进入清华实验班,系院士领入计算机世界的大门
清华有一个实验班,入学摸底考试后,从电子类相关的专业选择了大概五十个同学有资格进入,夏华夏名列前茅。“我们很幸运,因为实验班给我们创造了很好的条件,而且可以直接向系里云集的院士泰斗(张钹、李三立、唐泽圣等老师)请益。”
不过,最开始夏华夏都不知道应该请教什么问题,因为这是他第一次跟计算机世界打交道。现在回忆起第一次上级课的情景,夏华夏记忆犹新,当时电脑配置的是386的处理器,找了老半天都不知道怎么开机,怎么进入系统。
90年代,几乎所有学编程的人都是从C语言开始。这门看起来有些古老的语言,一度耗费了夏华夏几乎全部的精力。“那个时候还不会双打,用两个指头打字,所以编程学习特别慢,现在已经很难想象那种情景了”。人生第一个应用程序,花了夏华夏整整一节课的时间,他记得很清楚,那是一个画图的程序,编译之后也没问题,但是后续检查中,发现目录里有两个没有见过的文件,“.”和“..”(DOS操作系统下的当前目录和父目录),貌似感染了“病毒”,吓得赶紧执行了一个“deltree .”的命令,试图把“病毒”删除,然后就发现整个程序都找不到了。所以夏华夏的第一个程序,其实是一个失败项目。
虽然最开始很窘迫,但一个全新的世界已经向这个懵懂的少年敞开了大门。
小试牛刀,做数据库系统挣到人生的第一桶金
当然,对刚刚接触编程世界的夏华夏来说,每个项目都会倾注很多的精力去完成,而且实验室学习气氛很好,所有同学都会把项目看得非常重要。现在,机器学习、图像识别、人工智能的概念几乎已经众人皆知了,当时还没有这么火爆,其实夏华夏很早就参与了一个人工智能相关的项目,严格来说属于图像识别范畴,项目要求识别一张图上的飞鸟的总数。这是一个难度不小的挑战,夏华夏使用了很多模型进行实践,当时也没有“模式识别”方法可以使用,后来他通过应用算法把“鸟”的边界线数出来,然后逐渐对周围进行“腐蚀”,“腐蚀”到最小的一个点,就认为这是一个“鸟”。夏华夏一直都相信,只要勤思考,肯定能找到解决问题的办法。
在那个年代,人工智能正在经历又一次的低谷期,绝大多数保送的研究生都不愿意去人工智能实验室。“其实很多时候,我们对某些事的认知,确实是受制于环境因素的。可能没有人能够想象到,二十多年后,人工智能领域的人才,已经成为了最为稀缺的资源。”夏华夏非常感叹。
后来,夏华夏又开始接触了Windows编程,做了一个非常炫酷的界面系统,被系里很多同学复制,要知道当时可视化的编程环境比如Visual C++等还没有进入中国,能够做出这种效果,在大家看来已经属于“高手”了。 所以,“钱”也开始找上门了。
对夏华夏来说,印象最深的就是大学时做的一个软件外包项目,这是一个仓库的管理查询项目,老板希望通过一个管理软件,可以将货物输入到数据库系统,能够查询货品的信息和库存信息。夏华夏当时刚刚读大二,他就利用几个月的时间,学习了编程和数据库相关的技术,然后通过各种途径学习研究,搞定了这个系统,挣到了人生第一个5000块钱。
这是夏华夏挣的人生第一笔钱,虽然现在看起并不多,但是当时在校普通学生的生活费,基本上也就是每月一两百块钱,所以绝对是一笔“巨款”。当然,清华计算机系人才济济,很多同学开始在外面写书,做各种软件,收入几千也并不特别稀奇。但这是夏华夏第一次通过计算机技术挣到了钱,意义非同一般。
做自己喜欢做的事情,进步会非常快
1993年到2000年,互联网开始在中国风起云涌,后来成为巨头的BAT都诞生在那个时代。夏华夏也触网了。他跟同年级的几个同学一起做了一个“酒井BBS”,名字源自他们住的9#男生楼的谐音。计算机系的女生住7号楼,刚好离的比较近,所以他们搭了一根线连通两个楼,让系里的男生女生可以一起聊天。
9#BBS最初是秦浩澜、卿芳慧、周霖等人带头做出来的。周霖就睡在夏华夏的上铺,他也是水木清华的BBS的站长(周霖后来曾任搜狐负责技术的高级副总裁,现在是搜狐旗下狐狸金服集团的联合创始人兼CTO)。
大学时期,夏华夏和他的同学们就接触了很多最新鲜的东西,一个全新的世界向他们敞开了怀抱。“我们开始去学习新的技术,学习网络相关的知识,这些都是兴趣驱动的,当时也没有就业压力。其实课堂上的知识带给的成长并是有限的,当你真正动手去做一些事情的时候,进步会非常快,成长也会非常大。”
夏华夏告诉我们,当时有个同学写了一款打升级的扑克游戏,后来很多年之后,发现很多扑克游戏还是基于当时他写的代码。“大学是比较单纯的,我们当时写了很多程序,大多都是因为有趣、好玩,功利性是很少的。”
不过当时,即使是顶尖的学府也没有开职业规划课,大家都是靠自己摸索。夏华夏刚读大学的时候,只想到能够保送研究生,并没有考虑太多。“我们班很多同学选择了出国,因为每个人接触的人不一样,看到的世界也不同。”夏华夏回忆说,即使是清华学习相对较差的同学,出路也都非常好,有个同学因好几门功课不及格而被推迟毕业,不得已去了一家小创业公司,这家小公司的创始人是一个海归,名字叫张朝阳,后来这位同学还成了张朝阳的重要副手。
每个人都有自己的路,关键是选择
“其实,每个人都有自己的路,出国是一种选择,保研是一种选择,工作也是一种选择,关键是看你怎么走。”夏华夏说,当时创业的人几乎没有,因为大家对互联网创业几乎是没有概念的,清华的创业协会应该是1997年左右才开始做(王兴是其中的积极分子),后续很多留学生回国创业,那已经是很多年之后了。
在大学时代,对夏华夏影响最大的一个人是研究生期间的导师郑纬民老师。夏华夏大三和大四时期就跟恩师在高性能计算所做项目,而且郑老师对最新出现的计算机技术都跟的很紧,从并行计算,到后来的分布式计算、云计算、大数据、异构计算等。夏华夏一直在学习和实践,这也为后来读博和工作打下特别好的基础。“如果不出国的话,我还准备跟郑老师读博士,后面因为一些原因决定退学出国留学,郑老师也给予很大的支持,还帮忙写了推荐信。”所以夏华夏一直到今天,都特别感谢郑老师的栽培之恩。
谷歌篇:重剑无锋,大巧不工
6年异国求学路,名师出高徒
本以为读完研究生读完博士,然后找一份稳定的工作,然后就跟大多数人一样平静的度过此生。但命运,变幻无常,夏华夏遇到了生命中最重要的一个人,他又再次踏上了未知的旅程。清华的计算机专业是五年制,夏华夏大五的下学期就认识了自己的女朋友,现在已经成了他太太。
爱情,总是在不经意间,悄然而至。夏太太是同年级的同学,本科毕业后在清华继续读两年制硕士。夏华夏当时正在读博士,因为太太想出国发展,思虑良久后他也决定退学,跟太太一起远赴大洋彼岸继续深造。“其实,从来没有考虑过会遇到自己一生的爱人,也没有想到会出国。因为入学最初的想法就是读个研究生或者博士,出国其实是一个偶然,完全不在人生的规划之中。”
加州大学圣迭戈分校(Universityof California, San Diego,简称UCSD)位于南加州拉荷亚社区,那里环境优美,气候宜人,且坐拥全美国最顶级海滩,被称之为美国“最性感”的理工科学习院校。2000年,夏华夏开启了异国他乡的的求学之路,并度过了人生中重要的6年。“我在美国读了很长时间的书,但玩得也很开心,加州可能是全美最适合居住的一个地方,一年四季都不冷不热。”
夏华夏的博士导师是知名的华裔计算机科学家Andrew A.Chien(中文名钱安达,ACM、IEEE和AAAS会士,现为芝加哥大学教授,著名技术刊物《Communications fo ACM》的主编)。在1990到1998年期间,钱安达老师在伊利诺伊大学(UIUC)任教授。1998年,钱老师转到UCSD当教授。所以夏华夏就跟随钱老师在UCSD继续做计算机相关的研究工作。钱老师研究的领域也比较广泛,后来研究的方向包括数据中心与超大规模系统架构与编程、弹性,数据密集计算工具,嵌入式与移动计算等。2017年钱老师还受邀来美团TopTalk讲座讲过课。
追寻自己的兴趣,实践出真知
在读博期间,夏华夏依然追寻自己的乐趣,做一些好玩的事情。“实验室有很多机器,我们可以在上面做任何东西,每个人都可以在机器上建网站,建个人主页。”当时,夏华夏和同学们搭建了当地的一个BBS,到目前这个网站还在,后来这个网站被迁移到云端,夏华夏和朋友还会发布一些住房的信息,然后进行一些社交活动。
2000年,MP3开始流行。夏华夏从国内下载了4万多首MP3歌曲。回到美国后,就跟同学一起建立了一个音乐库,对收集歌曲进行打分,开始没有对外开放,但是因为工作量比较大,然后就邀请更多的人参与到这个项目中来共同完成,很快就将想法落地了。“其实,当你有很好的想法时,都是可以去实践的,即使没有收到太多的关注,但你自己会有很大的收获。”
在夏华夏看来,整个读书阶段就是不断的去折腾,参与了很多计算机相关的项目,这才让他积累了很多编程的经验。即使读博阶段做了很多研究型的工作,但是其中参与的一个项目也写了几万行的代码。在夏华夏看来,如果没有去做很多这种小型的、有趣的编程实践项目,很多的知识自己也不会知道,也不会对计算机有那么全面的了解。仅仅靠课程内掌握的技术,可能也很难去面试成功一家公司,而且还是世界上最好的互联网公司。
经过7轮面试,成功加入谷歌
2000年,互联网泡沫破灭。整个IT行业进入低谷,一直到2004年才开始复苏,那一年,谷歌在纳斯达克上市。2006年,夏华夏读完博士,同年10月1日正式加入谷歌,当时最好的互联网公司。谷歌纯技术面试有7轮,前两轮都是通过电话进行技术面试,电话面试通过后,再去谷歌总部面试。总部的面试从早晨一直持续到下午,候选人坐在同一个会议室里;每过45分钟就有一个新的面试官进到会议室来,用各种算法、系统、编程、数学的难题来“刁难”候选人。
“无论是电话面试,还是总部面试,都会强调算法与编程,没有太多网上传言的那种类似脑筋急转弯那类的题目,更多的是算法编程、算法能力、分析能力、编程能力。很多人认为谷歌的面试不太公平,有的工作七八年了,还问这么简单的算法和系统问题,但真实情况就是这样,谷歌的标准是希望大家进入谷歌以后,能够写出更高质量的代码。”因为夏华夏大学和研究生期间的实践经验非常多,所以加入谷歌相对比较顺利。
在谷歌,想要“改变世界”是一件很容易的事情,因为谷歌服务全球市场,拥有的计算机的数量也是非常庞大的,用户数量也非常庞大,只要随便找一个项目去优化一下,那么就会产生特别巨大的效果,不仅仅可以提升用户体验,甚至能够影响公司的运营成本。
很多书中或者网上也提到,在谷歌工作往往是工程师自己找事情去做,很多团队中甚至没有产品经理。相比之下,国内很多大型的互联网公司对产品经理的要求其实很高,而谷歌属于工程师文化,偏技术主导。包括后面谷歌做PaaS平台,组建了一个两三百人的团队,但是产品人员只有个位数,谷歌的工程师都是凭借很强的自我驱动能力来把事情做完。
夏华夏在谷歌的经历主要分成两个阶段。第一个阶段,2006年谷歌进入中国,面临很多特殊的问题,包括访问受限,数据的存储问题,中国要求有些数据必须放在中国,而谷歌对自己的敏感数据不愿意放在中国,所以需要一个专门的团队去解决这些问题,然后再做一些新的技术解决方案。夏华夏加入了一个名为China SRE的项目组,去解决这些富有挑战性的工作。
第二个阶段,夏华夏参与了Google+的研发。由于看到了Facebook发展的非常迅速,当时谷歌也希望在社交领域加大投入,所以谷歌在2009年启动了一个代号“Emerald Sea”(“翡翠海”)的项目,目标是研发功能强大的Google+社交平台。当时谷歌把”翡翠海“视为战略级项目,调集了几百人的精英团队去做这个项目,时任CEO的Larry Page也把办公室搬到了项目所在的楼。
注重开放能力,勇于改变
从2006年到2011年,夏华夏在谷歌度过了非常美好的一段时光。谷歌的架构设计非常有特色,后来搭建美团整个架构体系时,夏华夏也借鉴了谷歌架构的很多设计理念,包括容灾系统的设计,到现在也没有过时。“在谷歌6年,让我感触最深的就是谷歌非常、非常注重开放,所以在美团我也非常鼓励工程师开放、多分享技术。”夏华夏说,谷歌几乎所有的代码都是开放的,除了很极少数的核心代码,比如搜索算法、排序算法等等。如果谷歌的同学觉得别人的代码里哪个地方设计的不够好,可以直接上去改。
夏华夏说:“谷歌的理念对我的影响比较大,在后来的工作中,特别是到美团后,我一直都试图往这个方向靠近,包括现在新组建的团队,我们希望让每个工程师都有对代码的控制和访问权,对代码质量的把控权,包括运维和安全的责任,这种理念能够帮助提升整个技术团队的主动性。”还有很重要的一点,谷歌的工程师都具备体系化的思维方式。比如谷歌的工程师,从产品到架构设计,再到最后的上线测试,工程师都是从头跟到尾,所有的代码包括后续优化的代码都统一放到一个代码仓库中,所有的文档也放在Git中,所有的培训资料,工程师可以随时进行修改和优化,这些对夏华夏都产生了影响。
谷歌投入了很多时间和精力去构建公司的课程体系,包括一套名为EngEDU的线上学习系统,这套体系中包括很多编程语言、内部工具、内部研发流程的学习,每个员工都可以从最初级的语言开始学习,还可以学习谷歌公司的一些系统的使用、公司的一些工具和代码库、以及网络系统的配置方法等等,每节课还会有编程的练习。夏华夏说,“未来美团也会向这个方向努力,现在美团技术学院推出了自己的学习平台,还制作了很多技术课程,向公司内部的同学开放,我们也希望能够沉淀成一些体系化的课程,帮助更多的工程师成长。”
其实,从大学毕业到进入谷歌,夏华夏一直没有刻意去选择自己要走那条路,感觉一切都是顺其自然的。对他来说,这些可能都算不上“很重大的决定”。如果说人生很重要的一个抉择,那么放弃谷歌的工作,回国发展,肯定算是夏华夏最重要的决定之一。
回国篇:宝剑锋从磨砺出,梅花香自苦寒来
因意识形态对立问题,决定回国
回国,是一个很长的话题。2000年到美国后,夏华夏无论是生活还是学习,都处在一个很舒适的环境中。2008年奥运会在北京举办,很多海外的华人都觉得很自豪,夏华夏也觉得为祖国骄傲。后来,华夏夫妇对美国所谓的自由和民主信念开始破裂,其中最重要的一件事就是奥运火炬当时经过旧金山,当时遭到部分反华势力组织的阻挠和捣乱,甚至于美国的很多媒体都在扭曲报道,包括美国最有名的媒体CNN也歧视中国,进行一些不实的报道。他们开始认识到,中美在意识形态层面是对立的,虽然美国有很多先天优势,在这里发展能有更好的全球视野,但是并不是特别理想的国度,所以夏华夏和太太开始把回国发展的提上日程。
还有一个很重要的因素,让夏华夏也深刻感受到国内互联网行业的蓬勃发展,国内很多互联网公司正在高速追赶美国,这点让夏华夏非常激动。夏华夏在谷歌的一位前上司加入百度做技术VP后,在2011年6月份找到夏华夏,希望他能够回国帮助百度做技术架构方面的工作。因为百度当时也在对标谷歌,而且当时发展非常不错,在工作内容方面比较匹配,所以夏华夏开始人生的非常重要的一个决定——回国。
遭遇挫折,用更高的维度去思考问题
2011年底,经过短暂的准备后,夏华夏回到了北京加入百度。夏华夏在百度一年多的时间里,担任运维部的总架构师,他当时的主要工作是把运维部的工作做了梳理,同时也参与了技术架构、基础软件等工作。“我觉得在百度,其实是一个比较好的缓冲或者落地。”夏华夏说。其实谷歌的工程师文化跟百度还是有很多不同的,当时在百度做技术架构工作是有一些“虚”的,也曾经试图跟基础架构部的同学,一起推动国外比较好的技术理念,但是由于种种原因,落地非常困难。
在夏华夏看来,很多公司在做基础架构层面的工作时,往往没有考虑到业务方的需求,只是想做一套很好的系统,很好的架构,让业务方去替换,这种模式存在很大的问题,而且这也是一份非常有挑战,非常非常有风险的工作,成功的可能性很小。百度的工作经历,提升了夏华夏对技术工作整体的认知,也让他能够从一个更高的维度去思考基础架构层面的工作,这也为后续在美团的发展,埋下了很好的伏笔。
太太牵线,结识美团技术团队
很多时候,选择比努力更重要。那么如何才能做出最好的、最适合自己的选择呢?需要勇气,魄力,更重要的是前瞻性的眼光,这些因素都在夏华夏身上得到很自然的体现。
夏华夏能够加入美团,很重要的一个原因也是因为自己的妻子。她此前是在eBay做电商方面的工作,所以回国后也想在这个行业发展,陆续跟国内电商类的公司京东、携程、拉手、窝窝、美团的技术负责人都聊过,其中大部分感觉都算不上很好的技术人员,如果加入他们负责的技术团队,实在是有点担心。唯一留下好印象的就是美团联合创始人穆荣均,在面试中让人感觉很靠谱。最后她决定选择美团。
夏太太还讲到一个细节,其实在2012年回国之前,她就给美团发了简历,很快得到回复,能不能回国面试。在告知了对方回国日期之后,她自己很快就忘记了,可是没想到在回国前两天,美团的HR同学很准时地再次与她联系。这件事让夏太太觉得,美团整个团队做事比较靠谱,令人印象深刻。虽然妻子一直在美团工作,但是夏华夏对美团并没有太多的了解。
2013年3月份,穆荣均通过夏太太向夏华夏抛出了”橄榄枝“。其实,最初就是以朋友的身份见面聊天,吃过几次饭,先建立了友谊,开始穆荣均并没有很快表明”想挖人“的意愿。
因为夏华夏住的小区离美团很近,所以他偶尔去美团接夏太太,当时夏太太在数据组工作,就发现美团的监控工具做的很好,虽然底层也是开源系统,但美团基于它做的功能很简介、很直观、也很好用。后来陆续又接触到很多美团的技术同学,发现整个技术团队很务实,技术氛围很好,整个团队的工作态度非常认真。所以每次面对穆荣均的约饭,夏华夏都欣然前往。
与王兴畅谈云计算,终被美团所打动
后来,穆荣均开始给夏华夏介绍了美团当时的情况,以及未来的发展规划,还有王兴的一个梦想。那还是在2009年年底的时候,王兴说:“其实很多做互联网创业的人,很少考虑怎么去帮助这些人,这些普罗大众,这么多的小商家。其实,他们都在努力改变自己的命运,我们美团就要帮助他们,帮助这些普普通通的老百姓。这也是属于我们的机会。”这句话,深深触动了夏华夏。
不久后,穆荣均将夏华夏介绍给王兴,他以为跟CEO聊天,应该会聊一聊公司的愿景,公司的发展目标之类,但是第一次见面,王兴跟夏华夏聊的主题却是云计算。“2013年,百度还没有正式开始做云计算,国内做云计算的也很少,所以王兴大谈云计算这个话题的时候,让我很诧异。”夏华夏问王兴为什么对云计算感兴趣,王兴说,其实从2012年开始,美团就在做云计算相关的技术储备了。
王兴对云计算技术理解很深刻,他做了很多的阅读,进行过很多的思考。当时给夏华夏留下非常深刻的印象。之后的更多接触,让他觉得美团做的事情,并不是想大多数人想的那样技术很Low,从开始就是一项非常有挑战性的技术工作,而且着眼长远,整个美团的技术团队也是很认真地想通过技术手段来解决吃、喝、玩、乐等一站式生活服务问题。
夏华夏再次选择了一条更难走的路。2013年清明节假期,他终于答应穆荣均,正式宣布加入美团。从国内顶级的互联网巨头,降薪跳到一家前途还不是很明朗的创业公司,充分显示了他的判断力和勇气。
选择需要魄力,更需要信仰
“那时候美团比较小,我太太倒是很担心,因为两个人都在同一家公司,万一公司干砸了怎么办。我自己倒是没有犹豫,因为我是那种不怎么考虑太多后果的人,这件事很有意义,反正想做就做了。而且除了收入减少了,并没有什么特别严重的影响,两个人的收入也够用的。”夏华夏很坦然。
命运,也总是会垂青那些努力的人,坚持的人,也会青睐那些不断有着人生追求的人。有时候,命运会在我们前行的道路上,设下重重障碍,很少有人愿意去打破那些障碍,去看看未知的世界。每一次抉择,夏华夏都是追寻自己的内心,并没有考虑太多财富、名望这些东西,所以他可以比绝大多数人,走的更远。
不择细土,方能成其高
2013年,美团技术团队已经初具规模,整个团队也很务实,但是跟谷歌这些互联网巨头相比,还是有很大的差距,夏华夏也希望能够将谷歌的技术理念带到美团。夏华夏的第一项任务,就是组建技术工程部(包括技术部和移动技术部)。当时美团投入很大的精力在做移动端,夏华夏用两个月左右的时间轮岗,摸清了从前端到后台几乎所有部门的大致情况,然后开始组建系统优化项目组。
美团很多同学对夏华夏的印象都是很务实的一个人,完全没有领导的架子。而且夏华夏也会深度参与很多技术项目,逐个解决,跟大家努力把项目做好,无论是技术层面,还是管理层面,还有对技术梯队的培训,夏华夏都会亲力亲为。
最开始到美团,夏华夏主要跟移动端的同学在一起,讨论如何优化网站性能。当时王兴和穆荣均也经常找夏华夏讨论网站的性能问题,因为他们看到了亚马逊的研究,0.1秒的网页延迟,会直接导致客户活跃度下降1%,当时美团首页加载需要4到5秒,如果提升几秒的话,对公司的价值可以想象有多么大。所以夏华夏的当务之急就是提升美团的访问速度。后来在“千团大战”中,美团能够脱颖而出,一方面因为王兴为首的创始团队从最开始就很注重技术,知道什么是关键因素,另一方面就是美团有很多像夏华夏这样的技术人才,他们对技术的追求非常执着而且很认真,战略和执行的统一,才让美团走的更高、更远。
其实,做基础架构方面的工作,事无巨细,所有跟技术相关的东西,都需要参与。夏华夏发现移动端对推荐算法的要求非常高,因为当时屏幕还很小,在有限的空间展示就需要非常好的算法,而团购产品推荐算法对UPS(用户画像)的要求非常高,所以又开始参与了用户画像的算法项目。
做完UPS后,夏华夏又陆续参与了很多业务项目的开发,包括技术存储、负载均衡、中间件系统等等。夏华夏又接手了运维团队,因为系统的稳定性直接关乎用户体验,这项重任又落在了他的肩上。
除了纯技术项目之外,夏华夏和穆荣均一样,都非常重视工程师文化和技术品牌的建设,他们知道在这方面投入,让更多技术同学有更好的成长,收益很高。夏华夏曾经是美团技术委员会的主席,也是美团技术学院最早的负责人。技术学院的很多项目包括培训、Hackathon、很有特色的图书馆和技术博客等等,最早都是他和从前端工程师转运营的弥新锋一起做起来的。
他本人还是公司很受欢迎的金牌讲师,不仅讲技术、架构,还讲授了非常多软技能方面的课程。
从技术走向管理,从接受C的评价开始
人生,不会是一帆风顺,难免也会遇到很多坎坎坷坷,很多人只会抱怨生活的苦难,而没有看到苦难背后,生活给予的礼物。
当然在美团,夏华夏也承受了一些“委屈”。在2014年年底,他给技术团队同学绩效考评,给某个同学打了C评价,但是这个同学表示不服。后来申诉到CTO那里,穆荣均找夏华夏沟通,问他为什么没有说服这个同学。在夏华夏看来,工作产出相对较差,所以应该给C的评价无可厚非。但是,穆荣均告诉夏华夏,给下面的同学打绩效、说服就是管理工作,如果没有很好地说服同学,就说明管理工作没有到位。
更令华夏没想到的是,“当时穆荣均说,要不这样吧,既然他不接受,要不你接受个C吧?当时我说,那行吧。其实我当时还是觉得比较委屈的。后来想起来,我觉得穆荣均说的非常有道理。”
那一次,夏华夏人生中第一次接受C级的评价。夏华夏说,他跟穆荣均相处的时间里,也学到了很多管理层面的东西。因为自己一直太专注于技术,所以在这方面存在很多问题,后来他也跟穆荣均学了很多管理上的理念和方法。也是因为在技术和管理层面的沉淀和积累,夏华夏才能抗起更加重大项目的挑战。
在美团,最难忘的那些经历
2015年,O2O再起硝烟,外卖大战正酣,夏华夏临危受命,第一次开始接手业务直接相关的工作。此前夏华夏一直都是做基础架构方面的工作,包括谷歌和百度,以及美团的前期。当时美团外卖部门业务压力非常大,系统已经快撑不住了,那时候已经做到180万单了。每天中午,整个技术团队都非常紧张,周末大家也加班,还开辟了美团外卖的“作战室”,这种情况一直持续了两个月左右,然后他又带领大家把以前技术的“坑”填补上。通过大家共同的努力,夏华夏带领技术团队将外卖系统的高可用从两个9提升到三个9,并解决了很多关键路径上服务的稳定性问题。终于在一个周五的晚上,夏华夏告诉大家,周末不用加班了,大家都表示非常开心。那个时刻,对夏华夏来说特别有感触,也很欣慰。
从谷歌到百度再到美团,夏华夏一直抱有一种理念,他觉得做技术最终是为了让团队越做越轻松。在百度的时候,夏华夏在负责运维就发现,如果公司的质量体系或者运维体系做的不够好,技术团队就会非常辛苦。所以到美团以后,他希望带领技术团队,不断追求卓越,尽量让大家不加班,轻轻松松把事情搞定。后来看到大家都能安安心心回家过周末,他也觉得非常具有成就感。
2015年,从基础架构到业务部门,夏华夏再次突破了技术的挑战,而且技术同学的笑脸,让他记忆非常深刻。这一年,美团技术团队抗过千万级流量并发的考验。这一年,夏华夏在技术层面也实现了自我的突破。
这两年,夏华夏又开始迎接新的挑战,负责公司最前沿的无人配送项目。
无人驾驶技术的落地是世界难题,但美团配送末端物流“小轻慢物”的特点,却提供了一个很好的场景。夏华夏从0开始组建了一支团队,涉及很多自己之前很少接触过的技术:机械结构、电子工程、嵌入式开发等等,并很快实现了产品并开始落地实践。现在,无人配送开放平台已经完成了在朝阳大悦城的B端测试运营,以及深圳联想大厦的C端试运营,并在上海松江大学城实现了从B端到C端的完整闭环运营。在松江大学城内,由无人车配送的美团外卖订单已经超过1000单/天,印证了美团无人配送开放平台进行片区规模化运营的可行性。
今年7月,美团还发布了无人配送开放平台,希望集合政府、高校、企业三方力量一起实现这个伟大梦想,已经吸引包括清华大学、加州伯克利大学、北京智能车联产业创新中心、华夏幸福、Segway等近20家国内国外合作伙伴加入。
加入美团后,夏华夏一直在不断打破自己的舒适区,一直对技术有着非常执着的追求。高速成长的美团,也刚好给了夏华夏足够大的舞台去施展。今天,他依然奔跑在技术的最前沿。因为在那里,是距离战场最近的地方,他可以继续探索技术的新边界......
对话夏华夏:程序员的人生抉择
Q:在你自己的成长经历中,你觉得有哪几个重要的里程碑?
夏华夏 :我觉得我的成长,很大程度上属于“阴差阳错”,自己的运气也不错。第一个里程碑,应该算是“蒙”到了清华计算机系。不过,后面的学习就是按部就班,每一步都走的比较稳,包括读博也是听系里老师的安排。如果不是我太太出现在我的生命中,我应该会留在国内发展,整个人生的发展路径也会不一样,当然现在说不清哪个好哪个差,因为时间无法倒流。
第二个里程碑就是出国读书,2000年那个时候,在计算机领域国内外差距很大,所以去UCSD学习对我专业能力的提升非常重要。我还记得刚到国外时,由于英文的问题,课程难度非常大,经常赶作业到凌晨12点以后了,最后一班校车也停了,只能走路回家。如果只是靠在清华学习的那点知识,进入谷歌显然没有任何机会,在国外都会要求有很强的编程能力,另外就是对系统的理解,在UCSD读博的过程中,还有自己搭建过一些网站,打下了比较好的基础,所以后面进入谷歌和百度,都非常顺利。
第三个很重要的里程碑就是加入美团,在加入美团之前,我很多时候是独立工程师或者架构师的角色,到美团以后才开始带大的团队,包括跟穆荣均也学习到很多管理层面的东西。后来跟老王(美团联合创始人、高级副总裁王慧文)工作,他是另外一种风格,实操性比较强、对业务和产品的思考角度非常新颖。所以在美团最大的收获是在从一个纯技术人成长为能力更综合的人。
值得一提的还有,2014年加入了美团管理学院讲师团队,因为在演讲的时候,跟真实情况也是不一样的,需要构建理论体系。其实最好的成长,就是分享,无论是做技术研究还是团队管理,这句话都非常有道理。
美团从创立之初,技术管理就比较规范,所以在这里成长也非常快。开始的时候,几乎每周换一个团队,跟这个团队的同学一起工作、一起学习,深入了解这个团队。我觉得技术管理者应该多接触一线的同学,可以让自己更快的融入团队,后续很多工作的开展,也会起到事半功倍的作用。
Q:你认为优秀的架构师或者技术管理者,都应该具备哪些特质?
夏华夏 :首先最主要的就是技术的深度,其实架构师也属于技术梯队,我们在面试的时候,要求技术同学对其所在的领域要非常熟悉,包括使用哪种技术方案解决问题,为什么要使用这种技术方案,在技术选择时要考虑哪些重要的因素等等,对技术细节的把控能力要足够深刻。
其次,就是技术人员要具备足够宽的技术视野,也就是广度,要对自己领域周边的技术发展要有所了解,同时也要了解这种新技术在其他公司的应用情况。我希望能够加入美团点评的技术同学都能够很好的深度和相对的广度。除此之外,也希望他能够具备比较强的学习能力和自我驱动力。因为技术发展变化非常快,我们希望新加入的同学拥有足够的热情去不断的学习。
在技术管理能力层面,一方面是管理项目的能力,如何才能更好的推动一个项目;另一方面就是如何更好的管理好人才,使用好人才,培养好人才。我觉得一个好的技术管理者必须具备一个很重要的特质,心态要足够开放,这样他就愿意去学习新技术,能对事情研究的比较深入。
Q: 对于美团的技术同学,您有什么建议?
夏华夏 :第一个方面是 保持不断学习的心态 ,这也是美团工程师文化特别提倡的,这是我们希望所有工程师具有的特质和建议,包括对技术领域深度和广度的学习,不断延伸个人的能力。
第二个方面是 全栈思维 ,从心态方面,希望大家能够站在团队的视角来看问题,我们鼓励开放的工作氛围,美团点评内部的很多代码也在逐渐开放。还有就是从技术能力层面,我建议大家的技术能力能够全面一些,现在美团有6个技术通道,包括前端、后台、算法、运维、测试、系统,每个技术同学应该逐渐从全栈的角度去考虑自己的发展,还有对产品和业务的思考。现在美团点评基础架构、研发服务框架、安全认证体系、容灾体系等等很多项目都还在持续的建设中,我们鼓励更多的工程师主动参与进来。
第三个方面,就是 前瞻思维 ,近几年涌现出很多的热点技术,我们应该积极的思考热点技术如何能够更好的跟我们的业务结合起来。比如利用人工智能相关的技术来提升用户体验,像语音识别技术可以帮我们做智能客服,我们也可以在算法层面做很多优化,来提升推荐和搜索引擎的准确度和效率等等,最近技术团队也在探索如何利用人工智能,实现自动化、智能化运维。我们鼓励大家利用新技术,从而来推动研发团队的成长。
最后还有一点,对技术管理者来说,美团有一个特别好的地方。就是没有跟很大大公司一样走两条发展路线,像百度,从T5、T6开始就分成两条线,团队中一个管理职责的人,一个做技术职责的人,管理者往往对技术的接触比较少,其实很容易产生很多问题。在美团点评这个大家庭里面,我们要求管理和技术齐头并进,提倡更均衡的发展,这种模式更适合培养更优秀的技术人才和领导者。
Q:你有什么特别佩服的人吗?
夏华夏 :Google的Jeff Dean。在Google,大家都把他奉为”神“一样的人物,我也很佩服他。谷歌的技术架构之所以这么好,其实跟Jeff有很大的关系。Jeff亲手打造的系统包括Google File System、MapReduce、BigTable以及Spanner等等,这些是大规模分布式系统的经典架构,称得上Google和现代互联网存在的“基石”。
Jeff一直没有脱离编程的前线。在2011年的Google+项目中,当时高并发场景下Feed流读写性能跟不上,而读写后台是基于BigTable,所以Jeff就过来解决问题。他当时已经是Fellow级别(相当于副总裁),自己一个人带个ThinkPad过来,找个工位,编了两天程序,就把BigTable架构优化了,顺利支撑了Google+上线后的高并发访问。
Jeff虽然职位已经很高了,但是他还在不断尝试新的领域。他现在是Senior Fellow,Google职级最高的工程师,相当于管理线的SVP。几年前他把注意力从基础架构转向了人工智能,现在是Google Brain的负责人,TensorFlow就是他团队的作品。就在不久前,他还发表了新论文,提出了使用机器学习索引来替代B-Trees,能够提速3倍,再次点燃了整个技术圈,当时朋友圈很多人在转发这个消息。
不断尝试新的领域,不断突破自己的边界。我觉得这是非常值得我们所有技术同学学习的地方。
Q:如果让你给技术同学推荐一些书,你会推荐哪些?
夏华夏 :我会推荐尤瓦尔·赫拉里的《人类简史》和《未来简史》,这两本不是计算机技术相关的书籍。但是作者从一个非常宏大的视角阐述了我们整个人类社会的发展,也强调了人与自然的关系,包括现阶段人类如何受到技术的影响,以及人生的意义等很多话题。我觉得这两本书可以帮助我们技术同学更好的理解、认识这个世界,认识“人类”这个种群,或者说这种生物,这两本书对我影响蛮大的,我也推荐给大家,希望大家也能从中有所感悟和收获。
招聘信息
美团无人配送部于2016年组建,自研无人配送产品,开放自身业务场景,致力用先进的技术,对配送侧进行改革,增加运力的供给。团队目前已经自主研发有两款适应不同场景的无人车产品和一款无人机产品,发布美团无人配送开放平台。目前美团无人配送已经完成在雄安、北京、深圳、上海多地的落地试运营,参与制定发布《服务型电动自动行驶轮式车技术要求》,在技术场景和法规等多方面推动产业发展,最终达到用无人配送让服务触达世界每个角落的目标。美团无人配送团队诚招各路英才,简历请投至: walle.hr@meituan.com
人工智能
2018-11-09 11:21:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
【Java】人流量统计-动态版之视频转图识别请访问 http://ai.baidu.com/forum/topic/show/940413
本文是基于上一篇进行迭代的。本文主要是以摄像头画面进行人流量统计。并对返回图像进行展示。需要额外了解 JavaCV OpenCV swing awt等
也许JavaCV OpenCV 不需要也可以实现效果。但是小帅丶就先用这样的方式实现了。别的方式大家就自己尝试吧
有可能显示的in out不对。请设置帧率试试。鄙人不是专业的。所以对帧率也不是很懂。以下代码加入也没有明显的变化。 grabber.setFrameRate(10); grabber.setFrameNumber(10);
项目代码地址 https://gitee.com/xshuai/bodyTrack 注意的问题 1.动态识别的area参数为矩阵的4个顶点的xy坐标(即像素) 顺序是 上左下右 也就是顺时针一圈4个点的坐标点 2.case_id 为int 请不要给大于int范围的值。或非int类型的值 即正整数就行 3.area的值不要大于图片本身的宽高 需要用到的jar 通过maven引入(下载的jar较多。需要等待较长时间) UTF-8 1.8 1.8 3.2.1-1.3 1.4.1 org.bytedeco.javacpp-presets ffmpeg-platform ${ffmpeg.version} com.alibaba fastjson 1.2.35 org.bytedeco javacv ${javacv.version} org.bytedeco.javacpp-presets opencv-platform 3.4.1-1.4.1 需要用到的Java工具类 HttpUtil https://ai.baidu.com/file/544D677F5D4E4F17B4122FBD60DB82B3 调用接口示例代码(需要自己的电脑有摄像头哦) import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; import java.awt.image.WritableRaster; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.OutputStream; import java.net.URLEncoder; import java.util.Base64; import java.util.Base64.Decoder; import java.util.Base64.Encoder; import javax.imageio.ImageIO; import javax.swing.JFrame; import org.bytedeco.javacpp.BytePointer; import org.bytedeco.javacpp.opencv_core.IplImage; import org.bytedeco.javacv.CanvasFrame; import org.bytedeco.javacv.Frame; import org.bytedeco.javacv.Java2DFrameConverter; import org.bytedeco.javacv.OpenCVFrameConverter; import org.bytedeco.javacv.OpenCVFrameConverter.ToIplImage; import org.bytedeco.javacv.OpenCVFrameGrabber; import com.alibaba.fastjson.JSONObject; import cn.xsshome.body.util.HttpUtil; /** * 获取摄像头画面进行处理并回显图片在画面中 * 人流量统计(动态版)JavaAPI示例代码 * @author 小帅丶 * */ public class JavavcCameraTest { static OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage(); //人流量统计(动态版)接口地址 private static String BODY_TRACKING_URL="https://aip.baidubce.com/rest/2.0/image-classify/v1/body_tracking"; private static String ACCESS_TOKEN ="";//接口的token /** * 每个case的初始化信号,为true时对该case下的跟踪算法进行初始化,为false时重载该case的跟踪状态。当为false且读取不到相应case的信息时,直接重新初始化 * caseId=0 第一次请求 case_init=true caseId>0 非第一次请求 case_init=false */ static int caseId = 0; public static void main(String[] args) throws Exception, InterruptedException { OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0); grabber.start(); // 开始获取摄像头数据 CanvasFrame canvas = new CanvasFrame("人流量实时统计");// 新建一个窗口 canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); canvas.setAlwaysOnTop(true); int ex = 0; while (true) { if (!canvas.isDisplayable()) {// 窗口是否关闭 grabber.stop();// 停止抓取 System.exit(2);// 退出 grabber.close(); } // canvas.showImage(grabber.grab());//显示摄像头抓取的画面 Java2DFrameConverter java2dFrameConverter = new Java2DFrameConverter(); // 摄像头抓取的画面转BufferedImage BufferedImage bufferedImage = java2dFrameConverter.getBufferedImage(grabber.grabFrame()); // bufferedImage 请求API接口 检测人流量 String result = getBodyTrack(bufferedImage); BufferedImage bufferedImageAPI = getAPIResult(result); // 如果识别为空 则显示摄像头抓取的画面 if (null == bufferedImageAPI) { canvas.showImage(grabber.grab()); } else { // BufferedImage转IplImage IplImage iplImageAPI = BufImgToIplData(bufferedImageAPI); // 将IplImage转为Frame 并显示在窗口中 Frame convertFrame = converter.convert(iplImageAPI); canvas.showImage(convertFrame); } ex++; // Thread.sleep(100);// 100毫秒刷新一次图像.因为接口返回需要时间。所以看到的画面还是会有一定的延迟 } } /** * BufferedImage转IplImage * @param bufferedImageAPI * @return */ private static IplImage BufImgToIplData(BufferedImage bufferedImageAPI) { IplImage iplImage = null; ToIplImage iplConverter = new OpenCVFrameConverter.ToIplImage(); Java2DFrameConverter java2dConverter = new Java2DFrameConverter(); iplImage = iplConverter.convert(java2dConverter.convert(bufferedImageAPI)); return iplImage; } /** * IplImage 转 BufferedImage * @param mat * @return BufferedImage */ public static BufferedImage iplToBufImgData(IplImage mat) { if (mat.height() > 0 && mat.width() > 0) { //TYPE_3BYTE_BGR 表示一个具有 8 位 RGB 颜色分量的图像,对应于 Windows 风格的 BGR 颜色模型,具有用 3 字节存储的 Blue、Green 和 Red 三种颜色。 BufferedImage image = new BufferedImage(mat.width(), mat.height(),BufferedImage.TYPE_3BYTE_BGR); WritableRaster raster = image.getRaster(); DataBufferByte dataBuffer = (DataBufferByte) raster.getDataBuffer(); byte[] data = dataBuffer.getData(); BytePointer bytePointer = new BytePointer(data); mat.imageData(bytePointer); return image; } return null; } /** * 接口结果转bufferimage * @param result * @return BufferedImage * @throws Exception */ private static BufferedImage getAPIResult(String result) throws Exception { JSONObject object = JSONObject.parseObject(result); BufferedImage bufferedImage = null; if(object.getInteger("person_num")>=1){ Decoder decoder = Base64.getDecoder(); byte [] b = decoder.decode(object.getString("image")); ByteArrayInputStream in = new ByteArrayInputStream(b); bufferedImage = ImageIO.read(in); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(bufferedImage,"jpg", baos); byte[] imageInByte = baos.toByteArray(); // Base64解码 for (int i = 0; i < imageInByte.length; ++i) { if (imageInByte[i] < 0) {// 调整异常数据 imageInByte[i] += 256; } } OutputStream out = new FileOutputStream("G:/testimg/xiaoshuairesult.jpg");//接口返回的渲染图 out.write(imageInByte); out.flush(); out.close(); return bufferedImage; }else{ return null; } } /** * 获取接口处理结果图 * @param bufferedImage * @return String * @throws Exception */ public static String getBodyTrack(BufferedImage bufferedImage) throws Exception{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(bufferedImage,"jpg",baos); byte[] imageInByte = baos.toByteArray(); Encoder base64 = Base64.getEncoder(); String imageBase64 = base64.encodeToString(imageInByte); // Base64解码 for (int i = 0; i < imageInByte.length; ++i) { if (imageInByte[i] < 0) {// 调整异常数据 imageInByte[i] += 256; } } // 生成jpeg图片 OutputStream out = new FileOutputStream("G:/testimg/xiaoshuai.jpg");// 新生成的图片 out.write(imageInByte); out.flush(); out.close(); System.out.println("保存成功"); baos.flush(); baos.close(); String access_token = ACCESS_TOKEN; String case_id = "2018"; String case_init = ""; String area = "10,10,630,10,630,470,10,469"; String params = ""; if(caseId==0){ case_init = "true"; params = "image=" + URLEncoder.encode(imageBase64, "utf-8") + "&dynamic=true&show=true&case_id=" + case_id + "&case_init="+case_init +"&area="+area; }else{ case_init = "false"; params = "image=" + URLEncoder.encode(imageBase64, "utf-8") + "&dynamic=true&show=true&case_id=" + case_id + "&case_init="+case_init +"&area="+area; } //静态识别 // String params = "image=" + URLEncoder.encode(imageBase64, "utf-8")+"&dynamic=false&show=true"; String result = HttpUtil.post(BODY_TRACKING_URL, access_token, params); System.out.println("接口内容==>"+result); return result; } /** * IplImage 转 BufferedImage * @param mat * @return BufferedImage */ public static BufferedImage bufferimgToBase64(IplImage mat) { if (mat.height() > 0 && mat.width() > 0) { BufferedImage image = new BufferedImage(mat.width(), mat.height(),BufferedImage.TYPE_3BYTE_BGR); WritableRaster raster = image.getRaster(); DataBufferByte dataBuffer = (DataBufferByte) raster.getDataBuffer(); byte[] data = dataBuffer.getData(); BytePointer bytePointer = new BytePointer(data); mat.imageData(bytePointer); return image; } return null; } }
摄像头中的内容截图示意(本人头像就不直接显示了。万一吓着大家呢) 也不要用去马赛克的技术还原图片哦。

还是很好玩的、不需要自己去整OpenCV一套就能实现统计摄像头中的人数。
人工智能
2018-11-09 10:06:08
「深度学习福利」大神带你进阶工程师,立即查看>>>
环境搭建比FNLP的简单,具体参考:https://github.com/hankcs/HanLP
各个版本的下载:https://github.com/hankcs/HanLP/releases
完毕后有一个报错:
字符类型对应表加载失败:
D:/eclipse_workspace/HanLPTest/HanLP/data/dictionary//other/CharType.dat.yes
直接在 D:/eclipse_workspace/HanLPTest/HanLP/data/dictionary//other/ 目录下新建一个txt文档将名称改为 CharType.dat.yes 即可。
相对比较简单。
尝试HanLP主要处于各个开源自然语言处理工具包之间的差异,寻找一个适合学习的开源工具包。
HanLP调用方法
HanLP几乎所有的功能都可以通过工具类HanLP快捷调用,当你想不起来调用方法时,只需键入HanLP.,IDE应当会给出提示,并展示HanLP完善的文档。所有Demo都位于com.hankcs.demo下,比文档覆盖了更多细节,更新更及时,强烈建议运行一遍。
HanLP的适用过程中注意的问题:
1、因为HanLP版本更新比较频繁,所以,jar源代码版本需要对应适用,否则源码和jar中接口调用对应不上。
在进行CRF分词过程中报错:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.nio.HeapByteBuffer.(HeapByteBuffer.java:57)
at java.nio.ByteBuffer.allocate(ByteBuffer.java:335)
at com.hankcs.hanlp.corpus.io.IOUtil.readBytesFromFileInputStream(IOUtil.java:251)
at com.hankcs.hanlp.corpus.io.IOUtil.readBytes(IOUtil.java:178)
at com.hankcs.hanlp.corpus.io.ByteArray.createByteArray(ByteArray.java:47)
at com.hankcs.hanlp.model.crf.CRFModel.loadTxt(CRFModel.java:89)
at com.hankcs.hanlp.seg.CRF.CRFSegment.(CRFSegment.java:58)
at com.hankcs.hanlp.seg.CRF.CRFSegment.(CRFSegment.java:73)
at test.Main.main(Main.java:56)

是因为CRF比较耗内存,所以出现内存不足,所以需要修改一下VM的最大内存。
选中工程,然后:
即可解决。
在源码包文件在eclipse中打开出现乱码,解决方法:
(必须)首先用txt打开,然后在第一行添加:encoding="utf-8"即可。
转载自 CrazyNong 的博客
人工智能
2018-11-09 09:36:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
在本文中,你将学习到以下内容: TensorFlow中调用ResNet网络 训练网络并保存模型 加载模型预测结果
前言
在深度学习中,随着网络深度的增加,模型优化会变得越来越困难,甚至会发生梯度爆炸,导致整个网络训练无法收敛。ResNet(Residual Networks)的提出解决了这个问题。在这里我们直接调用ResNet网络进行训练,讲解ResNet细节的文章有很多,这里找了一篇供 参考 。
搭建训练网络
如果你看过了前面的准备工作, 图片预处理 和 制作tfrecord格式 ,默认已经有tfrecord格式的数据文件了。我们接着搭建网络,来处理100类商标图片的分类问题。将制作好的tfrecord数据通过队列系统传入ResNet网络进行训练。
首先导入必要的库: import tensorflow as tf import tensorflow.contrib.slim.nets as nets
nets库里面集成了现有的很多网络(AlexNet,Inception,ResNet,VGG)可以直接调用,我们在这里使用ResNet_50,即50层的网络训练。
接下来我们先定义一个读取tfrecord文件的函数: def read_and_decode_tfrecord(filename): filename_deque = tf.train.string_input_producer(filename) reader = tf.TFRecordReader() _, serialized_example = reader.read(filename_deque) features = tf.parse_single_example(serialized_example, features={ 'label': tf.FixedLenFeature([], tf.int64), 'img_raw': tf.FixedLenFeature([], tf.string)}) label = tf.cast(features['label'], tf.int32) img = tf.decode_raw(features['img_raw'], tf.uint8) img = tf.reshape(img, [224, 224, 3]) img = tf.cast(img, tf.float32) / 255.0 #将矩阵归一化0-1之间 return img, label
定义模型保存地址,batch_sizes设置的小一点训练效果更好,将当前目录下的tfrecord文件放入列表中: save_dir = r"./train_image_63.model" # 模型保存路径 batch_size_ = 2 lr = tf.Variable(0.0001, dtype=tf.float32) # 学习速率 x = tf.placeholder(tf.float32, [None, 224, 224, 3]) # 图片大小为224*224*3 y_ = tf.placeholder(tf.float32, [None]) train_list = ['traindata_63.tfrecords-000', 'traindata_63.tfrecords-001', 'traindata_63.tfrecords-002','traindata_63.tfrecords-003', 'traindata_63.tfrecords-004', 'traindata_63.tfrecords-005','traindata_63.tfrecords-006', 'traindata_63.tfrecords-007', 'traindata_63.tfrecords-008','traindata_63.tfrecords-009', 'traindata_63.tfrecords-010', 'traindata_63.tfrecords-011','traindata_63.tfrecords-012', 'traindata_63.tfrecords-013', 'traindata_63.tfrecords-014', 'traindata_63.tfrecords-015', 'traindata_63.tfrecords-016', 'traindata_63.tfrecords-017','traindata_63.tfrecords-018', 'traindata_63.tfrecords-019', 'traindata_63.tfrecords-020','traindata_63.tfrecords-021'] #制作成的所有tfrecord数据,每个最多包含1000个图片数据 # 随机打乱顺序 img, label = read_and_decode_tfrecord(train_list) img_batch, label_batch = tf.train.shuffle_batch([img, label], num_threads=2, batch_size=batch_size_, capacity=10000,min_after_dequeue=9900)
注意这里使用了 tf.train.shuffle_batch 随机打乱队列里面的数据顺序, num_threads 表示线程数, capacity 表示队列的容量,在这里设置成10000, min_after_dequeue 队列里保留的最小数据量,并且控制着随机的程度,设置成9900的意思是,当队列中的数据出列100个,剩下9900个的时候,就要重新补充100个数据进来并打乱顺序。如果你要按顺序导入队列,改成 tf.train.batch 函数,并删除 min_after_dequeue 参数。这些参数都要根据自己的电脑配置进行相应的设置。
接下来将label值进行onehot编码,直接调用 tf.one_hot 函数。因为我们这里有100类, depth 设置成100: # 将label值进行onehot编码 one_hot_labels = tf.one_hot(indices=tf.cast(y_, tf.int32), depth=100) pred, end_points = nets.resnet_v2.resnet_v2_50(x, num_classes=100, is_training=True) pred = tf.reshape(pred, shape=[-1, 100])
我们通过 nets.resnet_v2.resnet_v2_50 直接调用ResNet_50网络,同样 num_classes 等于类别总数, is_training 表示我们是否要训练网络里面固定层的参数,True表示所有参数都重新训练,False表示只训练后面几层的参数。
网络搭好后,我们继续定义损失函数和优化器,损失函数选择sigmoid交叉熵,优化器选择Adam: # 定义损失函数和优化器 loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=pred, labels=one_hot_labels)) optimizer = tf.train.AdamOptimizer(learning_rate=lr).minimize(loss)
定义准确率函数,tf.argmax函数返回最大值所在位置: # 准确度 a = tf.argmax(pred, 1) b = tf.argmax(one_hot_labels, 1) correct_pred = tf.equal(a, b) accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
最后我们构建Session,让网络跑起来: saver = tf.train.Saver() with tf.Session() as sess: sess.run(tf.global_variables_initializer()) # 创建一个协调器,管理线程 coord = tf.train.Coordinator() # 启动QueueRunner,此时文件名队列已经进队 threads = tf.train.start_queue_runners(sess=sess, coord=coord) i = 0 while True: i += 1 b_image, b_label = sess.run([img_batch, label_batch]) _, loss_, y_t, y_p, a_, b_ = sess.run([optimizer, loss, one_hot_labels, pred, a, b], feed_dict={x: b_image,y_: b_label}) print('step: {}, train_loss: {}'.format(i, loss_)) if i % 20 == 0: _loss, acc_train = sess.run([loss, accuracy], feed_dict={x: b_image, y_: b_label}) print('--------------------------------------------------------') print('step: {} train_acc: {} loss: {}'.format(i, acc_train, _loss)) print('--------------------------------------------------------') if i == 200000: saver.save(sess, save_dir, global_step=i) elif i == 300000: saver.save(sess, save_dir, global_step=i) elif i == 400000: saver.save(sess, save_dir, global_step=i) break coord.request_stop() # 其他所有线程关闭之后,这一函数才能返回 coord.join(threads)
当我们使用队列系统时,在Session部分一定要创建一个协调器管理线程。我们每20步输出一次准确率,在200000,300000,400000步的时候自动保存模型。
训练结束后会得到如下模型文件,我在这里只保留了300000步的模型:
模型文件
附上训练网络完整代码: import tensorflow as tf import tensorflow.contrib.slim.nets as nets def read_and_decode_tfrecord(filename): filename_deque = tf.train.string_input_producer(filename) reader = tf.TFRecordReader() _, serialized_example = reader.read(filename_deque) features = tf.parse_single_example(serialized_example, features={ 'label': tf.FixedLenFeature([], tf.int64), 'img_raw': tf.FixedLenFeature([], tf.string)}) label = tf.cast(features['label'], tf.int32) img = tf.decode_raw(features['img_raw'], tf.uint8) img = tf.reshape(img, [224, 224, 3]) img = tf.cast(img, tf.float32) / 255.0 #将矩阵归一化0-1之间 return img, label save_dir = r"./train_image_63.model" batch_size_ = 2 lr = tf.Variable(0.0001, dtype=tf.float32) x = tf.placeholder(tf.float32, [None, 224, 224, 3]) y_ = tf.placeholder(tf.float32, [None]) train_list = ['traindata_63.tfrecords-000','traindata_63.tfrecords-001','traindata_63.tfrecords-002','traindata_63.tfrecords-003','traindata_63.tfrecords-004','traindata_63.tfrecords-005','traindata_63.tfrecords-006','traindata_63.tfrecords-007','traindata_63.tfrecords-008''traindata_63.tfrecords-009','traindata_63.tfrecords-010','traindata_63.tfrecords-011','traindata_63.tfrecords-012','traindata_63.tfrecords-013','traindata_63.tfrecords-014','traindata_63.tfrecords-015','traindata_63.tfrecords-016','traindata_63.tfrecords-017','traindata_63.tfrecords-018','traindata_63.tfrecords-019','traindata_63.tfrecords-020','traindata_63.tfrecords-021'] # 随机打乱顺序 img, label = read_and_decode_tfrecord(train_list) img_batch, label_batch = tf.train.shuffle_batch([img, label], num_threads=2, batch_size=batch_size_, capacity=10000,min_after_dequeue=9900) # 将label值进行onehot编码 one_hot_labels = tf.one_hot(indices=tf.cast(y_, tf.int32), depth=100) pred, end_points = nets.resnet_v2.resnet_v2_50(x, num_classes=100, is_training=True) pred = tf.reshape(pred, shape=[-1, 100]) # 定义损失函数和优化器 loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=pred, labels=one_hot_labels)) optimizer = tf.train.AdamOptimizer(learning_rate=lr).minimize(loss) # 准确度 a = tf.argmax(pred, 1) b = tf.argmax(one_hot_labels, 1) correct_pred = tf.equal(a, b) accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32)) saver = tf.train.Saver() with tf.Session() as sess: sess.run(tf.global_variables_initializer()) # 创建一个协调器,管理线程 coord = tf.train.Coordinator() # 启动QueueRunner,此时文件名队列已经进队 threads = tf.train.start_queue_runners(sess=sess, coord=coord) i = 0 while True: i += 1 b_image, b_label = sess.run([img_batch, label_batch]) _, loss_, y_t, y_p, a_, b_ = sess.run([optimizer, loss, one_hot_labels, pred, a, b], feed_dict={x: b_image,y_: b_label}) print('step: {}, train_loss: {}'.format(i, loss_)) if i % 20 == 0: _loss, acc_train = sess.run([loss, accuracy], feed_dict={x: b_image, y_: b_label}) print('--------------------------------------------------------') print('step: {} train_acc: {} loss: {}'.format(i, acc_train, _loss)) print('--------------------------------------------------------') if i == 200000: saver.save(sess, save_dir, global_step=i) elif i == 300000: saver.save(sess, save_dir, global_step=i) elif i == 400000: saver.save(sess, save_dir, global_step=i) break coord.request_stop() # 其他所有线程关闭之后,这一函数才能返回 coord.join(threads)
预测结果
我们利用1000张测试数据评估我们的模型,直接放代码: import tensorflow as tf import tensorflow.contrib.slim.nets as nets from PIL import Image import os test_dir = r'./test' # 原始的test文件夹,含带预测的图片 model_dir = r'./train_image_63.model-300000' # 模型地址 test_txt_dir = r'./test.txt' # 原始的test.txt文件 result_dir = r'./result.txt' # 生成输出结果 x = tf.placeholder(tf.float32, [None, 224, 224, 3]) classes = ['1', '10', '100', '11', '12', '13', '14', '15', '16', '17', '18', '19', '2', '20', '21', '22', '23', '24','25', '26', '27', '28', '29', '3', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '4', '40','41', '42', '43', '44', '45', '46', '47', '48', '49', '5', '50', '51', '52', '53', '54', '55', '56', '57','58', '59', '6', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '7', '70', '71', '72', '73','74', '75', '76', '77', '78', '79', '8', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '9','90', '91', '92', '93', '94', '95', '96', '97', '98', '99']# 标签顺序 pred, end_points = nets.resnet_v2.resnet_v2_50(x, num_classes=100, is_training=True) pred = tf.reshape(pred, shape=[-1, 100]) a = tf.argmax(pred, 1) saver = tf.train.Saver() with tf.Session() as sess: sess.run(tf.global_variables_initializer()) saver.restore(sess, model_dir) with open(test_txt_dir, 'r') as f: data = f.readlines() for i in data: test_name = i.split()[0] for pic in os.listdir(test_dir): if pic == test_name: img_path = os.path.join(test_dir, pic) img = Image.open(img_path) img = img.resize((224, 224)) img = tf.reshape(img, [1, 224, 224, 3]) img1 = tf.reshape(img, [1, 224, 224, 3]) img = tf.cast(img, tf.float32) / 255.0 b_image, b_image_raw = sess.run([img, img1]) t_label = sess.run(a, feed_dict={x: b_image}) index_ = t_label[0] predict = classes[index_] with open(result_dir, 'a') as f1: print(test_name, predict, file=f1) break
需要注意的是test数据集并没有处理成tfrecord格式,在这里直接将图片一张张导入用模型预测,生成的结果文件主要是为了提交比赛使用。原始数据和模型我会放在 这里 ,密码:8xbi。有兴趣自提。
至此,我们就完成了一个CNN图像识别项目。
相关文章 “笨方法”学习CNN图像识别(二)—— tfrecord格式高效读取数据 “笨方法”学习CNN图像识别(一)—— 图片预处理
人工智能
2018-11-08 19:36:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
近年来,机器学习变得愈加火热,中国选手柯洁与AlphaGo的人机大战更是引起热议。目前,在图像识别和视觉分析研究中, 卷积神经网络 (CNN)技术的使用越来越多。 Tensorflow 是由 Google 团队开发的神经网络模块,短短几年间, 就已经有很多次版本的更新。最近我也在自学Tensorflow,想通过卷积神经网络快速识别 整块 验证码(不分割字符)。期间也碰到许多问题,诸如 软件安装 ,Tensorflow 版本差异 等。一开始学习tensorflow是盲目的,不知如何下手,网上的资料都比较单一,为了回报社会,让大家少走弯路,我将详细介绍整个过程。本教程所需要的完整材料,我都会放在 这里 ,密码:5e91。限于个人水平,如有错误请指出!
接下来我将介绍如何使用Python+Tensorflow的CNN技术快速识别验证码。在此之前,介绍我们用到的工具:
1. PyCharm社区版 (python的IDE):写代码非常方便,安装第三方库(tensorflow 1.2.1)操作简单。
2. Python3 :当我还在犹豫py2还是py3的时候,tensorflow已能支持windows、py3了,并且python3代表未来,建议使用Python3。
3. Photoshop :用于验证码的分析和处理(在这里不需要你精通)。
本文将从以下几个方面来介绍:
验证码分析和处理 —— tensorflow安装 —— 模型训练 —— 模型预测
验证码分析和处理
网上搜索验证码识别能够得到很多教程,但大部分都是将验证码切割成单个字符训练,有时候 验证码字符大小不一或者发生重叠,切割验证码变得不适用。因此通过CNN技术将整块验证码进行识别,能使问题变得更加简单(以下操作对其他验证码分析有参考作用)。
在这里我们选择模拟学习这样的验证码:
该验证码来源于 这里 (正如sci-hub网站所言”to remove all barriers in the way of science”,知识就该如此)。
原始的验证码
该验证码只由六位小写字母、噪点和干扰线组成,如果能去除噪点和干扰线,能够大大降低学习的难度。很多验证码的噪点和干扰线RGB值和字母的不一致,这个我们能通过Photoshop来分析,使用颜色取样器工具,分别在图片噪点、干扰线、空白处和字母处点击获得RGB值,如下图:
颜色取样器获得RGB值
分析后发现,只要将图片二值化只保留字母,就能得到不错的输入图片:
处理后的图片
实现代码如下:
验证码处理代码
以上就是验证码处理方法,为了下面的分析方便,我将处理好的验证码打包放到 这里 ,密码:5e91。
Tensorflow安装
如果你查看了官方文档会发现提供了很多安装方式,但是还是比较复杂。针对不同的系统,不同设备(CPU or GPU)都不一样,我在这里选择用pycharm直接安装tensorflow非常好用,而且跟python版本兼容,不用考虑过多。打开pycharm,在菜单栏里flie-settings-project-project interpreter,选择python3 interpreter,
添加第三方库
然后点击 + 按钮,输入tensorflow,install package。
添加tensorflow库
至此,tensorflow就在电脑上安装好了,非常简单吧,我安装的时候版本是1.2.1。准备工作全部结束。
模型训练
如果你对卷积神经网络或者Python代码实现还不熟悉,我推荐你先看看《tensorflow实战》黄文坚著这本书,比官方文档详细多。搞清楚代码如何实现后,再来看接下来的内容(毕竟我也是花了时间走弯路的)。
首先,我们先输入验证码的信息备用,图片是114*450像素,最大有6个字母,每个字母通过26个0或1表示,比如a表示成 10000000000000000000000000 ,b表示成 01000000000000000000000000 ,以此类推。
验证码信息
接下来定义一个函数,随机从训练集(3430张)中提取验证码图片,由于验证码经过我手动打标签(码了6小时),在这里只要获取验证码的名字和图片就够了,我默认放在 "F:/captcha4/" 目录下,需要注意的是返回的图片是以矩阵的形式。
获取验证码名字和图片
接下来定义两个函数,将名字转变成向量,将向量转变成名字。
名字向量互转
生成一个训练batch,也就是采样的大小,默认一次采集64张验证码作为一次训练,需要注意通过 get_name_and_image() 函数获得的image是一个含布尔值的矩阵,在这里通过 1*(image.flatten()) 函数转变成只含0和1的1行114*450列的矩阵。
采样batch
接下来定义卷积神经网络结构,我们采用3个卷积层加1个全连接层的结构,在每个卷积层中都选用2*2的最大池化层和dropout层,卷积核尺寸选择5*5。需要注意的是在全连接层中,我们的图片 114*450 已经经过了3层池化层,也就是长宽都压缩了8倍,得到 15*57 大小。
卷积神经网络结构
结构建立好后就可以开始训练了,在这里选择的 sigmoid_cross_entropy_with_logits() 交叉熵来比较loss,用adam优化器来优化。输出每一步的loss值,每100步,输出一次准确率。在这里我调节当准确率达到99%后,结束训练。需要注意的是, keep_prob = 0.5 ,这个参数控制着过拟合,当我们机器学习速度过快的时候,可以减小该值,让机器遗忘的多一点(像人一样,记得多不一定好,哈哈)。
训练模型
训练完成后,你应该会得到如下几个文件。在这里我花了将近9个小时跑了1800步,达到99.5%的准确率。输出文件的详细介绍参考 这里 。
模型输出文件
模型预测
我们的模型训练成功后,我们就要检验一下该模型的预测水平,在这里我们首先要把 train_crack_captcha_cnn() 函数注释掉,然后再定义一个预测模型的函数 crack_captcha() ,需要注意为了从预测集中抽数据,这里的 get_name_and_image() 函数调用 "F:/captcha5/" 目录下的10张预测图片。
更改到预测集文件夹
从预测集中随机预测10次
预测结果如下:
预测结果对比
经过比较,我发现10张预测的能有4张准确,这还有待改进,但是整体上还是达到了我的要求。毕竟训练集的准确率有99.5%。如果我调低 keep_prob 的值,增加样本量,增加卷积层,最后的预测效果应该会更好。完整代码详见
总之,通过上面这个教程,只是教大家如何通过tensorflow的CNN技术处理整块验证码,大家可以尝试着用其他验证码试试,但是样本量越多越好。
总结
首先本文教大家如何简单处理验证码,然后介绍了tensorflow的快速安装方式,最后通过实现了CNN下整块验证码的识别,训练集准确率达到99.5%,测试集准确率在40%左右。如果调低keep_prob的值,增加样本量,增加卷积层,最后的预测效果应该会更好。
希望大家以后在tensorflow的学习道路中少点阻碍!!!
人工智能
2018-11-08 19:19:00
「深度学习福利」大神带你进阶工程师,立即查看>>> 2018 年是见证「奇迹」的一年。AI 从多年的热门话题中开始走下神坛,逐渐深入到了各个行业,加速经济结构优化及行业智慧化升级,AI 已不再是难以企及的神话而是可触摸的美好未来。 政策支持加上资本推动,无论是从新兴行业还是传统行业都出现了人工智能方面的布局者和佼佼者,智慧教育、移动社交、智能语音、智慧客服、传统媒体等行业都在突破技术上和流程上的难点和困惑。
11 月 23 日,一场由七牛云主办主题为「AI 产业技术的渗透与融合」的 NIUDAY 小牛汇共享日将在北京举行。会上,将邀请众多行业内知名企业及技术专家,针对当前 AI 在技术上以及行业中遇到的一些壁垒问题,进行深入探讨和分享。
连线行业专家,洞悉专业视点
人工智能技术在飞速发展过程中得到了国家以及政府的极大关注与大力支持,中国人工智能产业发展联盟作为国家发展改革委、科学技术部、工业和信息化部、中央网信办四部委共同指导下的人工智能产业权威联盟机构,也将加入到此次 NIUDAY 小牛汇共享日活动中来。
中国信息通信研究院人工智能部副主任,中国人工智能产业发展联盟总体组组长、数据中心联盟秘书长孙明俊女士将出席本次活动,并将从行业专家的角度带来主题为《人工智能产业发展水平分析》的演讲,向大家解析产业发展水平、分享行业利好政策等。
智慧教育、移动未来,体验指尖上的 AI
在此次活动中,除行业专家的视点剖析之外,对于 AI 与行业的渗透与融合度是理论大于实践亦或是理论与实践已完美结合,已经应用的行业代表案例有哪些?对于这些问题,大家可以在此次活动中得以解惑。
科技发展教育先行,技术与教育的结合又将碰撞出怎样的火花,会上,将有好未来 SEG 智慧教育事业部技术总监谢华亮带来主题为《AI 在教育行业中的应用》的精彩演讲。
移动互联网的发展已影响到我们身边的每一个人,游戏、娱乐、社交等手机平台的火爆更是带来了巨大的信息流量。但如何应对这些突然爆发的信息流,如何让产品与技术更好地去结合以吸引更多的受众人群,成为人们关注的话题。以作为专注于移动互联网社交的知名企业 Blued 为例,实践与技术并重的技术专家佘超杰将分享给我们《AI 在 Blued 上的应用》。
手机电商、手机软件系统的快速更迭让在线客服、移动客服有了更大的发展空间,成了市场中的一片蓝海,究竟现状如何、客户体验的真实反馈是什么?环信 CEO 刘俊彦先生带来的《人工智能赋能客户互动之现状与未来》让你更贴近生活,更能体会 AI 的无处不在。
战略签约中国网 传统与创新的再突破
值得一提的是,本次 NIUDAY 小牛汇共享日活动上七牛云将与中国互联网新闻中心举行战略合作签约仪式。届时,中国互联网新闻中心·中国网副总编辑杨新华先生将带来《AI 如何讲好中国故事》的演讲,介绍七牛云在未来媒体平台构建中发挥的作用,以及正处于变革中的媒体行业对 AI 的思考。
当然作为本次 NIUDAY 小牛汇活动的主办方,七牛云也准备了满满的干货带给大家。七牛云技术总监陈超《数据智能时代的智慧工厂实践》、七牛云人工智能实验室资深产品经理杨叶青《一站式审核助力无忧运营》带你体会七牛云两大重要产品线的技术与发展。
更多大咖嘉宾,请往下看~
点击 「阅读原文」
立即报名!
人工智能
2018-11-08 14:32:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
2018年11月7日晚,被称为“深度学习三巨头”之一的蒙特利尔大学计算机科学与运算研究系教授Yoshua Bengio在清华大学做了《深度学习抵达人类水平人工智能所面临的挑战(Challenges for Deep Learning towards Human-Level AI》的学术报告。Yoshua Bengio教授客观的说,目前人工智能距离人类水平还仍然十分遥远,人工智能在工业应用的成功主要得益于监督学习方法,人工智能仍然面临巨大挑战,尤其在人类智能机理方面的研究还亟需加强。在报告中,Yoshua Bengio深度探讨了深度学习模型的具体内容,如何实现对抽象特征的多层次学习,如何更好地进行表示学习,使用判别器优化信息间的独立性、相关性和熵,Baby AI框架等话题。
Yoshua Bengio
Yoshua Bengio教授是蒙特利尔大学计算机系教授和加拿大科学院院士,被称为神经网络三巨头之一。著有《Deep Learning》、《Learning Deep Architectures for AI》、《A neural probabilistic language model》等多部畅销书/课本。在他的倡导下,加拿大成立了Mila研究院,专注研究人工智能和深度学习。也正是因为在深度学习方面的重要贡献,Yoshua Bengio教授获得了加拿大总督功勋奖,该奖项主要为了纪念做出了卓越成就或者对国家做出了重大贡献的各领域人士,是加拿大公民的最高荣誉之一。
人工智能
2018-11-13 13:50:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 蚂蚁金融科技全面开放战略的公布,意味着蚂蚁金融科技正式进入全新的3.0时代。蚂蚁金融科技15年来的演进,在其发展史上不断留下了技术里程碑,同时,也缔造出一个又一个的业界“奇迹”。本文将深度揭秘蚂蚁金服的技术战略及布局。
导读: 蚂蚁金融科技全面开放战略的公布,意味着蚂蚁金融科技正式进入全新的3.0时代。蚂蚁金融科技15年来的演进,在其发展史上不断留下了技术里程碑,同时,也缔造出一个又一个的业界“奇迹”。本文将深度揭秘蚂蚁金服的技术战略及布局。
11月7日,第五届世界互联网大会在浙江乌镇开幕。当天下午,代表着行业最高水准的“世界互联网领先科技成果”发布,蚂蚁金服自主可控的金融级商用区块链平台等十余项先进技术获得此项殊荣。
11月8日,世界互联网大会上由中国人民银行科技司主办的“金融科技与信用社会建设”主题论坛,蚂蚁金服宣布基于网络黑灰产防控治理的“天朗计划”全面升级,将蚂蚁风险大脑对传销、非法集资、金融诈骗等金融风险防控融入其中,同时,蚂蚁风险大脑也将会全面赋能合作伙伴,为其业务发展保驾护航,为投资者和消费者提供一个天朗气清的网络空间。
而在同期举行的 “互联网之光”博览会上,蚂蚁金服不仅展示了15年来的技术演进之路,而且重点展示了区块链技术和蚂蚁风险大脑等相关产品及解决方案。
蚂蚁金服15年技术演进之路
经过15年的发展,蚂蚁金服已经成长为中国最重要的金融科技平台。除了支付、信贷、保险、理财、征信等众多业务,在金融技术的研发、投入及开放上,也已深耕不辍了多年。最初的蚂蚁金融云逐渐演变,在积累了众多云计算能力和技术组件的基础上,早已超越了传统金融云的概念,而囊括了云计算、大数据、AI、IoT、区块链等一整套技术体系。我们势必需要重新认识蚂蚁金服,将它的立体与多维展现出来,让金融科技的价值被真正重视!
全面开放:数字金融技术整体解决方案
当下,以支付宝为代表的蚂蚁金服的产品从一开始就要接受来自于网上的各种检验、钓鱼、攻击、窃取。面对一个开放的系统,没有办法关起门来,需要去研发各种技术,这对技术能力是非常大的考验。3年前,蚂蚁金服启动了“互联网推进器”计划,该计划表明,蚂蚁金服将在5年内助力超过1000家金融机构向新金融转型升级,在平台、数据和技术等方面实施能力全面对外开放。
从2015年蚂蚁金融云发布到2016年GeaBase在支付场景上线,从2017年OceanBase 三地五中心集群部署到2018年“蚂蚁风险大脑”上线,蚂蚁金融科技开放一直在往纵深方向发展。
到了今天,蚂蚁金服已经逐渐形成了“点线面”相结合的技术解决方案体系,包含了海量金融交易技术、金融智能技术、新一代金融交互技术、金融安全、区块链、综合技术等。在蚂蚁金融科技的大版图上,强调“技术开放”,而不是“技术输出”,或许这不仅仅是喊的口号不同,更是因为两者所导致的结果是真正差异化的:“开放”更具开源精神,它助推着金融科技的融合与创新,让新金融变成了“更好的金融”。
在此前云栖ATEC主论坛上,蚂蚁金服副CTO胡喜就宣布,蚂蚁金服的金融科技正式全面开放,为行业提供完整的数字金融解决方案。包括容灾系统在内的多项核心技术和解决方案,如金融安全、蚂蚁风险大脑、区块链等都将对合作伙伴开放。
五大关键技术详解:蚂蚁金服的“完整答卷”
除了让金融机构摆脱传统IT架构的束缚外,蚂蚁金服也成就了自己世界级的技术能力。在多条重要技术主线上,无数的金融场景都能被一一对应,蚂蚁金服也由此不断进入“新领地”,在技术前沿展开探索。因此,主要梳理的技术主线有如下5条:
海量金融交易技术
交易技术是支付宝创造“人间奇迹”的起点。2017年的“双11”,支付宝凭借多项新纪录成为当天的主角:11秒钟破亿,28秒钟破10亿,3分01秒破100亿,6分05秒钟破200亿。根据支付宝官方数据,第5分22秒,双11的支付峰值达到25.6万笔/秒,同时蚂蚁金服自主研发的数据库处理峰值达到4200万次/秒,双双创下新纪录。
而海量金融交易技术的背后,其实是分布式架构所带来的创新优势,敏捷迭代、容灾安全、弹性伸缩构成了分布式架构转型升级的三大驱动力。其中,OceanBase分布式数据库、SOFA ware分布式中间件、CAF?容器云平台三大技术构成了蚂蚁金服金融级的分布式架构。
金融交易技术最关键的目标是“数据不丢失,业务不停机”。目前,TRaaS 技术风险防控平台(Technological Risk-defence as a Service)已一跃成为技术风险领域最为成熟的产品,在高可用架构(异地多活、全链路压测)、资损防控(交易实时核对、自动决策)、智能运维(AIOps故障自愈)等功能上做到了极致。
而金融级分布式架构SOFAStack(Scalable Open Financial Architecture Stack)专注为金融用户提供安全、敏捷的基础架构能力,解决传统集中式架构转型的困难,将传统集中式架构转变为分布式系统架构。以人保健康为例,借助SOFAStack,其互联网保险云核心业务处理能力提升了上千倍,并支持弹性扩容,出单时间达到每秒1000单,外部渠道产品接入效率提升6倍,新产品上线时间缩短80%以上。经过四代架构演进,八年“双十一”的考验,现在SOFA已经从中间件这一层开始,逐渐对外进行开放和开源。
金融安全技术
安全是蚂蚁金服BASIC五大技术开放战略之一(Blockchain区块链、Artificial intelligence金融智能、Security安全、IoT物联网和Computing计算),事实上十多年以来,在业务场景的迫切需求的驱动下,蚂蚁金服的风控技术也经历了多次升级迭代,才发展成一套以AI智能算法、生物核身为基础的多层级立体闭环风控系统——蚂蚁风险大脑(Risk Brian)。人脸识别、指纹识别、虹膜识别、活体检测等技术加上智能设备终端、传感器识别等共同组成了蚂蚁风险大脑数字核身解决方案。
面对日益复杂的新金融场景监管,地方金融监管机构正在承担越来越多的责任,同时监管痛点也逐步显现出来。而当下,蚂蚁风险大脑集风险感知、风险识别、智能进化、自动策略调整4大功能为一身,已形成了“金融消费者教育预警”、“7+4行业监测”、“涉众金融风险防控”、“金融风险联动处置”、“投资人信访登记”等完整的防控链路。目前,蚂蚁风险大脑已与北京、天津、广州等多个地方金融监管部门建立合作,共同保护消费者合法权益。
全面、多样化的数字身份认证体系也是安全技术一大亮点。运用ZOLOZ(生物认证),对人脸识别的准确率高达99.99%, 覆盖2亿+互联网金融用户,确保20亿+次交易安全;运用IFAA(本地生物认证框架),实现覆盖终端设备12亿台,支持380款Android手机,TEE级别、高安全性,设备接入轻量快速低成本,周期从4个月降至1周内。除此之外,AlphaRisk (智能风控引擎)在风险感知、风险识别、智能进化、自动驾驶上也有着诸多应用,向着自动化、自学习、高准确率、高计算性能、自适应的方向进化。
金融智能决策技术
蚂蚁金服的金融智能决策技术与旗下网商银行独创的“310”模式息息相关。“310”即“3分钟申请、1秒钟到账、0人工干预”的服务标准,至今服务了1000万中小微企业的贷款。2018年6月,蚂蚁金服董事长兼CEO井贤栋透露,网商银行将启动“凡星计划”:未来三年,网商银行将与1000家各类金融机构合作,服务3000万家小微企业和个体经营户。
在过去,发放一笔小微企业贷款的平均人力成本在2000元,而网商银行通过技术支撑的“310”模式,让每笔贷款的平均运营成本降低至2.3元,其中2元是计算和存储硬件等技术投入费用。可以说,技术降低了金融服务的成本,实现了商业上的可持续发展。
具体运行方式上,金融智能决策技术涉4大步骤,分别是数据的采集与计算、AB试验体系和BI深度分析、统一指标与策略管理、模拟训练和预测平台等,至今已积累10万余项指标体系、3000多种风控策略,仅行业化风控模型就建立100多个。与此同时,在2017双11支付宝 25.6万笔支付每秒也需要其迅速做出大量高效的决策,最难得的是其资损率一直小于百万分之0.5的水平,交易资金的安全性得到了高度保障。
新一代金融交互技术
在新一代金融交互技术上,蚂蚁金服有着坚实的中台能力,新一代mPaaS平台,让客户端运行更为高效与稳定;小程序的组件和API则将支付宝特色能力与系统原生能力做了紧密地结合,实现了一次开发多端投放,并可以无缝迁移支付宝小程序到自己的App中;Ant Design让用户研究、交互模式、设计语言等形成了良好的循环圈,将终端用户的体验提升到了极致。
具体来看,开发者能够利用蚂蚁金服移动开发平台mPaaS做好移动App的开发、管理、发布,并做好App全生命周期的管理,其中包括了开发期的研发测试、打包构建、发布管理,还有发布之后的用户行为分析、闪退分析等。2018年9月27日,支付宝小程序一站式云服务正式开放公测,为小程序开发者提供了完整的云端支持,让开发者无需自己搭建服务器,即可实现支付宝小程序的快速上线和迭代,大大节省开发成本、加快开发速度。
如果说PaaS平台是对企业后台服务的生命周期的管理,包括研发、发布、监控这一套流程,那么mPaaS就是对移动应用App一整套全生命周期的管理服务,能有效降低技术门槛、减少研发成本、提升开发效率,协助金融机构快速搭建稳定高质量的移动应用。
区块链技术
蚂蚁金服自研可控的金融级区块链平台已经在多个社会和商业应用场景实现多机构、多国全球部署,提供面向政府、企业和普通百姓的各类数字服务。同时,蚂蚁区块链解决了很多区块链产业面临的技术挑战,在性能、安全性以及跨链交互等多个技术难点的研究与攻关进展方面均处于世界前列,已经具备金融级平台所需要的高性能、高可靠和高安全的技术特点。
蚂蚁金服区块链总体定位是做一个信任连接的基础设施,与信美人寿相互保险社的合作是其区块链技术的试水,而在天猫跨境电商溯源、茅台溯源这两个可信的溯源服务上,区块链技术日臻成熟。2017年11月,蚂蚁金服正式上线关于天猫境外商品的跨境溯源的服务。在这个场景中,支付宝用户从天猫针对来自澳洲、新西兰26个商品、奶制品提供了关于每一瓶奶制品的身份证的溯源码服务。
目前,蚂蚁金服在区块链领域申请了160多件专利,国家专利局公开授权的有65件,在知识产权产业媒体IPRdaily最新发布的《2018年全球区块链专利企业排行榜》排名第一。目前,蚂蚁区块链的专利方向主要集中于底层技术,并将这些技术首先应用在公益慈善、食品安全、跨境汇款、房屋租赁等更具社会价值的民生领域。
2018年6月25日,蚂蚁金服宣布全球首个基于区块链技术的电子钱包跨境汇款服务在香港上线。在香港工作22年的菲律宾人Grace幸运地第一个尝鲜,整个汇款过程耗时仅3秒,而在以前需要短则10分钟、长则几天。在区块链技术的支持下,支付宝香港钱包可以为在港菲律宾劳工提供7×24小时不间断的跨境汇款服务,实现3-6秒汇款到账服务体验。同时,大大降低了多方对账成本。据了解,蚂蚁金服依次攻克了符合各国监管要求的隐私保护设计、区块链节点跨境多地多机房部署、低延时智能合约交易确认等技术难题。
“BASIC”综合技术实力跻身一线
可以说,除了上文介绍的数字金融五大关键技术,蚂蚁金服的综合技术实力在经历了“原始积累”之后,已经跻身一线技术厂商。“BASIC”是现在的蚂蚁金服最常提到的核心技术能力,即Blockchain(区块链)、AI(金融智能)、Security(安全)、IoT(物联网)、Computing(计算),未来所有的金融科技都围绕着这些技术来展开并实施开放开源。
此外,蚂蚁金服完全自主研发的OceanBase 是高性能、高可扩展、数据强一致的金融级分布式关系型数据库,具备丰富的关系数据库功能,支持完整的 ACID 特性,首创的“三地五中心”城市级故障无损容灾方案正成为越来越多金融机构核心系统高可用的选择。OceanBase还高度兼容 MySQL,让用户能够以最小的迁移成本使用高性能、可扩展、持续可用的分布式数据库服务,同时对用户数据提供金融级可靠性的保障。
而在最近几年被业界广泛关注的图数据库领域,蚂蚁金服经过3年多的探索,也自主研发出多项指标领先业界的金融级分布式图数据库GeaBase。GeaBase具备高性能、高可用、高扩展性及可移植性强等多重特性,支撑着蚂蚁金服旗下支付的风险控制、反洗钱、反欺诈、反刷单、反套现、金融案件审理、知识图谱、会员拉新、好友推荐、理财资讯推荐等众多的业务和应用。目前,GeaBase不仅广泛应用于蚂蚁金服的生态体系内,而且已经技术对外开放,正与多家银行等企业开展合作。
从开放到开源,蚂蚁金服的“暖科技”在探索新的空间
蚂蚁金服是最早提出技术开放的企业之一。在2015-2018三年间,从“互联网推进器计划”到“成熟一个开放一个”,蚂蚁金服公布的产品数量从5个增长到了80个,解决方案从3个发展到了50个,未来将以“蚂蚁金融科技”为技术输出品牌。现在,蚂蚁金融科技正式进入了3.0时代:支付宝对内延续“BASIC”战略,对外开放的技术越来越完整、越来越核心,是成建制、有体系的全面开放,并实现了技术商业化。
业务上,实现了余额宝开放、借呗开放、花呗开放、小微企业贷款开放、蚂蚁财富平台、蚂蚁保险平台、蚂蚁森林等的开放……
能力上,实现了小程序、生活号、实名核身能力、信用能力、风控能力、会员运营能力的开放……
技术上,实现了区块链、金融智能、金融安全、金融分布式框架、移动开发、金融分布式数据库等100%开放……
此外,在开源这条路上,蚂蚁金服一直保持着自己的节奏。
2016年5月,企业级产品的设计体系Ant Design 1.0正式发布;
2016年9月,企业级Node.js框架Egg宣布开源;
2017年11月,专业的数据可视化解决方案AntV 3.0发布;
2018年1月,首届蚂蚁金服体验科技大会在杭州蚂蚁Z空间成功举办;
2018年4月,Ant Design成为国内公司star数最多的开源项目;
2018年4月,蚂蚁金服启动分布式中间件开源计划,用于快速构建金融级云原生架构。
......
蚂蚁金服副CTO胡喜此前表示,蚂蚁金服内部建立了一个开源共建的体制,代码完全开放,其他业务的垂直BU自己也可以实现定制化需求。
蚂蚁金服CTO程立曾说过,蚂蚁金服不是为了做技术本身而做技术,而希望用技术来解决社会当下和未来的问题。如果说用金字塔结构来描绘数字金融的社会价值,在塔顶的就是数字金融能在全球范围内带来更多平等的机会。
同样,面向未来的技术探索与挑战,对“数据不丢失,业务不停机”保持极致追求,让整个数字世界变得安全可信,给全世界每一个人可信数字身份,在IoT的海量数据之上实时安全计算,蚂蚁金服责无旁贷。
原文链接
人工智能
2018-11-13 11:33:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 关于矩阵和张量的区别有些人可能不太清楚,看了这篇文章相信你会很明白了
这个问题有一个简短的答案,让我们从那里开始吧。然后,我们可以查看一个应用程序以获得更深入的了解。
矩阵是由括号括起的n×m(例如,3×3)个数字的网格。我们可以加上和减去相同大小的矩阵,只要大小兼容((n×m)×(m×p)= n×p),就将一个矩阵与另一个矩阵相乘,以及可以将整个矩阵乘以常数。向量是一个只有一行或一列的矩阵(但见下文)。因此,我们可以对任何矩阵进行一系列数学运算。
不过,基本的思想是,矩阵只是一个二维的数字网格。
张量通常被认为是一个广义矩阵。也就是说,它可以是1-D矩阵(一个向量实际上就是一个张量),3-D矩阵(类似于一个数字的立方),甚至是0-D矩阵(单个数字),或者一个更难形象化的高维结构。张量的维数叫做它的秩。
但是这个描述忽略了张量最重要的性质!
张量是一个数学实体,它存在于一个结构中并与其他数学实体相互作用。如果以常规方式转换结构中的其他实体,那么张量必须服从一个相关的变换规则。
张量的这种“动态”特性是将其与单纯矩阵区分开来的关键。它是一个团队成员,当一个影响到所有成员的转换被引入时,它的数值会随着队友的数值而变化。
任何秩-2张量都可以表示为一个矩阵,但并不是每个矩阵都是秩-2张量。张量矩阵表示的数值取决于整个系统应用了什么变换规则。
对于您的目的,这个答案可能已经足够了,但是我们可以通过一个小例子来说明它是如何工作的。这个问题是在一个深度学习研讨会上提出的,所以让我们看一下该领域的一个简单例子。
假设我在神经网络中有一个隐藏的3个节点层。数据流入它们,通过它们的ReLU函数,然后弹出一些值。对于确定性,我们分别得到2.5,4和1.2。 (别担心,图表即将出现。)我们可以将这些节点的输出表示为向量,
假设有另外一层3个节点。第一层的3个节点中的每个节点都有一个权重,该权重与其对接下来3个节点的输入相关联。那么,将这些权重写为3×3矩阵的条目将是非常方便的。假设我们已经对网络进行了多次更新,并得到了权重(本例中半随机选择)。
在这里,一行的权值都到下一层的同一个节点,而某一列的权值都来自第一层的同一个节点。例如,输入节点1对输出节点3的权值是0.2(第3行,第1列)。 我们可以通过将权重矩阵乘以输入向量来计算馈入下一层节点的总值,
不喜欢矩阵?这里有一个图。数据从左到右流动。
太棒了!到目前为止,我们所看到的只是矩阵和向量的一些简单操作。
但是,假设我想对每个神经元进行干预并使用自定义激活函数。一种简单的方法是从第一层重新缩放每个ReLU函数。在本例中,假设我将第一个节点向上扩展2倍,保留第二个节点,将第三个节点向下扩展1/5。这将改变这些函数的图形如下图所示:
这种修改的效果是将第一层生成的值分别乘以2、1和1/5。等于L1乘以一个矩阵A,
现在,如果这些新值通过原来的权值网络被输入,我们得到完全不同的输出值,如图所示:
如果神经网络之前运作正常,我们现在就把它破坏了。我们必须重新进行训练以恢复正确的重量。
或者我们会吗?
第一个节点的值是之前的两倍。 如果我们将所有输出权值减少1/2,则它对下一层的净贡献不变。我们没有对第二个节点做任何处理,所以我们可以不考虑它的权值。最后,我们需要将最后一组权值乘以5,以补偿该节点上的1/5因子。从数学上讲,这相当于使用一组新的权值,我们通过将原权矩阵乘以A的逆矩阵得到:
如果我们将第一层的修改后的输出与修改后的权值结合起来,我们最终会得到到达第二层的正确值:
太好了!尽管我们做出了最大努力,但网络仍在重新运作!
好了,我们已经学了很多数学了,让我们回顾一下。
当我们把节点的输入,输出和权值看作固定的量时,我们称它们为向量和矩阵,并用它完成。
但是,一旦我们开始用其中一个向量进行修复,以常规方式对其进行转换,我们就必须通过相反的方式转换权值来进行补偿。这个附加的、集成的结构将单纯的数字矩阵提升为一个真正的张量对象。
事实上,我们可以进一步描述它的张量性质。如果我们把对节点的变化称为协变(即,随着节点的变化而乘以A),那么权值就变成了一个逆变张量(具体来说,对节点变化,乘以A的倒数而不是A本身)。张量可以在一个维度上是协变的,在另一个维度上是逆变的,但那是另外的事了。
现在你知道了矩阵和张量之间的区别了吧。
原文链接
人工智能
2018-11-12 12:31:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 网络安全遇见机器学习,会摩擦出怎样的火花呢?
网 络 安全任 务 和机器学 习
让我们看看常见的网络安全任务和机器学习结合的机会,而不是查看ML任务并尝试将它们应用于网络安全。具体我们需要考虑三个维度(Why,What和How)。
第一个维度是目标或任务(例如,检测威胁,攻击预测等)。根据 Gartner 的 PPDR 模型,所有安全任务可分为五类:
1. 预测 ;
2. 预防 ;
3. 检测 ;
4. 响 应 ;
5. 监测 。
第二个维度是技术层和“什么”问题的答案(例如,在哪个级别监控问题),以下是此维度的图层列表:
1. 网 络 (网 络 流量分析和入侵 检测 ) ;
2. 端点(反 恶 意 软 件) ;
3. 应用程序( WAF 或数据 库 防火 墙 ) ;
4. 用 户行为分析 ( UBA ) ;
5. 过程(反欺诈) 。
每个图层都有不同的子类别。例如,网络安全可以是有线、无线或云。请放心,至少在不久的将来,你不能将具有相同超参数的相同算法应用于两个区域。因为缺少数据和算法来找到对这三个区域都很友好的方法,因此可以将一个算法更改为不同的算法。
第三个维度是“如何”的问题(例如,如何检查特定区域的安全性):
1. 实时检测 ;
2. 静态检测 ;
3. 历史查看 ;
例如,如果你要查看端点保护,查找入侵,则可以监视可执行文件的进程,执行静态二进制分析,分析此端点中的操作历史记录等。
有些任务应该从三个方面解决。有时,对于某些任务,某些维度中没有值。我们需要从其他维度来找到解决方法。这些通常很难详细介绍它们,所以我们关注最重要的维度-技术层。从这个角度看网络安全解决方案。
用于网 络 保 护的 机器学习
网络保护不是单一领域,而是一系列不同的解决方案,专注于以太网、无线、SCADA甚至SDN等虚拟网络等协议。
网络保护是指众所周知的入侵检测系统(IDS)解决方案。网络安全中的ML意味着称为网络流量分析(NTA)的新解决方案,旨在深入分析每层的所有流量并检测攻击和异常。
ML 如何在这里提供帮助?有一些例子:
1. 回 归预测 网 络 数据包参数并与正常数据包 进 行比 较 ;
2. 分 类 以 识别 不同 类别 的网 络 攻 击 ,例如 扫 描和欺 骗 ;
3. 聚 类数据 用于分析;
你可以在学术研究论文中找到至少10篇描述不同方法的论文。
更多资源:
1. 入侵 检测 机器学 习 技 术 ;
2. 用于 时间 序列异常 检测 的 长 短期 记忆 网 络 ;
3. 基于 规则 提取的高效入侵 检测 异常 检测 框架 ;
4. 网 络 异常 检测 技 术综 述 ;
5. 浅 层 和深 层 网 络 入侵 检测 系 统 :分 类 与 调查 ;
6. 深度数据包:一种利用深度学 习进 行加密流量分 类 的新方法 ;
7. 入侵 检测 系 统 的性能比 较 及机器学 习 在 Snort 系 统 中的 应 用 ;
8. 入侵 检测 系 统 机器学 习 算法 评 估 ;
9. 基于 LSTM 的一 类 集体异常 检测 ;
10. 基于 递归 神 经 网 络 的网 络 流量异常 检测 ;
11. 计算机网络流量异常检测的序列聚合规则 ;
12. IDS 所有方法的大集合 ;
用于端点保 护 的机器学 习
新一代的反病毒是端点检测和响应,建议最好学习可执行文件或进程行为中的特征。
请记住,如果你在端点层处理应用机器学习,你的解决方案可能会有所不同,具体取决于端点类型(例如工作站、服务器、容器、云端、移动设备、PLC、物联网设备)。每种端点都有自己的细节,常见任务类别:
1. 回 归 以 预测 可 执 行 过 程的下一个系 统调 用,并将其与 实际过 程 进 行比 较 ;
2. 将程序划分 为恶 意 软 件、 间谍软 件和勒索 软 件等 类别 的分 类 ;
3. 聚类在安全 电 子 邮 件网关上 进 行 恶 意 软 件保 护 (例如将法律文件附件与异常 值 分开);
关于端点保护和恶意软件的学术论文特别受欢迎。这里有一些论文:
1. 通 过 侵蚀整个 EXE 进行恶意软件检测 ;
2. 浅 层 深度学 习 :非域 专 家的 恶 意 软 件分 类 ;
3. TESSERACT :消除跨空 间 和 时间 的 恶 意 软 件分 类 中的 实验 偏差 ;
用于应用程序安全的机器学习
在app安全性中使用ML?用于静态和动态的WAF或代码分析?不得不提醒你一下,应用程序安全性可能有所不同。因为他们有很多应用场景:比如说有Web应用程序、数据库、ERP系统、SaaS应用程序、微服务等。在不久的将来,几乎不可能建立一个通用的ML模型来有效地处理所有威胁。但是,你可以尝试解决某些任务。
以下是使用机器学习实现应用程序安全性的示例:
1. 回 归 以 检测 HTTP 请求中的异常(例如, XXE 和 SSRF 攻 击 以及 auth 旁路) ;
2. 用于 检测 已知 类 型的攻 击 (如注入( SQLi , XSS , RCE 等))的分 类 ;
3. 集中用 户 活 动 以 检测 DDOS 攻 击 和大 规 模利用。
更多资源:
1. 自适 应检测 Web 攻 击 中的 恶 意 查询 ;
2. 恶意脚本的神经分类:使用 JavaScript 和 VBScript 进行的研究 ;
3. URLNet :通 过 深度学 习 学 习 URL 表示以 进 行 恶 意 URL 检测 ;
用于用 户 行 为 的机器学 习
这类任务需求始于安全信息和事件管理(SIEM)。如果配置正确,SIEM能够解决许多任务,包括用户行为搜索和ML。然后,UEBA解决方案宣称SIEM无法处理新的,更高级的攻击类型和持续的行为更改。
如果从用户层面考虑威胁,市场已经接受了需要特殊解决方案的观点。
但是,即使最高级的UEBA工具也不包括与不同用户行为相关的所有内容。(域用户、应用程序用户、SaaS用户、社交网络、信使和其他应该监控的帐户)。
与常见攻击的恶意软件检测和训练分类器的可能性不同,用户行为属于无监督学习问题之一。通常,没有标记数据集以及要查找的内容。因此,为所有类型的用户创建通用算法的任务在用户行为区域中是棘手的。以下是公司在ML的帮助下解决的任务:
1. 回 归 以 检测 用 户 操作中的异常(例如,在异常 时间 登 录 ) ;
2. 分 类 以将不同用 户 分 组 以 进 行 对 等 组 分析 ;
3. 聚 类 以分离用 户组 并 检测 异常 值 。
更多资源: 使用扩展隔离算法检测异常用户行为;
用于进程行为的机器学习
进程区域是最后但并非最不重要的,在处理它时,有必要知道一个大致的业务流程,以便找到异常值。注意不同行业的业务流程可能有很大差异。你可以在银行和零售系统或制造厂中查找欺诈行为。两者完全不同,找到它们的不同需要很多领域知识。机器学习特征工程(将数据表示为算法的方式)对于实现结果至关重要。同样,特征在所有进程中都不同。
通常,进程行为也有任务示例:
1. 回 归:预测 下一个用 户 行 为 并 检测 信用卡欺 诈 等异常 值 ;
2. 分 类:检测 已知 类 型的欺 诈 ;
3. 聚 类: 比 较业务 流程和 检测 异常 值 。
更多资源: 信用卡欺 诈检测 技 术综 述:面向数据和技 术 的 视 角 ; 异常 检测 , 工 业 控制系 统 : 卷 积 神 经 网 络 ;
机器学 习 网 络 安全 书 籍
如果你想了解有关网络安全中机器学习的更多信息,可以阅读以下书籍:
1. Cylance 的网 络 安全 AI ( 2017 ) - 对网络安全 ML 的基 础 知 识 的 简 短,而且有很好的 实际 例子。
2. O'reilly 的机器学 习 和安全 ( 2018 ) - 迄今 为 止关于 这 个主 题 的最佳 书 籍,但很少 关于深度 学 习 的例子,大多是一般的 ML 。
3. Packt 的渗透 测试 机器学 习 ( 2018 ) - 不像前一个那么优秀,但有很多的深度学 习 方法。
4. 恶意软件数据科学:攻击检测和归因 ( 2018 ) - 从 标题 中可以看出,这本 书 主要关注 恶 意 软 件。它 刚刚 在撰写本文 时发 布,所以到目前 为 止我无法 给 出任何反 馈 。但我相信, 这对 端点保 护团队 的每个人来 说 都是必 须 的。
结论
如果你想保护你的系统,机器学习绝对不是一个银弹解决方案。毫无疑问,可解释性存在许多问题(特别是对于深度学习算法)。另一方面,随着数据量的增加和网络安全专家数量的减少,ML是唯一的补救措施。它现在有效,很快就会执行。现在最好开始做这些。因为请记住,黑客也开始在攻击中使用ML。
原文链接
人工智能
2018-11-12 11:52:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
tutorial5
1.运行ros内核 $ roscore
2.使用rosnode
rosnode list
rosnode info /rosout
3.运行一个节点 $ rosrun [package_name] [node_name]
4.测试节点是否在线 $ rosnode ping my_turtle
人工智能
2018-11-12 11:30:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 网络安全遇见机器学习,会摩擦出怎样的火花呢?
相当多的文章已经描述了机器学习在网络安全的应用以及保护我们免受网络攻击的能力。尽管如此,我们仍然需要仔细研究人工智能(AI)、机器学习(ML)和深度学习(DL),它们到底能不能像炒作内容所说的无所不能。
首先,我要让你失望了。我通过研究发现与图像识别或自然语言处理相比,机器学习永远不会成为网络安全的灵丹妙药,而这两个领域的机器学习应用正在蓬勃发展。因为总会有人试图找到系统或ML算法的弱点并绕过安全机制。更糟糕的是,现在黑客能够利用机器学习来完成他们邪恶想法。
幸运的是,机器学习可以帮助解决最常见的任务,包括回归,预测和分类。在数据量极大且网络安全人才短缺的时代,ML似乎又是唯一的解决方案。
本文介绍了实际应用于网络安全的ML研究的当前进展和未来方向的实用技术理解。
机器学 习术语 AI (人工智能) 是一个广泛的概念。简单来说是通过技术使机器变得聪明或者换言之通过机器算法(例如视觉识别,自然语言处理等)进行人工任务。重点是AI不是机器学习或自动化的机器。它可以是安装在清洁机器人中的经典程序,如边缘检测。总的来说,AI是以某种方式执行人工任务的系统。 ML (机器学 习 ) 是人工智能的一种方法,它是一种能够从经验中学习的系统。它不仅可以复制人类行为,而且还可以减少用于困难任务(如股票价格预测)的工作量和时间。换句话说,ML是一个可以通过使用示例而不是通过编程来识别模式的系统。如果你的系统经常学习,根据数据而不是算法做出决策,并改变其行为,那就是机器学习。 DL (深度学 习 ) 是一套用于实现机器学习的技术,例如图像识别系统,系统主要识别对象边缘、结构、对象类型、然后识别对象本身。重点是深度学习并不完全是深度神经网络,它还有其他算法,它们被改进以学习模式模式,例如强化任务中的迁移学习。
定义表明,网络安全领域主要指机器学习(而不是AI),而且很大一部分任务与人类无关。
机器学习意味着使用基于你拥有的数据和特定方法来解决某些任务。
大多数最常见的任务,如下所述: 回归(或预测)-基于先前值预测下一个值的任务; 分类-将事物分成不同类别的任务; 聚类-类似于分类,但类是未知的,通过它们的相似性对事物进行分组; 关联规则学习(或推荐)-基于先前经验推荐某事的任务; 降维—是在多个示例中搜索常见和最重要特征的任务; 生成模型:基于先前的分布知识创建内容的任务。
对于某些任务,你只能使用一种方法,但可以有多种方法用于其他任务。
ML 的趋势
过去的趋势 监督学习: 首先,你应该标记数据,例如向模型提供可执行文件的示例,并说该文件是恶意软件。基于此标记数据,模型可以决定新数据,缺点是标记数据的限制。 Eensemble (集成) 学 习 : 这是监督学习的扩展,同时混合不同的简单模型来解决任务。
当前的 趋势 无 监 督学 习 : 数据驱动模式,当没有标记数据时,可以使用该方法,并且模型可以以某种方式基于属性自行标记它。通常,它旨在发现数据中的异常,因为几乎不可能标记所有数据。 半 监 督学 习 : 顾名思义,当有一些标记数据时,半监督学习试图结合有监督和无监督方法进行学习训练。
未来的 趋势 强化学习: 当行为应该以某种方式对变化的环境做出反应时,可以使用环境驱动的方法。这就像一个通过反复试验来学习环境的孩子。 主 动 学 习 : 它更像是强化学习的子类,可能会成长为一个单独的类型。主动学习类似于教师,除了环境变化之外,还可以帮助纠正错误和行为。
机器学 习 和网 络 安全
让我们看一下可用于解决机器学习任务的不同方法的示例,以及它们与网络安全任务的关系。
回 归
回归(或预测)很简单。利用关于现有数据的知识来了解新数据。举一个房价预测的例子。在网络安全中,它可以应用于欺诈检测,通过特征(例如,可疑交易的总量,位置等)确定欺诈行为的概率。
至于回归这方面的技术,可以分为两大类:机器学习和深度学习。
机器学 习& 回 归
以下是可用于回归任务的机器学习方法的简短列表(具有各自的优缺点)。 线性回归 多项式回归 岭回归 决策树 SVR(支持向量回归) 随机森林
你可以 在此处 找到每种方法的详细说明 。
深度学 习& 回 归
对于回归任务,可以使用以下深度学习模型: 人工神经网络(ANN) 递归神经网络(RNN) 神经图灵机(NTM) 可微分神经计算机(DNC)
分 类
分类也很简单。想象一下,你有两堆按类型分类的图片(例如,狗和猫)。在网络安全方面,将垃圾邮件与其他邮件分开的垃圾邮件过滤器可以作为一个例子。垃圾邮件过滤器可能是应用于网络安全任务的第一种ML方法。
监督学习方法通​​常用于分类,其中某些组的示例是已知的,所有类都应该在开头定义。
下面是与算法相关的列表。
机器学习类 LogisticRegression(LR) K-Nearest Neighbors(K-NN) 支持向量机(SVM) KernelSVM NaiveBayes DecisionTreeClassification 随机森林分类
SVM 和随机森林这样的方法被认为是效果最好的,但是请记住,没有一个通用的规则。
深度学习类 人工神经网络 卷积神经网络
如果你有更多数据,深度学习方法会更好。但是,如果你计划在生产中使用它并定期重新训练系统,它们会消耗更多计算资源。
聚 类
聚类是类似于具有唯一但有主要差异的分类方式。有关数据类的信息未知,大致意思是不知道这些数据是否可以分类。这其实是无人监督的学习。
据推测,聚类的最佳任务是 取证分析 。事件的原因、过程和结果都很模糊,需要对所有活动进行分类以找出异常情况。 恶意软件分析 (即 恶意软件保护 或 安全电子邮件 网关)的解决方案可以实现它以将 法律 文件与异常值分开。
可以应用聚类的另一个有趣的领域是用户行为分析。在这种情况下,应用程序 用户 聚集在一起,以便可以查看它们是否应属于特定组。
通常,聚类不适用于解决网络安全中的特定任务,因为它更像是管道中的子任务之一(例如,将用户分组到单独的组中以调整风险值)。
用于聚 类 的机器学 习 K-最近邻居(KNN) K-means Mixturemodel(LDA) DBSCn 贝叶斯 GaussianMixtureModel Mean-shift 凝聚式层次聚类
用于聚类的深度学 习 自组织映射(SOM)或Kohonen Networks
关 联规则 学 习 (推荐系 统 )
Netflix 和SoundCloud根据你的电影或音乐偏好推荐电影或歌曲。在网络安全方面,这一原则主要用于事件响应。如果公司面临一系列事件并提供各种类型的响应,系统会学习特定事件的响应类型(例如,将其标记为误报、更改风险值、进行调查)。 如果风险管理 解决方案自动为新 漏洞 或基于其描述构建的错误配置分配 风险 值,那么它们可以带来很大的便利。
解决推荐任务的算法:
关 联规则 学 习 的机器学 习 Apriori Euclat FP-growth
关 联规则 学 习 的深度学 习 受限玻尔兹曼机(RBM) 深度信念网络(DBN) 堆叠式自动编码器
最新的推荐系统是基于首先玻尔兹曼机及其更新版本,例如有前途的深度新年网络。
降 维
降维或泛化不像分类那样受欢迎,但如果你处理具有未标记数据和许多潜在特征的复杂系统,那必须进行降维。你无法应用聚类,因为传统的方法会限制特征的数量,或者它们不起作用。降维可以帮助处理它并减少不必要的特征。与聚类一样,降维通常是更复杂模型中的任务之一。对于网络安全任务,降维是常见的面部检测解决方案。
用于降维的机器学 习 主成分分析(PCA) 奇异值分解(SVD) T分布式邻域嵌入算法(T-SNE) 线性判别分析(LDA) 潜在语义分析(LSA) 因子分析(FA) 独立分量分析(ICA) 非负矩阵分解(NMF)
你可以在 此处 找到有关降维的更多 信息 (包括方法及其功能的一般说明)。
生成模型
生成模型的任务不同于上述模型,虽然这些任务涉及现有信息和相关决策,但生成模型旨在根据先前的决策模拟实际数据(而不是生成决策)。
攻击性网络安全的任务是生成输入参数列表,以测试针对注入漏洞的特定应用程序。或者是拥有适用于Web应用程序的漏洞扫描工具。其中一个模块是测试文件以进行未经授权的访问。这些测试能够改变现有的文件名以识别新的文件名。例如,生成模型很擅长更擅长,如果爬虫检测到名为login.php的文件,最好通过尝试login_1.php,login_backup.php,login.php.2017等名称来检查是否存在任何备份或测试其副本。
用于生成模型的机器学 习 马尔可夫链 遗传算法
用于生成模型的深度学 习 变分自动编码器 生成对抗网络(GAN) 玻尔兹曼机器
最近,GANs取得了令人瞩目的成绩。他们成功地模仿了一段视频,我们可以想象一下它如何用于生成模糊测试的示例。
原文链接
人工智能
2018-11-12 11:20:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
软件:IDEA2014、Maven、HanLP、JDK;
用到的知识:HanLP、Spark TF-IDF、Spark kmeans、Spark mapPartition;
用到的数据集:http://www.threedweb.cn/thread-1288-1-1.html(不需要下载,已经包含在工程里面);
工程下载:https://github.com/fansy1990/hanlp-test 。
1、 问题描述
现在有一个中文文本数据集,这个数据集已经对其中的文本做了分类,如下:
其中每个文件夹中含有个数不等的文件,比如环境有200个,艺术有248个;同时,每个文件的内容基本上就是一些新闻报道或者中文描述,如下:
现在需要做的就是,把这些文档进行聚类,看其和原始给定的类别的重合度有多少,这样也可以反过来验证我们聚类算法的正确度。
2.、解决思路:
2.1 文本预处理:
1. 由于文件的编码是GBK的,读取到Spark中全部是乱码,所以先使用Java把代码转为UTF8编码;
2. 由于文本存在多个文件中(大概2k多),使用Spark的wholeTextFile读取速度太慢,所以考虑把这些文件全部合并为一个文件,这时又结合1.的转变编码,所以在转变编码的时候就直接把所有的数据存入同一个文件中;
其存储的格式为: 每行: 文件名.txt\t文件内容
如: 41.txt 【 日 期 】199601....
这样子的话,就可以通过.txt\t 来对每行文本进行分割,得到其文件名以及文件内容,这里每行其实就是一个文件了。
2.2 分词
分词直接采用HanLP的分词来做,HanLP这里选择两种:Standard和NLP(还有一种就是HighSpeed,但是这个木有用户自定义词典,所以前期考虑先用两种),具体参考:https://github.com/hankcs/HanLP ;
2.3 词转换为词向量
在Kmeans算法中,一个样本需要使用数值类型,所以需要把文本转为数值向量形式,这里在Spark中有两种方式。其一,是使用TF-IDF;其二,使用Word2Vec。这里暂时使用了TF-IDF算法来进行,这个算法需要提供一个numFeatures,这个值越大其效果也越好,但是相应的计算时间也越长,后面也可以通过实验验证。
2.4 使用每个文档的词向量进行聚类建模
在进行聚类建模的时候,需要提供一个初始的聚类个数,这里面设置为10,因为我们的数据是有10个分组的。但是在实际的情况下,一般这个值是需要通过实验来验证得到的。
2.5 对聚类后的结果进行评估
这里面采用的思路是:
1. 得到聚类模型后,对原始数据进行分类,得到原始文件名和预测的分类id的二元组(fileName,predictId);
2. 针对(fileName,predictId),得到(fileNameFirstChar ,fileNameFirstChar.toInt - predictId)的值,这里需要注意的是fileNameFirstChar其实就是代表这个文件的原始所属类别了。
3. 这里有一个一般假设,就是使用kmeans模型预测得到的结果大多数是正确的,所以fileNameFirstChar.toInt-predictId得到的众数其实就是分类的正确的个数了(这里可能比较难以理解,后面会有个小李子来说明这个问题);
4. 得到每个实际类别的预测的正确率后就可以去平均预测率了。
5. 改变numFeatuers的值,看下是否numFeatures设置的比较大,其正确率也会比较大?
3、具体步骤:
3.1 开发环境--Maven
首先第一步,当然是开发环境了,因为用到了Spark和HanLP,所以需要在pom.xml中加入这两个依赖:
1.
2.
3.com.hankcs
4.hanlp
5.${hanlp.version}
6.

7.
8.
9.org.apache.spark
10.spark-core_2.10
11.${spark.version}
12.

13.
14.org.apache.spark
15.spark-mllib_2.10
16.${spark.version}
17.

其版本为:
portable-1.3.41.6.0-cdh5.7.3
3.2 文件转为UTF-8编码及存储到一个文件

这部分内容可以直接参考:src/main/java/demo02_transform_encoding.TransformEncodingToOne 这里的实现,因为是Java基本的操作,这里就不加以分析了。
3.3 Scala调用HanLP进行中文分词
Scala调用HanLP进行分词和Java的是一样的,同时,因为这里有些词语格式不正常,所以把这些特殊的词语添加到自定义词典中,其示例如下:
1.import com.hankcs.hanlp.dictionary.CustomDictionary
2.import com.hankcs.hanlp.dictionary.stopword.CoreStopWordDictionary
3.import com.hankcs.hanlp.tokenizer.StandardTokenizer
4.import scala.collection.JavaConversions._
5./**
6.* Scala 分词测试
7.* Created by fansy on 2017/8/25.
8.*/
9.object SegmentDemo {
10.def main(args: Array[String]) {
11.val sentense = "41,【 日 期 】19960104 【 版 号 】1 【 标 题 】合巢芜高速公路巢芜段竣工 【 作 者 】彭建中 【 正 文 】 安徽合(肥)巢(湖)芜(湖)高速公路巢芜段日前竣工通车并投入营运。合巢芜 高速公路是国家规划的京福综合运输网的重要干线路段,是交通部确定1995年建成 的全国10条重点公路之一。该条高速公路正线长88公里。(彭建中)"
12.CustomDictionary.add("日 期")
13.CustomDictionary.add("版 号")
14.CustomDictionary.add("标 题")
15.CustomDictionary.add("作 者")
16.CustomDictionary.add("正 文")
17.val list = StandardTokenizer.segment(sentense)
18.CoreStopWordDictionary.apply(list)
19.println(list.map(x => x.word.replaceAll(" ","")).mkString(","))
20.}
21.}
运行完成后,即可得到分词的结果,如下:
考虑到使用方便,这里把分词封装成一个函数:
1./**
2.* String 分词
3.* @param sentense
4.* @return
5.*/
6.def transform(sentense:String):List[String] ={
7.val list = StandardTokenizer.segment(sentense)
8.CoreStopWordDictionary.apply(list)
9.list.map(x => x.word.replaceAll(" ","")).toList
10.}
11.}

输入即是一个中文的文本,输出就是分词的结果,同时去掉了一些常用的停用词。
3.4 求TF-IDF
在Spark里面求TF-IDF,可以直接调用Spark内置的算法模块即可,同时在Spark的该算法模块中还对求得的结果进行了维度变换(可以理解为特征选择或“降维”,当然这里的降维可能是提升维度)。代码如下:
1.val docs = sc.textFile(input_data).map{x => val t = x.split(".txt\t");(t(0),transform(t(1)))}
2..toDF("fileName", "sentence_words")
3.
4.// 3. 求TF
5.println("calculating TF ...")
6.val hashingTF = new HashingTF()
7..setInputCol("sentence_words").setOutputCol("rawFeatures").setNumFeatures(numFeatures)
8.val featurizedData = hashingTF.transform(docs)
9.
10.// 4. 求IDF
11.println("calculating IDF ...")
12.val idf = new IDF().setInputCol("rawFeatures").setOutputCol("features")
13.val idfModel = idf.fit(featurizedData)
14.val rescaledData = idfModel.transform(featurizedData).cache()
变量docs是一个DataFrame[fileName, sentence_words] ,经过HashingTF后,变成了变量 featurizedData ,同样是一个DataFrame[fileName,sentence_words, rawFeatures]。这里通过setInputCol以及SetOutputCol可以设置输入以及输出列名(列名是针对DataFrame来说的,不知道的可以看下DataFrame的API)。
接着,经过IDF模型,得到变量 rescaledData ,其DataFrame[fileName,sentence_words, rawFeatures, features] 。
执行结果为:
3.5 建立KMeans模型

直接参考官网给定例子即可:
1.println("creating kmeans model ...")
2.val kmeans = new KMeans().setK(k).setSeed(1L)
3.val model = kmeans.fit(rescaledData)
4.// Evaluate clustering by computing Within Set Sum of Squared Errors.
5.println("calculating wssse ...")
6.val WSSSE = model.computeCost(rescaledData)
7.println(s"Within Set Sum of Squared Errors = $WSSSE")
这里有计算cost值的,但是这个值评估不是很准确,比如我numFeature设置为2000的话,那么这个值就很大,但是其实其正确率会比较大的。
3.6 模型评估
这里的模型评估直接使用一个小李子来说明:比如,现在有这样的数据:
其中,1开头,2开头和4开头的属于同一类文档,后面的0,3,2,1等,代表这个文档被模型分类的结果,那么可以很容易的看出针对1开头的文档,
其分类正确的有4个,其中("123.txt",3)以及(“126.txt”,1)是分类错误的结果,这是因为,在这个类别中预测的结果中0是最多的,所以0是和1开头的文档对应起来的,这也就是前面的假设。
1. 把同一类文档分到同一个partition中;
1.val data = sc.parallelize(t)
2.val file_index = data.map(_._1.charAt(0)).distinct.zipWithIndex().collect().toMap
3.println(file_index)
4.val partitionData = data.partitionBy(MyPartitioner(file_index))
这里的file_index,是对不同类的文档进行编号,这个编号就对应每个partition,看MyPartitioner的实现:
1.case class MyPartitioner(file_index:Map[Char,Long]) extends Partitioner
2.override def getPartition(key: Any): Int = key match {
3.case _ => file_index.getOrElse(key.toString.charAt(0),0L).toInt
4.}

5..override def numPartitions: Int = file_index.size
6.}
2. 针对每个partition进行整合操作:
在整合每个partition之前,我们先看下我们自定义的MyPartitioner是否在正常工作,可以打印下结果:
1.val tt = partitionData.mapPartitionsWithIndex((index: Int, it: Iterator[(String,Int)]) => it.toList.map(x => (index,x)).toIterator)
2.tt.collect().foreach(println(_))
运行如下:
其中第一列代表每个partition的id,第二列是数据,发现其数据确实是按照预期进行处理的;接着可以针对每个partition进行数据整合:
1.// firstCharInFileName , firstCharInFileName - predictType
2.val combined = partitionData.map(x =>( (x._1.charAt(0), Integer.parseInt(x._1.charAt(0)+"") - x._2),1) )
3..mapPartitions{f => var aMap = Map[(Char,Int),Int]();
4.for(t <- f){
5.if (aMap.contains(t._1)){
6.aMap = aMap.updated(t._1,aMap.getOrElse(t._1,0)+1)
7.}else{
8.aMap = aMap + t
9.}
10.}
11.val aList = aMap.toList
12.val total= aList.map(_._2).sum
13.val total_right = aList.map(_._2).max
14.List((aList.head._1._1,total,total_right)).toIterator
15.// aMap.toIterator //打印各个partition的总结
16. }
在整合之前先执行一个map操作,把数据变成((fileNameFirstChar, fileNameFirstChar.toInt - predictId), 1),其中fileNameFirstChar代表文件的第一个字符,其实也就是文件的所属实际类别,后面的fileNameFirstChar.toInt-predictId 其实就是判断预测的结果是否对了,这个值的众数就是预测对的;最后一个值代码前面的这个键值对出现的次数,其实就是统计属于某个类别的实际文件个数以及预测对的文件个数,分别对应上面的total和total_right变量;输出结果为:
(4,6,3)
(1,6,4)
(2,6,4)
发现其打印的结果是正确的,第一列代表文件名开头,第二个代表属于这个文件的个数,第三列代表预测正确的个数
这里需要注意的是,这里因为文本的实际类别和文件名是一致的,所以才可以这样处理,如果实际数据的话,那么mapPartitions函数需要更改。
3. 针对数据结果进行统计:
最后只需要进行简单的计算即可:
1.for(re <- result ){
2.println("文档"+re._1+"开头的 文档总数:"+ re._2+",分类正确的有:"+re._3+",分类正确率是:"+(re._3*100.0/re._2)+"%")
3.}
4.val averageRate = result.map(_._3).sum *100.0 / result.map(_._2).sum
5.println("平均正确率为:"+averageRate+"%")
输出结果为:
4. 实验
设置不同的numFeature,比如使用200和2000,其对比结果为:

所以设置numFeatures值越大,其准确率也越高,不过计算也比较复杂。
5. 总结
1. HanLP的使用相对比较简单,这里只使用了分词及停用词,感谢开源;
2. Spark里面的TF-IDF以及Word2Vector使用比较简单,不过使用这个需要先分词;
3. 这里是在IDEA里面运行的,如果使用Spark-submit的提交方式,那么需要把hanpl的jar包加入,这个有待验证

文章来源于fansy1990的博客
人工智能
2018-11-12 10:09:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
tutorial1
1.查看ros有关环境变量 $ printenv | grep ROS
2.Create a ROS Workspace $ mkdir -p ~/catkin_ws/src $ cd ~/catkin_ws/ $ catkin_make
添加当前workspace变量 $ source devel/setup.bash
查看确认变量添加成功 $ echo $ROS_PACKAGE_PATH /home/youruser/catkin_ws/src:/opt/ros/kinetic/share
tutorial2
ROS filesystem concepts
1.查找package信息 $ rospack find [package_name]
2. roscd,rosls
tutorial3
create a new package
1.最简单的包结构必须包含: my_package/ CMakeLists.txt package.xml
2.创建包(src目录下) # catkin_create_pkg [depend1] [depend2] [depend3]
$ cd ~/catkin_ws/src
$ catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
3.build(workspace目录) $ cd ~/catkin_ws $ catkin_make
添加当前变量(这一步必做,不然找不到新建的包) $ . ~/catkin_ws/devel/setup.bash
4.查看包依赖
直接依赖: $rospack depends1 beginner_tutorials
递归依赖:depends1 替换成depends
5.修改package.xml和CMakeLists.txt
人工智能
2018-11-12 06:29:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
定义矩阵乘法 def mult(h, x): result = [] for x in h: summ = 0 for index, y in enumerate(x): summ += y * x[index] result.append(summ) return result
创建希尔伯特矩阵 def create_hobert(n): h=[] for x in range(1, n + 1): row = [] for y in range(1, n + 1): row.append(1 / (x + y - 1)) h.append(row) return h
雅克比迭代法 def jacobi(A,B,sigma,N): n = len(A) x0 = [] x = [] for i in range(0,n): x0.append(0) x.append(0) for k in range(1,N+1): R = 0 for i in range(0,n): sum_ax = 0 for j in range(0,n): sum_ax = sum_ax + A[i][j] * x0[j] x[i] = x0[i] + ((B[i] - sum_ax)/A[i][i]) if abs(x[i] - x0[i]) > R: R = abs(x[i] - x0[i]) if R <= sigma: print("精确度等于",sigma,"时,jacobi迭代法需要迭代",k,"次收敛") return (x,k) for i in range(0,n): x0[i] = x[i] return (x,k)
Hauss-Seidel迭代法 def gauss_seidel(A,B,sigma,N): n = len(A) x0 = [] x = [] for i in range(0,n): x0.append(0) x.append(0) for k in range(1,N+1): R = 0 for i in range(0,n): sum_ax = 0 for j in range(0,n): if j >= i: sum_ax = sum_ax + A[i][j] * x0[j] else: sum_ax = sum_ax + A[i][j] * x[j] x[i] = x0[i] + ((B[i] - sum_ax)/A[i][i]) if abs(x[i] - x0[i]) > R: R = abs(x[i] - x0[i]) if R <= sigma: print("精确度等于",sigma,"时,gauss_seidel迭代法需要迭代",k,"次收敛") return (x,k) for i in range(0,n): x0[i] = x[i] return (x,k)
SOR迭代法 def sor(A,B,sigma,N,omega): n = len(A) x0 = [] x = [] for i in range(0,n): x0.append(0) x.append(0) for k in range(1,N+1): R = 0 for i in range(0,n): sum_ax = 0 for j in range(0,n): if j >= i: sum_ax = sum_ax + A[i][j] * x0[j] else: sum_ax = sum_ax + A[i][j] * x[j] x[i] = x0[i] + omega * ((B[i] - sum_ax)/A[i][i]) if abs(x[i] - x0[i]) > R: R = abs(x[i] - x0[i]) if R <= sigma: print("精确度等于",sigma,"时,松弛因子为",omega,"时,sor迭代法需要迭代",k,"次收敛") print(x) return (x,k) for i in range(0,n): x0[i] = x[i] return (x,k)
测试希尔伯特矩阵H if __name__ == "__main__": n = 10 H = create_hobert(n) x = [1 for x in range(n)] b = mult(H,x) print('雅克比迭代法:',jacobi(H, b, 0.1, 200)) print('SOR迭代法:',sor(H, b, 0.001, 20000, 1.5)) # print('Guass-Seidel迭代法:',gauss_seidel(H,b,0.00001,20))
人工智能
2018-11-11 23:42:00
「深度学习福利」大神带你进阶工程师,立即查看>>> #include #define WORKTAG 1 #define DIETAG 2 /* Local functions */ static void master(void); static void slave(void); static unit_of_work_t get_next_work_item(void); static void process_results(unit_result_t result); static unit_result_t do_work(unit_of_work_t work); int main(int argc, char **argv) { int myrank; /* Initialize MPI */ MPI_Init(&argc, &argv); /* Find out my identity in the default communicator */ MPI_Comm_rank(MPI_COMM_WORLD, &myrank); if (myrank == 0) { master(); } else { slave(); } /* Shut down MPI */ MPI_Finalize(); return 0; } static void master(void) { int ntasks, rank; unit_of_work_t work; unit_result_t result; MPI_Status status; /* Find out how many processes there are in the default communicator */ MPI_Comm_size(MPI_COMM_WORLD, &ntasks); /* Seed the slaves; send one unit of work to each slave. */ for (rank = 1; rank < ntasks; ++rank) { /* Find the next item of work to do */ work = get_next_work_item(); /* Send it to each rank */ MPI_Send(&work, /* message buffer */ 1, /* one data item */ MPI_INT, /* data item is an integer */ rank, /* destination process rank */ WORKTAG, /* user chosen message tag */ MPI_COMM_WORLD); /* default communicator */ } /* Loop over getting new work requests until there is no more work to be done */ work = get_next_work_item(); while (work != NULL) { /* Receive results from a slave */ MPI_Recv(&result, /* message buffer */ 1, /* one data item */ MPI_DOUBLE, /* of type double real */ MPI_ANY_SOURCE, /* receive from any sender */ MPI_ANY_TAG, /* any type of message */ MPI_COMM_WORLD, /* default communicator */ &status); /* info about the received message */ /* Send the slave a new work unit */ MPI_Send(&work, /* message buffer */ 1, /* one data item */ MPI_INT, /* data item is an integer */ status.MPI_SOURCE, /* to who we just received from */ WORKTAG, /* user chosen message tag */ MPI_COMM_WORLD); /* default communicator */ /* Get the next unit of work to be done */ work = get_next_work_item(); } /* There's no more work to be done, so receive all the outstanding results from the slaves. */ for (rank = 1; rank < ntasks; ++rank) { MPI_Recv(&result, 1, MPI_DOUBLE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); } /* Tell all the slaves to exit by sending an empty message with the DIETAG. */ for (rank = 1; rank < ntasks; ++rank) { MPI_Send(0, 0, MPI_INT, rank, DIETAG, MPI_COMM_WORLD); } } static void slave(void) { unit_of_work_t work; unit_result_t results; MPI_Status status; while (1) { /* Receive a message from the master */ MPI_Recv(&work, 1, MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &status); /* Check the tag of the received message. */ if (status.MPI_TAG == DIETAG) { return; } /* Do the work */ result = do_work(work); /* Send the result back */ MPI_Send(&result, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); } } static unit_of_work_t get_next_work_item(void) { /* Fill in with whatever is relevant to obtain a new unit of work suitable to be given to a slave. */ } static void process_results(unit_result_t result) { /* Fill in with whatever is relevant to process the results returned by the slave */ } static unit_result_t do_work(unit_of_work_t work) { /* Fill in with whatever is necessary to process the work and generate a result */ }
人工智能
2018-11-11 21:31:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
CMake cmake_minim_required(VERSION 3.0) project(TEST) find_package(MPI REQUIRED) include_directories(${MPI_INCLUDE_PATH}) add_executable(hello hello.cpp) target_link_libraries(hello ${MPI_LIBRARIES}) int MPI_Ssend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm); int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status); comm : 沟通器 tag : 信息标签 dest/source : 在该沟通器中的发送者和接受者的等级号 datatype : 所发送的数据的类型 count :发送和接受的数据数量 buf : 发送/接收的数据的开始地址
进程2发给进程3一个int型数字 :1 #include #include int main(int argc, char** argv) { MPI_Init(&argc, &argv); int wrank; MPI_Comm_rank(MPI_COMM_WORLD, &wrank); int witness = 0; if (wrank==2) { int modifier = 1; MPI_Ssend(&modifier, 1, MPI_INT, 3, 28, MPI_COMM_WORLD); } else if (wrank==3){ MPI_Recv(&witness, 1, MPI_INT,2,28,MPI_COMM_WORLD,MPI_STATUS_IGNORE); } printf("Rang %d, witness %d.\n", wrank, witness); MPI_Finalize(); return 0;
多参数传递 // intro/send-receive.c int witness[] = {0, 0}; if (wrank==2) { int modifier[] = {1, 1}; MPI_Ssend(modifier, 2, MPI_INT, 3, 28, MPI_COMM_WORLD); } else if (wrank==3) MPI_Recv(witness, 2, MPI_INT, 2, 28, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
如果发送的字节数等于接收的字节数,通信将成功。例如,可以发送一个包含两个int的数组,并接收一个long或者一个double。
有关标签的详细信息
标记必须是介于0和系统相关值之间的整数,系统相关值由以下程序获取。该最大值总是≥32767。 // tag.c #include #include int main(int argc, char** argv) { MPI_Init(&argc, &argv); int flag; int* max_tag;    MPI_Comm_get_attr(MPI_COMM_WORLD, MPI_TAG_UB, &max_tag, &flag); printf("Maximum tag : %d.\n", *max_tag); MPI_Finalize(); return 0; }
多个进程允许重复使用相同的标签:无论通信的模式如何,接收顺序与发送顺序相同。
MPI基本数据类型
MPI C 字节数 MPI_CHAR char 1
MPI_SHORT short 2
MPI_INT int 4
MPI_LONG long 8
MPI_UNSIGNED_CHAR unsigned char 1
MPI_UNSIGNED_SHORT unsigned short 2
MPI_UNSIGNED_LONG unsigned long 8
MPI_UNSIGNED unsigned int 4
MPI_FLOAT float 4
MPI_DOUBLE
MPI_LONG_DOUBLE
double
long double
8
16
所有MPI_ *类型的大小均为8个字节。
只有收到指定标签的全部消息时,接收过程才会退出对MPI_Recv的调用。 发送过程的行为更加复杂。 MPI_STATUS_IGNORE是一个可以用来代替状态变量的预定义常量。 可以创建和传达更复杂的数据结构。
人工智能
2018-11-11 19:29:00
「深度学习福利」大神带你进阶工程师,立即查看>>> include_directories(${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/include) set(RC_NNET_FILES ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/activation_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/activation_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/activations.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/activations.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/avgpool_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/avgpool_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/batchnorm_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/batchnorm_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/blas.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/blas.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/box.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/box.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/classifier.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/col2im.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/col2im.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/compare.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/connected_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/connected_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/convolutional_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/convolutional_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/cost_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/cost_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/crnn_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/crnn_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/crop_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/crop_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/cuda.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/cuda.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/data.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/data.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/deconvolutional_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/deconvolutional_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/demo.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/demo.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/detection_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/detection_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/dropout_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/dropout_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/gemm.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/gemm.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/gru_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/gru_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/im2col.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/im2col.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/image.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/image.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/image_opencv.cpp ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/stb_image_write.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/iseg_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/iseg_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/l2norm_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/l2norm_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/list.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/list.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/local_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/local_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/logistic_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/logistic_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/lstm_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/lstm_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/matrix.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/matrix.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/maxpool_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/maxpool_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/network.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/network.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/normalization_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/normalization_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/option_list.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/option_list.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/parser.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/parser.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/region_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/region_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/region_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/region_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/reorg_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/reorg_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/rnn_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/rnn_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/route_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/route_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/shortcut_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/shortcut_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/softmax_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/softmax_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/stb_image.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/tree.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/tree.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/upsample_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/upsample_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/utils.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/utils.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/yolo_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/yolo_layer.h ) set(YOLO3 ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/darknet.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/detector.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/dice.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/rnn.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/rnn_vid.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/segmenter.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/super.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/swag.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/tag.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/voxel.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/writing.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/coco.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/art.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/attention.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/captcha.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/cifar.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/classifier.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/lsd.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/regressor.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/nightmare.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/instance-segmenter.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/go.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/yolo.c ) add_executable(rcnetapp ${YOLO3}) target_link_libraries(rcnetapp rcnet pthread stdc++ ${OpenCV_LIB} pthread m)
人工智能
2018-11-11 19:09:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
各位童鞋们,如果您已经拼了别人的团,但是还不知道怎么玩?小编来告诉你!
最后一天了,大家就不要再开团了,马上进入官方热荐团直享最低折扣:http://click.aliyun.com/m/1000023288/
您拼团后将享受以下福利:
福利1:拉新赢红包
您拼团后可通过专属分享链接,邀请好友来参团。每成功邀请1个新用户参团购买您团里的云产品,您将获得1个拉新红包!几十块——1111元红包都有可能!
最大的红包有1111元的现金红包,将即时发放到您的阿里云账户中!拉新人数越多,红包越多!
福利2:享受云产品折扣
参团新用户在活动期间,通过活动页面首次购买指定云产品的,可根据同一团内的拼团人数,享受不同的拼团折扣价格,具体如下:
以2核8G5M配置的云服务器为例:
3年版的配置原价14850元,活动起拼价4140元,相当于28折起购,团首购满6人即低至2070元,相当于14折,最高省12780元。
福利3:云大使返现
参加开团/拼团活动都将加入阿里云云大使。
您参团后即加入阿里云云大使,可获取专属分享链接,邀请其他用户参团。如果您是新用户,不仅能享受以上云产品折扣,和拉新红包,还能获得首单返25%,30天内拉的用户再消费会再返现15%。
举个例子:
如果您所在的团当前团购的云产品为2070元的ECS云服务器,您每拉一个新人,可获得2070*25%=517.5元的返佣。
如果30天内您拉的新人再次购买ECS云服务器,如4140元的云产品,您可再获得4140*15%=621元的返佣。
老用户如何赚钱?
拉新用户即得红包,再享云大使25%的额外返现,如果拉一个新人购买2核8G5M的配置,拼团价4140元,您将会得到(4140元*25%)1035元+1111元(最高)=2146元的最高返现,平均能得>1035元的现金红包及返现。

原文链接
本文为云栖社区原创内容,未经允许不得转载。
人工智能
2018-11-11 15:35:00
「深度学习福利」大神带你进阶工程师,立即查看>>> 2018 年 10 月 12 日,七牛云与北京锐安科技有限公司签署战略合作协议。锐安科技总经理谢永恒、副总经理帅佩章,七牛云总裁吕桂华、七牛云人工智能实验室负责人彭垚、市场副总裁钱骥华出席签约仪式。
七牛云与锐安科技将在警务安防、网络信息安全、大数据服务等重要领域达成全面长期战略合作。通过深度整合七牛云人工实验室自研的城市慧眼系统、内容安全、深度学习平台、智能城管、智能人像等久经实战检验的机器视觉产品和解决方案,锐安科技将与七牛云一起,打造国内顶尖的网络大数据产品。
双方将从以下三个层面达成全面合作,充分发挥各自优势,为构建大数据合作生态链在国内各行业的应用落地而不懈努力。
共建公安标准体系
蓝图规划,标准先行。在全国公安领域处于领先地位的锐安科技,将与七牛云等十余家生态合作伙伴一起,共同发布最新标准体系,为公安大数据产业发展提供最先进的规划。
达成产品深度结合
灵活组合,优势互补。七牛云人工智能实验室将提供内容安全、智能多媒体处理、OCR、智能人像、城市慧眼系统、智能人像等 10 余种性能优秀的计算机视觉产品,与生态合作伙伴共同打造千种安防产品货架,在应用落地过程中实现产品效果最大化。
建设全国服务团队
服务至上,全面支撑。七牛云将与锐安科技一同打造全国服务团队,计划在明年十余个省市实现应用落地,并提供高水平专业服务。
随着公安大数据时代来临,人工智能、大数据等技术注定将在今后的行业应用中扮演更重要的角色。在公安领域全国领先的锐安科技,与七牛云人工智能实验室走在行业之先,达成全面战略合作,进一步促进公安大数据行业生态稳步发展。
点击 「阅读原文」
了解七牛云人工智能实验室
人工智能
2018-11-06 12:50:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
1.英文题目 Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example: Given nums = [2, 7, 11, 15], target = 9, Because nums[ 0 ] + nums[ 1 ] = 2 + 7 = 9, return [ 0 , 1 ].
2.解题 public static int[] twoSum(int[] nums, int target) { for (int i=0; i < nums.length; i++) { for (int j=i+1; j < nums.length; j++) { if (nums[i] + nums[j] == target) { return new int[]{i,j}; } } } throw new IllegalArgumentException("No two sum solution"); }
人工智能
2018-11-06 10:30:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
STOCHRSI 指标理解
这几天帮一个朋友解决一个关于指标的问题 ,这个指标就是 STOCHRSI 。在网上查了很多资料,中文的真是甚少。而且仅有的也不是讲的很清楚。对于我这样的 交易小白,简直是天书。 不过只要研究多少会有点收获的,下面分享下经验,需要用这个的朋友可以借鉴。
在网上找到了一些 关于这个指标的计算公式。 /* LC := REF(CLOSE,1); //REF(C,1) 上一周期的收盘价 RSI:=SMA(MAX(CLOSE-LC,0),N,1)/SMA(ABS(CLOSE-LC),N,1) *100; %K: MA(RSI-LLV(RSI,M),P1)/MA(HHV(RSI,M)-LLV(RSI,M),P1)*100; LLV(l,60)表示:检索60天内的最低价,可适应于检索任何股票 %D:MA(%K,P2); LC := REF(CLOSE,1); RSI:=SMA(MAX(CLOSE-LC,0),N,1)/SMA(ABS(CLOSE-LC),N,1) *100; STOCHRSI:MA(RSI-LLV(RSI,M),P1)/MA(HHV(RSI,M)-LLV(RSI,M),P1)*100; */

天哪! 我竟然耐心看完了。(当时看见这个的时候,就感觉碰到钉子了。) 这个描述是通用 公式。但是有点编程经验的我也只能 猜!猜!猜! 在网上找到的资料说,这个指标有大概3个不同形态。上面的公式是其中2个。 但是资料也没说,这3个不同形态的其他详细信息。 在各个平台的图表行情中看、对比。发现,关于这个指标的描述各不相同。平台上的 talib指标库 中的指标函数 STOCHRSI 的参数描述也没有完全明白。 用talib指标库 传入参数 14,14,3,3 这组参数,得出的数据和其他平台的对比,发现差异较大。看了看参数描述发现不一样。于是放弃现成的。 有点想动手撸这个指标…(有点怕怕,弄不好就被代码虐了)。

经过了一番痛苦挣扎…
总结: 这个指标不管哪种形态,RSI 指标是这个指标的基础数据。对比了其他平台描述和上述公式。确定STOCHRSI指标的参数必然有一个是RSI的参数。 又发现 这个指标的不同描述,有的描述是指标输出的是 %K , %D两条线。 有的描述是 输出的为 STOCHRSI , MA(3) (这个描述的参数是14,14,3,3) 分析了一下, 其实 虽然是2种不同形态, %K === STOCHRSI , %D === MA(3) 输出的2条线(数据)计算公式是一样的。 确定 MA(3)中的3是一个参数。 剩下2个参数,动手往上面的公式里面带入,就是M 和 P1了 。14、3 都试试。最终发现撸出来的指标数据 ,终于对的上其他平台上的数据了。
绿色是快线 %K ,橙色是 %D
自己写的指标,可以对比下 OKCoin的 。 如有问题欢迎留言 ^^ function LLV(array,period){ if(!array || array.length - period < 0){ throw "error:" + array; } var min = array[array.length - period]; for(var i = array.length - period; i < array.length; i++){ if( array[i] < min ){ min = array[i]; } } return min; } function HHV(array,period){ if(!array || array.length - period < 0){ throw "error:" + array; } var max = array[array.length - period]; for(var i = array.length - period; i < array.length; i++){ if( array[i] > max){ max = array[i]; } } return max; } function DeleteNullEle(initArr){ var dealArr = []; var initArrLen = initArr.length; for(var i = 0,j = 0 ; i < initArrLen ; i++,j++){ if(initArr[i] === null || isNaN(initArr[i]) ){ j--; continue; } dealArr[j] = initArr[i]; } return dealArr; } /* LC := REF(CLOSE,1); //REF(C,1) 上一周期的收盘价 RSI:=SMA(MAX(CLOSE-LC,0),N,1)/SMA(ABS(CLOSE-LC),N,1) *100; %K: MA(RSI-LLV(RSI,M),P1)/MA(HHV(RSI,M)-LLV(RSI,M),P1)*100; LLV(l,60)表示:检索60天内的最低价,可适应于检索任何股票 %D:MA(%K,P2); LC := REF(CLOSE,1); RSI:=SMA(MAX(CLOSE-LC,0),N,1)/SMA(ABS(CLOSE-LC),N,1) *100; STOCHRSI:MA(RSI-LLV(RSI,M),P1)/MA(HHV(RSI,M)-LLV(RSI,M),P1)*100; */ function FstochRSI(records,n,m,p1,p2){ var len = records.length; //var LC = records[len-2];//上一周期收盘价 //var rsi = TA.RSI(records,n);// RSI 数组 ,talib var rsi = talib.RSI(records,n); rsi = DeleteNullEle(rsi);//ceshi var arr1 = []; var arr2 = []; var arr3 = []; var arr4 = []; var rsi_a = []; var rsi_b = []; var k = []; var d = null; /*不包含当前柱 for(var a = 0 ;a < rsi.length ; a++ ){//改造 不用 LLV for(var aa = 0 ; aa <= a; aa++ ){ rsi_a.push(rsi[aa]); } arr1.push(rsi[a] - TA.Lowest(rsi_a,m)); } for(var b = 0 ;b < rsi.length ; b++ ){//改造 不用 HHV for(var bb = 0 ; bb <= b; bb++ ){ rsi_b.push(rsi[bb]); } arr2.push(TA.Highest(rsi_b,m) - TA.Lowest(rsi_b,m)); } */ for(var a = 0 ;a < rsi.length ; a++ ){//改造 不用 LLV if(a < m){ continue; } for(var aa = 0 ; aa <= a; aa++ ){ rsi_a.push(rsi[aa]); } arr1.push(rsi[a] - LLV(rsi_a,m)); } for(var b = 0 ;b < rsi.length ; b++ ){//改造 不用 HHV if(b < m){ continue; } for(var bb = 0 ; bb <= b; bb++ ){ rsi_b.push(rsi[bb]); } arr2.push(HHV(rsi_b,m) - LLV(rsi_b,m)); } arr1 = DeleteNullEle(arr1); arr2 = DeleteNullEle(arr2); //Log("arr1:",arr1.length,"-",arr1);//ceshi //Log("arr2:",arr2.length,"-",arr2);//ceshi arr3 = talib.MA(arr1,p1); arr4 = talib.MA(arr2,p1); arr3 = DeleteNullEle(arr3); arr4 = DeleteNullEle(arr4); //Log("ceshi");//ceshi var c = 0; var diff = 0; if(arr3.length !== arr4.length){//实测 长度不相等 throw "error: !=" + arr3.length + "----" + arr4.length; diff = arr4.length - arr3.length; //example diff = 10 - 6 }else{ //throw "error:" + arr3.length + "----" + arr4.length; } for( ;c < arr3.length ; c++ ){ k.push(arr3[c] / arr4[c + diff] * 100); } d = talib.MA(k,p2); return [k,d,rsi]; }

原文地址:https://quant.la/Article/View/43/
人工智能
2018-11-06 09:19:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
【一】综述
利用jieba进行关键字提取时,有两种接口。一个基于TF-IDF算法,一个基于TextRank算法。TF-IDF算法,完全基于词频统计来计算词的权重,然后排序,在返回TopK个词作为关键字。TextRank相对于TF-IDF,基本思路一致,也是基于统计的思想,只不过其计算词的权重时,还考虑了词的上下文(通过窗口滑动来实现),而且计算词的权重时,也考虑了相关联系词的影响。可以说,TextRank实际上是依据位置与词频来计算词的权重的。下面,结合基于jieba源码,来分别解释两种算法的实现。
【二】TF-IDF
1. 原理解析
假设,共有N篇文档,分别用 d1,d2,d3,,,,,,,dn来表示。
TF = 某个词在di篇文章中出现的次数/di篇文章的总词数 = count(W in di)/ count(di)。因此,TF计算的是单个词在单个文档中出现的词频。
IDF = 总的文档数 / 出现词W的文档数 。 IDF其实反映了词W在文档之间的区别度。如果W在仅在一篇文档中出现,则说明可以使用W将该文档与其他文档区别开来。即IDF可以反映W的独特性 。
TF*IDF,可以得到词的重要性。比如: 北京和西安在同一篇文档中的词频均为20%,那如何估计北京是该文的关键字,还是西安呢?如果同时有10篇文章均提到了北京,恰好只有这篇文章提到了西安,则西安作为这篇文章的关键字更为合理。
2. idf.txt
jieba有统计好的idf值,在 jieba/analyse/idf.txt中。 劳动防护 13.900677652 生化学 13.900677652 奥萨贝尔 13.900677652 考察队员 13.900677652 岗上 11.5027823792 倒车档 12.2912397395
3. idf.txt 加载
代码在 jieba/analyse/tfidf.py class IDFLoader(object): def __init__(self, idf_path=None): self.path = "" self.idf_freq = {} # 初始化idf的中位数值 self.median_idf = 0.0 if idf_path: # 解析idf.txt self.set_new_path(idf_path) def set_new_path(self, new_idf_path): if self.path != new_idf_path: self.path = new_idf_path content = open(new_idf_path, 'rb').read().decode('utf-8') self.idf_freq = {} # 解析 idf.txt,拿到词与idf的对应值,key = word,value = idf for line in content.splitlines(): word, freq = line.strip().split(' ') self.idf_freq[word] = float(freq) # 取idf的中位数 self.median_idf = sorted( self.idf_freq.values())[len(self.idf_freq) // 2]
4. 利用tfidf算法提取关键字的接口:extract_tags def extract_tags(self, sentence, topK=20, withWeight=False, allowPOS=(), withFlag=False): """ Extract keywords from sentence using TF-IDF algorithm. Parameter: - topK: return how many top keywords. `None` for all possible words. - withWeight: if True, return a list of (word, weight); if False, return a list of words. - allowPOS: the allowed POS list eg. ['ns', 'n', 'vn', 'v','nr']. if the POS of w is not in this list,it will be filtered. - withFlag: only work with allowPOS is not empty. if True, return a list of pair(word, weight) like posseg.cut if False, return a list of words """ # 判断提取出哪些词性的关键字 if allowPOS: allowPOS = frozenset(allowPOS) # 如果需要提取指定词性的关键字,则先进行词性分割 words = self.postokenizer.cut(sentence) else: # 如果提取所有词性的关键字,则使用精确分词 words = self.tokenizer.cut(sentence) freq = {} # 按照分词结果,统计词频 for w in words: if allowPOS: if w.flag not in allowPOS: continue elif not withFlag: w = w.word wc = w.word if allowPOS and withFlag else w # 该词不能是停用词 if len(wc.strip()) < 2 or wc.lower() in self.stop_words: continue #统计该词出现的次数 freq[w] = freq.get(w, 0.0) + 1.0 # 计算总的词数目 total = sum(freq.values()) for k in freq: kw = k.word if allowPOS and withFlag else k # 依据tf-idf公式进行tf-idf值,作为词的权重。其中,idf是jieba通过语料库统计得到的 freq[k] *= self.idf_freq.get(kw, self.median_idf) / total # 对词频做个排序,获取TopK的词 if withWeight: tags = sorted(freq.items(), key=itemgetter(1), reverse=True) else: tags = sorted(freq, key=freq.__getitem__, reverse=True) if topK: return tags[:topK] else: return tags
5. jieba实现tf-idf总结
1):idf的值时通过语料库统计得到的,所以,实际使用时,可能需要依据使用环境,替换为使用对应的语料库统计得到的idf值。
2):需要从分词结果中去除停用词。
3):如果指定了仅提取指定词性的关键词,则词性分割非常重要,词性分割中准确程度,影响关键字的提取。
【三】TextRank
1. 算法原理介绍
TextRank采用图的思想,将文档中的词表示成一张无向有权图,词为图的节点,词之间的联系紧密程度体现为图的边的权值。计算词的权重等价于计算图中节点的权重。提取关键字,等价于找出图中权重排名TopK的节点。
如上图所示:有A B C D E五个词,词之间的关系使用边连接起来,词之间连接的次数作为边的权值。比如:A和C一起出现了2次,则其边的权重为2,A与B/C/E都有联系,而D仅与B有联系。
所以说,TextRank背后体现的思想为:与其他词关联性强的词,越重要。通俗一点就是:围着谁转,谁就重要。就像大家基本都会围着领导转一样。
2. 图的构建
图的构建分为两部分:
1):确认图的节点之间的联系
2):确认边的权值
jieba是如何做的呢? def textrank(self, sentence, topK=20, withWeight=False, allowPOS=('ns', 'n', 'vn', 'v'), withFlag=False): """ Extract keywords from sentence using TextRank algorithm. Parameter: - topK: return how many top keywords. `None` for all possible words. - withWeight: if True, return a list of (word, weight); if False, return a list of words. - allowPOS: the allowed POS list eg. ['ns', 'n', 'vn', 'v']. if the POS of w is not in this list, it will be filtered. - withFlag: if True, return a list of pair(word, weight) like posseg.cut if False, return a list of words """ # 初始化关键字词性过滤条件 self.pos_filt = frozenset(allowPOS) # 初始化一个无向权值图 g = UndirectWeightedGraph() cm = defaultdict(int) # 使用精确模式进行分词 words = tuple(self.tokenizer.cut(sentence)) # 遍历分词结果 for i, wp in enumerate(words): # 词wp如果满足关键词备选条件,则加入图中 if self.pairfilter(wp): # span为滑动窗口,即词的上下文,借此来实现此的共现,完成词之间的连接。 for j in xrange(i + 1, i + self.span): if j >= len(words): break # 后向词也要满足备选词条件 if not self.pairfilter(words[j]): continue if allowPOS and withFlag: # 共现词作为图一条边的两个节点,共现词出现的次数,作为边的权值 cm[(wp, words[j])] += 1 else: cm[(wp.word, words[j].word)] += 1 # 将 备选词和与该词连接的词加入到graph中,即完成graph的构造 for terms, w in cm.items(): g.addEdge(terms[0], terms[1], w) # 调用graph的rank接口,完成TextRank算法的计算,即计算出各节点的权重 nodes_rank = g.rank() if withWeight: # 对graph中的阶段的权重进行排序 tags = sorted(nodes_rank.items(), key=itemgetter(1), reverse=True) else: tags = sorted(nodes_rank, key=nodes_rank.__getitem__, reverse=True) if topK: return tags[:topK] else: return tags
3. TextRank算法的实现 def rank(self): ws = defaultdict(float) outSum = defaultdict(float) # 计算初始化节点的weight值 wsdef = 1.0 / (len(self.graph) or 1.0) # 初始化各个节点的weight值,并计算各个节点的出度数目 for n, out in self.graph.items(): ws[n] = wsdef outSum[n] = sum((e[2] for e in out), 0.0) # this line for build stable iteration sorted_keys = sorted(self.graph.keys()) # 循环迭代10,迭代计算出各个节点的weight值 for x in xrange(10): # 10 iters for n in sorted_keys: s = 0 # 依据TextRank公式计算weight for e in self.graph[n]: s += e[2] / outSum[e[1]] * ws[e[1]] ws[n] = (1 - self.d) + self.d * s (min_rank, max_rank) = (sys.float_info[0], sys.float_info[3]) for w in itervalues(ws): if w < min_rank: min_rank = w if w > max_rank: max_rank = w for n, w in ws.items(): # to unify the weights, don't *100. ws[n] = (w - min_rank / 10.0) / (max_rank - min_rank / 10.0) return ws
【四】TF-IDF与TextRank算法的比较
1. 从算法原理上来看,基础都是词频统计,只是TD-IDF通过IDF来调整词频的权值,而TextRank通过上下文的连接数来调整词频的权值。TextRank通过滑动窗口的方式,来实现词的位置对词的权值的影响。
2. TD-IDF计算简单,运行性能更好。
人工智能
2018-11-05 23:20:00
「深度学习福利」大神带你进阶工程师,立即查看>>>

最近几年随着大数据技术快速发展与应用,智慧城市随即被正式提出。而且,我们也可以深刻感受到“智慧”正在慢慢改变我们的生活方式和城市。要让城市变智慧的地方太多太多,当前我们接触做多的可能就是外出停车,比如很多商场的停车系统,很多商城的停车场都实现了无人值守。这就是得益于智慧城市停车云平台。
很多人对智慧停车云的概念不是明白,智慧停车平台就是利用云计算、物联网、大数据处理技术等手段,通过可持续运营的商业服务模式,面向各类停车场实现跨区域、多层级的集中监控和管理,为政府、相关主管部门和运营企业提供远程监控、决策支持、统计分析和数据展现等服务,同时可面向公众提供多渠道停车即时讯息的平台。
汽车已经成为了家庭的重要代步工具,车方便了我们的出行,但停车却成为了最大的难题。传统的停车场存在的问题,如:车辆进出场的效率低、找车位难、找车也难、管理难度大、管理成本高。
为了解决传统停车的这些问题,智慧停车解决方案应用而生。市面上做智慧停车解决方案的可以说也是比较多的吧,这里就不与大家讨论解决方案了,还是聊一聊智慧停车云平台的体系与架构!
做智慧停车方案的很多,但能够做智慧停车云平台的就明显的比较少了,之所以少的原因也很简单,技术难度比较大!这里分享一个大快的城市智慧停车云平台解决方案的体系与架构。
关于大快的智慧停车云平台的体系与架构,我直接截图展示一下给大家看,结构脉络比较清晰,比起我用文字来说要简单明了!
这是城市智慧停车云平台的产品体系图!
这是城市智慧停车云平台的系统架构!
这两张图是我找的大快站点上的解决方案里的,看起来可能有点不怎么清晰。感兴趣的可以去看下大快站点的对于城市智慧停车云平台的详细介绍。
人工智能
2018-11-05 13:35:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 本文通过使用Keras及一个预训练模型的实例,教你如何通过迁移学习快速简便地解决图像分类问题。
摘要:如何快速简便地解决图像分类问题呢?本文通过使用Keras及一个预训练模型的实例,教你如何通过迁移学习来解决这个问题。

深度学习 正在迅速成为人工智能应用开发的主要工具。在计算机视觉、自然语言处理和语音识别等领域都已有成功的案例。
深度学习擅长解决的一个问题是 图像分类 。图像分类的目标是根据一组合理的类别对指定的图片进行分类。从深度学习的角度来看,图像分类问题可以通过 迁移学习 的方法来解决。
本文介绍了如何通过迁移学习来解决图像分类的问题。 本文中所提出的实现方式是基于Python语言的Keras。
本文结构:
1)迁移学习
2)卷积神经网络
3)预训练模型的复用
4)迁移学习过程
5)深度卷积神经网络上的分类器
6)示例
7)总结 1、迁移学习
迁移学习在计算机视觉领域中是一种很流行的方法,因为它可以 建立精确的模型,耗时更短 。利用迁移学习,不是从零开始学习,而是从之前解决各种问题时学到的模式开始。这样,你就可以利用以前的学习成果(例如VGG、 Inception、MobileNet),避免从零开始。我们把它看作是站在巨人的肩膀上。
在计算机视觉领域中,迁移学习通常是通过使用 预训练模型 来表示的。预训练模型是在大型基准数据集上训练的模型,用于解决相似的问题。由于训练这种模型的计算成本较高,因此,导入已发布的成果并使用相应的模型是比较常见的做法。 2、卷积神经网络(CNN)
在迁移学习中,常用的几个预训练模型是基于大规模 卷积神经网络 的(Voulodimos)。一般来说,CNN被证明擅长于解决计算机视觉方面的问题。它的高性能和易训练的特点是最近几年CNN流行的两个主要原因。
典型的CNN包括两个部分:
(1) 卷积基 ,由卷积层和池化层的堆栈组成。卷积基的主要目的是由图像生成特征。为了直观地解释卷积层和池化层,请参阅Chollet 2017。
(2) 分类器 ,通常是由多个全连接层组成的。分类器的主要目标是基于检测到的特征对图像进行分类。全连接层是其中的神经元与前一层中的所有激活神经元完全连接的层。
图1显示了一个 基于CNN的模型体系结构 。这是一个简化的版本,事实上,这种类型的模型,其实际的体系结构比我们在这里说的要复杂得多。

图1.基于CNN的模型体系结果
这些深度学习模型的一个重要方面是,它们可以自动学习分层的特征表示。这意味着由第一层计算的特征是通用的,并且可以在不同的问题域中重用,而由最后一层计算的特征是较特殊的,并且依赖于所选择的数据集和任务。根据Yosinski等人在2014年提出的“如果第一层的特征是通用的并且最后一层的特征是特殊的,那么网络中必定有一个从一般到特殊的转变。因此,我们的CNN的卷积基特别是它下面的层(那些更接近输入的层)适用于一般特征,而分类器部分和卷积基中一些较高的层适用于特殊的特征。 3、预训练模型的复用
当你根据自己的需要重用预训练模型时,首先要删除原始的分类器,然后添加一个适合的新分类器,最后必须根据以下的三种策略之一对模型进行微调:
(1)训练整个模型 在这种情况下,利用预训练模型的体系结构,并根据数据集对其进行训练。如果你从零开始学习模型,那么就需要一个大数据集,和大量的计算资源。
(2)训练一些层而冻结其它的层 较低层适用的是通用特征(独立问题),而较高层适用的是特殊特征。这里,我们通过选择要调整的网络的权重来处理这两种情况。通常,如果有一个较小的数据集和大量的参数,你会冻结更多的层,以避免过度拟合。相比之下,如果数据集很大,并且参数的数量很少,那么可以通过给新任务训练更多的层来完善模型,因为过度拟合不是问题了。
(3)冻结卷积基 这种情况适用于训练/冻结平衡的极端情况。其主要思想是将卷积基保持在原始形式,然后使用其输出提供给分类器。把你正在使用的预训练模型作为固定的特征提取途径,如果缺少计算资源,并且数据集很小,或者预训练模型解决了你正要解决的问题,那么这就很有用。
图2以图表的形式说明了这三种策略。

与策略3的这种直接简单的应用不同,策略1和策略2要求你小心谨慎地应对卷积部分中使用的学习率。学习率是一个超参数,它控制你调整网络权重的大小。当你正在使用基于CNN的预训练模型时,使用一个低学习率是比较明智的,因为使用高学习率会增加失去之前所积累知识的风险。假设预训练模型经过了比较好的训练,保持低学习率将确保你不会过早和过度地调整CNN权重。 4、迁移学习过程
从实践的角度来看, 整个迁移学习过程可以概括如下:
(1)选择预训练模型. 从大量的预训练模型,可以选择一个适合你要解决的问题的。如果你正在使用Keras,可以立即使用一系列模型,例如VGG、InceptionV3和ResNet5。点击 这里 你可以看到Keras上所有的模型
(2)根据大小相似性矩阵进行分类. 在图3中你用矩阵来控制选择,这个矩阵是根据数据集的大小,以及预训练模型被训练之后的数据集的相似性,来对计算机视觉问题进行分类的。根据经验,如果每个类的图像少于1000个,则认为是小数据集。就数据集的相似性而言,常识占了上风。例如,如果是识别猫和狗,那么ImageNet将是一个类似的数据集,因为它有猫和狗的图像。然而,如果是识别癌细胞,ImageNet就不行了。
(3)微调模型. 这里可以使用大小和相似性矩阵来指导你的选择,然后参考前面提到的重用预训练模型的三个策略。请见图4。
象限 1. 大数据集,但不同于预训练模型的数据集。这种情况将会让你使用策略1。因为有一个大数据集,你就可以从零开始训练一个模型。尽管数据集不同,但在实践中,利用模型的体系结构和权重,通过预训练模型对初始化模型仍然是很有帮助的;
象限 2. 大数据集与类似于预训练模型的数据集。在这里任何选项都有效,可能最有效的是策略2。由于我们有一个大数据集,过度拟合不应该是个问题,所以我们可以尽可能多地学习。然而,由于数据集是相似的,我们可以通过利用以前的知识来节省大量的训练工作。因此,仅对卷积基的分类器和顶层进行训练就足够了。
象限 3. 小数据集,不同于预训练模型的数据集,这里唯一适合的就是策略2。很难在训练和冻结的层数之间平衡。如果你涉及的太深入,那么模型就会过度拟合;如果你仅停留在模型的表面,那么你就不会学到任何有用的东西。也许,你需要比象限2更深入,并且需要考虑数据增强技术。
象限 4. 小数据集,但类似于预训练模型的数据集。你只需删除最后一个全连接层(输出层),并且执行预训练模型作为固定的特征提取器,然后使用结果特征来训练新的分类器。

图3和图4. 尺寸相似性矩阵(左)和微调预训练模型的决策图(右) 5、深度卷积神经网络上的分类器
如前所述,由基于预训CNN的迁移学习方法得到的图像分类模型通常由以下两部分组成:
(1)卷积基,实现特征提取;
(2)分类器,通过卷积基提取的特征对输入图像进行分类;
由于在本节中我们主要关注分类器部分,所以必须首先说明可以遵循不同的方法来构建分类器:
(1)全连接层 . 对于图像分类问题,标准的方法是使用一组下面是softmax激活层的全连接层。softmax激活层输出每个可能的类标签上的概率分布,然后只需要根据最可能的类对图像进行分类。
(2)全局平均池化层 . Lin在2013年提出了一种基于全局平均池化的方法。在这个方法中,我们没有在卷积基最上面添加全连接层,而是添加了一个全局平均池化层,并将其输出直接提供给softmax激活层。
(3)线性支持向量机 . 线性支持向量机(SVM)是另一种可能的方法。根据Tang在2013年所说的,可以利用卷积基在提取的特征上通过训练线性SVM分类器来提高分类精确度。SVM方法的优缺点细节可以在下文中找到。 6. 示例
6.1 准备数据
在例子中,我们将使用原始数据集的小版本,这可以更快地运行模型,适用于那些计算能力有限的任务。
为了构建小版本数据集,我们可以使用Chollet 2017所提供的代码。 # Create smaller dataset for Dogs vs. Cats importos , shutil original_dataset_dir = '/Users/macbook/dogs_cats_dataset/train/' base_dir = '/Users/macbook/book/dogs_cats/data' if not os . path . exists ( base_dir ) : os . mkdir ( base_dir ) # Create directories train_dir = os . path . join ( base_dir , 'train' ) if not os . path . exists ( train_dir ) : os . mkdir ( train_dir ) validation_dir = os . path . join ( base_dir , 'validation' ) if not os . path . exists ( validation_dir ) : os . mkdir ( validation_dir ) test_dir = os . path . join ( base_dir , 'test' ) if not os . path . exists ( test_dir ) : os . mkdir ( test_dir ) train_cats_dir = os . path . join ( train_dir , 'cats' ) if not os . path . exists ( train_cats_dir ) : os . mkdir ( train_cats_dir ) train_dogs_dir = os . path . join ( train_dir , 'dogs' ) if not os . path . exists ( train_dogs_dir ) : os . mkdir ( train_dogs_dir ) validation_cats_dir = os . path . join ( validation_dir , 'cats' ) if not os . path . exists ( validation_cats_dir ) : os . mkdir ( validation_cats_dir ) validation_dogs_dir = os . path . join ( validation_dir , 'dogs' ) if not os . path . exists ( validation_dogs_dir ) : os . mkdir ( validation_dogs_dir ) test_cats_dir = os . path . join ( test_dir , 'cats' ) if not os . path . exists ( test_cats_dir ) : os . mkdir ( test_cats_dir ) test_dogs_dir = os . path . join ( test_dir , 'dogs' ) if not os . path . exists ( test_dogs_dir ) : os . mkdir ( test_dogs_dir ) # Copy first 1000 cat images to train_cats_dir fnames = [ 'cat.{}.jpg' . format ( i ) for i in range ( 100 ) ] forfname in fnames : src = os . path . join ( original_dataset_dir , fname ) dst = os . path . join ( train_cats_dir , fname ) shutil . copyfile ( src , dst ) # Copy next 500 cat images to validation_cats_dir fnames = [ 'cat.{}.jpg' . format ( i ) for i in range ( 200 , 250 ) ] forfname in fnames : src = os . path . join ( original_dataset_dir , fname ) dst = os . path . join ( validation_cats_dir , fname ) shutil . copyfile ( src , dst ) # Copy next 500 cat images to test_cats_dir fnames = [ 'cat.{}.jpg' . format ( i ) for i in range ( 250 , 300 ) ] forfname in fnames : src = os . path . join ( original_dataset_dir , fname ) dst = os . path . join ( test_cats_dir , fname ) shutil . copyfile ( src , dst ) # Copy first 1000 dog images to train_dogs_dir fnames = [ 'dog.{}.jpg' . format ( i ) for i in range ( 100 ) ] forfname in fnames : src = os . path . join ( original_dataset_dir , fname ) dst = os . path . join ( train_dogs_dir , fname ) shutil . copyfile ( src , dst ) # Copy next 500 dog images to validation_dogs_dir fnames = [ 'dog.{}.jpg' . format ( i ) for i in range ( 200 , 250 ) ] forfname in fnames : src = os . path . join ( original_dataset_dir , fname ) dst = os . path . join ( validation_dogs_dir , fname ) shutil . copyfile ( src , dst ) # Copy next 500 dog images to test_dogs_dir fnames = [ 'dog.{}.jpg' . format ( i ) for i in range ( 250 , 300 ) ] forfname in fnames : src = os . path . join ( original_dataset_dir , fname ) dst = os . path . join ( test_dogs_dir , fname ) shutil . copyfile ( src , dst ) # Sanity checks print ( 'total training cat images:' , len ( os . listdir ( train_cats_dir ) ) ) print ( 'total training dog images:' , len ( os . listdir ( train_dogs_dir ) ) ) print ( 'total validation cat images:' , len ( os . listdir ( validation_cats_dir ) ) ) print ( 'total validation dog images:' , len ( os . listdir ( validation_dogs_dir ) ) ) print ( 'total test cat images:' , len ( os . listdir ( test_cats_dir ) ) ) print ( 'total test dog images:' , len ( os . listdir ( test_dogs_dir ) ) )
6.2 从卷积基中提取特征
卷积基将用于提取特征,这些特征将为我们想要训练的分类器提供输入,以便能够识别图像中是否有狗或猫。
再次把Chollet 2017提供的代码修改了一下,请看代码2。 # Extract features importos , shutil fromkeras . preprocessing . image import ImageDataGenerator datagen = ImageDataGenerator ( rescale = 1 . / 255 ) batch_size = 32 defextract_features ( directory , sample_count ) : features = np . zeros ( shape = ( sample_count , 7 , 7 , 512 ) ) # Must be equal to the output of the convolutional base labels = np . zeros ( shape = ( sample_count ) ) # Preprocess data generator = datagen . flow_from_directory ( directory , target_size = ( img_width , img_height ) , batch_size = batch_size , class_mode = 'binary' ) # Pass data through convolutional base i = 0 forinputs_batch , labels_batch in generator : features_batch = conv_base . predict ( inputs_batch ) features [ i * batch_size : ( i + 1 ) * batch_size ] = features_batch labels [ i * batch_size : ( i + 1 ) * batch_size ] = labels_batch i += 1 ifi * batch_size >= sample_count : break return features , labels train_features , train_labels = extract_features ( train_dir , train_size ) # Agree with our small dataset size validation_features , validation_labels = extract_features ( validation_dir , validation_size ) test_features , test_labels = extract_features ( test_dir , test_size )
代码2.从卷积基中提取特征。
6.3 分类器
6.3.1 全连接层
我们提出的第一个解决方案是基于全连接层的。在分类器中添加一组全连接层,把从卷积基中提取的特征作为它们的输入。
为了保持简单和高效,我们将使用Chollet2018上的解决方案,并稍作修改,特别地使用Adam优化器来代替RMSProp。
代码3显示了相关的代码,而图5和图6表示了学习曲线。 # Define model fromkeras import models fromkeras import layers fromkeras import optimizers epochs = 100 model = models . Sequential ( ) model . add ( layers . Flatten ( input_shape = ( 7 , 7 , 512 ) ) ) model . add ( layers . Dense ( 256 , activation = 'relu' , input_dim = ( 7 * 7 * 512 ) ) ) model . add ( layers . Dropout ( 0.5 ) ) model . add ( layers . Dense ( 1 , activation = 'sigmoid' ) ) model . summary ( ) # Compile model model . compile ( optimizer = optimizers . Adam ( ) , loss = 'binary_crossentropy' , metrics = [ 'acc' ] ) # Train model history = model . fit ( train_features , train_labels , epochs = epochs , batch_size = batch_size , validation_data = ( validation_features , validation_labels ) )
代码3.全连接层解决方案

图5.全连接层方案的准确性

图6.全连接层方案的损失
结果简述:
(1)验证精确度约为0.85,对于给定数据集的大小,这个结果是非常不错的。(2)这个模型过度拟合,在训练曲线和验证曲线之间有很大的差距。
(3)由于我们已经使用了dropout,所以应该增大数据集来改善结果。
6.3.2 全局平均池化层
这种情况与之前的不同之处在于,我们将添加一个全局平均池化层,并将其输出提供到一个sigmoid激活层,而不是添加一组全连接层。
请注意,我们所说的是sigmoid激活层,而不是SoftMax激活层。我们正在改为sigmoid激活,因为在Keras中,为了执行二进制分类,应该使用sigmoid激活和binary_crossentropy作为损失。
代码4是构建分类器的代码。图7和图8表示所得结果的学习曲线。 # Define model fromkeras import models fromkeras import layers fromkeras import optimizers epochs = 100 model = models . Sequential ( ) model . add ( layers . GlobalAveragePooling2D ( input_shape = ( 7 , 7 , 512 ) ) ) model . add ( layers . Dense ( 1 , activation = 'sigmoid' ) ) model . summary ( ) # Compile model model . compile ( optimizer = optimizers . Adam ( ) , loss = 'binary_crossentropy' , metrics = [ 'acc' ] ) # Train model history = model . fit ( train_features , train_labels , epochs = epochs , batch_size = batch_size , validation_data = ( validation_features , validation_labels ) )
代码4.全局平均池化解决方案

图7.全局平均池化层方案的准确性

图8.全局平均池化方案的损失
结果简述 :
(1)验证精确度与全连接层方案的类似;
(2)模型不像以前那样过度拟合;
(3)当模型停止训练时,损失函数的结果仍在减小,大概可以通过增加周期数来完善模型;
6.3.3 线性支持向量机
在这种情况下,我们将利用卷积基提取的特征来训练一个线性支持向量机(SVM)的分类器。
为了训练这种分类器,可以使用传统的机器学习方式。因此,我们将使用k-fold cross-validation来估算分类器的误差。由于将使用k-fold cross-validation,我们可以将训练集和验证集连接起来以扩大训练数据(像前面一样保持测试集不变)。
代码5显示了如何联系数据。 # Concatenate training and validation sets svm_features = np . concatenate ( ( train_features , validation_features ) ) svm_labels = np . concatenate ( ( train_labels , validation_labels ) )
代码 5. 数据连接
最后,我们必须要知道SVM分类器有一个超参数,它是误差项的惩罚参数C。为了优化这个超参数,我们将使用穷举的方法进行网格搜索。
代码6表示用于构建该分类器的代码,而图9表示了学习曲线。 # Build model importsklearn fromsklearn . cross_validation import train_test_split fromsklearn . grid_search import GridSearchCV fromsklearn . svm import LinearSVC X_train , y_train = svm_features . reshape ( 300 , 7 * 7 * 512 ) , svm_labels param = [ { "C" : [ 0.01 , 0.1 , 1 , 10 , 100 ] } ] svm = LinearSVC ( penalty = 'l2' , loss = 'squared_hinge' ) # As in Tang (2013) clf = GridSearchCV ( svm , param , cv = 10 ) clf . fit ( X_train , y_train )
代码6. 线性 SVM解决方案.

图9.线性支持向量机方案的精确度
结果简述 :
(1)模型的精确度在0.86左右,类似于前一个方案;
(2)过度拟合即将出现。此外,训练精确度始终是1,这是不正常的,可以解释为过度拟合的现象;
(3)模型的精确度应随着训练样本数量的增加而提高。然而,这似乎并没有出现,这可能是由于过度拟合的原因。有趣的是,当数据集增加的时候,模型将会如何反应。 7. 总结
· 本文提出了迁移学习、卷积神经网络和预训练模型的概念;
· 定义了基本的微调策略来重新调整预训练模型;
· 描述了一种基于数据集的大小和相似度来决定应该使用哪种微调策略的结构化方法;
· 介绍了三种不同的分类器,可用于通过卷积基提取的特征上面;
· 为文中阐述的三个分类器中的任意一个都提供了关于图像分类的端到端的例子;
阿里云双十一1折拼团活动:已满6人,都是最低折扣了
【满6人】1核2G云服务器99.5元一年298.5元三年 2核4G云服务器545元一年 1227元三年
【满6人】1核1G MySQL数据库 119.5元一年
【满6人】3000条国内短信包 60元每6月
参团地址: http://click.aliyun.com/m/1000020293/
原文链接
人工智能
2018-11-05 11:49:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
安装
pip3 install --user jupyter
启动
python3 -m IPython notebook
启动界面如下;
安装数据分析和绘图
pip3 install pandas numpy matplotlib
安装可视化库 seaborn
pip3 install seaborn if sys.getdefaultencoding() != 'utf-8': reload(sys) sys.setdefaultencoding('utf-8') default_encoding = sys.getdefaultencoding()
pip3 install statsmodels
pip3 install scikit-learn





人工智能
2018-11-04 22:01:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
【一】词典加载
利用jieba进行分词时,jieba会自动加载词典,这里jieba使用python中的字典数据结构进行字典数据的存储,其中key为word,value为frequency即词频。
1. jieba中的词典如下:
jieba/dict.txt X光 3 n X光线 3 n X射线 3 n γ射线 3 n T恤衫 3 n T型台 3 n
该词典每行一个词,每行数据分别为:词 词频 词性
2. 词典的加载
jieba/_init_.py,源码解析如下: # 加载词典 def gen_pfdict(self, f): # 定义字典,key = word, value = freq lfreq = {} # 记录词条总数 ltotal = 0 f_name = resolve_filename(f) for lineno, line in enumerate(f, 1): try: line = line.strip().decode('utf-8') # 取一行的词语词频 word, freq = line.split(' ')[:2] freq = int(freq) # 记录词频与词的关系,这里直接采用dict存储,没有采用Trie树结构 lfreq[word] = freq ltotal += freq # 对多个字组成的词进行查询 for ch in xrange(len(word)): # 从头逐步取词,如 电风扇,则会一次扫描 电,电风,电风扇 wfrag = word[:ch + 1] # 如果该词不在词频表中,将该词插入词频表,并设置词频为0 if wfrag not in lfreq: lfreq[wfrag] = 0 except ValueError: raise ValueError( 'invalid dictionary entry in %s at Line %s: %s' % (f_name, lineno, line)) f.close() return lfreq, ltotal
在词典初始化时,会调用该接口,将词频表存储到变量FREQ中,后续进行分词时,会直接进行该词频表的查询。
调用点如下: def initialize(self, dictionary=None): self.FREQ, self.total = self.gen_pfdict(self.get_dict_file())
【二】分词
jieba进行分词时,使用词典的最大前缀匹配的方式。当使用精确匹配模型且启动HMM时,对于未登录词(即词典中不存在的词),jieba会使用HMM模型对未登录词进行分词,具体的算法是viterbi算法。
jieba分词的第一步是将待分配的文本,依据词典,生成动态图DAG。
1. 动态图的生成。 # 生成动态图 ''' 例如:sentence = '我爱北京天安门' id = 0 1 2 3 4 5 6 则 DAG = { 0:[0], 1:[1], 2:[2,3], 3:[3], 4:[4,5,6], 5:[5], 6:[6] } ''' def get_DAG(self, sentence): # 查看词典是否已经初始化,若没有,则加载词典,初始化词频表。 # 由此可以看出,jieba采用的是词典懒加载模式 self.check_initialized() # 使用字典结构存储动态图 DAG = {} # 获取待分词的句子的长度 N = len(sentence) # 从头到尾,逐字扫描 for k in xrange(N): tmplist = [] i = k # 获取句子中第k个位置的字 frag = sentence[k] # 如果该字在词频表中,则继续扫描,直到扫描出的词不再词频表中为止 # 即jieba采用的最大前缀匹配法来搜索词 # 例如: 句子为: 我爱北京天安门,frag = 北,则该while循环会一直搜索到京, # 即搜索到北京,而tmplist里面会存储:北,北京两个词 while i < N and frag in self.FREQ: if self.FREQ[frag]: tmplist.append(i) i += 1 frag = sentence[k:i + 1] # 存储一个字到动态图中 if not tmplist: tmplist.append(k) DAG[k] = tmplist return DAG
2. 分词接口流程分析 # 分词接口 def cut(self, sentence, cut_all=False, HMM=True): ''' The main function that segments an entire sentence that contains Chinese characters into seperated words. Parameter: - sentence: The str(unicode) to be segmented. - cut_all: Model type. True for full pattern, False for accurate pattern. - HMM: Whether to use the Hidden Markov Model. ''' # 对待分词的序列进行编解码,解码成utf-8的格式 sentence = strdecode(sentence) # 依据是否使用全模式,确定待使用的正则表达式式, # 结巴先使用正则表达式对待分割内容进行预处理,主要是去除标点符号 if cut_all: re_han = re_han_cut_all re_skip = re_skip_cut_all else: re_han = re_han_default re_skip = re_skip_default # 依据分割模式,设置分词接口,有点类似于函数指针的意思哈 if cut_all: # 全模式,使用__cut_all cut_block = self.__cut_all elif HMM: # 精确匹配模式,且使用HMM对未登录词进行分割,则使用__cut_DAG cut_block = self.__cut_DAG else: # 精确匹配模式,但不使用HMM对未登录词进行分割,则使用__cut_DAG_NO_HMM cut_block = self.__cut_DAG_NO_HMM # 使用正则表达式对待分词序列进行预处理 blocks = re_han.split(sentence) for blk in blocks: if not blk: continue if re_han.match(blk): # 调用分词接口进行分词 for word in cut_block(blk): yield word else: tmp = re_skip.split(blk) for x in tmp: if re_skip.match(x): yield x elif not cut_all: for xx in x: yield xx else: yield x
3. 全模式分词 def __cut_all(self, sentence): # 生成动态图 ''' 例如:sentence = '我爱北京天安门' id = 0 1 2 3 4 5 6 则 DAG = { 0:[0], 1:[1], 2:[2,3], 3:[3], 4:[4,5,6], 5:[5], 6:[6] } ''' dag = self.get_DAG(sentence) old_j = -1 # 扫描动态图 for k, L in iteritems(dag): # 如果只有一个字,且该字未在前面的词中出现过,则生成一个词,否则跳过 # 例如: ‘北京’已经成词了,再次扫描到‘京’时,需要跳过 if len(L) == 1 and k > old_j: yield sentence[k:L[0] + 1] old_j = L[0] else: #对于至少2个字的词,如 4:[4,5,6], 则分割为 天安,天安门 两个词 # 这符合jieba的全模式定义:尽量细粒度的分词 for j in L: if j > k: yield sentence[k:j + 1] old_j = j
4. 精确模式分词,且使用HMM对未登录词进行分割 def __cut_DAG(self, sentence): DAG = self.get_DAG(sentence) route = {} # 使用动态规划算法,选取概率最大的路径进行分词 ''' 例如:sentence = '我爱北京天安门' id = 0 1 2 3 4 5 6 则 DAG = { 0:[0], 1:[1], 2:[2,3], 3:[3], 4:[4,5,6], 5:[5], 6:[6] } ''' # 在进行 4:[4,5,6], 分词时,计算出成词的最大概率路径为4~6,即‘天安门’的概率大于‘天安’ self.calc(sentence, DAG, route) x = 0 buf = '' N = len(sentence) while x < N: y = route[x][1] + 1 l_word = sentence[x:y] if y - x == 1: buf += l_word else: if buf: if len(buf) == 1: yield buf buf = '' else: # 对于未登录词,使用HMM模型进行分词 if not self.FREQ.get(buf): recognized = finalseg.cut(buf) for t in recognized: yield t else: for elem in buf: yield elem buf = '' yield l_word x = y if buf: if len(buf) == 1: yield buf elif not self.FREQ.get(buf): recognized = finalseg.cut(buf) for t in recognized: yield t else: for elem in buf: yield elem
5. 动态规划算法求解最大概率路径。
jieba在使用精确模式进行分词时,会将‘天安门’分割成‘天安门’,而不是全模式下的‘天安’和‘天安门’两个词,jieba时如何做到的呢?
其实,求解的核心在于‘天安门’的成词概率比‘天安’大。
5.1 先看看jieba的动态规划后的结果 ''' 例如:输入的动态图如下 DAG = { 0:[0], 1:[1], 2:[2,3], 3:[3], 4:[4,5,6], 5:[5], 6:[6] } 则,返回值为: R = { 0:(f1,0), 1:(f2,1), 2:(f3,3), 3:(f3,3), 4:(f4,6), 5:(f5,5), 6:(f6,6) } 这个返回值是什么含义呢? 例如:0:(f1,0) ----> id从0到0成词概率最大,最大概率为f1 4:(f4,6), ----> id从4到6成词概率最大,最大概率为f4 依据返回值R,可以得到成词下标,0->0,1->1,2->3,4->6,即:我/爱/北京/天安门 ''' def calc(self, sentence, DAG, route): N = len(sentence) route[N] = (0, 0) logtotal = log(self.total) for idx in xrange(N - 1, -1, -1): route[idx] = max((log(self.FREQ.get(sentence[idx:x + 1]) or 1) - logtotal + route[x + 1][0], x) for x in DAG[idx])
5.2 动态规划算法
jieba使用的是1-gram模型,即 P(S) = P(W1)*P(W2)*....P(W3). 要求得P(S)取得最大值时,P(W1)/P(W2)..../P(Wn)依次取得什么值。
这里采用动态规划算法来求解该问题。即:argmax P(S) = argmax ( P(Wn)*P(Sn-1)) <=> argmax (log(P(Wn))+log(P(Sn-1)))
当使用jieba中的Route来存储最大概率路径时,即得到 R[i] = argmax(log(Wi/V) + R[i-1]),jieba中使用了一个小技巧,即倒着扫描,这与DAG中的list存储着后向节点有关系。即R[i] = argmax(log(Wi/V) + R[i+1]),于是便有了上述代码。
6. 关于未登录词的HMM求解。
关于HMM介绍这里不做赘述,这里仅描述一下,jieba是怎么依据HMM模型进行分词的。
6.1 问题建模
jieba 使用 BMES对词进行建模。比如:我爱北京天安门,用BMES表示为:SSBEBME。只要拿到了SSBEBME这个字符串,就可以对“我爱北京天安门”进行分词,按照该字符串,分词结果为: 我/爱/北京/天安门。
那么问题来了,如何由“我爱北京天安门”得到“SSBEBME”这个字符串呢?
我们可以将“我爱北京天安门”理解为观察结果,“SSBEBME”理解为隐藏的词的状态的迁移结果,即HMM中的隐式状态转移。那么问题就成了:如何求解:P(S|O)= P(隐式状态迁移序列|观测序列).
6.2 问题求解
依据贝叶斯公式: P(S|O) = P(S,O)/P(O) = P(O|S)P(S)/P(O)
结合HMM相关知识,进一步求解P(S|O) = P(St|Ot) = P(Ot|St)*P(St|St-1)/P(Ot),由于每一个t时刻,P(Ot)都一样,可以去掉,因此:
P(St|Ot) = P(Ot|St)*P(St|St-1),其中 P(Ot|St)为发射概率,即HMM的参数Bij,P(St|St-1)是HMM的状态转移矩阵参数,即Aij。
另外还已知初始状态向量参数,因此可以求解出P(S|O)的最大值时的概率路径,也就是 “SSBEBME”。
6.3 jieba中的HMM参数值
初始状态概率在 jieba/finalseg/prop_start.py里面。 P={'B': -0.26268660809250016, 'E': -3.14e+100, 'M': -3.14e+100, 'S': -1.4652633398537678}
状态转移矩阵参数在 jieba/finalseg/prop_trans.py P={'B': {'E': -0.510825623765990, 'M': -0.916290731874155}, 'E': {'B': -0.5897149736854513, 'S': -0.8085250474669937}, 'M': {'E': -0.33344856811948514, 'M': -1.2603623820268226}, 'S': {'B': -0.7211965654669841, 'S': -0.6658631448798212}}
发射概率在 jieba/finalseg/prop_emit.py
6.4 jieba中这些HMM的参数是怎么来的呢?
据jieba官方介绍,是采用人明日报的语料库 和另外一个分词工具训练来的。总而言之,这些参数是依据特殊语料统计得到的。如果使用jieba的默认参数导致分词不理想时,应该考虑到重新训练自己的HMM参数。
6.5 jieba HMM源码解析
源码路径在 jieba/finalseg/_init_.py
主体代码流程如下: def cut(sentence): # 先解码 sentence = strdecode(sentence) # 再按照正则表达式进行初步分割 blocks = re_han.split(sentence) for blk in blocks: if re_han.match(blk): # 依据HMM模型,对未登录词进行分割 for word in __cut(blk): if word not in Force_Split_Words: yield word else: for c in word: yield c else: tmp = re_skip.split(blk) for x in tmp: if x: yield x
HMM分词如下: def __cut(sentence): global emit_P # 使用viterbi算法进行HMM求解,即生成 BMES的状态迁移序列 prob, pos_list = viterbi(sentence, 'BMES', start_P, trans_P, emit_P) begin, nexti = 0, 0 # print pos_list, sentence # 依据 BMES的状态迁移序列,进行分词 for i, char in enumerate(sentence): pos = pos_list[i] if pos == 'B': begin = i elif pos == 'E': yield sentence[begin:i + 1] nexti = i + 1 elif pos == 'S': yield char nexti = i + 1 if nexti < len(sentence): yield sentence[nexti:]
这里使用了viterbi算法求解状态转移序列。关于viterbi算法,注意两点:该算法的推导时自顶向下,但是最终的计算是自底向上,体现在分词上,就是从前往后计算。求解的目的也是找到一条最大概率路径,因此也是动态规划算法。这里就不推导了。
【三】总结
jieba分词,对于登录词,使用最大前缀匹配的方法,其中精确模式使用了动态规划算法来计算最大概率路径,进而得到最佳分词。对于未登录词,jieba使用HMM模型来求解最佳分词。
两种方式,都用到了词典与模型的HMM模型参数。因此,对于某些分词场景,可以使用自己的词典和自己的语料库训练出来的HMM模型参数进行中文分词,进而提升分词准确性。
jieba分词的核心理论基础为:统计和概率论。不知道基于深度学习的算法,是否可以进行中文分词。
人工智能
2018-11-02 21:41:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
人工智能、机器学习都已走进了我们的日常,尤其是愈演愈热的大数据更是跟我们的生活息息相关,做 人工智能、数据挖掘的人在其他人眼中感觉是很高大上的,总有一种遥不可及的感觉,在我司也经常会听到数据科学部的同事们提到 机器学习、数据挖掘 之类的词。但这些名词真的跟我们移动开发就没直接关系了吗?
作为移动开发者来说,无时无刻不被这些名词狠狠地敲打着脆弱的内心。???? ???? ???? 何时才能够将机器学习、深度学习应用在移动端,敲响移动端机器学习工业化的大门呢?
想象一下,某一天你身处一个完全陌生的环境,周围都是陌生的事物,而运行在iPhone的某个APP却对这个环境了如指掌,你要做的就是打开这个APP,输入你需要了解的事物,iPhone告诉你这个事物的信息,你也就没有了陌生事物了。世界就在眼前!
如下图:
上面物体的识别准确率还是蛮不错的,基本识别出了键盘(49%的概率)、鼠标(46%的概率)和水杯(24%的概率)。
但是在某些事物的识别准确度方便却差强人意,比如下图:
Phone 8被识别成了iPod(59%的概率),而iPod的却是不怎么敢认(10%的概率)。想想最崩溃的估计是iPhone 8了,身价直接被降了好几个等级。
上面的例子来自于TensorFlow官方iOSDemo,暂且不评述TensorFlow的识别准确度如何,毕竟它还年轻,但是仅凭其识别能力的体现,也给机器学习在移动端的运用带来了无限的可能。
一、TensorFlow(简称TF)
去年,Google资深系统专家Jeff Dean在湾区机器学习大会上隆重介绍了其第二代深度学习系统TensorFlow,一时间网络上针对TensorFlow的文章铺天盖地,揭秘TensorFlow:Google开源到底开的是什么?、Google开源TensorFlow系统,这背后都有什么门道?、如何评价Google发布的第二代深度学习系统TensorFlow?等等文章,TensorFlow的燎原之火一直在燃烧蔓延着,其GitHub上的开源库在此文撰写时,也已经被star:27550,fork:11054了。???? ???? ???? ???? ????
不负众望,Google一直宣称平台移植性非常好的TensorFlow,终于在2016年6月27日,发布0.9版本,宣布移动端支持。TensorFlow v0.9 now available with improved mobile support( 有墙???? ),同时也给出了移动端的Demo,对于代码为生的程序员,身处大数据处理为主导的TalkingData,也小试身手了一把,下载TensorFlow源码,查看编译指南,开始跳坑、填坑之路,也成就了此篇拙文的产生。
如果对Python编程、网络爬虫、机器学习、数据挖掘、web开发、人工智能、面试经验交流。感兴趣可以519970686,群内会有不定期的发放免费的资料链接,这些资料都是从各个技术网站搜集、整理出来的,如果你有好的学习资料可以私聊发我,我会注明出处之后分享给大家。
二、从TensorFlow到iOS静态库
对于iOS平台下如何使用TensorFlow,TensorFlow也给出了详细的编译脚本命令,详情请查看官方文档的命令。
第一步. 工具准备
工欲善其事必先利其器,在开始编译工作之前,需要准备一些编译所必须的工具:
Homebrew: Mac os x 上包管理工具 $ /usr/bin/ruby -e ``"$(curl -fsSL [https://raw.githubusercontent.com/Homebrew/install/master/install](https://raw.githubusercontent.com/Homebrew/install/master/install))"
Homebrew安装好之后,依次安装三个辅助性编译工具: $ brew install libtool $ brew install autoconf $ brew install automake
第二步. 克隆TensorFlow
Google以Apache 2.0开源协议将TensorFlow开源在GitHub上,我们可以直接使用TensorFlow源码。
在任意你想存放TensorFlow源码的地方(建议不要放在桌面。_),clone项目。 $ git clone [https://github.com/tensorflow/tensorflow](https://github.com/tensorflow/tensorflow)
第三步. 编译前准备
在TensorFlow的tensorflow/contrib/makefile/目录下,有很多可使用的编译脚本,其中build_all_ios.sh脚本专门用来一键编译TensorFlow iOS静态库。虽然可以直接使用此脚本进行一键编译,但是因为有墙,某些依赖需要提前做处理。
1、下载protobuf protobuf 是编译前唯一需要特殊处理的依赖库,[点击下载](https://github.com/google/protobuf/archive/master.zip),下载protobuf之后,解压,备用。
2、下载googlemock 虽然protobuf编译脚本autogen.sh中的googlemock链接地址https://googlemock.googlecode.com/files/gmock-1.7.0.zip无法直接下载到,但是细心的人会发现,在浏览器中输入 https://googlemock.googlecode.com/地址后,会跳转到https://github.com/google/googlemock地址,google在GiHub上的仓库地址。而GitHub上的仓库,我们可以直接的下载,克隆等。
我们直接在GitHub上下载googlemock(点击下载),下载完成后,修改压缩包名字为gmock-1.7.0.zip,修改后将此压缩包移至上一步protobuf文件夹目录下,备用。
3、修改下载依赖脚本,移除protobuf的下载
在tensorflow/contrib/makefile/目录下,download_ dependencies.sh 脚本用来下载相关依赖,打开此脚本文件,注释掉或者直接删掉git clone https://github.com/google/protobuf.git ${DOWNLOADS_DIR}/protobuf部分,目的是不让脚本去下载protobuf。
上面三步准备好后,接下来就进入静态库编译了。
第四步. 一键编译
前面已经知道在TensorFlow文件夹tensorflow/contrib/makefile/目录下的build_all_ios.sh脚本是用来编译iOS静态库的脚本,因此可以直接执行此脚本,开始静态库的编译工作了。
但是有一个问题大家可能会发现,由于编译TensorFlow需要用到protobuf,但是protobuf使我们自己手动下载的,该怎么让手动下载的protobuf能够直接让build_all_ios.sh脚本使用呢?
答案是复制、粘贴。可能有些low,但是有效。执行命令 build_all_ios.sh之后,立即把之前手动下载的protobuf文件夹拷贝进tensorflow/contrib/makefile/downloads目录。(放心,你拷贝的速度会很快,不会影响编译的执行的。_) $ build_all_ios.sh
一切准备就绪,接下来就是静静的等待编译完成了。在Mac编译的过程中,建议插上电源,最好不要让设备休眠断电,也最好不要去干别的东西,出去溜达一圈,回来后就看到战果了。
编译完成之后,会在tensorflow/contrib/makefile/gen/目录下看到编译的结果,关于这些静态库该如何使用,自己的项目如何应用,请参考 TensorFlow iOS Examples 。
三、遇到的问题
1、googlecode.com被墙了,需要翻墙!(目前测试挂了VPN也没用),这也是上面编译前准备为什么要那么做的原因。 curl: (7) Failed to connect to googlemock.googlecode.com port 443: Operation timed out
解决: 请参考 『第三步. 编译前准备』。
2、没有Xcode。 xcrun: error: SDK "iphoneos" cannot be located xcrun: error: SDK "iphoneos" cannot be located xcrun: error: unable to lookup item 'PlatformPath' in SDK 'iphoneos' + IPHONEOS_PLATFORM=
解决:安装Xcode,从上面报错的命令中可以看到,在编译静态库的过程中使用了xcrun,而此命令是xCode本身具有的能力。
3、你的Xcode版本不是7.3或以后,或者你有多个Xcode,而默认的安装路径版本不是7.3或以后。 error: Xcode 7.3.0 or later is required. exit 1
解决:更新Xcode至最新版本,并且保证默认路径下是最新/版本。
如果Xcode是7.3,并且没有条件更新Xcode,你可以修改tensorflow/contrib/makefile/compile_ios_tensorflow.sh 里的REQUIRED_XCODE_VERSION=7.3.0,为REQUIRED_XCODE_VERSION=7.3。(这样修改,目前还不确定会不会带来一些其他影响,最好是升级你的Xcode)
人工智能
2018-11-02 15:49:00
「深度学习福利」大神带你进阶工程师,立即查看>>>

大数据技术的发展与应用已经在深刻地改变和影响我们的日常生活与工作,可以预见的是在大数据提升为国家战略层面后,未来的几年里大数据技术将会被更多的行业应用。
相信很多人对于大数据技术的应用还是处于一个非常陌生的阶段,可能在很多地方听说过大数据,但具体应用在哪方面可能就并不清楚了。举个最简单的的例子,前段时间新闻报道说警方在某明星的演唱会上抓捕了一名在逃嫌犯,而这名嫌犯是在进入现场时被监控识别出来的。这种就是大数据技术的一种具体的应用表现。这个案例可能不是很贴切,但应该很好理解了吧!
企业对大数据技术的需求尤其是在移动互联网进入到井喷式发展阶段后变得尤为强烈。当然,我们这里探讨的仅是大型企业而非中小型企业。中小型企业当然也是可以应用大数据技术,但着实没有这样做的必要,因为中小企业基本不会产生大量的数据,换句话就是中小企业产生的这些数据不能用体现大数据技术在处理这些数据方面的优势。
企业大数据解决方案在市场上不能说是很多吧,毕竟大数据技术难度高度摆在这里,不是一般的企业就可以去做的。不同的解决方案会一些方面存在一定的差异,这里给大家介绍分析一下DKH大数据解决方案的的优势。
DKH大数据解决方案:以大数据云计算技术为核心的,统一数据管控解决方案
以大快的DKH为基础,增加数据可视化,异构数据全文搜索,跨平台数据整合,NLP以及人工只能等基础功能,面向大中型企业及政府机构,提供的基于大数据与云计算技术的新一代跨平台数据中心解决方案。(备注:资料来源于大快搜索)
以DKH(大快的发行版hadoop)为核心,增加数据可视化、数据权限管控,异构数据管理、全文搜索引擎、语义搜索和自然语言处理等技术,实现大数据的跨平台整合管控。
DKH大数据解决方案优势: 数据互联互通,支持多数据集实时同步; 支持数据资源管理,实现多源异构数据的整合管控; 提供完善的大数据分析基础运行环境,提供统一二次开发接口; 动态数据可视化,支持权限管理 集成基于人工智能的全文搜索引擎和语义搜索技术 提供容灾备份功能吗,原有数据可无缝全自动灾备还原; 全程管控,实现数据交换全流程跟踪及服务状态实时监控; 简捷极致的运维管理,有效降低运维难度和管理成本。
人工智能
2018-11-02 13:33:04
「深度学习福利」大神带你进阶工程师,立即查看>>>
NumPy是在python中处理数据的最基本和最强大的包。 如果您打算从事数据分析或机器学习项目,那么对numpy的充分理解几乎是必须的。 其他用于数据分析的软件包(如pandas)是建立在numpy之上,用于构建机器学习应用的scikit-learn软件包也在numpy上运行。 但对于.NET开发人员来说,却没有这样的强大工具库。 虽然有像Deedle和Math.NET这样的开源库,但它们不是很容易使用,也不能借用很多现有的python代码。
NumSharp(Numerical .NET)可以说是C#中的线性代数库。 它是用C#编写的,符合.netstandard 2.0库标准。 它的目标是让.NET开发人员使用NumPy的语法编写机器学习代码,从而最大限度地借鉴现有大量在python代码的转译成本。 NumSharp使用最新的Span技术安全高效地访问内存,优化每个模拟API的性能,确保最底层的NDArray达到最佳性能状态。NumSharp对于在数组上执行数学和逻辑运算非常有用。 它为.NET中的n阵列和矩阵的操作提供了大量有用的功能。
让我们给出一个代码片段来说明如何使用NumSharp。 // 初始化一个NumSharp实例,类名故意叫NumPy var np = new NumPy(); // 产生一个数字0到9的向量 np.arange(10) // 产生一个3维张量 np.arange(12).reshape(2, 3, 2); // 产生10个0到9的随机数,并转换成5*5的矩阵 np.random.randint(low: 0, high: 10, size: new Shape(5, 5));
上面的代码是不是看起来否非常接近python代码?简直就是如出一辙。NumSharp的目的就是让你可以轻松的复制粘贴Python代码。
如何安装: PM> Install-Package NumSharp
如果您觉得这个图书馆对您有帮助,请积极参与讨论。 欢迎在 Github 上为我点赞。 这里还有个 神经网络代码 ,是完全基于NumSharp编写的。
人工智能
2018-11-08 10:58:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
#导入 直接将文本load成numpy.ndarray,如果类型不是默认类型(dtype=float)会导致部分数据nan,skip_footer world_alcohol = numpy.genfromtxt("world.txt", delimiter=",", #以“,”为列的分隔符 skip_header=1, #跳过第一行 usecols=(0, -1), #只读取的列 dtype="U75", #设定类型 names="A, B, C", #设定列名 missing_values={0:"N/A", 'b':" ", 2:"???"}, #某列缺失值定义 filling_values={0:0, 'b':0, 2:-999} #某列缺失值替换 )
#初始化 vector = numpy.array([5, 10, 15, 20]) matrix = numpy.array([[5, 10, 15], [20, 25, 30], [35, 40, 45]]) np.zeros ((3,4)) np.ones( (2,3,4), dtype=np.int32 ) np.arange( 0, 2, 0.3 ) #0-2,以0.3为步长 np.random.random((2,3)) #2行3列的0-1 array from numpy import pi np.linspace( 0, 2*pi, 100 ) #设置100个点 z = np.linspace(0,10,11,endpoint=True,retstep=True) #生成0~10之间均匀分布的11个数,包括0和10 help(np.linspace) a=[1,2,3] np.diag(a) 是生成1,2,3 为对角线的方阵
#常用方法属性 查看维度:vector.shape 查看类型:vector.dtype 更改类型:vector = vector.astype(float) type(d) 和 d.dtype 一个返回的是d 的数据类型 nd.array 另一个返回的是数组中内容的数据类型 类型NumPy array必须所有数据是相同类型 a.ndim #查看维度坐标的数量,axes (dimensions)的数量 a.dtype.name a.size#总数
#索引 vector[1,4]第一行第四列的值,从0开始.vector[0:3]是0-2的数列 matrix[:,1],所有行的第2列,matrix[:,0:2],所有行的1,2列 matrix = numpy.array([ [5, 10, 15], [20, 25, 30], [35, 40, 45] ]) matrix[1:3,1:3] [[20 25]
  [35 40]]
#比较 vector = numpy.array([5, 10, 15, 20]) vector == 10 -> array([False,  True, False, False], dtype=bool) 比较每一个元素 通过比较的bool结果索引 vector = numpy.array([5, 10, 15, 20]) equal_to_ten = (vector == 10) print equal_to_ten -> [False  True False False] print(vector[equal_to_ten]) -> [10] matrix = numpy.array([ [5, 10, 15], [20, 25, 30], [35, 40, 45] ]) second_column_25 = (matrix[:,1] == 25) print second_column_25 -> [False  True False] print(matrix[second_column_25, :]) -> [[20 25 30]] equal_to_ten_and_five = (vector == 10) & (vector == 5) #进行与或非操作 vector = numpy.array([5, 10, 15, 20]) equal_to_ten_or_five = (vector == 10) | (vector == 5) vector[equal_to_ten_or_five] = 50 print(vector) -> [50 50 15 20] matrix = numpy.array([ [5, 10, 15], [20, 25, 30], [35, 40, 45] ]) second_column_25 = matrix[:,1] == 25 print second_column_25 -> [False  True False] matrix[second_column_25, 1] = 10 print matrix -> 中间25->10
#运算 vector = numpy.array([5, 10, 15, 20]) 求和:vector.sum() 求平均:vector.mean() numpy.exp():返回e的幂次方 matrix.sum(axis=1) # 1是按行相加,0是按列相加 is_value_empty = numpy.isnan(world_alcohol[:,4]) #判断是不是nan,各个位置是bool值 z = np.zeros((5,5)) z += np.arange(5) print np.arange(5) -> [0 1 2 3 4] print z [[0. 1. 2. 3. 4.] [0. 1. 2. 3. 4.] [0. 1. 2. 3. 4.] [0. 1. 2. 3. 4.] [0. 1. 2. 3. 4.]] a1=mat([1,1]); a2=mat([2,2]); a3=multiply(a1,a2) np.array的+/-/平方**2/开方np.sqrt(A)都是对应元素操作,<>也是对应元素,返回对应的bool值 两种点乘操作:A.dot(B) np.dot(A, B) A.T #转置 np.floor()#各个元素向下取整
#变形 a = np.arange(15).reshape(3, 5)#更改形状 reshape:有返回值,所谓有返回值,即不对原始多维数组进行修改; resize:无返回值,所谓有返回值,即会对原始多维数组进行修改; 将多维数组降位一维: numpy.ravel()   #返回的是视图(view,也颇有几分C/C++引用reference的意味),会影响原始矩阵 numpy.flatten() #返回一份拷贝,对拷贝所做的修改不会影响(reflects)原始矩阵
#拼接 np.hstack((a,b))#列相拼接,多了列,行数不变 np.vstack((a,b))#行拼接,多了行,列数不变 np.vsplit(a,3)#将a从行切出3个array b = a  #是一个对象 相等 变化牵连 c = a.view() #创建一个新对象 不相等 变化不牵连 d = a.copy() #完全复制一个对象 不相等 变化不牵连 ind = data.argmax(axis=0)  np.argmax(data,axis=0) #array每行上最大数的索引下标 (3,)#一维数组 (1,3)#二维 import numpy as np data = np.sin(np.arange(20)).reshape(5,4) print data [[ 0.          0.84147098  0.90929743  0.14112001] [-0.7568025  -0.95892427 -0.2794155   0.6569866 ] [ 0.98935825  0.41211849 -0.54402111 -0.99999021] [-0.53657292  0.42016704  0.99060736  0.65028784] [-0.28790332 -0.96139749 -0.75098725  0.14987721]] ind = data.argmax(axis=0) print ind - > [2 0 3 1] data_max = data[ind, xrange(data.shape[1])] print data_max ->[0.98935825 0.84147098 0.99060736 0.6569866 ] all(data_max == data.max(axis=0)) -> True
#numpy.tile(A,reps) numpy.tile(A,reps) #tile共有2个参数,A指待输入数组,reps则决定A重复的次数。整个函数用于重复数组A来构建新的数组。 numpy.tile([1,2,3],2) -> array([1, 2, 3, 1, 2, 3]) numpy.tile([1,2,3],(1,2)) -> array([[1, 2, 3, 1, 2, 3]]) numpy.tile([1,2,3],(2,1)) ->array([[1, 2, 3],[1, 2, 3]]) 注意维度:一维数组shape为(3,),扩充至2维则shape值为(1,3),扩充至3维则shape值为(1,1,3) y = x.argsort() #argsort()函数是将x中的元素从小到大排列,提取其对应的index(索引),然后输出到y a = np.array([4, 3, 1, 2]) j = np.argsort(a) print j -> [2 3 1 0] print a -> [4 3 1 2] print a[j] -> [1 2 3 4]
#sort() # 直接对对象进行排序,不会产生一个新数组,而是在原数组的基础上进行修改 # None : 如果待排序的对象是一个视图的话,则原始数据将会被修改 obj.sort() # 这种方式会为原数组创建一个已排序的副本,所以并不会对原数组进行修改 np.sort(obj) # 相同之处:两种排序都可以接受一个axis参数,用于对相应的行或者列进行排序 # Note : 两个排序方法都不可以被设置为降序,只能是升序, ndarray.sort(axis=-1, kind='quicksort', order=None) 或者:ndarray.sort(axis=-1, kind='quicksort', order=None) 参数     描述 axis     排序沿数组的(轴)方向,0表示按行,1表示按列,None表示展开来排序,默认值为-1,表示沿最后的轴排序 kind     排序的算法,提供了快排'quicksort'、混排'mergesort'、堆排'heapsort', 默认为‘quicksort' order     排序的字段名,可指定字段排序,默认为None
#meshgrid() [X,Y]=meshgrid(x,y) [X,Y]=meshgrid(x)=[X,Y]=meshgrid(x,x) m, n = (5, 3) x = np.linspace(0, 1, m) y = np.linspace(0, 1, n) X, Y = np.meshgrid(x,y) X,Y:3行5列
#NumPy 用字符编码来表示数据类型 数据类型     字符编码 整数      i 无符号整数     u 单精度浮点数     f 双精度浮点数     d 布尔值      b 复数      D 字符串      S Unicode      U Void      V
#其他操作: z[1::2,::2] = 1 z[::2,1::2] = 1 z = np.random.random((10,10)) zmin,zmax = z.min(),z.max() #归一化,将矩阵规格化到0~1,即最小的变成0,最大的变成1,最小与最大之间的等比缩放 z = 10*np.random.random((5,5)) print z zmin,zmax = z.min(),z.max() z = (z-zmin)/(zmax-zmin) print z 交换第0,1行:a[[0,1]] = a[[1,0]] #找出数组中与给定值最接近的数 z = np.array([[0,1,2,3],[4,5,6,7]]) a = 5.1 print np.abs(z-a).argmin() -> 5 #判断二维矩阵中有没有一整列数为0? z = np.random.randint(0,3,(2,10)) print z -> [[1 1 2 0 0 1 1 0 2 2],[0 0 2 1 0 2 1 0 1 0]] print z.any(axis=0) -> [ True  True  True  True False  True  True False  True  True]
人工智能
2018-11-07 21:44:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 10月27日下午,2018中国计算机大会上举办了主题“存储软硬件之国产化挑战与机遇”的技术论坛,共同探讨存储软硬件栈上的关键系统与技术的国产化发展道路。论坛上,阿里数据库资深技术专家黄贵针对存储软硬件国产化进行了《存储新硬件给数据库自研带来的机会》的报告。
10月27日下午,2018中国计算机大会上举办了主题“存储软硬件之国产化挑战与机遇”的技术论坛,共同探讨存储软硬件栈上的关键系统与技术的国产化发展道路。论坛上,阿里数据库资深技术专家黄贵针对存储软硬件国产化进行了《存储新硬件给数据库自研带来的机会》的报告。
专家简介:
黄贵,阿里巴巴数据库事业部资深技术专家,近10年一直从事分布式存储、分布式数据库的设计与研发工作,经历过连续6年双11的数据库大考,见证了阿里从商业数据库到开源数据库再到自主研发分布式数据库的过程。目前的方向是打造全面兼容MySQL生态,新一代跨地域高可用,高可扩展,高性能低成本分布式数据库X-DB。
首先,黄贵介绍了阿里巴巴随着业务迅猛增长而实现的数据库的进化,一直发展到目前已被广泛应用到阿里各项业务的异地多活,云化,分布式数据库X-DB。
其次,黄贵详述了阿里巴巴数据库面临的特殊挑战,以及为了应对这些挑战而做的设计,具体思路就是利用现代存储的多层次结构,根据业务访问数据特点,设计出一套分层的存储架构,结合了内存数据库和磁盘数据库技术,同时达成高性能和低成本。

最后,黄贵详述了数据库存储引擎X-Engine的设计思想,包括存储方式、应对超大并发事务的流水线事务处理模式、元数据索引结构、数据布局、数据访问加速、数据压缩等特性,同时指出其利用NVM引入新的存储层次,将存储层次分为冷数据、暖数据及热数据三类,三个层次采用Flash/HDD、NVM、DRAM不同存储类型,以应对不同数据特性。X-Engine结合大数据访问热点集中的特点,采用了基于数据访问频率区分冷热数据,并基于数据的冷热进行封层存储的架构,并在此架构上进行充分的优化以满足不断增长的需求。
了解更多阿里云产品请戳链接:
https://www.aliyun.com/product/list?utm_code=p_2018090501
阿里云双十一1折拼团活动:已满6人,都是最低折扣了
【满6人】1核2G云服务器99.5元一年298.5元三年 2核4G云服务器545元一年 1227元三年
【满6人】1核1G MySQL数据库 119.5元一年
【满6人】3000条国内短信包 60元每6月
参团地址: http://click.aliyun.com/m/1000020293/
原文链接
人工智能
2018-11-07 16:25:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 10月27日下午,2018中国计算机大会上举办了主题“数据中心计算”的技术论坛,一起探讨解决数据中心所面临的挑战。论坛上,阿里云分布式存储团队高级技术专家田磊磊进行了《阿里云文件存储的高性能架构演进之路》的报告。
10月27日下午,2018中国计算机大会上举办了主题“数据中心计算”的技术论坛,一起探讨解决数据中心所面临的挑战。论坛上,阿里云分布式存储团队高级技术专家田磊磊进行了《阿里云文件存储的高性能架构演进之路》的报告。
专家简介
田磊磊,阿里云存储团队高级技术专家,主要从事分布式文件系统领域工作多年,具有丰富的分布式存储开发经验。
田磊磊从存储介质、网络的发展以及人工智能、高性能计算、基因等领域的兴起给高性能计算带来的机遇和挑战出发,介绍了新一代Cloud Native文件存储在应用中所需要的特性以及更高的要求,尤其是要求高吞吐、高iops、低延时。随后,他又详述了阿里云文件存储如何架构在飞天盘古之上,同时简述了阿里云文件存储的高效元数据、高效线程模型以及文件协议等典型特性。

最后,田磊磊介绍了阿里云在高性能计算领域的最新实践,包括数据迁移、多种数据接入、云监控、云上大规模渲染。

了解更多阿里云产品请戳链接:
https://www.aliyun.com/product/list?utm_code=p_2018090501
原文链接
人工智能
2018-11-07 16:01:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
摘要: 近日,为了提升用户网站访问体验,阿里云虚拟主机宣布推出流量型独享虚拟主机新规格,流量型独享虚拟主机新规格可以提供高速流量包,提高访问速度。在高速流量包用尽后,网站也不会关停,可自动降为低带宽模式,保证网站一直在线。
近日,为了提升用户网站访问体验,阿里云虚拟主机宣布推出流量型独享虚拟主机新规格,流量型独享虚拟主机新规格可以提供高速流量包,提高访问速度。在高速流量包用尽后,网站也不会关停,可自动降为低带宽模式,保证网站一直在线。
全球首发,独享虚拟主机和流量包会结合出什么火花?
与共享云虚拟主机相比,独享云虚拟主机最大的不同点是用户可以资源独享,享有整个服务器的软硬件资源,即每台轻云服务器的 CPU、内存、带宽、硬盘均为独享,因此是企业建站的首选。稳定性具备了,提升访问速度也是重中之重。
阿里云独享虚拟主机流量包新规格是全球第一个将独享虚拟主机和流量包结合的产品,既带有独享虚拟主机的稳定特性,又提升了网站访问速度,同时最低带宽能够保证用户网站一直在线。
用户购买主机后开始计算高速流量,如果当月高速流量耗尽,则主机网络速度降为保底带宽1Mbps。保底带宽下流量速度不限制。流量包每月1日重置,同时峰值带宽恢复。
相较于阿里云之前推出的独享虚拟主机带宽型,独享虚拟主机流量型的网络峰值访问速度有了明显提升,其中基础版和标准版均比之前的带宽规格提升了1Mbps,而高级版和豪华版则相对之前(2Mbps)提升了4Mbps和8Mbps,网络访问速度最高提升了400%。
此次阿里云流量型独享虚拟主机新规格在国内主要地区均有上线,了解更多阿里云流量型独享虚拟主机新规格详情,请戳链接:
https://wanwang.aliyun.com/hosting?spm=a2c4e.11155435.1146454.867.450c3312naCJmF
原文链接
人工智能
2018-11-07 10:30:00