编程语言研究书库

数据分析与机器学习:Gonum 生态与「异常值统治一切」的教训

数据分析与机器学习:Gonum 生态与「异常值统治一切」的教训

这一章回答「Go 能做数据分析吗」。 答案是:能,但生态比 Python 年轻。 Go 的甜点位不在实验室里调整数学模型,而在把模型/数据流水线(数据一步步 流过去被处理的一条龙)部署成跑得快、并发强的服务。主线例子会亲手让你看到 数据分析最重要的一课: 一个异常值(10 亿的薪水)就能把均值推到 5 亿——统计量不看分布(数据摊开 长什么样)就是自欺。

1. 两个定义与 Go 的位置

书里先划清两个词1:

  • 机器学习:让计算机从数据里学规律、做预测,不靠人逐条写规则;
  • 数据分析:检查、清洗、转换、建模数据,提取有用的信息支撑决策。

Go 的角色书里说得很直白:不是取代 Python 当 ML 研究平台, 而是用 Gorgonia、GoLearn、Gonum 这些库,把数据处理、模型部署 做成「快、可扩展」的应用——吃 Go 速度和并发红利2。

机器学习为什么重要,书里列了七个应用方向(数据挖掘、预测分析、推荐系统、 欺诈检测、医疗、NLP(让机器理解人类语言)、科研)3——这张表读一遍建立直觉即可,不用记。

2. 数据处理三件套:清洗、转换、归一化

数据处理的三个基本动作,书里各给了可跑的代码骨架4:

清洗(cleaning):去重、去空行、统一格式。原书的 cleanData 函数 是教科书式写法:用一个 map 当「见过的集合」去重 (键是行的字符串化,值用空结构体——第 13 章的惯用法), 每行转小写、去首尾空格。

转换(transformation):换格式、换结构。书里用 struct + encoding/xml 演示了 XML 序列化(Marshal)与反序列化(Unmarshal): 结构体标签(反引号里的 xml:"name")告诉编码器字段和标签的对应关系—— 这是第 10 章埋过伏笔的「结构体标签」,这里第一次实战5。

归一化(normalization):把不同量纲的特征(数据里的每一列,比如年龄、薪水) 压到同一尺度, 防止「数值大的字段统治分析」。书里选了最直观的 min-max 缩放:

  x_scaled = (x - min) / (max - min)

  数据:[100, 550, 280, 4000, 50]
  → [0.0127, 0.1266, 0.0582, 1, 0]      ← 最小值变 0,最大值变 1

图说:5 个数原来跨 4 个数量级的感觉(50 到 4000),缩放后全部落在 0~16。

3. 主线例子:一份脏 CSV 的七步体检

本章主线,照原书的 EDA(探索性数据分析)完整流程。 数据集 dataset.csv 两列(Age、Salary),10 行——其中藏着两个雷: 年龄 0(缺失)和薪水 10,000,000,000(异常)7。

第 ① 步:解析。 encoding/csv 读全量;FieldsPerRecord = -1 容忍列数不齐;每个值 TrimSpace 后用 strconv.ParseFloat 转 float64, 转不了的静默跳过(if err == nil)。

第 ② 步:准备。 所有数值摊平进一个 []float64—— 注意这会把 Age 和 Salary 两列混进同一根切片,是教学简化。

第 ③ 步:描述性统计(gonum/stat 包):

sort.Float64s(data)                                  // Quantile 要求先排序
mean     := stat.Mean(data, nil)                     // 均值
median   := stat.Quantile(0.5, stat.Empirical, data, nil)  // 中位数
variance := stat.Variance(data, nil)                 // 方差
stdDev   := stat.StdDev(data, nil)                   // 标准差:数据离均值平均有多远

第 ④ 步:可视化。 gonum/plot 画直方图,16 个分桶,存成 histogram.png8。

第 ⑤ 步:相关分析(书里给的是 2×2 示例矩阵——矩阵就是排成矩形的一批数—— 示意 mat 包的用法)。

第 ⑥ 步:数缺失值。 规则:值 == 0 视为缺失 → 数到 1 个(那个 Age 0)。

第 ⑦ 步:找异常值。 规则:超过 3 倍标准差 → 抓到 [1e+10]。

