Quantcast
Channel: IT社区推荐资讯 - ITIndex.net
Viewing all 15896 articles
Browse latest View live

汽车分时租赁市场,有这七大发展趋势

$
0
0

从经济学的角度来说,一切能优化资源配置提升经济效率的模式,即最大可能实现帕累托最优的模式,都是有理论上的经济效益的。从出行领域来说,分时租赁的出现正好符合了这一要求。

分时租赁这一模式,更多承担的是城市公共出行的结构调整以及汽车行业供给侧的产能优化。2017年国家也从政策层面给予了定调,让市场信心大增。当然,这也意味着分时租赁其实距离市场和用户比想象中要远。

单纯从模式上讲,分时租赁其实并不是个新鲜东西。在这个维度里,早年的一嗨租车、神州租车本质上也算是分时租赁。关键在于,就像共享单车一样,如今的分时租赁要能做到线下广泛布点,实现无人值守、程序简单、线上运用互联网大数据优化车辆调配,这才是与传统分时租赁的不同点。归结到一个点,就是效率大大优化提升,符合现代人的快节奏生活。

从近三年的发展来看,汽车分时租赁之所以没有出现共享单车一样的火爆局面,很大的一个区别在于分时租赁的门槛更高。这不仅仅指资金投入、运营成本、技术层面的续航储能等进入门槛,还体现在线下布局的停车位资源及充电设施稀缺,这涉及到土地规划问题,在这个年代,这可是比黄金还昂贵的东西。另外的一个维度是,用户的进入门槛也更高,缺乏用户基础。

目前,分时租赁的基本面其实没有太大变化,以三年的发展周期来考量还是太短。2018年分时租赁也不会出现爆炸性发展的局面,短期内还是会集中在用户教育、扩大布局、打磨运营层面,细水长流可能才是常态。当然,有几个可能的发展趋势不妨盘点下。

趋势一:需求端待激活,市场启蒙将会加速

分时租赁的用户基础还不够,很多人甚至不知道分时租赁到底是什么,更谈不上使用了,需求端亟待激活。分时租赁要真正成为公共交通的有效补充,加速市场启蒙、用户教育几乎是板上钉钉的事。最近,滴滴、摩拜甚至美团都相继加入了分时租赁战场,这其实是个非常好的信号。

互联网巨头们都是流量与用户“黑洞”,可以在短时间内形成广泛的口碑传播和规模效应。随着越来越多互联网公司的跟进,分时租赁的用户启蒙工作可能会在短时间内有质的飞跃。

不过,由于滴滴、摩拜们原有业务切入的是10公里以下的短途出行,用户习惯相对固定,与分时租赁更集中在10~100公里的用车场景不同,当然不排除同一个用户群体会有多层次的使用和场景需求,但用户群体的迁移势必是缓慢的。

分时租赁的替代属性非常强,回归用户场景来看,用户可以选择专车、出租车、传统短期租车等等多种形式。但反过来看也一样,替代具有双向性,分时租赁同样可以替代其他。由此,在用户培育维度上,分时租赁将与其他可替代出行方式时刻处于拉锯战状态。

趋势二:用户层“补贴战”或将重现,但补贴不是唯一手段

分时租赁要激活需求端,并尽可能降低其可替代属性,做到性价比高和用车体验好是最基础的。

性价比对于基数众多的尝鲜型用户来说,少花钱甚至不花钱是最好不过的。补贴向来是互联网公司快速攻城略地的有效手段,分时租赁会迎来新一轮针对用户的“补贴战”吗?很有可能,并且目前已经有些苗头。

1月18日,神州租车宣布进军汽车分时租赁市场,主打的策略就是超低定价,并宣称价格基本不到市场上主要分时租赁车辆收费的60%,甚至还同时面向全国拿出1000万小时(1亿公里)招募500万名免费体验客户。这是要挑起补贴大战的节奏,一旦神州租车靠这个策略快速打开局面、蚕食其他玩家的份额,补贴战将不可避免。

当前分时租赁基本是不盈利的,而且政策层面对新能源汽车的补贴正在收紧,到2020年甚至有可能停止补贴,对用户的大范围“补贴”将是很多中小玩家不能承受之重。

补贴之外,车型够不够“逼格”也对用户习惯和忠诚度的养成至关重要。从实际使用场景来看,汽车分时租赁有很大的“炫富心理”在里面,跟摩拜的平民主义稍有不同。对于很多有本无车一族来说,豪华车的吸引力是巨大的。当然,很多汽车厂商也考虑到了这个问题,就连神州租车这次也打起了豪华车的主意,宣称将上线包括沃尔沃、宝马、路虎等50几款豪华车型。一位朋友租了辆宝马新能源车,跟我说起那感觉,“还真不一样啊”。

趋势三:市场集中度提高,小玩家或将陆续退出

分时租赁是个高资产、高资源整合能力、高运营能力、高技术能力的“四高”行业,要优化出行效率、向实现帕累托最优的路上再进一步,规模化、集中化是必然方向,也是长期过程。目前数据显示的400多家分时租赁企业,多而不大,各自为战根本无法承担产能升级、结构调整的重任。

当前,国内汽车的保有量已经超过3亿,核心城市早已拥挤不堪,在停车位等资源稀缺的制约下,分时租赁行业其实没有太多“试错”空间。这就像光伏行业的“路条”一样,“配额”有限,不是谁都能拿到。

分时租赁起步之初,小玩家还能在区域性小心测试,慢慢推动布局、打磨运营,在越来越多的整车厂加强投入,越来越多实力互联网公司伺机而动的当下,这样的创业环境几乎已经成为过去。

而随着新能源补贴政策的退坡,资源逐渐向优势企业集中,拼车辆、资金、资源的小企业都没有任何优势,抛开这些拼运营那更是“无水之源”,不知从何谈起。即使“补贴战”不会很快到来,小玩家们也会不断被头部企业挤压,逐步被吸纳消化最后退出。而这一天或许不远了。

趋势四:先行者有优势,大厂商或成格局霸主,甚至形成地区垄断

在分时租赁的大格局里,有一定规模的先行者有巨大优势,最终很可能形成各大厂商鼎立的局面,甚至形成阶段性的地区垄断。

从分时租赁的发展轨迹来看,很多人认为分时租赁的快速发展是政策引导的结果,但最合理的解释应该是,企业先行先试,然后政府看到希望,从而采取措施进行支持引导,是政府与市场合力的结果。在这样的视角下,有一定规模的先行者,会更有优势去争取补贴和资源。事实上,这种先行者恰恰都是大厂商,比如上汽EVCARD、首汽GoFun、北汽绿狗、吉利康迪等等,这些企业在产能优化的刺激下也是分时租赁领域最激进的。

简单来看,目前分时租赁市场的入局者主要有汽车厂商、租车公司、互联网公司以及充电设施等产业链公司,竞争的核心将会聚焦在先行者汽车厂商和来势凶猛的互联网巨头之间。在两者的对位中,无论是资源还是资金实力,互联网巨头们并不占优势,车企们也不怎么缺乏互联网思维。互联网公司在现阶段的意义依然是重大的,快速启蒙市场非他们莫属。而且,延展场景、打通生态链,对互联网公司们讲故事、拉估值都有帮助,并不是一无是处。

就像EVCARD几乎已经垄断了上海市场一样,未来最可能的格局是,各大厂商以大本营为依托,先占领自己脚底下的底盘,像传统租车市场一样形成阶段性的地区垄断,上海是EVCARD的天下,西安是比亚迪的天下,安徽是奇瑞的天下,武汉是东风的天下等等。

当然,前提是这些厂商都愿意去做汽车分时租赁,如果谁不愿意,那这块地区市场就是大家都来抢了。

趋势五:造车之下,互联网巨头与大厂商合作是大势所趋

不过,大厂商的发展瓶颈也会比较明显:平台生态不够开放,产品线相对单一,各家主消化各家的车,这并不利于分时租赁的发展。不过,目前这一局面正在发生改变,从EVCARD开始向平台化战略就可见一斑。这个步子不会迈得很快,厂商们还会在各自的舒适区继续前行。

这几年,几乎与分时租赁同时起步的,还有国内轰轰烈烈的新能源造车运动,大量互联网公司甚至BAT巨头入局,再造一个“特斯拉”成了大家共同的目标。造车运动的战火蔓延,一定程度上加快了分时租赁的发展,尤其在2017年下半年,投入分时租赁领域的新能源汽车数量陡增。

事实上,在分时租赁不断消化新能源汽车产能的背景下,互联网巨头们和大厂商对位的必要性越来越小,合作共赢越来越成为大势所趋。从目前来看,无论是滴滴、摩拜还是神州租车,运营的车辆品牌越来越多,但目前的合作方式还处在集中采购或融资租赁层面,未来的合作也许会更多集中在自动驾驶技术的推进、云和大数据的开放互通、智慧出行解决方案的整合等更深的层面上。

趋势六:技术突破势在必行,并孕育新的创业机会

分时租赁同时是个高技术壁垒行业,涉及车辆充电、车辆的安全性、车联网系统、智能辅助驾驶甚至无人驾驶等多个维度,技术的突破对于分时租赁效率的提升至关重要。技术不成熟,大量运营工作只能采用原始的人工服务,不仅运营效率低下、成本高昂,还会造成诸多安全隐患。而在充电这个维度,目前的解决方案主要有充电和换电两种,如何提升充电效率和电池续航能力一直是业界亟待解决的难题,大大制约着分时租赁的发展。

换句话说,对于分时租赁这门生意而言,如果资源和资本是其肌肉,大数据可能是其血液,那么骨骼必然是其技术,技术的突破势在必行。从这个角度来说,中小玩家在分时租赁的竞争中并非完全没有机会,在底层的技术支持、大数据服务的提供等轻运营层面还有大量的机遇,但这口汤并不是谁都能喝。

趋势七:将市场的还给市场,补贴趋紧监管从宽

历经三年发展的分时租赁行业,尚处于起步阶段,不可否认,政策层面对分时租赁的发展影响很大。最近,双积分政策的出台也为分时租赁的发展释放了良好信号。但还是如前文所说的,分时租赁的发展是政府和市场合力的结果,创新的主体是市场中的企业这是毋庸置疑的。

将市场的还给市场是必然趋势,只是早晚的问题。聚焦到分时租赁领域来看,补贴趋紧但监管从宽可能会成为常态。当然,所谓的监管从宽,更多指的是让市场充分竞争,所谓的“引导”会淡化,政府监管将更多停留在规制层面,避免出现违规违法行为。

总而言之一句话,分时租赁短时间内不太可能出现疾风骤雨般的火爆局面,身处其中的大小玩家们,一场长期的攻坚战必然少不了。至于行业的趋势变化,早布局,早应对,倘若不行就干脆早早退出,商业战场向来如此。

【钛媒体作者介绍:晓枫说,游走在科技与人文边缘,专栏作者】

更多精彩内容,关注钛媒体微信号(ID:taimeiti),或者下载钛媒体App


微网关与服务啮合

$
0
0

技术雷达:现在越来越多的大型组织在向更加自组织的团队结构转型,这些团队拥有并运营自己的微服务,但他们如何在不依赖集中式托管的基础架构下,确保服务之间必要的一致性与兼容性呢?为了确保服务之间的有效协作,即使是自组织的微服务也需要与一些组织标准对齐。服务啮合(SERVICE MESH)在服务发现、安全、跟踪、监控与故障处理方面提供了一致性,且不需要像API网关或ESB这样的共享资产。服务啮合的一个典型实现包含轻量级反向代理进程,这些进程可能伴随每个服务进程一起被部署在单独的容器中。反向代理会和服务注册表、身份提供者和日志聚合器等进行通信。通过该代理的共享实现(而非共享的运行时实例),我们可以获得服务的互操作性和可观测性。一段时间以来,我们一直主张去中心化的微服务管理方法,也很高兴看到服务啮合这种一致性模式的出现。随着linkerd和Istio等开源项目的成熟,服务啮合的实现将更加容易。

新瓶旧酒还是厚积薄发?

对于持续关注云服务架构设计最新发展趋势的同学来说,刚过去的2017年,最火的词莫过于 CNCF了,这是一个专注于“云原生”(Cloud Native)的基金会,由众多战斗在云服务一线的公司(包括了谷歌、AWS、阿里云等等)组建而来,旨在推进云原生的架构标准化与最佳实践的普及。

而在最近一期的 技术雷达中,“云原生”(Cloud Native)和 “微服务”(Microservices)也引出了许多相关的技术,随着 Kubernetes、Docker 等一众容器管理工具的普及,我们也看到在容器的内部,微服务的架构设计也发生着一些变化,其中“服务啮合”(Service Mesh)就成为了大家关注的热点。

那么这些变化到底是新瓶旧酒,还是厚积薄发?我们不妨先从一个更耳熟能详的架构——“网关”(Gateway)谈起。

网关(Gateway)的作用

作为微服务工具链中的元老,“网关”(Gateway) 的引入为微服务API提供统一的入口和平台,不同的服务可以得到一致的管理。使用网关的架构可以减少企业大量的重复开发。甚至有一些通用的逻辑也可以使用网关来承载(如Zuul、Enovy、OpenResty等)。

不论初心为何,这些网关们随着时光流转,功能也变得越来越丰富,网关可以负责解决不同服务的服务注册发现、负载均衡、配额流控、监控日志、缓存加速、配置分离、安全管控、跟踪审计等问题。这一系列的功能,我们可以大致分为两类:“数据面”和“控制面”。

数据面(Data Plane)负责在 数据包粒度上进行筛选和处理

  • 路由转发
  • 负载均衡
  • 安全通信
  • 缓存加速
  • 认证鉴权
  • 日志审计
  • 健康检查
  • 熔断限流

控制面(Control Plane)负责在 服务粒度上进行统筹和管理

  • 注册发现
  • 配置管控
  • 弹性伸缩
  • 统筹遥测
  • 容错自愈
  • 策略执行
  • 证书签发

这一系列的功能,就是网关面临的问题域。在了解问题域之后,让我们回归本篇的主题:继承了“网关”(Gateway)衣钵的“微网关”(MicroGateway)和“服务啮合”(Service Mesh),它们到底是什么?

什么是微网关?

随着微服务的普及,传统的中心化网关变得越来越厚重,由于与中心化节点通信,带来了大量网络、IO开销以及单点问题,往往无法满足我们对于实时性、高可用的要求。另外越来越多的自治化需求,与原有集权式微服务治理方法之间,也产生出许多冲突矛盾。因此,与微服务化相适应的,可以 本地化、分布式部署的微网关(MicroGateway)也逐渐涌现出来。

什么是服务啮合?

服务啮合(Service Mesh)是一种为了保证“服务到服务”的安全、快速和可靠的通信而产生的基础架构层, 区别于应用层、通信层的一种新的云原生上下文内的抽象层。如果你正在构建云原生的应用程序,在微服务拓扑结构日益复杂的今天,服务啮合层的提出,可以帮助开发者将服务的交互通信问题与微服务内部的业务问题隔离开来,专注于各自的领域。

演进中的微网关与服务啮合

当我们了解到微网关与服务啮合的作用之后,就可以一起来看一下微网关与服务啮合架构是如何一步步设计出来的。

低侵入性组件(Low-Invasive Component)

最初的服务间互访,常常由于业务尚不清晰,给标准化带来了障碍。因此我们常常见到一些由领域专家提供的低侵入性的组件,为服务的开发者提供抽象的规范,使其能轻松获得定制化能力。

img

组件可以更好地规范问题,并且尽可能地将组件封装为简单的接口,早期的服务发现常常通过该类方式实现,例如 Eureka 套件通过引入 Client 来获得完整的如报告、监控、熔断等能力。

我们在一些 IAM (Identity Access Management)的服务设计中采用了这种模式,为各个业务服务提供了一致的认证鉴权接口, 由领域专家驱动,设计规范化的调用模式。由于该类组件尽可能设计为低侵入性的接口,因此微服务团队也可以更加便利地根据不同场景取舍是否使用该组件提供的功能,例如通过配置文件加 feature toogle 简单地在开发环境中关闭认证鉴权的功能,以加快开发进程。

反向代理(Reverse Proxy)

随着服务成熟度的提高,我们可以发现一些常见的非业务强相关的逻辑,可以从原有的服务中剥离出来,通过反向代理统一进行过滤处理。

img

反向代理,可以为微服务处理请求的前后环节增添通用逻辑,例如 apigee 提供的 API proxy 封装,通过反向代理模式为原有的服务添加 PreFlow、PostFlow, 解决请求生命周期前后常见的问题,例如检查配额和记录调用频度,对 CORS 等 Http Header 的添加和消费,这些功能有些类似于传统的 Filter 模型,但是却可以独立部署。

反向代理可以提供更高的可用性,并帮助微服务开发者从这些常见细节中解脱出来。

侧车模式(Sidecar Pattern)

准确来说,侧车模式(Sidecar Pattern)本身并非微网关或者服务啮合技术独有,它只是一种特定的软件模块共生关系。侧车模式可以是一个反向代理,也可以作为一个服务存在。

img

作为反向代理使用的Sidecar进程可以过滤请求与返回内容,实现如安全通信、认证鉴权、服务端/客户端负载均衡、自动路由等功能。

img

作为服务使用的Sidecar进程可以为主服务提供额外能力,实现分布式缓存同步、配置文件拉取、日志搜集等功能。

侧车模式常见于分布式缓存和安全基础设施网关,通过与微服务进程共同启停的服务或容器,可以更方便地与微服务一并调度,享受微服务管理平台本身提供的服务发现、注册、配置、扩容能力。 通过共享生命周期,在简单部署和灵活应用中寻找一个平衡

我们在微服务框架 Jhipster 提供的基础能力中,可以直接通过注解使用 Hazelcast 的分布式缓存,正是通过 Sidecar 模式实现的,拥有共生的分布式缓存实例后,可轻松实现服务接口的缓存,而分布式缓存自身的同步策略等问题都被封装在 Sidecar 进程中,无需开发者花费大量时间重新开发和调试。Sidecar也可以用于实现例如OAuth等安全相关的守护服务,帮助微服务处理业务界限外的专项问题。

原生的基础设施(Native Infrastructure)

服务啮合带来的最大的不同就是原生无感知,通过侧车模式部署的反向代理,与一些容器系统级的配置结合,更彻底地解决微服务在数据面与管理面的能力一致性问题。

服务啮合框架 Istio 提供了 Istio-Initializer 和 istioctl 工具,你可以在Kubernetes的容器整备过程中,注入所需的配置和 Envoy 容器, 将Sidecar Proxy、Sidecar Service注册为容器集群中的原生服务,可以在享受弹性部署的同时,享受数据面和控制面协同提供的标准化能力。无痛地加入Istio提供的功能,如 iptables 代理转发、双向TLS认证、限流策略、日志收集等等。

img

图片来自:http://t.cn/RETWzGV

我们在设计服务啮合层时也可以考虑使用更原生的服务组织与部署策略,例如将微服务容器注册为系统服务、通过控制流对容器进行编排、尽可能与微服务共享生命周期和运行环境来提高可用性与性能等等。

从现在开始,拥抱微服务的云原生生态

既是新瓶旧酒,又是厚积薄发,云原生趋势下的微服务也在不断的演进,逐渐变成我们最初希望的“会呼吸”的模样。我们建议您考虑在一些适用的场景,尤其是微服务化的架构设计中,考虑使用微网关与服务啮合,并总结最佳实践与我们交流。

让我们一起期待云原生生态下的微服务,为数字化时代提供更多的想象力。

如何看待消息中间件的选型

$
0
0

前言

近来有很多网友留言:公司要做消息中间件选型,该如何选?你哪个比较好?我的回答一般是:It’s a nice topic~如果随意回答一个的话显得很不严谨也不太负责任,如果严谨的回答的话一天就不用干活了。消息选型的确是一个大论题,实则说来话长的事情又如何长话短说。被问的越多越觉得需要整理一篇自己的观点出来,主要的目的将自己的经验分享出来,可以让别人少踩点误区,次要的目的是下次再被问到了可以直接甩链接而不用再打太极(如果你后者觉得这是主要目的话,那么我只能回答:橘生淮南则为橘,嘿嘿~~)。不过本文的主要内容为观点表达(别名:“吹水”),不涉及具体的技术细节。

历程

目前大多数所用的、所讨论的(Fashion的)消息中间件大致为Kafka、RabbitMQ和RocketMQ这三种,本文尽量站在一个中立的视角上去看待这个问题。当然如果你说市面上的MQ多了去了,比如还有ActiveMQ、ZeroMQ呢,这点我也不否认、不反驳,也不接茬~

关于消息中间件(下文会时不时的以MQ作为简称)的玩法,或者更贴切的称为使用历程大致可以分为四个阶段:

  • 大多数情况下基于时间、成本、技术栈等等考虑都会直接使用一种(或者多种)成熟的开源消息中间件。当然在选择之前一般也会做一些调研,不一样的选择意味着未来踩不一样的坑。很多初创型公司也会选择直接购买MQ的云服务,这不失为省钱的一个好办法。
  • 随着对消息中间件的了解以及业务需求的发展,基于现有的消息中间件来说无法完全满足目前的需求,这时候最好的方式就是对消息中间件本身做深度包装(也有可能再换一种MQ继续耍),最好是做成平台化的、以监控和管理等为一体的。
  • 当然也有团队选择自研。自研不是指拿一个开源的消息中间件出来随意“动两刀”,然后换个名称的假自研,而是大刀阔斧的对现有的消息中间件动刀或者是完全的功能自实现。至于自研具体原因其实有很多:是基于业务需求的拓展、还是现有的MQ无能力掌控、还是leader内心的躁动、还是KPI的压迫那就不得而知了,不过这的确是玩转消息中间件历程中不可或缺的一步。但这一步不是说比前面的两步绝对的高级,你完全可以简单对ArrayBlockingQueue做一个简单的封装而成为一个MQ,你也可以基于文件、数据库、redis等做封装而形成一个MQ,玩法随意、在“吹水”的同时能够不忘初心、真正落地即可。这一步的风险在于你基本脱离了生态社区的支持,自己挖的坑没人帮填;还有一个风险就是:老人离职、新人抓瞎。如果自研一个功能丰富的MQ的话,对人力、精力、财力都是不小的考验。
  • 最终极的当然是形成一定的规模体系、技术深度、生态口碑之后进行产品开源,技术来源于社区回馈于社区,既可以为公司做一定程度上的技术宣导,也可以提升自身境界。

选择

再回到本文的主题上来,个人对于消息的选型有3点看法:

  1. 没有蹩脚的MQ,只有蹩脚的coder
    很多时候你会看到网上的文章说这个MQ不好,哪个MQ不好。比如经常有评论说Kafka容易丢消息,我的内心回答:滚~说Kafka消息可靠,我的内心回答:也滚~ 这个世界上的事物没有绝对的,关键在于你对MQ本身的掌握程度。新版的Kafka有很多机制能够保证消息的可靠性,容易丢失是coder玩不转,如果说消息绝对可靠也是错误的,即使不说机房被炸,那你也是没有遇到偷硬盘的贼哦~ 不管选择哪个MQ都会有坑,没有绝对的好坏优劣,关键在于coder的把控。如果一些功能其他的MQ有而你的MQ么有,那你可以做一些深度包装;如果你的MQ性能跟不上,那你可以试一试优化,或者分布式水平扩展等等。
  2. 基于当前及可见未来的需求
    目前网络上的消息选型的对比文章,除非在文中严格限定了基于比较的版本,否则都是辣眼睛的,唾弃之。比如消息的幂等性,以前三大Fashion的MQ都不支持消息幂等性,所以很多选型对比类的文章在这一功能栏就写上了:不支持,现在最新版的Kafka就能支持一定程度上的幂等性,那么现在再看这篇文章的时候是不是觉得有槽点。再比如说RabbitMQ在消息大量堆积时会对性能产生影响,那你是没有调过优吧,你没玩过惰性队列吧。再比如流控、多租户、多语言支持、事务、可靠性等等方面的对比,Fashion的MQ时刻在level up,今天没有的、受限支持的功能或许明天就能实现。绝对的去评判哪个MQ好哪个MQ不好没有实际的意义,而是要根据实际的需求来做决定,多想想你的需求,有些业务需求对于某个MQ而言可以很容易的得到解决,而有些却是要山路十八弯,一个贴近需求的MQ选型可以让团队事半功倍。同时也需要考虑团队的技术栈,如果团队中对于某个MQ很熟悉,掌控力度很高,而对另一个MQ非常的陌生,如果此时选择是后者的话那就要多想想以后的路,路漫漫其修远兮~贴近需求,但也不要盲目的幻想需求,基于当前及可见未来的需求内而寻求能够落地的准则,没有最好的,只有最合适的,类似爱情~~
  3. 社区力度及生态发展
    对于目前流行的编程语言Java、Python而言,当然还有宇宙最强的php,如果你在使用过程中遇到了某个Exception,那么去搜索引擎上随意搜索下就能找到很多解决方案。对于MQ而言同样可以使用,如果你选择的是一种Fashion的MQ,那么势必用的人很多,用的人多了踩出来的坑也就多了,顺其自然的解决方案也就多了,版本更新弥补的也多了,进而你就可以站在这些“巨人的肩膀”上了。相反如果你采用了一种生僻的MQ,有可能在某些方面用的很爽,但是版本更新缓慢、遇到棘手问题难以得到社区的支持,最后就只能“跪在地板上”抓瞎了。社区力度越大的MQ,更新力度也大,不仅可以填补旧版本的坑,也能时不时带来一些新功能,释放你的双手。当然消息的选型也要考虑下其生态的发展,能够在多个领域里大放异彩的MQ基本是好的MQ,也可以为你的职业发展多加点料。

吴恩达deeplearning.ai五项课程完整笔记了解一下?

$
0
0

项目地址:https://github.com/mbadry1/DeepLearning.ai-Summary

上周吴恩达在推特上展示了一份由 TessFerrandez 完成的深度学习专项课程信息图,这套信息图优美地记录了深度学习课程的知识与亮点。这一份信息图的详细介绍请查看:这是一份优美的信息图,吴恩达点赞的 deeplearning.ai 课程总结

Deeplearning.ai 课程开课以来,一直受到大家的关注,也有众多读者积极的参与到学习中。机器之心在这段时间内也介绍了多篇该系列课程的学习笔记,以下为前四课的笔记与学习心得:

Mahmoud Badry 完成的笔记主要分为五部分,分别对应神经网络与深度学习基础、提升 DNN 性能的技巧与方法等、结构化机器学习项目、卷积神经网络和序列模型五门课程。值得注意的是,该项目完成的笔记十分详细,基本上五门课程的知识点全都覆盖到了。例如第一项课程以每周不同主题为序记录了从神经网络简介到 Goodfellow 采访等基本知识点。

由于前四课很多知识点都已经介绍过,因此本文我们着重介绍第五课的笔记概要,读者可自行查阅 GitHub 阅读完整的笔记,也可查看机器之心往期发过的一些课程资料。

第五课序列模型简介

本课程将讲授如何构建自然语言、音频和其他序列数据的模型。在深度学习的帮助下,序列算法比两年前效果更好,用于大量有趣的应用,如语音识别、音乐合成、聊天机器人、机器翻译、自然语言理解等。学完本课,你将:

  • 了解如何构建和训练循环神经网络(RNN)及其常用变体,如 GRU 和 LSTM。

  • 使用序列模型处理自然语言问题,如文本合成。

  • 将序列模型应用到音频应用中,如语音识别和音乐合成。

  • 这是 Deep Learning Specialization 课程的第五课,也是最后一课。

适用人群:

  • 学完第一、二、四课的学习者。同样推荐大家学习第三课。

  • 已经对神经网络(包括 CNN)具备深厚理解,并想学习如何开发循环神经网络的人。

该课程介绍循环神经网络(RNN)、自然语言处理和词嵌入还有序列模型和注意力机制等,以下将简要介绍 Mahmoud Badry 所完成的序列模型笔记。

序列模型

序列模型(如 RNN 和 LSTM)极大地改变了序列学习,序列模型可通过注意力机制获得增强。序列模型在语音识别、音乐生成、情感分类、DNA 序列分析、机器翻译、视频活动识别、命名实体识别等方面得到应用。

循环神经网络模型(RNN)

循环神经网络出现于 20 世纪 80 年代,最近由于网络设计的推进和图形处理单元上计算能力的提升,循环神经网络变得越来越流行。这种网络尤其是对序列数据非常有用,因为每个神经元或者单元能用它的内部存储来保存之前输入的相关信息。在语言的案例中,「I had washed my house」这句话的意思与「I had my house washed」大不相同。这就能让网络获取对该表达更深的理解。

RNN 有很多应用,在自然语言处理(NLP)领域表现良好。下图是一个用于解决命名实体识别任务的 RNN 网络。

用于解决命名实体识别任务的 RNN 网络。

简化版 RNN 表示法。

沿时间的反向传播(BPTT)

RNN 架构中的反向传播,w_a、b_a、w_y、b_y 被序列中的所有元素共享。

这里使用交叉熵损失函数:

其中第一个公式是序列中一个元素的损失函数,整个序列的损失是每个元素的损失之和。


在上图中沿时间反向传播中,激活值 a 从一个序列元素向另一个元素传播。

RNN 的类型

RNN 的不同类型。

RNN 的梯度消失

「梯度消失」指的是随着网络深度增加,参数的梯度范数指数式减小的现象。梯度很小,意味着参数的变化很缓慢,从而使得学习过程停滞。循环神经网络在语言建模等序列问题上有非常强大的力量,但同时它也存在很严重的梯度消失问题。因此像 LSTM 和 GRU 等基于门控的 RNN 有非常大的潜力,它们使用门控机制保留或遗忘前面时间步的信息,并形成记忆以提供给当前的计算过程。

门控循环单元(GRU)

GRU 旨在解决标准 RNN 中出现的梯度消失问题。GRU 背后的原理与 LSTM 非常相似,即用门控机制控制输入、记忆等信息而在当前时间步做出预测,表达式如下:

GRU 有两个有两个门,即一个重置门(reset gate)和一个更新门(update gate)。从直观上来说,重置门决定了如何将新的输入信息与前面的记忆相结合,更新门定义了前面记忆保存到当前时间步的量。如果我们将重置门设置为 1,更新门设置为 0,那么我们将再次获得标准 RNN 模型。使用门控机制学习长期依赖关系的基本思想和 LSTM 一致,但还是有一些关键区别:

  • GRU 有两个门(重置门与更新门),而 LSTM 有三个门(输入门、遗忘门和输出门)。

  • GRU 并不会控制并保留内部记忆(c_t),且没有 LSTM 中的输出门。

  • LSTM 中的输入与遗忘门对应于 GRU 的更新门,重置门直接作用于前面的隐藏状态。

  • 在计算输出时并不应用二阶非线性。

为了解决标准 RNN 的梯度消失问题,GRU 使用了更新门(update gate)与重置门(reset gate)。基本上,这两个门控向量决定了哪些信息最终能作为门控循环单元的输出。这两个门控机制的特殊之处在于,它们能够保存长期序列中的信息,且不会随时间而清除或因为与预测不相关而移除。

带有门控循环单元的循环神经网络

以下展示了单个门控循环单元的具体结构。

门控循环单元

LSTM

使用传统的通过时间的反向传播(BPTT)或实时循环学习(RTTL/Real Time Recurrent Learning),在时间中反向流动的误差信号往往会爆炸(explode)或消失(vanish)。但 LSTM 可以通过遗忘和保留记忆的机制减少这些问题。

LSTM 单元一般会输出两种状态到下一个单元,即单元状态和隐藏状态。记忆块负责记忆各个隐藏状态或前面时间步的事件,这种记忆方式一般是通过三种门控机制实现,即输入门、遗忘门和输出门。

以下是 LSTM 单元的详细结构,其中 Z 为输入部分,Z_i、Z_o 和 Z_f 分别为控制三个门的值,即它们会通过激活函数 f 对输入信息进行筛选。一般激活函数可以选择为 Sigmoid 函数,因为它的输出值为 0 到 1,即表示这三个门被打开的程度。

图片来源于李弘毅机器学习讲义。

若我们输入 Z,那么该输入向量通过激活函数得到的 g(Z) 和输入门 f(Z_i ) 的乘积 g(Z) f(Z_i ) 就表示输入数据经筛选后所保留的信息。Z_f 控制的遗忘门将控制以前记忆的信息到底需要保留多少,保留的记忆可以用方程 c*f(z_f)表示。以前保留的信息加上当前输入有意义的信息将会保留至下一个 LSTM 单元,即我们可以用 c' = g(Z)f(Z_i) + cf(z_f) 表示更新的记忆,更新的记忆 c' 也表示前面与当前所保留的全部有用信息。我们再取这一更新记忆的激活值 h(c') 作为可能的输出,一般可以选择 tanh 激活函数。最后剩下的就是由 Z_o 所控制的输出门,它决定当前记忆所激活的输出到底哪些是有用的。因此最终 LSTM 的输出就可以表示为 a = h(c')f(Z_o)。

双向 RNN(BRNN)

双向 RNN 和深度 RNN 是构建强大序列模型的有效方法。下图是一个命名实体识别任务的 RNN 模型:

BRNN 架构

BRNN 的缺点是在处理之前需要整个序列。

深度 RNN

深度 RNN 可帮助构建强大的序列模型。

3 层深度 RNN 图示。

RNN 的反向传播

在现代深度学习框架中,你只需实现前向传播,框架会执行反向传播,因此大部分机器学习工程师不需要担心反向传播。但是,如果你是微积分专家,想了解 RNN 中反向传播的细节,可参考该 notebook:https://www.coursera.org/learn/nlp-sequence-models/notebook/X20PE/building-a-recurrent-neural-network-step-by-step。

自然语言处理与词表征

词表征在自然语言处理中是必不可少的部分,从早期的 One-Hot 编码到现在流行的词嵌入,研究者一直在寻找高效的词表征方法。Mahmoud Badry 在笔记中详细记录了词嵌入方法,包括用于命名实体识别、人脸识别和翻译系统的词嵌入等,下图展示了用于人脸识别的词嵌入结构:

在这种词嵌入方法中,我们可以将不同的人脸编码压缩为一个向量,进而根据该向量比较是不是同一张脸。

词嵌入有非常多的优秀属性,例如给定一张词嵌入表。该笔记用案例来解释词嵌入的语义相近关系,如下图所示,男性变化到女性与国王变化到女王的反向在嵌入空间内是相同的,这意味着词嵌入捕捉到了词与词之间的语义相关性。

一般来说,Word2Vec 方法由两部分组成。首先是将高维 one-hot 形式表示的单词映射成低维向量。例如将 10,000 列的矩阵转换为 300 列的矩阵,这一过程被称为词嵌入。第二个目标是在保留单词上下文的同时,从一定程度上保留其意义。Word2Vec 实现这两个目标的方法有 skip-gram 和 CBOW 等,skip-gram 会输入一个词,然后尝试估计其它词出现在该词附近的概率。还有一种与此相反的被称为连续词袋模型(Continuous Bag Of Words,CBOW),它将一些上下文词语作为输入,并通过评估概率找出最适合(概率最大)该上下文的词。

对于连续词袋模型而言,Mikolov 等人运用目标词前面和后面的 n 个词来同时预测这个词。他们称这个模型为连续的词袋(CBOW),因为它用连续空间来表示词,而且这些词的先后顺序并不重要。CBOW 可以看作一个具有先知的语言模型,而 skip-gram 模型则完全改变将语言模型的目标:它不像 CBOW 一样从周围的词预测中间的词;恰恰相反,它用中心语去预测周围的词。

Mahmoud Badry 还展示了另一种学习词嵌入的方法 GloVe,该方法虽然不像语言模型那样使用广泛,但它精简的结构非常容易理解:

序列模型与注意力机制

最后一部分作者着重介绍了注意力机制,包括编码器解码器架构的缺陷和引入注意力机制的解决方案。下图展示了使用语境向量 C 或注意力权重编码信息的过程。

其实当我们翻译一个句子时,会尤其关注于正在翻译的单词。神经网络可以通过注意力来实现同样的行为,即关注所收到信息子集的一部分。

我们通常是使用基于上下文的注意力生成注意力分布。参与的 RNN 会生成一个描述它想关注内容的查询。每一个条目和这个查询做点乘来产生一个分数,这个分数描述这个条目与查询匹配程度。这些分数被输入一个 softmax 来生成注意力分布。

Patriciachen: A股业绩预告披露规则 注:交易所有权修订披露规则,大的原则不变(都是依据他们各自的交易所上市规则),但细节会有调整。深交所的内容来源于其网站于... - 雪球

$
0
0
注:交易所有权修订披露规则,大的原则不变(都是依据他们各自的交易所上市规则),但细节会有调整。深交所的内容来源于其网站于2016年12月29日发布的相关备忘录,上交所的内容来源于其网站发布的信息披露监管问答。

一、深圳证券交易所

(一)创业板
披露条件:预计全年度、半年度、前三季度出现以下情况的,应进行业绩预告, 部分上市公司需要进行业绩预告:净利润为负、同比变化+- 50%以上、同比或与最近一期相比出现盈亏变化、期末净资产为负。
需要披露业绩修正公告的情形:业绩变动方向不一致;方向一致,但变动幅度或者盈亏金额超出原先预计范围的 20%或者以上;预计盈亏变化等。
披露时间(业绩预告与业绩修正公告时间同)
         
业绩快报:年度报告预约披露时间在 3-4 月份的上市公司,应当在 2 月底之前披露年度业绩快报,误差在+-20%以内。

(二)中小板
披露条件:公司应在第一季度报告、半年度报告和第三季度报告中披露对年初至下一报告期末的业绩预告。 即全部上市公司均进行业绩预告。公司预计第一季度业绩将出现归母净利润为负值、净利润与上年同期相比变化+- 50%以上(前一年基数较小的除外)、扭亏为盈,应不晚于3月31日(在年报摘要或临时公告)进行业绩预告。

需要披露业绩修正公告的情形:
1.最新预计的业绩变动方向与已披露的业绩预告不一致,包括:原先预计亏损,最新预计盈利;原先预计扭亏为盈,最新预计继续亏损;原先预计净利润同比上升,最新预计净利润同比下降;原先预计净利润同比下降,最新预计净利润同比上升。
2.最新预计的业绩变动方向与已披露的业绩预告一致,且变动幅度或盈亏金额与原先预计的范围差异较大。

修正公告披露时间:
         
业绩快报:年度报告预约披露时间在 3-4 月份的公司,应在 2 月底之前披露年度业绩快报。 本所鼓励半年度报告预约披露时间在8月份的公司在7月底前披露半年度业绩快报。

(三)主板
披露条件:预计(第一季度、半年度、第三季度和年度)报告期内出现以下情况的,应进行业绩预告, 部分上市公司需要进行业绩预告:净利润为负、盈利且同比变化+- 50%以上(基数过小的除外)、扭亏为盈、期末净资产为负、年度营业收入低于1千万元。

需要披露业绩修正公告的情形:
1.最新预计的业绩或财务状况变动方向与已披露的业绩预告的变动方向不一致,包括但不限于: 1)原预计亏损、最新预计盈利;2)原预计扭亏为盈、最新预计继续亏损;3)原预计净利润同比上升、最新预计净利润同比下降;4)原预计净利润同比下降、最新预计净利润同比上升;5)原预计净资产为负值、最新预计净资产不低于零值;6)原预计年度营业收入低于 1000 万元、最新预计年度营业收入不低于 1000万元。 前4条与中小板同
2.最新预计的业绩变动方向虽与已披露的业绩预告一致,但业绩变动幅度超出已预告变动范围,且与原预告变动范围的上限或下限相比差异达到±50%以上(预告为比例范围)或盈亏金额与原先预计金额存在较大差异,最新预计盈亏金额比此前预告盈亏金额同向变动达到50%以上(预告为金额范围)。

业绩预告披露时间(与中小板业绩修正公告时间同):
         
业绩快报:鼓励披露业绩快报。


二、上海证券交易所
披露条件:从规则上看,只要求部分上市公司对全年业绩进行预告。对于年度报告,如果上市公司预计全年可能出现亏损、扭亏为盈、净利润较前一年度增长或下降50%以上等三类情况,应当在当期会计年度结束后的1月31日前披露业绩预告。公司在期限届满后,如果发现这三类情况,但没有在规定期间预告的,应当在第一时间尽快作出预告。
对于半年报和季度报告,《股票上市规则》没有就业绩预告做出强制要求,公司可以自主决定是否发布业绩预告。
内容要求:如果采用数值或者比例区间进行业绩预告的,预测的区间不宜过大,较高数值(比例)一般不得超过较低数值(比$例)的20%为宜,且最大区间不得超过50%。

如何用Python和机器学习训练中文文本情感分类模型?

$
0
0

利用Python机器学习框架scikit-learn,我们自己做一个分类模型,对中文评论信息做情感分析。其中还会介绍中文停用词的处理方法。

如何用Python和机器学习训练中文文本情感分类模型?

image

疑惑

前些日子,我在微信后台收到了一则读者的留言。

如何用Python和机器学习训练中文文本情感分类模型?

image

我一下子有些懵——这怎么还带点播了呢?

但是旋即我醒悟过来,好像是我自己之前挖了个坑。

之前我写过《 如何用Python从海量文本抽取主题?》一文,其中有这么一段:

为了演示的流畅,我们这里忽略了许多细节。很多内容使用的是预置默认参数,而且完全忽略了中文停用词设置环节,因此“这个”、“如果”、“可能”、“就是”这样的停用词才会大摇大摆地出现在结果中。不过没有关系,完成比完美重要得多。知道了问题所在,后面改进起来很容易。 有机会我会写文章介绍如何加入中文停用词的去除环节。

根据“自己挖坑自己填”的法则,我决定把这一部分写出来。

我可以使用偷懒的办法。

例如在原先的教程里,更新中文停用词处理部分,打个补丁。

但是,最近我发现,好像至今为止,我们的教程从来没有介绍过如何用机器学习做情感分析。

你可能说,不对吧?

情感分析不是讲过了吗?老师你好像讲过《 如何用Python做情感分析?》,《 如何用Python做舆情时间序列可视化?》和《 如何用Python和R对《权力的游戏》故事情节做情绪分析?》。

你记得真清楚,提出表扬。

但是请注意,之前这几篇文章中,并没有使用机器学习方法。我们只不过调用了第三方提供的文本情感分析工具而已。

但是问题来了,这些第三方工具是在别的数据集上面训练出来的,未必适合你的应用场景。

例如有些情感分析工具更适合分析新闻,有的更善于处理微博数据……你拿过来,却是要对店铺评论信息做分析。

这就如同你自己笔记本电脑里的网页浏览器,和图书馆电子阅览室的网页浏览器,可能类型、版本完全一样。但是你用起自己的浏览器,就是比公用电脑上的舒服、高效——因为你已经根据偏好,对自己浏览器上的“书签”、“密码存储”、“稍后阅读”都做了个性化设置。

咱们这篇文章,就给你讲讲如何利用Python和机器学习,自己训练模型,对中文评论数据做情感分类。

# 数据

我的一个学生,利用爬虫抓取了大众点评网站上的数万条餐厅评论数据。

这些数据在爬取时,包含了丰富的元数据类型。

我从中抽取了评论文本和评星(1-5星),用于本文的演示。

从这些数据里,我们随机筛选评星为1,2,4,5的,各500条评论数据。一共2000条。

为什么只甩下评星数量为3的没有选择?

你先思考10秒钟,然后往下看,核对答案。

答案是这样的:

因为我们只希望对情感做出(正和负)二元分类,4和5星可以看作正向情感,1和2是负向情感……3怎么算?

所以,为了避免这种边界不清晰造成的混淆,咱们只好把标为3星的内容丢弃掉了。

整理好之后的评论数据,如下图所示。

如何用Python和机器学习训练中文文本情感分类模型?

image

我已经把数据放到了演示文件夹压缩包里面。后文会给你提供下载路径。

模型

使用机器学习的时候,你会遇到模型的选择问题。

例如,许多模型都可以用来处理分类问题。逻辑回归、决策树、SVM、朴素贝叶斯……具体到咱们的评论信息情感分类问题,该用哪一种呢?

幸好,Python上的机器学习工具包 scikit-learn 不仅给我们提供了方便的接口,供我们调用,而且还非常贴心地帮我们做了小抄(cheat-sheet)。

如何用Python和机器学习训练中文文本情感分类模型?

image

这张图看似密密麻麻,非常混乱,实际上是一个非常好的迷宫指南。其中绿色的方框,是各种机器学习模型。而蓝色的圆圈,是你做判断的地方。

你看,咱们要处理类别问题,对吧?

顺着往下看,会要求你判断数据是否有标记。我们有啊。

继续往下走,数据小于100K吗?

考虑一下,我们的数据有2000条,小于这个阈值。

接下来问是不是文本数据?是啊。

于是路径到了终点。

Scikit-learn告诉我们:用朴素贝叶斯模型好了。

小抄都做得如此照顾用户需求,你对scikit-learn的品质应该有个预期了吧?如果你需要使用经典机器学习模型(你可以理解成深度学习之外的所有模型),我推荐你先尝试scikit-learn 。

向量化

如何用Python从海量文本抽取主题?》一文里,我们讲过自然语言处理时的向量化。

忘了?

没关系。

子曰:

学而时习之,不亦乐乎?

这里咱们复习一下。

对自然语言文本做向量化(vectorization)的主要原因,是计算机 看不懂自然语言。

计算机,顾名思义,就是用来算数的。文本对于它(至少到今天)没有真正的意义。

但是自然语言的处理,是一个重要问题,也需要自动化的支持。因此人就得想办法,让机器能尽量理解和表示人类的语言。

假如这里有两句话:

I love the game.

I hate the game.

那么我们就可以简单粗暴地抽取出以下特征(其实就是把所有的单词都罗列一遍):

  • I
  • love
  • hate
  • the
  • game

对每一句话,都分别计算特征出现个数。于是上面两句话就转换为以下表格:

如何用Python和机器学习训练中文文本情感分类模型?

image

按照句子为单位,从左到右读数字,第一句表示为[1, 1, 0, 1, 1],第二句就成了[1, 0, 1, 1, 1]。

这就叫向量化。

这个例子里面,特征的数量叫做维度。于是向量化之后的这两句话,都有5个维度。

你一定要记住,此时机器依然不能理解两句话的具体含义。但是它已经尽量在用一种有意义的方式来表达它们。

注意这里我们使用的,叫做“一袋子词”(bag of words)模型。

下面这张图(来自 https://goo.gl/2jJ9Kp),形象化表示出这个模型的含义。

如何用Python和机器学习训练中文文本情感分类模型?

image

一袋子词模型不考虑词语的出现顺序,也不考虑词语和前后词语之间的连接。每个词都被当作一个独立的特征来看待。

你可能会问:“这样不是很不精确吗?充分考虑顺序和上下文联系,不是更好吗?”

没错,你对文本的顺序、结构考虑得越周全,模型可以获得的信息就越多。

但是,凡事都有成本。只需要用基础的排列组合知识,你就能计算出独立考虑单词,和考虑连续n个词语(称作 n-gram),造成的模型维度差异了。

为了简单起见,咱们这里还是先用一袋子词吧。有空我再给你讲讲……

打住,不能再挖坑了。

中文

上一节咱们介绍的,是自然语言向量化处理的通则。

处理中文的时候,要更加麻烦一些。

因为不同于英文、法文等拉丁语系文字,中文天然 没有空格作为词语之间的分割符号。

我们要先将中文分割成空格连接的词语。

例如把:

“我喜欢这个游戏”

变成:

“我 喜欢 这个 游戏”

这样一来,就可以仿照英文句子的向量化,来做中文的向量化了。

你可能担心计算机处理起中文的词语,跟处理英文词语有所不同。

这种担心没必要。

因为咱们前面讲过,计算机其实连英文单词也看不懂。

在它眼里,不论什么自然语言的词汇,都只是某种特定组合的字符串而已。
不论处理中文还是英文,都需要处理的一种词汇,叫做停用词。

中文维基百科里,是这么定义停用词的:

在信息检索中,为节省存储空间和提高搜索效率,在处理自然语言数据(或文本)之前或之后会自动过滤掉某些字或词,这些字或词即被称为Stop Words(停用词)。

咱们做的,不是信息检索,而已文本分类。

对咱们来说,你不打算拿它做特征的单词,就可以当作停用词。

还是举刚才英文的例子,下面两句话:

I love the game.

I hate the game.

告诉我,哪些是停用词?

直觉会告诉你,定冠词 the 应该是。

没错,它是虚词,没有什么特殊意义。

它在哪儿出现,都是一个意思。

一段文字里,出现很多次定冠词都很正常。把它和那些包含信息更丰富的词汇(例如love, hate)放在一起统计,就容易干扰我们把握文本的特征。

所以,咱们把它当作停用词,从特征里面剔除出去。

举一反三,你会发现分词后的中文语句:

“我 喜欢 这个 游戏”

其中的“这个”应该也是停用词吧?

答对了!

要处理停用词,怎么办呢?当然你可以一个个手工来寻找,但是那显然效率太低。

有的机构或者团队处理过许多停用词。他们会发现,某种语言里,停用词是有规律的。

他们把常见的停用词总结出来,汇集成表格。以后只需要查表格,做处理,就可以利用先前的经验和知识,提升效率,节约时间。

在scikit-learn中,英语停用词是自带的。只需要指定语言为英文,机器会帮助你自动处理它们。

但是中文……

scikit-learn开发团队里,大概缺少足够多的中文使用者吧。

好消息是,你可以使用第三方共享的停用词表。

这种停用词表到哪里下载呢?

我已经帮你找到了 一个 github 项目,里面包含了4种停用词表,来自哈工大、四川大学和百度等自然语言处理方面的权威单位。

如何用Python和机器学习训练中文文本情感分类模型?

image

这几个停用词表文件长度不同,内容也差异很大。为了演示的方便与一致性,咱们统一先用哈工大这个停用词表吧。

如何用Python和机器学习训练中文文本情感分类模型?

image

我已经将其一并存储到了演示目录压缩包中,供你下载。
# 环境

请你先到 这个网址下载本教程配套的压缩包。

下载后解压,你会在生成的目录里面看到以下4个文件。

如何用Python和机器学习训练中文文本情感分类模型?

image

下文中,我们会把这个目录称为“演示目录”。

请一定注意记好它的位置哦。

要装Python,最简便办法是安装Anaconda套装。

请到 这个网址下载Anaconda的最新版本。

如何用Python和机器学习训练中文文本情感分类模型?

image

请选择左侧的 Python 3.6版本下载安装。

如果你需要具体的步骤指导,或者想知道Windows平台如何安装并运行Anaconda命令,请参考我为你准备的 视频教程

打开终端,用cd命令进入 演示目录。如果你不了解具体使用方法,也可以参考 视频教程
我们需要使用许多软件包。如果每一个都手动安装,会非常麻烦。

我帮你做了个虚拟环境的配置文件,叫做environment.yaml ,也放在演示目录中。

请你首先执行以下命令:

conda env create -f environment.yaml

这样,所需的软件包就一次性安装完毕了。

之后执行,

source activate datapy3

进入这个虚拟环境。

注意一定要执行下面这句:

python -m ipykernel install –user –name=datapy3

只有这样,当前的Python环境才会作为核心(kernel)在系统中注册。
确认你的电脑上已经安装了 Google Chrome 浏览器。如果没有安装请到这里 下载安装。

之后,在演示目录中,我们执行:

jupyter notebook

Google Chrome会开启,并启动 Jupyter 笔记本界面:

如何用Python和机器学习训练中文文本情感分类模型?

image

你可以直接点击文件列表中的demo.ipynb文件,可以看到本教程的全部示例代码。

如何用Python和机器学习训练中文文本情感分类模型?

image

你可以一边看教程的讲解,一边依次执行这些代码。

但是,我 建议的方法,是回到主界面下,新建一个新的空白 Python 3 (显示名称为datapy3的那个)笔记本。

如何用Python和机器学习训练中文文本情感分类模型?

image

请跟着教程,一个个字符输入相应的内容。这可以帮助你更为深刻地理解代码的含义,更高效地把技能内化。

如何用Python和机器学习训练中文文本情感分类模型?

image

准备工作结束,下面我们开始正式输入代码。

代码

我们读入数据框处理工具pandas。

import pandas as pd 

利用pandas的csv读取功能,把数据读入。

注意为了与Excel和系统环境设置的兼容性,该csv数据文件采用的编码为GB18030。这里需要显式指定,否则会报错。

df = pd.read_csv('data.csv', encoding='gb18030') 

我们看看读入是否正确。

df.head() 

前5行内容如下:

如何用Python和机器学习训练中文文本情感分类模型?

image

看看数据框整体的形状是怎么样的:

df.shape 
(2000, 2) 

我们的数据一共2000行,2列。完整读入。

我们并不准备把情感分析的结果分成4个类别。我们只打算分成正向和负向。

这里我们用一个无名函数来把评星数量>3的,当成正向情感,取值为1;反之视作负向情感,取值为0。

def make_label(df):     df["sentiment"] = df["star"].apply(lambda x: 1 if x>3 else 0) 

编制好函数之后,我们实际运行在数据框上面。

make_label(df) 

看看结果:

df.head() 
如何用Python和机器学习训练中文文本情感分类模型?

image

从前5行看来,情感取值就是根据我们设定的规则,从评星数量转化而来。

下面我们把特征和标签拆开。

X = df[['comment']] y = df.sentiment 

X 是我们的全部特征。因为我们只用文本判断情感,所以X实际上只有1列。

X.shape 
(2000, 1) 

而y是对应的标记数据。它也是只有1列。

y.shape 
(2000,) 

我们来看看 X 的前几行数据。

X.head() 
如何用Python和机器学习训练中文文本情感分类模型?

image

注意这里评论数据还是原始信息。词语没有进行拆分。

为了做特征向量化,下面我们利用结巴分词工具来拆分句子为词语。

import jieba 

我们建立一个辅助函数,把结巴分词的结果用空格连接。

这样分词后的结果就如同一个英文句子一样,单次之间依靠空格分割。

def chinese_word_cut(mytext):     return " ".join(jieba.cut(mytext)) 

有了这个函数,我们就可以使用 apply 命令,把每一行的评论数据都进行分词。

X['cutted_comment'] = X.comment.apply(chinese_word_cut) 

我们看看分词后的效果:

X.cutted_comment[:5] 
如何用Python和机器学习训练中文文本情感分类模型?

image

单词和标点之间都用空格分割,符合我们的要求。

下面就是机器学习的常规步骤了:我们需要把数据分成训练集和测试集。

为什么要拆分数据集合?

在《 贷还是不贷:如何用Python和机器学习帮你决策?》一文中,我已解释过,这里复习一下:

如果期末考试之前,老师给你一套试题和答案,你把它背了下来。然后考试的时候,只是从那套试题里面抽取一部分考。你凭借超人的记忆力获得了100分。请问你学会了这门课的知识了吗?不知道如果给你新的题目,你会不会做呢?答案还是不知道。所以考试题目需要和复习题目有区别。

同样的道理,假设咱们的模型只在某个数据集上训练,准确度非常高,但是从来没有见过其他新数据,那么它面对新数据表现如何呢?

你心里也没底吧?

所以我们需要把数据集拆开,只在训练集上训练。保留测试集先不用,作为考试题,看模型经过训练后的分类效果。

from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1) 

这里,我们设定了 random_state取值,这是为了在不同环境中,保证随机数取值一致,以便验证咱们模型的实际效果。

我们看看此时的 X_train数据集形状。

X_train.shape 
(1500, 2) 

可见,在默认模式下, train_test_split函数对训练集和测试集的划分比例为 3:1。

我们检验一下其他3个集合看看:

y_train.shape 
(1500,) 
X_test.shape 
(500, 2) 
y_test.shape 
(500,) 

同样都正确无误。

下面我们就要处理中文停用词了。

我们编写一个函数,从中文停用词表里面,把停用词作为列表格式保存并返回:

