如何存储已拟合PCA模型以转换未知测试集且无需保留训练数据集
解决方案
完全可以实现训练端完成拟合、部署端仅存储必要参数完成变换,不需要将整个训练集存入Arduino,整体所需参数总大小不到1KB,完全符合256KB的存储限制。
核心原理
PCA变换和后续的标准化都属于线性运算,拟合完成后仅需要保存运算用到的固定参数,不需要原始训练数据参与预测阶段的计算。
你现有测试代码存在逻辑错误:测试阶段重新实例化PCA、重新拟合StandardScaler是完全错误的做法,应该直接复用训练阶段拟合完成的两个对象做变换,导出这两个对象的核心参数即可直接移植到Arduino。
步骤1:训练端导出必要参数
在PC上完成拟合后,仅需要提取以下4类参数,直接导出为C语言常量数组就能放到Arduino代码中:
- 从拟合好的
pca对象提取:- 原始特征均值向量
pca.mean_:长度等于原始特征维度12000,用于输入数据中心化 - PCA投影矩阵
pca.components_:形状为(PC数量, 原始特征维度),你这里是(15,12000),用于线性投影得到PC值
- 原始特征均值向量
- 从拟合好的
StandardScaler对象提取:- PC分量均值
scaler.mean_:长度等于PC数量15,用于PC值标准化 - PC分量标准差
scaler.scale_:长度等于PC数量15,用于PC值标准化
- PC分量均值
修正后的训练+参数导出参考代码:
from sklearn.preprocessing import StandardScaler from sklearn.decomposition import PCA import pandas as pd # 训练阶段 transposed_normDF.columns = transposed_normDF.columns.map(str) features = [str(i) for i in range(0,11999)] x = transposed_normDF.loc[:, features].values y = df.loc[:,['label']].values # 拟合PCA并保存对象 pca = PCA(n_components=0.99) principalComponents_train = pca.fit_transform(x) # 拟合标准化器并保存对象,不要在测试阶段重新fit scaler = StandardScaler() x1_train = scaler.fit_transform(principalComponents_train) # 导出参数为C数组格式,直接复制到Arduino代码中即可 print("/* 以下为C语言格式参数,复制到Arduino代码开头 */") print(f"const float pca_mean[12000] = {{{','.join(map(str, pca.mean_))}}};") for i, comp in enumerate(pca.components_): print(f"const float pca_comp_{i}[12000] = {{{','.join(map(str, comp))}}};") print(f"const float scaler_mean[15] = {{{','.join(map(str, scaler.mean_))}}};") print(f"const float scaler_scale[15] = {{{','.join(map(str, scaler.scale_))}}};") # 正确的测试逻辑,直接复用训练好的pca和scaler def transform_new_data(in_data): pca_out = pca.transform(in_data) scaled_out = scaler.transform(pca_out) newdf = pd.DataFrame(data = scaled_out, columns = [f'pc_stdscaled_{i}' for i in range(len(scaled_out[0]))]) return newdf
步骤2:Arduino端实现变换逻辑
不需要依赖任何第三方库,手写简单线性运算即可完成变换,逻辑如下:
- 输入12000维的新样本原始数据
- 中心化:每个原始特征减去
pca_mean中对应的均值 - PCA投影:对每个PC分量,计算中心化后的数据和对应投影矩阵行的点积,得到15个原始PC值
- 标准化:每个原始PC值减去
scaler_mean对应值,再除以scaler_scale对应值,得到最终用于模型推理的标准化PC特征
存储优化方案
如果投影矩阵占用空间超出256KB限制,可做以下优化:
- 将浮点参数替换为Q15等定点格式,存储占用直接减半
- 如果原始数据已经提前做过全局中心化,可不需要存储
pca_mean,节省12000个float的存储空间 - 可适当降低保留的方差阈值,减少PC数量,比如降到12个PC可直接减少20%的投影矩阵存储占用
内容的提问来源于stack exchange,提问作者Quine
相关产品推荐
相关产品推荐

