Skip to main content

数据相关的职位分为三类:数据分析师、大数据工程师和算法工程师。数据分析师需要丰富的领域知识和敏感的业务思维;大数据工程师为数据分析提供了数据基础和分析工具,需要掌握Spark和Flink等大数据技术,对编程和逻辑思维要求较高;算法工程师的技术要求最高,不仅要懂业务,会大数据,还要熟悉机器学习算法,并且能够将机器学习模型部署到生产环境。当然,因为优质算法工程师稀缺,他们的薪资水平最高。

在大数据和人工智能行业,有众多与数据相关的岗位,名目繁多:数据分析师、数据产品经理、数据挖掘工程师、大数据工程师、数据开发工程师、机器学习工程师、算法工程师、NLP算法工程师、数据科学家等等。很多应届生或准备转行的朋友面对如此多的岗位名称,都会傻傻分不清楚。本文将这些数据相关的职位分为三类:数据分析师、大数据工程师和算法工程师,并从工作内容和技能要求来做一下分析,帮助新入行朋友选择适合自己的岗位。这里我暂且不谈最顶级的数据科学家,这部分人均为名校博士,全世界可能只有几千个,他们可以轻轻松松年薪百万,是整个食物链的最顶层。他们不需要找工作,都是工作在找他们。

数据行业金字塔

数据科学金字塔 来源:hackernoon.com 数据科学金字塔 来源:hackernoon.com

上图的数据金字塔展示了数据科学领域各岗位的大致职能。

  1. 最底层是数据收集部分,主要是原始数据的生成和收集。这部分数据来自各种IOT设备、传感器、手机APP上的用户行为、外部数据、以及用户生成数据(类似抖音用户主动发布的视频)。
  2. 第二层是数据存储部分,一般需要构建数据仓库,生成一系列数据流,将原始数据存储至大数据平台。
  3. 第三层是数据清洗和转化部分,主要对数据进行清洗和预处理,将数据转化为更高层次的数据,为上层数据分析做准备。
  4. 第四层是数据聚合部分,主要做一些基础的数据分析和业务报表,进行一些数据挖掘,并构建机器学习的训练数据。
  5. 第五层是机器学习部分,主要构建机器学习模型,将模型发布到生产系统,进行AB实验。
  6. 最顶层是人工智能部分,顶级的科学家提出新算法或新架构。

绝大多数数据岗位的工作内容一般在第二至第五层,很多岗位的工作内容互相交叉,很难严格区分每个人在做具体哪些事情。无论哪个岗位,都需要衡量候选人以下技能:

  • 领域知识
  • 数学和统计学
  • 逻辑思维
  • 编程开发
  • 大数据
  • 机器学习

数据分析师

我个人认为,数据分析师、数据产品经理(增长黑客)、数据运营以及部分商业智能分析师虽然主要工作各有侧重,但数据相关的核心技能都可以归纳为数据分析。

数据分析师的入行技术门槛相对较低。这里强调技术门槛相对较低,是指“编程开发”、“大数据”和“机器学习”等技能的门槛要求相对较低,甚至可以说,只要会用Excel,就能进行数据分析。但数据分析师的岗位对于领域知识、逻辑思维和统计学的要求并不低,尤其是领域知识和逻辑思维。数据分析师主要在研究和分析该领域的数据,且必须对该领域数据有非常深刻的理解和认识,那领域知识主要指什么呢?以今日头条这样的内容推荐引擎为例,数据分析师所做的事情可能是:

  • 用户画像分析:哪些用户是该APP的重度用户?小镇青年还是都市白领?60岁以上老人是否也会使用?哪部分用户是需要下一步重点发展的潜在用户?
  • 用户行为分析:用户在一天中的哪个时段会频繁打开APP,是上下班通勤途中还是午饭后睡觉前?每次打开时的核心诉求是消磨时间还是获取有价值信息?当用户短时间内切换了一所城市,用户更希望在当时获取哪些资讯?
  • 内容分析:不同类别的用户倾向于阅读哪些类型的文章,国家大事、炒菜养生还是娱乐星座?视频兴起后,该给用户推荐多少视频类内容?
  • 广告分析:哪些新的功能会促进用户点击APP类的广告?广告出现的频次应该如何控制?广告与用户阅读兴趣如何结合?

今日头条内容分析报告 今日头条内容分析报告

如果换做电商领域,则需要分析师对电商场景有独到的理解。对于不同业务场景来说,所用到的统计学知识并不复杂的,所需要分析的内容不尽相同,但都紧紧围绕着业务。数据分析师的领域知识包括对业务系统的熟悉程度、行业的从业经验、对一些数据和场景的深刻的见解。新入行的数据分析师主要在分析过去发生了什么,产生这些结果的原因是什么;有经验的数据分析师能够从数据中预测未来趋势,为管理层提供前瞻性预见。数据是基础,从数据中发现一些潜在的因果关系、产品优化方向、未来商业机会等洞见性的想法才是数据分析的精华所在。

数据分析进阶 数据分析进阶

数据分析师每天的工作是处理百万或上亿用户的数据,并且能够在这些数据中挖掘到一些有趣的用户行为模式,给决策层提供前瞻性建议,颇有一种站在上帝视角俯瞰众生的感觉,非常有趣也很有挑战。

数据分析师对专业的没有明确的要求,一般要求候选人有计算机、统计学、电子、通信等背景,实际上这个岗位也接受大量其他专业转行。只要了解业务场景,不同专业背景的人都可以快速转行到数据分析上。数据分析师的这个岗位看似“谁都可以做”,但我个人感觉这个岗位的职能在慢慢被其他岗位所蚕食,反而对从业人员的技能要求越来越高。一方面,现在那些所谓“动动嘴皮子”的岗位已经不能再靠“忽悠”就能胜任了,必须用数据说话,一些岗位如“数据产品经理”、“数据运营”以及“商业智能分析师”都要求相关人员在工作中进行大量的数据驱动的分析,抢占了一部分数据分析师的工作。中小型公司为精简成本,会尽量让一个人去做两个人的事情,会让产品或运营来做轻量型数据分析的工作。另一方面,随着数据量的爆炸增长,数据分析师所使用的工具也在发生快速变化,甚至Python都无法胜任大数据的场景,必须使用Hive等大数据分析工具,更不要提Excel这种只能处理单机数据的软件了。

因此,本节一开始提到的:“相比业务知识,数据分析师岗位对「编程开发」等技术门槛要求相对不高”也只是一个相对概念。这并不意味着数据分析师不需要掌握编程技术。翻看某招聘APP上数据分析师的职位要求,几个核心的技能包括:Python、SQL、数据挖掘等。这其实对没有相关工作经验的应届生或转行人士的技能要求相当高了。在无相关工作经验的情况下,一般人很难接触到大规模的数据量,或者可供分析的业务场景,自学了很久的Python,可能在用人单位眼里只是一些小玩具,难以胜任真正的工作。另外,学术圈喜欢使用R语言,互联网公司一般不使用,从R转到Python对于非计算机专业应届生来说也是一个不小的挑战。

数据分析师技能图谱 数据分析师技能图谱

对于想为数据分析师、数据产品经理、商业智能分析师的朋友,一个大致的学习路线图为:Python基础 -> 数据库和SQL -> 数据分析和可视化 -> 业务实战。本专栏后续会更新一些Python及数据分析的入门教程。

大数据工程师

数据分析师直接面向一线业务,大数据工程师则在为数据分析提供数据基础、分析工具和软件平台,构建数据分析环境。原始的数据就像麦田里的麦子,需要经过层层工序,才能最终将其转化餐桌上的面包。大数据工程师打通了粮食收割、清理、制粉的整个流程,数据分析师和算法工程师就像是大厨,将面粉加工成面包。

OLAP架构示意图 OLAP架构示意图

