第2讲 · EECS 189:数据工具(Data Tools)

UC Berkeley EECS 189/289A《机器学习导论》2026 春季 · 课堂实录重构

主讲 Jennifer Listgarten、Alex Dimakis
视频 https://www.youtube.com/watch?v=IzfaWKuxThw
课程主页 https://eecs189.org/sp26/
官方讲义/笔记(Lecture 2) Google Drive PDF
教材 Machine Learning: A First Course for Engineers and Scientists(Lindholm 等)
幻灯片致谢 Lecture 2 幻灯片由 Joseph E. Gonzalez、Narges Norouzi 制作
图片来源 书中幻灯片插图为官方 PDF 高清渲染图;少量截图为视频画面

对应讲次:第2讲(UC Berkeley EECS 189 机器学习导论)

制作模型:deepseek-flash(coding-agent / pi;据 ~/.pi/agent/settings.json)

说明:本讲对应的 pandas 主题不在教材中;课程材料版权归 UC Berkeley 及授课教师所有,本书仅供学习

编者说明:本讲分两部分。前半段(约 00:03–00:31)回顾第一讲的机器学习范式与问题类型;后半段(约 00:31 起)进入本讲主题 pandas 与数据可视化。转录自英文自动字幕(滚动字幕),已去重整理并按官方幻灯片校准术语。


第一部分:回顾——机器学习的范式与问题类型

(参考时间: 00:03)

1. 从一个模型范式说起

上一讲我们学习了模型的通用范式:在一张表里,某一列是我们要预测的(特殊)列,这类问题称为监督学习(supervised learning)。

随后我们强调了一个机器学习中至关重要的观念:重要的不是训练集上的准确率,而是模型在新数据上的准确率。这就是贯穿整门课的核心矛盾——泛化(generalization)与过拟合(overfitting)。

2. 泛化、记忆与「奥卡姆剃刀」

总存在一些模型能在训练集上表现完美却「愚蠢至极」——这就是记忆模型(memorization model),而且它有很多变体。我们的一半工作,就是要确保模型不是在死记硬背,而是真正能预测新数据。

