Flink窗口机制

1.窗口的概念

在这里插入图片描述

时间是为窗口服务的。窗口是什么?为什么会有窗口呢?
(1)Flink要处理的数据,一般是从Kafka过来的流式数据,如果只是单纯地统计流的数据量,是没办法统计的。
(2)所以,要人为的 加上了一个时间区间限制(窗口),才可以进行统计。

2.窗口的分类

2.1滚动窗口(tumble)

2.1.1 sql版

窗口大小 = 滑动距离。
它的窗口是紧密排布的,中间没有任何的数据重复和丢失。
在这里插入图片描述

--创建表
CREATE TABLE source_table ( 
 user_id STRING, 
 price BIGINT,
 `timestamp` bigint,
 row_time AS TO_TIMESTAMP(FROM_UNIXTIME(`timestamp`)),
 watermark for row_time as row_time - interval '0' second
) WITH (
  'connector' = 'socket',
  'hostname' = 'node1',        
  'port' = '9999',
  'format' = 'csv'
);

--语法
tumble(row_time,时间间隔),比如,如下的sql
tumble(row_time,interval '5' second),每隔5秒滚动一次。

--业务查询逻辑(传统方式)
select 
user_id,
count(*) as pv,
sum(price) as sum_price,
UNIX_TIMESTAMP(CAST(tumble_start(row_time, interval '5' second) AS STRING)) * 1000  as window_start,
UNIX_TIMESTAMP(CAST(tumble_end(row_time, interval '5' second) AS STRING)) * 1000  as window_end
from source_table
group by
    user_id,
    tumble(row_time, interval '5' second);

--TVF写法
--语法,跟3个参数:
--参数1:表名
--参数2:表中事件时间列
--参数3:窗口大小
from table(tumble(table source,descriptor(row_time),interval '5' second))
--sql为:
SELECT 
    user_id,
    UNIX_TIMESTAMP(CAST(window_start AS STRING)) * 1000 as window_start,
    UNIX_TIMESTAMP(CAST(window_end AS STRING)) * 1000 as window_end,
    sum(price) as sum_price
FROM TABLE(TUMBLE(
        TABLE source_table
        , DESCRIPTOR(row_time)
        , INTERVAL '5' SECOND))
GROUP BY window_start, 
      window_end,
      user_id;
--window_start,window_end是新写法的关键字

在这里插入图片描述

在事件时间下,窗口的划分是根据第一条事件时间来划分的,只有等数据来了才会创建窗口。

计算公式 = 事件时间   - (事件时间 % 窗口大小)
刚刚的案例中,第一条数据的事件时间为1,窗口大小为5
1 - (1 % 5) = 0,所以,窗口的起始是从0开始。
由于窗口的大小是5秒,因此,后面的窗口排布就是:
[0,5)
[5,10)
[10,15)

什么时候触发计算呢?
在事件时间下,窗口的触发计算就是窗口结束 - 1(毫秒)。

比如上面的窗口是[0,5),结束的点就是5 * 1000 - 1 = 4999。

所以,我们输入5秒的时候,会触发窗口内的数据计算。

2.1.2 DataStream API版

开发步骤:
//1.创建流式执行环境
//2.数据源
//3.数据处理
	//3.1数据map转换操作,转成Tuple3
	//3.2把Tuple3的数据添加Watermark(monotonousTimestamps)
	前两个目的是为了指定时间列(才能根据这一列进行窗口的划分)
	//3.3把数据根据id进行分组
	//3.4分组之后,设置滚动事件时间窗口,并且制定窗口大小为5秒钟
	//3.5对窗口内的数据进行sum操作
	//3.6把Tuple3转成了Tuple2(取id和sum的值)
//4.数据输出
//5.启动流式任务
package flink.test;

import org.apache.flink.api.common.eventtime.SerializableTimestampAssigner;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.typeinfo.Types;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.KeyedStream;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows;
import org.apache.flink.streaming.api.windowing.time.Time;