一部分大数据工程师主要关注构建数据仓库,为公司提供OLAP(Online Analytical Processing,联机分析处理)服务:主要是在Hadoop生态上,构建大数据分析平台。包括提供HDFS、HBase、对象存储等数据存储服务;Hive和Spark批处理、Druid和Kylin预处理等数据分析工具;Spark Streaming、Flink等流式计算工具。这部分工程师关注基础设施。

构建高可用数据流涉及众多大数据中间件 来源:www.iguazio.com 构建高可用数据流涉及众多大数据中间件 来源:www.iguazio.com

还有一部分大数据工程师主要关注ETL(Extract、Trasform、Load):在收集到的基础数据上做提取和转化,生成更高层次的数据。这部分工程师关注业务相关的数据流。因为原始数据一般都是互相独立的,数据与数据之间关联性差,使用这些原始数据,几乎很难快速生成用户画像、广告收入等高层次数据分析结果,更不用提如何进行机器学习建模了。还是以今日头条内容推荐引擎为例,整个推荐引擎要接入不同类型的异构大数据源:每个用户在APP上的使用行为、公司购买的第三方数据(包括用户金融能力数据等)、自媒体产生的海量图文视频内容等等。数据工程师的工作包括:将用户在APP内的点击行为与点击的内容做关联,生成用户兴趣画像;将用户的APP内部数据与第三方数据关联,生成用户的消费能力画像等。

大数据工程师主要对收集过来的底层数据做处理,建立一系列数据管道,将来自不同数据源的原始数据经过层层转化,生成对数据分析和算法建模更有价值的中间数据,一般称这个流程为数据流。小公司限于人力有限,数据流的响应时间有可能是天级或小时级;大公司对数据流的响应要求极高,有可能是分钟级、秒级甚至亚秒级。很多朋友都发现,在某个平台刚刚搜索过某一个内容,下一分钟就能收到相似内容的推荐了,因为大数据工程师提供了这种秒级数据管道。

大数据工程师技能图谱 大数据工程师技能图谱

相比数据分析师,大数据工程师对从业人员的“编程开发”和“大数据”大数据要求比较高,而且数据量越大的公司,对技能要求越高。公司一般要求工程师在Java和Scala语言上,基于Hadoop生态系统,构建实时或批量的数据流。但公司与公司的差异很大,整个技术栈和工作内容与公司架构高度相关。某招聘APP上对大数据开发工程师的技能要求:Java、Scala、Linux、Hadoop、Kafka、Spark、Flink等。面试时一般会重点考察候选人对Google大数据三大论文的理解,即MapReduce、GFS和BigTable,分别对应了开源的Hadoop MapReduce、HDFS和HBase,这三篇论文也被称为驱动大数据的三驾马车。非信息学类专业背景的朋友,未经系统培训,很难转行到这个领域。在校学生应该积极参与校园项目或进入公司实习,以获取大数据开发的实战经验。

算法工程师

人工智能时代最火爆的概念当属机器学习了,机器学习工程师也被推上了风口,曾出现毕业后起薪三五十万,各大公司争相追捧的盛况。机器学习工程师又被称为算法工程师,主要职责是针对业务场景,建立机器学习模型,并将模型部署到生产系统,为公司赢得利润。算法工程师也是一个业务相关的岗位,一个合格的算法工程师必须要熟悉业务,明确工作所要优化的目标,才能有的放矢。不同的业务场景所使用的机器学习模型一般不同,常见的方向有推荐算法、自然语言处理、计算机视觉等。

算法工程师也需要在大数据工程师提供的数据基础上做进一步的数据开发,以构建自己的机器学习数据流。限于公司规模和技术架构,不同公司的算法工程师所做的具体工作可能也有很大差异,但算法工程师的核心工作有两点:

  1. 构建机器学习模型
  2. 将机器学习模型发布到生产系统

机器学习典型流程 来源:towardsdatascience.com 机器学习典型流程 来源:towardsdatascience.com

很多朋友看到网上的机器学习例子中,只需要调用一下model.fit()函数就能训练一个模型,认为机器学习非常简单。实际上,一个机器学习流程很长,包括:模型选择、数据预处理、特征工程、样本生成、模型调优以及模型上线。整个工作对工程师的各项技能要求也非常高。

对于模型训练和线上发布,各公司差异也比较较大。对于数据量较小的场景,可以直接用“Python + Shell + SQL”的方式构建机器学习数据流,使用scikit-learn或TensorFlow这样的框架。对于数据量大的场景,还是必须依赖大数据处理框架Spark或Flink,并使用分布式训练工具。大公司一般为适配自己的数据量和业务场景,都会有一套自己的模型训练和上线工具,并配有专人来开发和维护这套机器学习框架。因此,在一个大公司里,可能有一部分人负责模型训练,主要是模型调参和特征工程;一部分人负责模型上线,主要保障模型能够提供稳定的在线服务;一部分人负责机器学习框架开发;机器学习并不是万能的,所以还需要一部分人使用人工策略来解决机器算法无法解决的那部分问题。听起来好像所有人的职责都带机器学习几个字,实际做的事情区别很大,所侧重各有不同。

限于人力条件,有些公司的算法工程师需要做类似于大数据工程师的的ETL工作,从原始数据开始生成机器学习训练所需数据,同时要兼任数据分析师,自己分析数据。算法工程师名字听起来高大上,实际上绝大多数时间在做脏活累活。

典型推荐算法 典型推荐算法

算法工程师最核心技能还是机器学习和统计学,这关乎机器学习模型能够在何种程度上优化目标、带来多大的效果提升。例如一个推荐算法工程师有可能在面试中被问到的机器学习知识包括但不限于:

  • GBDT的原理
  • 如何进行特征选择
  • 如何评估模型效果
  • softmax函数的定义
  • 如何将embedding应用到推荐系统中

综上,算法工程师直接面向业务,因此需要对丰富的领域知识,同时需要强大的统计学和机器学习基础,因为算法工程师要生成训练数据,因此要掌握必要的大数据分析和处理工具。负责模型上线的工程师还要有很强的编程开发能力。可见,算法工程师对各项技能的要求非常高。

算法工程师技能图谱 算法工程师技能图谱

小结

数据相关的职位分为三类:数据分析师、大数据工程师和算法工程师。数据分析师需要丰富的领域知识和敏感的业务思维;大数据工程师为数据分析提供了数据基础和分析工具,需要掌握Spark和Flink等大数据技术,对编程和逻辑思维要求较高;算法工程师的技术要求最高,不仅要懂业务,会大数据,还要熟悉机器学习算法,并且能够将机器学习模型部署到生产环境。当然,因为优质算法工程师稀缺,他们的薪资水平最高。

尽管依赖问题非常棘手,但明白包管理以及包编译安装原理有助于我们深刻理解计算机基本原理,避免成为一个调包侠。

最近在一台GPU机器上安装了LightGBM,主要是希望LightGBM能够利用GPU的算力进行加速,中间遇到GPU驱动以及CUDA等问题,断断续续持续了一个月才完全使其正常运行。为了彻底弄明白Python打包和安装依赖的问题,我下载了LightGBM、TensorFlow等机器学习库的源码,并做了一些调研。

为什么pip安装的机器学习库对GPU支持不好

对于主流机器学习库,比如TensorFlow、PyTorch、LightGBM等,主要都是使用C/C++编写的。C/C++有如下优势:

  • 如果用Python语言实现,Python解释器(例如CPython)会将Python代码翻译转化成机器能够理解的代码。而C/C++代码被直接编译成机器码,能够充分利用CPU、GPU等硬件的算力。
  • CPython有一个限制并行计算的GIL锁。C/C++程序能够更好地进行并行计算,避免了CPython的GIL锁。
  • C/C++可以显式(Explicitly)管理变量和内存,处理结果具有确定性(Deterministically)。

