LeeYzero的博客

自强不息,厚德载物

0%

最近两个月学完 Andrew Ng机器学习 课程,对机器学习有了一个整体的认识,感谢Andrew Ng及其团队,能够让机器学习这门专业学起来如此生动有趣。本文是对课程的学习笔记,主要目的是从宏观角度对机器学习整体框架和核心概念有基本认识并形成知识框架,以便在后续遇到实际问题时,能够进一步深入学习并解决实际问题。

什么是机器学习

机器学习(Machine Learning,简称ML)是人工智能(AI)的一个核心分支,是使计算机具有像人一样的学习能力的技术,其核心目标是让计算机系统通过从数据中自动学习规律和模式,从而完成任务或做出预测,而无需显式编程。

机器学习的核心是数据驱动和迭代优化:

  • 数据驱动:机器学习依赖大量数据,通过分析数据中的统计规律、关联性或结构,形成模型(如分类规则、预测函数等)。
  • 迭代优化:系统通过不断调整模型参数(如神经网络的权重)来减少预测错误,逐步模型的准确性和性能。

机器学习的类型

根据所处理的数据种类的不同,机器学习可以分为有监督学习无监督学习强化学习

有监督学习

有监督学习(Supervised Learning),是机器学习的一个分支,是指通过输入带有标签(正确答案)数据,模型学习输入到输出的映射。监督学习的核心是,从已知答案中学习规律

如果把机器学习用一个函数表示:

1
y = f(x)

x为输入,y为输出,f为模型,监督学习就是给定x和y,让机器学习f的过程。

监督学习也可以理解为,一位学生从老师那里获取知识,老师提供对错指示,告知最终答案的学习过程。学生对应于计算机,老师则对应于周围环境。根据在学习过程中所获得的经验、技能(即模型f),对没有学习过的问题也可以做出正确解答(推理),使计算机获得这种泛化能力。

监督学习在手写文字识别、声音处理、图像处理、垃圾邮件分类与拦截、基因诊断以及股票预测等方面都有广泛应用。

无监督学习

无监督学习(Unsupervised Learning)是机器学习的一个分支,是指通过无标签数据,模型自行发现隐藏结构(如聚类、降维)。核心在于从无标签数据中自动发现隐藏的结构、模式或规律,无需依赖人工标注的答案。与监督学习不同,无监督学习的目标是探索数据内在的分布特性,常用于数据探索、特征提取或预处理。

无监督学习也可以理解为,在没有老师的情况下,学生自学的过程(无师自通)。

无监督学习在客户分群市场分析、图像与信号处理、推荐系统、异常检测、自然语言处理、生成与合成等方面都有广泛应用。

强化学习

强化学习(Reinforcement Learning)是机器学习的一个分支,其核心在于让智能体(Agent)通过与环境的交互学习最优策略,以最大化长期累积奖励。与监督学习(依赖标注数据)和无监督学习(探索数据分布)不同,强化学习通过“试错”机制在动态环境中自主决策,广泛应用于需要序列决策的复杂任务。

强化学习在游戏与竞技、机器人控制、自动驾驶、资源管理与优化、推荐系统(动态个性化推荐)以及医疗与健康都有广泛应用。

机器学习的基本流程

问题定义

通过需求分析,明确输入、输出和约束条件,将业务问题抽象为机器学习问题。主要包括:

1、任务类型:明确机器学习任务,如回归、分类、聚类、强化学习等。
2、业务目标:将业务需求转化为可量化的机器学习目标,如预测用户点击率。
3、评估指标:选择合适的评估标准,如准备率、RMSE、AUC等。

数据准备

1、数据收集与清洗:消除噪声,保证数据质量。
2、特征工程:通过提取关键信息,提升模型对数据的表达能力。
3、数据增强:扩充数据多样性,防止过拟合。

模型选择

1、算法匹配问题:不同算法解决不同任务。

  • 回归任务:线性回归、梯度提升树(GBDT)、LSTM(时间序列)。
  • 分类任务:逻辑回归、随机森林、SVM、神经网络。
  • 聚类任务:K-Means、DBSCAN、层次聚类。

2、超参数调优:平衡模型复杂度与泛化能力。

  • 网格搜索(Grid Search):遍历预设参数组合,选择最优解。
  • 随机搜索(Random Search):高效探索超参数空间。
  • 贝叶斯优化:基于概率模型指导参数搜索方向(如Hyperopt库)。

模型训练

模型训练方法多种多样,主要根据数据使用方式、优化策略和学习模式进行分类。

