ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

吴恩达机器学习Python实验资源包:从数据读取到推荐系统实战

吴恩达机器学习Python实验资源包:从数据读取到推荐系统实战 简介重庆大学机器学习课程的笔记、作业与实验资源合集代码基于 Python 实现。内容来自 Coursera 吴恩达《Machine Learning》听课笔记覆盖监督学习分类与回归、高级学习算法决策树、神经网络、模型评估与选择及推荐系统等模块适合初学者对照课程同步练习。压缩包共 292 个文件以 png 笔记截图、ipynb 实验笔记本、csv 数据集和 py 脚本为主另有 md 笔记、npy 数据文件、mplstyle 绘图样式等总大小 26.04MB。已有 206 人学习/下载。资料内包含分节整理的核心笔记、配套数据集与可运行实验代码目录按课程三大单元划分便于检索。读者可借助这些材料复盘课程重点、复现实验流程并参考 Python 实现完成作业或扩展练习。1. 一份跟完吴恩达机器学习课程后攒出来的Python实验资源包如果你正在跟吴恩达的机器学习入门课同时又需要在重庆大学的机器学习课程里交作业、做实验这份资源能帮你省掉大量整理数据的时间。它把 Coursera Machine Learning 的听课笔记、课后作业和实验代码拆成了可复用的 Python 工程small_movies 系列 csv 是推荐系统实验的原始数据toy_dataset 和 diabetes 分别覆盖回归与分类c2w3 开头的文件对应课程第三周实验的训练样本。对于想快速跑通监督学习、神经网络、推荐系统三条主线的学习者这里既有可直接运行的实验数据也有按课程模块整理的 Class Notes。新手可以跟着笔记理解概念老手可以直接把数据文件迁移到自己的模型里。2. 先读数据small_movies 与 toy_dataset 的文件结构和读入方式拿到这份资源后的第一件事不是打开 notebook 运行而是先把每个 csv 读进 pandas确认行列数、缺失值、索引是否对齐。因为课程实验里的数据文件命名规律很强搞懂它们之间的关系后面所有实验都能少踩一半坑。2.1 数据文件清单与对应实验资源根目录下的 csv 文件名基本直接对应吴恩达课程实验中的原始数据。我按课程模块整理成下表方便你快速定位文件用途文件名内容对应课程模块toy_dataset.csv合成小样本特征集最后一列是目标值Supervised Machine Learningdiabetes.csv糖尿病指标含 Outcome 分类列逻辑回归 / 分类实验small_movies_X.csv电影特征矩阵每行一部电影推荐系统协同过滤small_movies_Y.csv用户对电影的评分矩阵行电影列用户推荐系统协同过滤small_movies_R.csv0/1 指示矩阵R1 表示有评分推荐系统协同过滤small_movie_list.csv电影名称列表推荐系统结果可视化content_user_train.csv用户内容特征训练集内容推荐content_item_train.csv物品内容特征训练集内容推荐content_y_train.csv评分标签与上面两个文件行对齐内容推荐c2w3_lab2_data4.csv第三周实验数据常用于神经网络入门Advanced Learning Algorithms注意small_movies_Y.csv和small_movies_R.csv的 shape 必须完全一致因为R就是Y的掩码。c2w3_lab2_data4.csv中的w3通常指 Course 2 Week 3 的 Lab我在复现时发现它常被用来做多分类实验读取前最好先打印columns确认是否需要把第一列当作索引而不是直接当成特征。2.2 用 pandas 读入并做基础探查我的习惯是先把所有 csv 放进data/子目录然后用一个统一函数读入这样后续脚本迁移到服务器或云环境时只需要改一处路径前缀。下面这段代码适用于资源里的所有文件import pandas as pd def load_csv(name, index_colNone): df pd.read_csv(fdata/{name}, index_colindex_col) print(f{name}: shape{df.shape}) return df toy load_csv(toy_dataset.csv) movies_X load_csv(small_movies_X.csv) movies_Y load_csv(small_movies_Y.csv) movies_R load_csv(small_movies_R.csv) diabetes load_csv(diabetes.csv) print(toy.head()) print(toy.info()) print(movies_R.iloc[:5, :5])其中read_csv的index_col参数需要特别注意如果 csv 第一列是无意义的序号如Unnamed: 0要设置index_col0否则 pandas 会把这一列当成普通特征导致后续矩阵运算 shape 对不上。我在处理small_movies_X.csv时第一次就踩了这个问题模型预测分数总是偏低最后发现是索引列混进了特征矩阵。info()会输出每列的非空计数和数据类型可以用来快速发现缺失值。toy_dataset.csv和diabetes.csv一般没有缺失但small_movies_Y.csv中的缺失值往往以空格或特殊字符存在需要用df.replace(, np.nan)清洗后再转成 float。2.3 特征矩阵与标签的对齐方式推荐系统实验的核心是理解Y、R、X三者关系。在吴恩达课程的常见设置中movies_X是电影特征矩阵形状为 (电影数, 特征数)movies_Y的形状是 (电影数, 用户数)movies_R与Y同形状取值 0 或 1。训练协同过滤时代价函数只统计R1的位置所以Y中未评分的位置用什么数字填充都不影响梯度计算。我通常把Y和R都转成numpy.ndarray并检查有效评分数import numpy as np Y movies_Y.values.astype(float) R movies_R.values.astype(float) num_items, num_users Y.shape valid_ratings int(R.sum()) print(电影数:, num_items, 用户数:, num_users) print(有效评分数量:, valid_ratings) print(评分密度: {:.2%}.format(valid_ratings / (num_items * num_users)))R.sum()得到的是实际有评分的条目总数除以矩阵总元素数就是评分密度。如果密度低于 5%说明是高度稀疏的显式评分数据直接训练协同过滤容易过拟合需要加大正则化系数。content_user_train.csv和content_item_train.csv的行数是样本数不是用户数或物品数它们每行是一条「用户-物品」交互记录必须通过行索引和content_y_train.csv对齐。如果在多个文件中各自执行了dropna()交互记录的行顺序就可能错位之后合并特征时要用df.reset_index(dropTrue)重新整理。3. 从回归到神经网络监督学习实验的复现路径这份资源里的toy_dataset.csv、diabetes.csv和c2w3_lab2_data4.csv基本覆盖了课程中监督学习的主要实验类型。按照「线性模型 → 神经网络 → 模型评估」的顺序去复现能贴合吴恩达课程的递进逻辑也方便对比不同模型在同一个数据集上的效果。3.1 回归与分类任务的基线模型先拿diabetes.csv做二分类拿toy_dataset.csv做回归。diabetes.csv的最后一列是Outcome表示是否患病适合用逻辑回归作为基线。注意逻辑回归默认的最大迭代次数是 100在特征量纲差异大时往往不收敛所以要手动调max_iter。代码如下from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score, mean_squared_error # 二分类diabetes df pd.read_csv(data/diabetes.csv) y df[Outcome].values X df.drop(columns[Outcome]).values X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42, stratifyy ) clf LogisticRegression(max_iter1000) clf.fit(X_train, y_train) print(逻辑回归 ACC:, accuracy_score(y_test, clf.predict(X_test)))stratifyy的作用是在切分训练集和测试集时保持正负样本比例与原数据集一致这对类别不平衡的医疗数据尤其重要。random_state42不是魔法数字它是为了保证你每次运行得到相同划分方便和其他同学对比实验。逻辑回归对特征尺度敏感实践中建议先对X做标准化from sklearn.preprocessing import StandardScaler再用Pipeline串联起来否则max_iter可能要调到 5000 以上。toy_dataset.csv是合成数据特征列没有明确的业务含义我用iloc统一取最后一列为目标值避免依赖列名from sklearn.linear_model import LinearRegression toy pd.read_csv(data/toy_dataset.csv) X_reg toy.iloc[:, :-1].values y_reg toy.iloc[:, -1].values X_train, X_test, y_train, y_test train_test_split( X_reg, y_reg, test_size0.2, random_state42 ) reg LinearRegression() reg.fit(X_train, y_train) print(线性回归 MSE:, mean_squared_error(y_test, reg.predict(X_test)))iloc[:, :-1]取所有行、除了最后一列的所有列这样即使 csv 文件里加了新特性列代码也不需要改。这里MSE的单位是目标值的平方如果目标值本身是 0~1 的小数MSE 会显得很小如果目标值上千MSE 会爆炸此时用mean_absolute_error或r2_score更能说明问题。3.2 神经网络部分用 Keras 复现课程作业结构c2w3_lab2_data4.csv通常是课程第二门课第三周实验的数据我拿它做二分类并用 Keras 搭一个两隐藏层的 MLP。这套结构基本就是吴恩达在 Advanced Learning Algorithms 里讲过的「输入层 → 隐藏层 → 输出层」的典型示例。import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense # 假设 df_lab 已读取并切分 X_train, y_train model Sequential([ Dense(25, activationrelu, input_shape(X_train.shape[1],)), Dense(15, activationrelu), Dense(1, activationsigmoid) ]) model.compile( optimizertf.keras.optimizers.Adam(learning_rate0.001), lossbinary_crossentropy, metrics[accuracy] ) history model.fit( X_train, y_train, epochs100, batch_size32, validation_split0.2, verbose0 )Dense(25, activationrelu, input_shape(X_train.shape[1],))中25是隐藏单元数只比课程默认值稍大一点再大容易在小型数据集上过拟合。lossbinary_crossentropy对应输出层的sigmoid如果是多分类就要改成categorical_crossentropy并把输出层换成softmax。validation_split0.2会从训练数据尾部直接切出 20% 作为验证集但这里有个坑如果你在这个fit之前已经用train_test_split切过一次那么验证集其实是从训练集内部又切了一次造成「验证集参与过训练数据分布」的误解。更稳妥的做法是先把原始数据用train_test_split切出最终的X_test, y_test然后让fit的validation_data直接指向这一份测试集或者干脆在完整训练集上只做cross_val_score。3.3 模型评估与选择交叉验证与学习曲线课程里专门有一节讲 Model Evaluation and Selection作业要求比较不同模型。我们可以在同一份diabetes数据上对逻辑回归和神经网络做 5 折交叉验证并整理成下表模型平均准确率标准差训练耗时特性LogisticRegression(max_iter1000)约 0.78±0.03秒级Keras MLP (25-15-1)约 0.75±0.04秒级至分钟级代码方面sklearn 的逻辑回归直接支持交叉验证但 Keras 模型需要包装成 sklearn 接口。注意 TensorFlow 2.16 之后已经移除了tf.keras.wrappers.scikit_learn现在需要用scikeras库from scikeras.wrappers import KerasClassifier from sklearn.model_selection import cross_val_score def create_model(): model Sequential([ Dense(25, activationrelu, input_shape(X.shape[1],)), Dense(15, activationrelu), Dense(1, activationsigmoid) ]) model.compile(optimizeradam, lossbinary_crossentropy, metrics[accuracy]) return model clf_nn KerasClassifier(modelcreate_model, epochs50, batch_size32, verbose0) scores_nn cross_val_score(clf_nn, X, y, cv5) print(神经网络 CV ACC: {:.4f} ± {:.4f}.format(scores_nn.mean(), scores_nn.std()))cross_val_score的cv5表示把数据切成 5 份每次用 4 份训练、1 份验证轮流 5 次。这种评估方式能更稳定地反映模型泛化能力但代价是训练时间增加到原来的 5 倍。KerasClassifier内部会自动调用model.fit所以你不能再在create_model里传validation_split否则交叉验证的验证集和内部验证集冲突结果会偏高。如果发现神经网络准确率明显低于逻辑回归先检查是否需要对特征做标准化神经网络对尺度不一致的特征非常敏感而逻辑回归可以通过增大max_iter硬扛。4. 推荐系统实验协同过滤代价函数与内容过滤数据构造推荐系统是这份资源里最有价值的部分因为课程实验数据small_movies系列很完整。我在这里拆开讲协同过滤和内容过滤两类数据的使用方法重点放在代价函数的向量化实现和训练对齐。4.1 small_movies 数据集的矩阵结构协同过滤的核心矩阵关系可以概括为Y是评分矩阵R是掩码矩阵X是物品/电影的特征矩阵W是用户偏好参数矩阵每个用户还有一个偏差b。预测评分的公式是预测值 X 与 W 的点积 b。small_movies_X.csv的行数等于small_movies_Y.csv的行数这个对应关系必须保持。常用维度关系如下表矩阵Shape含义X(电影数, 特征数)每部电影的特征向量W(用户数, 特征数)每个用户的偏好向量b(用户数,) 或 (1, 用户数)每个用户的评分偏差Y(电影数, 用户数)真实评分缺失处可为任意值R(电影数, 用户数)1 表示有评分0 表示没有课程作业里X是课程预设的电影特征W和b是要学习的参数。如果直接运行课程提供的cofi_cost_func需要注意X W.T b的广播规则X W.T得到(电影数, 用户数)的矩阵b的形状要和这个矩阵的第二个维度一致。4.2 用 NumPy 实现协同过滤代价函数这是整个推荐系统实验最容易写错的地方。我给出一个向量化实现同时包含正则化项def cofi_cost_func(X, W, b, Y, R, lambda_): X: (nm, n) 电影特征矩阵 W: (nu, n) 用户偏好矩阵 b: (nu,) 用户偏移 Y: (nm, nu) 评分矩阵 R: (nm, nu) 0/1掩码 nm, nu Y.shape pred X W.T b # (nm, nu) err (pred - Y) * R # 只保留有评分的项 cost 0.5 * np.sum(err ** 2) reg (lambda_ / 2) * (np.sum(W ** 2) np.sum(X ** 2)) # 注意一般不对 b 做正则化b 是标量偏差 return cost regX W.T是把电影特征矩阵和用户偏好矩阵相乘得到每一部电影在每个用户下的预测分。err (pred - Y) * R里的乘法是逐元素相乘R中 0 的位置不会产生梯度贡献所以Y里缺失值填 0 也没问题。0.5 * np.sum(err ** 2)是 MSE 的一半课程公式里通常这么写方便求导时消掉系数 2。正则化项里我刻意没有加入np.sum(b ** 2)因为用户偏差本质上是均值偏移过度正则化会让预测结果整体收缩向 0课程标准实现也往往把b排除在正则化之外。如果需要反向传播常见做法是用tensorflow的自定义层来自动求导但如果想手写梯度可以再实现一个函数返回grad_w, grad_x, grad_b。调试时最简单的验证方法是把随机初始化的X, W, b代入cost应该是正的且随迭代下降如果cost出现NaN先检查Y中是否有特殊字符或非数值再看学习率是否过大。4.3 内容推荐模型的训练数据构造内容推荐Content-based Filtering在课程里被归为 Other Power Learnings核心是使用用户特征 物品特征预测评分。这份资源里的content_user_train.csv、content_item_train.csv和content_y_train.csv已经提前构造好了样本级数据。我的做法是把用户特征和物品特征横向拼接成一个长向量然后交给线性回归或浅层网络学习。user_feats pd.read_csv(data/content_user_train.csv).values item_feats pd.read_csv(data/content_item_train.csv).values labels pd.read_csv(data/content_y_train.csv).values.ravel() assert user_feats.shape[0] item_feats.shape[0] labels.shape[0] X_content np.hstack([user_feats, item_feats]) reg_content LinearRegression() reg_content.fit(X_content, labels) print(内容推荐训练样本数:, X_content.shape[0], 特征数:, X_content.shape[1])np.hstack要求两个数组行数完全一致否则会直接报错所以先assert做检查。特征拼接后每一行的前半部分是用户特征后半部分是物品特征线性模型可以自动学习这两组特征的加权组合。这里的content_y_train.csv是显式评分值如果你用pd.read_csv读出来是一列数据需要.ravel()把它变成一维数组否则fit会认为标签是单列矩阵而报警告。内容过滤和协同过滤的区别在于协同过滤从历史评分中学出用户偏好向量W而内容过滤直接把用户画像和物品属性作为输入。实际部署中内容过滤的优点是能推荐从未评过分的冷启动物品缺点是特征工程成本高。课程实验里这两个方向都用到了我一般会先用内容过滤的线性模型跑一个 baseline再用协同过滤对比最后看 RMSE 谁更低。5. 笔记与代码复盘的几个实用技巧5.1 按课程模块组织 Class Notes 文件夹资源里的Class Notes文件夹保留了吴恩达课程的三段式结构Supervised Machine Learning、Advanced Learning Algorithms、Other Power Learnings。我在本地复刻时会把每节课的笔记拆成独立 Markdown 文件并在文件名前加数字序号Class Notes/ 01_Supervised/regression_note.md 01_Supervised/classification_note.md 02_Advanced/neural_network_note.md 02_Advanced/decision_tree_note.md 03_Other/recommender_system_note.md这样用ls命令或文件管理器查看时可以按照学习顺序阅读。笔记里我倾向于把课程中的公式用 LaTeX 写出来但不用截图因为截图的文字无法检索MD 文件里的公式在 Typora 和 VS Code 里都能渲染搜索时也能直接搜到关键词。5.2 用命令行把 notebook 导出为 Markdown 并保留输出实验 notebook 往往混有代码、输出和 Markdown 说明如果想把它们合并到笔记系统里直接用 jupyter 导出即可jupyter nbconvert --to markdown --output-dir./notes --templatelab experiment.ipynb--to markdown指定输出格式--output-dir./notes指定目标目录。--templatelab会让导出的 Markdown 保留代码块的完整输出包括表格和图片。如果不加这个模板默认会删除部分输出导致复习时看不到实验结果。导出的 Markdown 中图片会被单独存成文件夹发布到博客平台时记得把图片文件夹一起上传。5.3 复现实验时的几个实用技巧路径处理用pathlib.Path代替字符串拼接。例如data_dir Path(data)然后data_dir / diabetes.csv在 Windows 和 Linux 上都不会有斜杠问题。版本锁定神经网络实验依赖 TensorFlow不同版本对 API 影响很大。建议在 requirements.txt 里写tensorflow2.4,2.16避免tf.keras.wrappers突然被移除。随机种子在代码开头设置np.random.seed(0); tf.random.set_seed(0)保证每次训练的可复现性。评分稀疏性判断用np.mean(R)计算评分密度如果小于 0.05评估模型时优先看 RMSE而不是准确率因为绝大多数位置是未评分状态准确率会被 0 主导。本文还有配套的精品资源点击获取
返回列表