以TensorFlow为例,它提供了Python的调用接口,用户一般用Python来调用TensorFlow。实际上,其底层代码绝大多数是用C/C++编写的。Python只是TensorFlow的一个前端(Front End),Python需要通过调用C语言的API,进而调用底层的TensorFlow核心库。它的架构图如下所示:

TensorFlow架构图 TensorFlow架构图 来源:TensorFlow Internals

上图中,最底层是硬件,包括了网络和计算设备,这里先只关注计算设备。由于CPU、GPU等硬件设计的区别,一些矩阵运算在不同硬件上的机器码有质的区别。线性代数部分一般基于Eigen库,这是一个专注于向量和矩阵运算的C++库;Eigen::Tensor是一个使用C++模板技术,它可以为多核 CPU/GPU 生成高效的并发代码。

GPU软硬件依赖栈 英伟达GPU软硬件依赖栈

GPU部分最底层是操作系统和驱动,再往上是提供给程序员的开发接口CUDA。英伟达在CUDA之上提供了cuBLAS、cuDNN等库,cuBLAS是运行在英伟达GPU上的线性代数库(Basic Linear Algebra Subprograms,简称BLAS),cuDNN是英伟达为优化深度神经网络,在CUDA上包装的库,里面包含了Tensor计算、卷积、池化等常见DNN操作。cuBLAS和cuDNN代码会最终编译成英伟达GPU可运行的机器码。

info

cuDNN对英伟达硬件、驱动和CUDA版本有依赖要求,由于版本迭代,新版本的cuDNN只能运行在高版本的驱动和CUDA上。英伟达官方提供了版本依赖表。对于使用英伟达GPU的朋友,第一件事是基于自己的硬件安装最新的驱动。如果驱动、CUDA和cuDNN版本与上层应用不匹配,容易出现各类问题。很多时候,我们按照网上的教程安装了驱动、CUDA,并用pip安装了TensorFlow,最后发现有99%的概率依然用不了。因为,TensorFlow提供的pip安装包主要基于下面的版本进行构建的。

TensorFlow官方提供的经过测试的版本依赖关系 TensorFlow官方提供的经过测试的版本依赖关系

到底什么是包

广义上来讲,包(Package)其实就是一个软件集合,安装完包之后,我们就可以使用包里的软件了。Windows上缺少包的概念,类Unix系统一般使用包管理软件(Package Manager)来管理和安装软件,我们在手机上常用的应用商店其实就是一个包管理软件。软件发布者将编译好的软件发布到包管理仓库(Repository,简称Repo),用户通过包管理软件来下载和安装,只不过类Unix系统一般使用命令行来安装这些软件。

常见的包管理有:

  • 在操作系统上安装软件:

    • Ubuntu的apt、CentOS的yum、macOS的homebrew
  • 在编程语言中安装别人开发的库:

    • Python的pip、Ruby的Gem
  • 包管理软件有对应的Repo:

    • pip的PyPI,conda的Anaconda.org、R的CRAN

无论包管理模式如何,这些包管理系统都会帮助我们解决:

  • 管理源码(Source Code)或者编译打包之后的二进制文件(Binary)。

  • 解决软件包之间的依赖问题。比如,LightGBM还依赖了NumPy等其他包。部分依赖还对版本号有要求。

从源码开始编译一个包其实很麻烦:

  • 很多时候需要基础环境一致,这包括操作系统版本(高版本的操作系统glibc版本比较高,一些新兴机器学习包一般基于更高版本的glibc,这些包无法安装到低版本的操作系统上)、编译工具(例如类Unix系统的GCC、CMake,Windows上的Visual Studio等)。

  • 当前包所依赖的其他软件,比如GPU版的TensorFlow所依赖的cuDNN、LightGBM所依赖的NumPy等。

  • 编译过程相当耗时。比如,TensorFlow的构建时间就非常长。

因此很多包管理系统在发布的时候,提供二进制文件。二进制文件下载解压之后就可以运行了,有点像Windows上的绿色免安装软件。但是:

  • 别人编译好的软件是在别人的基础环境上进行的,这就导致这个软件非常依赖当初编译它的环境。
  • 安装当前包之前肯定要先安装好这个包所依赖的软件包。

可见,包管理也是一个有一定挑战的问题。就像很多桌面软件和游戏只有Windows的版本一样,一些大数据、深度学习类的应用因为基于Linux环境开发和构建,常常对Linux支持更好。

pip和conda

回到Python的包管理上,经过这些年的发展,Python领域目前有两大主流包管理系统:pipconda。那这两个到底有什么区别呢?

pip是Python官方的包管理工具:

  • 它从PyPI(Python Package Index)上拉取数据,或者说它的Repo在PyPI上。绝大多数的Python包会优先发布到PyPI上。目前(2020年5月),PyPI上的项目有23万之多。
  • 支持源码和二进制文件,二进制文件以Wheel文件形式存在。
  • 只支持Python,不关注其他一些非常重要但是更加底层的软件包,比如针对Intel CPU加速的数学库Intel MKL。
  • pip安装包时,尽管也对当前包的依赖做检查,但是并不保证当前环境的所有包的所有依赖都同时满足。这可能导致一个环境的依赖冲突,当某个环境所安装的包越来越多,很早之前安装的包可能和当前包相互冲突。

conda是另外一个被广泛应用的工具,它:

  • 它从Anaconda.org上拉取数据。Anaconda上有一些主流Python包,但在数量级上明显少于PyPI,缺少一些小众的包。

  • 它只支持二进制文件,二进制文件是提前编译好的。

  • 不仅支持Python,还支持R、C/C++等其他语言的包。

  • 提供了环境隔离,可以使用conda命令创建多个环境,每个环境里安装Python、R等环境,某个特定的环境内包含了独立的Python解释器,不同环境之间互不影响。相比而言,pip只提供安装功能,多环境之间的隔离需要依赖另外的工具(如virtualenv)来完成。从这个角度来讲,conda可以管理Python解释器,而pip必须依附于Python解释器。

  • conda在安装包时,对所安装包的依赖检查更严格,它会保证当前环境里的所有包的所有依赖都满足。

condapip
RepoAnaconda,包数量远少于PyPIPyPI,Python包会被优先发布到PyPI上
包内容二进制源码和二进制
支持语言Python、R、C/C++等只支持Python
多环境管理可以创建多个环境,环境内包含Python解释器本身不支持,需要依赖其他工具
依赖检查严格的依赖检查依赖检查不严格

可以看到,目前没有一个完美的Python包管理模式,conda虽然对依赖检查更严格,但是它支持的包比较少。pip对依赖检查不够严格,会导致环境的冲突,但是很多Python包,尤其是一些小众的Python包会优先发布到PyPI上。因此,我们可能需要将condapip结合起来,并且要善于创建不同的环境,每个环境处理某些具体的计算任务,以免环境里的各类包越来越臃肿,造成依赖冲突。

机器学习库安装方法

TensorFlow

如果想在GPU上使用TensorFlow,官方建议使用Docker。用户只需要安装GPU驱动即可,连CUDA都不需要安装。Docker在一定程序上能解决环境的隔离。

如果不习惯使用Docker,一些文章推荐使用conda来安装TensorFlow。因为conda不仅管理Python,还支持C/C++的库。因此在安装TensorFlow时,它不仅将TensorFlow所需要的一些二进制文件下载安装,还安装了一些其他依赖包。

使用conda创建一个名为tf_gpu的虚拟环境,安装GPU版本的TensorFlow:

conda create --name tf_gpu tensorflow-gpu

安装过程中显示除了TensorFlow本身,conda还将安装包括CUDA、cuDNN在内的依赖包:

conda安装TensorFlow时会安装相关依赖 conda安装TensorFlow时会安装相关依赖,包括CUDA、cuDNN、BLAS等

LightGBM

