写点什么

构建可扩展的机器学习系统(一):你所需的架构设计知识

  • 2019-05-20
  • 本文字数:4030 字

    阅读完需:约 13 分钟

构建可扩展的机器学习系统(一):你所需的架构设计知识

本文介绍了机器学习应用中的一些软件工程基础,快速浏览了最流行的一些架构模式、设计模式,以及面向对象设计的 SOLID 原则,目的是让读者尽可能多地了解构建可扩展软件的主要贡献因素。应用程序设计是否能够适应变化,是构建成功解决方案的关键,如果设计过程很仓促,项目结束时,一定会为犯下的错误交学费。

正文

本专题将通过两篇系列文章,介绍与体系结构和设计有关的软件工程基础知识,以及如何在机器学习管道(ML Pipeline)的每个步骤中应用这些基础知识:


第1部分:问题陈述 |架构风格 |设计模式 |SOLID

第2部分:构建机器学习管道

介绍

就像以前在 Steven Geringer 著名的维恩图中看到的,数据科学是 3 个学科的交集:计算机科学、数学/统计学和特定的领域知识。



数据科学维恩图[©Steven Geringer]


拥有基本(甚至是高级)的编程技能,是将端到端的经验结合在一起的关键,但还不足以创建一个可以发布的应用程序。除非从 IT 背景进入数据科学和机器学习(ML),并且在构建企业级的、分布式的、可靠的系统方面拥有实际经验,否则您的 Jupyter 笔记本(译者: 可创建和共享自己的文学化程序文档)没资格成为优秀的软件,遗憾的是,您也不能成为软件工程师!


虽然您打算构建的是一个很好的预测产品的原型,但仍然需要通过工程技术的路线图来推动它。所需要的是一个由专业软件工程师组成的团队,可以将(一次性)概念验证转化为高性能可靠松耦合可扩展的系统!


一切都是设计出来的; 但设计得好的东西很少!


在本系列中,我们将展示如何实现良好设计的一些想法。第一部分从基础知识开始,第二部分逐步设计整体架构。这里建议的架构是技术无关的,机器学习管道将被分解成责任明确的不同层,可以从许多技术堆栈中选择如何来实现每一层。


接下来看看成功的解决方案应该是如何实现的。

问题陈述

我们的主要目标是建立一个系统,具备以下特性:


▸减少延迟;

▸集成系统的其他部分(例如数据存储,报告,图形用户界面),但松耦合

▸可以水平和垂直伸缩

▸消息驱动,即系统通过异步、非阻塞的消息传递进行通信

▸提供工作负载管理相关的高效计算

▸容错和自我修复,即故障管理

▸支持批量和实时处理。

架构风格

我们将首先介绍一个反应式系统,并快速浏览最流行的架构模式。

反应式系统

反应式系统设计范式采用前后一致的方法来建立更好的系统,这些系统是根据“反应式宣言”的原则进行设计的。每个反应式原则对应一个可扩展性的重要系统维度:


• 易响应的 → 时间


• 易扩展的 → 负载


• 可恢复的→ 错误


• 消息驱动的 → 通信。



反应系统的特性

面向服务架构(SOA)

SOA 将业务问题分解为服务,这些服务通过网络来共享信息。它们还共享代码(即公共组件),以保持反应式系统的一致性和特性,从而减少开发工作。


服务提供者发布合约,规定服务的特征以及如何使用服务。服务使用者可以在注册中心中找到服务元数据,开发所需的客户端组件来绑定和使用它。


协调器(Orchestrator)是一个综合服务,负责调用和组合其他服务。此外,编排(Choreography)采用去中心化的方法组合服务,服务通过消息/事件的交换进行交互。



SOA

流式(Streaming)架构

流式架构包括以下组件:


  • 生产者:生成和发送消息的应用程序

  • 消费者:订阅和使用消息的应用程序

  • 主题:类别特定的记录流,存储成有序和不可变的记录序列,通过分布式集群进行分区和复制

  • 流处理器:以特定方式处理消息的应用程序(例如数据转换、ML 模型等)。



流式架构

Lambda 架构

Lambda(λ)架构旨在以集成的方式处理实时和过去聚合的批量数据。它分离了实时和批处理的职责,查询层提供了所有数据的统一视图。


这个概念很简单:生成数据时,会在存储之前对其进行处理,因此分析可以包括最后一秒、最后一分钟或最后一小时生成的数据,只处理传入的数据,而不是所有的数据。



Lambda 架构

微服务架构

微服务是一种架构风格,它将应用程序构造为小型、自主、松耦合和协作的服务集合,围绕业务领域进行建模。这些服务使用同步协议(HTTP/REST)或异步协议(AMQP)进行通信,可以彼此独立地开发和部署。每个服务都有自己的数据库,以便与其他服务分离。



微服务架构

REST 架构

