我想应用 scikit-learn
提供的缩放sklearn.preprocessing.scale
模块来居中化我将用于训练 svm 分类器的数据集。
然后,如何存储标准化参数,以便将它们也应用于要分类的数据?
我知道我可以使用standarScaler
但是我可以以某种方式将其序列化为文件,这样我就不必在每次要运行分类器时都将其适合我的数据?
我认为最好的方法是在fit
后腌制它,因为这是最通用的选项。也许稍后您将创建一个由要素提取器和缩放器组成的管道。通过腌制(可能是复合的)阶段,你正在使事情变得更加通用。关于模型持久性的 sklearn 文档讨论了如何做到这一点。
话虽如此,您可以在sklearn.preprocessing.StandardScaler
查询拟合参数:
scale_ : 形状, 形状 (n_features,) 每个特征的数据相对缩放。 版本 0.17 中的新功能:建议使用 scale_,而不是已弃用的std_。 mean_ : 形状为 [n_features] 的浮点数组 训练集中每个特征的平均值。
以下简短代码段对此进行了说明:
from sklearn import preprocessing
import numpy as np
s = preprocessing.StandardScaler()
s.fit(np.array([[1., 2, 3, 4]]).T)
>>> s.mean_, s.scale_
(array([ 2.5]), array([ 1.11803399]))
使用标准缩放器缩放
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(data)
scaled_data = scaler.transform(data)
保存mean_并var_供以后使用
means = scaler.mean_
vars = scaler.var_
(您可以打印和复制粘贴手段和变量或使用 np.save 保存到磁盘...
以后使用保存的参数
def scale_data(array,means=means,stds=vars **0.5):
return (array-means)/stds
scale_new_data = scale_data(new_data)
您可以使用 joblib 模块来存储缩放器的参数。
from joblib import dump
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(data)
dump(scaler, 'scaler_filename.joblib')
稍后您可以加载缩放器。
from joblib import load
scaler = load('scaler_filename.joblib')
transformed_data = scaler.transform(new_data)
Pickle 带来了一个安全漏洞,并允许攻击者在服务器上执行任意代码。条件是:
-
可以将 pickle 文件替换为服务器上的另一个 pickle 文件(如果没有对 pickle 进行审核,即签名验证或哈希比较)
-
相同,但在开发人员PC上(攻击者破坏了一些开发PC
如果您的服务器端应用程序以 root 身份执行(或在 docker 容器中的 root 下执行),那么这绝对值得您关注。
可能的解决方案:
-
模型训练应在安全的环境中进行
-
经过训练的模型应该由来自另一个安全环境的密钥签名,该密钥不会加载到 gpg 代理中(否则攻击者可以很容易地替换签名)
-
CI 应在隔离环境(隔离区)中测试模型
-
使用 python3.8 或更高版本,它添加了安全钩子以防止代码注入技术
-
或者只是避免泡菜:)
一些链接:
-
https://docs.python.org/3/library/pickle.html
-
Python:我可以安全地解冻不受信任的数据吗?
-
https://github.com/pytorch/pytorch/issues/52596
-
https://www.python.org/dev/peps/pep-0578/
避免酸洗的可能方法:
# scaler is fitted instance of MinMaxScaler
scaler_data_ = np.array([scaler.data_min_, scaler.data_max_])
np.save("my_scaler.npy", allow_pickle=False, scaler_data_)
#some not scaled X
Xreal = np.array([1.9261148646249848, 0.7327923702472628, 118, 1083])
scaler_data_ = np.load("my_scaler.npy")
Xmin, Xmax = scaler_data_[0], scaler_data_[1]
Xscaled = (Xreal - Xmin) / (Xmax-Xmin)
Xscaled
# -> array([0.63062502, 0.35320565, 0.15144766, 0.69116555])