相比TensorFlow,LightGBM尽管也在Anaconda.org上有二进制文件,但是并没有明确是否支持GPU,其官方文件中GPU版本是基于源码安装的。因此,LightGBM可以作为一个小众的案例。

如果我们使用pip安装LightGBM,可以直接安装二进制文件,也可以从使用源码安装。

LightGBM的PyPI页面中显示,LightGBM依赖C/C++库,比如Windows的Visual Studio(2015或更新版本),Linux的glibc >=2.14。

拉取二进制文件并安装:

pip install lightgbm

使用源码安装,Linux和macOS需要先安装CMake。

pip install --no-binary :all: lightgbm

# 安装GPU版本
pip install lightgbm --install-option=--gpu

安装GPU版本之前需要先安装GPU驱动。LightGBM使用开源的OpenCL而不是CUDA进行GPU加速,因此还要安装OpenCL。使用源码安装本质上是使用CMake将C/C++代码编译,编译过程中依赖了本地的基础环境,包括了C/C++各个类库、GPU驱动、OpenCL等。

安装命令成功执行之后,LightGBM会被放在当前Python解释器的site-packages目录下。

cd prefix/lib/python3.6/site-packages/lightgbm
tree

.
├── basic.py
├── callback.py
├── compat.py
├── engine.py
├── __init__.py
├── lib_lightgbm.so
├── libpath.py
├── plotting.py
├── __pycache__
│   ├── basic.cpython-36.pyc
│   ├── callback.cpython-36.pyc
│   ├── compat.cpython-36.pyc
│   ├── engine.cpython-36.pyc
│   ├── __init__.cpython-36.pyc
│   ├── libpath.cpython-36.pyc
│   ├── plotting.cpython-36.pyc
│   └── sklearn.cpython-36.pyc
├── sklearn.py
└── VERSION.txt

安装之后会有一个lib_lightgbm.so的动态链接库。这是C/C++代码编译之后生成的库,Python通过ctypes来访问动态链接库中的C/C++接口。于是,我们就可以在Python中调用这些C/C++的程序。

小结

为了避免依赖问题,我们可能需要按照下面的顺序来管理我们的Python包:

  • Docker
  • conda
  • pip
  • 源码安装

尽管依赖问题非常棘手,但明白包管理以及包编译安装原理有助于我们深刻理解计算机基本原理,避免成为一个调包侠。

本文和大家分享一个来自Stanford的开源大数据和机器学习系统:MacroBase。

MacroBase源于Stanford的DAWN项目(Data Analytics for What’s Next,下一代数据分析)。Stanford团队称,DAWN项目的初衷是为了让人工智能更加平民化,更多普通人也可以构建AI应用,享受人工智能技术所带来的生产力的提升。可能一些人对DAWN项目并不熟悉,但我们肯定听说过并使用过Apache Spark或Apache Mesos,DAWN团队曾经在这些项目中投入大量研发精力。如今,DAWN开始将视野放到端到端的机器学习问题上,他们构建了一系列工具,希望能够让机器学习工具更加高效,更容易使用。

MacroBase就是DAWN项目中的一个分支,它是一个实时异常点检测系统。定位异常点之后,MacroBase还会对这个结果进行解释,定位到底是哪些因素所影响导致异常的出现。用知乎网友张泰源的解释:“MacroBase不仅会告诉你出事了,还会告诉你为什么出事了。”MacroBase团队发表了很多论文,比如某篇论文获得Best of SIGMOD 2017。本次我主要学习的是他们发表在ACM Transactions on Database Systems上的《MacroBase: Prioritizing Attention in Fast Data》,论文里对MacroBase的具体实现和算法都有详细的介绍。同时,MacroBase代码也在github开源了:https://github.com/stanford-futuredata/macrobase

背景

工业界为了快速定位问题,通常会对各类设备进行监控,监控数据会实时上传到服务端。比如,大型数据中心在运维时会收集物理机、虚拟机和应用程序上的的各类数据,用以监控服务器和程序是否正常运行。AWS美国东部的数据库曾爆出异常,影响了运行在其上的Netflix和Reddit的应用。但是,AWS的工程师并没有及时跟进解决,造成了重大损失。

这类监控问题可以被归纳为异常点检测问题。异常点检测的一大挑战是数据量太大,数据速度太快,人的精力很难覆盖这么庞大的数据量。因此,论文的题目是Prioritizing Attention in Fast Data,如果人力无法胜任这么庞大的工作,可以先让机器做一些初步的分析,MacroBase对流数据做了提纯,自动识别出流数据中的异常,并进行异常的归因,以此节省人的精力。

系统设计

MacroBase是一个流处理系统,它实时监测数据流,进行异常点检测,并对异常结果进行解释。它是一个实时流处理系统,使用了流处理界领先的Dataflow模型。下图为MacroBase一个数据分析工作流(Pipeline),可以看到,这个图与Spark的有向无环图(DAG)模型、Flink的数据流图模型极其相似。

MacroBase Dataflow模型 MacroBase Dataflow模型

整个Pipeline分为五大部分:

  • Ingest:数据的输入。可以从外部数据源经过ETL转化,将数据导入MacroBase。
  • Transform:对数据进行一定的转化处理。比如,进行时间维度上的处理:设置时间窗口、去除时间序列数据中的周期性偏差(Seasonality Removal)等;进行一些统计学处理:数据归一化、数据降维等;针对特定领域的数据处理:对视频数据使用光流处理(Optical Flow)等。
  • Classify:数据经过Transform处理后,MacroBase使用一些模型进行分类。最简单的模型是规则,MacroBase默认使用的是无监督模型,即基于数据的统计学特性区分出哪些是正常点(Inlier)、哪些是异常点(Outlier)。MacroBase也支持用户使用自己的监督学习模型。
  • Explain:基于刚刚分类结果,生成一些解释,以告知使用者哪些特征导致了异常点。比如,数据中心运维案例中,分析出型号为5052的机器产生了更多异常点,但是正常数据里,这样的数据模式不明显。
  • Present:将解释结果展示给用户。解释结果是一个列表,最有可能导致异常的特征会被排在最前面。

MacroBase是一个框架,其核心功能是在数据流上进行Classify和Explain。因为MacroBase是一个框架,它允许用户在已有的基础上进行扩展,比如自己定义Classify所使用的机器学习模型。

如果用户不进行自定义,MacroBase提供了一个默认的Pipeline,这个Pipeline是基于无监督学习的,数据流图如下所示。

MacroBase默认的无监督学习Pipeline MacroBase默认的无监督学习Pipeline

这张图省却了Ingest、Transform和Present几个阶段,重点展示了Classify和Explain过程。图中的专有名词缩写较多,下面会逐一进行解释。

Classify

这里先绕开MacroBase,谈谈数据流上的机器学习。对于数据流上进行机器学习模型的在线预测,最简单有效的办法都是基于监督学习模型。一般是离线训练好一个模型,线上系统读取加载这个模型,每接收到一条新数据,线上系统根据离线模型来预测新流入数据。离线模型一般非常准确,但是离线模型一般是基于批处理的,更新速度较慢。目前,我们身边很多机器学习应用都是使用很久以前训练的模型,来预测未来新流入的数据。

数据流上的无监督学习其实是一个巨大的挑战。无监督学习一般需要对整个数据集进行遍历和学习,当学到一些参数后,再用来进行新一轮的预测。在批处理领域,训练的问题似乎并不难,因为数据本身就是批量存储的。但是在数据流上,尤其是高速数据流上,计算引擎一般是将数据缓存在本机的内存或者磁盘中,内存和磁盘的所能承载的数据量是有限的,因此,如果数据量巨大,我们是不可能将整个数据集缓存下来的。另外,流数据本身有时效性,在绝大多数流处理场景下,人们只对最近的数据比较关注,一个月之前、一星期之前或者一天之前的数据必须经过衰减才行。

