Python Spark ML K-Meansの例

Python Spark ML K-Meansの例

  • 人工知能(AI)
6分で読めます 更新日 Nov 28, 2019

ポイント: データはApache SparkとK-Meansアルゴリズムを使用して異なるグループにクラスタリングでき、チュートリアルでデモされています。コード例が含まれており、シルエットスコアや二乗誤差の合計などの指標を通じてクラスタリングの効果を評価します。

  • クラスタは重心とハイパープレーンを使用してデータポイントに基づいて形成されます。
  • 評価指標にはシルエットスコアと二乗誤差の合計が含まれます。

この記事では、Apache SparkとSpark ML K-Meansアルゴリズムを使用して、データを「クラスタ」と呼ばれる異なるグループに分ける方法を示します。このアプローチは、共通の特性に基づいて分けたいあらゆる種類のデータに対応します。このデータは、心臓病のある患者とない患者を示しています。このデータをロジスティック回帰を使用して既に見ています。分類は、どの患者が心臓病を持っているかを教えてくれるわけではありません(それは前回の投稿でロジスティック回帰が行ったことです)が、健康の指標が入力データであるため、一方の患者が病気で他方がそうでないことを論理的に推測できます。

Spark ML K-Meansアルゴリズムの理解

分類は、n次元空間の中でこのデータを最も近くに分離する座標を見つけることで機能します。これを3D空間の平面として考えてください: 一方の側には一つのクラスタに属するデータポイントがあり、もう一方には別の側にあります。この例では、12のデータ特徴(データポイント)があり、下に示される座標を持つ平面があります。それは平面そのものではなく、3次元以上の次元があるため、ハイパープレーンと呼ぶことができます。(それでも、この例を説明するための平面の精神的なイメージは十分に近いです。)以下では、データを二つのクラスタに分けており、なぜ二つの座標セットがあるのかを説明しています。これらが各クラスタの重心、または中央点です。より多くのクラスタに分けようとすると、データが十分に離れていないため、精度が低下します。

    [5.68235294e+01 5.68627451e-01 3.25490196e+00 1.35803922e+02
 3.00078431e+02 1.47058824e-01 1.18627451e+00 1.45225490e+02
 4.01960784e-01 1.09705882e+00 1.59803922e+00 8.23529412e-01]
[5.29821429e+01 7.44047619e-01 3.12500000e+00 1.28636905e+02
 2.19047619e+02 1.48809524e-01 9.22619048e-01 1.52380952e+02
 2.85714286e-01 1.02142857e+00 1.57738095e+00 5.77380952e-01]

以下のコードは、Zeppelinノートブックとして保存されたコードです。(このガイドの関連投稿では、データフィールドとSparkデータフレームの読み込み方法について説明しています。)データは同じですが、患者IDの列を追加しています。

    %spark.pyspark

def isSick(x):
    if x in (3,7):
        return 0
    else:
        return 1
        
        
import pandas as pd
from pyspark.sql.types import StructType, StructField, NumericType

 
cols = ('age',       
      'sex',         
       'chest pain',           
       'resting blood pressure',    
       'serum cholestoral',       
       'fasting blood sugar',         
       'resting electrocardiographic results', 
       'maximum heart rate achieved',  
       'exercise induced angina',     
       'ST depression induced by exercise relative to rest',  
      'the slope of the peak exercise ST segment',     
      'number of major vessels ',       
       'thal',  
       'last')
      

      
data = pd.read_csv('/home/ubuntu/Downloads/heart.csv', delimiter=' ', names=cols)

data['isSick'] = data['thal'].apply(isSick)

rowCount = data['age'].count()
ids = np.arange(1,rowCount+1,1)
data['id'] = ids 


df = spark.createDataFrame(data)


from pyspark.ml.feature import VectorAssembler

features =   ('age',       
      'sex',         
       'chest pain',           
       'resting blood pressure',    
       'serum cholestoral',       
       'fasting blood sugar',         
       'resting electrocardiographic results', 
       'maximum heart rate achieved',  
       'exercise induced angina',     
       'ST depression induced by exercise relative to rest',  
      'the slope of the peak exercise ST segment',     
      'number of major vessels ') 
      
 

assembler = VectorAssembler(inputCols=features,outputCol="features")

dataset=assembler.transform(df)
dataset.select("features").show(truncate=False)