现在看输出,这是全章最有冲击力的一组数字9:

  Mean:               500028467.05     ← 五亿!
  Median:             50.00            ← 五十
  Variance:           4999970035809240064.00
  Standard Deviation: 2236061277.29    ← 二十二亿
  Number of missing values: 1
  Outliers: [1e+10]

图说:10 行数据、1 个异常值,均值被拖到 5 亿,而中位数纹丝不动(50)。 这就是数据分析的第一课,用 10 行数据讲完了:

均值怕异常值,中位数不怕。 拿到任何数据,先问「这里面有没有怪物」, 再决定用哪个统计量描述它。标准差在这里也失效了(22 亿,比数据本身还大)。

书里这一步的处理很克制——只检测、不修复,把「删还是修」留给了读者判断。

4. 机器学习三范式:一张地图

书里按「有没有标签、怎么学」把机器学习(让计算机从数据里自己学规律的总称)切成三类10:

范式学什么书内点名的算法(名字认脸即可)
监督学习有标签(每个训练样本都带正确答案):学「输入→输出」的映射(对应关系)分类(预测属于哪一类,如垃圾邮件判断):决策树(一路 if-else 问到答案)、KNN(看离它最近的邻居是谁);回归(预测一个数值,如房价):线性回归(用一条直线拟合数据)
无监督学习没标签:自己从数据里找结构聚类(自动把相似的归成一堆):K-means;降维(把太多特征压缩成少数几个,方便画图和分析):PCA
强化学习试错的智能体:做什么动作能拿到最多奖励Q-Learning(把「状态+动作」的好坏记在一张表里,边试边学)

强化学习的五要素书里单独给了定义:智能体(agent)、环境(environment)、 状态(state)、策略(policy)、动作(action)、奖励(reward)—— 「智能体观察环境状态、按策略选动作、拿奖励反馈」这个循环就是全部11。

5. Go 的机器学习库清单

书里列了九个,按用途归拢(2025 年口径)12:

库干什么
GoLearn最像 Scikit-learn 的全家桶:分类/回归/聚类/交叉验证
GonumNumPy/MATLAB 的精神续作:线性代数、统计、优化、矩阵——本章 EDA 和回归的主力
Gorgonia神经网络(模仿脑细胞连接的数学模型)/深度学习(很多层堆起来的神经网络)框架,Gonum 家族
GoML在线学习、反应式学习模型
GoBrain / Gomind神经网络
Hector经典算法合集(主攻二分类,即只分「是/否」两类的问题)
libsvm-goLIBSVM 的 Go 移植(SVM 训练与预测)
go-cluster聚类:DBSCAN、OPTICS、k-means++
GoBot机器人/IoT 物理设备接口(ML 实验的四肢)

判断(我们的,不是书里的): 这张清单里最值得投入的是 Gonum—— 它不是「机器学习库」,是科学计算的地基;而 Go 机器学习生态的共识用法是: 训练在 Python,部署/服务化在 Go(ONNX Runtime 的 Go 绑定、 TensorFlow Serving 的客户端)。GoLearn/Gorgonia 能玩,但别指望它们 追平 PyTorch 一天的更新量。 如果错,会错在: 如果 Gorgonia 或后续项目把「图计算 + 自动微分」 做成了生产级,Go 也可能长出像样的训练生态——但就本书成书时可见的 社区活跃度看,这个可能性不大。

6. 时间序列:用线性回归预测股价(玩具版)

本章压轴例子:30 天的股价(y 从 143.0 缓涨到 144.8),用 Gonum 的 线性回归 + 优化器(自动搜索最优参数的工具)预测第 31 天13:

  第 1 步:造设计矩阵 X —— 每行 [1, x],那个 1 是偏置项(bias)
  第 2 步:目标向量 Y —— 30 个真实价格
  第 3 步:目标函数 = Σ(X·θ - Y)²      ← 预测与实际的差的平方和
  第 4 步:optimize.Minimize 用默认的 BFGS 算法找让目标函数最小的 θ
  第 5 步:预测 = θ₀ + θ₁ × 31
  Predicted stock price for tomorrow: 145.27