MacroBase对此采用的方案是采样(Sample)。对于采样问题,有一个专门的名词:Reservoir Sampling。Reservoir Sampling表示,当数据总体共有n条,n非常大,且n对于流处理来说未知,将n条数据都放入内存不现实,需要使用一定的采样方法不断生成一个k条数据组成的样本。系统刚启动时,内存中的数据小于k,当数据慢慢增多,达到k的限制时,需要使用一种机制,将新数据替换已有的k条数据,以不断更新样本。MacroBase提出了一个名为Adaptable Damped Reservoir(ADR)的算法,用来动态生成样本集。生成样本集的过程需要考虑两个问题:1. 每条流入数据能够进入样本的概率应该是一样的;2. 数据能够根据时间衰减。MacroBase的ADR采样算法考虑了这两个问题,主要基于两个思想:1. 每条数据赋予一个权重(Weight),最终的采样概率跟权重正相关;2. 对权重进行时间上的衰减。从经验上来讲,MacroBase的ADR采样算法应该是可行的。在图中,ADR也是整个过程的入口。

接着是在数据集上进行无监督学习过程。MacroBase使用了异常点检测算法,常见的异常点检测一般基于样本数据的统计学特性,由于本人专长并不在统计学上,因此这里只做一些简单介绍。最传统的异常点检测假设数据基于正态分布,那么偏离均值(Mean)几个标准差(Standard Deviation)的数据可以被认定为异常点。这种朴素的思想有一个缺点,那就是一个偏离较大的异常点很可能造成整个样本均值和标准差的偏离。对此,MacroBase将目光转向了中位数。对于一元数据,它使用了Median Absolute Deviation(MAD)方法,因为中位数对异常点更不敏感,能够抵消异常点带来的样本偏离。对于多元数据,它使用了Minimum Covariance Determinant(MCD),主要基于Mahalanobis 距离。无论是一元的MAD还是多元的MCD,其实都是已有的异常点检测算法,在搜索引擎中搜索可以了解这两个方法的具体计算过程,这里不再详细叙述。在上图中为Model部分所使用的算法。

经过MAD或MCD两个统计方法的计算,我们可以确定一个阈值,超过阈值的数据可以被认定为异常点。比如,我们设定99分位值的数据为阈值边界,超过99分位的数据被识别为异常点,其他数据被认定为正常数据。在批处理领域,对于一个数据集,这个边界可能是确定的,但在流处理领域,数据不断流入,阈值也需要不断更新。MacroBase使用了第二个ADR采样,用来计算阈值。

Explain

有了阈值,我们就可以识别出异常点了。对流入数据分类后,进入到下一环节:Explain。假设数据有M维特征,到底哪些特征导致异常点区别于正常点呢?MacroBase使用了一个流行病学的概念:相对风险(Risk Ratio)。举个例子,如果吸烟者发生肺癌的概率是20%,而非吸烟者发生肺癌的概率为1%,从是否吸烟这个特征上来讲,吸烟者相比非吸烟者有20倍的相对风险发生肺癌。可见,Risk Ratio表示某个属性相比其他属性来说更可能导致异常点出现。用原文的话来描述Risk Ratio:

MacroBase中Risk Ratio的概念

在数据中心的例子中,我们可以计算特征机器型号相比特征机房房间号哪个Risk Ratio更高,就说明哪个属性最有可能导致了机器异常。这个问题在数据挖掘中被称为Frequent Patterns Mining,即发现数据集中出现频次比较高的某种模式。MacroBase使用了韩家炜2000年提出的FPGrowth算法。

然而,这又是一个批处理容易,流处理很难的问题。当然还是因为流处理无法记录所有的数据。MacroBase提供的思路为Amortized Maintenance Counter(AMC)和CPS-Tree,其大致思想是,在处理过程中要丢掉一部分数据,牺牲一定准确度来换取实时性。

小结

MacroBase融合了数据库、计算引擎、机器学习等多个领域,并在这些领域的顶级学术会议上获得非常好的反响,可谓是机器学习的集大成者。另一方面,其实MacroBase中使用的绝大多数方法和思路都是基于前人的工作,它最大的贡献就是将一些方法和思路落地,并且开源了出来。通过论文和开源代码,可以窥见Stanford实验室超强的工程能力。实际上,在计算机工程实践上,算法模型的力量固然重要,但是将算法落地,能够提供实际的价值,这是绝大多数从业人员所要面对和解决的问题。从这个角度来讲,MacroBase项目本身开源出来就是一大成功。

“聚类”(Clustering)试图将数据集中的样本划分为若干个不相交的子集,每个子集被称为一个“簇”或者“类”,英文名为Cluster。比如鸢尾花数据集(Iris Dataset)中有多个不同的子品种:Setosa、Versicolor、Virginica,不同品种的一些观测数据是具有明显差异的,我们希望根据这些观测数据将其进行聚类。

Clustering

下图可以看到,不同品种的鸢尾花的花萼(Sepal)和花瓣(Petal)长度和宽度存在明显的差异。花萼长度(Sepal Length)、花萼宽度(Sepal Width)等观测数据可以作为样本的特征,用来进行聚类分析。

不同鸢尾花的花萼长度和宽度不同 不同鸢尾花的花萼长度和宽度不同

形式化地说,一个样本集D包含m个样本,每个样本有n维特征,聚类算法根据n维特征数据中的一些潜在数据分布,将样本集D分为k个不相交的簇。需要注意的是:聚类过程是机器算法自动确定分类的过程,机器所确定的分类与真实分类之间的语义联系需要使用者把握。总之,聚类是一种非监督学习(Unsupervised Learning),我们可以不用事先确定一个样本到底分到哪一类,机器会从样本的特征数据中发现一些潜在模式,最终将相似样本归结到一起。

K-Means算法

K均值(K-Means)算法是最常用的聚类算法。

K-Means算法的伪代码 来源:周志华《机器学习》 K-Means算法的伪代码 来源:周志华《机器学习》

上图为周志华老师《机器学习》一书给出的伪代码,用数学语言表示这个算法,看起来有些缭乱,但其算法思想很简单。假如我们想把数据集D划分为K个簇,大致需要以下几步:

  1. 在数据集D中随机选择K个点,这K个点表示K个簇的中心点,即伪代码第1行。
  2. 计算数据集D中各个数据应该被分到哪些簇:具体而言,计算样本中所有点距离这K个中心点的距离,将某个样本x划分到距离其最近的中心点对应的簇上,如伪代码的4-8行。
  3. 优化当前的聚类结构:对于刚刚生成的分类簇,重新计算簇的中心点,如伪代码的9-16行。
  4. 重复前面两步,直到我们得到一个满意的结果。

K-Means算法是一种采用贪心思想的迭代算法。下图展示了从初始状态开始进行的4次迭代,每次迭代,簇的中心点和簇内数据点也在变化。

将数据集分为3个簇,四轮迭代的结果,样本点为“·”,簇中心点为“+” 来源:周志华《机器学习》 将数据集分为3个簇,四轮迭代的结果,样本点为“·”,簇中心点为“+” 来源:周志华《机器学习》

使用scikit-learn对Iris数据集进行聚类

Iris数据集共有3种类别的鸢尾花,每种50个样本。数据集提供了4个特征:花萼长度(Sepal Length)、花萼宽度(Sepal Width)、花瓣长度(Petal Length)和花瓣宽度(Petal Width)。

数据探索

from sklearn import datasets
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.cluster import KMeans

iris = datasets.load_iris()

### 对数据集进行探索
# 打印数据集特征
print("特征名:" + str(iris.feature_names))

# 探索一个样本数据,每行数据4列,分别表示上述4种特征
print("第一行样本:" + str(iris.data[:1]))

# 第一个样本属于哪个品种,用数字代号表示
print("第一行样本所属品种:" + str(iris.target[:1]))

打印结果为:

