web-dev-qa-db-ja.com

K PySparkでのクラスタリングの意味

sparkデータフレーム 'mydataframe'に多くの列があります。2つの列のみでkmeansを実行しようとしています。これらの2つの列だけに基づいて7つのクラスターを抽出し、クラスターの割り当てを元のデータフレームに添付します。私はもう試した:

from numpy import array
from math import sqrt
from pyspark.mllib.clustering import KMeans, KMeansModel

# Prepare a data frame with just 2 columns:
data = mydataframe.select('lat', 'long')
data_rdd = data.rdd  # needs to be an RDD
data_rdd.cache()

# Build the model (cluster the data)
clusters = KMeans.train(data_rdd, 7, maxIterations=15, initializationMode="random")

しかし、しばらくするとエラーが発生します:

org.Apache.spark.SparkException:ステージの失敗によりジョブが中止されました:ステージ5191.0のタスク1が4回失敗し、最新の失敗:ステージ5191.0のタスク1.3が失われました(TID 260738、10.19.211.69、エグゼキューター1):org.Apache。 spark.api.python.PythonException:トレースバック(最新の呼び出しは最後)

クラスターをデタッチおよび再アタッチしようとしました。同じ結果。私は何を間違えていますか?

どうもありがとうございました!

9
user3245256

あなたの最近の別の質問 に基づいて、Sparkクラスタリング(あなたはsqrtarray、使用しないで、おそらく docs example )のようなものであるため、ここで尋ねている特定の質問ではなく、より一般的なレベルでアドバイスを提供させてください(うまくいけば)また、クラスタの割り当てをデータフレームに戻そうとすると、さらに3〜4つの質問を開く必要がなくなります)...

以来

  1. データフレームに既にデータがあります

  2. クラスターメンバーシップを初期データフレームに戻したい

rDDに戻して( 非推奨 )MLlibパッケージを使用する理由はありません。データフレームを直接操作する(現在推奨されている)MLパッケージを使用して、はるかに簡単に、エレガントに、効率的に作業を行うことができます。

ステップ0-自分に似たおもちゃデータを作成します:

_spark.version
# u'2.2.0'

df = spark.createDataFrame([[0, 33.3, -17.5],
                              [1, 40.4, -20.5],
                              [2, 28., -23.9],
                              [3, 29.5, -19.0],
                              [4, 32.8, -18.84]
                             ],
                              ["other","lat", "long"])

df.show()
# +-----+----+------+
# |other| lat|  long|
# +-----+----+------+
# |    0|33.3| -17.5|
# |    1|40.4| -20.5| 
# |    2|28.0| -23.9|
# |    3|29.5| -19.0|
# |    4|32.8|-18.84|
# +-----+----+------+
_

ステップ1-フィーチャーを組み立てます

ほとんどのMLパッケージとは対照的に、Spark MLでは、通常featuresという名前のデータフレームの単一列に入力フィーチャを収集する必要があります。そして、これを行うための特定のメソッド VectorAssembler を提供します。

_from pyspark.ml.feature import VectorAssembler

vecAssembler = VectorAssembler(inputCols=["lat", "long"], outputCol="features")
new_df = vecAssembler.transform(df)
new_df.show()
# +-----+----+------+-------------+ 
# |other| lat|  long|     features|
# +-----+----+------+-------------+
# |    0|33.3| -17.5| [33.3,-17.5]|
# |    1|40.4| -20.5| [40.4,-20.5]|
# |    2|28.0| -23.9| [28.0,-23.9]| 
# |    3|29.5| -19.0| [29.5,-19.0]|
# |    4|32.8|-18.84|[32.8,-18.84]|
# +-----+----+------+-------------+ 
_

おそらくすでに推測されているように、引数inputColsは、データフレーム内のどの特定の列を機能として使用するかをVectoeAssemblerに伝えるのに役立ちます。

ステップ2-KMeansモデルに適合

_from pyspark.ml.clustering import KMeans

kmeans = KMeans(k=2, seed=1)  # 2 clusters here
model = kmeans.fit(new_df.select('features'))
_

select('features')は、アルゴリズムにデータフレームのどの列をクラスタリングに使用するかを伝えるのに役立ちます-上記のステップ1の後、元のlatlongの機能は直接使用されないことに注意してください。

ステップ3-初期データフレームを変換してクラスターの割り当てを含める

_transformed = model.transform(new_df)
transformed.show()    
# +-----+----+------+-------------+----------+ 
# |other| lat|  long|     features|prediction|
# +-----+----+------+-------------+----------+
# |    0|33.3| -17.5| [33.3,-17.5]|         0| 
# |    1|40.4| -20.5| [40.4,-20.5]|         1|
# |    2|28.0| -23.9| [28.0,-23.9]|         0|
# |    3|29.5| -19.0| [29.5,-19.0]|         0|
# |    4|32.8|-18.84|[32.8,-18.84]|         0|
# +-----+----+------+-------------+----------+
_

transformedデータフレームの最後の列predictionはクラスターの割り当てを示しています-私のおもちゃの場合、クラスター#0に4つのレコード、クラスター#1に1つのレコードがあります。

transformedステートメントでselectデータフレーム、またはdrop _features列でさらに操作することができます(これは機能を果たし、不要になりました)。

願わくば、そもそも実際に達成したいと思っていたものにずっと近いことを願っています。クラスタ統計などを抽出するには、 私のもう1つの最近の回答 が役立つかもしれません...

42
desertnaut

私の他の一般的な答えにもかかわらず、そして何らかの理由でMLlibとRDDに固執しなければならない場合、同じおもちゃdfを使用するとエラーが発生します。

データフレームのselect列をRDDに変換する場合、結果はRowsのRDDになります:

df.select('lat', 'long').rdd.collect()
# [Row(lat=33.3, long=-17.5), Row(lat=40.4, long=-20.5), Row(lat=28.0, long=-23.9), Row(lat=29.5, long=-19.0), Row(lat=32.8, long=-18.84)]

これはMLlib KMeansへの入力としては適切ではありません。これを機能させるには、map操作が必要です。

df.select('lat', 'long').rdd.map(lambda x: (x[0], x[1])).collect()
# [(33.3, -17.5), (40.4, -20.5), (28.0, -23.9), (29.5, -19.0), (32.8, -18.84)]

したがって、コードは次のようになります。

from pyspark.mllib.clustering import KMeans, KMeansModel

rdd = df.select('lat', 'long').rdd.map(lambda x: (x[0], x[1]))
clusters = KMeans.train(rdd, 2, maxIterations=10, initializationMode="random") # works OK
clusters.centers
# [array([ 40.4, -20.5]), array([ 30.9 , -19.81])]
4
desertnaut