public class tests {
    public static void main(String[] args) throws Exception {
        // TODO:  1.创建流式执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        // TODO: 2.数据源
        DataStreamSource<String> source = env.socketTextStream("node1", 9999);

        // TODO: 3.处理数据
        //分配窗口,创建窗口就有水位线,不需要就设置为0,类似于sql版
        /**
         * WatermarkStrategy的策略有四种:
         * forMonotonousTimestamps,单调递增水印
         * forBoundedOutOfOrderness,允许乱序数据(数据迟到)的水印
         * forGenerator,自定义水印
         * noWatermarks,没有水印
         *
         * ---
         * (1)map转换得到 每一行对应的列
         * (2)通过 .assignTimestampsAndWatermarks(WatermarkStrategy.<Tuple3<String, Integer, Long>>forMonotonousTimestamps() 来创建窗口
         * (3) .withTimestampAssigner() 来指定哪一列来表示时间列(才能根据这一列进行窗口的划分)
         */
        SingleOutputStreamOperator<Tuple3<String, Integer, Long>> mapAndWatermarkStream = source.map(new MapFunction<String, Tuple3<String, Integer, Long>>() {
            @Override
            public Tuple3<String, Integer, Long> map(String s) throws Exception {
                String[] lines = s.split(",");
                /**
                 * lines分为3个字段:String id,Integer price,Long ts 所有要类型转换一下
                 */
                return Tuple3.of(lines[0], Integer.valueOf(lines[1]), Long.valueOf(lines[2]));
            }
        }).assignTimestampsAndWatermarks(WatermarkStrategy.<Tuple3<String, Integer, Long>>forMonotonousTimestamps().withTimestampAssigner(
                new SerializableTimestampAssigner<Tuple3<String, Integer, Long>>() {
                    @Override
                    public long extractTimestamp(Tuple3<String, Integer, Long> element, long l) {
                        //这个方法用于标记 哪一列是表示时间戳
                        return element.f2 * 1000L;
                    }
                }));
        mapAndWatermarkStream.print("原数据:");
        //数据分组 sql group by
        KeyedStream<Tuple3<String, Integer, Long>, String> keybyStream = mapAndWatermarkStream.keyBy(value -> value.f0);
        //划分窗口和统计  指定窗口的大小,再sum  ---》类似与离线 sql  where条件限制范围 time between  20240101 and 20240107(比如说求一周内的某个指标) 和 select中的 sum
        SingleOutputStreamOperator<Tuple3<String, Integer, Long>> result = keybyStream.window(TumblingEventTimeWindows.of(Time.seconds(5)))
                .sum(1)
                .returns(Types.TUPLE(Types.STRING, Types.INT));

        // TODO: 4.数据输出
        result.printToErr("聚合后的数据:");
        // TODO: 5.启动流式任务
        env.execute();

    }
}

数据输出和结果输出:
在这里插入图片描述
在这里插入图片描述

2.2滑动窗口(hop)

滑动窗口 :滑动距离 不等于 窗口大小。

(1)如果滑动距离<窗口大小===>数据重复;

(2)如果滑动距离=窗口大小===>滚动窗口(没有任何的数据重复和丢失);

(3)如果滑动距离>窗口大小===>数据丢失(不考虑)!!!
在这里插入图片描述

2.2.1 sql版

--创建表
CREATE TABLE source_table ( 
 user_id STRING, 
 price BIGINT,
 `timestamp` bigint,
 row_time AS TO_TIMESTAMP(FROM_UNIXTIME(`timestamp`)),
 watermark for row_time as row_time - interval '0' second
) WITH (
  'connector' = 'socket',
  'hostname' = 'node1',        
  'port' = '9999',
  'format' = 'csv'
);

--语法
hop(事件时间列,滑动间隔,窗口大小)
hop(row_time,interval '2' second, interval '5' second)

--业务SQL
SELECT user_id,
UNIX_TIMESTAMP(CAST(hop_start(row_time, interval '2' SECOND, interval '5' SECOND) AS STRING)) * 1000 as window_start,
UNIX_TIMESTAMP(CAST(hop_end(row_time, interval '2' SECOND, interval '5' SECOND) AS STRING)) * 1000 as window_end, 
    sum(price) as sum_price
FROM source_table
GROUP BY user_id
    , hop(row_time, interval '2' SECOND, interval '5' SECOND);--每隔两秒滑动一次


--TVF写法
--table:表名
--descriptor:事件时间列
--滑动距离:interval 2 second
--窗口大小:interval 5 second
from table(hop(table 表名,descriptor(事件时间列),滑动间隔,窗口大小))
from table(hop(table source,descriptor(row_time),interval '2' second,interval '5' second))

--sql为:
SELECT 
    user_id,
UNIX_TIMESTAMP(CAST(window_start AS STRING)) * 1000 as window_start,  
UNIX_TIMESTAMP(CAST(window_end AS STRING)) * 1000 as window_end, 
    sum(price) as sum_price
FROM TABLE(HOP(
        TABLE source_table
        , DESCRIPTOR(row_time)
        , interval '2' SECOND, interval '6' SECOND))
GROUP BY window_start, 
      window_end,
      user_id;


数据输入和运行结果如下:

在这里插入图片描述

在这里插入图片描述
说明:

(1)事件时间1的到来,会让窗口仅限排布(划分),划分的窗口如下:

[-2,3],[0,5],[2,7],[4,9]

(2)窗口每隔两秒滑动一次,所以会有数据重复计算。

2.2.2 DataStream API版

package flink.test;

import org.apache.flink.api.common.eventtime.SerializableTimestampAssigner;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.api.common.typeinfo.Types;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.assigners.SlidingEventTimeWindows;
import org.apache.flink.streaming.api.windowing.time.Time;

public class Demo02_SlideWindow {
    public static void main(String[] args) throws Exception {
        //1.创建流式执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        //2.数据源
        DataStreamSource<String> source = env.socketTextStream("node1", 9999);
        //3.数据处理
        //3.1数据map转换操作,转成Tuple3
        SingleOutputStreamOperator<Tuple3<String, Integer, Long>> mapStream = source.map(value -> {
            /**
             * 由一行数据中,用逗号进行切分【id,price,ts】
             * String id
             * Integer price
             * Long ts
             */
            String[] lines = value.split(",");
            return Tuple3.of(lines[0], Integer.valueOf(lines[1]), Long.parseLong(lines[2]));
        }).returns(Types.TUPLE(Types.STRING, Types.INT, Types.LONG));
        //3.2把Tuple3的数据添加Watermark(monotonousTimestamps)
        /**
         * WatermarkStrategy生成水印的策略有四种:
         * forMonotonousTimestamps,单调递增水印(用的次多)
         * forBoundedOutOfOrderness,运行数据迟到(乱序)(用的最多)
         * forGeneric,自定义水印(不用)
         * noWatermark,没有水印(不用)
         */
        SingleOutputStreamOperator<Tuple3<String, Integer, Long>> watermarks = mapStream.assignTimestampsAndWatermarks(WatermarkStrategy.<Tuple3<String, Integer, Long>>forMonotonousTimestamps()
                .withTimestampAssigner(new SerializableTimestampAssigner<Tuple3<String, Integer, Long>>() {
                    @Override
                    public long extractTimestamp(Tuple3<String, Integer, Long> element, long recordTimestamp) {
                        return element.f2 * 1000L;
                    }
                }));
        //3.3把数据根据id进行分组
        watermarks.print("源数据:");
        SingleOutputStreamOperator<Tuple3<String, Integer, Long>> sumStream = watermarks.keyBy(value -> value.f0)
                //3.4分组之后,设置滑动事件时间窗口,并且制定窗口大小为5秒钟,滑动间隔为2秒。
                /**
                 * SlidingEventTimeWindows,滑动事件时间窗口,带2个参数:
                 * 参数1:窗口大小
                 * 参数2:滑动间隔
                 */
                .window(SlidingEventTimeWindows.of(Time.seconds(5), Time.seconds(2)))
                //3.5对窗口内的数据进行sum操作
                .sum(1);
        //3.6把Tuple3转成了Tuple2(取id和sum的值)
        SingleOutputStreamOperator<Tuple2<String, Integer>> result = sumStream.map(value -> Tuple2.of(value.f0, value.f1))
                .returns(Types.TUPLE(Types.STRING,Types.INT));
        //4.数据输出
        result.printToErr("聚合后的数据:");
        //5.启动流式任务
        env.execute();
    }
}


数据输入和结果输出:
在这里插入图片描述
在这里插入图片描述

2.3会话窗口(session)

会话窗口:在一个会话周期内,窗口的数据会累积,超过会话周期就会触发窗口的计算,同时开辟下一个新窗口。
注意:

数据本身的事件时间大于窗口间隔,才会触发当前窗口的计算。
在这里插入图片描述

2.3.1 sql版

--创建表
CREATE TABLE source_table ( 
 user_id STRING, 
 price BIGINT,
 `timestamp` bigint,
 row_time AS TO_TIMESTAMP(FROM_UNIXTIME(`timestamp`)),
 watermark for row_time as row_time - interval '0' second
) WITH (
  'connector' = 'socket',
  'hostname' = 'node1',        
  'port' = '9999',
  'format' = 'csv'
);

--语法
session(事件时间列,窗口间隔)
session(row_time,interval '5' second)

--业务SQL
SELECT 
    user_id,
UNIX_TIMESTAMP(CAST(session_start(row_time, interval '5' SECOND) AS STRING)) * 1000 as window_start,
UNIX_TIMESTAMP(CAST(session_end(row_time, interval '5' SECOND) AS STRING)) * 1000 as window_end, 
    sum(price) as sum_price
FROM source_table
GROUP BY user_id
      , session(row_time, interval '5' SECOND);


!!!会话窗口没有TVF写法。

数据输入和结果输出:
在这里插入图片描述

在这里插入图片描述

2.3.2 DataStream API版

package flink.test;

import org.apache.flink.api.common.eventtime.SerializableTimestampAssigner;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.typeinfo.Types;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.assigners.EventTimeSessionWindows;
import org.apache.flink.streaming.api.windowing.time.Time;

public class Demo03_SessionWindow {
    public static void main(String[] args) throws Exception {
        //1.创建流式执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        //2.数据源
        DataStreamSource<String> source = env.socketTextStream("node1", 9999);
        //3.数据处理
        //3.1数据map转换操作,转成Tuple3
        SingleOutputStreamOperator<Tuple3<String, Integer, Long>> mapStream = source.map(new MapFunction<String, Tuple3<String, Integer, Long>>() {
            @Override
            public Tuple3<String, Integer, Long> map(String value) throws Exception {
                /**
                 * String id
                 * Integer price
                 * Long ts
                 */
                String[] lines = value.split(",");
                return Tuple3.of(lines[0], Integer.valueOf(lines[1]), Long.parseLong(lines[2]));
            }
        });
        //3.2把Tuple3的数据添加Watermark(monotonousTimestamps)
        SingleOutputStreamOperator<Tuple3<String, Integer, Long>> watermarks = mapStream
                .assignTimestampsAndWatermarks(WatermarkStrategy.<Tuple3<String, Integer, Long>>forMonotonousTimestamps()
                .withTimestampAssigner(new SerializableTimestampAssigner<Tuple3<String, Integer, Long>>() {
            @Override
            public long extractTimestamp(Tuple3<String, Integer, Long> element, long recordTimestamp) {
                return element.f2 * 1000L;
            }
        }));
        watermarks.print("源数据:");
        //3.3把数据根据id进行分组
        //3.4分组之后,设置会话事件时间窗口,并且指定窗口间隔为5秒钟。
        //3.5对窗口内的数据进行sum操作
        SingleOutputStreamOperator<Tuple3<String, Integer, Long>> sumStream = watermarks.keyBy(value -> value.f0)
                .window(EventTimeSessionWindows.withGap(Time.seconds(5)))
                .sum(1);
        //3.6把Tuple3转成了Tuple2(取id和sum的值)
        SingleOutputStreamOperator<Tuple2<String, Integer>> result = sumStream.map(value -> Tuple2.of(value.f0, value.f1)).returns(Types.TUPLE(Types.STRING, Types.INT));
        //4.数据输出
        result.printToErr("聚合后的结果:");
        //5.启动流式任务
        env.execute();
    }
}