REST 是一种用于开发 Web 服务的架构风格,它建立在 Internet HTTP 的现有特性之上,允许以无状态的方式传输、访问和操作文本数据,即应用程序可以在不知道状态的情况下进行通信。


RESTful API 服务通过统一资源定位器(URL)公开,提供了创建、请求、更新或删除(CRUD)数据的功能。它最适合处理解耦(生成/消费的 ) 信息和(生成/使用信息的 ) 技术的系统。



REST 架构

设计模式

我们将浅显地介绍这个主题,并且只讨论我在本系列的第二部分中可能提到的那些模式。(虽然我每天都在使用它们,但很难用简单的语言全部解释清楚)


软件设计模式是针对软件工程中常见问题的优化的、可重复的解决方案。它是一个解决问题的模板,可以在许多不同的情况下使用。

策略

策略模式定义了一系列算法,将每个算法放在一个单独的类中,相互之间可互换。将行为封装在单独的类中,消除了任何条件语句,在运行时可以选择正确的算法(即策略)。


  • 使用说明:业务规则有不同的实现,或者需要算法的不同变体。



策略模式

模板方法

模板方法旨在从不同的过程中抽象出一个通用的过程。它定义了算法的骨架,将某些步骤推迟到子类。子类可以覆盖某些行为,但不能更改骨架。


  • 使用说明:遵循一系列一致的步骤,各个步骤可能有不同的实现。


⭐ 与策略模式的区别


  • 模板:子类编译时选择算法。

  • 策略:控制运行时选择算法。



模板方法模式

责任链

责任链模式通过启用一个或多个处理程序来满足请求,避免将客户端(请求的发送者)与接收者耦合。这些处理程序连接到一个链中,每个处理程序都包含对链中下一个处理程序的引用。



  • 使用说明:多个对象可以处理一个请求,处理程序(或序列)的优先级事先不知道。



责任链模式

观察者

观察者模式(缩写为 Publish/Subscribe 或简称 PubSub)通过定义对象之间的一对多依赖关系,可以轻松地进行通信广播,当一个对象的状态发生变化时,它的所有依赖关系都会自动得到通知和更新。观察者负责注册它们所“观察”的事件。


  • 使用说明:当改变某个对象时同时需要改变其他对象,不知道多少对象需要改变。



观察者模式

建造者

建造者模式旨在逐步构造一个复杂的对象,分离构造与表示。实质上,它允许使用相同的代码,生成对象的不同类型和表示形式。


  • 使用说明:虽然各个构造步骤有所不同,但可以使用相同的整体构建过程来构建多种复杂对象。



建造者模式

工厂方法

工厂方法定义了一个用于创建对象的接口,由子类来完成实例化。


  • 使用说明:对象的具体类型和依赖关系事先不知道。



工厂方法模式

抽象工厂

抽象工厂关注如何创建相关产品的系列,不指定它们具体的类。


  • 使用说明:不同的规则采用不同的实现,这些规则要么是未知的,要么是可扩展的。


⭐️ 与抽象方法的区别


  • 抽象工厂:创建其他工厂,这些工厂反过来创建从基类派生的对象。

  • 抽象方法:创建从特定基类派生的对象。



抽象工厂模式

装饰

装饰模式动态地将新的职责附加到对象上,将对象放置在包含行为的特殊包装类(wrapper)中,因此不会影响原来方法的签名(继承上的组合)。


  • 使用说明:运行时为对象分配额外的行为,不会破坏使用这些对象的代码。



装饰模式

仓库

仓库模式解决了数据检索和持久化的代码集中化问题,并为数据访问操作提供了抽象,类似内存中域对象的集合,允许执行 CRUD 方法,消除了各种数据库问题。


  • 使用说明:分离业务逻辑和访问数据的代码。



资源库模式

小奖励

想进一步了解模式?可以先从“Gang of Four”的书《设计模式:可重用的面向对象软件的基础》开始。下面的图展示了模式之间的关系,非常重要:



设计模式之间的关系

SOLID

我们唯一的设计原则是 SOLID,它们对于每个软件开发人员来说都是必不可少的。


正如Bob大叔所说:它们不是法律,也不是完美的真理。它们类似于一个规则:每天一个苹果,医生远离我 ”。


这意味着,它们不是某种“魔法”,不是带来牛奶、蜂蜜和优质软件的应许之地,它们是健壮、持久软件的关键贡献者。


简而言之,这些原则围绕两个主要的概念展开,是成功企业应用程序的基石:耦合是类了解另一个类并与之交互的程度;而内聚表示类具有单一用途的程度。换一种说法:


- 耦合是关于类如何相互作用的;

- 内聚关注单个类的设计方式。

单一责任原则

一个类应该有一个,而且只有一个变化的理由


这是不言自明的,但说起来容易做起来难。我们总是想在现有类中添加新的行为,但这是一个引发灾难的处方:每个行为都可能成为未来变化的理由,因此行为越少,在变化时产生错误的机会就越少。

开闭原则

