web-dev-qa-db-ja.com

タイプ行をベクトルに変換してKMeansにフィードする方法

df2をkmeansにフィードしようとすると、次のエラーが発生します

clusters = KMeans.train(df2, 10, maxIterations=30,
                        runs=10, initializationMode="random")

私が得るエラー:

Cannot convert type <class 'pyspark.sql.types.Row'> into Vector

df2は、次のように作成されたデータフレームです。

df = sqlContext.read.json("data/ALS3.json")
df2 = df.select('latitude','longitude')

df2.show()


     latitude|       longitude|

   60.1643075|      24.9460844|
   60.4686748|      22.2774728|

この2つの列をVectorに変換して、KMeansにフィードするにはどうすればよいですか?

8
chessosapiens

ML

問題は、 ドキュメントの例 を見逃したことです。また、メソッドtrainDataFrameを機能として持つVectorを必要とすることは明らかです。

現在のデータの構造を変更するには、 VectorAssembler を使用できます。あなたの場合、それは次のようなものである可能性があります。

from pyspark.sql.functions import *

vectorAssembler = VectorAssembler(inputCols=["latitude", "longitude"],
                                  outputCol="features")

# For your special case that has string instead of doubles you should cast them first.
expr = [col(c).cast("Double").alias(c) 
        for c in vectorAssembler.getInputCols()]

df2 = df2.select(*expr)
df = vectorAssembler.transform(df2)

さらに、より良い結果を得るには、クラス MinMaxScaler を使用してfeaturesを正規化する必要もあります。

MLLib

MLLibを使用してこれを実現するには、最初にマップ関数を使用して、すべてのstring値をDoubleに変換し、それらを DenseVector

rdd = df2.map(lambda data: Vectors.dense([float(c) for c in data]))

この時点以降、rdd変数を使用して MLlibのKMeansモデル をトレーニングできます。

10

次のように、PySpark 2.3.1DataFrame に対して KMeans を実行しました。

  1. クラスタリング分析に含める列のリストを記述します。
feat_cols = ['latitude','longitude']`
  1. すべての列が数値である必要があります:
expr = [col(c).cast("Double").alias(c) for c in feat_cols]
df2 = df2.select(*expr)
  1. mllib.linalg.Vectorsを使用してfeaturesベクトルを作成します。
from pyspark.ml.feature import VectorAssembler
assembler = VectorAssembler(inputCols=feat_cols, outputCol="features")
df3 = assembler.transform(df2).select('features')
  1. 正規化は必ずしも必要ではないので、機能を正規化する必要がありますが、ほとんど問題はありません( これについて詳しくはこちら ):
from pyspark.ml.feature import StandardScaler
scaler = StandardScaler(
    inputCol="features",
    outputCol="scaledFeatures",
    withStd=True,
    withMean=False)
scalerModel = scaler.fit(df3)
df4 = scalerModel.transform(df3).drop('features')\
                     .withColumnRenamed('scaledFeatures', 'features')
  1. DataFrame オブジェクトdf4を密なベクトルに変換します [〜#〜] rdd [〜#〜]
from pyspark.mllib.linalg import Vectors
data5 = df4.rdd.map(lambda row: Vectors.dense([x for x in row['features']]))
  1. 取得したRDDオブジェクトをKMeansトレーニングの入力として使用します。
from pyspark.mllib.clustering import KMeans
model = KMeans.train(data5, k=3, maxIterations=10)
  1. 例:ベクトル空間内の点pを分類します。
prediction = model.predict(p)
3
Jed