簡體   English   中英

使用python lime作為火花上的udf

[英]Using python lime as a udf on spark

我想在pyspark的udf中使用lime的 explainer器。 我之前已經訓練了表格解釋器,並且存儲了如鏈接中所建議的蒔蘿模型

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)

然而這需要花費很多時間,因為看起來很多計算都發生在驅動程序上。 我當時一直在嘗試使用spark廣播將解釋器廣播給執行者。

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?

我是dill作者。 我同意@Majaha,並會稍微延長@ Majaha的回答。 在@ Majaha的答案的第一個鏈接中,它清楚地指出一個Broadcast實例是硬連線使用pickle ...所以建議dill到一個字符串,然后unill dill后是一個很好的。

不幸的是, extend方法可能不適合你。 Broadcast類中,源使用CPickledill無法擴展。 如果查看源代碼,它會使用import CPickle as pickle; ... pickle.dumps import CPickle as pickle; ... pickle.dumps用於python 2的import CPickle as pickle; ... pickle.dumps ,以及import pickle; ... pickle.dumps import pickle; ... pickle.dumps用於python的import pickle; ... pickle.dumps 3.它是否使用了import pickle; ... pickle.dumps import pickle; ... pickle.dumps用於python 2的import pickle; ... pickle.dumps ,以及import pickle; ... pickle._dumps import pickle; ... pickle._dumps用於python 3的import pickle; ... pickle._dumps ,然后dill可以通過執行import dill dill來擴展import pickle; ... pickle._dumps 例如:

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和其他一些軟件包所做的事情。

看看這個來源 ,似乎你別無選擇,只能使用提供的pickler。 因此,我只能建議您將蒔蘿嵌套在默認的pickler中。 不理想,但它可以工作。 嘗試類似的東西:

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

或者您可以嘗試調用Dill extend()方法 ,該方法應該將Dill數據類型添加到默認的pickle包調度中。 不知道這是否有效,但你可以嘗試一下!

你的location_to_explainer數據模式是什么? 也許最好轉換為spark的數據幀。

根據蒔蘿的說法

dill可用於將python對象存儲到文件中,但主要用途是將python對象作為字節流通過網絡發送。 dill非常靈活,允許序列化任意用戶定義的類和函數。 因此,dill不是為了防止錯誤或惡意構造的數據。 由用戶決定他們取消的數據是否來自可信賴的來源。

什么時候不使用泡菜

如果要跨不同編程語言使用數據,建議不要使用pickle。 它的協議特定於Python,因此不保證跨語言兼容性。 對於不同版本的Python本身也是如此。 取消在不同版本的Python中腌制的文件可能並不總是正常工作,因此您必須確保使用相同的版本並在必要時執行更新。 您還應該嘗試不從不受信任的來源中取消數據。 解壓縮時可能會執行文件中的惡意代碼。

根據這個討論 ,你可以試試pysparkling

我不認為這是一個蒔蘿問題,因為我不認為你的代碼是使用蒔蘿。 所以,據我所知,pyspark使用泡菜或雲雀而不是蒔蘿。 但是,如果您確實希望將dill與pyspark一起使用,則可以使用pysparkling( https://pypi.python.org/pypi/pysparkling )...並使用它可能會清除序列化問題。 我建議你打開一張帶有pyspark的門票或嘗試pysparkling,如果失敗,請在那里打開一張票 - 然后給我CC或參考這個問題,這樣我就可以按照這個問題進行操作了。 我要關閉這個...所以,如果我不正確並且您正在使用蒔蘿,請隨時重新打開此問題。

閱讀更多在當地閱讀pyspark泡菜

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM