2016-09-28 95 views
-1

我一直在嘗試火花mllib來訓練word2vec模型,但我似乎並沒有越來越分佈式機器學習對大數據集的性能優勢。我的理解是,如果我有w個工人,那麼,如果我創建了n個分區的RDD,其中n> w,我嘗試通過調用Word2Vec的擬合函數並將RDD作爲參數來創建Word2Vec模型,則spark將分佈數據統一在這些工作人員上訓練單獨的word2vec模型,並在最後使用某種類型的reducer函數從這些w模型創建單個輸出模型。這會減少計算時間而不是1塊,同時處理大塊數據。這種權衡取決於最終使用的減速器功能,可能會發生某些精度損失。 Spark中的Word2Vec實際上以這種方式工作嗎?如果確實如此,我可能需要使用可配置的參數。分佈式Word2Vec模型訓練使用Apache 2.0.0星火和mllib

編輯

添加背後問這個問題的原因。我在10臺工作機器上運行了java spark word2vec代碼,並在通過文檔後爲執行程序內存,驅動程序內存和num-executors設置了合適的值,用於2.5gb輸入文本文件,該文本被映射到rdd分區,然後用作訓練mllib word2vec模型的數據。培訓部分需要多個小時。工作節點的數量似乎對訓練時間沒有太大影響。相同的代碼成功運行在較小的數據文件

代碼

SparkConf conf = new SparkConf().setAppName("SampleWord2Vec"); 
conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer"); 
conf.registerKryoClasses(new Class[]{String.class, List.class}); 
JavaSparkContext jsc = new JavaSparkContext(conf); 
JavaRDD<List<String>> jrdd = jsc.textFile(inputFile, 3).map(new Function<String, List<String>>(){    
     @Override 
     public List<String> call(String s) throws Exception { 
      return Arrays.asList(s.split(",")); 
     }   
}); 
jrdd.persist(StorageLevel.MEMORY_AND_DISK()); 
Word2Vec word2Vec = new Word2Vec() 
     .setWindowSize(20) 
     .setMinCount(20); 

Word2VecModel model = word2Vec.fit(jrdd); 
jrdd.unpersist(false); 
model.save(jsc.sc(), outputfile); 
jsc.stop(); 
jsc.close(); 
+0

如果你分享了你的代碼和關於你如何運行spark-submit的更多細節,這將會有所幫助。當你跑步時,你是否看到你的所有工作人員始終處於活動狀態? Spark歷史用戶界面可讓您深入瞭解。有可能您的代碼無法正常運行,並且您沒有完全分配代碼。 Spark ML包含基於數據幀API的JavaWord2Vec。這應該是非常快的。 – tadamhicks

+0

火花ml JavaWord2Vec(dataframes api)應該比mllib版本(javardd api)更好。我放棄了火花ml版本,因爲當我嘗試遍歷模型向量時,它給出了一些編譯錯誤。 – Kabutops

+0

數據幀API背後的催化劑優化器性能更高,應該更容易。你不會迭代,這是一個糟糕的方式來使用Spark。 ML允許您構建管道,該管道基本上針對所選列的所有值執行功能映射。再次,代碼會有所幫助。 – tadamhicks

回答

1

從評論,答案和downvotes判斷我想我不能正確地框架我的問題。但是我想知道的答案是肯定的,可以在火花上並行地訓練word2vec模型。此功能的上拉請求創建長的時間回:

https://github.com/apache/spark/pull/1719

在java中,存在於火花mllib的Word2Vec對象的setter方法(setNumPartitions)。這使您可以在多個並行執行器上訓練word2vec模型。 按照上面提到的上拉請求評論:

爲了讓我們的實現更具可擴展性,我們分別培養每個分區和每次迭代後合併每個分區的模型,使模型更加準確,多次迭代。可能需要

希望這可以幫助別人。

+0

你有沒有得到一些基準?我也有興趣比較gensim,原始word2vec,火花..(請注意,火花使用的skipgram模型與另外兩個cbow相比) –

+0

我遇到了同樣的問題 - 即使使用DataFrame,默認情況下,Spark w2v默認使用一個執行器進行培訓。正如你所說的,你必須使用setNumPartition來並行訓練。謝謝你指出。就我個人而言,我認爲這是一個默認值的可怕設置。 – Pete

0

我看不出有什麼內在的錯誤代碼(的MB的10s的順序)。但是,我強烈建議您考慮數據框架API。作爲一個例子,這裏有一個小的圖表,頻繁拋來拋去:

enter image description here

另外,我不知道你怎麼可能被「迭代」在數據幀的元素(這不是真的他們如何工作)。下面是來自Spark online docs一個例子:

enter image description here

你的總體思路...但你必須並行數據作爲數據幀,第一。將javardd翻譯成DataFrame是相當簡單的。

DataFrame fileDF = sqlContext.createDataFrame(jrdd, Model.class); 

Spark運行有向非循環圖(DAG)來代替MR,但概念是相同的。對您的數據運行'fit()確實會在工作人員的數據上運行,然後再減少到單個模型。但是這個模型本身會分佈在內存中,直到你決定寫下來。

但是,作爲一種嘗試,多長時間將它帶你到運行同樣的文件,通過說NLTK或Word2Vec的原生C++二進制?

最後一個思想...有你堅持到內存和磁盤的一個原因? Spark有一個原生.cache(),默認情況下它保留在內存中。 Spark的強大功能是對內存中保存的數據進行機器學習......內存中的大數據。如果你堅持使用磁盤,即使使用kryo,你也會在磁盤I/O上創建一個瓶頸。恕我直言,首先要嘗試的是擺脫這一點,並堅持只是爲了記憶。如果性能提高,那麼效果會很好,但是通過DataFrames,您可以依靠Catalyst的強大功能來發現性能的飛躍和突破。

我們沒有討論過的一件事是你的集羣。考慮每個節點的內存量有多少......每個節點有多少個核心......您的集羣是通過其他需要資源的應用進行虛擬化的(像大多數vHosts一樣過度配置)......雲中的羣集?共享還是專用?

你看過Spark的UI來分析代碼的運行時操作嗎?當模型適合時,您在工作人員上運行top時看到了什麼?你能看到完整的CPU利用率嗎?您是否嘗試過指定--executor-cores以確保充分利用CPU?

我已經看到它發生過很多次,所有的工作都在一個工作節點上的一個核心上完成。獲得這些信息會有所幫助。

排除故障性能時,有很多地方需要注意,包括Spark配置文件本身!

+0

由於程序無法將jrdd緩存在內存中,因此我堅持使用內存和磁盤。當我遇到這個問題時,我改變了默認設置(僅限於內存)。同樣作爲一個基準測試,同一個文件在python中的gensim上運行半小時,其中一臺機器比上面使用的10臺機器(4倍內核數量,相同RAM)功能更強大。我想我們正在談論更多關於配置級別的設置。我想知道當有人稱它爲fit時,Spark如何訓練word2vec模型,即它是否分割數據,爲這些分割創建單獨的模型並將它們分解爲單個模型? – Kabutops