基于新一代kaldi项目的语音识别应用实例

news2024/11/17 15:54:09

本文是由郭理勇在第二届SH语音技术研讨会和第七届Kaldi技术交流会上对新一代kaldi项目在学术及“部署”两个方面报告的内容上的整理。如果有误,欢迎指正。

文字整理丨李泱泽 

编辑丨语音小管家

喜报:新一代Kaldi团队三篇论文均被语音顶会ICASSP-2023接收

  论文链接:

  • Fast and parallel decoding for transducer

    https://arxiv.org/abs/2211.00484

  • Delay-penalized transducer for low-latency streaming ASR

    https://arxiv.org/abs/2211.00490

  • Predicting Multi-Codebook Vector Quantization Indexes for Knowledge Distillation

    https://arxiv.org/abs/2211.00508

感谢各位对新一代Kaldi社区的关注。今天我主要介绍新一代Kaldi在学术及“部署”两个方面应用实例。“部署”在这里打了引号,是因为部署是一个复杂的系统,25分钟无法很好地描述它。因此今天只有一两页PPT会涉及到它,更多介绍在学术方面的应用。

今天的演讲主要包含以下几个环节,首先是我们项目以及团队的介绍。第二个环节是关于k2的学术应用,第三个环节是模型部署和sherpa子项目的介绍。由于只有25分钟时间,后面Q&A的时间可能不是特别充足,欢迎大家关注我们的公众号,扫码进入交流群。公众号每周五会推送一篇k2的文章,会介绍我们近期的工作和k2论文核心算法的实现。我们非常用心地去准备并且写得非常详细,强烈推荐对新一代Kaldi应用以及核心算法感兴趣的朋友关注我们公众号。

我们团队在小米有一个7人小组,同时也有很多来自开源社区广大工程师的支持。另外 Daniel Povey 教授领衔开发了k2 Lhotse 和 Icefall 项目,数据处理项目是以 Piotr 博士领衔开发。再次感谢广大开源社区工程师的支持。

今天的演讲主要涉及k2项目,熟悉新一代Kaldi项目的同学知道它包含很多子项目(而第一代Kaldi是一个单独的项目)。新一代Kaldi采用项目群的方式有利有弊。先说弊端,有的刚接触的朋友可能会说这项目哪是哪,我怎么一键跑不起来,一会儿要装这个一会儿要装那个。然后好处呢,如果朋友们听完今天的分享,可能会意识到为什么要拆成一个一个子项目,以及拆成子项目的好处。

新一代Kaldi是一个项目群,所以现代Kaldi项目并不完全等同于k2。k2只是其中一个子项目。今天我们主要涉及k2的学术应用。这个截图是k2 官网上截的一个介绍,当时 Dan 哥在写这个介绍时,我其实没有太看懂什么意思,今天我把这个重点标出来。第一段讲的是无缝融合,k2与Pytorch以及状态求导转换机的无缝结合。结合的目的在于可以很容易地修改结合各种不同的损失函数,像这里写到的交叉熵损失函数、CTC损失函数。第二个重点在于Compose函数,如何把一个神经网络的 embedding 转成状态机,转成状态机后,它就可以与很多传统的状态机的状态图去结合计算。我们今天主要针对这两段展开介绍。

这一页ppt是将k2官网首页的愿景翻译成中文。第一个就是Pytorch的无缝融合。既然说到k2 与 Pytorch是无缝融合。我们先来看看原来的缝在哪里。在没有k2的时候,也有很多把状态图的算法实现出来给Pytorch打补丁。早期的时候,我们有一个用pybind11给Kaldi 打包的项目(注:第一代Kaldi 项目中的pybind11分支),它和Pytorch有那么一点点的缝,不像k2那么无缝结合。它的缝在于底层内存分配没有用 torch的Allocator。k2 消除的另一缝在于它关键数据结构和算法都继承了 torch.autograd.Function。熟悉 Pytorch 的朋友可能知道,一旦继承了这个 function 之后,相当于就被 Pytorch 的 outograd graph 图追踪。所以k2的这些函数和Pytorch的自动求到就无缝结合上了。

