Sparklyr: `ft_index_to_string`はインデックスを文字列に戻すのに失敗します

作成日 2017年04月06日  ·  4コメント  ·  ソース: sparklyr/sparklyr

ft_index_to_stringを使用して予測を元の文字列に変換しようとしていますが、エラーjava.lang.ClassCastException: org.apache.spark.ml.attribute.UnresolvedAttribute$ cannot be cast to org.apache.spark.ml.attribute.NominalAttributeが発生します。

Sparkはdouble型の列をstringに変換する方法を知らないことは理解していますが、正確な理由はわかりません。 ドキュメントは、この関数がどのように機能するかについて非常に明確です。「 ft_string_indexerと対称的に、 ft_index_to_stringは、ラベルインデックスの列を元のラベルを文字列として含む列にマップします。」 しかし、例がないので、どこが間違っているのかわかりません。

再現可能な例:

ex_df <- dplyr::data_frame(label = sample(LETTERS, replace = TRUE, size = 40), 
                           feature1 = runif(40),
                           feature2 = runif(40))

library(sparklyr)
library(dplyr)
sc <- spark_connect(master = "local", version = "2.0.0")
ex_tbl <- copy_to(sc, ex_df)
partition <- ex_tbl %>%
  ft_string_indexer(input.col = "label", output.col = "label_ind") %>%
  sdf_partition(train = 0.5, test = 0.5, seed = 8585)
train_tbl <- partition$train
test_tbl <- partition$test
ml_formula <- formula(label_ind ~ . - label)
ml_nb <- ml_naive_bayes(train_tbl, ml_formula, type = "classification")

pred <- sdf_predict(ml_nb, test_tbl) %>%
  ft_index_to_string(input.col = "prediction", output.col = "pred_label") 
pred

完全なエラー:

Error: java.lang.ClassCastException: org.apache.spark.ml.attribute.UnresolvedAttribute$ cannot be cast to org.apache.spark.ml.attribute.NominalAttribute
    at org.apache.spark.ml.feature.IndexToString.transform(StringIndexer.scala:311)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sparklyr.Invoke$.invoke(invoke.scala:94)
    at sparklyr.StreamHandler$.handleMethodCall(stream.scala:89)
    at sparklyr.StreamHandler$.read(stream.scala:55)
    at sparklyr.BackendHandler.channelRead0(handler.scala:49)
    at sparklyr.BackendHandler.channelRead0(handler.scala:14)
    at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:244)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:846)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:745)

sessionInfo():

R version 3.3.2 (2016-10-31)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: macOS Sierra 10.12.3

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] dplyr_0.5.0    sparklyr_0.5.3

loaded via a namespace (and not attached):
 [1] Rcpp_0.12.9     withr_1.0.2     digest_0.6.12   rprojroot_1.2   assertthat_0.1  rappdirs_0.3.1  R6_2.2.0       
 [8] jsonlite_1.3    DBI_0.6         backports_1.0.5 magrittr_1.5    httr_1.2.1      lazyeval_0.2.0  config_0.2     
[15] tools_3.3.2     parallel_3.3.2  yaml_2.1.14     base64enc_0.1-3 tibble_1.2     

最も参考になるコメント

@mikhailBalyasin新しいAPIの動作は次のとおりです

partition <- ex_tbl %>%
  sdf_partition(train = 0.5, test = 0.5, seed = 8585)
train_tbl <- partition$train
test_tbl <- partition$test
ml_nb <- ml_naive_bayes(
  train_tbl, label ~ ., label_col = "label_col")

pred <- ml_predict(ml_nb, test_tbl)
> pred %>%
  +   glimpse()