数据输入和结果输出:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/562791.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux-软件安装--jdk安装

jdk安装 前言1、软件安装方式二进制发布包安装rpm安装yum安装源码编译安装 2、安装jdk2.1、使用finalShell自带的上传工具将jdk的二进制发布包上传到Linux2.2、解压安装包2.3、配置环境变量![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/61ba9750e2e34638a39575c5…

【OpenHarmony-NDK技术】简单将cJson移植到OpenHarmony中,并在c层修改参数值再返回json

1、cJson的简单介绍 cJson - github网址 概述 一般使用cJson是&#xff0c;需要将json文本转化为json对象–编码&#xff0c;将json对象转化为json文本–解析。 git clone https://github.com/DaveGamble/cJSON.git 后留意cJSON.h和cJSON.h两个文件。 1、cJson的介绍 cJso…

决策树分类任务实战(python 代码详解)

目录 一、导入库、数据集、并划分训练集和测试集 二、参数调优 (一)第一种调参方法&#xff1a;for循环 (1)单参数优化 ①单参数优化(无K折交叉验证) ②单参数K折交叉验证 优化 (2)多参数优化 ①多参数优化(无K折交叉验证) 参数介绍&#xff1a; ②多参数K折交叉验证…

ruoyi-vue前端的一些自定义插件介绍

文章目录 自定义列表$tab对象打开页签关闭页签刷新页签 $modal对象提供成功、警告和错误等反馈信息&#xff08;无需点击确认&#xff09;提供成功、警告和错误等提示信息&#xff08;类似于alert&#xff0c;需要点确认&#xff09;提供成功、警告和错误等提示信息&#xff08…

常见现代卷积神经网络(ResNet, DenseNet)(Pytorch 11)

一 批量规范化&#xff08;batch normalization&#xff09; 训练深层神经网络是十分困难的&#xff0c;特别是在较短的时间内使他们收敛更加棘手。批量规范化&#xff08;batch normalization&#xff09;是一种流行且有效的技术&#xff0c;可持续加速深层网络的收敛速度。 …

数据结构与算法解题-20240421

数据结构与算法解题-20240421 一、278. 第一个错误的版本二、541. 反转字符串 II三、右旋字符串四、替换数字五、977.有序数组的平方 一、278. 第一个错误的版本 简单 你是产品经理&#xff0c;目前正在带领一个团队开发新的产品。不幸的是&#xff0c;你的产品的最新版本没有…

数据可视化(七):Pandas香港酒店数据高级分析,涉及相关系数,协方差,数据离散化,透视表等精美可视化展示

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

centos7搭建git服务器

1.centos7安装git yum install -y git yum install -y git-daemon 2.初始化空目录仓库 mkdir /usr/local/git mkdir /usr/local/git/projects mkdir /usr/local/git/projects/test-projects.git cd test-projects.git git --bare init 3.修改目录权限 cd .. chmod 775 tes…

力扣283. 移动零

Problem: 283. 移动零 文章目录 题目描述思路复杂度Code 题目描述 思路 1.定义一个int类型变量index初始化为0&#xff1b; 2.遍历nums当当前的元素nums[i]不为0时使nums[i]赋值给nums[index]&#xff1b; 3.从index开始将nums中置对应位置的元素设为0&#xff1b; 复杂度 时间…

第三届 SWCTF-Web 部分 WP

写在前面 题目主要涉及的是前端 php 内容知识&#xff0c;仅以本篇博客记录自己 Web 出题的奇思妙想。 Copyright © [2024] [Myon⁶]. All rights reserved. 目录 1、HTTP 2、再见了晚星 3、myon123_easy_php 4、baby_P0P 5、LOGIN!!! 1、HTTP 首页文件默认就是 ind…

基于Hadoop的电商用户行为分析系统设计与实现的系统架构设计

采集层&#xff1a;利用Flume采集电商服务器端用户行为数据&#xff0c;把数据处理后发送至HDFS。 存储层&#xff1a;用户行为数据采集上传至HDFS存储&#xff0c; 导入到数据仓库Hive进行计算处理&#xff0c;分析结果保存至MySql数据库中。 计算层&#xff1a;根据分析需求建…

Dynamic Wallpaper for Mac激活版:视频动态壁纸软件

Dynamic Wallpaper for Mac 是一款为Mac电脑量身打造的视频动态壁纸应用&#xff0c;为您的桌面带来无限生机和创意。这款应用提供了丰富多样的视频壁纸选择&#xff0c;涵盖了自然风景、抽象艺术、科幻奇观等多种主题&#xff0c;让您的桌面成为一幅活生生的艺术画作。 Dynami…

将记录从excel当中导出为.sql文件,再新增到数据库

一、背景 临时遇到了一个需求&#xff0c;比如根据人员的名字查询对应记录&#xff0c;看起来还是很简单的&#xff0c;直接用select查询就可以&#xff0c;然而如果此时存在以下情况&#xff1a; 数据库根本就没有人员信息表&#xff1b;------这个倒是好操作&#xff1b;现…

R: 阿尔法α多样性计算和箱图制作,以及差异分析

# install.packages("vegan") library(vegan) library(ggplot2) library(ggpubr)setwd("xxx") # 使用read.table()函数读取数据 df <- read.table("xxx", header TRUE, row.names 1)# 转置数据框 df <- t(df)# 计算每个样品的香农多样性…

【声呐仿真】学习记录1.5-使用docker配置dave(先看这个!)、解决一些问题

【声呐仿真】学习记录1.5-使用docker配置dave、解决一些问题 docker配置dave123 以下为未完全解决问题的随手记录&#xff0c;待日后解决再补充1.pcap、png解决&#xff0c;libusb未解决&#xff08;不要修改libusb相关的&#xff09;2.ISO C3.换源4.自动安装相关依赖 docker配…

Excel数据处理:动态数据分析报表、单元格数字格式、使用排序工具

1、在生成数据透视表之后选中一个单元格&#xff0c;点击插入&#xff0c;在图表中选择一个自己想要的图表。&#xff08;生成可视化的图表&#xff09; 2、在分析中找到切片器&#xff0c;通过点击切片器可以即时变换生成不同的可视化图&#xff0c;可以右键切片器选择关联两个…

怎么用 today函数求月份的汇总?

怎样用today函数来求以下表格中11月、12月的总额呢&#xff1f; 在excel里&#xff0c;可识别的日期实际上也是数值&#xff0c;这样的条件汇总&#xff0c;妨用SUMPRODUCT函数。 一、使用SUMPRODUCT函数 SUMPRODUCT((TEXT(A2:A5,"e-m")TEXT(EDATE(TODAY(),-1),&qu…

Llama3新一代 Llama模型

最近&#xff0c;Meta 发布了 Llama3 模型&#xff0c;从发布的数据来看&#xff0c;性能已经超越了 Gemini 1.5 和 Claud 3。 Llama 官网说&#xff0c;他们未来是要支持多语言和多模态的&#xff0c;希望那天赶紧到来。 未来 Llama3还将推出一个 400B大模型&#xff0c;目前…

【大模型应用极简开发入门(2)】GPT模型简史:从GPT-1到GPT-4:从小数据量的微调到大数据量的强化学习不断优化模型

文章目录 一. GPT-1&#xff1a;无监督与微调1. 在GPT-1之前的监督学习的问题2. GPT-1中新的学习过程-无监督的预训练3. 复杂任务下的微调4. GPT-1为更强大的模型铺平了道路 二. GPT-2&#xff1a;context learning1. 核心思想&#xff1a;context learning2. GPT-2的数据集 三…

【编译原理】03语法分析

1&#xff0c;语法分析的若干问题 1.1 语法分析器的作用 编译器前端的重要组成部分&#xff1a; (1) 根据词法分析器提供的记号流&#xff0c;为语法正确的输入构造分析树(或语法树)。 (2) 检查输入中的语法(可能包括词法)错误&#xff0c;并调用出错处理器进…