特征名:['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
第一行样本:[[5.1 3.5 1.4 0.2]]
第一行样本所属品种:[0]

对花萼长度和宽度这两维数据进行可视化:

# 查看前两列数据,即花萼的长度和宽度
X = iris.data[:, :2]
y = iris.target

# 将数据集中所有数据进行二维可视化展示
plt.scatter(X[:,0], X[:,1], c=y, cmap='gist_rainbow')
plt.xlabel('Spea1 Length', fontsize=12)
plt.ylabel('Sepal Width', fontsize=12)

花萼长度和宽度散点图可视化 花萼长度和宽度散点图可视化

# 为了更好理解数据集,使用PCA建模,观察3D模式下数据的分布
fig = plt.figure(1, figsize=(8, 6))
ax = Axes3D(fig, elev=-150, azim=110)
X_reduced = PCA(n_components=3).fit_transform(iris.data)
ax.scatter(X_reduced[:, 0], X_reduced[:, 1], X_reduced[:, 2], c=y,
cmap=plt.cm.Set1, edgecolor='k', s=40)
ax.set_title("PCA建模")
ax.set_xlabel("1st eigenvector")
ax.w_xaxis.set_ticklabels([])
ax.set_ylabel("2nd eigenvector")
ax.w_yaxis.set_ticklabels([])
ax.set_zlabel("3rd eigenvector")
ax.w_zaxis.set_ticklabels([])

PCA 3D数据分布 PCA 3D数据分布

通过图表中可以看到:数据集共有三个品种,不同品种的特征分布有一定的模式。

使用K-Means算法进行聚类分析

### 对数据集使用K-Means进行聚类
km = KMeans(n_clusters = 3)
km.fit(X)

# 打印聚类后各个簇的中心点
centers = km.cluster_centers_
print(centers)

数据集被分为3个簇,这三个簇的中心点坐标为:

[[5.006      3.428     ]
[6.81276596 3.07446809]
[5.77358491 2.69245283]]

我们可以比较一下K-Means聚类结果和实际样本之间的差别:

# 比较聚类效果与真实品种之间的差异
predicted_labels = km.labels_

fig, axes = plt.subplots(1, 2, figsize=(16,8))
axes[0].scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1,
edgecolor='k', s=150)
axes[1].scatter(X[:, 0], X[:, 1], c=predicted_labels, cmap=plt.cm.Set1,
edgecolor='k', s=150)
axes[0].set_xlabel('Sepal length', fontsize=16)
axes[0].set_ylabel('Sepal width', fontsize=16)
axes[1].set_xlabel('Sepal length', fontsize=16)
axes[1].set_ylabel('Sepal width', fontsize=16)
axes[0].tick_params(direction='in', length=10, width=5, colors='k', labelsize=20)
axes[1].tick_params(direction='in', length=10, width=5, colors='k', labelsize=20)
axes[0].set_title('Actual', fontsize=18)
axes[1].set_title('Predicted', fontsize=18)

K-Means聚类后,聚类结果和实际样本之间的差别图 K-Means聚类后,聚类结果和实际样本之间的差别图

左侧是实际情况,右侧是聚类结果,实际结果中橘黄色和灰色类别的两种鸢尾花的数据表现上有一些交叉,聚类算法无法智能到将这些交叉在一起的点区分开来。

对于绝大多数IT从业人员来说,开源(Open Source)是个绕不过去的话题。开源意味着任何人可以免费地访问,下载,修改源代码,甚至进一步将其用作商业用途。开源往往与免费划等号。有趣的是,虽然免费,但是那些资本驱动的商业巨头们却纷纷投入巨资进行开源软件的开发。那么,开源软件到底是如何赚钱?普通开发者又如何面对开源的大趋势呢?

卖软件 V.S. 卖服务

由于国内版权保护相对落后,中国人似乎不太习惯付费使用商业软件。从Windows操作系统到Adobe全家桶,从MATLAB科研利器到各类工业设计软件,中文互联网上曾充斥大量“破解版”。人们习惯了购买硬件,然后在网上找一些破解软件。实际上,像Microsoft、Oracle、Adobe等一些老牌商业软件公司曾经红极一时,他们靠销售软件许可证(License)赚得盆满钵满。时至今日,一款Windows 7家庭版在Amazon上标价为110美元,Windows 7专业版则要169美元。对于很多人来说,花1千块钱买一个软件似乎有些不可思议。但从另一个角度来讲,微软需要雇佣大量专职员工开发和维护它的操作系统,微软是一个拥有十几万员工的超大公司(2016年数据),给这么多员工开工资绝对是个不小的负担。员工开发的源代码是商业软件公司知识产权的重要组成部分。因此,为了应对这么庞大的成本,微软不太可能将员工辛辛苦苦开发的软件免费分享出去。

近几年,风向似乎变了,一向贪婪的微软似乎开始不相信“资本主义”了,开始搞起了“社会主义”,对外宣布大家可以“免费”升级到Windows 10。不仅微软在大肆宣扬“免费”的概念,其他一些公司更进一步,不仅免费而且还开源。Google在智能手机兴起时就开源了安卓(Android)操作系统。将这些源代码发布到网上,任何人都可以免费下载、修改,然后继续商用,难道资本家不想赚钱了吗?

Windows由付费走向免费 来源:helpnetsecurity Windows由付费走向免费 来源:helpnetsecurity

其实,是竞争更加激烈了,钱不那么好赚了,原来那种卖License的套路不那么好用了。移动互联网用户已经远超桌面电脑,很多事情原本需要在电脑上进行,现在手机也可以操作,如果继续抱残守缺,按照原来卖License的套路,微软很难再占领用户市场了。

Windows虽然免费了,但是并没有完全开源,也就是说其他人无法查看其源代码。相比之下,安卓是一款正儿八经的开源软件。10年前,智能手机还未普及,Google为了在苹果、黑莓、诺基亚等手机操作系统商之间的战争之中争得一席之位,将安卓开源了。因为免费,很多硬件厂商都采用了安卓系统,安卓提供了一个免费基础,省去了很大一部分底层工作。这些工作耗时耗力,还难以短时间获得收益。时至今日,智能手机界分为苹果和安卓两大阵营。除去苹果外,三星、华为、Oppo、Vivo、小米等所有主流手机厂商都基于安卓系统进行了二次开发。

看起来,Google似乎在安卓上没捞到什么钱,实际上,谷歌的商业模式靠卖服务赚钱。安卓系统中最赚钱的服务之一是应用商店Google Play。2019年的数据显示,Google Play营收293亿美元。在应用商店领域,Google虽远逊于苹果,但它占领了七成以上的手机操作系统市场,未来的增长潜力巨大。此外,Google的搜索、邮箱、地图等服务都是欧美人高度依赖的应用,这些服务中一般都会有广告商投放广告,都是Google传统的赚钱机器。

Google Play全球收入近年增长趋势 来源:statista.com Google Play全球收入近年增长趋势 来源:statista.com

更有意思的是,Google不仅开源了手机操作系统,而且还在人工智能和云计算领域开源了众多软件,比较著名的有深度学习框架TensorFlow和云编排系统Kubernetes,这两款软件目前已经成为人工智能和云计算领域绝对的王者。要知道,云计算领域原本的老大是Amazon,其地位似乎不可撼动。面对云计算这块肥肉,Google不能不眼红,但是Amazon在虚拟化领域积累太强,Google干脆照搬当年开源安卓的套路,把Kubernetes这款容器云计算操作系统开源了,而且加大对Kubernetes的宣传和布道。有Google的背书,大大小小的软件公司疯一般地转向Kubernetes,使用Kubernetes改造升级自己的IT系统,假如这些中小公司的Kubernetes服务上云,首选很可能是Google Cloud。Kubernetes虽然免费,但是Google Cloud的云服务是收费的啊!仔细分析会发现,在Kubernetes开源这件事上,除了Amazon,包括微软的Azure、阿里云等厂商都非常积极,因为他们都想接此机会撼动Amazon的霸主地位。同样,TensorFlow也是走一样的套路。人工智能时代,如果有一款软件可以一统天下,那么可以依赖这款软件卖培训、卖专属硬件、卖计算服务。卖服务已经植根于Google的DNA里了。