图说:「训练」在这里就是一句话:找一组参数,让「预测错的平方和」最小。 线性回归没有魔法,优化器替你试参数而已。

书里附的免责声明同样原样接住:这是非常基础的例子,真实股价预测 需要特征工程、严肃模型、风险管理与评估14——这句诚实, 是整章数据科学内容的合格线。

7. 边界与局限

  • EDA 的例子把两列数据混进一根切片(Age 和 Salary 一起算均值)—— 教学上省事,实际上每列应该独立统计;书中的「均值 5 亿」因此更是 「列不该混」的反面教材;
  • 缺失值处理只数了个数,没讲填充(均值/中位数/模型插补);
  • 相关分析是硬编码(把数据直接写死在代码里,不从外部读)的 2×2 示例矩阵, 不是真从数据算的相关系数;
  • 异常值检测的「3 倍标准差」在标准差本身被污染时会失效(本章数据就是), 更稳的是 IQR 或稳健统计量——书里列了名字没给代码15。

8. 可带走的

  1. Go 的数据科学定位:部署与流水线,不是实验室调模型;
  2. 数据处理三件套:清洗(去重去空)、转换(序列化/换格式)、归一化(min-max);
  3. 结构体标签(反引号)是 Go 数据交换(XML/JSON)的通用机制;
  4. EDA 六步:解析 → 准备 → 统计 → 画图 → 相关 → 缺失/异常;
  5. 均值怕异常值、中位数不怕——10 行数据、1 个怪物,均值 5 亿 vs 中位数 50;
  6. 标准差也会被异常值绑架;稳健场景先看分布再选统计量;
  7. 机器学习三范式:监督(有标签)、无监督(找结构)、强化(试拿奖励);
  8. Go 库先记 Gonum(地基)和 GoLearn(全家桶);Gorgonia 管神经网络;
  9. 线性回归 = 找参数让「错的平方和」最小;optimize.Minimize 一行代劳;
  10. 股价预测例子是玩具——书里自己写了免责声明,真实场景要特征工程与评估。

9. 原文地图

