看到@ 爱可可-爱生活转发的文章。稍微看了下,在这里记录下。
overfit是机器学习的一个重要概念。在狭义上可以定义为模型过于复杂,导致模型的generalization不够好。我认为应采用一个广义的定义凡是generalization不行的,都可以定义为overfit。从我的定义出发的话,可以认为这个文章围绕overfit展开,从三个方面讨论了这个新手老鸟都会犯的错误。
第一部分概述了overfit,这一部分可看作从建模的复杂度来讨论overfit,你的模型越复杂越容易overfit。其中overfit是memorizing而不是learning的比喻很贴切。我们需要通过something学到规律而不是仅仅简单的记住someting。我补充下,overfit可以通过bayes的prior来引入regulatization,从而提高generalization。
第二部分从数据的角度来讨论overfit,你用来训练的数据也会带来overfit。这部分可分成两个小节:首先,bias的训练数据当然会bias你的预测,generalization不够好,overfit随之产生。其次,leakage的训练数据,会引入测试数据的规律到模型中,等于您白测了,cross-validating的hyper-param作废了,不能generalization,于是overfit又来了。的确很多论文都没注意这一点,微软就闹过这种笑话。
本文链接:关于overfit的随笔,转载请注明。
新来老大年前开会说:各位同学,公司业务越来越重,未来几年要成倍增长......,我们要梳理出一套新架构,才能更好的支持N万用户.....,以后升职加薪当上....打败.....
想想还有点小激动呢,于是过年时楼主趁等待相亲妹纸无聊的时候,反思了目前系统现状,构思设计新架构如下。
阅读目录:
- 现有系统
- 新架构
2.1 逻辑架构图
2.2 解释说明 - 系统实施
3.1 SOA管理中心
3.2 发布服务
3.3 订阅服务
3.4 采蘑菇示例 - 设计目标
4.1 尽可能少的侵入
4.2 服务自治&&水平扩展
4.3 系统升级降级 - 常见问题
5.1 ClientApi VS ServiceApi
5.2 聚合服务
5.3 服务分级 - 总结心得
鄙司业务比较重,系统也有些年头,各研发团队、系统都比较稳定了。所以不差也不太好,总之也能满足现有需求。但近2年O2O,移动互联网等大行其道,老大们也都心动了,开始磨刀霍霍了。而现有系统应对复杂的变化,在一些地方颇显不足:
- 接口没有统一管理
- 很多组件无法复用/重复造轮子
- 模块间职责不清,耦合过深
- 联调排查问题比较慢
- 开发前规划不足,形成堆积
- 缺乏API规范/文档较少
- A开头:是系统级别,可以独立部署。即可寄宿在IIS/WindowsService等上面。
- B开头:是模块级别,不可独立部署。相对独立的功能模块,而又不大,所以依附其他系统或者和多个模块组成一个子系统。模块级别在项目中可以分多层,可根据分数升级成子系统(见系统升级降级)。
- C开头:是组件级别,不可独立部署。大多数是公共性组件,一般是单独类库存在,以DLL提供使用。一些开源组件也归到这里,例:Aufofac,FluentData。 需要自搭Nuget服务器,进行统一版本管理。
- 字母后面的数字:是代表服务的级别,见服务分级。
- 系统通信: 各系统之间尽量走内网Wcf/Tcp,对外合作单位及各移动端走WebApi/Http。
- 传输格式: Protobuffer、Json。
- 数据交换: 优先通过数据服务接口,其次SSIS、Job。
- 基础平台: 缓存Redis,队列RabbitMq等。依赖抽象,框架可替换。
- DB 层: 每个子系统拥有自己的子DB,原则上不能跨库读其他的。
- 高可用 : 子系统自行做负载,服务变更通知使用zookeeper。
- 单向2级:只能订阅服务,不能发布服务,2级只能订阅2级服务。
- 定点:某个客户端只能订阅某个服务端提供的服务。
这是新架构的核心部分,主要功能如下:
- 提供发布/订阅/ServiceAdapter组件
- 提供Web管理界面
- 对服务访问的各种配置
- 在高峰期对服务限流/报警
- 服务访问授权、描述
各系统通过Web管理页面进行服务配置发布。
也可以通过管理中心提供的组件,进行配置发布:
{
ServicePublisher.Pushlish(new ServiceConfig()
{
ServiceName = "获取预订单详情",
Qps = 1000,
Level = 1,
Key = "xxxx-yyyy",
Source = SubscribeSource.All,
ServiceAddress = "/Order/GetDetail",
//其他
});
}
[ServiceFilter]
void GetDetail()
{
}
各系统通过管理中心提供的组件,去获取订阅的服务,然后通过适配器去访问接口,服务变更在心跳里面做:
{
//获取服务列表
var serviceList = ServiceManager.GetServiceList();
GlobalService.ServiceList=serviceList;
}
void Heartbeat()
{
var serviceList = ServiceManager.GetServiceList();
GlobalService.ServiceList=serviceList;
}
ServiceAdapter.Access(GlobalService.ServiceList[0]);
这点是非常重要的,如果不能很好的重用已有的系统或侵入性太强,势必会导致:
- 新架构周期过长,长期维护二套结构。这种情况下,成本太高,不好推行下去或者还未推行就被砍了。
- 开发人员的抵抗,每个猿类内心都有桀骜的脾气、造轮子的天赋、重组世界的梦想...。如果太复杂、约束太强,天知道你们这群猿类会干出什么事情!
基于这种考虑,才采用服务分布式而不是服务集中式。
- 每个系统在需要时,去订阅服务,然后拉取服务地址/MyNeedServcie.list。
- 然后通过ServiceAdapter访问服务,ServiceAdapter中会做权限等一些校验。
- 在服务上增加ServiceFilter,Fileter会做权限校验及服务被调用的信息采集。
- 然后在管理中心添加服务,文档描述。
好处是:A系统与B系统是直接交互的,服务调用不走中转路由,性能也好。而组件的作用仅是辅助性的约束。
由于侵入性较小,所以各个系统之间的服务变更,维护完全由各自研发团队维护。
本系统之间通讯不走服务,直接内部调用。调用通过ServiceAdapter组件访问,ServiceAdapter包含对进程内、WCF、WebApi等访问的封装,这样便于以后替换成其他服务。 各服务在扩展上不受管理中心节制,自行做负载、增加服务器即可。
当有个新需要过来时,会根据产品是否需要独立部署,和现有系统耦合性等因素,来评估是模块级还是系统级。
对于旧模块,根据重要程度、访问量等评估出分数。达标的由模块抽离出子系统,单独管理。
同样对于旧系统,不达标的进行降级处理,缩小成模块整合到其他系统里面。
这块其实很重要,如果不对项目做好评估的话,往往会导致一个系统越来越沉重。最后的结果就是维护越来越麻烦,经常出问题。最后逼不得已就推到重来,这个成本就较大些,当然成本的事情老大会考虑更多些。处于这种情况下猿类们会一边吐槽着之前的同类渣渣,一边跃跃欲试准备大展身手,让你们瞧瞧什么叫DDD、TDD、设计模式......。
前提是在需求开发时,按模块进行分小层而不是整个大层,这样方便协作开发和抽取成子系统。
ClientApi这个在前期用的比较多的办法。优点很明显:简单快捷,从Nuget上安装引用即可。这样后期会问题越来越多。
就拿缓存Redis来说,多个系统都使用客户端直接访问Redis服务器。如果有个系统连接数忘记关闭,就会影响整个大系统,原因就是Client权限过大,客户端是可以对redis服务器直接进行操控。这种情况下redis服务器本身是暴露在外的,哪怕客户端封装的再好也不行,只要研究下通信协议规范,就可以自己写个客户端连(参见:c#实现r
没有评论:
发表评论