Google开源项目有两千个之多 来源:opensource.google Google开源项目有两千个之多 来源:opensource.google

其实,这种卖服务的商业模式就跟互联网时代的媒体行业一样。互联网媒体绝大多数的文章都免费发布到网上,赚取流量和粉丝,有了流量和粉丝,打个广告、带个私货甚至做了粉丝群,钱就这样被赚走了。

众人拾柴火焰高

俗话说,一人拾柴火不旺,众人拾柴火焰高。这句话正好可以应用在开源软件领域。一般地,公司内部在解决具体业务问题时发现一些场景具有很强的共性需求,需要一个组件来集中解决这一类问题,公司内部成立相应的开发团队,开发出软件的初代版本。初代软件本身存在不少Bug,很多功能也不尽完善,开源之后,全世界的开发者都可以加入进来,帮忙改Bug、提方案、做设计。本来软件只有公司内部有限的人来进行开发,开源之后将得到全世界开发者的支持。Google的TensorFlow开源之后,一度占尽深度学习领域的风头,而Facebook旗下的Torch却不温不火,被边缘化。随着Facebook将PyTorch开源,更多的人帮助其修改Bug,完善功能,PyTorch逐渐在学术圈流行起来,已经能和TensorFlow分庭抗礼。

实际上,开源软件的迭代开发并没有想象中那么自由,也不是为所欲为。和很多公司的组织架构一样,开源软件有一个管理决策层,决定着整个软件未来发展方向。下面以大数据领域著名的Apache软件基金会(Apache Software Foundation)为例。Apache基金会有一个董事会(Board),董事会监督和管理整个基金会,基金会下的每个Apache项目都有一个项目管理委员会(Project Management Committee,PMC),PMC负责具体项目的管理工作。与员工在公司晋升类似,开源软件开发者从最简单的问题做起,直到有足够影响力后,可以被提名为PMC成员。PMC有足够的权利决定资源投入到哪些方向上,因此他们在一定程度上可以决定开源软件的发展方向。很多商业公司非常重视开源软件基金会中的席位,这意味着商业公司在基金会里有更多的话语权。因为PMC可以在一定程度影响软件的发展,商业公司非常乐意在这些大型软件基金会中掌握更多话语权。这也是为什么很多大公司会重点培养开源软件工程师,鼓励他们在开源软件基金会发出自己的声音,甚至花重金捐助这些开源社区。

Kubernetes所在的CNCF基金会白金赞助商

仔细观察Kubernetes所在的CNCF基金会白金赞助商,不难发现,这些公司基本上是当前世界上顶级的云计算服务提供商。每家公司都希望在开源基金会中争取更大话语权,当然,这些公司也会得到一定的回馈。在这场全球的竞争中,没有任何一家公司足够自信,敢另起炉灶,否则很可能在快速的技术变革中被主流所淘汰。

这种大公司入局的开源软件模式有点像国家之间成立的各类国际组织,组织内的各个成员国虽然是竞争对手,但是为了共同的目的,求同存异,共同影响未来的趋势。

中国的开源软件现状

开源在一定程度上对大公司是有商业利益的,国内巨头已经重视在这方面的投入。

2019年3月中国互联网公司开源情况数据统计 来源:InfoQ 2019年3月中国互联网公司开源情况数据统计 来源:InfoQ

上图为InfoQ 2019年3月统计的国内各大公司开源情况,一个结论是:

  • 大前端(前端和移动开发)项目最多,因为前端代码一般不涉密,方便开源。
  • 阿里巴巴在各个维度上都位居国内首位。
  • 百度有 4 个是人工智能领域项目,在众多公司中别树一帜,包括 Paddle、Apollo 等都比较受欢迎。
  • 腾讯过去不太重视开源,但现在已经积极靠近各大开源基金会。
  • 华为虽然项目少,但基本全是基础设施领域的项目,如 ServiceComb、CarbonData、LiteOS 等。
  • 小米有几个操作系统相关的项目较受欢迎,在大数据领域贡献也不小。

但是,这些中国巨头在底层关键项目上和国外仍然有一定差距。

开发者应积极参与开源项目

全球化浪潮下的今天,开源软件没有国界。作为一名开发者个体,非常有必要关注开源软件领域。参与开源软件的开发,成为项目的主力,最大的收益人其实是开发者自己。

一方面,开源软件孵化于大公司,又经过专业委员会的管理和运作,从技术规范到管理模式都多多少少有大公司的影子。对于希望进一步提升自己的开发者,优秀的开源项目是一本实战教科书。比如,我最近一直在阅读Apache Flink的源代码,从前期设计,到分支修改,到单元测试,到Code Review,再到代码合并,都有一定的流程和规范,即使注释也必须描述得非常清晰,以便其他开发者能够明白当初的设计意图。这些规范甚至比绝大多数公司都正规。开源项目的经历,对于开发者个人的技术和管理都是一次精进。

另一方面,好的开源项目是会说话的简历,能够代表一个人的综合实力。2019年,小米吸引了语音识别领域的大牛Daniel Povey,他是语音识别领域著名开源项目Kaldi的创始人。当他离开约翰·霍普金斯大学寻求新的工作机会时,全世界的人工智能研发机构争相对他发出邀请。他拒绝了美国硅谷的Offer,希望来中国工作。在中国,他得到了清华北大、上海交大等一系列高校和巨头公司的邀请,后来加入了小米。同样,深度学习框架Caffe作者贾扬清曾先后在谷歌大脑、Facebook工作,年纪轻轻的他现在已经是阿里巴巴技术副总裁。当然,这些大牛毕竟凤毛麟角,但普通人通过参与开源项目,也可以打怪升级,逐步提升自己。开源软件PMC肯定能得到各大公司的追捧,即使是一个普通参与者,也能得到用人单位的认可。

小结

在开源浪潮中,商业IT巨头一直在引领时代,其他公司则拿来即用,必要时会购买大公司的开源软件服务。开发者参与开源项目能够增强自身竞争力,是个很好的提升自我的机会。

这是一篇Medium平台上获得上万点赞的优质文章,是一篇不错的关于个人成长的建议,不鸡汤,不做作,不是开口闭口“我有一个朋友”。我认为这篇文章对我和很多人的职场和生活都非常有启发性,尤其是当前疫情全球扩散的大环境下,人与自己、人与人之间的矛盾突然爆发的现实下,冷静的思考对我们都非常有必要。我将其翻译成中文,分享给更多的人。本文原作者Nick Wignall,是一个临床心理学家兼作家。Medium地址:https://medium.com/personal-growth/4-things-emotionally-intelligent-people-dont-do-24ea6ea53992

很多人认为情商就像一种技能,我们可以通过不断的练习来提升情商。

确实,这种观点没错。关于情商,很多人容易忽略的一个重要事实是:提升情商可能并在于你多做了什么,而在于你没做什么。

作为一个心理学家,我在工作中会接触一些看起来情商不那么高的人,他们:

  • 将自身问题的怪罪到他人头上
  • 把自己困在紧张和焦虑的恶性循环里
  • 破坏自己刚刚取得的一些突破和进步

从我个人的经历来讲,很多这样的人并不是天生与高情商无缘。实际上,这些人已经展示出很高的情商潜能。

但不幸的是,因为恶习缠身,这些人的内在潜力被限制了。

如果你想提高你的情商,不妨反观你的生活和工作中是否有本文所介绍的一些恶习。如果有的话,你可以试着尽量去避免他们。你会发现,你的真实情商水平远比你想象的高得多。

