如何存储缩放参数以供以后使用

Posted

技术标签:

【中文标题】如何存储缩放参数以供以后使用【英文标题】:How to store scaling parameters for later use 【发布时间】:2016-06-26 23:13:21 【问题描述】:

我想应用scikit-learn 提供的缩放sklearn.preprocessing.scale 模块来使我将用于训练支持向量机分类器的数据集居中。

然后我如何存储标准化参数,以便我也可以将它们应用于我想要分类的数据?

我知道我可以使用standarScaler,但我可以以某种方式将其序列化到一个文件中,这样每次我想运行分类器时就不必将它与我的数据相匹配吗?

【问题讨论】:

【参考方案1】:

我认为最好的方法是在fit 之后对其进行腌制,因为这是最通用的选项。也许您稍后会创建一个由特征提取器和缩放器组成的管道。通过腌制(可能是复合的)阶段,您可以使事情变得更加通用。 sklearn documentation on model persistence 讨论了如何做到这一点。

话虽如此,您可以查询sklearn.preprocessing.StandardScaler获取拟合参数:

scale_:ndarray,形状(n_features,) 数据的每个特征相对缩放。 0.17 版中的新功能:建议使用 scale_ 而不是弃用的 std_。 mean_ : 形状为 [n_features] 的浮点数组 训练集中每个特征的平均值。

以下简短的 sn-p 说明了这一点:

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]))

【讨论】:

应该有一种方法可以使用之前拟合保存的参数来构建标准缩放器。【参考方案2】:

使用标准缩放器进行缩放

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)

【讨论】:

【参考方案3】:

您可以使用 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 是否缓解了 joblib 最初试图解决的一些问题?不知道,但这些信息会很有帮助。【参考方案4】:

Pickle 带来了一个安全漏洞,允许攻击者在服务器上执行任意代码。条件是:

可以用服务器上的另一个pickle文件替换pickle文件(如果没有对pickle进行审计,即签名验证或哈希比较)

相同,但在开发人员 PC 上(攻击者入侵了一些开发人员 PC

如果您的服务器端应用程序以 root 身份执行(或在 docker 容器中以 root 身份执行),那么这绝对值得您关注。

可能的解决方案:

模型训练应该在安全的环境中进行

经过训练的模型应该由来自另一个安全环境的密钥签名,该密钥不会加载到 gpg-agent(否则攻击者可以很容易地替换签名)

CI 应在隔离环境(隔离)中测试模型

使用python3.8或更高版本,添加了安全钩子以防止代码注入技术

或者只是避免泡菜:)

一些链接:

https://docs.python.org/3/library/pickle.html

Python: can I safely unpickle untrusted data?

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])

【讨论】:

由于安全问题,泡菜是个坏主意吗?还是有其他原因? @AdrianTompkins 是的,因为可以用任何其他对象替换泡菜对象并在主机上执行它。加上酸洗在酸洗协议的兼容性方面产生了不必要的限制 @AdrianTompkins 感谢您提出这个问题。我实际上在答案中有一个错误。现在它是固定的。添加了 allow_pickle=False :) 并在 numpy 源码中提供了参考 “酸洗在生产中是一个坏主意”的说法具有误导性,特别是因为您通过链接引用的原因。您不应该笼统地声明,尤其是如果您是该行业的新手 - 这会误导整个社​​区。​​span> @wellplayed 感谢您的留言。我试图在描述我的立场时更加透明。我更新了答案。如果您不同意,请提供您的想法、论据

以上是关于如何存储缩放参数以供以后使用的主要内容,如果未能解决你的问题,请参考以下文章

初始化Open IDC auth dance时存储GET请求参数以供以后使用

如何存储闭包完成处理程序以供以后调用?

如何检索和存储这些指南以供以后使用?

如何 $.post 一个 js 变量并将其存储到 php 以供以后使用,类似于 LocalStorage?

如何保存对象以供以后使用?通过 JSON 或其他方式发送并存储在数据库中然后恢复

如何腌制或存储 Jupyter (IPython) 笔记本会话以供以后使用