以下のコードは、Spark MLのドキュメントから直接取得したもので、いくつかの修正が加えられています。アルゴリズムを使用する方法は一つだけです。いくつかの項目に注意してください:

  • KMeans().setK(2).setSeed(1)⁠—数字の2は、データを分けるクラスタの数です。この値ClusteringEvaluator()が0.5を下回ると、明確な分割ではないことがわかります。最適なクラスタ数を確認する別の方法は、エルボー曲線をプロットすることです。
  • predictions = model.transform(dataset)—これにより、データフレームに予測列が追加され、どの患者がどのカテゴリに該当するかを示すことができます。

残りのコードは自明です。コードは各分割のクラスタ中心と二乗誤差の合計を印刷します。それはどのように機能するかの手がかりです: 各データポイントがクラスタの中心の推測からの距離を計算し、推測を調整し、最小値に達するまで繰り返します。この中央点からの各ポイントの距離は二乗されるため、距離は常に正です。目標は可能な限り最小の数を持つことです—すべてのデータポイント間の最短距離。

    %spark.pyspark

from pyspark.ml.evaluation import ClusteringEvaluator
from pyspark.ml.clustering import KMeans

# Trains a k-means model.
kmeans = KMeans().setK(2).setSeed(1)
model = kmeans.fit(dataset)

# Make predictions
predictions = model.transform(dataset)

# Evaluate clustering by computing Silhouette score
evaluator = ClusteringEvaluator()

silhouette = evaluator.evaluate(predictions)
print("Silhouette with squared euclidean distance = " + str(silhouette))


# Evaluate clustering.
cost = model.computeCost(dataset)
print("Within Set Sum of Squared Errors = " + str(cost))

# Shows the result.
print("Cluster Centers: ")
ctr=[]
centers = model.clusterCenters()
for center in centers:
    ctr.append(center)
    print(center)

以下のアルゴリズムは二乗ユークリッド距離を示しています。

  • この数が負の場合、データは全く分離できません。
  • 1に近い値は最大の分離を示します。
  • ゼロに近い値は、データがほとんど分離できないことを意味します。

この例では、0.57は悪くありません。

    Silhouette with squared euclidean distance = 0.5702065126840549
Within Set Sum of Squared Errors = 548301.9823949672
Cluster Centers: 
[5.68235294e+01 5.68627451e-01 3.25490196e+00 1.35803922e+02
 3.00078431e+02 1.47058824e-01 1.18627451e+00 1.45225490e+02
 4.01960784e-01 1.09705882e+00 1.59803922e+00 8.23529412e-01]
[5.29821429e+01 7.44047619e-01 3.12500000e+00 1.28636905e+02
 2.19047619e+02 1.48809524e-01 9.22619048e-01 1.52380952e+02
 2.85714286e-01 1.02142857e+00 1.57738095e+00 5.77380952e-01]

視覚化を容易にするために、SparkデータフレームをPandasデータフレームに変換し、Zeppelin関数z.showを使用してテーブルをリストします。

    %spark.pyspark
pandasDF=predictions.toPandas()
centers = pd.DataFrame(ctr,columns=features)

このデータをグラフ化することはできません。なぜなら、3Dグラフは3つの変数しかプロットできないからです。したがって、心臓病患者がどのように分離されているかを示すことはできませんが、z.display()を使用して表形式のレポートにまとめ、予測列を観察して、患者を一方または他方のカテゴリに配置します:

    %spark.pyspark
z.show(pandasDF)

見ての通り、患者90と91はクラスタ1に、患者92はクラスタ0にいます。

これらの投稿は私自身のものであり、必ずしもBMCの立場、戦略、または意見を代表するものではありません。

人工知能(AI)の関連記事

BMCからのさらなる情報に興味がありますか?

ザ・ブリーフは、メインフレームとエンタープライズオーケストレーションに関する月刊メールです:研究、顧客ストーリー、製品ニュース、イベント。

このオファーに登録することで、あなたはBMCのプライバシーポリシーを読み、同意したことを確認します。

ザ・ブリーフに登録しました

ザ・ブリーフは、メインフレームとエンタープライズオーケストレーション—BMC AMIおよびControl-M—に関するアナリストの研究、顧客の展開、両者にわたるイベントを網羅しています。