减少状态模型 glm 的多重处理
Reduce multiprocessing for statsmodels glm
我目前正在为我们需要逻辑回归的业务流程之一进行概念验证。我一直在使用 statsmodels glm 对我们的数据集进行分类(按照下面的代码)。我们的数据集包含约 1000 万行和大约 80 个特征(其中近 70 多个是虚拟变量,例如基于定义的分类变量的“1”或“0”)。使用较小的数据集,glm 工作正常,但是如果我 运行 它针对完整数据集,python 会抛出错误 "cannot allocate memory".
glmmodel = smf.glm(formula, data, family=sm.families.Binomial())
glmresult = glmmodel.fit()
resultstring = glmresult.summary().as_csv()
这让我想到这可能是由于 statsmodels 被设计为利用所有可用的 cpu 内核,并且下面的每个子进程都会将数据集的副本创建到 RAM 中(如果我有错误请纠正我我弄错了)。现在的问题是 glm 是否有办法只使用最少数量的内核?我不喜欢性能,只是希望能够 运行 glm 针对完整数据集。
作为参考,下面是机器配置,如果需要还可以提供更多信息。
CPU: 10 cores
RAM: 40 GB (usable/free ~25GB as there are other processes running on the
same machine)
swap: 16 GB
dataset size: 1.4 GB (based on Panda's DataFrame.info(memory_usage='deep')
GLM 仅通过线性代数库使用多处理
以下从https://github.com/statsmodels/statsmodels/issues/2914复制我的FAQ问题描述
它包含一些指向出现此问题的其他问题的链接。
(引用:)
Statsmodels 在我们控制的几个地方使用 joblib 进行并行处理。目前主要用于bootstrap,并没有直接在模型中使用。
但是,numpy/scipy 中的一些底层 Blas/Lapack 库也使用多核。这对于具有大型数组的线性代数可能是有效的,但它也会减慢操作速度,尤其是当我们想要在更高级别上使用并行处理时。
我们如何限制线性代数库使用的内核数量?
这取决于使用哪个线性代数库。查看邮件列表线程
https://groups.google.com/d/msg/pystatsmodels/Lz9-In0pgPk/BtcYsj_ABQAJ
openblas:尝试设置环境变量OMP_NUM_THREADS=1
在 OSX 上加速,设置 VECLIB_MAXIMUM_THREADS
水蟒中的 mkl:
import mkl
mkl.set_num_threads(1)
这是因为 Statsmodels 在估计 GLM 时使用 IRLS,而 IRLS 过程利用其 WLS 回归例程,该例程再次使用 QR 分解。 QR 分解是直接在 X 上完成的,你的 X 有 1000 万行,80 列,结果给内存带来了很大压力 CPU.
这是来自 statsmodels 的源代码:
if method == 'pinv':
pinv_wexog = np.linalg.pinv(self.wexog)
params = pinv_wexog.dot(self.wendog)
elif method == 'qr':
Q, R = np.linalg.qr(self.wexog)
params = np.linalg.solve(R, np.dot(Q.T, self.wendog))
else:
params, _, _, _ = np.linalg.lstsq(self.wexog, self.wendog,
我目前正在为我们需要逻辑回归的业务流程之一进行概念验证。我一直在使用 statsmodels glm 对我们的数据集进行分类(按照下面的代码)。我们的数据集包含约 1000 万行和大约 80 个特征(其中近 70 多个是虚拟变量,例如基于定义的分类变量的“1”或“0”)。使用较小的数据集,glm 工作正常,但是如果我 运行 它针对完整数据集,python 会抛出错误 "cannot allocate memory".
glmmodel = smf.glm(formula, data, family=sm.families.Binomial())
glmresult = glmmodel.fit()
resultstring = glmresult.summary().as_csv()
这让我想到这可能是由于 statsmodels 被设计为利用所有可用的 cpu 内核,并且下面的每个子进程都会将数据集的副本创建到 RAM 中(如果我有错误请纠正我我弄错了)。现在的问题是 glm 是否有办法只使用最少数量的内核?我不喜欢性能,只是希望能够 运行 glm 针对完整数据集。
作为参考,下面是机器配置,如果需要还可以提供更多信息。
CPU: 10 cores
RAM: 40 GB (usable/free ~25GB as there are other processes running on the
same machine)
swap: 16 GB
dataset size: 1.4 GB (based on Panda's DataFrame.info(memory_usage='deep')
GLM 仅通过线性代数库使用多处理
以下从https://github.com/statsmodels/statsmodels/issues/2914复制我的FAQ问题描述 它包含一些指向出现此问题的其他问题的链接。
(引用:)
Statsmodels 在我们控制的几个地方使用 joblib 进行并行处理。目前主要用于bootstrap,并没有直接在模型中使用。
但是,numpy/scipy 中的一些底层 Blas/Lapack 库也使用多核。这对于具有大型数组的线性代数可能是有效的,但它也会减慢操作速度,尤其是当我们想要在更高级别上使用并行处理时。
我们如何限制线性代数库使用的内核数量?
这取决于使用哪个线性代数库。查看邮件列表线程 https://groups.google.com/d/msg/pystatsmodels/Lz9-In0pgPk/BtcYsj_ABQAJ
openblas:尝试设置环境变量OMP_NUM_THREADS=1
在 OSX 上加速,设置 VECLIB_MAXIMUM_THREADS
水蟒中的 mkl:
import mkl
mkl.set_num_threads(1)
这是因为 Statsmodels 在估计 GLM 时使用 IRLS,而 IRLS 过程利用其 WLS 回归例程,该例程再次使用 QR 分解。 QR 分解是直接在 X 上完成的,你的 X 有 1000 万行,80 列,结果给内存带来了很大压力 CPU.
这是来自 statsmodels 的源代码:
if method == 'pinv':
pinv_wexog = np.linalg.pinv(self.wexog)
params = pinv_wexog.dot(self.wendog)
elif method == 'qr':
Q, R = np.linalg.qr(self.wexog)
params = np.linalg.solve(R, np.dot(Q.T, self.wendog))
else:
params, _, _, _ = np.linalg.lstsq(self.wexog, self.wendog,