下图分析翻译里面的链接恶意代码分析实战 pdf

我的图书馆
特别说明:
本文写于2015年11月,当时我在找工作,据此优化简历,每投必中。当时我还写了求职相关的其它文章,发布在公众号“程序视界”和简书,比如、等。
文章特长,特考验耐性,特冲击三观,特消耗时间和精力,特容易造成心理压力,请先深呼吸三次再往下看。
求职季到了,我后续会在简书和公众号“程序视界”发布一系列求职相关的文章
文/foruok(简书作者)原文链接:file:///C:/Users/Administrator/Desktop/%E7%A8%8B%E5%BA%8F%E5%91%98%E8%BF%99%E6%A0%B7%E4%BC%98%E5%8C%96%E7%AE%80%E5%8E%86%EF%BC%8C%E4%B8%80%E6%8A%95%E5%88%B6%E8%83%9C%20-%20%E7%AE%80%E4%B9%A6.html著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。《花千骨》一剧,白子画为什么收花千骨为徒?《琅琊榜》中,梅长苏为什么选靖王而弃太子、誉王?《泰坦尼克号》里,杰克和露丝为什么会一见钟情?王子基特为什么会选择灰姑娘辛德瑞拉?
这些问题乍一看似乎和程序员找工作没什么关系,但其实,内在的道理都是相通的,搞明白这些问题,就能清楚下面的问题:
为什么你投十份简历,只有一两家公司约你?又或者为什么你每投一份简历都能获得面试机会?
最根本的原因,就是一方在汲汲渴求,而恰恰另一方呈现出的关键点让其怦然心动。求者心中有所想,而应者恰恰展现了求者所想的那一面。这就是个中奥妙。
程序员在找工作时,在一开始有三件事情会对能否获得面试机会至关重要:
知识、技能、经历梳理
确立求职目标
友情提示:假如你不想看万字长文,可以:跳到第3部分,看简历优化实操;跳到第4部分,看如何提高简历投递成功率。
【01】知识、技能、经历梳理
知识、技能、经历,这都是一个人能体现出来的商业价值。一家企业招募某个人,一定是因为这个人可以帮助企业在某方面实现价值。而且,正常情况下,个人的贡献一定要大于企业为这个人负担的各种成本(薪水、社保、公积金、个税等),否则,要你毛用啊。
所以,作为程序员,我们一定要清楚自己的价值在哪里。个人的商业价值,可以通过下面五大要素分析出来:
我们在招聘网站上填写简历时,内容最多的就是前三个要素,都是差不多的模板,填下来千人一面。
在最开始的时候,不建议直接到招聘网站上填写简历。强烈建议先用word或MarkdownPad来整理记录你认为你具备的所有有价值的知识、技能、经历,不论大小,统统记录下来。这是我们后续优化简历的基础,也是确立求职目标的基础。
1.1 知识与技能
有必要说一下知识和技能的区别,这是很多人常常混淆的。
知识可以通过语言文字、语音、视频等进行传授,比如像C++、Java、数学、物理、Qt、Android、设计模式、网络协议等都是知识。
技能是指按照某种规则应用知识和经验完成某种任务的能力。比如使用Qt开发桌面客户端软件就是一种技能,使用Java和Android界面类库开发App也是一种技能。
我的知识大概有这些:
C、C++、Java、Scala、Python、Qt、MFC、WTL、QML、Qt Quick、JavaScript、HTML、CSS、Lua、MySQL、MongoDB、XML、Json、Win32 SDK、Node.js、AngularJS、ffmpeg、VLC、DirectShow、Android、Objective-C、HTTP、P2P、RTMP、RTSP、HLS、P2P、socket、UML、软件开发模型(瀑布、迭代、Scrum等)、项目管理知识、团队管理知识、自媒体运营
知识会淡忘,一段时间不用就扔掉了,所以在你的知识图谱里,一定有一些是你经常使用的,比如我最熟悉的就是C、C++和Qt。
我们需要把自己最熟悉的三种知识标注出来,后面会派上用场。
技能就是对知识的运用,所以一般来讲你有什么知识,就能找到一组技能。比如我可能有下列技能:
使用Qt开发客户端软件
使用Qt开发服务器软件
使用Java开发Android App
管理项目,制定项目计划,跟踪计划,控制项目进度
团队管理与激励
博客、公众号等自媒体运营
好啦,现在我们应该可以进行知识和技能的梳理工作了。
需要特别注意的是,每个人都有很多知识和技能,一定要找出你擅长的2~3种知识,2~3种技能,这将是你求职时的重要参考。人只有使用最擅长的技能去做事情,才能达到最好的效果。
知识和技能可以帮助我们创造商业价值,而知识和技能的积累过程本身也是有价值的。积累知识和技能的过程,就是经历。
著名电影《贫民窟的百万富翁》讲述了这样一个故事:在孟买贫民窟长大的少年贾马尔参加一个名叫“谁想成为百万富翁”的节目,过五关斩六将,最终赢得了2000万卢布的大奖和他心爱的姑娘。
这个故事的神奇之处就在于贾马尔回答对了诸如“《darshan do ghanshyam》的词作者”、“1973年的动作电影《囚禁》的主演是谁”、“哪一位板球运动员是本世纪历史得分最多的”、“谁发明了左轮手枪”、“百元美钞上是哪一位美国总统的肖像”之类的问题,而这些问题连博士专家都没把握全中!这与他的身份完全不符,引起了节目主持人的质疑,认定他作弊,趁节目暂停录映,通知了警方以欺诈的罪名逮捕了贫民小子。
为什么贾马尔可以做到?随着问答节目的推进,我们发现,原来,这些问题相关的知识,贾马尔根本没有学习过,而是他独特的贫民窟生活刚好遭遇了这些问题。这就是经历的价值。
程序员的(学习、工作、项目)经历同样具有非常独特的价值,在求职过程中往往会发挥非常重要的作用。比如你做过视频项目,那再找类似做视频的公司就很容易脱颖而出;比如你做过图像处理相关的项目,进入美图秀秀之类的公司就相对容易……
在回顾项目经历时,关于你自己的那部分,一定要想明白并记录下来,从下面三点来挖掘你的亮点:
你负责的工作内容
用到的知识、技能
你对整个项目的贡献(最好可以量化)
我的一个项目经历:
【互联网视频卡顿优化】项目描述:  智能机顶盒上的视频聚合客户端,在播放视频时,高峰时段或热点视频,经常卡顿。针对此问题,进行优化,以使能够对用户提供流畅的观看体验业绩:  播放效果大幅度提升,卡顿投诉下降80%。职责:  作为项目经理,负责项目范围界定、进度跟踪与控制  作为系统设计,选择技术方案,设计加速与优化算法,设计系统结构。    作为核心开发人员,负责客户端 http 基础类库的开发和服务端 http server(基于Qt)的开发。
我没有列出前面所说三点对应的所有内容,个人亮点也没完全写出来,但你的心里一定要清楚,你发挥了什么关键作用,如果有攻克技术难点的经历和明显可以量化的业绩,一定要总结出来,面试时经常会被问到哦。
天赋和人脉其实也是个人非常重要的商业价值。但在程序员的简历中较难体现出来,在面谈中倒是有较多机会展现。
【02】确立求职目标
不管是从大学走向社会的初次求职,还是在职场摸爬滚打了N年的老鸟,找工作时都要忌讳一点:茫无目的,漫天撒网。
求职时,明确目标行业、企业、职位,有针对性的做准备,事半功倍。
2.1 职业延续性
跳一次槽换一个行业,跳一次槽换一条技术栈,这样极其不利于程序员的商业价值积累(知识、技能、业务等)。假如你不是第一次求职,就有必要考虑职业延续性。
假如你现在在金融行业,那换工作时,最好还在里面。这样你的行业相关的经验就可以积累下来,慢慢形成优势。假如你现在做iOS开发,最好换工作时还找iOS相关的,这样你的Objective-C啊,Swift啊、Cocoa啊才能持续精进……
有一种情况另当别论:你发现你不喜欢现在的行业和所用的技术。此时跳槽,就要找到新的方向(后面方法可以帮到你)。一旦你找到新的方向,转换过去之后,同样要考虑以后的延续性。每次都说自己不喜欢现在的,更喜欢另一个,这样捣腾几年之后,你很可能会发现,那些闷生不响持续深耕的小伙伴们居然一夜之间都牛逼闪闪起来了……
2.2 成就事件挖掘职业兴趣
在我们总结整理自己的工作、项目经历时,要特别留意那些让你特别有成就感的事件,它里面隐藏你的职业兴趣,可以挖掘出你今后乐意从事的职业方向。
我们可以遵循STAR原则来回顾成就事件:
S(Situation),背景情况,包括面临的障碍、限制或困难
T(Task),任务,目标,想完成的事情
A(Action),行动计划与步骤,如何克服障碍、达成目标
R(Result),对结果的描述,重点关注你取得了什么成就
成就事件列出来后,可以按照下面两点来深入挖掘:
哪一个具体的点让你特别有成就感,比如“达成结果受到领导表彰”、“独立克服某个技术难题”、“用自己的XXX帮到了某某某”、“成功组织大家齐心协力达到目标”……
用到了什么知识、技能
通过这样的分析,你就可能找到自己的最佳技能和工作中最在意的点在哪里,就可以根据他们来确立新的职业目标。
2.3 聚焦行业、企业、职业
聚焦的目的是缩小目标范围,节省时间和精力,深入研究分析,有针对性的对自己的商业价值进行优化组合,提高简历的吸引力,最后提升获取面试机会的概率。
程序员运用编程语言、技术框架、设计模式、算法等开发针对某个领域问题的软件,软件必然和目标需求和业务密不可分,所以,程序员左手技术,右手业务,假如你对业务内容完全不感兴趣,很难想象你可以把软件做好。因此,当你有了目标产业,目标公司,还要去了解这家公司做什么产品,是产品导向的公司,还是项目导向,还是外包为主,选择那家你对它的业务范围感兴趣的公司,不感兴趣的就果断筛掉。
基于延续性的考量,以往工作过的行业领域都需要认真对待,但不一定非要继续在之前的方向上做,换一换也可以。但有一个基本的原则,离夕阳产业和走下坡路的企业远点儿。
以我为例来分析一下。
技术方面最擅长的语言是C++,最擅长的框架是Qt(出过《Qt on Android核心编程》和《Qt Quick核心编程》两本书),最擅长的是客户端软件开发。然后对Android开发有了解也有兴趣。新的职位最好和这两方面相关。
不过,也不是所有人都想一直沿着一条技术栈走下去,我知道有一个哥们儿,用了10年C#,实在腻歪透了,在原公司不能转到其它方向,就跳了出来,想换到C++相关的技术栈上,结果总是有公司希望他从事能用到C#的岗位,不断给他打电话,他每次都拒绝掉。
我锁定的第一个目标是高级软件开发工程师,语言是C++。行业领域的话,互联网、智慧城市、企业服务等都可以。
还有,我之前都在小公司摸爬滚打,现在希望到比较大一点的公司里体验一下不同的工作氛围。
在锁定职位的过程中,还要考虑自己当前的劣势,以便在简历和面试过程中妥善应对。以我为例,如果找软件开发工作,就有两个不好的点:
最近一年没做什么开发工作,会被人质疑廉颇老矣尚能饭否
最近几年都在做技术管理工作,别人可能会奇怪你为什么倒回去做开发
这两点也会影响到目标职位的选择和匹配度,比如有的高级开发工程师职位要求有一定团队管理经验,那和我的匹配度就高一些。
好啦,我的聚焦过程已经完成了,接下来咱们进入简历优化的实操过程。
【03】简历优化实操
知道了自己有什么商业价值、弄清了想到什么样的行业什么样的企业里什么样的岗位上工作,接下来就该优化简历了。
简历优化有这么几个要点:
分析招聘信息,提取知识、技能、职责当中的关键词
根据招聘信息里的关键词,筛选个人知识、技能、经历
将匹配到的知识、技能、经历重新组织、呈现
程序员的简历,一般包含下列内容:
基本资料(姓名、性别、年龄、婚否、电话、当前在职状态)
求职意向(职位、工作地点)
知识、技能
附加信息(比如兴趣爱好、荣誉、博客、开源项目等)
根据实际情况,有的简历可能没有自我评价、附加信息,有的可能没有可写的教育经历(比如高中生),有的可能没有工作经历和项目经验(如大学生等初次求职者)。
特别提一下程序员的一些个人品牌相关的附加信息(具体参看),比如技术博客、github主页、参与的开源项目、自己做的App、公众号等,都是能非常好展现程序员知识、技能的东西,能为你的简历加分,也能弥补面试时间短信息交流补充分的问题。要知道,决定你能否通过简历关的,通常是另外一个程序员,而对聪慧内敛的程序员致敬的最好方式,就是“Show me the code”。
3.1 简历模板
很多程序员都使用招聘网站提供的简历模板,要在不同招聘网站上发布简历的话,可能要重复填写5、6次简历,非常耗时。我一般会有一份基础的word格式的简历,根据它在不同的招聘网站创建不同的简历。
接下来介绍我的简历,非常简单,顺次包括下列五部分内容:
技能与评价
我简历的前三部分简单如下:
个人信息  男,xxxx年xx月xx日生于xxx地方  2002年毕业于西安交通大学,电子信息工程专业,学士学位  153xxxxxxxx,  已婚求职意向  高级软件开发工程师,西安技能与评价  7年部门管理经验,丰富的项目、团队管理经验  7年嵌入式开发经验,在互联网电视机顶盒、车载娱乐系统、手持娱乐设备(MP3/MP4)等领域有成功经验  丰富的软件系统架构设计经验  熟悉常见的设计模式,有丰富的面向对象设计经验  精通C/C++,熟悉Java,Shell,了解python,Lua,JavaScript等  可熟练在Android、嵌入式Linux、Windows CE、Windows、Linux等平台下进行开发  熟悉Android/Qt(E)/MFC/WTL等GUI框架  熟悉DirectShow/GStreamer/MPlayer/FFMPEG/VLC/Vitamio等多媒体框架  熟悉网络编程,熟悉各种流媒体协议(http/HLS/rtmp/p2p/rtsp等)  博客:  github:  公众号:程序视界(programmer_sight)  著有《Qt on Android核心编程》和《Qt Quick核心编程》
我工作年限长,挑最近的几段看下:
工作经历5.12,陕西XX网络科技有限公司  ·职位:技术总监  ·职责:团队组建、管理、技术方向把握、项目管理、产品管理  ·业绩:3个月组建10人团队 4.12,北京XX有限公司(西安)  ·职位:平台组高级软件开发工程师  ·职责:跨平台软件开发  ·业绩:解决了Qt在Android和iOS两个平台与原生UI叠加的问题4.09,西安XX软件科技有限公司  ·职位:CMC部门经理  ·职责:   1). 部门员工组织、领导、管理、激励,绩效考评   2). 项目计划、实施、跟踪、管理   3). 技术路线评估与选择   4). 系统分析与设计   5). 关键模块代码实现  ·业绩:   1). 2009年至2010年,负责组建机顶盒开发团队与互联网视频搜索开发团队,并带领团队,完成了技术积累和产品探索,使得公司成功进入新的行业领域,完成公司的业务转型   2). 年,负责组建智能机顶盒团队,完成机顶盒产品智能化转型   3). 2012.07—至今,主持智能机顶盒产品研发   4). 12.06,主持第二代高清互联网机顶盒产品研发   5). 12.01,负责第一代高清互联网机顶盒产品研发与改进
好了,我简历的主体框架就是这样子了。接下来,我会根据我的目标职位——高级软件开发工程师——来找几条招聘信息,通过分析招聘信息来优化简历的技能与评价、项目经历两个部分。这两部分也是我们优化简历时的重点。
3.2 简历优化
大多数招聘需求是由我们的同行提供的,假如能从招聘信息里反推出拟定招聘需求的那个软件工程师或经理心中的关键词,那你的简历优化就有针对性了。
下图是一个招聘需求:
C++高级开发工程师
红线标注出来的,是一些关键的基本要求,C++、Qt、Windows桌面客户端,这些是硬性要求,要应聘该岗位必须要满足。
绿线标注出来的,是软性要求,不太容易直接量化和衡量,但面试官可能会在面试中通过交谈来考察。比如软件设计能力、技术传播能力、沟通能力、沟通与团队协作等,通常都是在面试中体现,而编码能力,则可能会通过笔试或者面试中不断的询问技术细节来检验。
蓝线标注出来的,是优选条件,在有多个候选人的情形下,你具备了这些要素,就会被优先考虑。
一般的企业处理软件开发工程师的简历,是HR先挑,然后是技术人员(程序员或经理)再次筛选,通过技术人员的筛选后,就会通知笔试或者面试。
HR拿到招聘需求,会和技术人员沟通要关注的关键点,然后根据这些关键点挑选合适的简历。通常在HR眼里,关键点就是关键词,所以,我们修改简历时,尽可能使用招聘信息里出现的字眼,便于HR识别。HR看一份简历,多则一分钟,少则20、30秒。
技术人员筛选简历,通常比HR要细一些,大致分两步,先筛关键词,然后是看项目经验里是否体现出了他们发布的岗位需要的技能和软实力。关键词匹配不上,PASS,30秒不到;能匹配上,继续看项目经验,整个过程可能会持续几分钟。
在看项目经验时,一方面看应聘者在项目中是否用到了将来需要的相关技能,另一方面看具体项目内容,做行业、产品、业务相关性比对,如果应聘者做的产品与招聘方要做的相关性高,就会被优先考虑。
通过对简历筛选流程的了解,可以知道关键词的重要性了。那接下来我们就要依据从招聘信息中提取的关键点来修改简历了。
在修改简历时,我的做法是尽可能多的在简历中体现企业要求的技能及软实力。一般可以在下面两处反复琢磨:
技能与评价
结合我的简历,先看技能与评价部分怎么修改。
因为目标职位是高级软件开发工程师,招聘信息也没有特别体现对管理能力和经验的要求,所以我的管理经验可以淡化或拿掉。然后是突出C++、Qt、软件设计、技术传播等内容。新的版本如下:
技能与评价  · 9年C++开发经验,精通C++,熟悉STL  · 5年Qt开发经验,基于Qt开发过8个商业项目,代码超过30万行  · 著有《Qt on Android核心编程》和《Qt Quick核心编程》  · 熟悉面向对象编程  · 熟悉GoF设计模式  · 丰富的软件设计、软件架构经验  · 熟悉MFC,熟悉网络编程,熟悉多媒体及各种流媒体协议  · 热衷技术传播,推动了Qt在团队和公司内的普及
新版本兼顾了硬性要求、软性要求和优选条件,与初始版本有明显不同。接下来,我们就要重新组织、呈现项目经历,让它更多地体现企业HR、面试官所关注的关键点。下面是我的一个具体的项目经验:
11.09,跨平台视频点播系统项目描述:面向电信运营商和零售市场的综合性视频服务产品,具有视频导航、搜索、点播、直播、天气、资讯、股票、教育等功能。产品形态有机顶盒、Windows客户端、Linux客户端等。软件环境:Embedded Linux,Qt Embedded 4.5.1,Qt 4.5.1,C/C++硬件环境:全志 F20芯片方案、PC角色:项目经理、核心程序员职责与工作内容:  1).软件系统结构设计  2).基于Qt GraphicsView框架设计实现十字菜单、影视信息墙  3).基于Qt的客户端业务流程代码实现  4).基于Qt实现认证模块  5).团队组建与项目管理业绩:  1).开发了稳定、性价比高的互联网机顶盒产品,打开了电信市场,销量超过30万台。  2).在团队里推广Qt,形成了技术积累  3).提供Windows及Linux客户端,为客服、运维、售后提供了强有力的支撑
这个招聘需求,和我的匹配点主要在技能(C++、Qt),接下来这个,责主要匹配的是业务(行业)经验。
高级C++开发工程师
红线标注出了基本要求:C/C++、Linux。
绿线标注的软性要求,一部分是不太容易量化的技能,比如精通多线程、独立设计经验等,一部分是产品业务相关的,比如音视频编解码、封装、流媒体、网络协议、视频业务系统等。
这则招聘信息中有两个优选条件,不过和我的知识、技能都不匹配。
一个程序员的知识、技能、经历,横看成岭侧成峰,角度很重要。
来看看新修改的技能与评价:
技能与评价  · 9年C++开发经验,精通C++,熟悉STL  · 可熟练在Linux、嵌入式Linux、Windows等平台下进行开发  · 熟悉常见的设计模式,有丰富的独立设计经验  · 6年视频业务开发经验,设计、开发过点播、直播流媒体处理系统,熟悉FFMPEG、GStreamer等开源框架  · 精通网络通信,自己实现过标准协议http协议和私有p2p协议,熟悉http/HLS/rtmp/p2p/rtsp等各种流媒体协议  · 热爱技术,著有《Qt on Android核心编程》和《Qt Quick核心编程》
和面向上一个招聘信息的内容又有了较大差异,是不是?
这次我改两个之前展示过的项目经历,方便比较不同。第一个:
1.09,跨平台视频点播系统项目描述:(略)软件环境:Embedded Linux,Qt Embedded 4.5.1,Qt 4.5.1,C/C++硬件环境:全志 F20芯片方案、PC角色:项目经理、核心程序员职责与工作内容:  1).软件系统结构设计  2).独立设计基于Qt的EPG框架  3).设计实现音视频解码、解封装流程(参考ffmpeg)  4).设计实现机顶盒软件的多线程模型  5).团队组建与项目管理业绩:  1).定制的多媒体框架保障了互联网机顶盒产品的视频处理效果,打开了电信市场,销量超过30万台。  2).提供Linux、Windows版本客户端,为客服、运维、售后提供了强有力的支撑  3).坚持自主实现关键的多媒体模块,形成了技术积累
这次我将重点放在了多媒体、设计等方面,与前面那份有了很大不同。
再来看文章最前面提到过的一个互联网视频卡顿的项目经验,新版本如下:
4.06,互联网视频卡顿优化项目描述:  智能机顶盒上的视频聚合客户端,在播放视频时,高峰时段或热点视频,经常卡顿。针对此问题,进行优化,以使能够对用户提供流畅的观看体验职责与工作内容:  1).作为系统设计,选择技术方案,设计加速与优化算法,设计系统结构。  2).C++实现标准http协议(含客户端和服务端)业绩:  播放效果大幅度提升,卡顿投诉下降80%。
和原来大不一样了。
需要特别提醒的是,简历优化是针对程序员知识、技能、经历进行的穿衣打扮,是从不同的视角呈现不同的侧面,可以用心琢磨,但万万不可造假。
3.3 检验优化效果
提供一个检验你简历优化水平的方法:
将你钟意的企业和职位分为A、B、C三类,A是最符合你目标的,B与你最核心的诉求匹配,C类呢可能抵触了你的某些核心价值观。
针对C类公司的职位,测试你的简历优化技能,找三五家来练手,投递简历,简历过了就去面试,攒面试经验。
C类之后进行B类,最后是A类。
这样的过程,能保证你先练简历和面试技术,然后以最好的状态走向你最心仪的公司最钟意的职位。
【4】如何提高简历投递成功率
根据前面的分析,要想提高简历投递的成功概率,遵循下面的流程将非常有帮助:
梳理知识、技能、经历并记录在案,形成基础简历
确立求职目标
筛选招聘信息,选择匹配自己目标的公司和职位
针对每个招聘信息进行分析,提取关键词
根据关键词,结合基础简历,优化技能描述和项目经验,生成一份有针对性的简历
根据我自己的经验,一天可能只能完成3份左右的简历投递。因为,针对每一个职位生成一份有针对性的简历,可能会花费1到2个小时时间,有时甚至更长。不过,花再多的时间都是值得的,因为这种优化将大大提高你简历通过的概率。
天啦撸,终于到结尾了,相关阅读(无链接的请到公众号“程序视界”查看):
做自己想做的工作
程序员跳槽神级攻略文/foruok(简书作者)原文链接:file:///C:/Users/Administrator/Desktop/%E7%A8%8B%E5%BA%8F%E5%91%98%E8%BF%99%E6%A0%B7%E4%BC%98%E5%8C%96%E7%AE%80%E5%8E%86%EF%BC%8C%E4%B8%80%E6%8A%95%E5%88%B6%E8%83%9C%20-%20%E7%AE%80%E4%B9%A6.html著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
TA的推荐TA的最新馆藏[转]&[转]&图像处理与机器视觉(1)
CS231n课程笔记翻译:图像分类笔记(上)
转自:/p/?refer=intelligentunit
译者注:本文首发,译自斯坦福CS231n课程笔记,由课程教师授权进行翻译。本篇教程由翻译完成。对译文进行了仔细校对,提出了大量修改建议,态度严谨,帮助甚多。对几处术语使用和翻译优化也提出了很好的建议。等亦有帮助。
这是一篇介绍性教程,面向非计算机视觉领域的同学。教程将向同学们介绍图像分类问题和数据驱动方法。下面是内容列表:
图像分类、数据驱动方法和流程
Nearest Neighbor分类器
k-Nearest Neighbor&译者注:上篇翻译截止处
验证集、交叉验证集和超参数调参
Nearest Neighbor的优劣
小结:应用kNN实践
目标:这一节我们将介绍图像分类问题。所谓图像分类问题,就是已有固定的分类标签集合,然后对于输入的图像,从分类标签集合中找出一个分类标签,最后把分类标签分配给该输入图像。虽然看起来挺简单的,但这可是计算机视觉领域的核心问题之一,并且有着各种各样的实际应用。在后面的课程中,我们可以看到计算机视觉领域中很多看似不同的问题(比如物体检测和分割),都可以被归结为图像分类问题。
例子:以下图为例,图像分类模型读取该图片,并生成该图片属于集合 {cat, dog, hat, mug}中各个标签的概率。需要注意的是,对于计算机来说,图像是一个由数字组成的巨大的3维数组。在这个例子中,猫的图像大小是宽248像素,高400像素,有3个颜色通道,分别是红、绿和蓝(简称RGB)。如此,该图像就包含了248X400X3=297600个数字,每个数字都是在范围0-255之间的整型,其中0表示全黑,255表示全白。我们的任务就是把这些上百万的数字变成一个简单的标签,比如“猫”。
—————————————————————————————————————————
图像分类的任务,就是对于一个给定的图像,预测它属于的那个分类标签(或者给出属于一系列不同标签的可能性)。图像是3维数组,数组元素是取值范围从0到255的整数。数组的尺寸是宽度x高度x3,其中这个3代表的是红、绿和蓝3个颜色通道。
—————————————————————————————————————————
困难和挑战:对于人来说,识别出一个像“猫”一样视觉概念是简单至极的,然而从计算机视觉算法的角度来看就值得深思了。我们在下面列举了计算机视觉算法在图像识别方面遇到的一些困难,要记住图像是以3维数组来表示的,数组中的元素是亮度值。
视角变化(Viewpoint variation):同一个物体,摄像机可以从多个角度来展现。大小变化(Scale variation):物体可视的大小通常是会变化的(不仅是在图片中,在真实世界中大小也是变化的)。形变(Deformation):很多东西的形状并非一成不变,会有很大变化。遮挡(Occlusion):目标物体可能被挡住。有时候只有物体的一小部分(可以小到几个像素)是可见的。光照条件(Illumination conditions):在像素层面上,光照的影响非常大。背景干扰(Background clutter):物体可能混入背景之中,使之难以被辨认。类内差异(Intra-class variation):一类物体的个体之间的外形差异很大,比如椅子。这一类物体有许多不同的对象,每个都有自己的外形。
面对以上所有变化及其组合,好的图像分类模型能够在维持分类结论稳定的同时,保持对类间差异足够敏感。
—————————————————————————————————————————
—————————————————————————————————————————
数据驱动方法:如何写一个图像分类的算法呢?这和写个排序算法可是大不一样。怎么写一个从图像中认出猫的算法?搞不清楚。因此,与其在代码中直接写明各类物体到底看起来是什么样的,倒不如说我们采取的方法和教小孩儿看图识物类似:给计算机很多数据,然后实现学习算法,让计算机学习到每个类的外形。这种方法,就是数据驱动方法。既然该方法的第一步就是收集已经做好分类标注的图片来作为训练集,那么下面就看看数据库到底长什么样:
—————————————————————————————————————————
一个有4个视觉分类的训练集。在实际中,我们可能有上千的分类,每个分类都有成千上万的图像。
—————————————————————————————————————————
图像分类流程。在课程视频中已经学习过,图像分类就是输入一个元素为像素值的数组,然后给它分配一个分类标签。完整流程如下:
输入:输入是包含N个图像的集合,每个图像的标签是K种分类标签中的一种。这个集合称为训练集。学习:这一步的任务是使用训练集来学习每个类到底长什么样。一般该步骤叫做训练分类器或者学习一个模型。评价:让分类器来预测它未曾见过的图像的分类标签,并以此来评价分类器的质量。我们会把分类器预测的标签和图像真正的分类标签对比。毫无疑问,分类器预测的分类标签和图像真正的分类标签如果一致,那就是好事,这样的情况越多越好。
Nearest Neighbor分类器
作为课程介绍的第一个方法,我们来实现一个Nearest Neighbor分类器。虽然这个分类器和卷积神经网络没有任何关系,实际中也极少使用,但通过实现它,可以让读者对于解决图像分类问题的方法有个基本的认识。
图像分类数据集:CIFAR-10。一个非常流行的图像分类数据集是。这个数据集包含了6的小图像。每张图像都有10种分类标签中的一种。这60000张图像被分为包含50000张图像的训练集和包含10000张图像的测试集。在下图中你可以看见10个类的10张随机图片。
—————————————————————————————————————————
左边:从数据库来的样本图像。右边:第一列是测试图像,然后第一列的每个测试图像右边是使用Nearest
Neighbor算法,根据像素差异,从训练集中选出的10张最类似的图片。
—————————————————————————————————————————
假设现在我们有CIFAR-10的50000张图片(每种分类5000张)作为训练集,我们希望将余下的10000作为测试集并给他们打上标签。Nearest Neighbor算法将会拿着测试图片和训练集中每一张图片去比较,然后将它认为最相似的那个训练集图片的标签赋给这张测试图片。上面右边的图片就展示了这样的结果。请注意上面10个分类中,只有3个是准确的。比如第8行中,马头被分类为一个红色的跑车,原因在于红色跑车的黑色背景非常强烈,所以这匹马就被错误分类为跑车了。
那么具体如何比较两张图片呢?在本例中,就是比较32x32x3的像素块。最简单的方法就是逐个像素比较,最后将差异值全部加起来。换句话说,就是将两张图片先转化为两个向量和,然后计算他们的L1距离:
这里的求和是针对所有的像素。下面是整个比较流程的图例:
—————————————————————————————————————————
以图片中的一个颜色通道为例来进行说明。两张图片使用L1距离来进行比较。逐个像素求差值,然后将所有差值加起来得到一个数值。如果两张图片一模一样,那么L1距离为0,但是如果两张图片很是不同,那L1值将会非常大。
—————————————————————————————————————————
下面,让我们看看如何用代码来实现这个分类器。首先,我们将CIFAR-10的数据加载到内存中,并分成4个数组:训练数据和标签,测试数据和标签。在下面的代码中,Xtr(大小是x3)存有训练集中所有的图像,Ytr是对应的长度为50000的1维数组,存有图像对应的分类标签(从0到9):
Xtr, Ytr, Xte, Yte = load_CIFAR10('data/cifar10/') # a magic function we provide
# flatten out all images to be one-dimensional
Xtr_rows = Xtr.reshape(Xtr.shape[0], 32 * 32 * 3) # Xtr_rows becomes 50000 x 3072
Xte_rows = Xte.reshape(Xte.shape[0], 32 * 32 * 3) # Xte_rows becomes 10000 x 3072
现在我们得到所有的图像数据,并且把他们拉长成为行向量了。接下来展示如何训练并评价一个分类器:
nn = NearestNeighbor() # create a Nearest Neighbor classifier class
nn.train(Xtr_rows, Ytr) # train the classifier on the training images and labels
Yte_predict = nn.predict(Xte_rows) # predict labels on the test images
# and now print the classification accuracy, which is the average number
# of examples that are correctly predicted (i.e. label matches)
print 'accuracy: %f' % ( np.mean(Yte_predict == Yte) )
作为评价标准,我们常常使用准确率,它描述了我们预测正确的得分。请注意以后我们实现的所有分类器都需要有这个API:train(X, y)函数。该函数使用训练集的数据和标签来进行训练。从其内部来看,类应该实现一些关于标签和标签如何被预测的模型。这里还有个predict(X)函数,它的作用是预测输入的新数据的分类标签。现在还没介绍分类器的实现,下面就是使用L1距离的Nearest
Neighbor分类器的实现套路:
import numpy as np
class NearestNeighbor(object):
def __init__(self):
def train(self, X, y):
&&& X is N x D where each row is an example. Y is 1-dimension of size N &&&
# the nearest neighbor classifier simply remembers all the training data
self.Xtr = X
self.ytr = y
def predict(self, X):
&&& X is N x D where each row is an example we wish to predict label for &&&
num_test = X.shape[0]
# lets make sure that the output type matches the input type
Ypred = np.zeros(num_test, dtype = self.ytr.dtype)
# loop over all test rows
for i in xrange(num_test):
# find the nearest training image to the i'th test image
# using the L1 distance (sum of absolute value differences)
distances = np.sum(np.abs(self.Xtr - X[i,:]), axis = 1)
min_index = np.argmin(distances) # get the index with smallest distance
Ypred[i] = self.ytr[min_index] # predict the label of the nearest example
return Ypred
如果你用这段代码跑CIFAR-10,你会发现准确率能达到38.6%。这比随机猜测的10%要好,但是比人类识别的水平()和卷积神经网络能达到的95%还是差多了。点击查看基于CIFAR-10数据的。
距离选择:计算向量间的距离有很多种方法,另一个常用的方法是L2距离,从几何学的角度,可以理解为它在计算两个向量间的欧式距离。L2距离的公式如下:
换句话说,我们依旧是在计算像素间的差值,只是先求其平方,然后把这些平方全部加起来,最后对这个和开方。在Numpy中,我们只需要替换上面代码中的1行代码就行:
distances = np.sqrt(np.sum(np.square(self.Xtr - X[i,:]), axis = 1))
注意在这里使用了np.sqrt,但是在实际中可能不用。因为求平方根函数是一个单调函数,它对不同距离的绝对值求平方根虽然改变了数值大小,但依然保持了不同距离大小的顺序。所以用不用它,都能够对像素差异的大小进行正确比较。如果你在CIFAR-10上面跑这个模型,正确率是35.4%,比刚才低了一点。
L1和L2比较。比较这两个度量方式是挺有意思的。在面对两个向量之间的差异时,L2比L1更加不能容忍这些差异。也就是说,相对于1个巨大的差异,L2距离更倾向于接受多个中等程度的差异。L1和L2都是在常用的特殊形式。
k-Nearest Neighbor分类器
你可能注意到了,为什么只用最相似的1张图片的标签来作为测试图像的标签呢?这不是很奇怪吗!是的,使用k-Nearest Neighbor分类器就能做得更好。它的思想很简单:与其只找最相近的那1个图片的标签,我们找最相似的k个图片的标签,然后让他们针对测试图片进行投票,最后把票数最高的标签作为对测试图片的预测。所以当k=1的时候,k-Nearest
Neighbor分类器就是Nearest Neighbor分类器。从直观感受上就可以看到,更高的k值可以让分类的效果更平滑,使得分类器对于异常值更有抵抗力。
—————————————————————————————————————————
上面示例展示了Nearest
Neighbor分类器和5-Nearest Neighbor分类器的区别。例子使用了2维的点来表示,分成3类(红、蓝和绿)。不同颜色区域代表的是使用L2距离的分类器的决策边界。白色的区域是分类模糊的例子(即图像与两个以上的分类标签绑定)。需要注意的是,在NN分类器中,异常的数据点(比如:在蓝色区域中的绿点)制造出一个不正确预测的孤岛。5-NN分类器将这些不规则都平滑了,使得它针对测试数据的泛化(generalization)能力更好(例子中未展示)。注意,5-NN中也存在一些灰色区域,这些区域是因为近邻标签的最高票数相同导致的(比如:2个邻居是红色,2个邻居是蓝色,还有1个是绿色)。
—————————————————————————————————————————
在实际中,大多使用k-NN分类器。但是k值如何确定呢?接下来就讨论这个问题。
图像分类笔记(上)完。
点击查看。
译者反馈:
因CS231n的单篇课程笔记长度长,完整阅读需较长时间。知友等建议对其进行适当分拆。故本次翻译将拆分为上下篇,每篇阅读量控制在1万字左右,降低阅读成本。效果如何,请知友们点评;知乎专栏的公式编辑器可以使用LaTeX语法,赞。但公式居中需手动空格,有无更优雅的方式?请知友们评论指教;翻译中的任何不足之处,请知友们在评论中批评指正,我们会及时讨论并作出反馈;本翻译是无偿行为,知乎专栏首发。允许转载,请全文保留并注明出处。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:3869次
排名:千里之外
转载:40篇
(3)(2)(7)(16)(2)(8)(1)(7)}

我要回帖

更多关于 恶意代码分析实战 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信