def get_custom_stopwords(stop_words_file):     with open(stop_words_file) as f:         stopwords = f.read()     stopwords_list = stopwords.split('/n')     custom_stopwords_list = [i for i in stopwords_list]     return custom_stopwords_list 

我们指定使用的停用词表,为我们已经下载保存好的哈工大停用词表文件。

stop_words_file = "stopwordsHIT.txt" stopwords = get_custom_stopwords(stop_words_file) 

看看我们的停用词列表的后10项:

stopwords[-10:] 
如何用Python和机器学习训练中文文本情感分类模型?

image

这些大部分都是语气助词,作为停用词去除掉,不会影响到语句的实质含义。

下面我们就要尝试对分词后的中文语句做向量化了。

我们读入 CountVectorizer向量化工具,它依据词语出现频率转化向量。

from sklearn.feature_extraction.text import CountVectorizer 

我们建立一个 CountVectorizer()的实例,起名叫做vect。

注意这里为了说明停用词的作用。我们先使用默认参数建立vect。

vect = CountVectorizer() 

然后我们用向量化工具转换已经分词的训练集语句,并且将其转化为一个数据框,起名为 term_matrix

term_matrix = pd.DataFrame(vect.fit_transform(X_train.cutted_comment).toarray(), columns=vect.get_feature_names()) 

我们看看 term_matrix的前5行:

term_matrix.head() 
如何用Python和机器学习训练中文文本情感分类模型?

image

我们注意到,特征词语五花八门,特别是很多数字都被当作特征放在了这里。

term_matrix的形状如下:

term_matrix.shape 
(1500, 7305) 

行数没错,列数就是特征个数,有7305个。

下面我们测试一下,加上停用词去除功能,特征向量的转化结果会有什么变化。

vect = CountVectorizer(stop_words=frozenset(stopwords)) 

下面的语句跟刚才一样:

term_matrix = pd.DataFrame(vect.fit_transform(X_train.cutted_comment).toarray(), columns=vect.get_feature_names()) 
term_matrix.head() 
如何用Python和机器学习训练中文文本情感分类模型?

image

可以看到,此时特征个数从刚才的7305个,降低为7144个。我们没有调整任何其他的参数,因此减少的161个特征,就是出现在停用词表中的单词。

但是,这种停用词表的写法,依然会漏掉不少漏网之鱼。

首先就是前面那一堆显眼的数字。它们在此处作为特征毫无道理。如果没有单位,没有上下文,数字都是没有意义的。

因此我们需要设定,数字不能作为特征。

在Python里面,我们可以设定 token_pattern来完成这个目标。

这一部分需要用到正则表达式的知识,我们这里无法详细展开了。

但如果你只是需要去掉数字作为特征的话,按照我这样写,就可以了。

另一个问题在于,我们看到这个矩阵,实际上是个非常稀疏的矩阵,其中大部分的取值都是0.

这没有关系,也很正常。

毕竟大部分评论语句当中只有几个到几十个词语而已。7000多的特征,单个语句显然是覆盖不过来的。

然而,有些词汇作为特征,就值得注意了。

首先是那些过于普遍的词汇。尽管我们用了停用词表,但是难免有些词汇几乎出现在每一句评论里。什么叫做特征?特征就是可以把一个事物与其他事物区别开的属性。

假设让你描述今天见到的印象最深刻的人。你怎么描述?

我看见他穿着小丑的衣服,在繁华的商业街踩高跷,一边走还一边抛球,和路人打招呼。

还是……

我看见他有两只眼睛,一只鼻子。

后者绝对不算是好的特征描述,因为难以把你要描述的个体区分出来。

物极必反,那些过于特殊的词汇,其实也不应该保留。因为你了解了这个特征之后,对你的模型处理新的语句情感判断,几乎都用不上。

这就如同你跟着神仙学了屠龙之术,然而之后一辈子也没有见过龙……

所以,如下面两个代码段所示,我们一共多设置了3层特征词汇过滤。

max_df = 0.8 # 在超过这一比例的文档中出现的关键词(过于平凡),去除掉。 min_df = 3 # 在低于这一数量的文档中出现的关键词(过于独特),去除掉。 
vect = CountVectorizer(max_df = max_df,                        min_df = min_df,                        token_pattern=u'(?u)//b[^//d//W]//w+//b',                        stop_words=frozenset(stopwords)) 

这时候,再运行我们之前的语句,看看效果。

term_matrix = pd.DataFrame(vect.fit_transform(X_train.cutted_comment).toarray(), columns=vect.get_feature_names()) 
term_matrix.head() 
如何用Python和机器学习训练中文文本情感分类模型?

image

可以看到,那些数字全都不见了。特征数量从单一词表法去除停用词之后的7144个,变成了1864个。

你可能会觉得,太可惜了吧?好容易分出来的词,就这么扔了?

要知道,特征多,绝不一定是好事儿。

尤其是噪声大量混入时,会显著影响你模型的效能。

好了,评论数据训练集已经特征向量化了。下面我们要利用生成的特征矩阵来训练模型了。

我们的分类模型,采用朴素贝叶斯(Multinomial naive bayes)。

from sklearn.naive_bayes import MultinomialNB nb = MultinomialNB() 

注意我们的数据处理流程是这样的:

  1. 特征向量化;
  2. 朴素贝叶斯分类。

如果每次修改一个参数,或者换用测试集,我们都需要重新运行这么多的函数,肯定是一件效率不高,且令人头疼的事儿。而且只要一复杂,出现错误的几率就会增加。

幸好,Scikit-learn给我们提供了一个功能,叫做管道(pipeline),可以方便解决这个问题。

它可以帮助我们,把这些顺序工作连接起来,隐藏其中的功能顺序关联,从外部一次调用,就能完成顺序定义的全部工作。

使用很简单,我们就把 vect 和 nb 串联起来,叫做pipe。

from sklearn.pipeline import make_pipeline pipe = make_pipeline(vect, nb) 

看看它都包含什么步骤:

pipe.steps 
如何用Python和机器学习训练中文文本情感分类模型?

image

看,我们刚才做的工作,都在管道里面了。我们可以把管道当成一个整体模型来调用。

下面一行语句,就可以把未经特征向量化的训练集内容输入,做交叉验证,算出模型分类准确率的均值。

from sklearn.cross_validation import cross_val_score cross_val_score(pipe, X_train.cutted_comment, y_train, cv=5, scoring='accuracy').mean() 

咱们的模型在训练中的准确率如何呢?

0.820687244673089 

这个结果,还是不错的。

回忆一下,总体的正向和负向情感,各占了数据集的一半。

如果我们建立一个“笨模型”(dummy model),即所有的评论,都当成正向(或者负向)情感,准确率多少?

对,50%。

目前的模型准确率,远远超出这个数值。超出的这30%多,其实就是评论信息为模型带来的确定性。

但是,不要忘了,我们不能光拿训练集来说事儿,对吧?下面咱们给模型来个考试。

我们用训练集,把模型拟合出来。

pipe.fit(X_train.cutted_comment, y_train) 

然后,我们在测试集上,对情感分类标记进行预测。

pipe.predict(X_test.cutted_comment) 
如何用Python和机器学习训练中文文本情感分类模型?

image

这一大串0和1,你看得是否眼花缭乱?

没关系,scikit-learn给我们提供了非常多的模型性能测度工具。

我们先把预测结果保存到 y_pred

y_pred = pipe.predict(X_test.cutted_comment) 

读入 scikit-learn 的测量工具集。

from sklearn import metrics 

我们先来看看测试准确率:

metrics.accuracy_score(y_test, y_pred) 
0.86 

这个结果是不是让你很吃惊?没错,模型面对没有见到的数据,居然有如此高的情感分类准确性。

对于分类问题,光看准确率有些不全面,咱们来看看混淆矩阵。

metrics.confusion_matrix(y_test, y_pred) 
array([[194,  43],        [ 27, 236]]) 

混淆矩阵中的4个数字,分别代表:

  • TP: 本来是正向,预测也是正向的;
  • FP: 本来是负向,预测却是正向的;
  • FN: 本来是正向,预测却是负向的;
  • TN: 本来是负向,预测也是负向的。

下面这张图(来自 https://goo.gl/5cYGZd)应该能让你更为清晰理解混淆矩阵的含义:

如何用Python和机器学习训练中文文本情感分类模型?

image

写到这儿,你大概能明白咱们模型的性能了。

但是总不能只把咱们训练出的模型和无脑“笨模型”去对比吧?这也太不公平了!

下面,我们把老朋友 SnowNLP 呼唤出来,做个对比。

如果你把它给忘了,请复习《 如何用Python做情感分析?

from snownlp import SnowNLP def get_sentiment(text):     return SnowNLP(text).sentiments 

我们利用测试集评论原始数据,让 SnowNLP 跑一遍,获得结果。

y_pred_snownlp = X_test.comment.apply(get_sentiment) 

注意这里有个小问题。 SnowNLP 生成的结果,不是0和1,而是0到1之间的小数。所以我们需要做一步转换,把0.5以上的结果当作正向,其余当作负向。

y_pred_snownlp_normalized = y_pred_snownlp.apply(lambda x: 1 if x>0.5 else 0) 

看看转换后的前5条 SnowNLP 预测结果:

y_pred_snownlp_normalized[:5] 
如何用Python和机器学习训练中文文本情感分类模型?

image

好了,符合我们的要求。

下面我们先看模型分类准确率:

metrics.accuracy_score(y_test, y_pred_snownlp_normalized) 
0.77 

与之对比,咱们的测试集分类准确率,可是0.86哦。

我们再来看看混淆矩阵。

metrics.confusion_matrix(y_test, y_pred_snownlp_normalized) 
array([[189,  48],        [ 67, 196]]) 

对比的结果,是 TP 和 TN 两项上,咱们的模型判断正确数量,都要超出 SnowNLP。

小结

回顾一下,本文介绍了以下知识点:

  1. 如何用一袋子词(bag of words)模型将自然语言语句向量化,形成特征矩阵;
  2. 如何利用停用词表、词频阈值和标记模式(token pattern)移除不想干的伪特征词汇,降低模型复杂度。
  3. 如何选用合适的机器学习分类模型,对词语特征矩阵做出分类;
  4. 如何用管道模式,归并和简化机器学习步骤流程;
  5. 如何选择合适的性能测度工具,对模型的效能进行评估和对比。

希望这些内容能够帮助你更高效地处理中文文本情感分类工作。

讨论

你之前用机器学习做过中文情感分类项目吗?你是如何去除停用词的?你使用的分类模型是哪个?获得的准确率怎么样?欢迎留言,把你的经验和思考分享给大家,我们一起交流讨论。

如果你对我的文章感兴趣,欢迎点赞,并且微信关注和置顶我的公众号“玉树芝兰”(nkwangshuyi)。

如果本文可能对你身边的亲友有帮助,也欢迎你把本文通过微博或朋友圈分享给他们。让他们一起参与到我们的讨论中来。

延伸阅读

如何用《玉树芝兰》入门数据科学?

数据科学相关文章合集(玉树芝兰)

如何降低90%Java垃圾回收时间?以阿里HBase的GC优化实践为例

$
0
0

      过去的一年里,我们准备在Ali-HBase上突破这个被普遍认知的痛点,为此进行了深度分析及全面创新的工作,获得了一些比较好的效果。以蚂蚁风控场景为例,HBase的线上young GC时间从120ms减少到15ms,结合阿里巴巴JDK团队提供的利器——AliGC,进一步在实验室压测环境做到了5ms。本文主要介绍我们过去在这方面的一些工作和技术思想。

   背景

      JVM的GC机制对开发者屏蔽了内存管理的细节,提高了开发效率。说起GC,很多人的第一反应可能是JVM长时间停顿或者FGC导致进程卡死不可服务的情况。但就HBase这样的大数据存储服务而言,JVM带来的GC挑战相当复杂和艰难。原因有三:

    1、内存规模巨大。线上HBase进程多数为96G大堆,今年新机型已经上线部分160G以上的堆配置

    2、对象状态复杂。HBase服务器内部会维护大量的读写cache,达到数十GB的规模。HBase以表格的形式提供有序的服务数据,数据以一定的结构组织起来,这些数据结构产生了过亿级别的对象和引用

    3、young GC频率高。访问压力越大,young区的内存消耗越快,部分繁忙的集群可以达到每秒1~2次youngGC, 大的young区可以减少GC频率,但是会带来更大的young GC停顿,损害业务的实时性需求。

 

  思路

 

      1. HBase作为一个存储系统,使用了大量的内存作为写buffer和读cache,比如96G的大堆(4G young + 92G old)下,写buffer+读cache会占用70%以上的内存(约70G),本身堆内的内存水位会控制在85%,而剩余的占用内存就只有在10G以内了。所以,如果我们能在应用层面 自管理好这70G+的 内存,那么对于JVM而言,百G大堆的GC压力就会等价于10G小堆的GC压力,并且未来面对更大的堆也不会恶化膨胀。 在这个解决思路下,我们线上的young GC时间获得了从120ms到15ms的优化效果。
      2. 在一个高吞吐的数据密集型服务系统中,大量的临时对象被频繁创建与回收,如何能够针对性管理这些临时对象的分配与回收,AliJDK团队研发了一种新的基于租户的GC算法—AliGC。集团HBase基于这个新的AliGC算法进行改造,我们在实验室中压测的young GC时间从15ms减少到5ms,这是一个未曾期望的极致效果。


     下面将逐一介绍Ali-HBase版本GC优化所使用的关键技术。

      消灭一亿个对象:更快更省的CCSMap

     目前HBase使用的存储模型是LSMTree模型,写入的数据会在内存中暂存到一定规模后再dump到磁盘上形成文件。

      下面我们将其简称为写缓存。写缓存是可查询的,这就要求数据在内存中有序。为了提高并发读写效率,并达成数据有序且支持seek&scan的基本要求,SkipList是使用得比较广泛的数据结构。



 

我们以JDK自带的ConcurrentSkipListMap为例子进行分析,它有下面三个问题:

     1. 内部对象繁多。每存储一个元素,平均需要4个对象(index+node+key+value,平均层高为1)

     2. 新插入的对象在young区,老对象在old区。当不断插入元素时,内部的引用关系会频繁发生变化,无论是ParNew算法的CardTable标记,还是G1算法的RSet标记,都有可能触发old区扫描。

      3. 业务写入的KeyValue元素并不是规整长度的,当它晋升到old区时,可能产生大量的内存碎片。

问题1使得young区GC的对象扫描成本很高,young GC时晋升对象更多。问题2使得young GC时需要扫描的old区域会扩大。问题3使得内存碎片化导致的FGC概率升高。当写入的元素较小时,问题会变得更加严重。我们曾对线上的RegionServer进程进行统计,活跃Objects有1亿2千万之多!

 

      分析完当前young GC的最大敌人后,一个大胆的想法就产生了,既然写缓存的分配,访问,销毁,回收都是由我们来管理的,如果让JVM“看不到”写缓存,我们自己来管理写缓存的生命周期,GC问题自然也就迎刃而解了。

      说起让JVM“看不到”,可能很多人想到的是off-heap的解决方案,但是这对写缓存来说没那么简单,因为即使把KeyValue放到offheap,也无法避免问题1和问题2。而1和2也是young GC的最大困扰。

      问题现在被转化成了: 如何不使用JVM对象来构建一个有序的支持并发访问的Map。
      当然我们也不能接受性能损失,因为写入Map的速度和HBase的写吞吐息息相关。
需求再次强化: 如何不使用对象来构建一个有序的支持并发访问的Map,且不能有性能损失。

为了达成这个目标,我们设计了这样一个数据结构:

 

  • 它使用连续的内存(堆内or堆外),我们通过代码控制内部结构而不是依赖于JVM的对象机制
  • 在逻辑上也是一个SkipList,支持无锁的并发写入和查询
  • 控制指针和数据都存放在连续内存中



 

       上图所展示的即是CCSMap(CompactedConcurrentSkipListMap)的内存结构。 我们以大块的内存段(Chunk)的方式申请写缓存内存。每个Chunk包含多个Node,每个Node对应一个元素。新插入的元素永远放在已使用内存的末尾。Node内部复杂的结构,存放了Index/Next/Key/Value等维护信息和数据。新插入的元素需要拷贝到Node结构中。当HBase发生写缓存dump时,整个CCSMap的所有Chunk都会被回收。当元素被删除时,我们只是逻辑上把元素从链表里"踢走",不会把元素实际从内存中收回(当然做实际回收也是有方法,就HBase而言没有那个必要)。

       插入KeyValue数据时虽然多了一遍拷贝,但是就绝大多数情况而言,拷贝反而会更快。因为从CCSMap的结构来看,一个Map中的元素的控制节点和KeyValue在内存上是邻近的,利用CPU缓存的效率更高,seek会更快。对于SkipList来说,写速度其实是bound在seek速度上的,实际拷贝产生的overhead远不如seek的开销。根据我们的测试,CCSMap和JDK自带的ConcurrentSkipListMap相比,50Byte长度KV的测试中,读写吞吐提升了20~30%。

       由于没有了JVM对象,每个JVM对象至少占用16Byte空间也可以被节省掉(8byte为标记预留,8byte为类型指针)。还是以50Byte长度KeyValue为例,CCSMap和JDK自带的ConcurrentSkipListMap相比,内存占用减少了40%。

         CCSMap在生产中上线后,实际优化效果: young GC从120ms+减少到了30ms

 



 
优化前


 优化后

 

 

       使用了CCSMap后,原来的1亿2千万个存活对象被缩减到了千万级别以内,大大减轻了GC压力。由于紧致的内存排布, 写入吞吐能力也得到了30%的提升

       永不晋升的Cache:BucketCache

       HBase以Block的方式组织磁盘上的数据。一个典型的HBase Block大小在16K~64K之间。HBase内部会维护BlockCache来减少磁盘的I/O。BlockCache和写缓存一样,不符合GC算法理论里的分代假说,天生就是对GC算法不友好的 —— 既不稍纵即逝,也不永久存活。

一段Block数据从磁盘被load到JVM内存中,生命周期从分钟到月不等,绝大部分Block都会进入old区,只有Major GC时才会让它被JVM回收。它的麻烦主要体现在:

       1. HBase Block的大小不是固定的,且相对较大,内存容易碎片化

       2. 在ParNew算法上,晋升麻烦。 麻烦不是体现在拷贝代价上,而是因为尺寸较大,寻找合适的空间存放HBase Block的代价较高

       读缓存优化的思路则是,向JVM申请一块永不归还的内存作为BlockCache,我们自己对内存进行固定大小的分段,当Block加载到内存中时,我们将Block拷贝到分好段的区间内,并标记为已使用。当这个Block不被需要时,我们会标记该区间为可用,可以重新存放新的Block,这就是BucketCache。关于BucketCache中的内存空间分配与回收(这一块的设计与研发在多年前已完成),详细可以参考 : http://zjushch.iteye.com/blog/1751387

       很多基于堆外内存的RPC框架,也会自己管理堆外内存的分配和回收,一般通过显式释放的方式进行内存回收。但是对HBase来说,却有一些困难。我们将Block对象视为需要自管理的内存片段。Block可能被多个任务引用,要解决Block的回收问题,最简单的方式是将Block对每个任务copy到栈上(copy的block一般不会晋升到old区),转交给JVM管理就可以。

       实际上,我们之前一直使用的是这种方法,实现简单,JVM背书,安全可靠。但这是有损耗的内存管理方式,为了解决GC问题,引入了每次请求的拷贝代价。由于拷贝到栈上需要支付额外的cpu拷贝成本和young区内存分配成本,在cpu和总线越来越珍贵的今天,这个代价显得高昂。

于是我们转而考虑使用引用计数的方式管理内存,HBase上遇到的主要难点是:

 

  1. HBase内部会有多个任务引用同一个Block
  2.  同一个任务内可能有多个变量引用同一个Block。引用者可能是栈上临时变量,也可能是堆上对象域。
  3. Block上的处理逻辑相对复杂,Block会在多个函数和对象之间以参数、返回值、域赋值的方式传递。
  4. Block可能是受我们管理的,也可能是不受我们管理的(某些Block需要手动释放,某些不需要)。
  5. Block可能被转换为Block的子类型。

       这几点综合起来,对如何写出正确的代码是一个挑战。但在C++ 上,使用智能指针来管理对象生命周期是很自然的事情,为什么到了Java里会有困难呢?

      Java中变量的赋值,在用户代码的层面上,只会产生引用赋值的行为,而C++ 中的变量赋值可以利用对象的构造器和析构器来干很多事情,智能指针即基于此实现(当然C++的构造器和析构器使用不当也会引发很多问题,各有优劣,这里不讨论)

      于是我们参考了C++的智能指针,设计了一个Block引用管理和回收的框架ShrableHolder来抹平coding中各种if else的困难。它有以下的范式:

 

  1. ShrableHolder可以管理有引用计数的对象,也可以管理非引用计数的对象
  2. ShrableHolder在被重新赋值时,释放之前的对象。如果是受管理的对象,引用计数减1,如果不是,则无变化。
  3. ShrableHolder在任务结束或者代码段结束时,必须被调用reset
  4. ShrableHolder不可直接赋值。必须调用ShrableHolder提供的方法进行内容的传递
  5. 因为ShrableHolder不可直接赋值,需要传递包含生命周期语义的Block到函数中时,ShrableHolder不能作为函数的参数。

      根据这个范式写出来的代码,原来的代码逻辑改动很少,不会引入if else。虽然看上去仍然有一些复杂度,所幸的是,受此影响的区间还是局限于非常局部的下层,对HBase而言还是可以接受的。为了保险起见,避免内存泄漏,我们在这套框架里加入了探测机制,探测长时间不活动的引用,发现之后会强制标记为删除。

将BucketCache应用之后,减少了BlockCache的晋升开销,减少了young GC时间:

 



 
 (CCSMap+BucketCache优化后的效果)

     追求极致:AliGC

       经过以上两个大的优化之后,蚂蚁风控生产环境的young GC时间已经缩减到15ms。由于ParNew+CMS算法在这个尺度上再做优化已经很困难了,我们转而投向AliGC的怀抱。AliGC在G1算法的基础上做了深度改进,内存自管理的大堆HBase和AliGC产生了很好的化学反应。

AliGC是阿里巴巴JVM团队基于G1算法, 面向大堆 (LargeHeap) 应用场景,优化的GC算法的统称。这里主要介绍下多租户GC。

      多租户GC包含的三层核心逻辑: 1)在JavaHeap上,对象的分配按照租户隔离,不同的租户使用不同的Heap区域; 2)允许GC以更小的代价发生在租户粒度,而不仅仅是应用的全局; 3)允许上层应用根据业务需求对租户灵活映射。

      AliGC将内存Region划分为了多个租户,每个租户内独立触发GC。在个基础上,我们将内存分为普通租户和中等生命周期租户。中等生命周期对象指的是,既不稍纵即逝,也不永久存在的对象。由于经过以上两个大幅优化,现在堆中等生命周期对象数量和内存占用已经很少了。但是中等生命周期对象在生成时会被old区对象引用,每次young GC都需要扫描RSet,现在仍然是young GC的耗时大头。

借助于AJDK团队的ObjectTrace功能,我们找出中等生命周期对象中最"大头"的部分,将这些对象在生成时直接分配到中等生命周期租户的old区,避免RSet标记。而普通租户则以正常的方式进行内存分配。

普通租户GC频率很高,但是由于晋升的对象少,跨代引用少,Young区的GC时间得到了很好的控制。在实验室场景仿真环境中,我们将young GC优化到了5ms。



 

(AliGC优化后的效果,单位问题,此处为us)



 

  云端使用

 

 

      阿里HBase目前已经在阿里云提供商业化服务,任何有需求的用户都可以在阿里云端使用深入改进的、一站式的HBase服务。云HBase版本与自建HBase相比在运维、可靠性、性能、稳定性、安全、成本等方面均有很多的改进,更多内容欢迎大家关注HBase技术社区微信公众号。



 

 

 

 

 

 

 



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



项目管理-敏捷过程总结

$
0
0

1.敏捷开发模型:

敏捷思想,有效沟通、小步快跑、拥抱变化、不断改进。

敏捷项目角色:

产品负责人(Product Owner):主要负责确定产品的功能和达到要求的标准,指定软件的发布日期和交付的内容,同时有权力接受或拒绝开发团队的工作成果。
流程管理员(Scrum Master):主要负责整个Scrum流程在项目中的顺利实施和进行,以及清除挡在客户和开发工作之间的沟通障碍,使得客户可以直接驱动开发。
开发团队(Scrum Team):主要负责软件产品在Scrum规定流程下进行开发工作,人数控制在5~10人左右,每个成员可能负责不同的技术方面,但要求每成员必须要有很强的自我管理能力,同时具有一定的表达能力;成员可以采用任何工作方式,只要能达到Sprint的目标。



 

2.敏捷开发过程:

1.首先我们需要确认一个 PB ( Product Backlog , 即按优先顺序排列的一个产品需求列表) ,这是由 PO(Product Owner) 负责的

2.ST(Scrum Team) 会根据 PB 列表,进行工作量的预估和安排

3.有了 PB 列表,我们需要通过 Sprint Planning Meeting( Sprint 计划会议)来从中挑选出一个 Story 作为本次迭代完成的目标,这个目标的时间周期是1~4个星期,然后把这个Story进行细化,形成一个Sprint Backlog

4.Sprint Backlog 是由 ST 去完成的,每个成员根据Sprint Backlog再细化成更小的任务(细到每个任务的工作量在2天内能完成)

5.在Scrum Team完成计划会议上选出的Sprint Backlog过程中,需要进行 Daily Scrum Meeting(每日站立会议),每次会议控制在15分钟左右,每个人都必须发言,并且要向所有成员当面汇报你昨天完成了什么,并且向所有成员承诺你今天要完成什么,同时遇到不能解决的问题也可以提出,每个人回答完成后,要走到黑板前更新自己的 Sprint burn down(Sprint燃尽图)

6.做到每日集成,也就是每天都要有一个可以成功编译、并且可以演示的版本;很多人可能还没有用过自动化的每日集成,其实TFS就有这个功能,它可以支持每次有成员进行签入操作的时候,在服务器上自动获取最新版本,然后在服务器中编译,如果通过则马上再执行单元测试代码,如果也全部通过,则将该版本发布,这时一次正式的签入操作才保存到TFS中,中间有任何失败,都会用邮件通知项目管理人员

7.当一个Story完成,也就是Sprint Backlog被完成,也就表示一次Sprint完成,这时,我们要进行 Srpint Review Meeting(演示会议),也称为评审会议,产品负责人和客户都要参加(最好本公司老板也参加),每一个Scrum Team的成员都要向他们演示自己完成的软件产品(这个会议非常重要,一定不能取消)

8.最后就是 Sprint Retrospective Meeting(回顾会议),也称为总结会议,以轮流发言方式进行,每个人都要发言,总结并讨论改进的地方,放入下一轮Sprint的产品需求中。

3.敏捷过程总结:

  1. Sprint 第一天,需要将目标定义清楚,并让团队所有人都知道「确保建立一致的目标并使之明确」;
  2. 若出现需求变更,则优先排到下次迭代,特殊情况需特殊处理「确保本次迭代可以按时完工」;
  3. Scrum Master 将迭代中的需求分解为任务,每个任务只能有一个任务负责人,且不超过一个人天「确保每日任务可评估」;
  4. 让 Product Owner 直接与相关开发人员确定需求,Scrum Master 需一同参与「确保需求与实现不会发生偏差」;
  5. 每日定时站会,时长不超过 15 分钟,规模不要太大「确保任务完成情况与计划保持一致」;
  6. 每日进行一次代码评审,由 Scrum Master 负责,并在次日将评审结果通知给相关开发人员「确保代码质量不要下降」;
  7. 各个团队的 Scrum Master 保持每日沟通一次,时间不要超过 15 分钟「确保项目管理不会出现风险」;
  8. 每次迭代结束,让大家稍微放松一下,可提供一些团队活动,比如聚餐「确保团队能够更加凝聚」;
  9. Scrum Master 需要给团队一些承诺,比如项目奖金或特殊福利等「确保团队更加有激情」;
  10. 对于情绪异常的员工,Scrum Master 需及时与其沟通「确保不要让一个人的情绪影响整个团队」;

