机器学习大作业全流程:从7z解压到模型评估
简介一份电子科技大学机器学习课程大作业的7z压缩包面向选修该课程或需要完成类似机器学习项目的本科生与研究生可用于快速把握课程作业的整体框架与实现思路尤其适合在模型选型、特征工程或实验对比环节遇到困难的学习者。压缩包整体约11.55MB内部文件数量及具体格式暂未标注主要应为源代码、实验数据与报告文档等常见作业组成部分。目前已有1263人学习或下载说明其在同类作业参考中有一定认可度。通过该资源读者可获得一份完整的课程大作业样例用于对比自身模型设计、调参过程与实验分析也能从中借鉴项目组织结构和论文式报告的写法同时可帮助理解从数据预处理到模型评估的完整流程提升机器学习实践与展示能力。1. 机器学习大作业压缩包期末周最该先搞懂的一件事期末周拿到一份“电子科技大学机器学习大作业.7z”第一反应是赶紧解压、赶紧跑通、赶紧交差。但真正打开过这类包的人都知道里面往往是一个主脚本、两份数据、三版报告模板配合一段没头没尾的 README能一次跑通全靠运气。这份资源的价值不在于代码有多惊艳而在于它把“机器学习算法怎么落地成课程项目”这件事完整地走了一遍数据预处理、特征构造、模型训练、结果评估都在一个工程里闭环。适合两类人一是课程压力大、需要一份能抄作业并讲清楚原理的参照二是想补“从数据集到模型评估”全流程的从业者。前提是你能顺利把 7z 打开并且不踩编码和路径的坑。2. 先解决打开问题Linux 下解压 7z 与工程目录识别2.1 为什么这份作业用 7z 打包而非 zip7z 在高压缩率场景下比 zip 平均能再省 20% 到 30% 的空间课程作业里经常塞 CSV 数据文件、模型权重和图片样本体积差距一下就出来了。另一个原因是 7z 对 Unicode 文件名的支持比传统 zip 更干净尤其是数据文件叫“训练集_最终版.csv”这种带下划线带中文的名字时用 zip 解出来经常会乱码7z 配合正确参数就很少出问题。代价是系统默认解压工具往往不支持 7zWindows 上需要装 7-ZipLinux 上需要装 p7zip。常见做法是先在 Linux 服务器或 WSL 里解压因为很多人的机器学习环境在远程机器上数据文件也直接丢在服务器里跑。如果你只有 Windows装 7-Zip 后右键解压就行这里不展开。下面重点说 Linux 上的两种解压方式。2.2 命令行解压p7zip 的安装与参数说明# Ubuntu/Debian 系安装 p7zip-full sudo apt install p7zip-full # 解压到当前目录 7z x 电子科技大学机器学习大作业.7z # 解压到指定目录并保留原目录结构 7z x 电子科技大学机器学习大作业.7z -o./ml_homework -y第一条7z x是解压命令x表示保留压缩包内的完整目录路径区别于e把所有文件平铺到当前目录。实际作业包里主脚本和数据往往分在不同子目录用x才能保证脚本里的相对路径不变。-o后面跟输出目录注意-o和路径之间没有空格写-o./ml_homework写成-o ./ml_homework会直接报错这是 7z 命令里比较容易翻车的地方。-y表示遇到文件覆盖询问时自动选 yes批量操作时不用守着终端。解压后第一件事确认文件是否完整。用ls -la看一眼目录结构重点核对数据文件大小如果某个 CSV 只有几 KB很可能解压不完整或者原始文件本身就缺行。我一般会顺手跑一句du -sh对比压缩包和解压后目录的大小压缩率在 5 倍以上是正常现象如果解压后只比压缩包大一点点说明数据大概率没解全。2.3 用 Python 解压py7zr 的适用场景import py7zr # 解压到指定目录 with py7zr.SevenZipFile(电子科技大学机器学习大作业.7z, moder) as z: z.extractall(path./ml_homework)如果你的作业要求在 Notebook 里一键复现开头直接写一段 Python 解压比让使用者额外装 7-Zip 更友好。py7zr支持带密码的压缩包SevenZipFile构造时传passwordxxx即可。这里有一个值得注意的点py7zr 解压时遇到中文文件名在 Linux 上默认输出 UTF-8行为是正常的在 Windows 上如果控制台代码页是 GBK打印文件名会看着乱码但实际写盘的文件名是对的。别被终端显示骗了用os.listdir确认真实文件名。python -c import os; print(os.listdir(./ml_homework))这种方式适合把解压逻辑写进自动化脚本交给组员复用。我一般只在需要批量处理多个压缩包时用 py7zr单次解压还是命令行更省事。2.4 解压之后先画一张工程地图作业包解压完先别急着点开主脚本用文本方式把目录结构看清楚。注意不要用 mermaid直接在代码块里画一个简化的目录树就够用ml_homework/ ├── data/ │ ├── train.csv │ └── test.csv ├── code/ │ ├── main.py │ ├── preprocess.py │ └── model.py ├── report/ │ ├── 模板.docx │ └── 实验截图要求.pdf └── README.md拿到这个结构后读文件的优先级是README 大于主脚本主脚本大于报告模板。README 里通常会写环境依赖和运行顺序这是整份作业的“说明书”。如果 README 没有写清楚就看主脚本的 import 部分把所有第三方库汇总成一个requirements.txt然后按main.py的调用顺序反推数据流向。这一步能帮你省掉后面一半的排错时间。3. 数据读取与特征工程从原始表格到可训练的样本3.1 数据集读取CSV 编码与缺失值处理作业数据一般是 CSV 格式第一行是列名行数是几千到几万不等。训练集和测试集的结构不完全相同是常态测试集常常少一列目标值。最常见的读取方式是用 pandasimport pandas as pd # 训练集 train_df pd.read_csv(data/train.csv, encodingutf-8) # 如果报 UnicodeDecodeError换 gbk 再试 # train_df pd.read_csv(data/train.csv, encodinggbk) print(train_df.shape) print(train_df.info()) print(train_df.head())这段代码背后有两件事值得说清楚。第一encoding参数要看数据文件的实际编码作业数据从课程平台导出的中文 CSVutf-8 和 gbk 各占一半我的习惯是先file data/train.csv看一眼编码再决定读入参数而不是一个个试。第二info()会打印每列的缺失值数量机器学习作业里最常见的坑是某列缺失比例超过 30%直接 dropna 会把训练样本砍掉一半这时候要先想清楚这个特征是不是本来就该缺失。缺失值处理的具体策略按特征类型分三类作为参考特征类型常用策略适用场景数值连续型中位数填充分布有偏均值被极端值拉高数值连续型均值填充分布接近正态缺失比例 5%分类型众数填充类别分布不极端众数有代表性时间序列型前向填充按时间排序缺失值前后有相关性作业场景里我一般优先中位数因为课程数据里离群值不少均值容易被带偏。如果你看到代码里用SimpleImputer或df.fillna(df.median())背后的选择逻辑就是上面这张表。3.2 特征工程标准化、编码与文本向量化作业数据如果全是数值特征直接做标准化就行。常见做法是用StandardScaler它把特征变成均值为 0、方差为 1 的分布这对后面对数几率回归和 SVM 的影响很大。如果直接拿原始数值喂给模型量级大的特征会在损失函数里占据主导地位模型看似收敛实际学到的是尺度假象。from sklearn.preprocessing import StandardScaler scaler StandardScaler() train_X scaler.fit_transform(train_df[[年龄, 收入, 消费次数]]) test_X scaler.transform(test_df[[年龄, 收入, 消费次数]])这段代码的关键是fit_transform和transform的区分训练集上fit_transform拟合均值和方差测试集上只能transform不能重新 fit。如果测试集也调fit_transform相当于让模型提前看到了测试集的分布信息作业报告的评估结果会虚高这在答辩时一问就露馅。分类特征的处理则要看类别数量。类别少于 10 个的时候用OneHotEncoder展开成哑变量类别超过 50 个的时候考虑LabelEncoder直接标号或者干脆扔掉该特征。对于作业数据最常见的是前三类特征加一个文本描述列前三类做 one-hot文本列做 TF-IDF 向量化然后拼成一个大矩阵。from sklearn.feature_extraction.text import TfidfVectorizer from scipy.sparse import hstack tfidf TfidfVectorizer(max_features500, ngram_range(1, 2)) X_text tfidf.fit_transform(train_df[描述]) import numpy as np from scipy.sparse import csr_matrix X_num csr_matrix(train_X) X_all hstack([X_num, X_text]) print(X_all.shape)max_features500限制特征维度防止文本列直接撑爆内存ngram_range(1, 2)同时保留单词和相邻词组合对中文短文本的分类效果提升明显但计算量会翻几倍数据量超过两万行时建议先跑(1, 1)看基线再决定要不要升到(1, 2)。作业里如果时间紧直接固定(1, 1)也不是不行准确率通常只差 1 到 2 个点。3.3 数据集划分分层抽样是隐藏得分点划分训练集和验证集看起来是两行代码的事但参数选不对会直接导致验证集分布失真。分类任务里如果正负样本比例是 9:1随机切分很容易让验证集里某一类样本数量很少模型评估结果波动非常大。from sklearn.model_selection import train_test_split X_train, X_val, y_train, y_val train_test_split( X_all, train_df[标签], test_size0.2, random_state42, stratifytrain_df[标签] )stratify参数是分类任务的标准配置它保证切分后训练集和验证集里各类别比例和原始数据一致。random_state42固定随机种子这组数字本身没有特殊含义但不同组员跑出来的结果必须完全一致否则报告里没法讨论谁调的参数更好。作业报告里经常要求放三次实验的平均结果如果不固定种子三次结果每次都不一样老师一眼就能看出你没理解实验设计。4. 模型训练与评估线性模型、集成模型与参数怎么选4.1 逻辑回归基线模型为什么选它作业里第一个该跑的模型是逻辑回归。原因很朴素它是线性模型训练快参数少结果好解释。老师在答辩时最常问的问题是“为什么选这个模型”逻辑回归的回答链路是最短的先验证特征和标签之间有没有线性关系再谈非线性模型做提升。from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score, f1_score model LogisticRegression(C1.0, max_iter1000, solverlbfgs) model.fit(X_train, y_train) y_pred model.predict(X_val) print(Acc: %.4f % accuracy_score(y_val, y_pred)) print(F1: %.4f % f1_score(y_val, y_pred, averagemacro))solverlbfgs是默认值适合中小型数据集且多分类场景如果数据量特别大可以换saga但它收敛慢需要配合更大的max_iter。C是正则化强度的倒数C 越大正则越弱、越容易过拟合C 越小正则越强、越容易欠拟合默认C1.0可以先跑通流程再调参。max_iter只设 100 时如果收敛警告出现优先调大它不要动别的参数。4.2 随机森林与梯度提升什么时候从线性模型换过来逻辑回归跑完基线如果验证集 F1 在 0.7 以下说明线性模型没有捕捉到特征间的非线性关系这时切入集成模型是合理的。随机森林的优点是几乎不需要特征缩放对缺失值容忍度高缺点是模型变大后推理变慢梯度提升树精度更高但参数更多调起来更费时间。from sklearn.ensemble import RandomForestClassifier rf RandomForestClassifier( n_estimators200, max_depth10, min_samples_split4, random_state42, n_jobs-1 ) rf.fit(X_train, y_train) print(RF Acc: %.4f % rf.score(X_val, y_val))n_estimators200是随机森林里提升最明显的参数200 之前准确率涨得快之后再翻倍收益递减max_depth10限制树深度防止单棵树记住噪声min_samples_split4让节点分裂至少需要 4 个样本这是抑制过拟合的第二道防线。n_jobs-1表示用满所有 CPU 核心课程机器一般 8 核这个参数能把训练时间缩短到接近单核的八分之一。4.3 网格搜索作业里最容易被问细节的操作调参如果用手写循环代码丑且慢。作业里标准做法是网格搜索加交叉验证下面的写法覆盖了 5 折交叉验证和候选参数组合from sklearn.model_selection import GridSearchCV param_grid { C: [0.1, 1.0, 10.0], solver: [lbfgs] } gs GridSearchCV( LogisticRegression(max_iter1000), param_grid, cv5, scoringf1_macro, n_jobs-1 ) gs.fit(X_train, y_train) print(gs.best_params_) print(gs.best_score_)cv5会把训练集切成 5 份每份轮流做验证其余 4 份做训练最后取平均 F1 决定最优参数。scoringf1_macro适合类别不均衡场景用准确率会被多数类掩盖。网格搜索跑完gs.best_params_是最优参数组合gs.best_score_是交叉验证平均分。注意网格搜索是在训练集内做的和测试集没有关系报告里写得分时必须区分清楚“验证集得分”和“交叉验证得分”。4.4 对比实验一张表说清模型选择依据作业报告里通常需要一个对比表列出不同模型在同一验证集上的表现这既是给老师看的也是帮自己做决策的工具。一个典型的对比表如下模型准确率F1 (macro)训练时间逻辑回归0.8230.8011.2s随机森林0.8510.83418.3s梯度提升0.8620.84556.7s表格里的数据要来自同一份验证集、同一种评估方式时间用time.time()包住训练过程记录。模型选择时我一般按这条线走先要求逻辑回归达到 0.8 以上的 F1再尝试随机森林看能涨多少如果随机森林提升超过 3 个点再花时间调梯度提升才有意义。5. 避坑指南解压、编码、路径与随机种子5.1 现象7z 解压后中文文件名全部乱码原因压缩包在 Windows 上用 7-Zip 创建文件名编码为 GBKLinux 系统默认按 UTF-8 解码两边对不上。解决解压时指定编码参数或者用convmv批量转换文件名编码。# 先解压 7z x 电子科技大学机器学习大作业.7z -o./ml_homework # 转换文件名编码 gbk - utf-8 convmv -f gbk -t utf-8 -r ./ml_homework --notest--notest表示真正执行重命名不加它只做预览。我一般建议先不加--notest跑一遍确认要改的文件名列表符合预期再带参数正式执行。5.2 现象压缩包提示密码正确但一直报错解压失败这个问题的出现频率远比想象中高。原因通常不是密码本身而是文件名校验失败或压缩包分卷缺失。7z 在密码正确的前提下如果文件名编码异常会报出类似 “Cannot open file as archive” 或 CRC 错误。另一个常见情况是压缩包被分卷打包你只拿到了.7z.001而没有后续分卷。解决先确认同目录下是否有.7z.002、.7z.003等分卷再检查解压命令是否指定了正确的字符集参数最后确认密码里是否包含被终端转义的特殊字符比如$、、!这类字符在终端里需要用单引号包住密码。# 密码含特殊字符时用单引号包住 7z x 电子科技大学机器学习大作业.7z -pPssw0rd!5.3 现象pandas 读 CSV 报 UnicodeDecodeError原因数据的实际编码和代码里指定的编码不一致。解决先用file命令确认文件编码再按探测结果修改 read_csv 参数不要盲目在 utf-8 和 gbk 之间反复试。file data/train.csv # 输出示例: CSV text, with CRLF line terminators5.4 现象Notebook 里跑脚本报找不到文件但文件明明在原因Notebook 的工作目录不等于脚本所在目录。Jupyter 默认的工作目录是启动时所在的目录如果你的.ipynb在code/子目录而数据在data/用相对路径data/train.csv会直接失败。解决在 Notebook 第一格强制切换工作目录。import os os.chdir(/绝对路径/ml_homework) print(os.getcwd())绝路径写死后换机器要改所以我一般把它写成内核启动时自动执行只保证一次运行通畅。另一个折中方案是使用pathlib.Path(__file__).parent定位脚本所在目录但 Notebook 里没有__file__变量只能切目录。5.5 现象随机森林训练结果每次都不一样原因模型内部有随机性没有固定随机种子。解决不只是模型本身数据切分和特征工程里的随机操作也要固定种子。凡是带random_state参数的地方都统一设为同一个值这是最容易被忽略的细节。# 数据切分 train_test_split(..., random_state42) # 模型实例化 RandomForestClassifier(..., random_state42) # 如果用了 SMOTE 之类的采样方法 # SMOTE(random_state42)6. 验证模型与扩展交叉验证、学习曲线与后续衔接6.1 用学习曲线判断过拟合和欠拟合换一个评判维度看模型状态。学习曲线横轴是训练样本量纵轴是模型得分训练集和验证集两条线的走势能直接说明问题。训练集得分高而验证集得分低是过拟合两条线都低是欠拟合两条线接近且随样本量单调上升是数据不够。一段快速绘制的实现import numpy as np import matplotlib.pyplot as plt from sklearn.model_selection import learning_curve train_sizes, train_scores, val_scores learning_curve( rf, X_train, y_train, cv5, train_sizesnp.linspace(0.1, 1.0, 5), scoringf1_macro ) train_mean train_scores.mean(axis1) val_mean val_scores.mean(axis1) plt.plot(train_sizes, train_mean, labeltrain) plt.plot(train_sizes, val_mean, labelvalidation) plt.legend() plt.xlabel(Training examples) plt.ylabel(F1 macro) plt.show()learning_curve的train_sizes指定按 10%、30%、50%、70%、100% 五个档位逐步增加训练样本每个档位做 5 折交叉验证得到每个档位下的平均得分。曲线画出来后如果训练集和验证集始终差 3 个点以上说明模型容量超出数据需要优先降低max_depth或增加正则化如果验证集得分还在明显上升趋势中说明数据量不足拿到更多数据比换模型更有用。作业报告里放学习曲线图是加分项关键是写清楚曲线告诉你的下一步动作而不是只贴图。6.2 特征重要性验证哪些特征真的在起作用模型跑完后随机森林的feature_importances_可以直接输出每个特征的贡献度。作业报告里通常会要求讨论特征选择的合理性这一步能帮你把结论落到实处importances rf.feature_importances_ feature_names [年龄, 收入, 消费次数] [ftext_{i} for i in range(X_text.shape[1])] top_indices np.argsort(importances)[::-1][:10] for i in top_indices: print(f{feature_names[i]}: {importances[i]:.4f})排序后如果文本类特征占了一半以上说明标签更依赖描述文本如果数值特征占主导说明标准化阶段和数值特征工程做得扎实。这些结论可以直接写进作业报告的“结果分析”部分比干巴巴放准确率数字更有说服力。6.3 和课程的后续衔接这份作业能导出什么成果课程作业的影响范围不止于期末分数。从这份作业里已经跑通的数据预处理代码、模型对比实验、评估函数可以直接复用到毕设开题实验里。更直接的做法是把它整理成一份个人项目把“电子科技大学机器学习大作业”的课程属性从代码里摘出来替换成自己的数据集和任务描述补一段 README 说明运行环境就变成一个可以放进作品集的小项目。这也是我把这份资源推荐给从业者的原因它不只是一份应付检查的作业更是一份可以二次开发的基线工程。建议你在跑通之后留一个压缩包备份里面同时保存原始代码和修改后的最终版这样不管以后要复现实验还是要迁移到新任务都有后悔药可吃。从那以后我每次拿到别人的项目压缩包都强制先走一遍“解压、看结构、跑基线、看曲线”这套流程再动笔改任何一行代码。希望帮到你。本文还有配套的精品资源点击获取