【问题标题】:Hyperparameter Optimization in sklearn and n_jobs > 1: Picklingsklearn 和 n_jobs > 1 中的超参数优化:酸洗
【发布时间】:2017-08-08 04:21:19
【问题描述】:

我在“泡菜”中。这是我的代码结构:

  • 类似于抽象类的基类
  • 可以实例化的子类
    • 一种设置参数并调用RandomizedSearchCVGridSearchCVn_jobs=-1 的方法。
      • 一个局部函数create_model,用于创建神经网络模型(参见this 教程),由KerasClassifierKerasRegressor 调用

我收到一条错误消息,提示无法腌制本地对象。如果我更改n_jobs=1,则没有问题。所以我怀疑问题出在本地函数和并行处理上。有解决办法吗?谷歌搜索了一下,似乎序列化程序dill 可以在这里工作(我什至找到了一个名为multiprocessing_on_dill 的包)。但我目前依赖sklearn 的包。

【问题讨论】:

  • 你可以monkeypatch joblib,让它在dill上运行。虽然不是一个理想的解决方案。
  • 是的,我对不需要像那样修补其他人的代码的解决方案更感兴趣...:/
  • 你使用哪个backend
  • @MarcinMożejko:对于Keras?我想同时尝试 TensorFlow 和 Theano。它会影响那个错误吗?
  • 对于Theano,不可能并行运行模型训练/评估。

标签: python scikit-learn multiprocessing pickle keras


【解决方案1】:

我找到了解决问题的“解决方案”。我真的很困惑为什么示例 here 可以与 n_jobs=-1 一起使用,但我的代码却不行。似乎问题在于驻留在子类方法中的本地函数create_model。如果我让本地函数成为子类的方法,我可以设置n_jobs > 1

回顾一下,这是我的代码结构:

  • 类似于抽象类的基类
  • 可以实例化的子类
    • 一种设置参数并调用RandomizedSearchCVGridSearchCVn_jobs=-1 的方法。
    • 一个方法create_model,用于创建由KerasClassifierKerasRegressor 调用的神经网络模型

代码的总体思路:

from abc import ABCMeta
import numpy as np
from sklearn.model_selection import GridSearchCV, RandomizedSearchCV

class MLAlgorithms(metaclass=ABCMeta):

    def __init__(self, X_train, y_train, X_test, y_test=None):
        """
        Constructor with train and test data.
        :param X_train: Train descriptor data
        :param y_train: Train observed data
        :param X_test: Test descriptor data
        :param y_test: Test observed data
        """
        ...

    @abstractmethod
    def setmlalg(self, mlalg):
        """
        Sets a machine learning algorithm.
        :param mlalg: Dictionary of the machine learning algorithm.
        """
        pass

    @abstractmethod
    def fitmlalg(self, mlalg, rid=None):
        """
        Fits a machine learning algorithm.
        :param mlalg: Machine learning algorithm
        """
        pass