此外,作为项目管理者,需要不断在团队中加强以下 5 点文化:

  1. 方向一致
  2. 当面沟通
  3. 全情投入
  4. 充分信任
  5. 说到做到

 



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐




丁磊两会提案:促进中小学精品在线开放课程平台建设

$
0
0

3月3日,全国政协十三届一次会议正式开幕。作为新当选的全国政协委员,网易公司董事局主席兼首席执行官丁磊履职首年向全国两会提交了多份提案,重点聚焦在两个话题:

一是推进信息的精品化建设,围绕教育、文化、网络内容改善等领域提出具体建议,包括建设中小学精品教育、在线开放课程、精品图书数字化、青少年健康上网等;二是关注民生问题的改革,围绕个税综合计征、慢性病防控、食品安全、“互联网+农业”精准扶贫、老年人便捷出行等。

其中,教育相关问题是丁磊最为重点关注的内容之一,在提案中被多次提及;而网易打造的有道精品课、网易公开课、网易云课堂等多款有口皆碑的在线教育产品,也成为了践行提案中“建设中小学精品教育、在线开放课程”的最好体现。

丁磊-官宣照

丁磊:互联网会解决传统教育所遇到的问题

之所以重点关注教育问题,是因为丁磊自己也遭遇过传统教育问题所带来的困扰。

“我大女儿读书时,为了学区房,我租了5年的房子住。”在一场小范围“两会”媒体沟通会上,丁磊提到了自己的经历。

丁磊还坦言,目前的现状是优质教育资源集中大城市,甚至是大城市的少数学校。而未来,应该依靠互联网、依靠科技的力量,可以让孩子不用学区房也能接受高质量教育、让三四线城市的孩子接受到一线城市的优质教育。

因此,针对国内中小学精品在线开放课程发展不平衡、不充分的问题,丁磊在《关于加快义务教育信息化改革,深化精品在线开放课程平台建设的提案》中提议:促进中小学精品在线开放课程平台建设,实现教育资源平台共享;重视STEAM教育资源在中小学精品在线开放课程平台的应用;继续加大对基础设施落后地区的支持;引导学校、教师观念升级,完善课程评价机制。

丁磊还强调:“现在的教育模式还很传统,应该有更多的互动和创新”,“因此应该在教育科技方面多研究、多投入,包括用游戏的方法去引导儿童教育,利用互联网开展线上精品教育课程手段等。”

在线教育蓬勃发展 优化教育资源分配

实际上,教育问题是全社会关心的大事,是提升全民素质最为关键的路径。在今年的政府工作报告上,总理说:“发展公平而有质量的教育。”“教育公平”也连续四年成为政府工作报告中“教育主要任务”。

然而,我国由于区域经济发展不均、城市和农村教育资源分配不均等种种客观因素的影响,三四线及广大农村的孩子,依然不能享受到同等优质的教育。

但随着互联网及科技的发展,在线教育正如火如荼的发展,正如丁磊所说“从技术上来讲,让三四五线的孩子接受到大城市一流的教育已经可行。”

来自CNNIC的一份数据报告显示,在线教育课程成为中国国民手机APP 用户增长率第二,仅次于网上外卖,甚至高于游戏。

包括网易在内的不少互联网公司,都已经布局在线教育,大力发展网络课程,这让更多的三四线城市的孩子们,只要通过一部手机、一台电脑就可以快速、高效、便捷地享受到和一线大城市的孩子们同等优质的师资和课程。

而其中,以“匠心精神”著称的网易,打造出了有道精品课这样的优质在线教育产品,受到众多学生的追捧和喜爱。

网易匠心 打造精品化网络课程

虽然今年是丁磊首次作为全国政协委员,并提出建设中小学精品教育、发展在线开放课程等内容的相关提案,但网易进入在线教育领域并不晚,尤其是在丁磊重点关注的青少年和中小学教育。

2014年有道精品课推出,为用户提供小学/初中/高中、四六级、考研、外语等精品课程。有道精品课的推出,正是今年丁磊在提案中 “促进中小学的精品在线开放课程平台的建设”的践行。

在线教育要做精品,不仅是“网易匠心”使然,更是行业和社会的极大需求。

目前,市面上做在线教育、提供网络内容的产品繁多,但同时也面临着鱼龙混杂、内容良莠不齐。尤其是在青少年和中小学领域,由于大部分未成年人对网络内容辨别能力有限、自控能力不高,因此,精品化的高质量课程就显得尤为重要。

以重点关注关注青少年和中小学在线教育的有道精品课为例,在2016年推出了的“同道计划”,目的是为了精选业内最顶尖的老师进行合作,从而保证课程的高质量。

例如,通过“同道计划“精选出来的高中老师,组成了“有道高中牛师团”,这是在高中学生群体中有相当号召力的一个团体,他们针对语文、数学、英语、物理等高中学科,认真研发有针对性、高品质的课程,每节课程都历时多个月的打磨,力求精品;老师们寓教于乐的教学方式,不仅能够带来学生们学习到课程重点,不少学生因此高考分数大幅提升,考上了理想的大学,还能帮助他们在网络上结交良师益友,树立正确的人生观、价值观。

实际上,除了“有道高中牛师团”外,秉承“精品”策略,有道精品课还孵化出了“有道四六级””有道考研““逻辑英语”等多个有口皆碑的教育产品,深受用户的喜欢。

而关于丁磊在提案中表示的“重视STEAM教育资源在中小学精品在线开放课程平台的应用”,有道精品课也早已做了不少探索。

例如,有道精品课专门开设“AI创客“等系列课程,能够帮助青少年快速学习编程、人工智能等领域的知识,从小培养良好的科学和技术基础,更好的适应未来科技社会。

据悉,有道精品课用户有超过六成来自三四线城市,初高中相关课程的比例甚至更高。通过技术手段,如有道精品课这样的在线教育产品,打破了传统教育资源分配不均的问题,让最优质的教育资源不受时间和地点的限制,最大范围的触及到更多的学生,尤其是三四线及广大农村,更好地助力我国教育事业的均衡发展。

大规模机器学习框架的四重境界

$
0
0

文章为转载,原文链接见 这里,作者是 carbon zhang。这篇文章主要介绍了分布式机器学习中的若干重点概念和经典论文,包括数据并行和模型并行、分布式框架的流派、参数服务器以及同步协议的演进等,非常值得一看。

背景

自从google发表著名的 GFS、MapReduce、BigTable 三篇paper以后,互联网正式迎来了大数据时代。大数据的显著特点是大,哪里都大的大。本篇主要针对volume大的数据时,使用机器学习来进行数据处理过程中遇到的架构方面的问题做一个系统的梳理。

有了GFS我们有能力积累海量的数据样本,比如在线广告的曝光和点击数据,天然具有正负样本的特性,累积一两个月往往就能轻松获得百亿、千亿级的训练样本。这样海量的样本如何存储?用什么样的模型可以学习海量样本中有用的pattern?这些问题不止是工程问题,也值得每个做算法的同学去深入思考。

简单模型or复杂模型

在深度学习概念提出之前,算法工程师手头能用的工具其实并不多,就LR、SVM、感知机等寥寥可数、相对固定的若干个模型和算法;那时候要解决一个实际的问题,算法工程师更多的工作主要是在 特征工程方面。而特征工程本身并没有很系统化的指导理论(至少目前没有看到系统介绍特征工程的书籍),所以很多时候特征的构造技法显得光怪陆离,是否有用也取决于问题本身、数据样本、模型以及 运气

在特征工程作为算法工程师主要工作内容的时候,构造新特征的尝试往往很大部分都不能在实际工作中work。据我了解,国内几家大公司在特征构造方面的成功率在后期一般不会超过20%。也就是80%的新构造特征往往并没什么正向提升效果。如果给这种方式起一个名字的话,大概是 简单模型+复杂特征;简单模型说的是算法比如LR、SVM本身并不服务,参数和表达能力基本呈现一种线性关系,易于理解。复杂特征则是指特征工程方面不断尝试使用各种奇技淫巧构造的可能有用、可能没用的特征,这部分特征的构造方式可能会有 各种trick,比如窗口滑动、离散化、归一化、开方、平方、笛卡尔积、多重笛卡尔积等等;顺便提一句,因为 特征工程本身并没有特别系统的理论和总结,所以初入行的同学想要构造特征就需要多读paper,特别是和自己业务场景一样或类似的场景的paper,从里面学习作者分析、理解数据的方法以及对应的构造特征的技法;久而久之,有望形成自己的知识体系。

深度学习概念提出以后,人们发现通过深度神经网络可以进行一定程度的表示学习(representation learning),例如在图像领域,通过CNN提取图像feature并在此基础上进行分类的方法,一举打破了之前算法的天花板,而且是以极大的差距打破。这给所有算法工程师带来了新的思路,既然深度学习本身有提取特征的能力,干嘛还要苦哈哈的自己去做人工特征设计呢?

深度学习虽然一定程度上缓解了特征工程的压力,但这里要强调两点:

  1. 缓解并不等于彻底解决,除了图像这种特定领域,在个性化推荐等领域,深度学习目前还没有完全取得绝对的优势;究其原因,可能还是数据自身内在结构的问题,使得在其他领域目前还没有发现类似图像+CNN这样的完美CP。
  2. 深度学习在缓解特征工程的同时,也带来了模型复杂、不可解释的问题。算法工程师在网络结构设计方面一样要花很多心思来提升效果。概括起来,深度学习代表的 简单特征+复杂模型是解决实际问题的另一种方式。

两种模式孰优孰劣还难有定论,以点击率预测为例,在计算广告领域往往以海量特征+LR为主流,根据VC维理论,LR的表达能力和特征个数成正比,因此海量的feature也完全可以使LR拥有足够的描述能力。而在个性化推荐领域,深度学习刚刚萌芽,目前google play采用了WDL的结构 [1],youtube采用了双重DNN的结构 [2]

不管是那种模式,当模型足够庞大的时候,都会出现模型参数一台机器无法存放的情况。比如百亿级 feature 的LR对应的权重w有好几十个G,这在很多单机上存储都是困难的,大规模神经网络则更复杂,不仅难以单机存储,而且参数和参数之间还有逻辑上的强依赖;要对超大规模的模型进行训练势必要借用分布式系统的技法,本文主要是系统总结这方面的一些思路。

数据并行vs模型并行

数据并行和模型并行是理解大规模机器学习框架的基础概念,其缘起未深究,第一次看到是在姐夫(Jeff Dean)的blog里,当时匆匆一瞥,以为自己懂了。多年以后,再次开始调研这个问题的时候才想起长者的教训,年轻人啊,还是图样图森破。如果你和我一样曾经忽略过这个概念,今天不放复习一下。

这两个概念在 这个问题中沐帅曾经给出了一个非常直观而经典的解释,可惜不知道什么原因,当我想引用时却发现已经被删除了。我在这里简单介绍下这个比喻:如果要修两栋楼,有一个工程队,怎么操作?第一个方案是将人分成两组,分别盖楼,改好了就装修;第二种做法是一组人盖楼,等第一栋楼盖好,另一组装修第一栋,然后第一组继续盖第二栋楼,改完以后等装修队装修第二栋楼。咋一看,第二种方法似乎并行度并不高,但第一种方案需要每个工程人员都拥有“盖楼”和“装修”两种能力,而第二个方案只需要每个人拥有其中一种能力即可。第一个方案和数据并行类似,第二个方案则道出了模型并行的精髓。

数据并行理解起来比较简单,当样本比较多的时候,为了使用所有样本来训练模型,我们不妨把数据分布到不同的机器上,然后每台机器都来对模型参数进行迭代,如下图所示

data parallel

图片取材于TensorFlow的paper [3],图中ABC代表三台不同的机器,上面存储着不同的样本,模型 P 在各台机器上计算对应的增量,然后在参数存储的机器上进行汇总和更新,这就是数据并行。先忽略synchronous,这是同步机制相关的概念,在第三节会有专门介绍。

数据并行概念简单,而且不依赖于具体的模型,因此数据并行机制可以作为框架的一种基础功能,对所有算法都生效。与之不同的是,模型并行因为参数间存在依赖关系(其实数据并行参数更新也可能会依赖所有的参数,但区别在于往往是依赖于上一个迭代的全量参数。而模型并行往往是同一个迭代内的参数之间有强依赖关系,比如DNN网络的不同层之间的参数依照BP算法形成的先后依赖),无法类比数据并行这样直接将模型参数分片而破坏其依赖关系,所以 模型并行不仅要对模型分片,同时需要调度器来控制参数间的依赖关系。而每个模型的依赖关系往往并不同,所以模型并行的调度器因模型而异,较难做到完全通用。关于这个问题,CMU的Erix Xing在 这里有所介绍,感兴趣的可以参考。

模型并行的问题定义可以参考姐夫的 [4],这篇paper也是tensorflow的前身相关的总结,其中图

model parallel

解释了模型并行的物理图景,当一个超大神经网络无法存储在一台机器上时,我们可以切割网络存到不同的机器上,但是为了保持不同参数分片之间的依赖,如图中粗黑线的部分,则需要在不同的机器之间进行concurrent控制;同一个机器内部的参数依赖,即途中细黑线部分在机器内即可完成控制。

黑线部分如何有效控制呢?如下图所示

parameter rely

在将模型切分到不同机器以后,我们 将参数和样本一起在不同机器间流转,途中 ABC 代表模型的不同部分的参数;假设C依赖B,B依赖A,机器1上得到A的一个迭代后,将A和必要的样本信息一起传到机器2,机器2根据A和样本对P2更新得到,以此类推;当机器2计算B的时候,机器1可以展开A的第二个迭代的计算。了解 CPU流水线操作的同学一定感到熟悉,是的,模型并行是通过数据流水线来实现并行的。想想那个盖楼的第二种方案,就能理解模型并行的精髓了。

parameter rely controller

上图则是对控制模型参数依赖的调度器的一个示意图,实际框架中一般都会用DAG(有向无环图)调度技术来实现类似功能,未深入研究,以后有机会再补充说明。

理解了数据并行和模型并行对后面参数服务器的理解至关重要,但现在让我先荡开一笔,简单介绍下并行计算框架的一些背景信息。

并行算法演进

MapReduce路线

从函数式编程中的受到启发,google发布了MapReduce [5]的分布式计算方式;通过将任务切分成多个叠加的Map+Reduce任务,来完成复杂的计算任务,示意图如下

MapReduce

MapReduce的主要问题有两个,一是原语的语义过于低级,直接使用其来写复杂算法,开发量比较大;另一个问题是依赖于磁盘进行数据传递,性能跟不上业务需求。

为了解决MapReduce的两个问题,Matei在 [6]中提出了一种新的数据结构RDD,并构建了Spark框架。Spark框架在MR语义之上封装了DAG调度器,极大降低了算法使用的门槛。较长时间内spark几乎可以说是大规模机器学习的代表,直至后来沐帅的参数服务器进一步开拓了大规模机器学习的领域以后,spark才暴露出一点点不足。如下图

spark

从图中可以看出, Spark框架以Driver为核心,任务调度和参数汇总都在driver,而driver是单机结构,所以spark的瓶颈非常明显,就在Driver这里。当模型规模大到一台机器存不下的时候,Spark就无法正常运行了。所以从今天的眼光来看,Spark只能称为一个中等规模的机器学习框架。剧透一句,公司开源的 Angel通过修改Driver的底层协议将Spark扩展到了一个高一层的境界。后面还会再详细介绍这部分。

MapReduce不仅是一个框架,还是一种思想,google开创性的工作为我们找到了大数据分析的一个可行方向,时至今日,仍不过时。只是逐渐从业务层下沉到底层语义应该处于的框架下层。

MPI技术

沐帅在 这个问题中对MPI的前景做了简要介绍;和Spark不同,MPI是类似socket的一种系统通信API,只是支持了消息广播等功能。因为对MPI研究不深入,这里简单介绍下优点和缺点吧;优点是系统级支持,性能杠杠的;缺点也比较多,一是和MR一样因为原语过于低级,用MPI写算法,往往代码量比较大。另一方面是基于MPI的集群,如果某个任务失败,往往需要重启整个集群,而MPI集群的任务成功率并不高。阿里在 [7]中给出了下图:

MPI

从图中可以看出,MPI作业失败的几率接近五成。MPI也并不是完全没有可取之处,正如沐帅所说,在超算集群上还是有场景的。对于工业届依赖于云计算、依赖于commodity计算机来说,则显得性价比不够高。当然如果在参数服务器的框架下,对单组worker再使用MPI未尝不是个好的尝试,[7]中的鲲鹏系统正式这么设计的。

参数服务器

历史演进

沐帅在 [8]中将参数服务器的历史划分为三个阶段,第一代参数服务器萌芽于沐帅的导师Smola的 [9],如下图所示:

parallel topic model

这个工作中仅仅引入memcached来存放key-value数据,不同的处理进程并行对其进行处理。 [10]中也有类似的想法,第二代参数服务器叫application-specific参数服务器,主要针对特定应用而开发,其中最典型的代表应该是tensorflow的前身 4

第三代参数服务器,也即是通用参数服务器框架是由百度少帅李沐正式提出的,和前两代不同,第三代参数服务器从设计上就是作为一个通用大规模机器学习框架来定位的。要摆脱具体应用、算法的束缚,做一个通用的大规模机器学习框架,首先就要定义好框架的功能;而所谓框架,往往就是把大量重复的、琐碎的、做了一次就不想再来第二次的脏活、累活进行良好而优雅的封装,让使用框架的人可以只关注与自己的核心逻辑。第三代参数服务器要对那些功能进行封装呢?沐帅总结了这几点,我照搬如下:

1) 高效的网络通信:因为不管是模型还是样本都十分巨大,因此对网络通信的高效支持以及高配的网络设备都是大规模机器学习系统不可缺少的;

2) 灵活的一致性模型:不同的一致性模型其实是在模型收敛速度和集群计算量之间做tradeoff;要理解这个概念需要对模型性能的评价做些分析,暂且留到下节再介绍。

3) 弹性可扩展:显而易见

4) 容灾容错:大规模集群协作进行计算任务的时候,出现Straggler或者机器故障是非常常见的事,因此系统设计本身就要考虑到应对;没有故障的时候,也可能因为对任务时效性要求的变化而随时更改集群的机器配置。这也需要框架能在不影响任务的情况下能做到机器的热插拔。

5) 易用性:主要针对使用框架进行算法调优的工程师而言,显然,一个难用的框架是没有生命力的。

在正式介绍第三代参数服务器的主要技术之前,先从另一个角度来看下大规模机器学习框架的演进

框架演进

这张图可以看出,在参数服务器出来之前,人们已经做了多方面的并行尝试,不过往往只是针对某个特定算法或特定领域,比如 YahooLDA 是针对LDA算法的。当模型参数突破十亿以后,则可以看出参数服务器一统江湖,再无敌手。

首先我们看看第三代参数服务器的基本架构

parameter server

上图的 resource manager 可以先放一放,因为实际系统中这部分往往是复用现有的资源管理系统,比如yarn、mesos或者k8s;底下的training data毋庸置疑的需要类似GFS的分布式文件系统的支持;剩下的部分就是参数服务器的核心组件了。

图中画了一个 server group和三个 worker group;实际应用中往往也是类似,server group 用一个,而worker group按需配置;server manager 是server group中的管理节点,一般不会有什么逻辑,只有当有server node加入或退出的时候,为了维持一致性哈希而做一些调整。

Worker group中的task schedule则是一个简单的任务协调器,一个具体任务运行的时候,task schedule负责通知每个worker加载自己对应的数据,然后去server node上拉取一个要更新的参数分片,用本地数据样本计算参数分片对应的变化量,然后同步给server node;server node在收到本机负责的参数分片对应的所有worker的更新后,对参数分片做一次update。

这里存在的一个问题就是不同的worker同时并行运算的时候,可能因为网络、机器配置等外界原因,导致不同的worker的进度是不一样的,如何控制worker的同步机制是一个比较重要的课题。详见下节分解。

同步协议

本节假设读者已经对随机梯度优化算法比较熟悉,如果不熟悉的同学请参考吴恩达经典课程机器学习中对SGD的介绍,或者我之前多次推荐过的书籍《最优化导论》。

我们先看一个单机算法的运行过程, 假设一个模型的参数切分成三个分片k1,k2,k3;比如你可以假设是一个逻辑回归算法的权重向量被分成三段。我们将训练样本集合也切分成三个分片s1,s2,s3;在单机运行的情况下,我们假设运行的序列是(k1,s1)、(k2,s1)、(k3、s1)、(k1、s2)、(k2、s2)、(k3、s2)。。。看明白了吗?就是假设先用s1中的样本一次对参数分片k1、k2、k3进行训练,然后换s2;这就是典型的单机运行的情况,而我们知道这样的运行序列最后算法会收敛。

现在我们开始并行化,假设k1、k2、k3分布在三个server node上,s1、s2、s3分布在三个worker上,这时候如果我们还要保持之前的计算顺序,则会变成怎样?work1计算的时候,work2和worker3只能等待,同样worker2计算的时候,worker1和work3都得等待,以此类推;可以看出这样的并行化并没有提升性能;但是也算简单解决了超大规模模型的存储问题。

为了解决性能的问题,业界开始探索这里的一致性模型,最先出来的版本是前面提到的 9中的 ASP模式,就是完全不顾worker之间的顺序,每个worker按照自己的节奏走,跑完一个迭代就update,然后继续,这应该是大规模机器学习中的freestyle了,如图所示

ASP

ASP的优势是最大限度利用了集群的计算能力,所有的worker所在的机器都不用等待,但缺点也显而易见,除了少数几个模型,比如LDA, ASP协议可能导致模型无法收敛。也就是SGD彻底跑飞了,梯度不知道飞到哪里去了。

在ASP之后提出了另一种相对极端的同步协议BSP,Spark用的就是这种方式,如图所示

BSP

每个worker都必须在同一个迭代运行,只有一个迭代任务所有的worker都完成了,才会进行一次worker和server之间的同步和分片更新。这个算法和严格一致的算法非常类似,区别仅仅在于单机版本的batch size在BSP的时候变成了有所有worker的单个batch size求和得到的总的butch size替换。毫无疑问,BSP的模式和单机串行因为仅仅是batch size的区别,所以在模型收敛性上是完全一样的。同时,因为每个worker在一个周期内是可以并行计算的,所以有了一定的并行能力。

以此协议为基础的spark在很长时间内成为机器学习领域实际的霸主,不是没有理由的。此种协议的缺陷之处在于, 整个worker group的性能由其中最慢的worker决定,这个worker一般称为straggler。读过GFS文章的同学应该都知道straggler的存在是非常普遍的现象。

能否将ASP和BSP做一下折中呢?答案当然是可以的,这就是目前我认为最好的同步协议SSP; SSP的思路其实很简单,既然ASP是允许不同worker之间的迭代次数间隔任意大,而BSP则只允许为0,那我是否可以取一个常数s?如图所示

SSP

不同的worker之间允许有迭代的间隔,但这个间隔数不允许超出一个指定的数值s,图中s=3.

SSP协议的详细介绍参见 [11],CMU的大拿Eric Xing在其中详细介绍了SSP的定义,以及其收敛性的保证。理论推导证明常数s不等于无穷大的情况下,算法一定可以在若干次迭代以后进入收敛状态。其实在Eric提出理论证明之前,工业界已经这么尝试过了

顺便提一句,考察分布式算法的性能,一般会分为 statistical performance 和 hard performance 来看, 前者指不同的同步协议导致算法收敛需要的迭代次数的多少,后者是单次迭代所对应的耗时。两者的关系和precision\recall关系类似,就不赘述了。有了SSP,BSP就可以通过指定s=0而得到。而ASP同样可以通过制定s=无穷大来达到。

核心技术

除了参数服务器的架构、同步协议之外,本节再对其他技术做一个简要的介绍,详细的了解请直接阅读沐帅的博士论文和相关发表的论文。

热备、冷备技术:为了防止server node挂掉,导致任务中断,可以采用两个技术,一个是对参数分片进行热备,每个分片存储在三个不同的server node中,以master-slave的形式存活。如果master挂掉,可以快速从slave获取并重启相关task。

除了热备,还可以定时写入checkpoint文件到分布式文件系统来对参数分片及其状态进行备份。进一步保证其安全性。

Server node管理:可以使用一致性哈希技术来解决server node的加入和退出问题,如图所示

一致性哈希

当有server node加入或退出的时候,server manager负责对参数进行重新分片或者合并。注意在对参数进行分片管理的情况下,一个分片只需要一把锁,这大大提升了系统的性能,也是参数服务器可以实用的一个关键点。

大规模机器学习的四重境界

到这里可以回到我们的标题了,大规模机器学习的四重境界到底是什么呢?

这四重境界的划分是作者个人阅读总结的一种想法,并不是业界标准,仅供大家参考。

境界1:参数可单机存储和更新

此种境界较为简单,但仍可以使用参数服务器,通过数据并行来加速模型的训练。

境界2:参数不可单机存储,可以单机更新

此种情况对应的是一些简单模型,比如 sparse logistic regression;当feature的数量突破百亿的时候,LR的权重参数不太可能在一台机器上完全存下,此时必须使用参数服务器架构对模型参数进行分片。但是注意一点,SGD的更新公式可以分开到单个维度进行计算,但是单个维度也是需要使用到上一轮迭代的所有参数(即计算预测值$f(w)$)。而我们之所以对参数进行分片就是因为我们无法将所有参数存放到一台机器,现在单个worker有需要使用所有的参数才能计算某个参数分片的梯度,这不是矛盾吗?可能吗?

答案是可能的,因为 单个样本的feature具有很高的稀疏性(sparseness)。例如一个百亿feature的模型,单个训练样本往往只在其中很小一部分feature上有取值,其他都为0(假设feature取值都已经离散化了)。

因此 计算$f(w)$的时候可以只拉取不为0的feature对应的那部分w即可。有文章统计一般这个级别的系统,稀疏性往往在0.1%(or 0.01%,记得不是很准,大致这样)以下。这样的稀疏性,可以让单机没有任何阻碍的计算$f(w)$。

目前公司开源的angel和AILab正在做的系统都处于这个境界。而原生spark还没有达到这个境界,只能在中小规模的圈子里厮混。Angel改造的基于Angel的Spark则达到了这个境界。

境界3:参数不可单机存储,不可单机更新,但无需模型并行

境界3顺延境界2二来,当百亿级feature且feature比较稠密的时候,就需要计算框架进入到这层境界了,此时 单个worker的能力有限,无法完整加载一个样本,也无法完整计算$f(w)$。怎么办呢?其实很简单,学过线性代数的都知道,矩阵可以分块。 向量是最简单的矩阵,自然可以切成一段一段的来计算。只是调度器需要支持算符分段而已了。

境界4:参数不可单机存储,不可单机更新,需要模型并行

进入到这个层次的计算框架,可以算是世界一流了。可以处理超大规模的神经网络。这也是最典型的应用场景。此时不仅模型的参数不能单机存储,而且同一个迭代内,模型参数之间还有强的依赖关系,可以参见姐夫对 distbelief 的介绍里的模型切分。

此时首先需要增加一个coordinator组件来进行模型并行的concurrent控制。同时参数服务器框架需要支持namespace切分,coordinator将依赖关系通过namespace来进行表示。

一般参数间的依赖关系因模型而已,所以较难抽象出通用的coordinator来,而必须以某种形式通过脚本parser来生产整个计算任务的DAG图,然后通过DAG调度器来完成。对这个问题的介绍可以参考 Erix Xing的分享

Tensorflow

目前业界比较知名的深度学习框架有Caffee、MXNet、Torch、Keras、Theano等,但目前最炙手可热的应该是google发布的Tensorflow。这里单独拿出来稍微分解下。

前面不少图片引自此文,从TF的论文来看,TF框架本身是支持模型并行和数据并行的,内置了一个参数服务器模块,但从开源版本所曝光的API来看,TF无法用来10B级别feature的稀疏LR模型。原因是已经曝光的API只支持在神经网络的不同层和层间进行参数切分,而超大规模LR可以看做一个神经单元,TF不支持单个神经单元参数切分到多个参数服务器node上。