1、基于梯度下降的优化方法:通过调整模型参数以最小化损失函数,梯度下降又包括:

  • 批量梯度下降(Batch Gradient Descent):每次迭代使用全部训练数据计算梯度,更新参数。
  • 随机梯度下降(Stochastic Gradient Descent, SGD):每次迭代随机选择一个样本计算梯度,更新参数。
  • 小批量梯度下降(Mini-batch SGD):折中方案,每次使用一小批样本计算梯度。

2、正则化与防过拟合方法:通过约束模型复杂度提升泛化能力

  • 早停法(Early Stopping):在验证集性能不再提升时提前终止训练。
  • Dropout:训练中随机丢弃部分神经元,增强鲁棒性。

3、数据驱动的增强方法:通过数据变换提升模型鲁棒性

  • 数据增强(Data Augmentation):对输入数据进行变换(如旋转、裁剪)以扩展数据集。
  • 对抗训练(Adversarial Training):生成对抗样本并加入训练,提升模型抗干扰能力。

4、迁移与自适应方法

  • 迁移学习(Transfer Learning):复用预训练模型参数,微调(Fine-tuning)新任务。
  • 领域自适应(Domain Adaptation):调整源域和目标域分布差异。

5、集成方法:组合多个模型提升整体性能

  • Bagging(Bootstrap Aggregating):通过自助采样训练多个模型并投票。
  • Boosting:序列化训练模型,后续模型修正前序错误。

6、强化学习方法:通过环境交互优化策略

  • Q-learning:基于价值迭代更新动作策略。
  • 策略梯度(Policy Gradient):直接优化策略函数参数。

7、半监督与自监督方法:利用无标注数据辅助训练:

  • 自训练(Self-training):用模型预测结果作为伪标签迭代训练。
  • 对比学习(Contrastive Learning):通过相似性对比学习数据表示。

8、分布式训练方法:加速大规模数据训练:

  • 数据并行(Data Parallelism):拆分数据到多个设备并行计算梯度。
  • 模型并行(Model Parallelism):拆分模型参数到不同设备。

模型评估

根据任务类型选择指标,量化模型性能。

1、分类任务

  • 准确率(Accuracy):正确预测样本数占总样本数的比例。
  • 精确率(Precision)与召回率(Recall):精确率是指预测为正的样本中实际为正的比例;召回率是指实际为正的样本中被正确预测的比例。
  • F1-Score:精确率和召回率的调和平均,综合衡量模型性能。
  • ROC 曲线与 AUC:ROC 曲线展示不同阈值下的 TPR(真正例率)与 FPR(假正例率),AUC 值越接近 1 模型越好。

2、回归任务

  • 均方误差(MSE):预测值与真实值差的平方均值,对异常值敏感。
  • 平均绝对误差(MAE):预测值与真实值差的绝对值均值,更鲁棒。
  • R²(决定系数):模型解释数据方差的比例,越接近 1 越好。

3、聚类任务

  • 轮廓系数(Silhouette Coefficient):衡量样本聚类紧密度和分离度,范围 [-1, 1],越大越好。

模型部署与应用

该过程更多是对模型的工程化。是指将模型集成到实际系统(如推荐系统),并通过监控系统,持续检测数据漂移(如特征分布变化)、模型性能衰减等,再根据数据和业务的变化对模型进行迭代。

机器学习的应用

机器学习作为人工智能的核心技术,已广泛应用于多个领域,深刻改变了传统行业的运作模式,主要应用场景包括但不限于:

1、计算机视觉(CV)

  • 医疗影像分析:辅助医生检测肿瘤(如乳腺癌筛查)、分析X光片和MRI图像。
  • 自动驾驶:实时识别行人、车辆和交通标志,支撑特斯拉、Waymo等系统。
  • 安防监控:人脸识别用于公共安全(如机场安检)、异常行为检测(如商场防盗)。

2、自然语言处理(NLP)

  • 智能客服:ChatGPT、客服机器人(如银行服务)处理用户查询。
  • 情感分析:舆情监控(如品牌声誉管理)、社交媒体情绪追踪。
  • 机器翻译:谷歌翻译、DeepL支持多语言实时转换。

3、推荐系统

  • 电商平台:亚马逊、淘宝的个性化商品推荐,提升用户购买率。
  • 内容平台:Netflix、YouTube的影视推荐,抖音的短视频推送。

4、金融

  • 欺诈检测:信用卡异常交易识别(如PayPal的风险模型)。
  • 量化交易:高频交易算法预测股价波动(如对冲基金RenTec)。
  • 信用评分:蚂蚁金服的芝麻信用评估用户还款能力。

