Apache flink apache flink KMeans对未排序分组的操作

Apache flink apache flink KMeans对未排序分组的操作,apache-flink,flinkml,Apache Flink,Flinkml,我有一个flink数据集(从文件中读取),其中包含来自许多不同传感器的传感器读数。我使用flinks groupBy()方法将数据组织为每个传感器的未排序分组。接下来,我想以分布式方式对数据集中的每个未排序的组运行KMeans算法 我的问题是,如何使用flink高效地实现此功能。 下面是我当前的实现:我编写了自己的groupReduce()方法,将flink KMeans算法应用于每个未排序的组。这段代码可以工作,但是看起来非常慢,并且占用了大量内存 我认为这与我必须进行的大量数据重组有关。必须

我有一个flink数据集(从文件中读取),其中包含来自许多不同传感器的传感器读数。我使用flinks groupBy()方法将数据组织为每个传感器的未排序分组。接下来,我想以分布式方式对数据集中的每个未排序的组运行KMeans算法

我的问题是,如何使用flink高效地实现此功能。 下面是我当前的实现:我编写了自己的groupReduce()方法,将flink KMeans算法应用于每个未排序的组。这段代码可以工作,但是看起来非常慢,并且占用了大量内存

我认为这与我必须进行的大量数据重组有关。必须执行多次数据转换才能使代码运行,因为我不知道如何更有效地执行:

  • 将分组取消排序为Iterable(groupReduce()方法的开头)
  • Iterable to LinkedList(使用fromCollection()方法时需要此选项)
  • 数据集的LinkedList(需要作为KMeans的输入)
  • 将生成的KMeans数据集发送到LinkedList(以便能够对收集器进行迭代)
当然,必须有一种更有效、更高效的方法来实现这一点? 有人能告诉我如何以一种干净高效的方式来实现这一点吗

//*************************************************************************
//变数
// *************************************************************************
静态int numberClusters=10;
静态整数最大迭代次数=10;
静态int传感器计数=117;
静态ExecutionEnvironment env=ExecutionEnvironment.getExecutionEnvironment();
// *************************************************************************
//节目
// *************************************************************************
公共静态void main(字符串[]args)引发异常{
最终长启动时间=System.currentTimeMillis();
字符串fileName=“C:/tmp/data.nt”;
数据集文本=env.readTextFile(文件名);
//从文本文件输入中筛选相关数据集
未排序的分组点=文本
.filter(x->x.contains(“Value”)和&x.contains(“valueLiteral”)。filter(x->!x.contains(“字符串”))
.map(x->new Tuple2(
整数.parseInt(x.substring(x.indexOf(“”)+1,x.indexOf(“>”))%sensorCount,
新点(Double.parseDouble(x.split(“\”)[1]))
.过滤器(x->x.f0<10)
.groupBy(0);
数据集输出=points.reduceGroup(新的DistinctReduce());
output.print();
//打印执行时间
最终长结束时间=System.currentTimeMillis();
System.out.println(“总执行时间:+(endTime-startTime)+“ms”);
}
公共静态类DistinctReduce实现groupreduce函数{
私有静态最终长serialVersionUID=1L;
@重写公共void reduce(Iterable in,Collector out)引发异常{
AtomicInteger计数器=新的AtomicInteger(0);
列表点列表=新建链接列表();
用于(tuple2t:in){
pointsList.add(新点(t.f1.x));
}
数据集点=环境fromCollection(点列表);
数据集质心=点
.distinct()
.第一(数字群集)
.map(x->新质心(counter.incrementAndGet(),x));
//数据集test=centroids.map(x->String.format(“质心%s”,x));//test.print();
IterativeDataSet循环=质心。迭代(maxIterations);
数据集newCentroids=点//计算每个点最近的质心
.map(新建SelectNearestCenter()).withBroadcastSet(循环,“质心”)//计算每个质心的点坐标并求和
.map(新CountAppender())
.groupBy(0)
.reduce(新质心累加器())//根据点计数和坐标和计算新质心
.map(新的质心平均器());
//将新质心反馈到下一个迭代中
数据集finalCentroids=loop.closeWith(新质心);
DataSet clusteredPoints=点//将点指定给最终簇
.map(new SelectNearestCenter())。带有广播集(finalcentroid,“质心”);
//emit result System.out.println(“来自KMeans算法的结果:”);
clusteredPoints.print();
//发出所有唯一的字符串。
List clusteredPoints List=clusteredPoints.collect();
for(tuple2t:clusteredPointsList){
out.collect(t);
}
}
}

您必须首先对数据点和质心进行分组。然后迭代质心并将其与数据点共同分组。对于组中的每个点,您将其分配给最近的质心。然后根据初始组索引和质心索引进行分组,以减少分配给同一质心的所有点。这就是结果一次迭代的lt

代码可以如下所示:

DataSet groupedPoints=。。。
数据集组质心=。。。
IterativeDataSet groupLoop=groupCentroids.iterate(10);
数据集newGroupCentroids=groupLoop
.coGroup(groupedPoints).where(0).equalTo(0).with(new CoGroupFunction()){
@凌驾
public void coGroup(Iterable centroidsIterable、Iterable points、Collector out)引发异常{
//缓存质心
列表质心=新的ArrayList();
迭代器centroidIterator=centroidsIterable.Iterator();
对于(Tuple2点tuple:points){
double minDistance=double.MAX_值;
int minIndex=-1;
Point=pointTuple.f1;
while(centroidIterator.hasNext()){
add(centroidIterator.next());
}
for(元组2质心元组:质心){
形心形心=形心元组.f1;
双距离=点欧氏距离(质心);
if(距离<距离){