于是有了一个哲学式的判断:训练集上表现相同的许多模型里,越简单的模型越可能在明天的新数据上表现良好——这正是奥卡姆剃刀(Occam's razor):「能解释数据的最简单解释,往往最接近真相」。

当我们用这个观念去看不同模型族时:

一旦选定了复杂度的度量,就得到一整套降低该族复杂度的技术,统称为正则化(regularization)——即「强迫模型变简单」。这门课会大量使用它。

3. 什么样的任务适合机器学习?

机器学习要解决的问题,是那些容易演示 / 评估,却难以用规则硬编码(hard-code)的问题——也就是「用例子编程」。当人类无法完整地把你想要的东西写清楚、只能靠训练数据去描述时,就要用机器学习。所以「编程」AI 的方式,其实是「创造数据」——这也是数据整理(data curation)如此重要的原因。

flowchart LR
    A["难以手写规则的问题"] -->|"提供训练数据"| B["监督学习:学习 f(x) ≈ y"]
    B --> C["在应用中对新输入做推理(inference)"]
    C --> D["持续获得反馈 / 迭代"]
    D --> B

4. 监督学习:四类数据

监督学习要求存在目标列 $y$。按数据类型可分为四类:

(1)表格数据(tabular data)

表格数据上的监督学习(房价、违约、购物篮、病人数据)

📷 表格数据上的监督学习(房价、违约、购物篮、病人数据)
回到原视频 (00:12:35)

(2)图像 / 计算机视觉(image / CV)

图像的关键区别在特征数量:一张 $n \times n$ 的图就有 $n^2$ 个特征;彩色图还要乘 3(红、绿、蓝)。我们要让模型从这些海量数字中判断「是否有缺陷」。

编者说明:讲师强烈建议去 Kaggle 上看这些竞赛——不仅能看到真实数据集,还能看到论坛里人们尝试的各种方法(特征工程、验证、优化……),以及你在这门课将要学到的所有技术。这些竞赛往往还有 $10{,}000–50{,}000 美元的奖金。参与它们能让你成为更好的机器学习实践者。

(3)时间序列(time series)

预测 EEG 有什么用?最直接的应用是癫痫发作预测:发作时 EEG 会剧烈变化,若能预测发作时刻,就能提前用药或帮助病人避免开车。预测的时间跨度越长(比如从 10 分钟延长到 1 小时),对患者生活的改善就越显著。

时间序列上的监督学习(EEG、COVID 预测、语音)

📷 时间序列上的监督学习(EEG、COVID 预测、语音)
回到原视频 (00:18:45)

(4)自然语言处理(NLP)

文本输入必须先转换成数字才能喂给模型。经典问题包括:Twitter 情感分类(关于可口可乐的推文是正面还是负面)、新闻分类(政治 / 体育 / 娱乐)、网络对话中的有害内容检测等。

5. 无监督学习

无监督学习中没有 $y$——你不预测某一列。那能做什么?

6. 机器学习简史与教材

(参考时间: 00:23)

AI 不是新学科,至少从 1950 年代的感知机(perceptron)论文就开始了。某种意义上,AI 比计算机科学更古老——先有「能否让机器思考」的想法,我们才发明了计算机科学。它经历了多次起落:50 年代的兴奋、AI 冬天、再次兴奋、第二次冬天;2010 年代 AlexNet 引发的深度学习革命让神经网络重新成为主流;而 2022 年 11 月开启的新革命,则让人们意识到重点不只是预测,更是生成文本、图像、视频与音频。

本课程使用的教材是 Machine Learning: A First Course for Engineers and Scientists。讲师建议大家下载它,课程会沿用书中的记号与概念(书中对概率框架的强调偏多,那部分我们不会全部遵循;且书中没有编程练习——编程活动会另行提供)。每次课都会给出对应的教材章节。

7. 课程路线图

(参考时间: 00:28)

8. 机器学习的生命周期

(参考时间: 00:26)

一个真实机器学习系统的生命周期如下:

flowchart TD
    A["现实问题"] --> B["把问题形式化<br/>(监督 / 无监督?预测什么?如何度量成功?用什么损失?)"]
    B --> C["收集与整理数据<br/>(往往是最被低估、也最关键的一步)"]
    C --> D["选择模型(假设空间)"]
    D --> E["优化 / 训练参数"]
    E --> F["在新数据上预测"]
    F --> G["评估:训练/测试划分、交叉验证、正则化"]
    G -->|"迭代"| D
机器学习的生命周期

📷 机器学习的生命周期
回到原视频 (00:26:10)


第二部分:Data Tools —— pandas 与可视化

(参考时间: 00:31)

2.1 为什么从数据开始

在机器学习中成功与否,取决于你如何处理实验的输入与输出。数据整理(data wrangling)与可视化,虽然可以自学,但讲师还是要做一个快速入门。今天要学的第一个工具是 pandas,第二个是可视化工具(Matplotlib / Plotly)。

Data Tools 标题页

📷 Data Tools 标题页
回到原视频 (00:31:53)

为什么先讲数据?因为数据是一切机器学习的基础:每个模型都始于数据、终于数据,它是训练与评估的原材料。处理输入输出的能力,无论进实验室还是进工业界,都是核心技能。

为什么从数据开始

📷 为什么从数据开始
回到原视频 (00:32:00)

本讲路线图

📷 本讲路线图
回到原视频 (00:32:15)

编者说明:pandas 的命名与由来——它代表「panel data(面板数据)」。历史上做机器学习的人用 MATLAB(没有 DataFrame),统计学家用 R(有 DataFrame);后来 pandas 把 DataFrame 原生引入 Python,在此之前大家用的是 NumPy,一切皆「矩阵」。

2.2 pandas 数据结构

pandas 让我们可以:把数据排成表格;按条件过滤提取信息;对数据运算获得新信息;用 NumPy 对数据做数值运算;以及做向量化(vectorized)计算以加速分析。它是科研与工业界处理表格数据的标准工具。

编者说明:讲师强调——你想做的每件事其实都能用 for 循环写,之所以不这样写,是因为 pandas 的操作被优化成能对大表做并行化;表小的时候无所谓,但学会这种新的数据操作方式,处理大数据时会快得多。

pandas 能做什么

📷 pandas 能做什么
回到原视频 (00:33:31)

pandas 简介

📷 pandas 简介
回到原视频 (00:33:50)

pandas 的核心数据结构:一张表称为 DataFrame;表中的一列称为 Series;行、列的标签集合称为 Index。

pandas 数据类型:DataFrame / Series / Index

📷 pandas 数据类型:DataFrame / Series / Index
回到原视频 (00:34:38)

import pandas as pd
welcome_series = pd.Series(["welcome", "to", "CS 189"])
welcome_series.values
welcome_series.index
Series

📷 Series
回到原视频 (00:35:00)

DataFrame

📷 DataFrame
回到原视频 (00:36:30)

创建 DataFrame

📷 创建 DataFrame
回到原视频 (00:37:05)

data = {
    'Landmark': ['Sather Gate', 'Campanile', 'Doe Library',
                 'Memorial Glade', 'Sproul Plaza'],
    'Type': ['Gate', 'Tower', 'Library', 'Open Space', 'Plaza'],
    'Height': [30, 307, 80, 0, 0],
    'Year Built': [1910, 1914, 1911, None, 1962]
}
df = pd.DataFrame(data)

# 实践中最常见:从 CSV 读取
event_data = pd.read_csv("data/uc_berkeley_events.csv", index_col='Year')

编者说明:讲师由此引出一个重要映射——在机器学习的语言里,列(columns)就是特征(features),行(rows/samples)就是样本。我们总是把特征按列堆叠;样本越多,行越多。

2.3 探索 DataFrame

理解 DataFrame 的结构与内容是数据分析的第一步。常用的「概览」方法有:head() / tail()、info()、describe()、sample()、value_counts()、unique()。

探索 DataFrame

📷 探索 DataFrame
回到原视频 (00:37:42)

DataFrame 的常用工具函数

📷 DataFrame 的常用工具函数
回到原视频 (00:37:52)

head() 与 tail()

📷 head() 与 tail()
回到原视频 (00:38:12)

shape 与 size

📷 shape 与 size
回到原视频 (00:38:48)

sample()

📷 sample()
回到原视频 (00:39:25)

编者说明:讲师特别强调可复现性(reproducibility)的重要性——你可能做出一个惊艳的结果,却在 57 个 notebook 里找不到是哪一个产生的。固定 random_state 就能让每次运行得到相同结果。(至于为什么是 42?——它是《银河系漫游指南》里「生命、宇宙以及一切终极问题的答案」。)

df['Type'].value_counts()   # 各类型出现次数
df['Type'].unique()         # 所有唯一值
value_counts() 与 unique()

📷 value_counts() 与 unique()
回到原视频 (00:40:50)

2.4 选择与提取数据:iloc 与 loc

(参考时间: 00:41)

按位置提取数据用 .iloc[]:

df.iloc[[1, 2]]             # 第 1、2 行
df.iloc[[1, 2], [1, 2, 3]]  # 第 1、2 行,第 1、2、3 列
df.iloc[2:4]                # 第 2、3 行(不含右端 4)
df.iloc[:, 1:2]             # 所有行,第 1 列
df.iloc[:, 0]               # 所有行,第 0 列(得到一个 Series)
df.iloc[2]                  # 第 2 行
df.iloc[0, 1]               # 第 0 行、第 1 列的元素
按整数位置提取:iloc

📷 按整数位置提取:iloc
回到原视频 (00:41:45)

iloc 的参数与示例

📷 iloc 的参数与示例
回到原视频 (00:42:20)

iloc:列表与切片

📷 iloc:列表与切片
回到原视频 (00:43:05)

iloc:切片语法不含右端

📷 iloc:切片语法不含右端
回到原视频 (00:43:45)

iloc:( `:` 取全部行 )

📷 iloc:( `:` 取全部行 )
回到原视频 (00:44:15)

iloc:单值与元素定位

📷 iloc:单值与元素定位
回到原视频 (00:45:15)

按标签提取数据用 .loc[]:

df.loc[[1, 2]]                              # 第 1、2 行
df.loc[[1, 2], ['Type', 'Height', 'Year Built']]
df.loc[2:3]                                 # 第 2、3 行(含右端 3!)
df.loc[:, 'Landmark':'Height']              # 所有行,Landmark 到 Height
df.loc[:, 'Landmark']                       # 所有行,Landmark 列(Series)
df.loc[2]                                   # 第 2 行
df.loc[0, 'Type']                           # 第 0 行、Type 列
按标签提取:loc

📷 按标签提取:loc
回到原视频 (00:45:55)

loc 的参数与切片(含右端)

📷 loc 的参数与切片(含右端)
回到原视频 (00:46:38)

loc:列表选择行列

📷 loc:列表选择行列
回到原视频 (00:46:50)

loc:切片含右端

📷 loc:切片含右端
回到原视频 (00:47:30)

loc:单值选择

📷 loc:单值选择
回到原视频 (00:48:35)

编者说明:讲师吐槽了 iloc 与 loc 切片语义不一致带来的困惑——df.iloc[2:4] 不含右端(2、3),而 df.loc[2:3] 含右端(2、3)。一个合理的解释是:把它们分别想象成「Python 列表切片」与「标签列表」——作为列表时当然要包含 3;作为 Python 切片时则会丢掉最后一个元素。实际使用中,请务必打印结果确认它做了你以为的事。

2.5 上下文相关的选择 []

[] 只接受一个参数,它可能是:

也就是说,[] 是上下文敏感的。注意:df[1:3] 按位置切片;df[[1,2]] 若 1、2 不是列名会报错——这正是它让人困惑的地方。

上下文相关的选择:只用方括号

📷 上下文相关的选择:只用方括号
回到原视频 (00:49:15)

方括号:行切片

📷 方括号:行切片
回到原视频 (00:49:22)

方括号:列标签列表

📷 方括号:列标签列表
回到原视频 (00:49:28)

方括号:单列(Series)

📷 方括号:单列(Series)
回到原视频 (00:49:33)

2.6 过滤数据

(参考时间: 00:49)

我们学会了按位置(.iloc)或标签(.loc)提取数据。如果我们要提取满足某个条件的行呢?

df['Height'] > 50          # 产生布尔 Series
df[df['Height'] > 50]      # 过滤
df.loc[df['Height'] > 50]  # 等价写法
过滤数据

📷 过滤数据
回到原视频 (00:49:48)

用布尔数组过滤 DataFrame

📷 用布尔数组过滤 DataFrame
回到原视频 (00:49:55)

多个条件可以用运算符组合:&(与)、|(或)、~(非)、^(异或)。

df[(df['Height'] > 50) & (df['Type'] == 'Library')]
组合布尔 Series 进行过滤

📷 组合布尔 Series 进行过滤
回到原视频 (00:50:45)

符号 用法 含义
~ ~p p 取反
\| p \| q p 或 q
& p & q p 且 q
^ p ^ q p 异或 q
位运算符

📷 位运算符
回到原视频 (00:51:16)

2.7 修改 DataFrame

(参考时间: 00:51)

添加 / 修改列很简单:用 [] 引用新列,再赋一个长度合适的 Series 或数组。

df['Experience'] = [2, 5, 1, 8, 4]
df['Height_Increase'] = df['Height'] * 0.1   # 向量化运算
添加与修改列

📷 添加与修改列
回到原视频 (00:51:28)

添加与修改列(续)

📷 添加与修改列(续)
回到原视频 (00:51:38)

删除列——这是最容易踩坑的地方:

df.drop(columns=['Experience'])
print(df)   # 咦?什么都没发生!

原因是:pandas 的大多数 DataFrame 操作不是原地(in-place)的——它计算出了结果,却没有「物化」回原对象(这样做是为了省内存)。要真正删除,需要:

df.drop(columns=['Experience'], inplace=True)
# 或直接赋值
df = df.drop(columns=['Experience'])
删除列:不是原地操作

📷 删除列:不是原地操作
回到原视频 (00:51:58)

删除列:inplace 或重新赋值

📷 删除列:inplace 或重新赋值
回到原视频 (00:52:42)

编者说明:讲师反复叮嘱——千万不要写一百行代码再 model.train(),因为几乎可以肯定某处埋着这类「看似成功实则没生效」的错误。每做一次切片或修改就打印出来看一眼,确认它真的按你想的做了。

排序用 sort_values(),可按一列或多列,升序或降序:

df = df.sort_values(by='Height')                              # 单列,默认升序
df = df.sort_values(by=['Height', 'Type'], ascending=[True, False])  # 多列,方向可不同
排序 DataFrame

📷 排序 DataFrame
回到原视频 (00:53:24)

按单列排序

📷 按单列排序
回到原视频 (00:53:38)

按多列排序

📷 按多列排序
回到原视频 (00:53:48)

2.8 处理缺失值

(参考时间: 00:54)

缺失值是真实数据集的常见问题。处理方式有两类:检测与处理(删除或插补 imputation)。

df_missing.isnull()   # 检测:返回布尔 DataFrame,标记所有缺失位置
df_missing.dropna()   # 处理:删除任何含缺失的行/列(会显著缩小数据集)
df_missing.fillna()   # 处理:插补
处理缺失值

📷 处理缺失值
回到原视频 (00:54:05)

用 isnull() 检测缺失值

📷 用 isnull() 检测缺失值
回到原视频 (00:54:38)

用 dropna() 删除缺失值

📷 用 dropna() 删除缺失值
回到原视频 (00:54:55)

用 fillna() 插补缺失值

📷 用 fillna() 插补缺失值
回到原视频 (00:55:32)

编者说明:讲师给了一个重要判断——只有在缺失值极少时才建议直接 dropna(),否则会丢掉大量数据。更好的做法是插补:填补服从同一分布的值。fillna(0) 是「非常糟糕」的做法——模型会以为这座建筑建于公元 0 年;退而求其次,可以填列的均值。你做的每一个假设,都在给你的模型增加或减少难度。

2.9 聚合与分组

(参考时间: 00:56)

聚合(aggregation)是对数据计算均值、和等汇总统计量。

df['Height'].mean()   # 83.4
df['Height'].std()    # 129.2...
df['Height'].idxmax() # 1(最大值的索引)

常见的聚合分三类:

聚合 DataFrame

📷 聚合 DataFrame
回到原视频 (00:56:30)

在 pandas 中聚合数据

📷 在 pandas 中聚合数据
回到原视频 (00:56:52)

分组(grouping)稍复杂:把同一类别的行分组,再对每组做聚合。它强大在能够一次性完成大规模运算,并概括数据中的趋势。一个 .groupby() 操作包含「拆分(split)— 应用(apply)— 合并(combine)」三步。

分组数据

📷 分组数据
回到原视频 (00:57:26)

groupby:拆分—应用—合并

📷 groupby:拆分—应用—合并
回到原视频 (00:57:42)

augmented_df.groupby('Type').agg(mean)   # 各类地标的平均高度/年份
groupby 示例

📷 groupby 示例
回到原视频 (00:57:55)

.agg() 里可以放任何把多个值汇总成一个值的函数,包括内置 Python 函数、NumPy 函数、pandas 函数:

.agg(sum)     .agg(np.sum)     .agg("sum")
.agg(max)     .agg(np.max)     .agg("max")
.agg(min)     .agg(np.min)     .agg("min")
              .agg(np.mean)    .agg("mean")
                               .agg("first")
                               .agg("last")

有些常用聚合甚至可以省略 .agg() 直接调用,例如 df.groupby("Type").mean()。

聚合函数

📷 聚合函数
回到原视频 (00:59:05)

按多列分组会得到一个二维表:

augmented_df.groupby(['Type', 'Campus']).agg('max')[['Height']]

它等价于一个透视表(pivot table):

pivot_table = pd.pivot_table(
    augmented_df,
    index='Type',        # 行
    columns='Campus',    # 列
    values='Height',     # 值
    aggfunc='max'
)
按多列分组

📷 按多列分组
回到原视频 (01:01:10)

pivot_table

📷 pivot_table
回到原视频 (01:01:50)

编者说明:讲师提醒——对缺失值做 mean 聚合时,结果的实现细节(是否把 NaN 计入分母)可能出乎意料,实现里甚至可能有 bug(尤其在 PyTorch 中),所以永远要检查角落情况。

2.10 连接 DataFrame

(参考时间: 01:02)

连接(join)基于公共键或索引把不同来源的表格合并起来——这是从 SQL 继承来的操作,也非常重要。现实中数据常常分散在多张表里;如果连接得低效,计算会浪费巨大。连接前往往需要数据清洗:先意识到「这两张表可以按某一列连接」,而现实中列名往往并不相同。

例如把 event_data(活动数据)与 landmarks(地标)按年份连接:

# 内连接:只保留两张表中都能匹配上的行
result_join_inner = landmarks.join(
    event_data.set_index('Year'), on='Year Built', how='inner')

result_merge_inner = landmarks.merge(
    event_data, how='inner', left_on='Year Built', right_on='Year')
连接 DataFrame

📷 连接 DataFrame
回到原视频 (01:02:30)

连接事件与地标表

📷 连接事件与地标表
回到原视频 (01:02:52)

内连接

📷 内连接
回到原视频 (01:03:32)

# 外连接:保留两张表的所有行,无匹配处填 NaN
result_merge_outer = landmarks.merge(
    event_data, how='outer', left_on='Year Built', right_on='Year')
外连接

📷 外连接
回到原视频 (01:04:20)

四类连接:

类型 含义
Inner Join 只返回两张表中键都匹配的行
Outer Join 返回两张表的所有行,无匹配处用 NaN 填充
Left Join 返回左表所有行,以及右表中匹配的行
Right Join 返回右表所有行,以及左表中匹配的行
连接类型总结

📷 连接类型总结
回到原视频 (01:04:50)


第三部分:课堂测验(Slido)

(参考时间: 01:10)

讲师用 Slido 做了一个随堂小测,检验大家对 DataFrame 的理解。测验题目如下:

  1. df['Type'] 返回什么?——返回一个 Series(该列)。
  2. df.tail(3) 做什么?——显示最后 3 行。
  3. df['Type'].unique() 返回什么?——一个包含 Type 列所有唯一值的 Series(对原始行标签建立索引,出现在每个值首次出现的位置)。
Slido 课堂测验入口

📷 Slido 课堂测验入口
回到原视频 (01:09:45)

测验:选取 Type 列返回什么?

📷 测验:选取 Type 列返回什么?
回到原视频 (01:10:37)

测验:df.tail(3) 做什么?

📷 测验:df.tail(3) 做什么?
回到原视频 (01:11:05)

测验:Type 列的 unique 方法返回什么?

📷 测验:Type 列的 unique 方法返回什么?
回到原视频 (01:11:51)

自由提问环节

📷 自由提问环节
回到原视频 (01:12:26)

Slido 课堂测验界面(视频画面)

📷 Slido 课堂测验界面(视频画面)
回到原视频 (01:11:00)

编者说明:视频的后半段(约 01:05 之后)主要是课程事务与问答:助教介绍选课、同步选课(concurrent enrollment)、办公时间与讨论课安排、期中考试(3 月 17 日晚 7–9 点,线下)、作业发布时间等。这些内容与机器学习知识无关,此处从略。


总结(Takeaways)


附录:课堂未展示的幻灯片

以下幻灯片属于本讲官方 deck 的「可视化(Visualization)」部分,本次录像未讲到,作为延伸阅读收录。

可视化(章节页)

🖼️ 可视化(章节页)

为什么要可视化数据

🖼️ 为什么要可视化数据

绘图库概览

🖼️ 绘图库概览

Matplotlib(章节页)

🖼️ Matplotlib(章节页)

Matplotlib 简介

🖼️ Matplotlib 简介

Plotly(章节页)

🖼️ Plotly(章节页)

为什么用 Plotly

🖼️ 为什么用 Plotly

用 Plotly 绘图的三种方式

🖼️ 用 Plotly 绘图的三种方式

使用 pandas 内置绘图函数

🖼️ 使用 pandas 内置绘图函数

使用 Plotly Express

🖼️ 使用 Plotly Express

如何进一步学习

🖼️ 如何进一步学习

致谢与参考

🖼️ 致谢与参考


附:官方参考与延伸阅读

主题 链接 / 说明
课程主页 https://eecs189.org/sp26/
官方讲义/笔记(Lecture 2) Google Drive PDF
教材 Machine Learning: A First Course for Engineers and Scientists Lindholm, Wahlström, Lindsten, Schön · https://doi.org/10.1017/9781108919371
Kaggle 竞赛总览 https://www.kaggle.com/competitions
↳ House Prices(房价回归,本课程贯穿示例) https://www.kaggle.com/c/house-prices-advanced-regression-techniques
↳ Instacart Market Basket Analysis(表格) https://www.kaggle.com/c/instacart-market-basket-analysis
↳ Walmart Sales in Stormy Weather(表格) https://www.kaggle.com/c/walmart-recruiting-sales-in-stormy-weather
↳ HHP 再入院预测(表格) https://www.kaggle.com/c/hhp
↳ Severstal 钢材缺陷检测(图像) https://www.kaggle.com/c/severstal-steel-defect-detection
↳ Dogs vs. Cats(图像) https://www.kaggle.com/c/dogs-vs-cats-redux-kernels-edition
↳ Global Wheat Detection(图像) https://www.kaggle.com/c/global-wheat-detection
↳ Seizure Prediction(时间序列 / EEG) https://www.kaggle.com/c/seizure-prediction
↳ COVID-19 Global Forecasting(时间序列) https://www.kaggle.com/c/covid19-global-forecasting-week-5
↳ Tweet Sentiment Extraction(NLP) https://www.kaggle.com/c/tweet-sentiment-extraction
↳ Quora Insincere Questions(NLP) https://www.kaggle.com/c/quora-insincere-questions-classification
pandas 官方文档 https://pandas.pydata.org/docs/
Matplotlib 官方文档 https://matplotlib.org/
Plotly / Plotly Express https://plotly.com/python/
推荐阅读(The Hitchhiker's Guide to the Galaxy,理解 random_state=42) ——

版权说明:本讲视频、幻灯片与课程材料版权归 UC Berkeley EECS 189/289A 课程团队(Jennifer Listgarten、Alex Dimakis 及幻灯片作者 Joseph E. Gonzalez、Narges Norouzi)所有。本书为课堂内容的学习性中文重构,仅供学习交流。