5、工业与物联网(IoT)

  • 预测性维护:工厂设备故障预警(如西门子工业AI)。
  • 供应链优化:需求预测(如沃尔玛库存管理)、物流路径规划。

6、医疗健康

  • 药物研发:DeepMind的AlphaFold预测蛋白质结构,加速新药开发。
  • 个性化治疗:基于患者数据的定制化诊疗方案(如IBM Watson Oncology)。

7、教育

  • 自适应学习:Knewton平台根据学生表现调整课程难度。
  • 智能阅卷:自动批改作文(如ETS的e-rater系统)。

机器学习、神经网络、深度学习、Transformer以及大语言模型之间的关系

ChartGPT出现后,大语言模型、Transformer等名词频繁出现在各类文章中。那机器学习、神经网络、深度学习、Transformer以及大语言模型之间是什么关系呢?

机器学习(Machine Learning)是人工智能的一个分支,让计算机通过数据自动学习规律,而不需要显式编程,完成预测或决策任务。

神经网络(Neural Networks)是受生物神经元启发设计的数学模型,由相互连接的“神经元”组成,能通过调整权重从数据中学习,它是机器学习的一种具体实现方式。

深度学习(Deep Learning)属于神经网络的分支,强调“深度”结构,通过增加隐藏层数量(“深度”)提升模型对复杂数据(如图像、文本)的表征能力。

Transformer是深度学习中的一种新型架构,是2017年 Google 在论文《Attention Is All You Need》中提出,旨在解决 RNN 的序列处理效率低和长程依赖问题。

大语言模型(Large Language Models, LLMs)是基于 Transformer 架构的超大规模预训练模型,是Transformer架构的典型应用。

cover


这篇文章基于最近在团队内做了一次分享,并做了一些简单修改,仅供各位网友参考,观点不一定成熟,但都是结合实际问题的一些反思与总结,欢迎讨论。

在软件的整个生命周期中,80%以上的时间是在维护软件,这也是开发者每天面临的最主要的工作。如果对代码的变更没有“章法”,随着时间流逝,软件就会不可避免地渐渐变得复杂、难以理解,最终拖慢产品迭代效率,甚至频繁引入线上故障,导致业务损失。

对于这个主题,Working Effectively with Legacy CodeRefactoring Improving the Design of Existing Code 给出了很多具体的做法,本文不会一一介绍。本文主要分为两部分:

  • 第一部分主要介绍软件的变更机制以及应对变更的策略,并着重介绍安全变更的重要保障——单元测试;
  • 第二部以通过一个案例解释如何进行安全重构;
Read more »

本文介绍计算机科学先驱David. L. Parnas在1972发表论文 On the Criteria To Be Used in Decomposing Systems into Modules。这篇论文首次提出了信息隐藏(information hiding)的思想,这一思想为面向对象程序设计的发展奠定了基础。在这篇论文中,Parnas 通过一个简单的例子论证和说明,如何将一个复杂系统分解为模块的标准。

这是一篇真正的经典论文!50多年过去了,虽然软件开发工具(如编译器、编程语言、IDE、中间件等)得到了长远发展,但软件开发的思想却并没有超越这篇论文。如果将论文中的模块换成服务,这一标准仍然适用于当前流行的微服务架构。

本文作者经历过几个大型软件的设计与开发经验,深刻理解模块化编程在复杂系统开发中的重要性,读完这篇论文后,有很多共鸣。本文是对这篇论文解读并谈谈自己的一些理解。

核心思想

摘要中的第一句话便给出了论文的目标:

This paper discusses modularization as a mechanism for improving the flexibility and comprehensibility of a system while allowing the shortening of its development time.

本文讨论了模块化作为一种提高系统灵活性和可理解性的同时缩短开发时间的一种机制。

灵活性可理解性在整个软件生命周期中,都是在解决同一个问题——开发效率,但侧重的阶段不一样。灵活性更强调在软件开发阶段,提高开发效率;可理解性则更多体现在软件维护阶段将具有更低成本。

Read more »

cover


最近本来想写一篇如何应对复杂系统的文章,偶然读到John Ousterhout软件设计哲学,读完后,发现我没有必要再写了。这篇文章对原文做一个概要性总结并谈谈自己的理解和思考。

对于一个软件系统,需求可以粗略的分为两类:

  • 功能性需求
  • 非功能性需求

功能性需求是面向用户的,非功能性需求是面向系统的,但非功能性需求最终是服务于功能性需求。我们通常会用非功能性需求去评估一个系统的质量,比如扩展性、维护性、安全性等。