class MLClassification(MLAlgorithms):
    """
    Main class for classification machine learning algorithms.
    """

    def setmlalg(self, mlalg):
        """
        Sets a classification machine learning algorithm.
        :param mlalg: Dictionary of the classification machine learning algorithm.
        """
        ...

    def fitmlalg(self, mlalg):
        """
        Fits a classification machine learning algorithm.
        :param mlalg: Classification machine learning algorithm
        """
        ...

    # Function to create model, required for KerasClassifier
    def create_model(self, n_layers=1, units=10, input_dim=10, output_dim=1,
                     optimizer="rmsprop", loss="binary_crossentropy",
                     kernel_initializer="glorot_uniform", activation="sigmoid",
                     kernel_regularizer="l2", kernel_regularizer_weight=0.01,
                     lr=0.01, momentum=0.0, decay=0.0, nesterov=False, rho=0.9, epsilon=1E-8,
                     beta_1=0.9, beta_2=0.999, schedule_decay=0.004):
        from keras.models import Sequential
        from keras.layers import Dense
        from keras import regularizers, optimizers

        # Create model
        if kernel_regularizer.lower() == "l1":
            kernel_regularizer = regularizers.l1(l=kernel_regularizer_weight)
        elif kernel_regularizer.lower() == "l2":
            kernel_regularizer = regularizers.l2(l=kernel_regularizer_weight)
        elif kernel_regularizer.lower() == "l1_l2":
            kernel_regularizer = regularizers.l1_l2(l1=kernel_regularizer_weight, l2=kernel_regularizer_weight)
        else:
            print("Warning: Kernel regularizer {0} not supported. Using default 'l2' regularizer.".format(
                kernel_regularizer))
            kernel_regularizer = regularizers.l2(l=kernel_regularizer_weight)

        if optimizer.lower() == "sgd":
            optimizer = optimizers.sgd(lr=lr, momentum=momentum, decay=decay, nesterov=nesterov)
        elif optimizer.lower() == "rmsprop":
            optimizer = optimizers.rmsprop(lr=lr, rho=rho, epsilon=epsilon, decay=decay)
        elif optimizer.lower() == "adagrad":
            optimizer = optimizers.adagrad(lr=lr, epsilon=epsilon, decay=decay)
        elif optimizer.lower() == "adadelta":
            optimizer = optimizers.adadelta(lr=lr, rho=rho, epsilon=epsilon, decay=decay)
        elif optimizer.lower() == "adam":
            optimizer = optimizers.adam(lr=lr, beta_1=beta_1, beta_2=beta_2, epsilon=epsilon, decay=decay)
        elif optimizer.lower() == "adamax":
            optimizer = optimizers.adamax(lr=lr, beta_1=beta_1, beta_2=beta_2, epsilon=epsilon, decay=decay)
        elif optimizer.lower() == "nadam":
            optimizer = optimizers.nadam(lr=lr, beta_1=beta_1, beta_2=beta_2, epsilon=epsilon,
                                         schedule_decay=schedule_decay)
        else:
            print("Warning: Optimizer {0} not supported. Using default 'sgd' optimizer.".format(optimizer))
            optimizer = "sgd"

        model = Sequential()
        model.add(
            Dense(units=units, input_dim=input_dim,
                  kernel_initializer=kernel_initializer, activation=activation,
                  kernel_regularizer=kernel_regularizer))
        for layer_count in range(n_layers - 1):
            model.add(
                Dense(units=units, kernel_initializer=kernel_initializer, activation=activation,
                      kernel_regularizer=kernel_regularizer))
        model.add(Dense(units=output_dim,
                        kernel_initializer=kernel_initializer, activation=activation,
                        kernel_regularizer=kernel_regularizer))

        # Compile model
        model.compile(loss=loss, optimizer=optimizer, metrics=['accuracy'])
        return model


class MLRegression(MLAlgorithms):
    """
    Main class for regression machine learning algorithms.
    """
    ...

【讨论】:

  • 我对这个问题非常感兴趣,但我似乎无法理解您的代码是如何组织的。你有抽象类的例子吗?
  • 我用部分代码更新了我的答案。希望对您有所帮助!
  • 谢谢伙计!真的很感激!
【解决方案2】:

我可以在 jupyter notebook/ipython 的 Windows 上使用并行化 (n_jobs>1) 的 kerasClassifier 模型上运行 sklearn 的网格搜索时确认相同的问题(在 Unix 上没有问题)。

我通过将导致 pickle 问题的 create_model 函数放入模块并导入模块而不是在环境中定义函数来解决了这个问题。

要为 Python 创建一个简单的模块,

  • 在运行主代码的同一文件夹中创建一个文本文件并将其保存为 my_module.py
  • 将create_model函数的定义放入文件中
  • 不要在代码中定义 create_model,而是使用 import my_module 导入模块并使用 my_module.create_model() 从模块中调用您的函数

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-23
    • 2019-02-01
    • 2021-11-15
    • 1970-01-01
    • 2021-01-13
    • 1970-01-01
    • 2016-01-06
    • 1970-01-01
    相关资源
    最近更新 更多