主题原书章原文位置
机器学习与数据分析定义Data Analysis and Machine Learningtext/29-fm-learning-go-programming.txt:55(搜「without explicit programming」) · text/29-fm-learning-go-programming.txt:61(搜「Gorgonia, GoLearn, and Gonum」)
数据结构与文件读写Data Analysis and Machine Learningtext/29-fm-learning-go-programming.txt:121(搜「third-party libraries」) · text/29-fm-learning-go-programming.txt:220(搜「ioutil package is obsolete」) · text/29-fm-learning-go-programming.txt:232(搜「bufio package」)
数据清洗示例Data Analysis and Machine Learningtext/29-fm-learning-go-programming.txt:370(搜「cleanData」) · text/29-fm-learning-go-programming.txt:418(搜「TrimSpace(strings.ToLower」)
数据转换(XML 与结构体标签)Data Analysis and Machine Learningtext/29-fm-learning-go-programming.txt:472(搜「xml.Name」) · text/29-fm-learning-go-programming.txt:499(搜「MarshalIndent」)
min-max 归一化Data Analysis and Machine Learningtext/29-fm-learning-go-programming.txt:577(搜「MinMaxScaler」) · text/29-fm-learning-go-programming.txt:663(搜「0.012658227848101266」) · text/29-fm-learning-go-programming.txt:672(搜「x scaled」)
EDA 工具清单Data Analysis and Machine Learningtext/29-fm-learning-go-programming.txt:684(搜「gonum/gonum/stat」) · text/29-fm-learning-go-programming.txt:687(搜「gonum/plot」) · text/29-fm-learning-go-programming.txt:693(搜「Interquartile Range」)
脏数据集与七步流水线Data Analysis and Machine Learningtext/29-fm-learning-go-programming.txt:835(搜「10000000000」) · text/29-fm-learning-go-programming.txt:931(搜「FieldsPerRecord = -1」) · text/29-fm-learning-go-programming.txt:991(搜「stat.Quantile」)
均值 vs 中位数的输出Data Analysis and Machine Learningtext/29-fm-learning-go-programming.txt:1126(搜「500028467.05」) · text/29-fm-learning-go-programming.txt:1129(搜「Median: 50.00」) · text/29-fm-learning-go-programming.txt:1150(搜「Outliers: [1e+10]」)
三范式与算法清单Data Analysis and Machine Learningtext/29-fm-learning-go-programming.txt:1162(搜「labeled data」) · text/29-fm-learning-go-programming.txt:1186(搜「unlabeled data」) · text/29-fm-learning-go-programming.txt:1198(搜「maximize a reward」)
库清单Data Analysis and Machine Learningtext/29-fm-learning-go-programming.txt:1228(搜「Similar to Python's Scikit-learn」) · text/29-fm-learning-go-programming.txt:1234(搜「inspired by NumPy」) · text/29-fm-learning-go-programming.txt:1237(搜「neural networks」)
线性回归预测股价Data Analysis and Machine Learningtext/29-fm-learning-go-programming.txt:1297(搜「design matrix」) · text/29-fm-learning-go-programming.txt:1330(搜「objective」) · text/29-fm-learning-go-programming.txt:1372(搜「Minimize」) · text/29-fm-learning-go-programming.txt:1411(搜「145.27」)
免责声明Data Analysis and Machine Learningtext/29-fm-learning-go-programming.txt:1433(搜「may not yield reliable results」)

Footnotes

  1. 出处:「Data Analysis and Machine Learning」第 55–58 段(text/29-fm-learning-go-programming.txt:55,搜「without explicit programming」)。 ↩

  2. 出处:「Data Analysis and Machine Learning」第 61 段(text/29-fm-learning-go-programming.txt:61,搜「Gorgonia, GoLearn, and Gonum」)。 ↩

  3. 出处:「Data Analysis and Machine Learning」第 64–91 段(七个应用方向)。 ↩

  4. 出处:「Data Analysis and Machine Learning」第 94–121 段(数据结构回顾)、第 364–445 段(清洗示例)。 ↩

  5. 出处:「Data Analysis and Machine Learning」第 448–553 段(text/29-fm-learning-go-programming.txt:472,搜「xml.Name」;text/29-fm-learning-go-programming.txt:499,搜「MarshalIndent」)。 ↩

  6. 出处:「Data Analysis and Machine Learning」第 556–672 段(text/29-fm-learning-go-programming.txt:663,搜「0.012658227848101266」;text/29-fm-learning-go-programming.txt:672,搜「x scaled」)。 ↩

  7. 出处:「Data Analysis and Machine Learning」第 675–931 段(数据集见第 713–856 段的表;解析见第 913–976 段)。 ↩

  8. 出处:「Data Analysis and Machine Learning」第 979–1052 段(text/29-fm-learning-go-programming.txt:991,搜「stat.Quantile」;text/29-fm-learning-go-programming.txt:1018,搜「NewHist」)。 ↩

  9. 出处:「Data Analysis and Machine Learning」第 1123–1150 段(text/29-fm-learning-go-programming.txt:1126,搜「500028467.05」;text/29-fm-learning-go-programming.txt:1129,搜「Median: 50.00」;text/29-fm-learning-go-programming.txt:1150,搜「Outliers: [1e+10]」)。 ↩

  10. 出处:「Data Analysis and Machine Learning」第 1156–1219 段(三范式的定义与算法清单)。 ↩

  11. 出处:「Data Analysis and Machine Learning」第 1198–1216 段(强化学习五要素的定义)。 ↩

  12. 出处:「Data Analysis and Machine Learning」第 1222–1252 段(九个库的分工)。 ↩

  13. 出处:「Data Analysis and Machine Learning」第 1255–1411 段(text/29-fm-learning-go-programming.txt:1297,搜「design matrix」;text/29-fm-learning-go-programming.txt:1306,搜「Bias term」;text/29-fm-learning-go-programming.txt:1372,搜「Minimize」;text/29-fm-learning-go-programming.txt:1411,搜「145.27」)。 ↩

  14. 出处:「Data Analysis and Machine Learning」第 1433 段(text/29-fm-learning-go-programming.txt:1433,搜「may not yield reliable results」)。 ↩

  15. 出处:「Data Analysis and Machine Learning」第 693 段(text/29-fm-learning-go-programming.txt:693,搜「Interquartile Range」)。 ↩

On this page