简介面向机器学习初学者与算法实践者这份压缩包将八种经典分类算法——AdaBoost、朴素贝叶斯、决策树、KNN、逻辑斯蒂回归、最大熵、SVM与感知机——统一用于MNIST手写数字识别任务提供一套完整的Python参考实现与使用案例。包内共有15个文件其中13个为.py脚本另附1个说明文档和1个辅助文本整体仅27KB轻量便携适合快速下载与本地运行。各类算法均按独立目录组织各自配有可执行的主程序部分还包含独立子模块同时提供决策树相关辅助文件与README说明便于按步骤重现结果、调整超参数并对比不同模型在同一数据上的分类精度与收敛表现。对希望掌握多种分类器原理、完成机器学习课程作业、或进行算法横向对比的读者这套代码既可作为入门模板也能作为扩展开发的起点。目前已有726人学习下载兼具实用性与参考价值。1. 一份跑通八种MNIST算法的源码包先看它能替你省下什么手头拿到一个sklearn-MNIST-main的压缩包打开一看adaboost、贝叶斯朴素法、决策树、KNN、逻辑斯蒂、最大熵、SVM、感知机八个算法目录排得整整齐齐每个目录下都挂着main.py或main1.py。这不是论文代码也不是教学演示而是一份能直接跑通的手写数字识别底稿——它把MNIST数据装载、训练、预测、评估这条链路在每个算法里都走了一遍。对正在做课程设计、入门机器学习对比实验、或者想快速抄一份能交差代码的人来说最值钱的不是某个算法的精度而是八个算法共用同一套数据管道的写法换算法只换模型行前后处理完全复用。我拆完这份包之后把每个脚本从头到尾过了一遍下面这篇笔记就是按“数据怎么进来、八个算法各自怎么落地、坑在哪、跑通后怎么变成工具”的顺序写的。2. 先把数据弄明白MNIST怎么装、装成什么形状、这份包怎么组织2.1 数据装载与标签转换npz格式和keras接口的取舍MNIST 最常见的获取方式有两种一是keras.datasets.mnist.load_data()二是直接读mnist.npz文件。很多初学者在这第一步就翻车因为keras接口在不同版本下的返回格式略有差异而且它依赖后端环境TensorFlow 没配好就报AttributeError。这份源码包里用的是后者——从data目录直接读mnist.npz再用 numpy 手动拆开好处是不依赖深度学习框架sklearn 环境下就能跑。import numpy as np # 从本地读取 mnist.npz对应包里的 data 目录 with np.load(data/mnist.npz) as f: x_train, y_train f[x_train], f[y_train] x_test, y_test f[x_test], f[y_test] # 原始数据是 28x28 的二维矩阵分类器需要一维特征这里直接拉平 x_train x_train.reshape(x_train.shape[0], 784).astype(float32) x_test x_test.reshape(x_test.shape[0], 784).astype(float32) # 标签统一转成 int后面做混淆矩阵和分类报告时才不会踩类型的坑 y_train y_train.astype(int) y_test y_test.astype(int) print(f训练集: {x_train.shape}, 测试集: {x_test.shape}) print(f标签范围: {y_train.min()} - {y_train.max()})这段代码的核心是reshape(x_train.shape[0], 784)MNIST 每张图是 28 乘 28 像素展开后就是 784 维向量这个维度对后面所有算法都一样。astype(float32)是为了减少内存占用八种算法里 KNN 和 SVM 特别吃内存如果默认读进来是float64训练集 60000 乘 784 的矩阵直接占掉几百 MB再加上算法内部的复制很容易把 8GB 内存的机器跑崩。标签转int是很多脚本里容易漏掉的一步——sklearn 的accuracy_score在标签是uint8时也能算但一旦做classification_report输出类别名或者画混淆矩阵类型不统一就会报警告。2.2 一份能直接跑的sklearn-MNIST目录导览数据目录和各算法入口别走错拆开压缩包后目录结构很清楚但第一次打开的人容易犯一个迷糊main.py和main1.py到底有什么区别。我在decision_tree、svm、max_shang这些目录里看到两个入口文件实际对一遍代码发现main.py是完整流程版——装载数据、切分、训练、评估一步不落main1.py是精简版有的只输出准确率有的把模型参数写死成了硬编码。跑的时候用哪个都行建议以main.py为准因为它的输出信息更全能看到分类报告和混淆矩阵。这份包里还有一个值得注意的点max_Ent.py放在max_shang目录下但目录里同时存在main.py两者不是同一份代码。拆开看max_Ent.py是用“最大熵模型的迭代求解”思路写的本质上是把逻辑斯蒂回归的多分类版本用梯度下降手工实现了一遍main.py则是直接调 sklearn 的LogisticRegression做对照。这些入口文件的位置是作者按自己习惯放的你复制到别的项目里时最好统一重命名避免后面维护的时候不知道跑哪个。2.3 train_test_split与归一化为什么MNIST必须除255而不是做标准化from sklearn.model_selection import train_test_split # 进一步切出验证集方便调参阶段快速看效果 x_train_sub, x_val, y_train_sub, y_val train_test_split( x_train, y_train, test_size0.2, random_state42, stratifyy_train ) # 像素归一化到 [0, 1]这是 MNIST 场景下最稳的预处理 x_train_sub x_train_sub / 255.0 x_val x_val / 255.0 x_test x_test / 255.0 print(f验证集大小: {x_val.shape[0]})这里用test_size0.2表示从 60000 张训练图里留出 12000 张做验证random_state42保证每次切分的结果一致stratifyy_train让切分后的类别比例和原始数据集一致——MNIST 里数字 0 和 1 的样本量本身就有差异不 stratify 的话某些数字可能在验证集里明显变少影响模型对比的可信度。归一化除 255 而不是做StandardScaler标准化是因为图片像素本身就是 0 到 255 的亮度值除 255 后落在 0 到 1 区间物理意义保留也避免标准化后负数像素把某些分类器的决策边界搞偏。SVM 和 KNN 对特征尺度极敏感这一步不做后面说啥都白搭。3. 八个算法逐个落地每个脚本的入口行、参数和动手改的位置3.1 KNN最容易出效果但也最吃内存的基线KNN 在这份包里被放在knn目录main.py的实现用的是最经典的KNeighborsClassifier。MNIST 用 KNN 的直觉很简单784 维空间里同数字的图片距离近不同数字的距离远。它不需要训练过程但预测时要拿新样本和所有训练样本算距离所以内存和耗时都在这里。from sklearn.neighbors import KNeighborsClassifier # n_neighbors5 是 sklearn 默认值MNIST 上可以先从 3 试起 knn KNeighborsClassifier( n_neighbors5, weightsdistance, # 距离加权近的邻居投票权重大 algorithmkd_tree, # 数据维度高kd_tree 比 brute 省时间 n_jobs-1 # 用满所有 CPU 核KNN 是天然可并行的 ) knn.fit(x_train_sub, y_train_sub) val_acc knn.score(x_val, y_val) print(fKNN 验证集准确率: {val_acc:.4f})weightsdistance是 KNN 在 MNIST 上是否好用的关键开关默认的uniform让所有邻居投票权重一样但如果某几个邻居离得非常远它们的票和最近邻同权很容易带偏。改成distance后距离近的样本话语权更大能明显提升准确率。algorithmkd_tree在高维数据上有争议因为 784 维下 kd_tree 的切分效率会退化但实际跑起来比暴力brute略快如果你要追求极致速度可以改成brute然后靠n_jobs-1拉满并行。3.2 逻辑斯蒂回归max_iter和solver参数别抄默认值logistics/logistics.py这份代码和别的目录有个明显区别它不是直接调 sklearn而是先写了一个二元逻辑斯蒂的梯度下降实现再在main.py里调LogisticRegression做多分类对照。这部分代码的价值在于让你看到手写实现和库实现的差距——手写版本跑得慢还不一定收敛库版本收敛稳定且接口完整。from sklearn.linear_model import LogisticRegression # MNIST 是多分类solver 用 lbfgs 或 newton-cg 都行别用 liblinear log_reg LogisticRegression( solverlbfgs, max_iter300, # 默认 100 在 MNIST 上经常没收敛就停了 multi_classmultinomial, C1.0 ) log_reg.fit(x_train_sub, y_train_sub) train_acc log_reg.score(x_train_sub, y_train_sub) val_acc log_reg.score(x_val, y_val) print(f逻辑斯蒂 训练集准确率: {train_acc:.4f}, 验证集准确率: {val_acc:.4f})max_iter300是这份代码里最实用的一行sklearn 默认max_iter100但 MNIST 有 784 维特征和 10 个类别优化器 100 轮根本不够跑完你会发现警告刷屏准确率也偏低。提到 300 是稳妥值再往上提收益就很小了。multi_classmultinomial表示用 Softmax 做多分类比ovr一对一在这个场景下更合适因为 MNIST 数字类别之间有相似性多项逻辑斯蒂能捕捉类别间的概率竞争关系。3.3 朴素贝叶斯高斯分布假设下MNIST的奇特表现bayes目录下的实现用的是GaussianNB这个选择本身值得说一句朴素贝叶斯假设特征之间独立MNIST 的像素点显然不独立相邻像素强相关所以理论上它在该数据集上表现不会太好。但代码的价值恰恰在于给你一个“反直觉”的基线——跑出来你就会发现它比想象中高因为手写数字的像素分布有强先验。from sklearn.naive_bayes import GaussianNB # var_smoothing 是平滑项数值越大对噪声越容忍 gnb GaussianNB(var_smoothing1e-9) gnb.fit(x_train_sub, y_train_sub) val_acc gnb.score(x_val, y_val) print(f高斯朴素贝叶斯 验证集准确率: {val_acc:.4f})var_smoothing1e-9是这里唯一的可调参数。它控制方差估计时的平滑量如果某个像素在所有样本里取值几乎不变方差会趋于 0除零就会导致概率计算崩溃。调大平滑值能让模型更稳但也会让边界变钝。我自己试过1e-2准确率会掉零点几个点所以1e-9是个不错的默认值。值得留意的是高斯朴素贝叶斯在 MNIST 上的训练速度快到令人发指几秒钟就完事适合作为“先跑通整条流水线”的探路模型。3.4 决策树max_depth不设就是全量特征的黑匣子decision_tree目录是最有意思的——里面除了main.py还带了一个myTree.txt是某次运行生成的树结构文本。打开这个文本你会看到一棵深不见底的树一层层判断“第 234 个像素是否大于 0.5”。这恰恰是决策树在 MNIST 上的最大陷阱不加深度限制它会无限生长把训练集背下来。from sklearn.tree import DecisionTreeClassifier # max_depth 必须限制否则树深随特征数膨胀过拟合到没法看 dt DecisionTreeClassifier( max_depth12, # 经验值8~16 之间都可以试 min_samples_leaf4, # 叶子节点最少样本数压制噪声分支 criteriongini ) dt.fit(x_train_sub, y_train_sub) train_acc dt.score(x_train_sub, y_train_sub) val_acc dt.score(x_val, y_val) print(f决策树 训练集准确率: {train_acc:.4f}, 验证集准确率: {val_acc:.4f})max_depth12是调参的核心如果你用默认None训练集准确率能到 99% 以上但验证集会掉到 80% 上下这就是典型的把噪声学进去了。min_samples_leaf4的意思是每个叶子节点至少要有 4 个样本才允许生成这个参数能过滤掉那些只对极个别样本有效的分裂。决策树在 MNIST 上你就别指望它拿最高分它的作用有两个一是作为集成学习的弱学习器底稿二是让你直观看到“决策树如何逼近真实曲线”——每深一层决策边界就多一次切分但到后面全是在拟合噪声。3.5 支持向量机线性核与rbf核在784维上的取舍svm目录里同样存在main.py和main1.py两个版本主版本用的是SVC并且同时演示了线性和 rbf 两种核。MNIST 原本就是 784 维样本量 6 万SVM 在这里是典型的“能做但别太贪”的模型——rbf 核准确率高但训练时间以小时计。from sklearn.svm import SVC # 先跑线性核速度极快拿一个基线分数 svm_linear SVC(kernellinear, C1.0) svm_linear.fit(x_train_sub, y_train_sub) print(fSVM 线性核 验证集准确率: {svm_linear.score(x_val, y_val):.4f}) # rbf 核准确率更高但计算量爆炸建议只在子集上验证 svm_rbf SVC(kernelrbf, gammascale, C1.0) svm_rbf.fit(x_train_sub, y_train_sub) print(fSVM rbf核 验证集准确率: {svm_rbf.score(x_val, y_val):.4f})gammascale是 sklearn 自动根据特征数计算 gamma 值的方式在 784 维下它会自动调小避免高维空间里距离度量失衡。这段代码还藏着一个性能教训rbf 核的 SVC 在 48000 个训练样本上 fit 一次可能要十几分钟机器内存不够还会崩。我的建议是在完整数据上跑线性核拿基线rbf 核只在切出来的 5000 到 10000 个子集上验证效果方向对再决定要不要全量跑。3.6 感知机原始形式与sklearn默认参数的不一致preceptron目录下的实现很有诚意main.py手写了一个感知机类包括权重初始化和迭代更新demo.py做可视化演示。感知机是最早的线性分类器它和 SVM 的决策本质一样是找一条直线超平面差别在于感知机只在误分类点更新权重没有间隔最大化的概念所以最终解不唯一。from sklearn.linear_model import Perceptron # Perceptron 在 sklearn 里本质上就是 SGD 分类器的一种特例 perc Perceptron( max_iter1000, # 感知机要迭代到收敛100 轮不够 tol1e-3, # 损失变化小于这个值就停 random_state42 ) perc.fit(x_train_sub, y_train_sub) val_acc perc.score(x_val, y_val) print(f感知机 验证集准确率: {val_acc:.4f})max_iter1000是手写版本和 sklearn 版本之间最容易出现差异的地方手写代码里你控制的是“对整个训练集扫多少遍”sklearn 的max_iter也是这个意思但默认只有 100。MNIST 特征维度高100 遍根本不足以让权重收敛到误差平稳区。tol1e-3表示连续两次迭代的损失变化小于这个阈值就提前停止训练它配合max_iter能省不少时间——实际跑的时候经常在几百轮就触发了提前停止。3.7 AdaBoostSAMME算法与弱学习器数量怎么组合adaboost目录下的main1.py是集成学习的入口。AdaBoost 在 MNIST 上的经典用法是以决策树桩深度为 1 的决策树作弱学习器通过反复调整样本权重把多个弱分类器加权组合成一个强分类器。sklearn 的AdaBoostClassifier默认支持SAMME和SAMME.R两种算法多分类场景下SAMME更通用。from sklearn.ensemble import AdaBoostClassifier from sklearn.tree import DecisionTreeClassifier # 弱学习器用深度为 1 的决策树桩这是 AdaBoost 的经典搭档 base_est DecisionTreeClassifier(max_depth1) ada AdaBoostClassifier( estimatorbase_est, n_estimators200, # 弱学习器数量越多拟合越强但也容易过拟合 learning_rate0.8, # 每轮的权重衰减调低能增强泛化 algorithmSAMME, random_state42 ) ada.fit(x_train_sub, y_train_sub) val_acc ada.score(x_val, y_val) print(fAdaBoost 验证集准确率: {val_acc:.4f})n_estimators200和learning_rate0.8是一对配合参数弱学习器多了模型对训练集的拟合增强但超过某个临界点后验证集准确率不再上升甚至下降调低learning_rate会让每个弱学习器的权重更新幅度变小需要更多树来补齐但泛化能力通常更好。这份代码选 200 和 0.8 是个不错的起点跑完看验证集曲线如果准确率还在上升就加到 300 试试如果已经持平就别再浪费训练时间了。algorithmSAMME在高版本 sklearn 里是默认值写出来是为了提醒你如果你用的是老版本SAMME.R要求弱学习器能输出概率深度为 1 的决策树桩概率输出不平滑用SAMME更稳。3.8 最大熵从最大熵到逻辑斯蒂的等价关系最大熵这个目录在别的 MNIST 教程里很少见值得单独说。最大熵模型的思路是在满足已知约束的条件下选择熵最大的概率分布。当特征函数定义得当、用对数线性模型建模时最大熵模型和逻辑斯蒂回归在数学上是等价的——这也是为什么max_shang目录里同时存在手写实现的max_Ent.py和调 sklearn 的main.py。# max_Ent.py 的核心用梯度下降迭代更新权重 def train_maxent(features, labels, lr0.01, epochs200): n_samples, n_features features.shape n_classes len(np.unique(labels)) # 权重初始化全零或小随机数 weights np.zeros((n_features, n_classes)) for epoch in range(epochs): # 线性部分 scores features weights # softmax 得到概率分布 exp_scores np.exp(scores - scores.max(axis1, keepdimsTrue)) probs exp_scores / exp_scores.sum(axis1, keepdimsTrue) # 梯度真实标签的 one-hot 减去预测概率 grad features.T (probs - one_hot(labels, n_classes)) weights - lr * grad / n_samples if epoch % 50 0: print(fepoch {epoch} 完成) return weightsmax_Ent.py里软最大函数scores.max(axis1, keepdimsTrue)是数值稳定的关键如果不先减去最大值exp在大数值输入下可能溢出成inf。lr0.01作为学习率在 200 轮内能收敛到一个不错的位置但比 sklearn 的lbfgs要慢不少。我的建议是手写版只用来理解最大熵的原理和梯度推导要拿准确率还是跑main.py的LogisticRegression两者结果一致正好反过来验证你的推导没写错。4. 避坑MNIST下载404、内存爆炸、收敛警告逐个给你排查路径4.1 torchvision下载MNIST报404或连接失败现象用torchvision.datasets.MNIST(root./data, downloadTrue)下载时报HTTP Error 404或者连接超时卡死不动。原因MNIST 官方源在部分网络环境下访问不稳定torchvision默认下载地址响应失败。这不是代码写错了是网络链路问题。解决换成手动下载mnist.npz文件放到项目的data目录再用np.load读取这一点正是这份源码包的做法。下载时注意不要解压npz是压缩格式代码里直接 load 就行。若np.load遇到编码问题给np.load加上allow_pickleFalse再读。4.2 KNN把内存吃满进程卡死现象knn.fit后进行knn.score时内存占用一直涨最后进程被杀或卡死。原因KNN 不显式训练但预测时要保存全部训练样本作为参考集。60000 个 784 维的数组本来就占内存代码里如果用float64存储每张图占 6272 字节合计约 360 MB 的参考集再加上 sklearn 内部距离矩阵的中间存储和n_jobs-1的多进程复制内存直接爆。解决数据读入后立刻astype(float32)把内存减半algorithm优先选kd_tree或ball_tree避免brute模式下生成全量距离矩阵真遇到超大输入用n_neighbors更小的值并配合chunk_size分批预测。4.3 ConvergenceWarning 刷屏模型准确率偏低现象跑逻辑斯蒂或最大熵时控制台不停弹ConvergenceWarning: Maximum iterations reached最终准确率也明显低于预期。原因sklearn 默认max_iter100在 784 维特征和 6 万级样本下优化器 100 轮通常还没走到最优解附近。SVM 等其他迭代类模型同理。解决把max_iter提到 300 到 500。改完之后如果警告消失但准确率没明显变化说明模型已经收敛这时再加大max_iter没有意义。还有一个隐藏点tol参数默认1e-4如果你的数据没归一化梯度量级大tol更严格会触发更多迭代归一化之后tol保持默认就好。4.4 决策树训练集准确率99%验证集却只有七成多现象决策树训练集准确率接近 1.0验证集准确率明显下滑两者差值超过 15 个百分点。原因决策树没限制深度树把训练集里每个数字的笔画细节、噪声点全背下来了这正好对应热搜里反复出现的“决策树如何逼近真实曲线”问题——它逼近过头了逼近的不是真实曲线而是训练集的噪声。解决max_depth从 8 到 16 之间用 2 的步长网格搜索同时设min_samples_leaf4。这两个参数往大了调训练集和验证集的准确率差距会缩小。注意一定要同时看两组数字只盯验证集准确率也容易误判。4.5 分类报告提示标签问题准确率统计出错现象classification_report(y_test, y_pred)报ValueError: Classification metrics cant handle a mix of multilabel-indicator and multiclass targets或者报告里类别信息乱掉。原因y_test是uint8或str类型y_pred是int两个数组 dtype 不一致sklearn 的指标函数无法自动对齐。解决统一在数据装载阶段做y.astype(int)同时检查predict的结果是否经过.astype(int)。神经网络真实标签文件里这种情况非常常见早期 dtype 不一致不报错拖到分类报告阶段才暴露很多人被这一下搞懵。5. 把八种算法的结果横向拉齐混淆矩阵、样本可视化与模型对比5.1 用混淆矩阵看KNN和SVM的混淆集中在哪两类跑完单个算法之后下一步一定是横向对比。最简单有效的手段是每个模型生成一张混淆矩阵看看预测错误集中在哪里——MNIST 上最经典的混淆是 4 和 9、3 和 8、7 和 2这些数字形近线性模型分不开很正常。from sklearn.metrics import confusion_matrix, classification_report import seaborn as sns import matplotlib.pyplot as plt # y_pred 来自任意一个训练好的模型 cm confusion_matrix(y_test, y_pred) plt.figure(figsize(8, 6)) sns.heatmap(cm, annotTrue, fmtd, cmapBlues) plt.xlabel(预测标签) plt.ylabel(真实标签) plt.show() # 打印每个类别的精确率、召回率、F1 print(classification_report(y_test, y_pred))fmtd让热力图显示整数计数而不是科学计数法annotTrue在每个格子里标出数值。分类报告里的macro avg是十个类别指标的平均如果它明显低于accuracy说明模型在某几个少数类别上特别差光看总准确率会漏掉这个信息。5.2 错误样本可视化把预测错的图打印出来定位问题混淆矩阵告诉你“哪里错了”但不知道“错在什么图”上。把预测错误的样本打印成图片是最直观的定位手段——你会发现很多错误样本连人眼都难分辨模型能分对反而奇怪。import math def show_misclassified(images, true_labels, pred_labels, num10): errors np.where(true_labels ! pred_labels)[0] show_idx errors[:num] # 取前 num 个错误样本 cols 5 rows math.ceil(num / cols) plt.figure(figsize(cols * 2, rows * 2)) for i, idx in enumerate(show_idx): plt.subplot(rows, cols, i 1) plt.imshow(images[idx].reshape(28, 28), cmapgray) plt.title(f真:{true_labels[idx]} 预:{pred_labels[idx]}) plt.axis(off) plt.tight_layout() plt.show() show_misclassified(x_test, y_test, y_pred, num10)errors np.where(true_labels ! pred_labels)[0]是所有预测错误的索引errors[:num]取前 10 个。打印出来的图片如果看起来确实模糊、偏斜、有干扰线就说明模型没问题如果有几张图片人眼看很清楚但模型错了那大概率是预处理或训练数据问题比如训练时没做数据增强、图没对齐。5.3 模型对比表把八种算法的训练时间、准确率和适用场景拉齐把八种算法跑完后整理一张对比表是课程设计报告里必不可少的内容。我拆这份包时顺手跑了一轮表格格式如下你可以直接替换自己的运行结果算法训练时间量级内存占用验证集准确率量级适用场景KNN秒级训练/ 分钟级预测高较高小数据集基线容易快速出结果逻辑斯蒂数十秒低较高需要训练快、可解释性强的场景高斯朴素贝叶斯极快低中等先跑通流水线的探路模型决策树秒级低偏低观察特征分裂过程、课程作业演示线性 SVM秒级中较高高维稀疏数据的入门基线RBF SVM小时级极高最高小样本高精度场景不推荐全量跑感知机数十秒低中等理解线性分类器的收敛过程AdaBoost分钟级中中等偏高需要展示集成学习效果时这张表的价值不只是给你一份答案而是让你知道每种算法的定位KNN 和逻辑斯蒂是“先拿基线”决策树和感知机适合演示原理SVM 和 AdaBoost 是“冲高分的选项但代价大”朴素贝叶斯适合验证流水线是否通着。我在实际跑的时候会用脚本把每种算法的训练时间和准确率自动追加到 CSV 文件里方便最后统一整理成报告表格。6. 跑通之后把它变成工具模型持久化与批量预测的一体化脚本6.1 用joblib把最优模型和归一化参数一起存下来训练完八种算法挑出验证集准确率最高的那个模型接下来的问题是怎么把它保存下来下次直接加载、不用重新训练。joblib是 sklearn 官方推荐的模型持久化方案比pickle对 numpy 数组的压缩效果好得多。import joblib # 保存模型的同时把归一化的基准值也存进去 joblib.dump(best_model, models/best_model.pkl) joblib.dump({scaler: 255.0}, models/norm_config.pkl) print(模型已保存到 models/best_model.pkl) # 下次加载 loaded_model joblib.load(models/best_model.pkl) print(f加载完成模型类型: {type(loaded_model).__name__})保存时只存模型参数不存训练数据joblib会自动处理 sklearn 模型内部复杂的对象结构。归一化基准单独存一份这步很多人忽略——新图片进来自动预测时要除 255但训练那次除 255 后模型已经学好了如果你加载模型后忘了重新归一化预测结果会全部乱掉。所以我把基准一起序列化加载时一并取用。6.2 新图片进来自动预测一套处理28x28输入的完整函数def predict_digit(image_array, model, norm_value255.0): 输入任意形状的图片数组自动转成 MNIST 标准格式并预测。 if image_array.shape ! (28, 28): from skimage.transform import resize image_array resize(image_array, (28, 28), anti_aliasingTrue) # 转灰度、拉平、归一化 img_flat image_array.reshape(1, -1).astype(float32) / norm_value pred model.predict(img_flat) return int(pred[0]) # 从项目目录里取一张测试图 sample x_test[0] print(f预测结果: {predict_digit(sample, loaded_model)})resize只在新图片不是 28 乘 28 时才执行anti_aliasingTrue可以避免缩放产生的锯齿伪影。函数内部统一做reshape(1, -1)表示“一条样本、全特征”这样无论传入的是单张 28 乘 28 图还是已经拉平的一维数组都能正确预测。6.3 批量跑八种算法的自动化循环给自己留一份可复现报告models { KNN: KNeighborsClassifier(n_neighbors5, weightsdistance, n_jobs-1), Logistic: LogisticRegression(max_iter300, solverlbfgs, multi_classmultinomial), BNB: GaussianNB(), Tree: DecisionTreeClassifier(max_depth12, min_samples_leaf4), LinearSVM: SVC(kernellinear, C1.0), Perceptron: Perceptron(max_iter1000, tol1e-3), AdaBoost: AdaBoostClassifier(n_estimators200, learning_rate0.8, algorithmSAMME), } results [] for name, model in models.items(): model.fit(x_train_sub, y_train_sub) acc model.score(x_val, y_val) results.append((name, acc)) print(f{name}: {acc:.4f}) # 按准确率排序输出前三名 results.sort(keylambda x: x[1], reverseTrue) print(\n前三名:) for rank, (name, acc) in enumerate(results[:3], start1): print(f{rank}. {name} - {acc:.4f})注意这个循环里没有把最大熵的代表放进去因为手写版max_Ent.py的接口和 sklearn 的统一fit/predict风格不一致——这也是实际工程里的常态。把接口统一的七个模型放到循环里跑手写模型单独跑然后结果手动合并。批量循环跑一遍并打印前三名之后把这轮结果存成日志文件你手上的这包代码就成了一个可复现的实验报告模板。拆完这份包、写完这份笔记我自己的感想是八种算法跑 MNIST 这件事本身不难难的是第一次搭数据管道时各种怪坑——数据读不进来、内存爆掉、dtype 不一致、收敛警告刷屏。从那时起我每次处理新数据集都会强制走一遍“先小样本跑通→确认 dtype 和归一化→再全量训练”的流程这套习惯帮我省掉了无数次卡死在训练到一半的时间。这份源码包把八种算法的常见坑都踩过一遍了希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
丙午年中秋月 丙午年中秋月月年今晚圆,金桂满院香。田地禾稻黄,柿树枝头绛。街道红旗展,归途车马翔。蔷薇已去花,佳肴烟火酿。千载共此时,万年同福祥。诗酒趁年华,情缘拜爹娘。一路平安行,四时诚信量。御梦完… · 2026/9/26 18:05:21
华麟包装 彩印纸箱定制厂家 适用电商物流/工业品运输 支持小批量起订 外贸纸箱包装行业的发展现状与市场需求近些年,国内外贸出口规模持续增长,机电、汽摩配、日用品、化妆品等品类的出海订单越来越多,出口包装作为出海链路的最后一道防护,需求也在发生明显变化。一方面,出口场景对包装的… · 2026/9/26 18:05:15
养老服务中心怎么挑?先评估老人自理能力再选服务方案 咱们给爸妈选养老机构,先搞懂这2个核心问题先不说挑机构的细节,先得给家里老人做个自理能力评估,这是选服务的根本前提。就拿我邻居张阿姨家老爷子来说,老爷子之前能自己做饭、遛弯,就以为选个普通养老公寓就行&#x… · 2026/9/26 18:05:09
电力系统潮流计算:牛顿-拉夫逊法与P-Q分解法的MATLAB实现 潮流计算在电力系统里属于那种“看起来简单、写起来全是细节”的东西。很多教材把公式推导梳理得很漂亮,但一到 MATLAB 里自己动手,就会遇到雅可比矩阵符号搞混、迭代发散、P-Q 分解法在某个算例里死活不收的尴尬。我当初就是因为不满足于直接调工具箱&a… · 2026/9/26 18:37:53
PP-OCR五种实现路径:从OpenCV到自研引擎的工程落地全景图 1. 为什么这5个PP-OCR项目不是“重复造轮子”,而是技术纵深的必经之路PP-OCR这个词,现在几乎成了OCR领域的默认代名词——轻量、准确、开源、中文友好。但如果你真把它当成一个“开箱即用”的黑盒,那大概率会在实际落地时撞上一堵看不见的墙&… · 2026/9/26 18:37:53
开源大模型安全内生护栏SingProbe Infra:设计、接入与排查指南 模型能力越强,用起来就越要小心。这一两年开源大模型的发展速度肉眼可见,Qwen、Llama、GLM、DeepSeek这些名字已经频繁出现在生产环境里。但大多数团队把模型拉回来部署之后,第一反应是测推理性能、调上下文窗口、压并发,很少有人… · 2026/9/26 18:37:53
大厂Agent工程实践:状态管理、工具契约与可治理性 1. 从“写个脚本”到“设计Agent系统”:一年半里认知边界的三次塌陷刚进大厂做Agent项目时,我脑子里想的还是“怎么让这个自动化流程跑得更稳一点”。带我的导师让我先搭个天气查询Bot,我吭哧吭哧写了三天Python,用Flask暴露API&a… · 2026/9/26 18:37:53
Knative + ACK:云原生弹性伸缩从固定资源池到按需智变 流量曲线跟账单之间的账,做过后端的人多半都心里有数。你的业务一天里峰值可能是低峰的十倍甚至几十倍,但Kubernetes集群里的Pod却只能按峰值预留常驻。结果就是:大促过去Deployment还在那里烧钱,凌晨三四点没人访问的时候&#x… · 2026/9/26 18:37:53
从刷榜到落地:大模型真实场景应用开发实战与避坑指南 1. 从“刷榜”到“落地”:为什么真实场景成了大模型的新战场过去两年,我身边做AI的朋友聊天的画风经历了三次明显转变。2023年上半年,大家见面第一句是“你那边卡够不够”;2023年下半年变成“你们微调用的什么数据集”;… · 2026/9/26 18:37:07
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46