那什么是软件设计呢?软件设计就是折衷(Trade Offs)。实际情况下,资源是受限的,需求面临着各种因素的制约,软件设计就是在有限资源条件下对影响因素的一种权衡。而这本书从另一个角度阐明了:软件设计即管理复杂性。在我看来,它更偏向于对非功能性需求的一种定义。

围绕着复杂性这个主题,这本书回答了以下三个问题:

  • 什么是复杂性?
  • 软件系统为什么会变得复杂?
  • 如何降低软件系统的复杂性?
Read more »

Leslie Lamport 在1978年发表了一篇论文Time, Clocks, and the Ordering of Events in a Distributed System,对分布式系统领域产生的深远影响,这篇论文也成为分布系统领域引用最高的文献之一。

论文中定义了分布式系统中事件的”happen before”关系,并引入了逻辑时钟解决分布式系统中事件同步的问题。但由于系统之外的信息传递并不受系统内部逻辑时钟的约束,所以会出现因果不一致的问题。于是论文中又提出物理时钟,只要能保证各进程中物理时钟同步在一个合理误差范围内,就能保证系统的全局排序。

读完后,除了对分布式系统中事件同步有了新的认识外,也对系统设计有了一些新的思考。这篇文章主要对论文做一些解读并谈谈自己的解理。

相对论的启示

据Leslie Lamport本人回忆,当他看到Paul Johnson和Bob Thomas的论文The Maintenance of Duplicate Databases中使用时间戳来提供分布式系统中的全局一致性时,他立即看出了算法中存在的问题。他之所以能够一下看出其本质,原因在于他对相对论有深刻的认识:

Special relativity teaches us that there is no invariant total ordering of events in space-time; different observers can disagree about which of two events happened first. There is only a partial order in which an event e1 precedes an event e2 iff e1 can causally affect e2.

狭义相对论告诉我们,时空中事件不存在绝对的全局顺序;不同的观察者可能对两件事件中哪件先发生持有不同的看法。事件在时空中只存在部分有序,只有当 e1 对 e2 产生因果影响时,事件 e1 才先于事件 e2。

Read more »

有些人在碰到问题时,就想:“我知道,我可以使用正则表达式。”现在,他们就有了两个问题。
– by Jamie “jwz” Zawinski, 1997年 8月

什么是正则表达式

正则表达式(Regular Expression),通常缩写为regex或regexp,是一种在文本中进行搜索和替换的模式描述语言。它使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。正则表达式是由普通字符(例如:字母和数字)以及元字符组成的。

这篇slide 描述正则表达式的发展历史。
regular-expressions是学习正则表达式的一个非常好的网站。

初识正则表达式

我们在日常中可能已经使用过正则表达式,比如我们在电脑中查找所有doc文档时,会使用*.doc搜索,这个就是正则表达式。其中*为元字符,表示可以匹配任意字符。.doc是普通字符,表示后续为.doc的文档。

当然这是一个比较简单的例子,正则表达式的功能非常强大,它提供了很多的特性,非常灵活。

在自己的日常开发过程中,有两种场景使用正常表达式比较多:

  • 使用Linux命令,如grepsedawk中的提供的正则表达式能力查询日志。
  • 使用各语言,如PythonPHPGo中提供的正则表达式库在大文本中查找目标字符串。

熟练掌握正则表达式,在处理字符匹配的问题上可以事半功倍。

Read more »

工欲善其事,必先利其器。作为一个曾经的资深vim党,在使用过CodeServer后,基本上不再使用vim了。CodeServer作为vscode的云端IDE,再也不用搭建本地开发环境了。之前介绍了 CentOS搭建CodeServer环境,只需要几步,就可以搭建自己的云端IDE,非常方便。

vscode-go是vscode中针对Go语言的扩展,提供了丰富的特性,包括:

  • 智能感知(IntelliSense)
  • 代码导航(Code navigation)
  • 代码编辑(Code editing)
  • 诊断(Diagnostics)
  • 增强的测试和调试支持(Enhanced support for testing and debugging)

vscode提供了语言无关的调试适配协议 Debug Adapter Protocol,使用各语言可以基于vscode的扩展实现各自的调试器。对于Go语言,其实现为dlv-dap

本文主要介绍在vscode如何使用vscode-go提供的debugging能力对go代码进行调试。

Read more »

缘起