在无缝结合的基础上,k2另一个愿景是实现很多FSA和FST算法,并且这些算法实现可以高效地运行于显卡之上。整个k2的运算不是在 tensor 维度,而是在 FST 维度。在k2里面有一个函数,它可以把Pytorch的tensor embedding转换为FSA。随后整个计算就转为了一个FSA/FST的操作,一个神经网络的embedding转化为FST/FSA的效果如上页ppt右图所示。这个示意图画的是,如果我有两个时刻,每个时刻有8帧的概率,那么这个 T x C = 2 x 8的这么一个矩阵,它转成FST/FSA后大概就长这个样子。这个也很容易理解,现在就2帧,第一个时刻和第二个时刻之间可以随意跳,第零个时刻和第一个时刻之间也可以随意跳,跳转概率就是每个token自己神经网络对应的概率。

k2要将所有的东西都转换为FST/FSA。接下来我们分析一个应用:k2是如何计算CTC损失函数的。现在假设 logits 也就是神经网络的输出为 2 x 8,标注文本只有一个token。即:两个时刻个logits, 一个tokenn。如果用Pytorch去计算的话,就是左边这个真实的代码,只需要调用 torch.Function.ctc_loss,一行就出来了(结果是5.0157)。如果用k2去实现的话,整个流程大概如右图所示。我们刚才说,k2把所有的概念所有的变量都转换为了FST/FSA。那么看到这个右边,k2计算CTC loss整体分为两大块。首先是左边,左边先处理文本信息label,然后和ctc_graph compose得到decoding_graph(注:逻辑上可以通过compose实现,在实际生产环节,会直接采用更为高效的k2.ctc_graph,“跳过”compose过程)。右边是处理神经网络的输出nnet_output,将它转为dense_fsa_vec,就是我们前一页看的那个图。然后decoding_graph和dense_fsa_vec compose后去做一个lattice,最后lattice再最大score。

token也就是右上角这个文本对应的fst也很好理解,token就是1,跳一步生成一个1。最后这个-1到0的边,是k2里自定义的一个特殊要求,每一个fst必须以-1结尾,这个不影响我们的理解,所以这个-1我们可以暂时忽略。左边的CTC graph,熟悉CTC的朋友可能知道,一般我们在论文里面画CTC gragh也都是这样画。现在把CTC graph和文本对应的线性序列去做compose的话,它会得到左下角这个图。左下角这个图其实就是表示怎样生成一个token 1。我们解释一下这个图,一个状态机可以看作一个集合,它的每一个状态就是一个路径。首先这个路径无法穷举,因为含有自环。我们就列出来几个,可以看出,无论左下角这个图怎么走,它最后输出的token都是1。所以这页PPT 展示了如果文本标注是一个token 1,它所对应的fst图结构会如左下角所示。

刚才我们将文本处理完了,现在处理神经网络。神经网络会转成这么一个dense_fsa,它和文本token对应的图结构(左上)去做intersect之后,输出左下角这个图。我们大概走一下这个图,比如0到1、1到3,它输出0 1,那么0是一个blank我们不要,相当于输出一个token 1。边上的概率就是从神经网络里拿到的,此时得到这个lattice,可以看到确实只有两个时刻(最后-1对应的边可以忽略)。各个边上的概率就是从神经网络上获取的概率,然后输出的label刚好就是我们文本要求的一个1。

那再对这个lattice做一个tot_score,得到5.0157。这个基于k2的CTC的损失函数结果有三个注意的点,首先它也等于5.0157(和前面torch.Function.ctc_loss结果完全一致)。第二点是,它是一个torch的tensor,这个的意义在于,神经网络的tensor转换为fsa/fst后经过k2的一番操作它还是一个tensor。从这个角度上我们可以说k2和Pytorch是无缝融合的。第三个点在于它有一个grad_fn,如果熟悉Pytorch就知道任何一个tensor只要它有grad_fn,它就可以做backward。

目前位置,我们以基于k2的CTC损失函数为例,解释了一下什么是Pytorch与k2的无缝融合。

明明Pytorch一行就能实现的东西,k2搞得这么复杂化简为繁是不是吃饱了没事干。其实不是,前面的几页PPT都是为接下来的两篇论文做铺垫。

首先我们分享一下英伟达的论文。如同刚开始宝秋总分享的那样,k2项目不只是小米一个团队开源出来的,还有很多开源社区的朋友一起贡献代码。不只是我们的工作值得关注,那些用k2来做研发的很好的一些点也值得大家关注。今天我们分享特意选了两篇不是我们团队的论文,避免大家说我们“王婆卖瓜,自卖自夸”。第一篇是英伟达最近被Interspeech接收的一篇论文。

我们回顾一下,这个就是刚才说的k2计算CTC的主要步骤。这篇论文主要修改了绿色这个点,也就是ctc_graph这一块儿。

看一下论文中的截图,常见的ctc_graph图是图a,论文里提出将这个图改为更简单一点的c、d。总体上来说,改了之后别的流程都不需要动,只需要把绿色这块儿的结构改了,就可以调用k2完成后续的计算。

它最终获得的效果是,如果去裁剪一下这个图,不按标准做法去做,去画一个特别小的图,准确率会有一定的损失,但是图的大小和内存占用可以小2到4倍。看到这里,我们就想这篇论文的工作,没有k2也是可以实现的。但是肯定会复杂一点,而且Pytorch CTC也不支持这样的操作。那k2究竟为这项工作带来多大的便利性呢。

我们看一下它的代码实现。这个代码是真实的代码,我直接从英伟达开源项目NVIDIA NeMo里截取出来的。看一下它是如何实现的,为什么说使用k2会给这个论文带来极大的便利性。他们最核心的函数就是我画红框和绿框的这两个,它调用的接口是k2.Fsa.from_str。我们只需要把边的信息写成一行一行的文本文件或者写成string类型。它前面这个构图实际上就写了一个for循环,构建了一个Python的代码。然后再写一个字符串的处理函数,就把这个图构出来了。构出来以后呢,直接就使用k2.Fsa.from_str导入进来。右边这个也是写一个字符串的处理函数去构一个图。构图之后,用k2.Fsa.from_str就把这个图导进来了。导进来之后,对k2来说,无论是标准的CTC拓扑图,还是改进后的拓扑图,或者还是你自己特地设计出来的别的图,只要合法,都能用k2.Fsa.from_str导进来,后续都可以用compose、intersect操作计算出来损失函数。所以说k2的便利性做的特别好。总体上来讲,用户只需要用python 字符串处理程序生成图,后续的操作都可以交给k2来探索不同结构的fst 的效果。

第二篇我们分享北京大学和腾讯基于k2的ICASSP论文,最近被ICASSP接受了。

它的工作是在经典的端到端训练框架上加了两个loss。一个是Character-Level CTC Loss,一个是LF-MMI Loss。结合上面那个例子,使用k2来实现这个的话就是天衣无缝了。我们只需要把图导进来,LF-MMI也是一个分子图一个分母图。把图做进来后,剩下的compose和intersect操作k2都是无缝支持的。

他们这里面也提到引入图操作的损失函数,准确率会获得大约4.1%到4.4%的提升。他们这个工作也是基于k2来实现的,也开源了,感兴趣的朋友可以关注一下。

这两篇是友商基于k2实现的论文,可以看一下他们用了大概哪些接口。第一个接口就是k2.Fsa.from_str,我个人感觉,翻译成·白话就是只要你会用Python处理字符串,你就可以构建Fsa的图,导进来后和pytorch无缝结合。from_str()还有一个接口是openfst=True。如果你现在已经有了一个由openfst构建的图,转成字符串后k2也可以识别,可以非常丝滑得导入。k2的图也可以非常丝滑地转成openfst的图。另一个我个人非常推荐的就是k2.to_dot,之前PPT里的都不是我特意去找什么画图工具画的,就是使用的k2.to_dot。可以看到截图里还有代码,调用k2.to_dot(fsa)。如果你在k2里做了一个字符串,想看看画的图对不对,直接就可以所见即所得,所得即所见,非常方便。还有一个函数就是k2.convert_dense_to_fsa_vec,如果想把一个torch的tensor转成fsa,只需要调用这个函数,接下整个fsa操作完成后返回的仍然是torch的tensor。tensor转成fsa之后,剩下的可以调用一系列k2里的工具,你可以用compose、intersect等各种各样的工具去处理它,处理完后返回的tensor与Pytorch无缝衔接,并且可导。