Observations: 25
Variables: 17
$ label           <chr> "A", "D", "D", "D", "E", "E", "F", ...
$ feature1        <dbl> 0.11230824, 0.04834678, 0.25245844,...
$ feature2        <dbl> 0.86993327, 0.92504589, 0.49927288,...
$ prediction      <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ probability     <list> [<0.17589514, 0.14304304, 0.099137...
$ rawPrediction   <list> [<-2.432049, -2.638792, -3.005435,...
$ predicted_label <chr> "U", "U", "U", "U", "U", "U", "U", ...
$ probability_U   <dbl> 0.1758951, 0.1766892, 0.1710263, 0....
$ probability_X   <dbl> 0.1430430, 0.1458818, 0.1308545, 0....
$ probability_I   <dbl> 0.09913703, 0.09577040, 0.11507541,...
$ probability_E   <dbl> 0.09723525, 0.09957837, 0.08753517,...
$ probability_N   <dbl> 0.09333505, 0.09477631, 0.08684602,...
$ probability_T   <dbl> 0.06872758, 0.06669677, 0.07802856,...
$ probability_M   <dbl> 0.09545482, 0.09736886, 0.08725261,...
$ probability_L   <dbl> 0.07282556, 0.07117707, 0.07993756,...
$ probability_K   <dbl> 0.07360868, 0.07204058, 0.08028413,...
$ probability_D   <dbl> 0.08073785, 0.08002064, 0.08315973,...

ft_index_to_string()にはlabels引数もあるので、パイプラインを最初から構築するときにこれをより「手動で」行うことができますが、メタデータを取得するのは少し難しいかもしれません。おそらく、それを作成する関数を実装します。後で簡単に。

全てのコメント4件

同時に、 label_ind列をft_index_to_stringに渡すと機能するため、列にはメタデータが含まれます。

ex_df <- dplyr::data_frame(label = sample(LETTERS, replace = TRUE, size = 40), 
                           feature1 = runif(40),
                           feature2 = runif(40))

library(sparklyr)
library(dplyr)
sc <- spark_connect(master = "local", version = "2.0.0")
ex_tbl <- copy_to(sc, ex_df)
partition <- ex_tbl %>%
  ft_string_indexer(input.col = "label", output.col = "label_ind") %>%
  sdf_partition(train = 0.5, test = 0.5, seed = 8585)
train_tbl <- partition$train
test_tbl <- partition$test
ml_formula <- formula(label_ind ~ . - label)
ml_nb <- ml_naive_bayes(train_tbl, ml_formula, type = "classification")

pred <- sdf_predict(ml_nb, test_tbl) %>%
  ft_index_to_string(input.col = "label_ind", output.col = "pred_label") 
pred

出力:

> pred
Source:   query [26 x 8]
Database: spark connection master=local[8] app=sparklyr local=TRUE

   label   feature1   feature2 label_ind rawPrediction probability prediction pred_label
   <chr>      <dbl>      <dbl>     <dbl>        <list>      <list>      <dbl>      <chr>
1      A 0.83615730 0.14315830        14    <dbl [11]>  <dbl [11]>          2          A
2      D 0.31364793 0.46122049        19    <dbl [11]>  <dbl [11]>          0          D
3      E 0.91040128 0.12862943        12    <dbl [11]>  <dbl [11]>          2          E
4      G 0.77647296 0.05422326        15    <dbl [11]>  <dbl [11]>          2          G
5      I 0.45718419 0.01273057         3    <dbl [11]>  <dbl [11]>          0          I
6      I 0.71337845 0.90460885         3    <dbl [11]>  <dbl [11]>          0          I
7      J 0.02232347 0.99550593         8    <dbl [11]>  <dbl [11]>          0          J
8      J 0.22278048 0.38470348         8    <dbl [11]>  <dbl [11]>          0          J
9      K 0.41756519 0.61650525        18    <dbl [11]>  <dbl [11]>          0          K
10     L 0.09293533 0.49025301         5    <dbl [11]>  <dbl [11]>          0          L
# ... with 16 more rows

したがって、問題は、 prediction列に元のlabelに関するメタデータが含まれていることを確認するにはどうすればよいですか?

良い質問! Sparkがこれらのトランスフォーマーの属性とメタデータを格納する方法についてはまだよくわかりませんが、これは関連するコードのようです。

https://github.com/apache/spark/blob/74aa0df8f7f132b62754e5159262e4a5b9b641ab/mllib/src/main/scala/org/apache/spark/ml/feature/StringIndexer.scala#L350 -L372

'StructField'メタデータに飛び込むと、次のようになります。

[[4]]$metadata
<jobj[1358]>
  class org.apache.spark.sql.types.Metadata
  {"ml_attr":{"vals":["W","A","J","V","F","M","I","Q","P","C","K","R","O","S","X","T","U","H","D"],"type":"nominal","name":"label_ind"}}

Sparkデータ列からメタデータフィールドを抽出するためにsparklyrでルーチンを提供することを確実に検討する必要があります。また、たとえばcollect()でもそれらを抽出する必要があります。

参考までに、私がこれを突くために使用したコード(あなたの例からコピーされた)

ex_df <-
  dplyr::data_frame(
    label = sample(LETTERS, replace = TRUE, size = 40),
    feature1 = runif(40),
    feature2 = runif(40)
  )

library(sparklyr)
library(dplyr)
sc <- spark_connect(master = "local", version = "2.0.0")
ex_tbl <- copy_to(sc, ex_df)
partition <- ex_tbl %>%
  ft_string_indexer(input.col = "label", output.col = "label_ind") %>%
  sdf_partition(train = 0.5, test = 0.5, seed = 8585)
train_tbl <- partition$train
test_tbl <- partition$test
ml_formula <- formula(label_ind ~ . - label)
ml_nb <-
  ml_naive_bayes(train_tbl, ml_formula, type = "classification")

pred <- sdf_predict(ml_nb, test_tbl) %>%
  ft_index_to_string(input.col = "label_ind", output.col = "pred_label")
pred

schema <- invoke(spark_dataframe(predicted), "schema")
fields <- lapply(0:6, function(i) {
  invoke(schema, "apply", as.integer(i))
})

lapply(fields, function(field) {
  list(
    comment = invoke(field, "getComment"),
    metadata = invoke(field, "metadata"),
    name = invoke(field, "name")
  )
})

これに依存するhttps://github.com/rstudio/sparklyr/issues/937で作業すると、そこで閉じて追跡します。

@mikhailBalyasin新しいAPIの動作は次のとおりです

partition <- ex_tbl %>%
  sdf_partition(train = 0.5, test = 0.5, seed = 8585)
train_tbl <- partition$train
test_tbl <- partition$test
ml_nb <- ml_naive_bayes(
  train_tbl, label ~ ., label_col = "label_col")

pred <- ml_predict(ml_nb, test_tbl)
> pred %>%
  +   glimpse()
Observations: 25
Variables: 17
$ label           <chr> "A", "D", "D", "D", "E", "E", "F", ...
$ feature1        <dbl> 0.11230824, 0.04834678, 0.25245844,...
$ feature2        <dbl> 0.86993327, 0.92504589, 0.49927288,...
$ prediction      <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ probability     <list> [<0.17589514, 0.14304304, 0.099137...
$ rawPrediction   <list> [<-2.432049, -2.638792, -3.005435,...
$ predicted_label <chr> "U", "U", "U", "U", "U", "U", "U", ...
$ probability_U   <dbl> 0.1758951, 0.1766892, 0.1710263, 0....
$ probability_X   <dbl> 0.1430430, 0.1458818, 0.1308545, 0....
$ probability_I   <dbl> 0.09913703, 0.09577040, 0.11507541,...
$ probability_E   <dbl> 0.09723525, 0.09957837, 0.08753517,...
$ probability_N   <dbl> 0.09333505, 0.09477631, 0.08684602,...
$ probability_T   <dbl> 0.06872758, 0.06669677, 0.07802856,...
$ probability_M   <dbl> 0.09545482, 0.09736886, 0.08725261,...
$ probability_L   <dbl> 0.07282556, 0.07117707, 0.07993756,...
$ probability_K   <dbl> 0.07360868, 0.07204058, 0.08028413,...
$ probability_D   <dbl> 0.08073785, 0.08002064, 0.08315973,...

ft_index_to_string()にはlabels引数もあるので、パイプラインを最初から構築するときにこれをより「手動で」行うことができますが、メタデータを取得するのは少し難しいかもしれません。おそらく、それを作成する関数を実装します。後で簡単に。

このページは役に立ちましたか?
0 / 5 - 0 評価