1. 批评他人

批评他人是我们人类一种潜意识的自我防御机制,因为批评他人可以减轻我们自己的不安全感。

我们经常带着批判性思维方式去看待问题,这并不是一件坏事。在当前我们所处的世界中,保持一种谨慎且批判的思维方式其实是一种非常重要的技能。它可以帮助我们以一种更客观的方式与这个世界相处。

但是,太多的批判,尤其是动不动就去批评别人,有可能让我们背离客观的初衷。这让我们变得心胸狭窄,心智蒙蔽。

我们习惯性地去批评别人,因为这让我们感觉非常爽:

  • 当你跟你自己说,另一个人是个傻逼,你其实在暗示自己非常聪明。这让你感觉很爽。
  • 当你批评别人幼稚,你其实在告诉自己你很成熟。这让你感觉很爽。
  • 当你默默地跟自己说别人的品味很LOW,你内心其实在秀优越感。这让你感觉很爽。

建设性的批评可以让这个世界更加完美。破坏性的批评呢,只能让你自己感觉很爽而已。

尽管批判他人可以让你短期自我感觉良好,但从长远角度来看,这可能让你陷入更加糟糕的境地。

与上面这类人相反,那些高情商、有自知之明的人知道,批评他人只不过是内心的一次自我防御。面对内心的焦虑和不安,我们应该采取很多能产生实际效果的应对方式。

那些以批评他人为乐的人一直没有意识到:对他人的批评其实只不过是为了缓解自己内心深处的不安全感罢了。

我们必须要明白,批评他人很可能是浪费自己的时间和精力,这些时间和精力本可以用来提升自己或者改变你周围的世界。

“批评他人是自我表彰的另外一种形式。——Fulton J. Sheen”

2. 担忧未来

生活本质上存在大量不确定性,对未来过度焦虑意味着我们对生活本质的否定。

作为人类,我们建立了秩序和确定性。在人类的进化史中,一部分祖先适者生存,因为他们做出决策,降低了未来的各类不确定性。从人的生物本质上来说,我们希望自己不断降低各类生活中的不确定性。

但是,做出合理决策以降低不确定性与因为恐惧而想消灭不确定是有本质区别的。

担忧未来的人一般会非常害怕不确定,而且不敢直面这些不确定。他们试图让自己的未来更加确定,但是使用的方法却南辕北辙,他们想通过不断地考虑未来来消除不确定。

担忧未来的人活在一种假象中,他们认为经常思考未来就能解决问题,对未来的规划可以让事情得到更加充分的准备。但是,我们需要反思:

  • 只在头脑中反复纠结某项问题并不意味着你能建设性和实质性地思考。
  • 脑补无数次的未来各种潜在问题,根据不同的问题做决策规划,并不意味着你真正拥有了解决这些问题的能力。你只是让你觉得你已经准备好了。

对未来的担忧给你了一种确定性的假象。但最终,过度焦虑让你心理脆弱不堪。

高情商的人理解生活本身的不确定性。他们知道,与其否定不确定性,不如冷静地直面生活。

试着不去让压力和焦虑从心理上打败你自己,你会惊喜滴发现,你再次感到自己激情满满、精力无限。

当你不再坚持让这个世界按照你大脑中安排的那样运转,你会发现你能更好地与这个世界相处。

“焦虑不会消除明天的悲伤,它们会掏空今天的力量。 ——Corrie Ten Boom”

3. 沉溺过去

沉溺于过去所做出的的错误决定其实是在误导你自己你可以控制你的生活。

和上一节提到的一样,人类建立了秩序和确定性,我们同时也增强了对周围事物的控制。一直以来我们被灌输这样的观点:基于足够的努力、持续的坚持,我们可以成就一切。

当然,很多人沉溺于过去的错误和失败,他们并不相信他们能够改变过去。他们回顾过去只是为了让自己短暂停留在对生活有控制感的假象之中。

当我们犯了错误,我们会自然而然地感到愧疚和悔恨。沉溺过去的人时不时地将过去犯下的错误一次次在脑中回放重演,这成了一种潜意识的习惯,因为这可以让他们感到一丝控制感。因为之前的错误才导致当下的无助,而那一丝丝的控制可以让他们短暂地逃避内心的无助。

事实上,过分沉溺于历史,频繁分析自己犯下的错误,这些都对已经发生的事情不会有任何影响。无助感和无力感油然而生。

这是一个冷酷的人生真相,高情商的人不仅能够看透,而且可以接受这种真相。

如果你想向前看而不是将自己埋葬在过去,你必须接受过去已经发生的事实,包括他们带给你的无力感。

你必须放弃那些无穷无尽的回忆,尽管这些回忆可以让你从当下的痛苦中暂时解脱。

现在就采取行动,而不是继续停留在过去。立刻马上,去做一些有意义的事情,不论是多小的事。抵制那些脑中时不时浮现出来的各种记忆。

决不能因为沉溺过去而觉得可以控制过去,进而放弃对未来的控制权。

“想得多是一种病。——Fyodor Dostoyevsky”

4. 对他人抱有不切实际的幻想

对他人抱有不切实际的幻想是另一种误导,这让你觉得你可以控制你的家人、朋友或者同事。

沉溺过去让我们觉得我们可以控制已经发生的事情,对他人抱有幻想其实是你的大脑试图在控制其他人。

当然,很多人对他人抱有幻想,但他们自己并不这么觉得。普遍认为,更高的期待是一件好事:对他人的高标准意味着鼓励他人变得更加成熟。

也许吧。但其实这里仍然有一种微妙的控制感。你的潜意识里塑造了一种形象,你周围的人应该按照这个形象去做他们该做的事以达到你的期望。你单方面希望别人按照你的期望行事,希望事情按照你的逻辑发展。

究竟什么是不切实际的幻想?

简单来说,你花大量时间在你的头脑中虚构一些别人应该做的事情。但当事与愿违,别人并没有按照你的期望行事,你自然而然地将现实中别人的所做所为与你的期望相比对,然后你会有很强烈的挫败感和失望感。

接下来,你会如何对这些挫败和失望做出反应?你可能变本加厉,对他人提出更多的要求,因为这样可以让你感觉良好,让你内心夺回控制感。

你当然对周围的人非常关心,你希望他们过的更好。而且,当你看到他们受伤、挣扎、痛苦时,你会感到痛心疾首。所以,你在大脑中对他人塑造了一个更加成功的期望,你会再次自我感觉良好。

但问题是,你无法控制别人,尽管你是为了他们好。有可能你创造了一个恶性的循环:一边是高耸入天的期望,一边是陷入泥土的失望。

更可怕的是,你会不断尝试去控制别人,管得太多,别人反而会慢慢对你产生怨恨。积怨成疾,别人可能会产生强烈的逆反情绪,你对别人做了更高的要求,他们会反其道行之。

这个问题的解决之道是,将这些幻想和期望抛之脑后。你应该停止单方面地虚构一些别人应该遵守的条条框框。你应该更关注他人当下的处境:

  • 了解他们当下所经历的挫折和痛苦,而不是做一些白日梦,梦到别人已经成功。
  • 不要奢求完美,但可以设置一些可操作的边界,并试图让他人在边界内行事。
  • 尝试和当前的他们交流,而不是与你幻想中的他们做朋友。

你可以保留你的美好期望,但是应该放弃不切实际的幻想。

“在他人的幻想之海中,人很可能被淹死。——Robert Jordan”

结论

如果你想提高你的情商,很多时候你需要退后一步。你应该去发现并消除以上这些恶习,这些恶习会严重制约你的情商。

  • 停止批评他人。Stop criticizing others

  • 不要再担忧未来。Stop worrying about the future.

  • 不要再沉溺过去。Stop ruminating on the past.

  • 放弃对他人近乎完美的期望。Stop expecting too much of others.