我们继续讲一下Pytorch这个可导该怎么理解。一种我个人感觉不是很全面的理解方式,可能受我们早期kaldi-pybind11的影响,总是觉得k2的函数是不是只能到最后计算损失函数的时候稍微用一下。以前把Pytorch和LF-MMI损失函数结合起来的时候,要把kaldi的LF-MMI函数打包成一个Python的接口。这样的话这个接口只能实现LF-MMI这个函数,别的什么都实现不了。从那个时代过来的朋友可能会有一个误区,觉得k2是不是也这样。input音频,经过Pytorch的transformer、Linear或是什么一大段处理,处理完后再送给k2的一个操作,返回一个loss。事实上这个理解是对的,刚才那两篇论文里也是这么实现的,但不是特别全面。因为我们说Pytorch与k2是完全无缝兼容的,两者的操作完全可以穿插着来。比如我现在有10个函数,第一个函数是Pytorch的函数。那现在我处理完后,我感觉到现在这个环节我需要一个k2的函数把它处理一下,比如k2的regular_tensor之类的去处理一下。那你第二个环节可以去插入一个k2的操作,k2的操作返回一个Pytorch的tensor。那你紧接着由可以在第三个环节插入一个Pytorch,在第四个环节插入一个k2。像三明治一样,一层加一层。我觉得这个可能是Pytorch与k2无缝理解的一种方式。包括我们最近在实现的MWER这样一种损失函数就是穿插着来的,先对神经网络的tensor做一个Pytorch的操作,然后做k2的操作,然后又是Pytorch的操作.....所以说完全无缝兼容。

结合起来,我们回答一个问题,k2是什么或者说k2能用来做什么。我个人感觉是k2提供了各种各样丰富的工具。这个工具究竟有什么用,我们写的时候也不知道这个工具能发挥到多大的威力。比如英伟达那篇论文,看完之后我也感觉很巧妙。当初在设计k2里的那些接口的时候,也没有想到会这么用。但是英伟达他们团队就用很巧妙的思维,找的点非常好,再加上辛苦的实验,做出来这么好的结果。做一个类比的话,k2里的工具就像是乐高的积木。那能用积木块搭成什么样子完全取决于社区广大工程师的思维探索。k2的工具并不会限制我们的能力,不像原来那种对kaldi工具打个包,那你只能用原有的版本,干不了别的。k2的工具是非常丰富的,你想怎么组装就怎么组装,实现什么功能能限制的就只有我们自己的思维了,k2这个工具其实已经完全做好了。再举一个类比的例子,这有点像torch的Linear和Conformer、Transformer之间的关系。像Linear这个结构,一个线性的变化Y = w * X,这个接口很早就出来了。后面就出来很聪明的人,把LInear去搭建这种attetion的qkv结构。这个例子就类似与k2,k2提供了很多的小工具接口,这些接口怎么搭建起来去做实验的一个功能,这个可能就需要一些思维火花。所以我个人建议,有发论文的这种要求的朋友们可以去研究一下k2。把奇思妙想和k2这些现有的工具结合起来,然后为我们学术领域做贡献。

前面pr了一堆友商的论文,我们也介绍一下我们自己的论文。前面有朋友问有没有论文链接,这边也给了链接。第一个就是Puned RNN-T的函数,我个人觉得不那么谦虚地讲可能是地球上最快的RNN-T损失计算方法。第二个就是RNN-T高速并行的解码方法,它可以实现基于CUDA加速,可以多个音频同时解码,并且集成了基于FST的解码图。第三个工作是label delay的控制方法,我们这个方法不仅可以用在RNN-T上也可用在CTC上。第四个引入的Training overhead几乎可以忽略不计的新型蒸馏框架,Dan哥前面有介绍,这边都给出了论文链接。