最近出现一例json.Unmarshal导致的精度丢失引发的线上问题,虽然这个问题在被及时发现,未对业务造成损失,但细挖这个问题的原因仍然比较有意思。这篇文章会从技术层面深入分析json.Unmarshal精度丢失的原因以及处理建议,以避免后续开发过程中再次踩坑。

Part1 中,我们着重说明了json.Unmarshal处理大整数可能出现精度丢失的问题,但遗留了一个问题,即大整数置换成浮点数时,为什么会造成精度丢失,在这篇文章中我会详细解释原因。

Go语言对浮点数的处理遵循IEEE-745标准,该标准规定了浮点数在计算机中的二进制表示以及舍入方式,下面先补充一些基础知识,然后再结合 Part1 中的case,分析精度丢失的原因。

十进制与二进制

十进制用0-9表示,逢十进一,同时二进制用0和1表示,逢二进一。而每个位可以使用位的值乘以位的权重表示,直接看例子:

十进制12.34可以表示为:
12.34 = 1×101 + 2×100 + 3×10−1 + 4×10−2 = 12.34

同理二进制101.11也可以表示为:

101.11 = 1×22 + 0×21 + 1×20 + 1×2−1 + 1×2−2 = 4 + 0 + 1 + 1/2 + 1/4 = 5.75

十进制小数点向左移动1位相当于将该数除以10,向右移动1位相当于将该数乘以10。
例如:123/10 = 12.3,12.3×10 = 123。

同理,二进制小数点向左移动1位相当于将该数除以2,向右移动1位相当于将该数乘以2。

例如:11/2 = 1.1,1.1x2 = 11

Read more »

缘起

最近出现一例json.Unmarshal导致的精度丢失引发的线上问题,虽然这个问题在被及时发现,未对业务造成损失,但细挖这个问题的原因仍然比较有意思。这篇文章会从技术层面深入分析json.Unmarshal精度丢失的原因以及处理建议,以避免后续开发过程中再次踩坑。

在分析这个问题的过程中,发现涉及Go对浮点数数值的处理,又涉及IEEE-745标准中的一些细节,放在一篇文章中会增大文章的阅读难度,故拆分成了两个部分:

  • Part1: 引出json.Unmarshal处理大整数可能出现精度丢失的问题,并浅层次分析原因以及解决办法。
  • Part2: 先补充IEEE-745的背景知识,然后解释为什么json.Unmarshal处理大整数可能会出现精度丢失。

示例

这个问题的现象是,原始json string是一个字典,其中包含了一个大整数,在业务场景中,需要向该字典中追加一些字段,然后再序列化后进行存储。为了使用上的方便,代码中使用map[string]any去接收json.Unmarshal的结果,然后再使用json.Marshal序列化,结果发现序列化后的大整数跟原始大整数不致。

下面代码片段做了一些简化,同时忽略错误处理细节:

1
2
3
4
5
6
7
str := `{"id":16505201442738640729}`

var m map[string]any
json.Unmarshal([]byte(str), &m)

data, _ := json.Marshal(&m)
fmt.Println(string(data))

上面代码片段输出:

1
{"id":16505201442738640000}

原始json string中,id的值是16505201442738640729,经过json.Unmarshal和json.Marshal后,id的值变成了16505201442738640000,看起来出现了精度有丢失。

Read more »

虽然PHP做业务后端逐步在被Go等语言替代,但使用PHP做简单业务封装和数据组装时,开发效率依然是比较高效的。使用Nginx运行PHP的常用方法是FastCGI模块。PHP-FPM (FastCGI进程管理器)极大地提高了你的Nginx+PHP环境的性能,所以这对高负载的网站很有用。本教程介绍在CentOS8上安装Nginx并配置PHP-FPM的步骤,以便后续参考。

依赖环境

  • CentOS8
  • 拥有sudo权限
  • 更新dnf
1
sudo dnf update 

Step1 安装Nginx

Nginx在仓库中已经存在,可以使用dnf工具直接安装:

1
sudo dnf install nginx

启动Nginx服务,同时让Nginx服务在系统启动时自动启动。

1
2
sudo systemctl enable nginx
sudo systemctl start nginx

检查nginx是否已启动

1
sudo systemctl status nginx

如果您的系统上启用了防火墙,请确保打开HTTP端口以供远程系统访问。HTTP为80端口,HTTPS,为443端口。

1
2
3
sudo firewall-cmd --zone=public --permanent --add-service=http
sudo firewall-cmd --zone=public --permanent --add-service=https
sudo firewall-cmd --reload

在浏览器使用ip访问主机器,看是否能访问到nginx的默认页面了呢?

Read more »