能够扩展类的行为,而无需对其进行修改


类应该对扩展“开放”,但是对修改“关闭”。要实现这一点可以通过继承,即创建一个子类,关闭对原始类进行修改,将自定义的代码添加到子类来引入新的行为。

里氏替换原则

派生类必须可替代基类


当类 A 的行为扩展到子类 B 时,可以确保在不造成任何破坏的情况下用 B 替换 A。这点可能比较吸引人,特别是当把这一原则与开闭原则结合起来时。

接口隔离原则

创建特定于客户端的细粒度接口


接口和类必须尽可能特定,客户端的调用不依赖未使用的方法。这与单一责任原则是一致的。

依赖倒置原则

依赖抽象,而不是具体实现


高层的类不应该依赖于低层的类。它们都应该依赖于抽象。同样,抽象不依赖于细节,细节依赖于抽象。

小奖励

我创建了下面这个快速参考图。如果想知道左边小符号的灵感来自哪里,请参看:“SOLID原则,用励志海报解释” —— 我喜欢作者在这些原则上增加的有趣改变???。



SOLID

脚注

这里无法涵盖所有软件工程概念的详尽列表,它只是阅读下一篇文章的基础,我希望它能让读者了解构建可扩展软件的主要贡献因素。应用程序设计是否能够适应变化,是构建成功解决方案的关键,如果设计过程很仓促,项目结束时,一定会为犯下的错误交付学费。


好的设计是易懂的。伟大的设计是透明的。


原文链接https://towardsdatascience.com/being-a-data-scientist-does-not-make-you-a-software-engineer-c64081526372


2019-05-20 17:226833
用户头像

发布了 43 篇内容, 共 34.3 次阅读, 收获喜欢 136 次。

关注

评论

发布
暂无评论
发现更多内容

盘点:2021年最新、最全、最实用的Java岗面试真题,已收录GitHub

Java 架构 面试

2021年前端趋势预测

阿里巴巴 开源 大前端 Web框架 逻辑编排

百度亮相全球量子信息处理顶会QIP2021 推动全球量子科技进步

爱极客侠

即构发布 LCEP 产品「RoomKit」 ,实现房间内0代码接入

ZEGO即构

LoraWan的第一个网关与设备

远鹏

物联网 IoT ChirpStack LoraWan

【得物技术】AB实验设计实现与分流算法

得物技术

算法 AB AB testing实战 实现 得物技术

Spring Boot 微服务性能下降九成!使用 Arthas 定位根因

Java架构师迁哥

产品经理训练营第二章作业2

阿波

Kubernetes 原生 CI/CD 构建框架 Argo 详解!

字节跳动 Kubernetes 云原生 CI/CD argo

为什么联盟链系统没有“激励”?

CECBC

区块链

LeetCode题解:529. 扫雷游戏,BFS,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

登上 Github 趋势榜,iMove 原理技术大揭秘!

阿里巴巴 开源 大前端 Web框架 逻辑编排

iMove 基于 X6 + form-render 背后的思考

阿里巴巴 开源 大前端 Web框架 逻辑编排

OpenCV--基本的线条操作

IT蜗壳-Tango

七日更 2月春节不断更

阿里新晋 CNCF TOC 委员张磊:“云原生”为什么对云计算生态充满吸引力?

阿里巴巴云原生

云计算 容器 微服务 云原生 cncf

F2C能否让前端像运营配置一样开发?

阿里巴巴 开源 大前端 Web框架 逻辑编排

架构师week11 作业

Geek_xq

正点原子DS100拆解全过程-硬件工程师必备

良知犹存

嵌入式

通过配置开关 Spring Boot 中的 @Scheduled 定时任务

和白白

Java 定时任务 springboot

SDS离全面EC(纠删码)还有多远?

XSKY星辰天合

存储

2021最新发布百度云面经总结:Java并发+Redis+数据库+分布式

比伯

Java 程序员 架构 面试 计算机

因果迷境:为什么我们会问“为什么”?

脑极体

所见即所得! iMove 在线执行代码探索

阿里巴巴 开源 大前端 Web框架 逻辑编排

架构师week11总结

Geek_xq

用 JSX 实现 Carousel 轮播组件

三钻

大前端 组件化 JSX

日记 2021年2月5日(周五)

Changing Lin

个人感悟 2月春节不断更

【LeetCode】尽可能使字符串相等

Albert

算法 LeetCode 2月春节不断更

团队中的三种成员

熊斌

学习 管理 2月春节不断更

威联通(NAS)应用篇:自建OwnCloud网盘(百度网盘,拜拜~~~)

BigYoung

NAS 威联通 28天写作 2月春节不断更

【百度技术分享】San介绍以及在百度APP的实践

百度Geek说

Java JavaScript feed

第十一周作业&总结

胡益

构建可扩展的机器学习系统(一):你所需的架构设计知识_AI&大模型_Semi Koen_InfoQ精选文章