接下来介绍k2工程部署的工作sherpa。这个图可能画的不是特别的全,因为sherpa这个项目正在不断地发展。但是我们还是希望以这个图尽量把sherpa项目的思想和大概设计展示给大家。第一是我们把这个项目以sherpa为核心分为前端和后端。后端支持k2的解码,包括各种各样的MACE、NCNN、ONNX这些神经网络的引擎。这些引擎驱动的模型或者来自于我们Icefall的训练,或者来自于WeNet的训练,甚至来自于Torchaudio和Espnet的训练。一旦能导成ONNX或者Torchscript的模型,就可以使用sherpa来驱动。Sherpa建立好语音服务的后端引擎后,你可以通过websocket或者HTTP,以及python的前端或者C++前端或者Javascript前端完全无缝地结合起来。解释到这里我还想解释一下为什么新一代kaldi选择用项目组的方式来组建这个项目而不是像kaldi一样单个项目。结合刚才我们两个工作,比如像英伟达和腾讯他们开源的项目都用了k2。从他们论文需求上讲,他们可能只是需要fst或者fsa的操作,他们只需要把k2的子项目去集成到他们整个语音项目里,不需要用我们sherpa、lhotest。另外一块比如说现在有一些公司或者团队他们想用sherpa项目,他们模型的工具可能是他们自己自研的一套。但是不影响,使用sherpa项目只需要把训练的流程转成ONNX或者任意一种sherpa支持的格式,那你就可以用sherpa驱动起来。我觉得这个也可以大概显示出来我们使用项目组,把各个子项目进行解耦管理的优势。

正如Dan哥所说,现场放demo总是可能有风险,再加上时间有限。对我们工作感兴趣的朋友,可以扫码关注一下公众号,也可以加入我们的群。我们尽量做到每周更新。朋友们对新一代kaldi有问题可以在群里面问,我们会写文章去回答,如果这个问题特别好的话。

总结一下今天我们简要的分享主要是分享了两个问题。一个是现代kaldi项目包含很多子项目,k2是其中一个主要用于实现fst和fsa算法的子项目。另一个是我们当前主力研发的sherpa子项目,它是用于部署我们训练所得的模型。

最后热烈欢迎朋友们来关注公众号。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

亿级高并发电商项目-- 实战篇 --万达商城项目 十三(编写购物车、优化修改商品、下架商品方法、购物车模块监听修改商品、删除商品消息)

👏作者简介:大家好,我是小童,Java开发工程师,CSDN博客博主,Java领域新星创作者 📕系列专栏:前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶 &#x1f4…

SSL证书对虚拟主机的用处有哪些?

虚拟主机是指在同一台服务器上,通过不同的域名或IP地址为多个网站提供服务的一种网络主机。而SSL证书则是一种数字证书,它用于加密网站与用户之间的通信,确保数据传输的安全性和完整性。在虚拟主机上,SSL证书有以下几个用处&#…

SQL Server2008详细安装步骤(保姆式教程)

安装包下载 链接:https://pan.baidu.com/s/1Rjx4DHJBeCW2asC_4Kzo6Q?pwdchui 提取码:chui 安装过程 1.解压后使用管理员身份打开安装程序 2.选择全新安装或向现有安装添加新功能 3.确认 4.输入产品密钥(上方网盘安装包里有&#xff0…

【路径规划】基于前向动态规划算法在地形上找到最佳路径(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

【ArcGIS Pro二次开发】(10):属性表字段(field)的修改

在ArcGIS Pro中,经常会遇到用字段计算器对要素的属性表进行计算。下面以一个例子演示如何在ArcGIS Pro SDK二次开发中实现。 一、要实现的功能 如上图所示的要素图层,要实现如下功能: 当字段【市级行政区】的值为【泉州市】时,将…

用 .NET 启动你的 DJI Ryze Tello 无人机

大疆的 DJI Ryze Tello 是入门级的无人机,不仅在 STEM 教育中有非常广泛的应用,也可以作为编程入门的首选。通过 UDP 协议调用 DJI Ryze Tello SDK 可以让 DJI Ryze Tello 无人机执行起飞,降落,转向以及不同的花式动作。本文将会通…

Parasoft的自动化测试平台到底强在哪?

在如今产品迭代如此之快的大背景下,软件测试这项工作越来越被大家所重视,但是通常情况下大家都是选择在产品上线前再去做测试,这个时候就会面临很多麻烦和挑战。首先,产品已经开发好之后,体量比较大,要从哪…

BurpSuite配置抓取HTTPS数据包

简介 我们在渗透测试的过程中,经常会遇到HTTPS的网站,Burp默认是没有办法抓取HTTPS的包的,想要让Burp抓取Https的包也很好办,只需要浏览器安装相关的证书即可,接下来将配置过程做一个记录。 前置条件: 1.J…

HashMap原理(一):哈希函数的设计

哈希函数的作用与本质 HashMap用来存储存在映射关系的数据对{key, value},在内部通过构造复合数据结构来封装数据对&#xff0c;即 //伪代码&#xff0c;非源码 class Pair<K, V> {public K key;public V value; }假设用来存储数据对的哈希数表为table&#xff0c;数据…

TCP状态转换

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 TCP状态转换专栏&#xff1a;《Linux从小白到大神》《网络编程》 TCP状态转换示意图如下 针对上面的示…

项目结束先别着急庆祝,项目经理还有这些事要做

项目管理生命周期结束阶段的目的是确认项目可交付成果的完成&#xff0c;使项目发起人满意&#xff0c;并向所有参与者和利益相关者传达项目的最终处置和状态。 项目结束确保项目的所有参与者和利益相关者都清楚后续活动&#xff08;如新项目、服务过渡、SLA等&#xff09;&a…

【ChatGPT情商大考验】ChatGPT教我谈恋爱

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️&#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

graph在细粒度分类中的应用

目录基于Graph-Propagation的相关性学习AAAI2020基于graph的高阶关系发现CVPR2021基于Graph-Propagation的相关性学习AAAI2020 来源&#xff1a;Graph-Propagation Based Correlation Learning for Weakly Supervised Fine-Grained Image Classification&#xff08;这或许是第…

MATLAB R2022b 安装教程

MATLAB R2022b 安装教程MathWorks 于2022年9月发布了 MATLAB 和 Simulink 产品系列的最新版本 Matlab R2022b版本 &#xff0c;加入两个新产品&#xff1a; Medical Imaging Toolbox — 可视化、配准、分割和标注二维及三维医学图像Simscape Battery — 设计和仿真电池和储能系…

HiveSql一天一个小技巧:如何巧用分布函数percent_rank()求去掉最大最小值的平均薪水问题

0 问题描述参考链接(3条消息) HiveSql面试题12--如何分析去掉最大最小值的平均薪水&#xff08;字节跳动&#xff09;_莫叫石榴姐的博客-CSDN博客文中已经给出了三种解法&#xff0c;这里我们借助于此题&#xff0c;来研究如何用percent_rank()函数求解&#xff0c;简化解题思路…

Kafka(五)生产者向发送消息的执行流程

&#xff08;1&#xff09;生产者要往 Kafka 发送消息时&#xff0c;需要创建 ProducerRecoder,代码如下&#xff1a; ProducerRecord<String,String> record new ProducerRecoder<>("CostomerCountry","Precision Products","France&q…

新闻稿的制作流程:从确定新闻稿目的到将其分发给媒体

对于任何希望向媒体和公众传达具有新闻价值的信息的组织来说&#xff0c;新闻稿都是必不可少的工具。精心制作的新闻稿可以帮助您宣传您的业务、产品或服务&#xff0c;并可以产生有价值的媒体报道。在本文中&#xff0c;我们将指导您完成新闻稿的制作过程&#xff0c;从确定新…

08_MySQL聚合函数

1. 聚合函数介绍什么是聚合函数聚合函数作用于一组数据&#xff0c;并对一组数据返回一个值。聚合函数类型AVG()SUM()MAX()MIN()COUNT()注意&#xff1a;聚合函数不能嵌套调用。比如不能出现类似“AVG(SUM(字段名称))”形式的调用。1.1 AVG和SUM函数可以对数值型数据使用AVG 和…

上海亚商投顾:ChatGPT概念领跌 两市约3800股下跌

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。市场情绪三大指数今日继续调整&#xff0c;创业板指午后一度跌超1%。ChatGPT、AIGC概念股集体走低&#xff0c;三六零跌超8%&…

面试阿里测开岗,被面试官针对,当场翻脸,把我的简历还给我,疑似被拉黑...

好家伙&#xff0c;金三银四一到&#xff0c;这奇葩事可真是多&#xff0c;前两天和粉丝聊天&#xff0c;他说前段时间面试阿里的测开岗&#xff0c;最后和面试官干起来了。 我问他为什么&#xff0c;他说没啥&#xff0c;就觉得面试官太装了&#xff0c;就爱问一些虚而不实的…