没有 GPU 也能学习小型神经网络。scikit-learn 的 MLPClassifier 可以在 CPU 上训练多层感知机,适合看清“划分数据、标准化、拟合、预测、检查损失”的完整链。下面用两维模拟数据和一个 16 单元隐藏层跑通实例。
这只是小型 CPU 教学模型,不代表你的电脑可以训练或运行任意大模型。scikit-learn 神经网络指南明确说明其 MLP 实现不面向大规模应用,且该实现没有 GPU 支持;文档同时强调 MLP 对特征缩放敏感。

安装环境,先确认使用的是哪个 Python
示例实际运行环境为 Windows、Python 3.11.15、scikit-learn 1.9.1、NumPy 2.4.6。没有安装 CUDA,也没有设置 GPU 设备。新建一个空目录,在终端运行:
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install scikit-learn==1.9.1 numpy==2.4.6
.\.venv\Scripts\python.exe -c "import sklearn, numpy; print(sklearn.__version__, numpy.__version__)"
把下段完整代码保存为 mlp_cpu.py,再用 .\.venv\Scripts\python.exe mlp_cpu.py 运行。macOS 或 Linux 用 python3 建环境,解释器路径换成 .venv/bin/python。若提示 No module named sklearn,先核对运行与安装是否用了同一个解释器。
先划分,再把标准化与网络放进同一管道
make_moons 生成 400 个带噪声的二分类样本,两个输入特征可以理解为坐标。它是算法生成的教学数据,不是用户业务样本。25% 留作测试,训练集只用来拟合 StandardScaler 和网络;测试集使用已经拟合的缩放规则。
隐藏层 16 个单元是学习用的配置,不能凭这个大小断言最优。这里选择 adam 求解器,max_iter 是训练遍历数据的最大轮数。MLPClassifier API 文档定义了这些参数,以及 n_iter_、loss_curve_ 等拟合后的诊断属性。
import warnings
import numpy as np
import sklearn
from sklearn.datasets import make_moons
from sklearn.exceptions import ConvergenceWarning
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
X,y = make_moons(n_samples=400,noise=0.27,random_state=42)
X_train,X_test,y_train,y_test = train_test_split(
X,y,test_size=0.25,stratify=y,random_state=42)
pipe = make_pipeline(StandardScaler(),MLPClassifier(
hidden_layer_sizes=(16,),solver='adam',alpha=0.001,
max_iter=2000,tol=1e-4,random_state=42))
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter('always',ConvergenceWarning)
pipe.fit(X_train,y_train)
net = pipe.named_steps['mlpclassifier']
pred = pipe.predict(X_test)
print('sklearn=', sklearn.__version__, 'numpy=',np.__version__)
print('train/test=',len(y_train),len(y_test))
print('iterations=',net.n_iter_,'max_iter=',net.max_iter)
print('loss_first/last=',round(net.loss_curve_[0],4),round(net.loss_curve_[-1],4))
print('test_accuracy=',round(accuracy_score(y_test,pred),4))
print('convergence_warnings=',sum(isinstance(w.message,ConvergenceWarning) for w in caught))
for warning in caught:
if isinstance(warning.message,ConvergenceWarning):print(str(warning.message))
np.savetxt('mlp_loss.csv',np.column_stack((np.arange(1,len(net.loss_curve_)+1),
net.loss_curve_)),delimiter=',',header='iteration,loss',comments='')
assert pred.shape == y_test.shape
assert np.isfinite(net.loss_curve_).all()
核对实际输出与损失记录
sklearn= 1.9.1 numpy= 2.4.6
train/test= 300 100
iterations= 1089 max_iter= 2000
loss_first/last= 0.6901 0.2011
test_accuracy= 0.94
convergence_warnings= 0
训练集为 300 行、测试集为 100 行;本次运行在第 1089 轮停止,损失从约 0.6901 降到 0.2011,没有收敛警告。测试准确率为 0.94,只描述这一固定随机划分与模拟数据,不是对其他数据的效果承诺。
验证时先检查预测形状与测试标签形状相同,再打开 mlp_loss.csv 看 iteration 和 loss 两列;最后核对损失数值有限,测试集没有参与 fit。损失下降说明优化有进展,不能单独证明模型没有过拟合。
这条曲线记录训练损失。真实任务若需要挑超参数,应另外留验证集或使用恰当交叉验证,最后再一次性查看独立测试结果;不要反复根据测试分数选择隐藏层和随机种子。
看到 ConvergenceWarning 时,按现象排查
把同一代码的 max_iter 改为 800,本环境实际出现了下面的警告,并得到 800 轮、末轮损失约 0.2344:
Stochastic Optimizer: Maximum iterations (800) reached and the optimization hasn't converged yet.
这表示在迭代上限前未满足当前停止条件。检查顺序是:先确认数据没有缺失值或无穷大,数值特征已按训练集缩放;再查看训练损失是否仍下降;仍有下降空间时可增加 max_iter,损失明显震荡时检查学习率和输入尺度。不要仅用过滤警告的方式宣称问题已经解决。
本示例把上限从 800 增到 2000 后消除了该警告,但测试准确率从 0.95 变成 0.94。收敛警告消失不保证泛化效果更好,也不应该为了这一次测试结果反向挑选 800 轮。
| 症状 | 先查什么 | 处理后怎样核对 |
|---|---|---|
| 导入失败 | 解释器路径、包版本 | 版本命令能在同一环境运行 |
| 损失含 NaN 或 inf | 输入是否有限、数值尺度、学习率 | np.isfinite 对输入和损失检查均通过 |
| 达到 max_iter | 损失是否仍下降、缩放是否正确 | 记录新轮数、损失、警告和验证结果 |
| 训练好而验证差 | 过拟合、数据划分和分布差异 | 用验证数据检查改动,保留最后测试集 |
下一步应该换真实数据,还是换框架?
先把 X、y 替换为有明确标签的小型数值表格,确认每行特征和标签一一对应,并延续训练集拟合缩放的规则。如果你的目标是自定义卷积网络、复杂张量操作或 GPU 训练,可学习 PyTorch 等框架;换框架后仍需处理输入、划分和评估,GPU 本身不会解决数据问题。
本文没有测量训练耗时或内存,也没有在你的设备上验证容量。真实运行速度和可处理规模取决于样本数、特征数、网络大小和 CPU;先从小样本观察资源占用,再扩大任务。
Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/30614.html