flink中数据集的循环iterate

本文介绍了如何使用Apache Flink进行机器学习算法的实现,特别是如何在Flink中构建循环结构以及设定根据特定条件(如loss收敛)动态结束循环的机制。通过示例代码展示了固定循环次数的实现,并详细解释了`closeWith`方法中使用termination criterion动态结束循环的原理。同时,文章还讨论了Flink在循环结束条件检查后的额外执行问题,指出这可能导致预期之外的结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

想使用flink实现机器学习算法,众所周知很多机器学习算法都需要涉及循环,比如说循环机器学习算法直到loss小于某个阈值,因此使用flink实现机器学习算法最基础的一环就是要学习在flink中怎么写循环。

这里演示了最基本的一个循环示例,

public static void main(String[] args) throws Exception {
    final ExecutionEnvironment env=ExecutionEnvironment.getExecutionEnvironment();
    //迭代次数
    int iterativeNum=10;
    // 定义要循环的数据集
    IterativeDataSet<String> input=env.fromElements("").iterate(iterativeNum);

    // 在循环中的方法体,本次操作产生的结果集会作为下一次循环的输入
    DataSet<String> iterativeBody = input.map(new RichMapFunction<String, String>() {
        @Override
        public String map(String s) throws Exception {
            s = s + String.format("step: %d \n" , getIterationRuntimeContext().getSuperstepNumber());
            return s;
        }
    });

    // 将要循环的数据集和循环的方法体连接起来
    DataSet<String> result = input.closeWith(iterativeBody);
    result.print();
}

输出结果为:

step: 1 
step: 2 
step: 3 
step: 4 
step: 5 
step: 6 
step: 7 
step: 8 
step: 9 
step: 10 

给个流程图
在这里插入图片描述


上面说完了固定循环次数,在flink中执行循环。但是我们往往需要根据某种条件结束循环,比方说,在机器学习程序中,我们往往是判断loss收敛、验证集精度来判断是否要结束循环,对于这种需要根据某种条件来结束循环的操作,flink提供了另一种方法:

    /**
     * Closes the iteration and specifies a termination criterion. This method defines the end of
     * the iterative program part.
     *
     * <p>The termination criterion is a means of dynamically signaling the iteration to halt. It is
     * expressed via a data set that will trigger to halt the loop as soon as the data set is empty.
     * A typical way of using the termination criterion is to have a filter that filters out all
     * elements that are considered non-converged. As soon as no more such elements exist, the
     * iteration finishes.
     *
     * @param iterationResult The data set that will be fed back to the next iteration.
     * @param terminationCriterion The data set that being used to trigger halt on operation once it
     *     is empty.
     * @return The DataSet that represents the result of the iteration, after the computation has
     *     terminated.
     * @see DataSet#iterate(int)
     */
    public DataSet<T> closeWith(DataSet<T> iterationResult, DataSet<?> terminationCriterion) {
        return new BulkIterationResultSet<T>(
                getExecutionEnvironment(), getType(), this, iterationResult, terminationCriterion);
    }

意思就是说,我们可以在closeWith方法中传入一个terminationCriterion参数,其就是判断循环是否结束的条件,给出一个小例子:

public class Test {
    public static void main(String[] args) throws Exception {
        ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
        DataSource<Integer> integerDataSource = env.fromElements(-8, -5, -1, 6, 7, 10);

        // 设置最大迭代次数:100次
        IterativeDataSet<Integer> iterativeDataSet = integerDataSource.iterate(100);

        // 循环体
        DataSet<Integer> iterativeBody = iterativeDataSet.map(x -> x + 2);

        // 循环结束条件
        DataSet<Integer> terminationCriterion = iterativeDataSet.filter(x -> (x<0));

        // 设置循环体和循环结束条件
        DataSet<Integer> result = iterativeDataSet.closeWith(iterativeBody, terminationCriterion);

        result.print();
    }
}

这里我设置了最大循环次数为100,但是根本不会指定到100次,因为使用了terminationCriterion,一旦所有的数字都大于0之后,这个循环就会停止。

这里还有一个很坑的事情,乍一看,上面的程序执行结果应该是:

0, 3, 7, 14, 15, 18

但是实际执行结果是:

2, 5, 9, 16, 17, 20

我开始看到结果结果也很懵,按理说当执行四次循环之后,terminationCriterion中就没有小于0的元素,循环就应该停止,输出结果0, 3, 7, 14, 15, 18。看论源码之后发现,flink在循环结束条件之后还会再执行一次iterativeBody。但是我觉得这是个很傻dior的设计,totally does not make sense。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

canaryW

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值