当然,以google的实力,绝对是可以做到第四重境界的,之所以没有曝光,可能是基于其他商业目的的考量,比如使用他们的云计算服务。

综上,个人认为如果能做到第四重境界,目前可以说的上是世界一流的大规模机器学习框架。仅从沐帅的ppt里看他曾经达到过,google内部应该也是没有问题的。第三重境界应该是国内一流,第二充应该是国内前列吧。

其他

资源管理

本文没有涉及到的部分是资源管理,大规模机器学习框架部署的集群往往资源消耗也比较大,需要专门的资源管理工具来维护。这方面yarn和mesos都是佼佼者,细节这里也就不介绍了。

设备

除了资源管理工具,本身部署大规模机器学习集群本身对硬件也还是有些要求的,虽然理论上来说,所有commodity机器都可以用来搭建这类集群,但是考虑到性能,我们建议尽量用高内存的机器+万兆及以上的网卡。没有超快速的网卡,玩参数传递和样本加载估计会比较苦逼。


参考文献:

[1] Cheng H T, Koc L, Harmsen J, et al. Wide & deep learning for recommender systems[C]//Proceedings of the 1st Workshop on Deep Learning for Recommender Systems. ACM, 2016: 7-10.

[2] Covington P, Adams J, Sargin E. Deep neural networks for youtube recommendations[C]//Proceedings of the 10th ACM Conference on Recommender Systems. ACM, 2016: 191-198.

[3] Abadi M, Agarwal A, Barham P, et al. Tensorflow: Large-scale machine learning on heterogeneous distributed systems[J]. arXiv preprint arXiv:1603.04467, 2016.

[4] Dean J, Corrado G, Monga R, et al. Large scale distributed deep networks[C]//Advances in neural information processing systems. 2012: 1223-1231.

[5] Dean J, Ghemawat S. MapReduce: simplified data processing on large clusters[J]. Communications of the ACM, 2008, 51(1): 107-113.

[6] Zaharia M, Chowdhury M, Das T, et al. Resilient distributed datasets: A fault-tolerant abstraction for in-memory cluster computing[C]//Proceedings of the 9th USENIX conference on Networked Systems Design and Implementation. USENIX Association, 2012: 2-2.

[7] Zhou J, Li X, Zhao P, et al. KunPeng: Parameter Server based Distributed Learning Systems and Its Applications in Alibaba and Ant Financial[C]//Proceedings of the 23rd ACM SIGKDD International Conference on Knowledge Discovery and Data Mining. ACM, 2017: 1693-1702.

[8] Li M, Andersen D G, Park J W, et al. Scaling Distributed Machine Learning with the Parameter Server[C]//OSDI. 2014, 14: 583-598.

[9] Smola A, Narayanamurthy S. An architecture for parallel topic models[J]. Proceedings of the VLDB Endowment, 2010, 3(1-2): 703-710.

[10] Power R, Li J. Piccolo: Building Fast, Distributed Programs with Partitioned Tables[C]//OSDI. 2010, 10: 1-14.

[11] Ho Q, Cipar J, Cui H, et al. More effective distributed ml via a stale synchronous parallel parameter server[C]//Advances in neural information processing systems. 2013: 1223-1231.

我们总不能活在摇篮里:马斯克的公司正如何变革八大领域?

$
0
0

编译  |晏奇、NN、张楚、张震

编辑 | 微胖

来源 | CBinsights 等


马斯克的每家公司都是事关人类未来的存在主义赌注。


这些也是任何人所能下的最大赌注,更别说作为一名企业家。当你惊讶于马斯克对这些领域进行变革时,记住这一点很重要。


然而,所有这些高额赌注和创新的背后,却是一个非常「无趣」的策略:不是创造全新的东西,而是让旧的东西更好。


正如马斯克在美国德克萨斯州西南偏南 (SXSW) 音乐节上发表演讲时说:


「生活不仅仅是不断解决那些悲惨的事情。」他补充说,「这不是唯一的事情。生活也需要那些激励你的事情,让你每天高兴地醒来,并成为你作为人的一部分。那就是我们为什么要做这些的原因。」


人工智能


在人工智能可以击败世界冠军的问题上,暴雪和 DeepMind 都对此持谨慎态度,没有给出一个确切的日期。


但是,2017 年夏天,OpenAI 机器人在单挑比赛中,大败 Dota 2 世界顶级玩家。


10 月,经过 3 天的训练后,AlphaGo Zero 击败 AlphaGo。而后者是去年击败韩国选手李世石的 DeepMind 系统。经过大约 40 天 2900 万场自玩游戏的训练后,AlphaGo Zero 击败了 AlphaGo Master,后者在今年早些时候击败了围棋世界冠军柯洁。


在此之前,AI 的成长速度是这样的。


2016 年 3 月,李世乭 1-4 败给了来自英国的围棋人工智能系统 AlphaGo。


2017 年 1 月 4 日,在取得了 59 场连胜之后,化名 Master 的神秘棋手在留言板上承认了自己的身份。


2017 年 5 月,在中国乌镇 ·围棋峰会上,AlphaGo 对阵人类世界排名第一的棋手柯洁,三局全胜。


这些只是侠义 AI 的应用。但是,通用人工智能会使用这些技术引导自己。现在,人工智能已经在学习自我发展。


人类才是棋盘游戏之王。马斯克指出,我们没有意识到自己的错误,知道既成事实的发生。「如何确保人工智能要的东西就是人类所要求的内容?」


2015 年,马斯克和美国著名加速器企业 Y Combinator 总裁 Sam Altman 共同发起创立 OpenAI,一个非盈利研究组织,旨在发挥人工智能的「正能量」。


「首先,它是一个推动人工智能发展的非盈利组织。从本质上说,它是一个研发实验室,它反对大企业掌控超级智能系统并用来谋取巨额利润,反对政府利用人工智能系统获得更大特权并用于压迫民众。」马斯克说。


除了进行研究,这个组织还「涉及元研究,也就是平台和基础结构方面的东西,让每个人的研究都能更快些。」


这个组织有两个核心组成部分:研究和系统。后者搭建平台帮助研究人员理解机器,进而将机器系统打造地更好,比如 AI Gym。


安全是OpenAI 主要关注的问题。人工智能研究人员在开发新应用程序时需要考虑安全因素;如果他们不这样做,罪犯就会利用这项技术来做恶意活动。


就在上个月底,OpenAI 、牛津大学、剑桥大学等 14 家机构和高校共同发布了一份《人工智能恶意使用》报告,该报告详细讲述了人工智能技术潜在的「恶意」用途,以及预防措施。


而早在 2016 年,谷歌就与 OpenAI 联合发布 AI 安全五大则,取代机器人三定律预防科技暴走:避免负面效应、避免奖励的黑客行为、可扩展监督、安全探索以及针对分配转变的鲁棒性。


OpenAI 在许多行业中促进了人工智能的研究和发展。不过在2 月 22 日,OpenAI 发布公告称,其联合主席马斯克宣布退出董事会。


原因是随着特斯拉更专注于 AI 技术,需要避免与 OpenAI 在未来可能存在的利益冲突。根据公告内容,此次退出董事会大多是马斯克为了避嫌。不过,他还有半只脚留在了 OpenAI:马斯克还将继续担任 OpenAI 顾问,继续提供资助和建议。



医疗健康


马斯克所有的赌注,几乎都是大规模的,但 Neuralink 完全不同:微观到你的神经元。也正因为如此,它也是马斯克至今为止最大的挑战,也是最激动人心的一个。


2017 年 3 月,华尔街日报一篇 1100 个单词的文章,低调宣告了这家公司的成立。


这家公司试图研发一种技术,将人脑与计算机系统融合在一起。这种利用脑机接口实现的融合,将有助于治疗人类的脑部疾病。以及,很可能,使人类变得更加强大。


公司汇集了许多令人敬佩的联合创始人,并设定了一个目标,即在 2021 年前开发残疾人临床使用的脑机接口。不过马斯克估算,为健全人设计的设备大约还需等待八到十年的时间。


Neuralink 并没有具体说明到底在做什么,但 Wait But Why 网站中的一篇长文章概述了马斯克的想法。在这篇文章中,他描述了人类之间彼此进行更快速沟通的必要性,同时提到人类与计算机沟通的必要性,否则人类将被人工智能遗弃在尘埃中。文章提到了一些非凡的可能性:从云端立刻汲取知识,或把来自某个人视网膜的图像直接输入到另一个人的视觉皮层;创造全新的感官能力,如红外视力、高频听力等; 最终,融合成为人机混合智能。


人脑与机器直接沟通,需要一个脑机接口(BCI)做通道。其实,脑机接口的使用历史可以被追溯至 2004 年,那一年,一个名为 BrainGate 的系统 被植入到 13 名瘫痪者的脑中。


这个系统由布朗大学研发(其他一些科研院所也有类似的设备),名为犹他电极阵列的小电极阵列被植入到运动皮层(大脑用于管理运动的一部分)中。这些电极对神经元进行监测,如果被植入者在其意识中试图移动手或胳臂,神经元所释放的电信号将通过电线从人的颅骨中传送到解码器,从而被转换成各种各样的系统,例如帮助被植入着移动光标、控制肢体等。


大脑和机器之间的交互还以其他方式改变了生活。比如,2014 巴西世界杯足球赛开幕式上,一名截瘫男子用意念控制机器人外骨骼「机械战甲」开球。


不过,即使脑机接口技术在人类方面有很多实验性的突破,它也很难转化为临床实践。连线杂志早在 2005 年就对当时新推出的 BrainGate 系统进行了一次非常轰动的报道。在该项技术发展的早期,一家名为 Cyberkinetics 的公司尝试将其商业化,但并未成功。此外,NeuroPace 花费了整整 20 年时间开发技术、与监管方进行谈判请求批准,但据其预计,今年将只有 500 名癫痫患者能够被植入该公司的电极并使用其系统。


不过,马斯克仍然坚持在 AI 掌控人类之前,让人类变得更强大。


「随着时间推移,我们可能将会看到生物智能和机器智能的结合体。这种结合主要是出于对带宽的考虑,就是你的大脑和数字设备之间的连接速度,特别是输出速度。」马斯克说,这种结合可能要借助一种名为「神经蕾丝(neural lace)」的技术。神经蕾丝是一种可注射的网状物,能从硬件上将人脑和计算机连接起来,让它们直接通信。


短期内,Neuralink 试图解决两个困扰现在脑机接口技术的两个问题:系统带宽很低以及倾入性很高。就目前而言,这家公司的主要受益人会是美国 30 万名脊髓问题患者,550 万老年痴呆症患者以及 250 万的中风患者。




基础设施/隧道


「我得做件事了,我要开一家叫『无聊』的公司(英语 boring 有钻孔的意思)。」马斯克出门遇上了堵车,堵得生气了


目前,Boring 公司正在洛杉矶建造一个地下隧道网络,在隧道中,系统将自动通过电动滑板来传输汽车,电动滑板的最快速度达到 130 英里 / 小时。路面上会有一些「停车位」,当汽车驶上这个位置时,会被自动降运到地下隧道里,随后,汽车会被以极快的速度传送出去。汽车在地下隧道的传输不只是单线运作,也可以根据实际需要更换线路。


这个地下隧道网络将多达 30 层隧道,可传输汽车,也可以传输超级列车。


为什么一定要挖隧道呢?目前,Uber 和 Google 联合创始人佩奇投资的两家创业公司都在研发飞行汽车。马斯克在接受彭博社采访时则表示,无论在技术上还是在监管上,地下交通都要比空中交通更有前景。


而且美国基础设施建设之落后,令人乍舌。2012 年,美国投入到基础设施建设中的资金位居世界 143 位,仅占整个 GDP 的 13%,全球最低之一。与欧亚形成鲜明对比。


马斯克不仅仅想挖隧道,也想让美国恢复基础建设能力。


目前公司有三个项目计划。第一个是在 SpaceX 测试隧道,隧道并不通往何方,仅仅作为一个研发试点。


问题在于挖掘成本。比如美国纽约第二大道地铁由两条 8.5 英里的轨道组成,共花费了 170 亿美元。隧道成本近乎每条 10 亿美元。马斯克认为,这个挖掘成本会降低到 1亿。而成本降低无非取决于两个因素:大小和速度。


「无聊公司」将缩小隧道直径至 14 英尺以下。直径减小一半可使隧道费用降低 3-4 倍。此外,「无聊公司」还将通过增加隧道挖掘机功率,使用自动化隧道挖掘机等方式提高挖掘速度。马斯克表示,为降低成本,Boring 正在寻求将隧道挖掘机的功率和发热限值提高「四五倍」的办法。



如果马斯克的地下隧道计划顺利进行,这些隧道最终可被用于地铁、超级高铁以及私家车。汽车将使用未来式的雪橇从地面道路降落至隧道,雪橇运输汽车的速度可达到每小时 125 英里(约合 201 千米)。


这家公司可能不仅仅是只占用马斯克 2% 到 3% 时间的业务爱好。它也将为马斯克在其他领域的努力提供坚实基础:特斯拉、Hyperloop 和 SpaceX.


能源


首先是 SolarCity,然后又是 Tesla,近十几年来,马斯克的首要任务之一就是让人类不再依靠化石燃料,让人类能从头顶上的超级聚变反应堆(太阳)获取能量。


SolarCity 是马斯克想让太阳能变得主流化、无所不在的第一个尝试,这家公司是 21 世纪初「太阳能淘金热」时期的领头羊。虽然从某种程度上讲,这家公司失败了,但是这对于了解致力于解决可再生能源的马斯克与 Tesla 来说非常重要。


当时,SolarCity 已经成长为美国最大的家用太阳能提供商,然后在它被马斯克的另外一家公司 Tesla 以 20 亿美金收购之前,SolarCity 遭遇了一些公共财政问题。


这笔 2016 年发生的收购充满争议,很多观察家将其称为「赤裸裸的求助」。然而,在接过 SolarCity 的工作以后,Tesla 凭借自己的努力让太阳能业务超越了原来的 SolarCity。


为什么选择太阳能?


2004 年,埃隆·马斯克将太阳能的理念(后来发展成 SolarCity)告诉了自己的表兄 Peter 和 Lyndon Rive。


SolarCity 的理念来源其实很简单:化石燃料正在逐渐减少。对替代能源的需求正在快速上升。「如果他们当时就开始行动,」据男士期刊(Men's Journal)的报道,「那么他们将占有整个市场。」


在 2004 年,已经有很多证据表明,除太阳能以外的其他能源形式并可靠。


在 1990 年代后期,煤炭业的增长已经进入停滞期——这是煤炭生产量下降的早期征兆,该现象一直持续到现在。同时,面临同样困境的还有核能发电产业。尽管有人在 2000 年左右预测称我们将迎来「核能的复兴」,但是到 2004 年,这一切并没有到来。


自 2000 年以来,尽管没有新增,但核能发电业基本还是处于稳定状态。可是自 2004 年起,美国大量的核反应堆与煤炭生产设备都进入了老旧期。在不久之后,人们就必须选择要么对其进行昂贵的升级或者是维护,要么就将其换成其他形式的能源。


这些核电或煤电装置平均年龄都已达 40 年。今天,在我们使用的电能中,大约有 250 千兆瓦都即将棉铃升级或维护或替代。


与此同时,在 2004 年,太阳能作为一种替代能源看起来十分吸引人。几十年来,太阳能产能的价格一直在下降,从 1977 年的一瓦 76.67 美元降到了 2004 年一瓦仅仅几美元。


Swanson 效应发现,太阳能电池板产量每翻一翻,制造用于生成太阳发电光电池价格便会下降约 20%。


此外,在房顶安装太阳能电池板的价格也在下降——而且可以肯定的是,在接下来的多年中,这一趋势会一直保持。


Musk 以及 SolarCity 接过了太阳能普及化的「最后一公里」挑战,让太阳能真正变得大众化、主流化。


到 2013 年,SolarCity 已经成为了全美最大家用太阳能系统安装商。


公司最核心的创新并不在于技术,而是在收费方面。当 SolarCity 刚成立时,如果人们要想在自家屋顶安装太阳能板,则需要预支 30000 到 50000 美元。于是,SolarCity 率先采用了「太阳能出租」战略,该战略让用户可以免费安装太阳能板,然后慢慢支付安装费用。GTM 研究报告称,自 2014 年起,有 72% 新安装的太阳能设备都使用了「太阳能出租」计划。


据 Fast 公司称,从股票价格来看,2014 年 2 月是 SolarCity 的鼎盛时期,但是随后不久,SolarCity 订单的取消率便上升到了 45% 甚至更高。


一些评论家指出,SolarCity 激进的销售策略是这一切的罪魁祸首。SolarCity 的销售人员会通过给客户提供省钱担保的方式(批评者称这为「歪曲事实」)来获得安装订单。但一旦客户意识到他们不会像他们承诺的那样节省那么多,便纷纷取消了安装订单。


自始至终,SolarCity 的销售团队都在以每周几百人的规模增长。这些人会鼓励客户预定安装,他们得到了大量的订单。然而,收益却并没有像订单率一样增长。到 2015 年年末,公司向投资人保证,他们会通过降低公司的规模增长率来挽回颓势。华尔街对此已经开始不耐烦。在 SolarCity2016 年 2 月宣布公司遭遇了一个很差的季度之后,他们的股票下跌了 3 个百分点。


2 月,马斯克宣布其公司收购了 Tesla。那段时间,Tesla 正在致力于研发帮助人们在家和路上给自己 Tesla 汽车充电的技术。这种电池被称为「powerwall」,它们可以装在家里或者是连在第三方的太阳能发电器上。在这笔交易完成后,SolarCity 的业务进行了调整,开始对 Tesla 的「太阳能屋顶」产品提供支持——Tesla 通过这款产品来向用户提供端到端的家用太阳能,而不仅仅是电池。


汽车


2013 年 8 月,马斯克就在 SpaceX 的官网上公布了一份长达五十八页的白皮书 Hyperloop Alpha,将 Hyperloop,飞机、火车、汽车、船只列为五大未来交通工具。


其中,特斯拉负责实现未来汽车交通电气化,加速可持续能源出现。为此,公司打算推出紧凑型 SUV、皮卡、重型卡车及高载客密度的城市交通工具。


「在国际象棋中有这样一种说法,如果你能提前看到 12 步,你就是个大师了。而在任何情况下,Elon 都能提前看到 12 步。」他哥哥曾说。马斯克的布局远比我们想象的更早。


上世纪九十年代,还在沃顿商学院求学的马斯克写了三篇论文,其中两篇关于清洁能源。


关于太阳能电池的论文得了 98 分,「很有趣,写得漂亮。」纸上谈兵终究不是工程师的风格,这项商业计划最后落地 SolarCity。


另一篇论文就是关于超级电容,也是特斯拉核心技术之一电池的前身。在这篇 44 页的论文中,他引用了硅谷研究人员最新研究:


「新的能源和燃料电池的出现,最终会产生首批新的能源存储方式。而且,由于超级电容保留了电容的基础属性,传输速度比传统相同重量的电池快一百倍以上,再充速度也很快。」


他写道,这种新的能源储存方式会与自己变革交通工具(汽车、飞机、火箭等)的「野心」契合。


「分析透彻」、「优秀的商业分析。」教授如此评价这篇论文。后来申请斯坦福博士学位时,马斯克还想研究高能量密度电容器,渴望找到比传统电池更高效的能量储蓄方式。


这个时期的马斯克,已经展现出未来成功的潜在要素:逻辑清楚、对科技知识的准确把握以及科技商业化的深刻见解:商业化是让科技变革人类生活最佳路径。


马斯克后来在接受媒体采访时也反复强调,沃顿商学院时期,自己就清楚自己想要改变世界。「用神奇的新技术改变世界或影响未来的事情,我很感兴趣。」马斯克说。作为一名学物理出身的天才工程师,马斯克更关心如何制造工具去改变世界,而不是在象牙塔里思考世界的本质。


这些先进技术(工具)就是电动汽车、清洁能源和互联网。


后来,超级电容的商业计划论文落地成特斯拉。「特斯拉的根本意图,至少我的动机,」马斯克曾解释过,「是为了加速可持续能源的出现。」


要想创新被主流接受(以及主流有能力接受),首先要找准早期采用者。虽然这些人占比很低,但是影响力非常大,能够通过人际沟通说服更多的人接受创新。


特斯拉的第一个产品是 Roadster,这是一款「以路特斯 Elise 为基础」的豪华电动双座敞篷跑车,售价为 9 万美元。看到这组数字,我们会对 Roadster 有一个基本的理解:其性能可以和法拉利这样的超跑媲美、是一款为社会精英打造的产品。


特斯拉也是从量少价高的产品入手,先回笼资金,随着核心技术的成熟和制造能力的提高,再生产普通大众负担得起的电动车。


2009 年 3 月,特斯拉正式对外公布了 Model S。2013 年,赢得「年度车辆」的荣誉。但是,它仍然不是面向大众的车。13 年之后,特斯拉终于实现了自己的初衷,Model 3。2017 年,推出 Semi 自动驾驶卡车,成为货运行业数十年来最重要的行业发展催化剂。


然而,量产问题一直困扰着特斯拉。去年 11 月,特斯拉公布了 2017 年第三季度财报。财报显示,特斯拉 Model S 和 Model X 车型在第三季度的销量创下新高,其在第三季度总计交付了 26137 辆汽车,但是只有 222 辆 Model 3。而特斯拉在财报中将问题归结为电池系统。


2015 年,特斯拉开始研发 Autopilot。在 2016 年底发布 Autopilot 2.0 系统时,马斯克曾表示,这些功能将于 2017 年被安装到车辆中,但后来马斯克承认,研发过程要比预想的更难,进度要晚于原先的计划表。


去年,马斯克表示特斯拉的目标是 5 级自动驾驶功能,即最高级别的自动驾驶功能,该功能可让人类驾驶员在车内「睡觉」,马斯克当时给出的时间预测依然是两年。


但是,在西南偏南活动的采访环节中,他又推迟了以往的猜测,「覆盖各类驾驶场景的完全自动驾驶将在 2019 年年末到来」。


据外媒透露,特斯拉目前在售车型已经具备「完全自动驾驶」功能,但并未被启用。但即便如此,公司声称一旦他们最终通过软件升级证明自己的产品性能优于人类驾驶员,并且在法规允许的条件下,该功能便会被释放。


 通信


谈及 Musk 和他的伙伴如何创新,实际上 Musk 的每个项目似乎都围绕着一个与众不同的准则:找到一个曾因技术匮乏而难以实现的旧想法,并请世界顶级的工程师来攻克它。


这就是 Musk 和 SpaceX 如何紧跟卫星互联网行业步伐的。通过卫星发射形成互联网其实是个旧想法。Teledesic 公司成立于 20 世纪 90 年代初,旨在建立一个能够实现宽带网覆盖广泛的卫星群。面临将众多卫星发射至太空以及维持低延迟连接的巨大运筹挑战,该公司及其他几家同类公司纷纷走向倒闭和破产。


2015 年初,Elon Musk 首次公开谈到用卫星网络覆盖全世界的想法。2016 年 11 月,SpaceX 向联邦通信委员会(FCC)提交了申请,要求在六年内发射超过 11000 颗宽带卫星,并「提供能够持续并全面覆盖全球的强大宽带服务。」


到 21 世纪 20 年代中期,这一卫星驱动的全新互联网服务——「Starlink」——有望成为世界最大的全球电信供应商。其价值可能达到 1 万亿美元。这相当于 SpaceX 的一个不错的附带项目,可为我们最终殖民火星提供资金支持。


SpaceX 计划从轨道传送全球宽带网,创建一个能够覆盖全球的网状网络。在他们向联邦通信委员会(FCC)提交了这一申请的几个月后,SpaceX 首次向太空发射了一枚使用过的火箭。这是 SpaceX 的「Master 计划」中迈出的一大步,其中一部分就是为了完善火箭重复使用的技术,使航天器可以在释放有效载荷的数小时内降落并返至太空。


当该技术与 SpaceX 的宽带愿景相结合时,有可能会打破电信公司经营业务的传统方式。


SpaceX 已经将卫星发射成本降至 3 亿多美元,相比于波音或者洛克希德公司发射一次所花费的 4.2 亿美元节省了大概 8500-9500 万美元。他们的第一个可重复使用的火箭,猎鹰 9 号,发射成本还不到其首次发射的一半。SpaceX 正致力于解决依然存在的各种难题,从而实现火箭的完全重复使用,Musk 计划于 2018 年底完成的这一项目。这样一来发射过程中就只剩下一种不能重复使用的东西——燃料——每次发射任务大约花费 25 万美元。


单次任务不到 100 万美元的单位成本将使发射 4000 颗以上的互联网卫星变得轻而易举。这些卫星一旦升上太空,将会让持久稳定的千兆低延迟宽带网覆盖全球——包括目前还没有互联网的地区。


世界上大部分地区目前甚至连内陆的千兆互联网连接都尚未拥有。


在过去的几十年间,一些杰出的卫星互联网公司走向倒闭——Iridium 和 Teledesic 就是其中两个代表。而 Starlink 项目在一些重要的方面有所不同:


成本:前文已经讨论,SpaceX 已经将卫星发射的成本降低至从前的一小部分(而且将会进一步降低)

速度:传统的卫星网络速度 25Mbps 已经是极限,而 SpaceX 的卫星网络速度将会达到 1 千兆

延迟:数据包在地球和卫星之间的传输时间——当前供应商的时钟延迟为 600+毫秒,而 SpaceX 的目标是大约 30 毫秒


SpaceX 网络卫星的第一个原型计划于 2018 年初发射升空。第一颗实际运行的卫星将随后在 2019 年发射。鉴于这家公司降低了发射成本,并且他们有更多卫星飞向太空,按照 Galvin Sheridan 的话来说,SpaceX 将「带来陆基网络的终结」——这种情况实现的几率会越来越高。


有关卫星互联网的想法已经存在了几十年,却始终停滞不前,而这将为卫星网络带来巨大改变。此外,这不是 Musk 和他的伙伴们正致力于恢复的唯一「旧想法」。例如,关于运输的最早想法是通过真空管来运输。1812 年,一位名为 George Medhurst 的英国人最早提出建造地下隧道,并依靠空气动力运输隧道舱中的乘客。


在 2012 年,Elon Musk 是第一个让人们相信能够将这一愿景变为现实的人。


交通


马斯克的超级高铁原始模型来自于 SpaceX 2013 白皮书关于这个模型的主题。


在白皮书中,他和 SpaceX 以及特斯拉团队一道测试这个想法的可行性,并理解了解其经济性。他们发现「pod, 吊舱」可以在 2.5 分钟内行驶 30 公里,将洛杉矶至旧金山之间的形成从 6 小时缩短到了半小时。而且大约只需花费 20 美元就能维持。


这比加州正在规划实现的高速公路还要便宜。


将加压舱和低压隧道结合起来,您将得到比以前设想的任何方式都快的运输方式。


就速度而言,Hyperloop 是现存交通方式中平均速度最快的一种。商业航空运输属于第二快,它的平均时速是 575 英里。Hyperloop 将会以 600 英里的平均时速运行,这或许是日本新干线(bullet)的三倍。


Hyperloop 可能会对一些不同的行业产生重大影响。首当其冲的是 660 万亿美元的航空运输业。除了可以在海洋上旅行之外,Hyperloop 可以比飞机更快、更便宜地运送乘客。


这种速度可以从很大程度上改变人们在美国的居住地点和居住方式,这也会极大地改变住宅和商业房产。一个人可以很容易地实现在曼哈顿工作,但是却住在佛蒙特州的伯灵顿,这段每天往返 6 小时的车程使用 Hyperloop 循环通勤只需半小时。


这也将改变政治,因为在特区服务的政治家可以每周或每天拜访一次他们家乡的选民。


它可以彻底改变货运业。几乎一半的美国进口货物都会通过洛杉矶和长滩的港口。SCPR 称,14,000 名卡车司机将这些货物运往南加州各地的「仓库和铁路场」。据普华永道 ( PricewaterhouseCoopers ) 称,它们每天要移动大约 11,000 个集装箱,每年消耗约 6,800 万加仑燃料。


虽然您仍然需要卡车和人类司机来完成最后一公里运输,但是一个类似于 Hyperloop 的运输系统可以以更低的成本、更低的污染、有着数量级差距的更快速度来运输货物。


当然,Hyperloop 有其反对者。尤其是那些有明显抗议的人——我们要把他们放在哪里?几十年来,实现在地面上建造火车所必需的通行权和建造成本注定了高速铁路项目的失败。隧道技术也还没有实现。


一天,当马斯克坐在洛杉矶郊外的公交中时,他发了一条推特发表抱怨,表示这将成为公司正面解决这个问题的动力。


航空航天


我们正在建造第一艘前往火星的星际飞船,我认为明年上半年就能实现短途飞行。马斯克在美国德克萨斯州西南偏南 (SXSW) 音乐节上发表演讲时说:他强调,整个飞船可多次重复使用。


2017 年 12 月 15 日,SpaceX CRS-13 在美国卡纳维拉尔角发射,对国际空间站进行再补给任务。这是 SpaceX 与 NASA 所签订合同中的第十三次再补给任务,是迄今为止,猎鹰 9 号的第 45 次发射。


仅 2017 年就有 18 次飞行,甚至将火箭着落在一辆移动船舶上都已成为很常规的事情。但这次任务有所不同。这是首次对 SpaceX 的核心特征进行夸大。它的规划是如何将人类送入火星——这是一个完全重新利用的火箭。猎鹰 9 号全推力版(Falcon 9 Full Thrust)第一阶段在六月份是作为 CRS-11 的一部分飞行。而 Dragon 太空舱首次是在 2015 年作为 CRS-6 的一部分飞行。猎鹰和 Dragon 以前都有重新使用的情况,但整个太空飞船由以前的飞行组件构成还尚属首次。


对马斯克来说,这是唯一一个使得太空旅行成为可行的方式。如果每个火箭都是一次性的,想要离开这个星球是不可能的。如果火箭像飞机一样,可以反复使用进行多次航行,到那时,太空就有可能成为下一个飞行出游的地点,让每个人都有机会进行太空旅游。


这一一个有关成本-重量比的问题。将数吨设备送入太空的成本越低,太空才越有可能成为一个好的去处。如果每次都要建造一个全新的航空飞机,这个成本就会及其的高昂。


在价格区间范围的顶端是可抛式发射系统 (Expendable launch system), 比如 rianespace 的 Vega 发射器以及波音/洛克马丁的 Atlas V 运载火箭(该火箭由发射同盟公司 (UnitedLaunchAlliance,ULA) 制造,ULA 是波音和洛克马丁的合资公司)。这种火箭可以将很多设备送入轨道,但无法重新使用。Space Shuttle (NASA) 的造价属于中等水平。这种航天飞机的造价较低,可以重复使用,但固体火箭助推器和主燃料箱是不可回收利用的,会导致使用成本增加,最终限制了该项目的价值。


在这个价格范围的低端是 SpaceX 的猎鹰火箭 (Falcon Rocket),目前的发射成本已降低了 3-5 倍。但这个成本仍然不是马斯克的最终目标。他不仅仅只想把一个航天飞机送上火星。


马斯克希望能用 SpaceX 把 1 百万人送上火星。为了实现这一目标,他说需要将「每吨的成本提高百分子五百万」


在马斯克看来,人类都在在一个星球上是一件很疯狂的事情,会不可避免的会走向灭绝。对地外空间不断探索,远离地球,我们人类就会变的更加坚强,对超越人类的人工智能或者地球自然资源的破坏就不会那么敏感。


火星不是最佳的宜居地,但确实最佳的一个选择。


火星上的大气和气温是一个很大的障碍,但除此之外,火星和地球有很多相似的地方。


火星上每天的长度和地球很类似,气温范围也大致一致,陆地的面积几乎相当。地表下有丰富的水资源,在陆地和空气中还有很多重要的元素。大气有所不同,这就是我们需要 The Boring Company(由埃隆·马斯克所创建。The boring company 公司的目的是为了解决美国地面交通拥堵问题)和它的管道的原因。


挖隧道的另外一个原因也和成本相关。「百分子 5 百万」成本优化,不仅要求火箭的可重复使用。这只是使到达火星更加经济的四个要素之一。


火箭技术的可重复利用性。这是 SpaceX 目前所关注的。CRS-13 已表明,目前这一要素已成为现实。


在轨道上为火箭补充燃料。所需的燃料很多,但把所有需要到达火星的燃料都带上是不可行的。


在火星上制造推进物的能力。如果无法在发射时带充足的燃料,还要带上返回时的燃料,成本就会变得很高昂。新殖民者要做的第一件事即使建造一个加油站。


制造合适推进物的能力。所有的证据都表明在火星上制造合适的推进物是可行的。


SpaceX 使用的燃料是 Methalox,这是甲烷和氧气的结合物。为了制造甲烷,SpaceX 将会从火星大气中收集二氧化碳(火星大气中 96% 是二氧化碳),从地表收集矿物质水。通过这种方式,公司可以生产出所有返程所需的燃料。


SpaceX 计划在地球和火星之间创建一条必要的太空公路,包括找到一种可以在火星上制造足够燃料的方式,以支撑航天飞机的返程。


这个航天设备不会是当前使用的猎鹰和 Dragon 结合的一个产物。SpaceX 正在研发 BFR-Big Falcon Rocket(大猎鹰火箭)。猎鹰 9 可以将 22900 公斤的设备送到近地轨道,BFR 将能够将 50 万公斤的设备送到近地轨道。在加上公司正在研发的 Raptor 发动机,到火星的行程将只需 80 天。不过,在成为火星人之前,我们仍然是地球上的生物。在 BFR 建造之前,另外一个猎鹰火箭仍在努力延长在这个星球上的使用寿命。这是马斯克真个战略的一部分:建造一些当前真正有用的东西以养活这个未来的宏大计划。


使用可重复使用的火箭将物质送入近地轨道,将会比以前节省相当大的成本。甚至开启了商业探索太空的可能性。SpaceX 计划商业可行性的一个可以类比的就是航空飞机。如果波音公司的每架 737 仅在飞行一次后就报废了,从洛杉矶到拉斯维加斯的一趟行程每人将花费大约 50 万美元。因为不必将每辆飞机在飞行一次后就销毁,同样一段行程,波音公司只需收取 43 美元。


这就是马斯克想要引入太空飞行的成本结构。到达火星的费用不可能是 43 美元,但会从当前的无法估量到只有 30-50 万美元。贵吗,但这是可行的价格。


当我们开始降低轨道空间的成本时,这家公司已不仅只是节约地球上出行的成本,它已经将星际间旅行成本的节约变成了现实。波音公司可能会担忧它正为马斯克的商业计划提供模式。马斯克不仅使用 BFR 进行地球到火星的飞行,他也看到使用 BFR 进行地球上飞行的可行性,这样速度会更快。


一趟飞行路线,甚至第次轨道飞行,绕着地球飞行比常规飞行都会更快。马斯克认为,在这种飞行轨迹下,人们可以在一个小时之内到达地球上的任何地方。这种飞行刚开始只有富人才能承受的起,但这种价格一定会降到和常规飞行差不多的价格。


马斯克所关注的长期未来的问题不仅仅是太空飞行的问题。气候变化、核战争、人们导致各种其它的灾难,而这些威胁在马斯克看来,从长期来看,都赶不上人工智能对人种的威胁程度。


2017 年 9 月,马斯克公开表明,他相信人工智能(以及在国家层面为追求人工智能的竞争主导优势)将最可能引发第三次世界大战。他说,这是比北朝鲜更大的威胁。在所有对人工智能持异的人中,马斯克是最坚决的,他的公司 OpenAI 将成立不久,一个月前,这个公司就干了一件其它人工智能都没有做过的事情。

盘活飞信,真的能让中国移动在社交领域翻身吗?

$
0
0

2017年10月,中国移动对外开始招标,将重新复活飞信,更名为“和飞信”,其中和飞信业务运营支撑服务项目招标金额达4764.6万,由此看出中国移动要利用飞信杀入移动社交工具的意图十分明显。

市场遭受挤压,移动盘活飞信进军社交领域

飞信是中国移动在2007年5月推出的通信服务产品,其功能主要包含语音、GPS定位、短信等多种通信功能。在互联网技术尚未成熟,互联网时代还未进入快车道之时,昂贵的上网费用让众多试图通过互联网来实现交流的用户望而却步。

在还未开化的互联网时代,电话语音通话和收发短信成为人们主要的线上社交方式。但在通信技术还未完全开化的时代,通话时间过长所产生的高额话费也令诸多手机用户苦不堪言,因此,相对于通话,费用便宜的短信则成为众多手机用户眼里的香饽饽。

而飞信出现,众多移动用户通过飞信就可以免费给好友发送短信的功能,更是掀起了手机用户通过短信交流的大浪潮。2012年第3季度,在国内移动IM市场活跃账户榜单中,手机飞信就以24.11%的市场份额领先于微信当年的17.58%。其用户规模在峰值时更是达到了5亿用户之多,被称为QQ最有竞争力的对手。

但随着腾讯将微信与QQ之间的转换通道逐渐成熟化打通之后,QQ用户通过QQ账号就可以登录微信的渠道得以实现,微信用户量也在QQ引流之后逐渐壮大;并且微信在实时语音交互、视频交互、分享生活点滴等社交功能上的优势较飞信更为明显,人们的社交方式发生改变,以短信为主的飞信在用户使用频次上也逐渐下降。

加之在移动通信领域,联通和电信在近几年的抢流大战中,纷纷迎合4G用户推出了流量优惠活动,帮助社交用户在社交软件上使用的数据流量提供保障之后,中国移动在通信领域的市场份额开始遭受挤压。

数据显示,2017年中国联通的4G用户数量达到1.7亿户,仅由联通大王卡产生的用户增量就超过了5000万户;而同期中国电信4G用户净增6017万户,累计用户数超过1.8亿户。其中,电信不限量套餐新增用户同样达到了惊人的5000万户。

在社交功能上,飞信不具备像微信那样的便捷多元的社交属性,而随着3G、4G时代的到来,用户在数据流量上的需求无法在中国移动上得以满足,联通和电信的不限流量模式则成为众多用户出逃的有力导向。在由社交功能和数据流量引发的用户流失问题不断加剧之后,中国移动在通信市场上的份额不断被挤压,其想要通过飞信收复失地实是必然之举。

物是人非,和飞信社交路上的荆棘

而在中国移动复盘飞信的消息公布之后,中国移动也公布了未来飞信的发展方向和新增功能。在发展方向上,新版飞信将会从原先的个人用户向企业客户进行转型;而在新增功能上,“定时消息”等新功能将会为和飞信用户带来全新的社交体验。并且会在原有的集团网业务上加以优化,为集团网用户提供独立数据流量收费标准。

虽然新版的和飞信在方向和功能上均做出了相应调整,中国移动对和飞信在社交市场上复盘抱有很大的希望,但是经过十年的发展,移动社交领域上的企业已如雨后春笋般林立而起,社交市场的格局也早已经从以腾讯的QQ、微信,旧版飞信为主的社交应用市场,逐渐转变为“一超多强”的多元化市场。因此在未来移动社交市场上,和飞信除了要面对QQ和微信这样传统的老对手之外,还将面对钉钉、新浪微博、网易易信等社交平台组合成的新市场格局。

一来,“老友”腾讯在熟人社交领域中跨年龄段的高渗透。在家庭、朋友等熟人社交领域上,微信和QQ两大社交平台的受众已经涵盖到大部分年龄段,拥有超高市场渗透率的腾讯社交平台,微信日活跃用户量已经超过9.5亿,而以95后、00后为主力军的QQ用户也有5亿之多。微信、QQ为用户带来的熟人社交便利让腾讯在移动社交时代占据了绝对优势。因此,中国移动要想通过盘活飞信来收复自己曾经在社交领域上的失地,在社交体系已经十分完善的微信和QQ面前并非轻而易举。

二来,心怀执念,阿里钉钉对企业社交来势汹汹。继来往在熟人社交领域败北之后,阿里在2014年又推出了主打企业社交的钉钉社交平台,钉钉的出现让诸多企业的员工将工作和生活分隔开来,逐渐形成了熟人社交之外的另一种社交模式。2017年12月底,阿里宣布钉钉用户量过亿,未来将面向全球企业社交市场。从来往到钉钉,阿里在社交产品上的投入力度不断加大,其想要在社交领域分得一杯羹已是司马昭之心。在未来社交领域中,与其说微信是未来飞信最大的竞争对手,不如说不断壮大的钉钉才是和飞信在企业社交上不容小觑的劲敌。

三来,微博和易信截断泛娱乐社交通道。在以陌生人为主的泛娱乐社交领域上,新浪微博和网易易信具有特色的社交功能更能满足用户的社交需求,两者均是介于熟人和陌生人之间的移动社交社区。用户在这两个平台上既可以与熟人分享生活趣事,又能与志同道合的用户建立新的社交关系,并且具有的短视频分享娱乐功能,能够满足用户泛娱乐社交需求。2017年,新浪微博宣布月活用户已达3亿,周边、热点等特色领域成为微博在社交抢流大战中功不可没;而网易与电信联手打造的易信在上线一年后也宣布用户过亿,通讯+娱乐社交模式也为易信在社交领域中积累更多粘性用户。

虽然中国移动在盘活和飞信之后一直将微信作为其未来社交领域中的第一劲敌,但是在企业社交上,钉钉在阿里的推动下已经逐渐步入正轨,同时能满足用户多元化社交需求的泛娱乐社交平台也将对和飞信造成不小的冲击。在这样多方割据的市场竞争格局下,和飞信从C端市场转像B端真的是可行之举吗?

创新方能让和飞信存活

从目前的通讯市场上看,虽然在经历了2017年联通大王卡和电信不限流量营销模式的强烈攻击之后,中国移动在移动通讯市场上的市场危机不断升级,但是中国移动凭借入局通讯领域较早的优势,仍有着联通、电信两家企业不可逾越的市场规模。中国通信网数据显示,截止2017年6月底,移动用户量约为8.67亿,其用户量和市场渗透率均是电信+联通用户总量的两倍。

未来,社交领域上的大战已经无法避免,而中国移动如何利用早期在市场积累的超高用户量和强大的市场渗透率,才能盘活飞信,打破当前以腾讯为首的“一超多强”的社交格局?

从历史来看,旧版飞信之所以取得成功,是基于用户在即时语音、短信的高消费场景下,用户对优惠甚至是免费的移动社交应用的需求。而在如今的社交领域中,能满足这样需求的社交应用琳琅满目,因此,创新成为和飞信重新杀入社交市场的唯一选择。

一方面,建立C端用户端口向和飞信引流。2018年,国内通讯领域的5G时代即将到来,各企业抢流大战也一触即发。对于通讯数据流量供应商的中国移动而言,这无疑是复盘和飞信的最佳时机,在满足用户对流量需求的前提条件下,利用5G技术加持和飞信,为消费用户提供全新的社交体验。同时加强5G技术对和飞信建设的优先性,实现用户、手机号、和飞信与5G技术的紧密相连。

另一方面,完善和飞信企业服务功能,明确未来走向。2017年极光大数据监测结果显示,2017年上半年,企业微信和钉钉均拥有较高的7天留存率,分别为81.7%和81.1%,而同期和飞信的7天留存率均值仅有不足70%。在相同的企业IM市场中,和飞信增加的文件传输留存期限和留存率不具有强有力优势,从IM市场上吸引更多企业入驻也就变得更加艰难。

同时,企业IM市场的社交应用均独具特色:有按管理者思路,自上而下打造的钉钉;也有因用户抱怨生活和工作混杂,自然延伸的企业微信;而企业易信则是倾向政府、企业用户……和飞信要想在企业IM领域中实现翻身,在完善其服务功能的同时,还要明确自身的运营和管理模式。

总体而言,随着消费者主导市场的能力日趋明显,传统以商家为主导的消费市场格局正在发生改变,用户流量已经成为判断某一企业是否拥有竞争力的重要风向标。而在这个流量为王的消费时代,企业只有始终维护消费者利益,为消费者提供优质体验的服务产品,才能在竞争日益激烈的市场中得以长存。

文/刘旷

The Open Session In View Anti-Pattern - Vlad Mihalcea

$
0
0
(Last Updated On: February 22, 2018)

Introduction

The Open Session in View is an Anti-Pattern, and this post is going to demonstrate why it is so. First of all, let’s start with the Wikipedia definition of an Anti-Pattern:

An anti-pattern (or antipattern) is a common response to a recurring problem that is usually ineffective and risks being highly counterproductive.

A LazyInitializationException band aid

When using JPA and Hibernate, the Fetching policy can have one of the biggest impacts on application performance, and, as explained in my High-Performance JDBC presentation, you should always fetch just as much data you need to fulfil the requirements of a given business logic use case. Fetching too many columns than necessary has an impact, and that’s why entities are not good candidates for read-only views. In turn, DTO projectionsare better suited for read-only data sets.

Entities are very useful for read-write transactions because you can benefit from the automatic dirty checking mechanismwhile preventing lost updates phenomenain multi-request logical transactions.

Unfortunately, many enterprise applications don’t make this distinction, and they rely solely on entities for both read-only and read-write transactions. Not only that an entity has more columns than a custom DTO projection, but the entity might have associations as well. Entity associations are convenient because it allows the application developer to access joined relationships without even needing to write a query.

Hibernate comes with Proxies that allow the application developer to defer fetching until the association is needed. This is very useful, especially from a performance perspective. The worst thing to do is to use EAGER associationsbecause, once a relationship is set to be eagerly fetched, it cannot be changed to being fetched lazily on a per query basis. For this reason, many associations are configured with the FetchType.LAZYattribute.

However, a LAZY association needs the Sessionto be opened in order to initialize the Proxy. If the Persistence Context is closed, when trying to access a non-initialized LAZY association, the infamous LazyInitializationExceptionis thrown.

For read-only views, when using DTO projections, we have to manually choose the child associations properties too, therefore, the LazyInitializationExceptioncannot occur. For read-write transactions, entities might be fetched with the intention of being modified and saved at the end of the currently running workflow. These entities are prone to LazyInitializationException(s), so there are good ways and bad ways of dealing with this issue.

It is only the business layer responsibility to fetch all the data that’s necessary for a particular business use case. For many-to-one and one-to-one associations, as well as to at most one one-to-manyrelationship, JOIN FETCHdirective is the best way of initializing the associations that are going to be needed in the view layer. For multiple one-to-manyassociations, to avoid a Cartesian Product, it’s necessary to use secondary queries. These secondary queries can be fired when the association is accessed for the first time, which can be done with the Hibernate.initialize(proxy)utility.

Open Session In View takes a different approach. Instead of letting the business layer decide how it’s best to fetch all the associations that are needed by the View layer, it forces the Persistence Context to stay open so that the View layer can trigger the Proxy initialization.

OpenSessionInView

  • The OpenSessionInViewFiltercalls the openSessionmethod of the underlying SessionFactoryand obtains a new Session.
  • The Sessionis bound to the TransactionSynchronizationManager.
  • The OpenSessionInViewFiltercalls the doFilterof the javax.servlet.FilterChainobject reference and the request is further processed
  • The DispatcherServletis called, and it routes the HTTP request to the underlying PostController.
  • The PostControllercalls the PostServiceto get a list of Postentities.
  • The PostServiceopens a new transaction, and the HibernateTransactionManagerreuses the same Sessionthat was opened by the OpenSessionInViewFilter.
  • The PostDAOfetches the list of Postentities without initializing any lazy association.
  • The PostServicecommits the underlying transaction, but the Sessionis not closed because it was opened externally.
  • The DispatcherServletstarts rendering the UI, which, in turn, navigates the lazy associations and triggers their initialization.
  • The OpenSessionInViewFiltercan close the Session, and the underlying database connection is released as well.

At a first glance, this might not look like a terrible thing to do, but, once you view it from a database perspective, a series of flaws start to become more obvious.

The service layer opens and closes a database transaction, but afterward, there is no explicit transaction going on. For this reason, every additional statement issued from the UI rendering phase is executed in auto-commit mode. Auto-commit puts pressure on the database server because each statement must flush the transaction log to disk, therefore causing a lot of I/O traffic on the database side. One optimization would be to mark the Connectionas read-only which would allow the database server to avoid writing to the transaction log.

There is no separation of concerns anymore because statements are generated both by the service layer and by the UI rendering process. Writing integration tests that assert the number of statements being generatedrequires going through all layers (web, service, DAO) while having the application deployed on a web container. Even when using an in-memory database (e.g. HSQLDB) and a lightweight web server (e.g. Jetty), these integration tests are going to be slower to execute than if layers were separated and the back-end integration tests used the database, while the front-end integration tests were mocking the service layer altogether.

The UI layer is limited to navigating associations which can, in turn, trigger N+1 query problems. Although Hibernate offers @BatchSizefor fetching associations in batches, and FetchMode.SUBSELECTto cope with this scenario, the annotations are affecting the default fetch plan, so they get applied to every business use case. For this reason, a data access layer query is much more suitable because it can be tailored to the current use case data fetch requirements.

Last but not least, the database connection is held throughout the UI rendering phase which increases connection lease time and limits the overall transaction throughput due to congestion on the database connection pool. The more the connection is held, the more other concurrent requests are going to wait to get a connection from the pool.

Read-life stories

After a long debate, it’s good that Spring Boot issues a warning id the Open Session In View mode is active.

If you enjoyed this article, I bet you are going to love my Bookand Video Coursesas well.

Conclusion

The Open Session in View is a solution to a problem that should not exist in the first place, and the most likely root cause is relying exclusively on entity fetching. If the UI layer only needs a view of the underlying data, then the data access layer is going to perform much better with a DTO projection.

A DTO projectionforces the application developer to fetch just the required data set and is not susceptible to LazyInitializationException(s). This way, the separation of concerns is no longer compromised, and performance optimizations can be applied at the data access layer level since all statements are confined to the boundaries of the currently executing transaction.

link:
https://blog.frankel.ch/the-opensessioninview-antipattern/

The best way to handle the LazyInitializationException - Vlad Mihalcea

$
0
0
(Last Updated On: January 29, 2018)

Introduction

The LazyInitializationExceptionis undoubtedly one of the most common exceptions you can get when using Hibernate. This article is going to summarize the best and the worst ways of handling lazy associations.

Fetching 101

With JPA, not only you can fetch entities from the database, but you can also fetch entity associations as well. For this reason, JPA defines two FetchTypestrategies:

  • EAGER
  • LAZY

The problem with EAGER fetching

EAGERfetching means that associations are always retrieved along with their parent entity. In reality, EAGER fetching is very bad from a performance perspectivebecause it’s very difficult to come up with a global fetch policy that applies to every business use case you might have in your enterprise application.

Once you have an EAGERassociation, there is no way you can make it LAZY. This way, the association will always be fetched even if the user does not necessarily need it for a particular use case. Even worse, if you forget to specify that an EAGER association needs to be JOIN FETCH-ed by a JPQL query, Hibernate is going to issue a secondary select for every uninitialized association, leading to N+1 query problems.

Unfortunately, JPA 1.0 decided that @ManyToOneand @OneToOneshould default to FetchType.EAGER, so now you have to explicitly mark these two associations as FetchType.LAZY:

@ManyToOne(fetch = FetchType.LAZY)
private Post post;

LAZY fetching

For this reason, it’s better to use LAZYassociations. A LAZYassociation is exposed via a Proxy, which allows the data access layer to load the association on demand. Unfortunately, LAZYassociations can lead to LazyInitializationException.

For our next example, we are going to use the following entities:

postpostcommentlazyinitializationexception

When executing the following logic:

List<PostComment> comments = null;

EntityManager entityManager = null;
EntityTransaction transaction = null;
try {
    entityManager = entityManagerFactory()
        .createEntityManager();
    transaction = entityManager.getTransaction();
    transaction.begin();

    comments = entityManager.createQuery(
        "select pc " +"from PostComment pc " +"where pc.review = :review", PostComment.class)
    .setParameter("review", review)
    .getResultList();

    transaction.commit();
} catch (Throwable e) {
    if (transaction != null && 
        transaction.isActive())
        transaction.rollback();
    throw e;
} finally {
    if (entityManager != null) {
        entityManager.close();
    }
}

try {
    for(PostComment comment : comments) {
        LOGGER.info(
            "The post title is '{}'", 
            comment.getPost().getTitle()
        );
    }
} catch (LazyInitializationException expected) {
    assertEquals("could not initialize proxy - no Session", 
        expected.getMessage()
    );
}

Hibernate is going to throw a LazyInitializationExceptionbecause the PostCommententity did not fetch the Postassociation while the EntityManagerwas still opened, and the Postrelationship was marked with FetchType.LAZY:

@ManyToOne(fetch = FetchType.LAZY)
private Post post;

How NOT to handle LazyInitializationException

Unfortunately, there are also bad ways of handling the LazyInitializationExceptionlike:

These two Anti-Patterns are very inefficient from a database perspective, so you should never use them in your enterprise application.

JOIN FETCH to the rescue

Entities are only needed when the current running application-level transactionneeds to modify the entities that are being fetched. Because of the automatic dirty checking mechanism, Hibernate makes it very easy to translate entity state transitionsinto SQL statements.

Considering that we need to modify the PostCommententities, and we also need the Postentities as well, we just need to use the JOIN FETCHdirective like in the following query:

comments = entityManager.createQuery("select pc " +"from PostComment pc " +"join fetch pc.post " +"where pc.review = :review", PostComment.class)
.setParameter("review", review)
.getResultList();

The JOIN FETCHdirective instructs Hibernate to issue an INNER JOIN so that Postentities are fetched along with the PostCommentrecords:

SELECT pc.id AS id1_1_0_ ,
       p.id AS id1_0_1_ ,
       pc.post_id AS post_id3_1_0_ ,
       pc.review AS review2_1_0_ ,
       p.title AS title2_0_1_
FROM   post_comment pc
INNER JOIN post p ON pc.post_id = p.id
WHERE  pc.review = 'Excellent!'

That’s it! It’s as simple as that!

DTO projection to the rescue

Now, we are not done yet. What if you don’t even want entities in the first place. If you don’t need to modify the data that’s being read, why would you want to fetch an entity in the first place? A DTO projectionallows you to fetch fewer columns and you won’t risk any LazyInitializationException.

For instance, we can have the following DTO class:

public class PostCommentDTO {

    private final Long id;

    private final String review;

    private final String title;

    public PostCommentDTO(
        Long id, String review, String title) {
        this.id = id;
        this.review = review;
        this.title = title;
    }

    public Long getId() {
        return id;
    }

    public String getReview() {
        return review;
    }

    public String getTitle() {
        return title;
    }
}

If the business logic only needs a projection, DTOs are much more suitable than entities. The previous query can be rewritten as follows:

List<PostCommentDTO> comments = doInJPA(entityManager -> {
    return entityManager.createQuery("select new " +"   com.vladmihalcea.book.hpjp.hibernate.fetching.PostCommentDTO(" +"       pc.id, pc.review, p.title" +"   ) " +"from PostComment pc " +"join pc.post p " +"where pc.review = :review", PostCommentDTO.class)
    .setParameter("review", review)
    .getResultList();
});

for(PostCommentDTO comment : comments) {
    LOGGER.info("The post title is '{}'", comment.getTitle());
}

And Hibernate can execute a SQL query which only needs to select threecolumns instead of five:

SELECT pc.id AS col_0_0_ ,
       pc.review AS col_1_0_ ,
       p.title AS col_2_0_
FROM   post_comment pc
INNER JOIN post p ON pc.post_id = p.id
WHERE  pc.review = 'Excellent!'

Not only that we got rid of the LazyInitializationException, but the SQL query is even more efficient. Cool, right?

If you enjoyed this article, I bet you are going to love my Bookand Video Coursesas well.

Conclusion

LazyInitializationExceptionis a code smell because it might hide the fact that entities are used instead of DTO projections. Sometimes, fetching entities is the right choice, in which case, a JOIN FETCHdirective is the simplest and the best way to initialize the LAZYHibernate proxies.


FastText 文本分类使用心得 - CSDN博客

$
0
0

最近在一个项目里使用了fasttext[1], 这是facebook今年开源的一个词向量与文本分类工具,在学术上没有什么创新点,但是好处就是模型简单,训练速度又非常快。我在最近的一个项目里尝试了一下,发现用起来真的很顺手,做出来的结果也可以达到上线使用的标准。

其实fasttext使用的模型与word2vec的模型在结构上是一样的,拿cbow来说,不同的只是在于word2vec cbow的目标是通过当前词的前后N个词来预测当前词,在使用层次softmax的时候,huffman树叶子节点处是训练语料里所有词的向量。

而fasttext在进行文本分类时,huffmax树叶子节点处是每一个类别标签的词向量,在训练的过程中,训练语料的每一个词也会得到对应的词向量,输入为一个window内的词对应的词向量,hidden layer为这几个词的线性相加,相加的结果作为该文档的向量,再通过层次softmax得到预测标签,结合文档的真实标签计算loss,梯度与迭代更新词向量。

fasttext有别于word2vec的另一点是加了ngram切分这个trick,将长词再通过ngram切分为几个短词,这样对于未登录词也可以通过切出来的ngram词向量合并为一个词。由于中文的词大多比较短,这对英文语料的用处会比中文语料更大。

此外,fasttext相比deep learning模型的优点是训练速度极快。我们目前使用fasttext来进行客户填写的订单地址到镇这一级别的分类。每一个省份建立一个模型,每个模型要分的类别都有1000多类,200万左右的训练数据,12个线程1分钟不到就可以训练完成,最终的分类准确率与模型鲁棒性都比较高(区县级别分类正确准确率高于99.5%, 镇级别高于98%),尤其是对缩写地名,或者漏写了市级行政区、区县级行政区的情况也都可以正确处理。

参数方面

  1. loss function选用hs(hierarchical softmax)要比ns(negative sampling) 训练速度要快很多倍,并且准确率也更高。

  2. wordNgrams 默认为1,设置为2以上可以明显提高准确率。

  3. 如果词数不是很多,可以把bucket设置的小一点,否则预留会预留太多bucket使模型太大。

因为facebook提供的只是C++版本的代码,原本还以为要自己封装一个python接口,结果上github一搜已经有封装的python接口了[2]。用起来特别方便,觉得还不能满足自己的使用要求,修改源码也非常方便。

对于同样的文本分类问题,后来还用单向LSTM做了一遍,输入pre-trained的embedding词向量,并且在训练的时候fine-tune,与fasttext对比,即使使用了GTX 980的GPU,训练速度还是要慢很多,并且,准确准确率和fasttext是差不多的。

所以对于文本分类,先用fasttext做一个简单的baseline是很适合的。

[1] https://github.com/facebookresearch/fastText
[2] https://github.com/salestock/fastText.py


NLP︱高级词向量表达(二)——FastText(简述、学习笔记) - CSDN博客

$
0
0

FastText是Facebook开发的一款快速文本分类器,提供简单而高效的文本分类和表征学习的方法,不过这个项目其实是有两部分组成的,一部分是这篇文章介绍的
fastText 文本分类(paper: A. Joulin, E. Grave, P. Bojanowski, T. Mikolov,
Bag of Tricks for Efficient Text
Classification(高效文本分类技巧)
),
另一部分是词嵌入学习(paper: P.
Bojanowski*, E. Grave*, A. Joulin, T. Mikolov, Enriching Word Vectors
with Subword
Information
(使用子字信息丰富词汇向量))。
按论文来说只有文本分类部分才是 fastText,但也有人把这两部分合在一起称为
fastText。笔者,在这即认为词嵌入学习属于FastText项目。
github链接: https://github.com/facebookresearch/fastText

.

高级词向量三部曲:

1、 NLP︱高级词向量表达(一)——GloVe(理论、相关测评结果、R&python实现、相关应用)
2、 NLP︱高级词向量表达(二)——FastText(简述、学习笔记)
3、 NLP︱高级词向量表达(三)——WordRank(简述)
4、其他NLP词表示方法paper: 从符号到分布式表示NLP中词各种表示方法综述


一、FastText架构

本节内容参考自:
1、开源中国社区 [ http://www.oschina.net]《Facebook 开源的快速文本分类器 FastTexT》
2、雷锋网文章:《 比深度学习快几个数量级,详解Facebook最新开源工具——fastText

.

1、fastText 架构原理

fastText 方法包含三部分:模型架构、层次 Softmax 和 N-gram 特征。

fastText 模型输入一个词的序列(一段文本或者一句话),输出这个词序列属于不同类别的概率。
序列中的词和词组组成特征向量,特征向量通过线性变换映射到中间层,中间层再映射到标签。
fastText 在预测标签时使用了非线性激活函数,但在中间层不使用非线性激活函数。
fastText 模型架构和 Word2Vec 中的 CBOW 模型很类似。不同之处在于,fastText 预测标签,而 CBOW 模型预测中间词。

这里写图片描述
.
.

2、改善运算效率——softmax层级

对于有大量类别的数据集,fastText使用了一个分层分类器(而非扁平式架构)。不同的类别被整合进树形结构中(想象下二叉树而非 list)。在某些文本分类任务中类别很多,计算线性分类器的复杂度高。为了改善运行时间,fastText 模型使用了层次 Softmax 技巧。层次 Softmax 技巧建立在哈弗曼编码的基础上,对标签进行编码,能够极大地缩小模型预测目标的数量。(参考 博客
这里写图片描述

考虑到线性以及多种类别的对数模型,这大大减少了训练复杂性和测试文本分类器的时间。fastText 也利用了类别(class)不均衡这个事实(一些类别出现次数比其他的更多),通过使用 Huffman 算法建立用于表征类别的树形结构。因此,频繁出现类别的树形结构的深度要比不频繁出现类别的树形结构的深度要小,这也使得进一步的计算效率更高。
这里写图片描述
.
.
.


二、FastText的词向量表征

1、FastText的N-gram特征

常用的特征是词袋模型。但词袋模型不能考虑词之间的顺序,因此 fastText 还加入了 N-gram 特征。
“我 爱 她” 这句话中的词袋模型特征是 “我”,“爱”, “她”。这些特征和句子 “她 爱 我” 的特征是一样的。
如果加入 2-Ngram,第一句话的特征还有 “我-爱” 和 “爱-她”,这两句话 “我 爱 她” 和 “她 爱 我” 就能区别开来了。当然,为了提高效率,我们需要过滤掉低频的 N-gram。

在 fastText 中一个低维度向量与每个单词都相关。隐藏表征在不同类别所有分类器中进行共享,使得文本信息在不同类别中能够共同使用。这类表征被称为词袋(bag of words)(此处忽视词序)。在 fastText中也使用向量表征单词 n-gram来将局部词序考虑在内,这对很多文本分类问题来说十分重要。

举例来说:fastText能够学会“男孩”、“女孩”、“男人”、“女人”指代的是特定的性别,并且能够将这些数值存在相关文档中。然后,当某个程序在提出一个用户请求(假设是“我女友现在在儿?”),它能够马上在fastText生成的文档中进行查找并且理解用户想要问的是有关女性的问题。
.
.

2、FastText词向量优势

(1)适合大型数据+高效的训练速度:能够训练模型“在使用标准多核CPU的情况下10分钟内处理超过10亿个词汇”,特别是与深度模型对比,fastText能将训练时间由数天缩短到几秒钟。使用一个标准多核 CPU,得到了在10分钟内训练完超过10亿词汇量模型的结果。此外, fastText还能在五分钟内将50万个句子分成超过30万个类别。
(2)支持多语言表达:利用其语言形态结构,fastText能够被设计用来支持包括英语、德语、西班牙语、法语以及捷克语等多种语言。它还使用了一种简单高效的纳入子字信息的方式,在用于像捷克语这样词态丰富的语言时,这种方式表现得非常好,这也证明了精心设计的字符 n-gram 特征是丰富词汇表征的重要来源。FastText的性能要比时下流行的word2vec工具明显好上不少,也比其他目前最先进的词态词汇表征要好。
这里写图片描述
(3)fastText专注于文本分类,在许多标准问题上实现当下最好的表现(例如文本倾向性分析或标签预测)。FastText与基于深度学习方法的Char-CNN以及VDCNN对比:
FastText与基于深度学习方法的Char-CNN以及VDCNN对比
(4)比word2vec更考虑了相似性,比如 fastText 的词嵌入学习能够考虑 english-born 和 british-born 之间有相同的后缀,但 word2vec 却不能(具体参考 paper)。
.
.

3、FastText词向量与word2vec对比

本节来源于博客: fasttext
FastText= word2vec中 cbow + h-softmax的灵活使用

灵活体现在两个方面:
1. 模型的输出层:word2vec的输出层,对应的是每一个term,计算某term的概率最大;而fasttext的输出层对应的是 分类的label。不过不管输出层对应的是什么内容,起对应的vector都不会被保留和使用;
2. 模型的输入层:word2vec的输出层,是 context window 内的term;而fasttext 对应的整个sentence的内容,包括term,也包括 n-gram的内容;

两者本质的不同,体现在 h-softmax的使用。
Wordvec的目的是得到词向量,该词向量 最终是在输入层得到,输出层对应的 h-softmax 也会生成一系列的向量,但最终都被抛弃,不会使用。
fasttext则充分利用了h-softmax的分类功能,遍历分类树的所有叶节点,找到概率最大的label(一个或者N个)

相关文章: Jupyter notebooks:Comparison of FastText and Word2Vec
.
.
.


三、FastText实现

github链接: https://github.com/facebookresearch/fastText
fastText基于Mac OS或者Linux系统构筑,使用 C++11 的特性。需要python 2.6 或者更高版本支持,以及numpy & scipy等软件支持。
FastText默认参数:

  $ ./fasttext supervised
Empty input or output path. The following arguments are mandatory: -input training file path -output output file path The following arguments are optional: -lr learning rate [0.1] -lrUpdateRate change the rate of updates for the learning rate [100] -dim size of word vectors [100] -ws size of the context window [5] -epoch number of epochs [5] -minCount minimal number of word occurences [1] -minCountLabel minimal number of label occurences [0] -neg number of negatives sampled [5] -wordNgrams max length of word ngram [1] -loss loss function {ns, hs, softmax} [ns] -bucket number of buckets [2000000] -minn min length of char ngram [0] -maxn max length of char ngram [0] -thread number of threads [12] -t sampling threshold [0.0001] -label labels prefix [__label__] -verbose verbosity level [2] -pretrainedVectors pretrained word vectors for supervised learning []

Mikolov 在 fastTetxt 的论文中报告了两个实验,其中一个实验和 Tagspace 模型进行对比。实验是在 YFCC100M 数据集上进行的, YFCC100M 数据集包含将近 1 亿张图片以及摘要、标题和标签。实验使用摘要和标题去预测标签。Tagspace 模型是建立在 Wsabie 模型的基础上的。Wsabie 模型除了利用 CNN 抽取特征之外,还提出了一个带权近似配对排序 (Weighted Approximate-Rank Pairwise, WARP) 损失函数用于处理预测目标数量巨大的问题。
这里写图片描述
上面就是实验结果,从实验结果来看 fastText 能够取得比 Tagspace 好的效果,并拥有无以伦比的训练测试速度。但严格来说,这个实验对 Tagspace 有些不公平。YFCC100M 数据集是关于多标记分类的,即需要模型能从多个类别里预测出多个类。Tagspace 确实是做多标记分类的;但 fastText 只能做多类别分类,从多个类别里预测出一个类。而评价指标 prec@1 只评价一个预测结果,刚好能够评价多类别分类。

YFCC100M 数据: https://research.facebook.com/research/fasttext/


.

延伸一:重磅:facebook公开了90种语言的Pre-trained word vectors

https://github.com/facebookresearch/fastText/blob/master/pretrained-vectors.md
可怕的facebook,用fasttext进行训练,使用默认参数,300维度

如何看待父亲发文怒斥网游:它害了一个年代的孩子? - 知乎

$
0
0
先说结论吧,养不教父之过。
我到现在还记得四年级时,我爸看到我进了网吧。

他没有当场把我拉出来,直接转头回了家。我知道他看到了我,可能因为我周围的朋友,他给我留了面子吧。

我做好了挨打的准备才回了家,毕竟那个年代因为进网吧挨打的孩子多了去了。

正在看报纸的父亲见我回家了,就收好报纸招呼我吃饭,我妈那天值班,父亲做了晚餐给我。

两个男人一句话都没有说的吃完了晚饭,然后例行看了会电视,我就去睡了。

第二天是周末,我爸把我叫起来,说带我去一个地方,我当时头就蒙了,难道是少管所???

我和父亲骑车去了郊外一个林场,环境很好的地方,空气清新,父亲开始给我讲,这是一个古战场,把当时的历史讲给了我听,还带我参观了一下当地一个小的展览馆。回来路上,父亲对我说,是不是发现其实现实里也有很多有趣的东西?

我说出来玩当然不错了,可也不能天天不上学出去玩吧。

父亲想了一会,说确实你每天上学都挺辛苦的。

在那以后,每天晚饭吃完,我和父亲看电视的时候,他都要开始给我讲故事,从阿拉法特的革命,到朝鲜半岛的局势。从罗马帝国的兴衰,到楚汉相争的经过。还根据热播的金庸电视里给我讲他认为其中的不足,帮我找到书籍,让我自己去看。

我中学时,已经读了部分资治通鉴,二十四史(主要的),金庸古龙的大部分名作,和不下二十本外国名著。四大名著里的三国和水浒更是读了不下五遍。初中特别喜欢的书有韩寒的一些小说,明朝那些事,还有马克吐温的书,另外我觉得钱钟书的小说也特别适合中学生看。

到了大学更是一发不可收,三体火之前,我已经被论坛大神推荐着读了两遍了。平凡的世界和白鹿原这类书,在大一就钻图书馆看完了,大学是最适合读书的年代,我很庆幸在这之前我就养成爱读书的习惯了。

虽然这么多年来,我也一直没有停过玩游戏。但说实话游戏对我来说就是一个消遣,而且是社交方面的,和朋友一起出去玩,去网吧五黑或者怎样。我一个人的时候,还是喜欢看书和看电影。

我喜欢相声,因为我爸那时候经常跟我一起看的节目就是相声,他喜欢让我笑,可能用其他的爱好吸引我是他认为的办法之一吧。



回想起来,我很感谢父亲那天在朋友面前给我留了面子,然后又用最完美的方法教育了我。

父亲后来也说,那天他基本没合眼,怪自己平时没有抽时间陪我,他也放弃了当时去外地的一个升职机会,为了能每天都陪我聊天。

说到底,沉迷虚拟世界的根本原因,就是现实生活对自己完全没有吸引力。

。。。。。。。。

评论里说的二十四史,这个是我表述不清晰了,我是指的主流的二十四史的历史书籍,全册的不可能看完的,大学想看也没大堆时间。

还有评论说我爸懂得多的,其实我爸是医生,可能平时涉猎比同龄人稍微多点,但是远远达不到在儿子面前口若悬河的地步,很多都是他提前准备的话题。而且我初中之后,我俩的聊天更多都是他在倾听我说,我去给他讲一些我的历史观世界观。直到现在,我爸有时候还会随时来一句:儿子,特朗普最近关税政策你怎么看?

。。。。大家讨论这么激烈,再说几句吧。。。

好多人在说如今父母根本没时间陪孩子,还拿还房贷说事。也有人说你不能指望每个父母都很博学,很会教育孩子。

真奇怪,你完全没时间陪孩子,也没有教育孩子的能力。那你为什么还要生????把他当宠物吗???

你心情好了,有时间了,抱着他玩一玩,逗逗他。

心情不好了,没时间了,就只管他吃喝拉撒睡。

这不就是养宠物吗??

使用 Spring Data JPA 简化 JPA 开发

$
0
0

Spring Data JPA 让一切近乎完美

通过前面的分析可以看出,Spring 对 JPA 的支持已经非常强大,开发者只需关心核心业务逻辑的实现代码,无需过多关注 EntityManager 的创建、事务处理等 JPA 相关的处理,这基本上也是作为一个开发框架而言所能做到的极限了。然而,Spring 开发小组并没有止步,他们再接再厉,于最近推出了 Spring Data JPA 框架,主要针对的就是 Spring 唯一没有简化到的业务逻辑代码,至此,开发者连仅剩的实现持久层业务逻辑的工作都省了,唯一要做的,就只是声明持久层的接口,其他都交给 Spring Data JPA 来帮你完成!

至此,读者可能会存在一个疑问,框架怎么可能代替开发者实现业务逻辑呢?毕竟,每一个应用的持久层业务甚至领域对象都不尽相同,框架是怎么做到的呢?其实这背后的思想并不复杂,比如,当你看到 UserDao.findUserById() 这样一个方法声明,大致应该能判断出这是根据给定条件的 ID 查询出满足条件的 User 对象。Spring Data JPA 做的便是规范方法的名字,根据符合规范的名字来确定方法需要实现什么样的逻辑。

接下来我们针对前面的例子进行改造,让 Spring Data JPA 来帮助我们完成业务逻辑。在着手写代码之前,开发者需要先  下载Spring Data JPA 的发布包(需要同时下载 Spring Data Commons 和 Spring Data JPA 两个发布包,Commons 是 Spring Data 的公共基础包),并把相关的依赖 JAR 文件加入到 CLASSPATH 中。

首先,让持久层接口 UserDao 继承 Repository 接口。该接口使用了泛型,需要为其提供两个类型:第一个为该接口处理的域对象类型,第二个为该域对象的主键类型。修改后的 UserDao 如下:

清单 12. Spring Data JPA 风格的持久层接口
1
2
3
public interface UserDao extends Repository<AccountInfo, Long> {
   public AccountInfo save(AccountInfo accountInfo);
}

然后删除 UserDaoImpl 类,因为我们前面说过,框架会为我们完成业务逻辑。最后,我们需要在 Spring 配置文件中增加如下配置,以使 Spring 识别出需要为其实现的持久层接口:

清单 13. 在 Spring 配置文件中启用扫描并自动创建代理的功能
1
2
3
4
<-- 需要在 <beans> 标签中增加对 jpa 命名空间的引用 -->
<jpa:repositoriesbase-package="footmark.springdata.jpa.dao"
entity-manager-factory-ref="entityManagerFactory"
transaction-manager-ref="transactionManager"/>

至此便大功告成了!执行一下测试代码,然后看一下数据库,新的数据已经如我们预期的添加到表中了。如果要再增加新的持久层业务,比如希望查询出给 ID 的 AccountInfo 对象,该怎么办呢?很简单,在 UserDao 接口中增加一行代码即可:

清单 14. 修改后的持久层接口,增加一个方法声明
1
2
3
4
5
6
7
public interface UserDao extends Repository<AccountInfo, Long> {
 
public AccountInfo save(AccountInfo accountInfo);
 
// 你需要做的,仅仅是新增如下一行方法声明
public AccountInfo findByAccountId(Long accountId);
}

下面总结一下使用 Spring Data JPA 进行持久层开发大致需要的三个步骤:

  1. 声明持久层的接口,该接口继承 Repository,Repository 是一个标记型接口,它不包含任何方法,当然如果有需要,Spring Data 也提供了若干 Repository 子接口,其中定义了一些常用的增删改查,以及分页相关的方法。
  2. 在接口中声明需要的业务方法。Spring Data 将根据给定的策略(具体策略稍后讲解)来为其生成实现代码。
  3. 在 Spring 配置文件中增加一行声明,让 Spring 为声明的接口创建代理对象。配置了 <jpa:repositories> 后,Spring 初始化容器时将会扫描 base-package 指定的包目录及其子目录,为继承 Repository 或其子接口的接口创建代理对象,并将代理对象注册为 Spring Bean,业务层便可以通过 Spring 自动封装的特性来直接使用该对象。

此外,<jpa:repository> 还提供了一些属性和子标签,便于做更细粒度的控制。可以在 <jpa:repository> 内部使用 <context:include-filter>、<context:exclude-filter> 来过滤掉一些不希望被扫描到的接口。具体的使用方法见  Spring参考文档

应该继承哪个接口?

前面提到,持久层接口继承 Repository 并不是唯一选择。Repository 接口是 Spring Data 的一个核心接口,它不提供任何方法,开发者需要在自己定义的接口中声明需要的方法。与继承 Repository 等价的一种方式,就是在持久层接口上使用 @RepositoryDefinition 注解,并为其指定 domainClass 和 idClass 属性。如下两种方式是完全等价的:

清单 15. 两种等价的继承接口方式示例
1
2
3
4
public interface UserDao extends Repository<AccountInfo, Long> { …… }
 
@RepositoryDefinition(domainClass = AccountInfo.class, idClass = Long.class)
public interface UserDao { …… }

如果持久层接口较多,且每一个接口都需要声明相似的增删改查方法,直接继承 Repository 就显得有些啰嗦,这时可以继承 CrudRepository,它会自动为域对象创建增删改查方法,供业务层直接使用。开发者只是多写了 "Crud" 四个字母,即刻便为域对象提供了开箱即用的十个增删改查方法。

但是,使用 CrudRepository 也有副作用,它可能暴露了你不希望暴露给业务层的方法。比如某些接口你只希望提供增加的操作而不希望提供删除的方法。针对这种情况,开发者只能退回到 Repository 接口,然后到 CrudRepository 中把希望保留的方法声明复制到自定义的接口中即可。

分页查询和排序是持久层常用的功能,Spring Data 为此提供了 PagingAndSortingRepository 接口,它继承自 CrudRepository 接口,在 CrudRepository 基础上新增了两个与分页有关的方法。但是,我们很少会将自定义的持久层接口直接继承自 PagingAndSortingRepository,而是在继承 Repository 或 CrudRepository 的基础上,在自己声明的方法参数列表最后增加一个 Pageable 或 Sort 类型的参数,用于指定分页或排序信息即可,这比直接使用 PagingAndSortingRepository 提供了更大的灵活性。

JpaRepository 是继承自 PagingAndSortingRepository 的针对 JPA 技术提供的接口,它在父接口的基础上,提供了其他一些方法,比如 flush(),saveAndFlush(),deleteInBatch() 等。如果有这样的需求,则可以继承该接口。

上述四个接口,开发者到底该如何选择?其实依据很简单,根据具体的业务需求,选择其中之一。笔者建议在通常情况下优先选择 Repository 接口。因为 Repository 接口已经能满足日常需求,其他接口能做到的在 Repository 中也能做到,彼此之间并不存在功能强弱的问题。只是 Repository 需要显示声明需要的方法,而其他则可能已经提供了相关的方法,不需要再显式声明,但如果对 Spring Data JPA 不熟悉,别人在检视代码或者接手相关代码时会有疑惑,他们不明白为什么明明在持久层接口中声明了三个方法,而在业务层使用该接口时,却发现有七八个方法可用,从这个角度而言,应该优先考虑使用 Repository 接口。

前面提到,Spring Data JPA 在后台为持久层接口创建代理对象时,会解析方法名字,并实现相应的功能。除了通过方法名字以外,它还可以通过如下两种方式指定查询语句:

  1. Spring Data JPA 可以访问 JPA 命名查询语句。开发者只需要在定义命名查询语句时,为其指定一个符合给定格式的名字,Spring Data JPA 便会在创建代理对象时,使用该命名查询语句来实现其功能。
  2. 开发者还可以直接在声明的方法上面使用 @Query 注解,并提供一个查询语句作为参数,Spring Data JPA 在创建代理对象时,便以提供的查询语句来实现其功能。

下面我们分别讲述三种创建查询的方式。

通过解析方法名创建查询

通过前面的例子,读者基本上对解析方法名创建查询的方式有了一个大致的了解,这也是 Spring Data JPA 吸引开发者的一个很重要的因素。该功能其实并非 Spring Data JPA 首创,而是源自一个开源的 JPA 框架 Hades,该框架的作者 Oliver Gierke 本身又是 Spring Data JPA 项目的 Leader,所以把 Hades 的优势引入到 Spring Data JPA 也就是顺理成章的了。

框架在进行方法名解析时,会先把方法名多余的前缀截取掉,比如 find、findBy、read、readBy、get、getBy,然后对剩下部分进行解析。并且如果方法的最后一个参数是 Sort 或者 Pageable 类型,也会提取相关的信息,以便按规则进行排序或者分页查询。

在创建查询时,我们通过在方法名中使用属性名称来表达,比如 findByUserAddressZip ()。框架在解析该方法时,首先剔除 findBy,然后对剩下的属性进行解析,详细规则如下(此处假设该方法针对的域对象为 AccountInfo 类型):

  • 先判断 userAddressZip (根据 POJO 规范,首字母变为小写,下同)是否为 AccountInfo 的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,继续第二步;
  • 从右往左截取第一个大写字母开头的字符串(此处为 Zip),然后检查剩下的字符串是否为 AccountInfo 的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,则重复第二步,继续从右往左截取;最后假设 user 为 AccountInfo 的一个属性;
  • 接着处理剩下部分( AddressZip ),先判断 user 所对应的类型是否有 addressZip 属性,如果有,则表示该方法最终是根据 "AccountInfo.user.addressZip" 的取值进行查询;否则继续按照步骤 2 的规则从右往左截取,最终表示根据 "AccountInfo.user.address.zip" 的值进行查询。

可能会存在一种特殊情况,比如 AccountInfo 包含一个 user 的属性,也有一个 userAddress 属性,此时会存在混淆。读者可以明确在属性之间加上 "_" 以显式表达意图,比如 "findByUser_AddressZip()" 或者 "findByUserAddress_Zip()"。

在查询时,通常需要同时根据多个属性进行查询,且查询的条件也格式各样(大于某个值、在某个范围等等),Spring Data JPA 为此提供了一些表达条件查询的关键字,大致如下:

  • And --- 等价于 SQL 中的 and 关键字,比如 findByUsernameAndPassword(String user, Striang pwd);
  • Or --- 等价于 SQL 中的 or 关键字,比如 findByUsernameOrAddress(String user, String addr);
  • Between --- 等价于 SQL 中的 between 关键字,比如 findBySalaryBetween(int max, int min);
  • LessThan --- 等价于 SQL 中的 "<",比如 findBySalaryLessThan(int max);
  • GreaterThan --- 等价于 SQL 中的">",比如 findBySalaryGreaterThan(int min);
  • IsNull --- 等价于 SQL 中的 "is null",比如 findByUsernameIsNull();
  • IsNotNull --- 等价于 SQL 中的 "is not null",比如 findByUsernameIsNotNull();
  • NotNull --- 与 IsNotNull 等价;
  • Like --- 等价于 SQL 中的 "like",比如 findByUsernameLike(String user);
  • NotLike --- 等价于 SQL 中的 "not like",比如 findByUsernameNotLike(String user);
  • OrderBy --- 等价于 SQL 中的 "order by",比如 findByUsernameOrderBySalaryAsc(String user);
  • Not --- 等价于 SQL 中的 "! =",比如 findByUsernameNot(String user);
  • In --- 等价于 SQL 中的 "in",比如 findByUsernameIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;
  • NotIn --- 等价于 SQL 中的 "not in",比如 findByUsernameNotIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;

使用 @Query 创建查询

@Query 注解的使用非常简单,只需在声明的方法上面标注该注解,同时提供一个 JP QL 查询语句即可,如下所示:

清单 16. 使用 @Query 提供自定义查询语句示例
1
2
3
4
5
6
7
8
9
public interface UserDao extends Repository<AccountInfo, Long> {
 
@Query("select a from AccountInfo a where a.accountId = ?1")
public AccountInfo findByAccountId(Long accountId);
 
   @Query("select a from AccountInfo a where a.balance > ?1")
public Page<AccountInfo> findByBalanceGreaterThan(
Integer balance,Pageable pageable);
}

很多开发者在创建 JP QL 时喜欢使用命名参数来代替位置编号,@Query 也对此提供了支持。JP QL 语句中通过": 变量"的格式来指定参数,同时在方法的参数前面使用 @Param 将方法参数与 JP QL 中的命名参数对应,示例如下:

清单 17. @Query 支持命名参数示例
1
2
3
4
5
6
7
8
9
10
11
public interface UserDao extends Repository<AccountInfo, Long> {
 
public AccountInfo save(AccountInfo accountInfo);
 
@Query("from AccountInfo a where a.accountId = :id")
public AccountInfo findByAccountId(@Param("id")Long accountId);
 
  @Query("from AccountInfo a where a.balance > :balance")
  public Page<AccountInfo> findByBalanceGreaterThan(
@Param("balance")Integer balance,Pageable pageable);
}

此外,开发者也可以通过使用 @Query 来执行一个更新操作,为此,我们需要在使用 @Query 的同时,用 @Modifying 来将该操作标识为修改查询,这样框架最终会生成一个更新的操作,而非查询。如下所示:

清单 18. 使用 @Modifying 将查询标识为修改查询
1
2
3
@Modifying
@Query("update AccountInfo a set a.salary = ?1 where a.salary < ?2")
public int increaseSalary(int after, int before);

通过调用 JPA 命名查询语句创建查询

命名查询是 JPA 提供的一种将查询语句从方法体中独立出来,以供多个方法共用的功能。Spring Data JPA 对命名查询也提供了很好的支持。用户只需要按照 JPA 规范在 orm.xml 文件或者在代码中使用 @NamedQuery(或 @NamedNativeQuery)定义好查询语句,唯一要做的就是为该语句命名时,需要满足”DomainClass.methodName()”的命名规则。假设定义了如下接口:

清单 19. 使用 JPA 命名查询时,声明接口及方法时不需要什么特殊处理
1
2
3
4
5
6
public interface UserDao extends Repository<AccountInfo, Long> {
 
......
   
public List<AccountInfo> findTop5();
}

如果希望为 findTop5() 创建命名查询,并与之关联,我们只需要在适当的位置定义命名查询语句,并将其命名为 "AccountInfo.findTop5",框架在创建代理类的过程中,解析到该方法时,优先查找名为 "AccountInfo.findTop5" 的命名查询定义,如果没有找到,则尝试解析方法名,根据方法名字创建查询。

创建查询的顺序

Spring Data JPA 在为接口创建代理对象时,如果发现同时存在多种上述情况可用,它该优先采用哪种策略呢?为此,<jpa:repositories> 提供了 query-lookup-strategy 属性,用以指定查找的顺序。它有如下三个取值:

  • create --- 通过解析方法名字来创建查询。即使有符合的命名查询,或者方法通过 @Query 指定的查询语句,都将会被忽略。
  • create-if-not-found --- 如果方法通过 @Query 指定了查询语句,则使用该语句实现查询;如果没有,则查找是否定义了符合条件的命名查询,如果找到,则使用该命名查询;如果两者都没有找到,则通过解析方法名字来创建查询。这是 query-lookup-strategy 属性的默认值。
  • use-declared-query --- 如果方法通过 @Query 指定了查询语句,则使用该语句实现查询;如果没有,则查找是否定义了符合条件的命名查询,如果找到,则使用该命名查询;如果两者都没有找到,则抛出异常。

Spring Data JPA 对事务的支持

默认情况下,Spring Data JPA 实现的方法都是使用事务的。针对查询类型的方法,其等价于 @Transactional(readOnly=true);增删改类型的方法,等价于 @Transactional。可以看出,除了将查询的方法设为只读事务外,其他事务属性均采用默认值。

如果用户觉得有必要,可以在接口方法上使用 @Transactional 显式指定事务属性,该值覆盖 Spring Data JPA 提供的默认值。同时,开发者也可以在业务层方法上使用 @Transactional 指定事务属性,这主要针对一个业务层方法多次调用持久层方法的情况。持久层的事务会根据设置的事务传播行为来决定是挂起业务层事务还是加入业务层的事务。具体 @Transactional 的使用,请参考  Spring的参考文档

为接口中的部分方法提供自定义实现

有些时候,开发者可能需要在某些方法中做一些特殊的处理,此时自动生成的代理对象不能完全满足要求。为了享受 Spring Data JPA 带给我们的便利,同时又能够为部分方法提供自定义实现,我们可以采用如下的方法:

  • 将需要开发者手动实现的方法从持久层接口(假设为 AccountDao )中抽取出来,独立成一个新的接口(假设为 AccountDaoPlus ),并让 AccountDao 继承 AccountDaoPlus;
  • 为 AccountDaoPlus 提供自定义实现(假设为 AccountDaoPlusImpl );
  • 将 AccountDaoPlusImpl 配置为 Spring Bean;
  • 在 <jpa:repositories> 中按清单 19 的方式进行配置。
清单 20. 指定自定义实现类
1
2
3
4
5
<jpa:repositoriesbase-package="footmark.springdata.jpa.dao">
<jpa:repositoryid="accountDao"repository-impl-ref=" accountDaoPlus "/>
</jpa:repositories>
 
<beanid="accountDaoPlus"class="......."/>

此外,<jpa:repositories > 提供了一个 repository-impl-postfix 属性,用以指定实现类的后缀。假设做了如下配置:

清单 21. 设置自动查找时默认的自定义实现类命名规则
1
2
<jpa:repositoriesbase-package="footmark.springdata.jpa.dao"
repository-impl-postfix="Impl"/>

则在框架扫描到 AccountDao 接口时,它将尝试在相同的包目录下查找 AccountDaoImpl.java,如果找到,便将其中的实现方法作为最终生成的代理类中相应方法的实现。

你不愿意停止工作,可能是因为没人爱你

$
0
0

曾经有一位著名的经济学家,曾经预言到 2028 年,我们每个人都将不再需要为赚钱烦恼,到那时我们每个人每天只需要工作 3 小时。这位经济学家,就是被称为“资本主义救星”的英国经济学家凯恩斯。

这样的 2028 年,你觉得会到来吗?

凯恩斯认为,在不惜一切进行原始积累的阶段过去了之后,人们终将从疯狂的工作劳动中解放出来,获得大把的空闲时间。(as cited in, Kolbert, 2014)。

不知道 2028 年世界会不会发生一个剧变,至少目前,我们比起几十年前已经是更加忙碌了。

一项美国的调查显示,尤其在投行、咨询、IT、律师等高薪领域中, 94%的人每周工作 50 小时以上,超过半数的人每周工作 65 小时以上,而且,这还不包括他们在办公室以外的地方,用手机处理公务的时间(Perlow & Poter, 2009)。

有趣的是,当大家都以为不停加班都只是因为工作压力、被逼无奈时,《纽约客》的专栏作家 Surowiecki(2014)却指出, 大部分人的持续忙碌,其实都是自己主动选择的。

而在这种自主选择的忙碌背后,可能是一种深深的焦虑感,一旦停止忙碌,人们就会身陷其中。

对于许多超时工作、不停加班的人而言,“不忙就焦虑”是他们普遍的困扰,但其背后的原因却是不尽相同的。正如我们曾提到过的,焦虑,是一枚情绪的通用货币,每个人的焦虑背后,都可能包含了千差万别的认知想法与情绪需求。

A 款焦虑:对被需要的渴望

无论你是否承认,每个人都或多或少需要“被需要”。 这种感觉,会让我们获得价值感与力量感——“我有能力帮助他人实现愿望”、“我受他人重视和感激”, 还会让我们直观感受到自己与世界上其他个体的联结。

对于 A 款“不忙碌焦虑”的人群来说, 你也许没有意识到,其实你需要的不是工作,而是在工作中被人需要的人际满足感。

他们在家庭和感情生活中,很难感受到“被需要”。只有在工作的忙碌中,才能体会人际互动、以及他人对自己的依赖和肯定。因此,一旦停止忙碌,他们就会不自觉地陷入一种莫名的焦虑。其实,他们是用焦虑掩盖了内心最深处的恐惧——潜意识中, 他们怀疑自己在工作以外的世界里,不会被需要、也不会被爱。在工作以外的世界里,他们感到自己失去价值,被他人和世界所遗忘。

他们以为自己享受的是忙碌,其实是人间烟火和温情脉脉。

B 款焦虑:误把成功与忙碌划等号

移动互联网的普及,催生了“永远在线”(always on)的职场文化,我们的工作和生活也早已不存在绝对的区隔,在周末或度假的时候收发邮件、随时随地处理工作是常态。不妨试着回想一下,你上一次可以“完全不处理任何工作”的时间是什么时候?

这种职场文化带来的是人们对于“忙碌”与“休息”看法的改变。越来越多的雇主与员工都开始认为 “不停忙碌才意味着尽职尽责”、“休息就是消极怠惰”、“越是忙碌的人,对公司价值越高”等等。在这种职场文化中, 忙碌,逐渐被与“尽职”、“成功”画上了等号。

永远在线的职场文化,让每个人都感染上了一种竞争压力。 如果不这么忙,自己会不会就变成一个失败者?没出息的人?就算自己并不想忙碌,一旦悠闲下来,也可能真的被老板和他人评价为 “懒惰”、“不尽责”、“不够优秀”。

这个社会对于人忙碌程度的要求已经不再合理了。

C 款焦虑:一种深刻的存在主义绝望(existential despair)

人们无时无刻忙碌的另一个原因,可能来自一种存在主义绝望。生活的意义,工作的目标,他人的期待等等,这些使得我们保持忙碌的事物,无论多么世俗,都令我们的“存在感”/ 生命意义感得以存续(Tsilimparis, 2018)。

Tsilimparis(2018)认为 当不再有这些可以让自己去努力和付出的事情时,人们很容易陷入对于自我有限性的过度思考之中。我们可能会强烈地感受到生而为人的平凡与渺小,怀疑生命存在的意义与价值,继而陷入一种巨大的、难以承受的绝望。

芝加哥大学的 Hsee 等人(2010)的实验也从某种程度上证明了这一点。

他们邀请了一群参与者完成 2 个任务。这两个任务之间有 15 分钟的休息时间,参与者需要在这段时间里将任务一中填写的调查表交还到指定地点。此时,这些参与者可以在两个制定地点中任选其一:

  • “远”:12 分钟在路上,3 分钟等待下一个任务
  • “近”:就在门口交表,15 分钟等待下一个任务

结果,大多数人选择离自己较远的地点交表格,力求减少一个人无所事事独自等待的时间。 人在纯粹无事可做的独处中,是很容易感到不舒服的。实验结果也证明,走了更远路的被试,在情绪反馈表上,比那些走得短但一直在等待的人,心情更加愉悦。

和对人际温暖的需求相似又略有区别。C 款不工作就焦虑的同学们,是用忙碌逃避一种停下来就是笼罩在身上的无意义感。人会因为过度思考“我为什么活着”这一类存在主义的问题而产生负面感受。人很容易在这样直面自身的过程中,陷入到虚无感中。“瞎忙”是很多人躲避陷入虚无感的自我保护手段,忙工作忙朋友聚餐忙四处旅行。

除此之外, 还有一些人比其他人更容易在停止忙碌之后倍感焦虑

重点人群 1 型:讨好者

他们总是忍不住想取悦他人。他们会在讨好别人的过程中表现出过度的责任心,试图让所有人都满意,也试图为所有人的工作负责。这就不可避免地会让他们陷入过度的忙碌之中,且一旦停止忙碌,他们就开始担心他人会对自己不满。

重点人群 2 型: 情绪无能者(爱无能的人)

Damaske 等人(2014)的研究发现, 越来越多的人正把办公室当做情感寄托,他们不寻找生活伴侣,或者不投入太多精力在家庭中。办公室对他们来说是更舒服的场景。 对于情绪无能的人来说,更是如此。

我们曾介绍过,“情绪无能”的人对于深刻的爱、或深层的情感交流不感兴趣也无所适从。他们不明白自己的情绪是什么,也不擅长共情他人的感受,也不知道如何沟通情绪和感受。于是,他们情愿把时间和精力花费在无需情感投入的工作上,这样自己就拥有了“我没时间处理感情”的正当理由。

第 1 款恶果:

情感瘫痪(Emotional Basket Cases)

身处被焦虑感支配的忙碌之中,人们在精神上和身体上都很难真正放松。有研究发现,那些工作时间更长的人,需要更长的时间才能从紧张的状态中真正放松下来,让身心得到修复(Virtanen, 2009)。

Gorden(2014)指出,在身体与心理长时间超负荷的工作下,人们很容易陷入 情感瘫痪,即在人际间解读情绪的能力急剧下降,不能觉察到自己和他人的情绪需求,甚至也很容易误读他人的情绪,与他人产生误会与摩擦。

比如,陷入情感瘫痪的人,常常不能意识到自己已经处在一种暴躁易怒的情绪当中,并且不自觉地说出了许多伤人的话,他们也无法从对方的表现里“读出”自己的话已经造成的伤害。

而这往往给人们的社交关系带来很大的影响,导致伴侣、同事及家人朋友之间的失和,甚至关系的彻底破裂。

第 2 款恶果:

你会变胖、变笨

正如我们在“情绪性进食”的文章中所提到的那样,当我们焦虑的时候,我们会试图吃点什么来给自己安慰。又因为我们正被这种焦虑感支配的忙不迭,我们往往只能选择一些方便易得的外卖或快餐来满足口欲。于是,肥胖,就成为了忙碌的另一个代价。

不仅如此,还有研究发现, 连续 5 年处于忙碌状态(每周工作超过 55 小时)的人,他们的大脑认知功能可能会下降,即他们在词汇、推理、记忆与运算速度上都比 5 年前有明显的下降;对照组中不那么忙碌的被试,在 5 年前后的区别远没有这么明显(Virtanen, 2009)。也就是说,过度忙碌还会让人变笨。

第 3 款恶果:

切换任务时反复消耗的认知成本

另外,为了让自己忙起来,我们还可能陷入一种不必要的“多线程工作”(multi-tasking)。比如,一个人明明可以先完成 A 项任务,再进行 B 任务。但 Ta 为了逃避焦虑感,就可能会在完成 A 任务的过程中,给自己穿插着安排 B 任务一起做,让自己处于不必要的多线程工作中。

这种不必要的多线程工作,会让我们产生一种“虚假的效能感”——自我感觉良好,感到自己很努力——但往往实际效率不高,工作质量也受到影响。

这是因为 每当人们从 A 任务转换到 B 任务中时,他们的注意力都仍有一部分被“残留”(attention residue)在了 A 任务之中(Leroy, 2009)。 每一次转换任务,都是有成本的(shifting cost),是对一个人认知资源与注意力的消耗。这就是为什么人们很容易“忙中出错”的原因(Dahl, 2015)。

首先,你需要意识到自己是上述哪一款焦虑宝宝。你用工作在逃避什么?是逃避人际中的孤独感?是担心影响别人对你的评价?是逃避一种停下来之后的空虚感?你的忙于工作,是不是因为感到自己不被人真心所爱、不被人保护、不被人需要。所以忙碌成为了一种替代性的可以让生活有充实感、幸福感的途径。

其次,你需要明白, 忙碌只不过是暂时缓解了焦虑感,但它可能带来更多长期的后果,比如,上文中提到的过度忙碌可能使人情感瘫痪,最终导致的人际关系的失和,甚至彻底破裂等等。

另外,你也要学会享受任务间歇的休息时间,不要总想一刻不停。有研究发现, 在工作期间进行 15~30 分钟的小睡,有助于提升记忆力,并且能让人在睡觉的期间及时“清空”大脑,减少注意力残留,为之后接触新的信息作准备(Soong, 2010)。

最后,对于那些长期与存在主义绝望对抗的人而言,人和人之间真正的情感联结才是你获得生命意义感的来源。这种情感的联结,是需要你付出尝试——至少要有机会不断接触到新的人,同时双方共同尝试走近对方、信任对方,才最终慢慢达成的。这个过程对于很多优秀工作者来说,可比做好工作难太多了。

人们都喜欢做自己擅长的人,而倾向于躲避自己的表现成绩不够好的任务。这些优秀的工作者,更不喜欢面对“我不足够优秀”的批评和自我批评。所以他们不断选择工作,放弃人与人之间的经营。最后前者越做越拿手,后者越来越落后同龄其他人群。最终形成恶性循环。

最终,我们都得面对自己真实的、全面的需要。只有当你的自我价值感和幸福感,来自于各种不同的来源时——工作、家庭、朋友、爱好等等——你的幸福才不是高空走高丝般如履薄冰,也不是有一方面出问题就能让你粉碎。

如果你是一个一停止忙碌就焦虑的人,是时候让自己停一段时间了。想一想,你缺的到底是什么,你工作最终渴望的生活目标是什么?不要畏难,选择自己最薄弱的方面做做练习、成长提升。

忙的正面意义只存在于当它真的能把你引向更好的生活时。而什么是好生活,对每个人来说的定义都是很个人的。没有人能帮你回答这个问题,包括所有会因为你看起来不够忙批判你的人。你要自己回答好这个问题,然后才能找到真正适合你的工作与生活的节奏。

以上。

混得不好,不用自责:研究表明运气对成功的影响超乎你想象

$
0
0

条条大路通罗马,但有的人就住罗马。来源: scientific american


这世界上绝大多数的成功读物都会孜孜不倦地教导你:只要努力,就能成功。但无论是科学研究还是社会经验都告诉我们,这并不是一个靠谱的结论。最近一组意大利的研究人员发现,那些平凡却幸运的个体,要比有天赋而不幸的个体更加成功。换言之, 很多取得巨大成就的人,他们也许并非具有过人的才能,而只是运气特别好罢了。这一结论可以帮助我们建立更加公平高效的社会机制。


作者 | Scott Barry Kaufman

翻译 | 施怿

编辑 | 王妍琳


想获得成功要具备什么条件?成功人士都有那些秘诀?从《成功》、《福布斯》、《企业家》等杂志的流行程度来看,人们对成功这一话题从不乏热情。一种深层次的假设认为: 成功是可以习得的。这一假设基于成功人士身上具备的、促使他们走到今天的那些个性特征,例如天赋、才能、意志力、勤奋、韧性、乐观、成长型思维以及情商。这一假设不仅是这些成功学杂志得以流行的基础,也影响了我们的社会进行资源分配的方式。从工作机会到荣誉,再到政府补助,再到公共政策决策, 我们都习惯于假设最成功的人也是最能干的,并将资源分配给那些有成功过往的人,而倾向于忽略那些不成功的人


但这一假设正确吗?在整个职业生涯中,我一直致力于研究能预测成就和创造力的心理特征。虽然我已经发现,有一些心理特征(例如:激情、毅力、想象力、求知欲和开放性)确实能很好地解释成功之间的差异,但我更感兴趣的是,有多少差异是这些特征无法解释的。


近几年里,有不少研究和书籍都认为, 在包括金融交易、商业、体育、艺术、音乐、文学和科学在内的多个领域中,运气和机会可能比我们以为的更重要。他们的观点是:虽然天赋也很重要,但数据表明,在试图找出成功的决定因素时,如果我们只专注于个人特征,那么就会错过成功图景中真正重要的一片拼图。


以下是一些新发现:

全世界人民的收入差异有一半可以由他们所在的居住国和该国的收入分配差异来解释;


科研成果的影响力是随机分布的,在科研生涯中,仅高生产力这一个因素对高影响力的研究成果产生的影响是有限的;


能否成为CEO会受到你叫什么名字或出生在几月的影响,在六月或七月出生的CEO比其他月份要少得多;


姓氏首字母在字母表中更靠前的人更有可能获得最高部门的职位,有中间名缩写的人更容易在智力和成就方面获得更多的正面评价;


名字更易拼写的人比名字难拼写的人更容易获得肯定;


女性姓名听起来更阳刚,则更易在法律职业生涯中获得成功。


运气这一隐藏维度的重要性引出了一个有趣的问题:我们社会中那些成功人士取得了成就,仅仅是因为他们比较幸运吗?这一假设哪怕只是部分正确,都将对我们如何分配有限的资源产生重大影响,也将帮助富人和成功人士更有效地回报社会。


为了试图阐明这一重大问题,意大利物理学家Allesandro Pluchino、Andrea Raspisarda和意大利经济学家Alessio Biondo组成研究小组,第一次尝试量化运气和天赋对成功的影响。在他们开创性的工作中,他们提醒那些“天真的精英”, 人们低估了随机因素的作用,而实际上并没有把荣誉和奖励赋予最有能力的人。为了进一步解释这一现象,他们提出了“玩具数学模型”,模拟了一群人在40年的工作生涯中(从20岁到60岁)职业的发展变化。


模拟初始化设定图(N=1000)

图片来源:Pluchino,Biondo, & Rapisarda 2018


意大利研究者们设定了大量“天赋”水平不同的假设个体(“代号1”至“代号1000”),将这些个体置于一个正方形的世界中,让他们在其中经历他们的整个工作生涯。他们将“天赋”定义为 让一个人能够抓住机遇的任何一组个性特征。天赋可以包括智力、技能、动机、决心、创造性思维、情商等等。这里的关键在于, 更有天赋的人会更倾向于从各种机会中找出最适合他们的那一个


在模拟开始时,所有的个体拥有相同的成功值(10“成功单位”)。每六个月,这些个体会遇到特定数量的 幸运事件(绿色)和特定数量的 不幸事件(红色)。当个体遇到不幸事件时,其成功值减半;当个体遇到幸运事件时,其成功值根据其天赋水平按比例增加(以反映真实世界中天赋与机会之间的关系)。


他们的发现是什么?首先,他们重现了著名的“ 帕雷托原理”。这一原理认为,少数人最终将获得大多数人的成功(Richard Koch又将其引用为“80/20原理”)。在40年模拟的最终结果中,虽然初始设定的天赋呈正态分布,成功却不是。 20名最成功的个体合计占有了44%的成功值,而将近半数人的成功值维持在10单位以下(与初始设定值相同)。这一结果和来自真实世界的数据相同,甚至有迹象表明,财富成功在真实世界中的分布要更加不平衡:最富有的8个人拥有的财富等于世界上最贫穷的一半人的财富总和。


天赋的正态分布

图片来源:Pluchino,Biondo, & Rapisarda 2018


高度不平衡的成功值分布

图片来源:Pluchino,Biondo, & Rapisarda 2018


尽管如此不平衡的分布看起来很不公平,如果那些最成功的人也是最有天赋最有能力的人,那么这一结果也可以合理化。那模拟结果是否是这样的呢?一方面,天赋并不是与成功毫不相干。通常情况下,天赋更高的人更有可能抓住运气提供的机遇。并且,模拟中最成功的个体天赋水平大多至少在平均值以上。所以 天赋确实重要


然而, 只有天赋是绝对不够的,因为那些最有天赋的个体只有极少数也是最成功的。通常情况下, 平凡却幸运的个体要比有天赋而不幸的个体更加成功。那些最成功的个体往往只有稍高于平均值的天赋水平,却在生活中充满了运气。


以下是他们模拟实验中最成功个体和最不成功个体的成功值演变图:


最成功和最不成功个体的成功值演变图

图片来源:Pluchino,Biondo, & Rapisarda 2018


正如你所见,绿色线条表示的最成功的个体在其生命中遇到了一系列非常幸运的事件,而红色线条表示的最不成功的个体(他们甚至比那些最成功的个体天赋更高)在生命中经历的不幸事件难以想象地多。正如论文作者所说,“在不幸的怒火面前,即使拥有极高的天赋也无济于事。”


怀才不遇无论对个体还是社会而言都是不幸的。因此,我们可以做些什么来让那些最有能力利用机会的人得到他们最需要的发展机会呢?



更有效的资助策略


许多“精英主义”用以分配荣誉、资金或奖励的策略,通常基于某个人过去的成功经历。以这样的方式进行选拔无疑会导致富人更富、穷人更穷,这也被称作“ 马太效应”。但这是激发潜力的最有效策略吗?如果你是决策人,哪一种投资策略会更为有效呢?向几位以前有成功经历的申请人提供大笔资助,还是将资金分成很多份分给许多不那么成功的普通人?


Jean-Michel Fortin和 David Currie 曾研究过更大规模的资助是否会带来更大的成果。他们发现在研究资金和科研成果影响力之间的确存在一定的正相关, 但这种关联非常微弱。更重要的是,那些获得第二笔资助的人并不比那些只获得一笔资助的人更多产,而且对于这些人而言成果通常是资助的递减函数。


论文作者们认为, 比起那些以“优秀”作为遴选标准的项目,更关注目标多样性的资助策略可能会对社会产生更大的影响。在一项更新的研究中,研究人员研究了魁北克在15年期间内对12720名研究人员提供的资金。他们得出的结论是,“在论文数量和科学影响方面,研究资金集中在所谓的‘精英’研究人员手中,通常会产生边际收益递减”。


基于这项工作,模拟了运气对成功的影响的意大利研究组进行了进一步模拟。他们从上帝视角探讨了许多不同资助策略的有效性。在模拟个体的40年工作生涯中,他们每隔5年就换用一次不同的资助策略。我们已经发现,在没有任何资助的情况下,最成功的个体是那些拥有平均天赋水平却非常幸运的人。当研究组向模拟中引入多种资助策略后,会有什么结果呢?


不同资助策略的效率

图片来源:Pluchino,Biondo, & Rapisarda 2018


这一表格按效率递减的排序列出了40年间最有效的资助策略(例如,需要的资金最少而获得的投资回报最大)。从下至上阅读列表,可以发现 那些把一定比例的资金给已经非常成功的人的资助策略是最无效的。将一定比例的资金给那些已经非常成功的个体而将余下的资金平均分配的“混合”策略相比之下要更有效一点, 但这些都还不如随机分配资金的策略高效。最后这一项发现非常有趣,因为它与其他一些研究结果一致,这些结果都表明,在复杂的社会和经济环境中,机会很可能发挥了一定的作用,在这一前提下, 结合了随机性的策略比基于“精英主义”的策略表现更好。


这表示,最佳资助策略应当是给每个人都分配同等数量的资金。当以每5个月1单位的速度分配资金时,60%的最有天赋个体获得了超过平均水平的成功值,以每6个月5单位的速度分配资金的结果是,100%的最有天赋个体都产生了影响力!这表明,如果一个资助机构或政府有更多的资金可供分配,那么将这些额外的资金均分给每个人,与只给一部分人相比是更明智的选择。


正如研究者总结道:“如果投资目标是奖励最有天赋的人,以使他们最终获得更高的成就,那么向所有人定期等额提供资金,会比将大额资金提供给被选中的小部分人更有效。”



什么样的社会更容易造就成功?


这个不可思议的意大利研究组并没有就此止步!既然拥有了上帝视角,为什么不钻研到底呢。他们还做了一些改变了个体所处环境的模拟实验。使用之前搭建的框架,他们模拟了一个非常激励人的环境,对每个人而言都充满了机遇(比如像美国那样富裕而高度工业化的国家),也模拟了一个相比之下不那么激励人的环境,只有非常少的机会(比如第二次世界大战中的国家)。以下是他们的发现:



最成功个体在充满机遇的环境(上)和机遇不多的环境(下)中的成功值

图片来源:Pluchino,Biondo, & Rapisarda 2018


观察比较充满机遇的环境(上)与机遇不多的环境(下)中结果分布的差异。在上半幅图模拟的环境中,一部分天赋水平中上的个体能够获得非常高的成功值,天赋较高的人获得较高成功值的可能性也比较高。相反,在第二幅图模拟的环境中,整个社会的总成功值水平很低,并且只有18个个体获得了比初始值更高的成功。


以上模拟实验的结果与越来越多的基于真实世界数据的研究结果相吻合,所有的结果都强烈表明, 运气和机会在决定个人的最终成功水平方面扮演着重要角色。正如研究者指出的,奖励和资源通常都被给予那些已经被高度赞扬的人们,而这往往会导致最有天赋的那些人(比如,最有潜力因这些资源真正受益的人)反而得不到机会。在进行这样的资源分配时我们忽视了运气扮演的重要角色,实际上,运气的影响在整个创造性的过程中难以避免。研究者们认为,为了给人们更多成功的机会,以下因素都很关键: 一个充满机遇的环境、良好的教育、密集的培训和行之有效的资金与资源分配策略。他们认为,任何能够影响这些因素的政策都将有助于公民的个人实现,也会在宏观层面为全社会带来更大的集体进步和更多创新。


原文链接:https://blogs.scientificamerican.com/beautiful-minds/the-role-of-luck-in-life-success-is-far-greater-than-we-realize/



《环球科学》3月刊现已上市

欢迎点击 阅读原文购买


Viewing all 15896 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>