Использование python lime как udf на spark - PullRequest
9 голосов
/ 26 марта 2019

Я хочу использовать lime's explainer в udf на pyspark. Ранее я обучал табличному объяснителю, и сохранил его как модель укропа, как предложено в ссылка

loaded_explainer = dill.load(open('location_to_explainer','rb'))

def lime_explainer(*cols):
    selected_cols = np.array([value for value in cols])
    exp = loaded_explainer.explain_instance(selected_cols, loaded_model.predict_proba, num_features = 10)
    mapping = exp.as_map()[1]

    return str(mapping)

Это, однако, занимает много времени, так как кажется, что большая часть вычислений происходит на драйвере. Затем я пытался использовать искровую трансляцию, чтобы транслировать объяснение исполнителям.

broadcasted_explainer= sc.broadcast(loaded_explainer)

def lime_explainer(*col):
    selected_cols = np.array([value for value in cols])
    exp = broadcasted_explainer.value.explain_instance(selected_cols, loaded_model.predict_proba, num_features = 10)
    mapping = exp.as_map()[1]

    return str(mapping)        

Однако при трансляции я сталкиваюсь с ошибкой засолки.

PicklingError: Невозможно засолить в 0x7f69fd5680d0>: поиск атрибута на lime.discretize завершился неудачей

Кто-нибудь может помочь с этим? Есть ли что-то вроде dill, которое мы можем использовать вместо CloudPickler, используемого в Spark?

Ответы [ 3 ]

2 голосов
/ 07 апреля 2019

Я dill автор.Я согласен с @Majaha и немного расширю ответ @ Majaha.В первой ссылке в ответе @ Majaha четко указано, что экземпляр Broadcast жестко связан с использованием pickle ... так что предложение dill в строку, затем un dill впоследствии является хорошим.

К сожалению, метод extend, вероятно, не будет работать для вас.В классе Broadcast источник использует CPickle, который dill не может расширяться.Если вы посмотрите на источник, он использует import CPickle as pickle; ... pickle.dumps для Python 2 и import pickle; ... pickle.dumps для Python 3. Если бы он использовал import pickle; ... pickle.dumps для Python 2 и import pickle; ... pickle._dumps для Python 3, то dill мог бы расширить средство выборапросто делая import dill.Например:

Python 3.6.6 (default, Jun 28 2018, 05:53:46) 
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from pickle import _dumps
>>> import dill
>>> _dumps(lambda x:x)
b'\x80\x03cdill._dill\n_create_function\nq\x00(cdill._dill\n_load_type\nq\x01X\x08\x00\x00\x00CodeTypeq\x02\x85q\x03Rq\x04(K\x01K\x00K\x01K\x01KCC\x04|\x00S\x00q\x05N\x85q\x06)X\x01\x00\x00\x00xq\x07\x85q\x08X\x07\x00\x00\x00<stdin>q\tX\x08\x00\x00\x00<lambda>q\nK\x01C\x00q\x0b))tq\x0cRq\rc__main__\n__dict__\nh\nNN}q\x0etq\x0fRq\x10.'

Таким образом, вы можете либо сделать то, что предлагает @Majaha (и перенаправить вызов на broadcast), либо вы можете пропатчить код, чтобы сделать замену, которую я описал выше (где это необходимо), но да ...), или вы можете создать свой собственный производный класс, который выполняет эту работу, используя dill:

>>> from pyspark.broadcast import Broadcast as _Broadcast
>>>
>>> class Broadcast(_Broadcast):
...   def dump(self, value, f):
...     try:
...       import dill
...       dill.dump(value, f, pickle_protocol)
...     ...[INSERT THE REST OF THE DUMP METHOD HERE]...

Если вышеописанное не удается ... вы все равно можете получить егоопределите, где происходит сбой сериализации (dill.detect.trace поможет вам в этом).

Если вы собираетесь pyspark использовать dill ... потенциально лучшее предложение - эторазрешить пользователям динамически заменять сериализатор.Это то, что mpi4py и несколько других пакетов делают.

0 голосов
/ 04 апреля 2019

Какая у вас схема данных location_to_explainer?Может быть, лучше преобразовать в фрейм данных spark.

Согласно dill desciption

укроп можно использовать для хранения объектов python в файл, но основное использованиедля отправки объектов Python через сеть в виде потока байтов.Укроп довольно гибок и позволяет сериализовать произвольные пользовательские классы и функции.Таким образом, укроп не предназначен для защиты от ошибочно или злонамеренно сконструированных данных.Пользователь должен решить, являются ли данные, которые он выбирает, из надежного источника.

И Когда не использовать, pickle

ЕслиВы хотите использовать данные на разных языках программирования, мариновать не рекомендуется.Его протокол специфичен для Python, поэтому совместимость между языками не гарантируется.То же самое относится к различным версиям самого Python.Отмена выбора файла, который был выбран в другой версии Python, может не всегда работать должным образом, поэтому вы должны убедиться, что вы используете ту же версию и выполнить обновление при необходимости.Вы также должны стараться не извлекать данные из ненадежного источника.Вредоносный код внутри файла может быть выполнен после удаления.

Согласно этому обсуждению , вы можете попробовать pysparkling

Я не думаю, что это проблема укропа, так как я не думаю, что ваш код использует укроп.Итак, насколько я знаю, pyspark использует маринад или маринад, а не укроп.Однако, если вы хотите использовать укроп с pyspark, есть pysparkling (https://pypi.python.org/pypi/pysparkling)..., и его использование может устранить проблему с сериализацией. Я предлагаю вам открыть тикет с pyspark или попробовать pysparkling, и в случае его сбояоткройте билет там - и отправьте мне сообщение или обратитесь к этой проблеме, чтобы я мог следить за темой. Я собираюсь закрыть это ... так что, если я ошибаюсь и вы используете укроп, пожалуйста, не стесняйтесь снова открыть этовыпуск.

Подробнее Чтение маринадов из pyspark локально

0 голосов
/ 04 апреля 2019

Глядя на этот источник , кажется, что у вас нет другого выбора, кроме как использовать предоставленный сборщик. Таким образом, я могу только предложить, чтобы вы вложили укроп в сборщик по умолчанию. Не идеально, но это может сработать. Попробуйте что-то вроде:

broadcasted_explainer = dill.loads(sc.broadcast(dill.dumps(loaded_explainer)).value)

Или вы можете попробовать вызвать метод Dill extension () , который должен добавить типы данных Dill в отправку пакета pickle по умолчанию. Не знаю, сработает ли это, но вы можете попробовать!

...