1、StringIndexer
標簽索引器,它將標簽的字符串列映射到標簽索引的ML列。
如果輸入列為數字,則將其強制轉換為字符串並為字符串值編制索引。
索引在[0,numLabels)中。
索引構建的順序為標簽的頻率,優先編碼頻率較大的標簽,所以出現頻率最高的標簽為0號
默認情況下,按標簽頻率排序,因此最常使用的標簽的索引為0。
StringIndexer轉換器可以把一列類別型的特征(或標簽)進行編碼,使其數值化,
索引的范圍從0開始,該過程可以使得相應的特征索引化,
使得某些無法接受類別型特征的算法可以使用,並提高諸如決策樹等機器學習算法的效率
//定義一個StringIndexerModel,將label轉換成indexedlabel StringIndexerModel labelIndexerModel=new StringIndexer(). setInputCol("label") .setOutputCol("indexedLabel") .fit(rawData); //加labelIndexerModel加入到Pipeline中 Pipeline pipeline=new Pipeline() .setStages(new PipelineStage[] {labelIndexerModel, featureIndexerModel, dtClassifier, converter}); //查看結果 pipeline.fit(rawData).transform(rawData).select("label","indexedLabel").show(20,false); 按label出現的頻次,轉換成0~num numOfLabels-1(分類個數),頻次最高的轉換為0,以此類推: label=3,出現次數最多,出現了4次,轉換(編號)為0 其次是label=2,出現了3次,編號為1,以此類推 +-----+------------+ |label|indexedLabel| +-----+------------+ |3.0 |0.0 | |4.0 |3.0 | |1.0 |2.0 | |3.0 |0.0 | |2.0 |1.0 | |3.0 |0.0 | |2.0 |1.0 | |3.0 |0.0 | |2.0 |1.0 | |1.0 |2.0 | +-----+------------+
StringIndexer對String按頻次進行編號 id | category | categoryIndex ----|----------|--------------- 0 | a | 0.0 1 | b | 2.0 2 | c | 1.0 3 | a | 0.0 4 | a | 0.0 5 | c | 1.0 如果轉換模型(關系)是基於上面數據得到的 (a,b,c)->(0.0,2.0,1.0),如果用此模型轉換category多於(a,b,c)的數據,比如多了d,e,就會遇到麻煩: id | category | categoryIndex ----|----------|--------------- 0 | a | 0.0 1 | b | 2.0 2 | d | ? 3 | e | ? 4 | a | 0.0 5 | c | 1.0 Spark提供了兩種處理方式: StringIndexerModel labelIndexerModel=new StringIndexer(). setInputCol("label") .setOutputCol("indexedLabel") //.setHandleInvalid("error") .setHandleInvalid("skip") .fit(rawData); (1)默認設置,也就是.setHandleInvalid("error"):會拋出異常 org.apache.spark.SparkException: Unseen label: d,e (2).setHandleInvalid("skip") 忽略這些label所在行的數據,正常運行,將輸出如下結果: id | category | categoryIndex ----|----------|--------------- 0 | a | 0.0 1 | b | 2.0 4 | a | 0.0 5 | c | 1.0
2、IndexToString
是一個轉換器“ Transformer”,它將一列索引映射回對應字符串值的新列。
索引字符串映射既可以來自輸入列的ML屬性,也可以來自用戶提供的標簽(優先於ML屬性)。
相應的,有StringIndexer,就應該有IndexToString。 在應用StringIndexer對labels進行重新編號后,帶着這些編號后的label對數據進行了訓練,並接着對其他數據進行了預測, 得到預測結果,預測結果的label也是重新編號過的,因此需要轉換回來。 見下面例子,轉換回來的convetedPrediction才和原始的label對應。 IndexToString converter=new IndexToString() .setInputCol("prediction")//Spark默認預測label行 .setOutputCol("convetedPrediction")//轉換回來的預測label .setLabels(labelIndexerModel.labels());//需要指定前面建好模型 Pipeline pipeline=new Pipeline() .setStages(new PipelineStage[] {labelIndexerModel, featureIndexerModel, dtClassifier, converter}); pipeline.fit(rawData).transform(rawData) .select("label","prediction","convetedPrediction").show(20,false); |label|prediction|convetedPrediction| +-----+----------+------------------+ |3.0 |0.0 |3.0 | |4.0 |1.0 |2.0 | |1.0 |2.0 |1.0 | |3.0 |0.0 |3.0 | |2.0 |1.0 |2.0 | |3.0 |0.0 |3.0 | |2.0 |1.0 |2.0 | |3.0 |0.0 |3.0 | |2.0 |1.0 |2.0 | |1.0 |2.0 |1.0 | +-----+----------+------------------+