scala – Weka,SimpleKMeans无法处理字符串属性
我在
Scala中使用Weka(虽然语法几乎与
Java相同).我试图用SimpleKMeans群集器来评估我的数据,但是群集器不会接受字符串数据.我不想对字符串数据进行聚类;我只是想用它来标记点.
这是我正在使用的数据: @relation Locations @attribute ID string @attribute Latitude numeric @attribute Longitude numeric @data 'Carnegie Mellon University',40.443064,-79.944163 'Stanford University',37.427539,-122.170169 'Massachusetts Institute of Technology',42.358866,-71.093823 'University of California Berkeley',37.872166,-122.259444 'University of Washington',47.65601,-122.30934 'University of Illinois Urbana Champaign',40.091022,-88.229992 'University of Southern California',34.019372,-118.28611 'University of California San Diego',32.881494,-117.243079 如您所见,它基本上是x和y坐标平面上的点集合.任何模式的价值都可以忽略不计;这只是与Weka合作的一项练习. 这是给我带来麻烦的代码: val instance = new Instances(new StringReader(wekaHeader + wekaData)) val simpleKMeans = new SimpleKMeans() simpleKMeans.buildClusterer(instance) val eval = new ClusterEvaluation() eval.setClusterer(simpleKMeans) eval.evaluateClusterer(new Instances(instance)) Logger.info(eval.clusterResultsToString) 我在simpleKMeans.buildClusterer(实例)上收到以下错误: [UnsupportedAttributeTypeException:weka.clusterers.SimpleKMeans:无法处理字符串属性!] 如何在进行群集时让Weka保留ID? 以下是我为解决此问题而采取的其他几个步骤: 我使用了Weka Explorer并将这些数据加载为CSV: ID,Latitude,Longitude 'Carnegie Mellon University',-117.243079 这就是我想在Weka Explorer中做的事情. Weka对点进行聚类并保留ID列以标识每个点.我会在我的代码中执行此操作,但我尝试在不生成其他文件的情况下执行此操作.正如您在Weka Java API中看到的,Instances仅将java.io.Reader解释为ARFF. 我也尝试了以下代码: val instance = new Instances(new StringReader(wekaHeader + wekaData)) instance.deleteAttributeAt(0) val simpleKMeans = new SimpleKMeans() simpleKMeans.buildClusterer(instance) val eval = new ClusterEvaluation() eval.setClusterer(simpleKMeans) eval.evaluateClusterer(new Instances(instance)) Logger.info(eval.clusterResultsToString) 这适用于我的代码,并显示结果.这证明Weka一般都在工作,但由于我正在删除ID属性,我无法真正将聚集点映射回原始值. 解决方法
我正在回答我自己的问题,在这样做的过程中,我想解决两个问题:
>为什么CSV使用字符串值 正如Sentry在评论中指出的那样,当从CSV加载时,ID实际上会转换为名义属性. 如果数据必须是ARFF格式(就像在我的示例中,从StringReader创建Instances对象),则可以应用StringToNominal过滤器: val instances = new Instances(new StringReader(wekaHeader + wekaData)) val filter = new StringToNominal() filter.setAttributeRange("first") filter.setInputFormat(instances) val filteredInstance = Filter.useFilter(instances,filter) val simpleKMeans = new SimpleKMeans() simpleKMeans.buildClusterer(instance) ... 这允许在聚类中使用“字符串”值,尽管它实际上只是作为标称值处理.它不会影响聚类(如果ID是唯一的),但它没有像我希望的那样对评估做出贡献,这让我想到了下一个问题. 我希望能够得到一个很好的集群和数据地图,比如集群:Int – >数组[(ID,纬度,经度)]或ID – >集群:Int.但是,群集结果并不方便.根据我过去几天的经验,有两种方法可用于查找每个数据点的集群. 为了获得集群分配,simpleKMeans.getAssignments返回一个整数数组,它是每个数据元素的集群分配.整数数组的顺序与原始数据项的顺序相同,必须手动关联回原始数据项.这可以通过在原始数据项列表上使用zip方法在Scala中轻松完成,然后使用其他方法(如groupBy或map)以您喜欢的格式获取集合.请记住,单独使用此方法根本不使用ID属性,并且可以完全从数据点中省略ID属性. 但是,您也可以使用simpleKMeans.getClusterCentroids或eval.clusterResultsToString()获取集群中心.我没有用过这么多,但在我看来,ID属性可以在这里从集群中心恢复.据我所知,这是唯一可以从群集评估中使用或恢复ID数据的情况. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |