大模型之SORA技术学习

文章目录 sora的技术原理文字生成视频过程sora的技术优势量大质优的视频预训练库算力多,采样步骤多,更精细。GPT解释力更强,提示词(Prompt)表现更好 使用场景参考 Sora改变AI认知方式,开启走向【世界模拟器】的史诗级的漫漫征途,才是未来暴风眼,真正的重点。 但Sora并没有理解整个世界和诸多物理细节,常识及定律,而是根据GPT语义解释能力、丰富的联想和丰富度,基于海量的视频库,抄写视频片段并猜视频下一帧,并使用Diffusion、GAN(对抗式生成网络技术)将多个视频片段混合在一起,产生稳定且连续的短视频。 Yann LeCun(ACM图灵奖得主,纽约大学教授。Meta首席人工智能科学家)针对Sora的评论。大意是: 让我在这里澄清一个巨大的误解。从提示文字,生成看起来相当逼真的视频,并不意味着,这个系统理解物理世界。生成一个视频,和基于世界模型的因果预测,大不相同。目前这种生成式的方向,代价高昂,可能还有更好的法子。 sora的技术原理 结合了 Diffusion model(扩散模型)和 Transformer 技术,以确保视频内容与文本描述紧密相连 Sora的官方技术报告详见: Sora官方的技术报告:Video generation models as world simulators 主要功能和目标: 目前,Sora 的主要功能是将文本输入转换成视频输出。这包括但不限于将故事、说明或命令转化为相应的视频。Sora 的目标是创建一个能够理解复杂文本描述并将其转化为高质量视频内容的系统。官方的声明指出,Sora 的最终目标是向一个“通用物理世界模拟器”的方向迈进,即成为一个能够模拟真实世界的复杂互动和动态环境的强大工具。 训练流程包括以下步骤: 收集视频数据与标注信息。训练图片字幕模型。利用 GPT-4 丰富视频描述。切分视频为 Patches。应用视频压缩模型。在潜在空间中处理视频数据。应用扩散模型与 Transformer 进行训练。最终恢复高清视频。 核心模块: Transformer 结构:这是一种深度学习模型的架构,最初用于自然语言处理,现在被广泛应用于各种领域,包括 Sora 的几个组件。Diffusion model:用于逐步去除视频中的噪声,从而生成清晰的图像场景。 文字生成视频过程 提供一段文字:依靠GPT语义解释能力、丰富的联想和丰富度,产生针对视频内容详细的描述。如文本是:“散步在夜晚东京街道上”,GPT发挥想象力,联想出一堆词和关联“高楼”、“繁华夜景”等等。它联想力越丰富,Sora能关联到的时空碎块就越多越准。Diffusion:作为一个画师,根据关键词特征值对应的可能性概率,在海量视频库到处翻,看看抄哪一个碎块比较像,看哪个像,就猜对应的下一笔要落在什么地方。重复很多步通过Diffusion和Transformer共同联想,死记硬背,从巨大视频库里生拉硬拽,配合GAN(对抗式生成网络技术),把这些一张张碎块拼成图,再拼接成一个序列,每秒播放几十张,视频就出来了 sora的技术优势 Sora实际上对于Pika等,只是量变,都是差不多的技术和原理,没有质变。但几乎达到了近似质变的效果了。原因在于: 量大质优的视频预训练库 大力出奇迹,是OpenAI的基因。 到底花了多少钱在高质量的视频素材上,搜集了多少的视频库,只有OpenAI自己知道。但可以肯定的是,远远不是Pika等创业团队所能比的。 记得多,才能抄的好,混得妙。 甚至,现在的视频量已经不能满足OpenAI的需求了。已经被爆料,OpenAI的视频库,大量使用了UE5生成的视频来做补充和训练。我们看到的赛车那个视频就是。 Pika、Runway、Stable Video和Sora有时候会撞车:都使用了同一个素材加到库中。那么使用一样类似的关键词,可能就能调出一模一样的元素。 算力多,采样步骤多,更精细。 不同采样和计算步骤后,通过同一个视频库“猜”的步骤越多,加的东西越细,效果越好。做32倍运算的效果,就明显好于4倍的效果。 还是大力出奇迹,OpenAI不变的配方和味道。 那么请问,Pika等创业公司能有多少张GPU卡呢? Sora能土豪的用32倍,1080p,渲染1分钟的视频。创业公司能用多少,4倍,360p,4-8秒,已经足够把钱烧光了… 画面精致度怎么比?时长怎么比?不公平。 Diffusion的不稳定性通病,在Pika等产品中已经表现无疑。 Sora和他们完全不在一个层次上,稳定性很好。已经不能完全用数据和算力来解释了。一定是采用了GAN(对抗式生成网络技术)这个增强连续性的技术。 生成的视频效果比较见下图: GPT解释力更强,提示词(Prompt)表现更好 对一段提示词或提示句子,GPT能展开的联想和丰富度,是决定了Sora抄什么,能猜多准的。 OpenAI的GPT能力天下第一,开源模型无能撼动。 所以,不幸的是,Pika等创业公司大多还是要依靠OpenAI的GPT能力。 那么,问题来了,亲儿子能用的,一定胜过外部客户能用到的深度和广度。 第二个点,就是外部公司的视频库和GPT联想能力不能首尾配对;但是Sora可以啊,GPT是自家的,视频库也是自家的,两者直接****关联的精准度以及调取的效率,完全是外部客户不能比的。 使用场景 生成创意素材。通过剪辑和局部使用,做出自己的成品。对于自媒体行业是一大利好。生成概念片和内部讨论稿,极大的加快创意沟通的效率。利用它的连续性,结合一些3D工具,快速建模。已经有人在做了,但效果还待改进。推荐大家看看B站UP主设计师的AI工具箱的Sora建模实践, 调试的好,是个路子。 参考 3原理+1揭秘,将Sora拉下神坛

大模型(LLM)的训练语料信息汇总

大规模语料是模型训练的基础 大模型的训练,大规模的语料是很重要的 大型语言模型在许多自然语言处理任务上取得了显著进展,研究人员正在转向越来越大的文本语料库进行训练 大多数基于Transformer的大型语言模型 (LLM) 都依赖于英文维基百科和Common Crawl、C4、Github的4个大型数据集。这几个数据集是最常用的,基本上大部分大模型训练过程都会使用到,其中CommonCrawl的数据集比较大,而wiki Pedia的数据集比较规整相对来说比较少 目前Hugging Face上包含中文的语料数据集有954个 已经处理好的语料信息 1. C4(Common Crawl Cleaned Corpus) 数据来源:C4 是由 Common Crawl 爬虫数据经过清洗后得到的语料库。Common Crawl 是一个从互联网上爬取大量文本的项目。数据规模:C4 包含来自互联网上超过 3.65 亿个域的超过 1560 亿个 token。清洗方式:C4 是通过获取 Common Crawl 的 2019 年 4 月快照并应用多个过滤器来创建的,旨在删除非自然英语的文本。过滤器包括去除不以终端标点符号结尾或少于三个单词的行,丢弃少于五个句子或包含 Lorem ipsum 占位符文本的文档,以及删除包含“Dirty,Naughty,Obscene 或 Otherwise Bad Words 清单”上任何单词的文档。此外,还使用 langdetect 删除未被分类为英语且概率至少为 0.99 的文档,因此 C4 主要由英文文本组成。数据下载:C4 GitHub Repository 2. ROOTS(Responsible Open-science Open-collaboration Text Sources) 数据来源:ROOTS 是一个跨越 59 种语言(46 种自然语言和 13 种编程语言)的 1.6TB 数据集,用于训练拥有 1760 亿个参数的 BigScience 大型公开科学多语言开放访问(BLOOM)语言模型。 ROOTS (Responsible Open-science Open-collaboration Text Sources) 这个数据集是一个由 huggingface datasets, dataset collections, pseudo-crawl dataset, Github Code, OSCAR 这几个数据构成的 数据构建:ROOTS 主要包括三个来源:已整理好的数据集、伪爬虫数据集(部分志愿者提交的网站,但还没包括内容,需要利用 URL 去 Common Crawl 的快照中解析对应的内容)、经过预处理的网络爬取数据集 OSCAR。数据清洗:清洗过程包括去除重复内容、过滤页面代码或爬行工件、过滤 SEO 页面、过滤色情垃圾等。数据下载:https://huggingface.

bert 相似度任务训练简单版本,faiss 寻找相似 topk

目录 任务 代码 train.py predit.py faiss 最相似的 topk 数 任务 使用 bert-base-chinese 训练相似度任务,参考:微调BERT模型实现相似性判断 - 知乎 参考他上面代码,他使用的是 BertForNextSentencePrediction 模型,BertForNextSentencePrediction 原本是设计用于下一个句子预测任务的。在BERT的原始训练中,模型会接收到一对句子,并试图预测第二个句子是否紧跟在第一个句子之后;所以使用这个模型标签(label)只能是 0,1,相当于二分类任务了 但其实在相似度任务中,我们每一条数据都是【text1\ttext2\tlabel】的形式,其中 label 代表相似度,可以给两个文本打分表示相似度,也可以映射为分类任务,0 代表不相似,1 代表相似,他这篇文章利用了这种思想,对新手还挺有用的。 现在我搞了一个招聘数据,里面有办公区域列,处理过了,每一行代表【地址1\t地址2\t相似度】 只要两文本中有一个地址相似我就作为相似,标签为 1,否则 0 利用这数据微调,没有使用验证数据集,就最后使用测试集来看看效果。 代码 train.py import json import torch from transformers import BertTokenizer, BertForNextSentencePrediction from torch.utils.data import DataLoader, Dataset # 能用gpu就用gpu # device = torch.device("cuda" if torch.cuda.is_available() else "cpu") device = torch.device("cpu") bacth_size = 32 epoch = 3 auto_save_batch = 5000 learning_rate = 2e-5 # 准备数据集 class MyDataset(Dataset): def __init__(self, data_file_paths): self.

Excel MATCH函数 两张顺序不同表格,统一排序

目录 一. 背景二. 添加辅助列,使用MATCH函数生成排序条件三. 效果 一. 背景 有如下图所示的两张表格,分别记录着同一批人的1月份和2月份的工资。表格A和表格B中的姓名列相同,工资列数据不同现在要求参考表格A中的姓名列对表格B中的数据进行排序, 即同一姓名的人在同一行上。 二. 添加辅助列,使用MATCH函数生成排序条件 ⏹ 基本语法 lookup_value:待查找的值lookup_array:待匹配的范围match_type:指定匹配的类型 1:小于-1:大于0:精确匹配 MATCH(lookup_value, lookup_array, [match_type]) ⏹添加辅助列,使用MATCH函数查找表格B中的姓名在表格A中的INDEX =MATCH(E3,$B$3:$B$11,0)可以使用F4键,让B3:B11由相对定位变为绝对定位 三. 效果 ⏹可以看到,通过辅助列的Index,两个表格的排序已经相同

深入了解Kafka的文件存储原理

Kafka简介 Kafka最初由Linkedin公司开发的分布式、分区的、多副本的、多订阅者的消息系统。它提供了类似于JMS的特性,但是在设计实现上完全不同,此外它并不是JMS规范的实现。kafka对消息保存是根据Topic进行归类,发送消息者称为Producer;消息接受者称为Consumer;此外kafka集群有多个kafka实例组成,每个实例(server)称为broker。无论是kafka集群,还是producer和consumer都依赖于zookeeper来保证系统可用性集群保存一些meta信息(kafka的0.8版本之后,producer不在依赖zookeeper保存meta信息,而是producer自己保存meta信息)。本文不打算对Apache Kafka的原理和实现进行介绍,而在编程的角度上介绍如何使用Apache Kafka。我们分别介绍如何编写Producer、Consumer以及Partitioner等。 Producer发送的消息是如何定位到具体的broker 生产者初始化:Producer在初始化时会加载配置参数,并开启网络线程准备发送消息。拦截器逻辑:Producer可以设置拦截器来预处理消息,例如,修改或者丰富消息内容。序列化:Producer将处理后的消息key/value进行序列化,以便在网络上传输。分区策略:Producer会根据分区策略选择一个合适的分区,这个分区策略可以是轮询、随机或者根据key的哈希值等。选择Broker:Producer并不直接将消息发送到指定的Broker,而是将消息发送到所选分区的leader副本所在的Broker。如果一个主题有多个分区,这些分区会均匀分布在集群中的Broker上。每个分区都有一个leader副本,Producer总是将消息发送到leader副本,然后由leader副本负责同步到follower副本。发送模式:Producer发送消息的模式主要有三种:发后即忘(不关心结果),同步发送(等待结果),以及异步发送(通过Future对象跟踪状态)。缓冲和批量发送:为了提高效率,Producer会先将消息收集到一个批次中,然后再一次性发送到Broker。可靠性配置:Producer可以通过设置request.required.acks参数来控制消息的可靠性级别,例如,设置为"all"时,需要所有in-sync replicas都确认接收后才认为消息发送成功。失败重试:如果请求失败,Producer会根据配置的retries参数来决定是否重试发送消息。 Kafka的Producer通过一系列步骤来确定消息的发送目标,其中分区策略和leader副本的选择是关键步骤,确保了消息能够正确地发送到相应的Broker。同时,通过合理的配置和重试机制,Producer能够保证消息的可靠性和系统的健壮性。 Kafka存储文件长什么样 在kafka集群中,每个broker(一个kafka实例称为一个broker)中有多个topic,topic数量可以自己设定。在每个topic中又有多个partition,每个partition为一个分区。kafka的分区有自己的命名的规则,它的命名规则为topic的名称+有序序号,这个序号从0开始依次增加。 在每个partition中有可以分为多个segment file。当生产者往partition中存储数据时,内存中存不下了,就会往segment file里面存储。kafka默认每个segment file的大小是500M,在存储数据时,会先生成一个segment file,当这个segment file到500M之后,再生成第二个segment file 以此类推。每个segment file对应两个文件,分别是以.log结尾的数据文件和以.index结尾的索引文件。 具体来说,Kafka中的每个分区(Partition)由一个或多个Segment组成。每个Segment实际上是磁盘上的一个目录,这个目录下面会包含几个特定的文件: .log文件:这是真正存储消息数据的地方。每个Segment有一个对应的.log文件,它存储了属于这个Segment的所有消息。.index文件:索引文件,用于快速定位到.log文件中的具体消息。通过.index文件可以高效地查找消息所在的.log文件位置。.timeindex文件(可选):如果启用了时间戳索引,还会有这个文件。它用于按时间戳高效检索消息。 此外,Segment作为Kafka中数据组织的基本单位,设计成固定大小,这样做可以方便地进行数据的清理和压缩,同时保证性能。当一个Segment文件写满后,Kafka会自动创建一个新的Segment来继续存储数据。旧的Segment文件在满足一定条件(如被消费且达到一定的保留期)后会被删除,释放磁盘空间。 每个segment file也有自己的命名规则,每个名字有20个字符,不够用0填充。每个名字从0开始命名,下一个segment file文件的名字就是上一个segment file中最后一条消息的索引值。在.index文件中,存储的是key-value格式的,key代表在.log中按顺序开始第条消息,value代表该消息的位置偏移。但是在.index中不是对每条消息都做记录,它是每隔一些消息记录一次,避免占用太多内存。即使消息不在index记录中在已有的记录中查找,范围也大大缩小了。 Consumer如何消费数据 Kafka中的Consumer通过以下步骤来消费数据: 创建消费者实例:需要创建一个消费者实例,并指定一些关键配置,如消费者所属的群组、Topic名称以及与服务器通信的相关设置。订阅主题:创建好的消费者实例需要订阅一个或多个主题,以便开始接收消息。拉取数据:与一些消息系统采用的推送模式不同,Kafka的消费者采用的是“拉取”模式。这意味着消费者需要主动从Broker拉取数据,而不是等待Broker将数据推送过来。这种模式使得消费者可以根据自身处理能力来控制数据的获取速度。长轮询机制:在没有新消息可消费时,消费者会使用长轮询机制等待新消息到达。消费者调用poll()方法时可以设置超时时间(timeout),这样如果没有新消息,消费者会在等待一段时间后返回,并在下次调用poll()时继续尝试获取新消息。提交偏移量:消费者在消费过程中会跟踪每个分区的消费进度,即偏移量(offset)。当消费者处理完消息后,它会提交当前的偏移量到Broker,以便在服务重启或故障恢复的情况下可以从准确的位置继续消费数据。故障恢复:如果消费者发生宕机等故障,由于Kafka会持久化消费者的偏移量信息,消费者可以在恢复后继续从之前提交的偏移量处消费数据,确保不丢失任何消息。消费者群组:Kafka支持多个消费者组成一个群组共同消费一个主题。在一个群组内,每个消费者会被分配不同的分区来消费,从而实现负载均衡和横向伸缩。同一个分区不能被一个群组内的多个消费者同时消费。数据处理:消费者在拉取到数据后,可以根据自己的业务逻辑对数据进行处理,比如进行实时流处理或者存储到数据库中进行离线分析。 综上所述,Kafka的Consumer通过上述流程高效地从Broker拉取并处理数据,这些特性使得Kafka能够在高吞吐量和可扩展性方面表现出色,适合处理大规模数据流的场景。 Kafka中的过期数据处理机制 kafka作为一个消息中间件,是需要定期处理数据的,否则磁盘就爆了。 处理的机制 根据数据的时间长短进行清理,例如数据在磁盘中超过多久会被清理(默认是168个小时) 根据文件大小的方式给进行清理,例如数据大小超过多大时,删除数据(大小是按照每个partition的大小来界定的)。 删除过期的日志的方式 Kafka通过日志清理机制来删除过期的日志,主要依赖于两个配置参数来实现这一功能: 日志保留时间:通过设置log.retention.hours参数,可以指定日志文件的保留时间。当日志文件的保存时间超过这个设定值时,这些文件将被删除。日志清理策略:Kafka支持两种日志清理策略,分别是delete和compact。delete策略会根据数据的保存时间或日志的最大大小来进行删除。而compact策略则是根据消息中的key来进行删除操作,通常用于特定类型的主题,如__consumer_offsets。 此外,在Kafka 0.9.0及更高版本中,日志清理功能默认是开启的(log.cleaner.enable默认为true)。这意味着Kafka会自动运行清理线程来执行定时清理任务。 综上所述,Kafka通过结合保留时间和清理策略的配置,实现了对过期日志的有效管理。这些机制确保了系统资源的合理利用,同时避免了因日志无限增长而导致的潜在问题

CDN技术解析:构建快速、可靠的内容分发网络

关注公众号:“DevOps实战派”,获取更多DevOps和运维的精彩内容。 在今日的世界中,互联网已经与人们的生活密不可分,诸如电商、门户网站、直播、游戏等业务都有着广泛的受众。对于这类业务而言,网络的稳定性和速度往往会成为影响用户体验的关键因素之一。因此,如何高效地将内容传输到用户端,也成为了各家公司一个必须解决的问题。 幸运的是,CDN(内容分发网络)技术应运而生,并为解决这一难题提供了一种强大的解决方案。 本文将探讨关于CDN技术的工作原理等相关知识点,带你深入了解这项技术。 一. 互联网业务的难题 举个例子:假设现在用户需要获取网站中某个视频资源,在没有CDN的情况下,所有的用户请求都需要到源站处理,并从源站下载资源。 在这种场景下会带来几个问题: 1. 跨运营商的网络影响 当前全国除三大运营商外,还有各地大大小小的运营商。在跨运营商的网络互访过程中,往往会出现较大的延迟,从而带来网络性能的下降; 2. 跨地域的距离影响 互联网业务往往是面向全国甚至更大范围内的用户,而随着用户到源站距离的增加,数据的往返时间也会随着增加,并可能影响到用户的使用体验; 3. 用户访问的压力影响 当大量的用户请求都通过源站进行处理时,无疑会给源站点带来巨大的压力,严重的情况下甚至可能压垮站点。 综上所述,在没有CDN的情况下,互联网业务将会面临诸多挑战,包括性能、网络等方面带来的的麻烦。而CDN则是解决这一系列麻烦的关键能力,也是提升网站整体运行效率和用户体验的重要法宝。 二. CDN的解决方案 对于CDN,在百度百科中有如下解释: CDN(Content Delivery Network)中文名为内容分发网络,是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。 如果用一句简单的话来概括,那就是CDN让用户实现了对资源的就近访问,从而达到最优的访问效率。 在使用CDN的场景中,CDN会将源站的静态资源(如图片、视频、CSS和JavaScript文件等)存储在位于各地的边缘节点上,这些服务器距离用户更近,可以更快地响应用户请求。当用户对资源进行请求时,将根据调度策略分配到最合适的边缘节点进行获取,从而获得最优的访问体验。 三. CDN的工作原理 在不使用CDN的场景下,我们通常是在DNS上配置业务域名的A记录,即将域名解析到源站IP。此时,当客户端解析域名时,将会从DNS获取到源站的服务器IP,并进行访问请求。 而在使用CDN后,源站域名解析将配置为Cname,即将域名解析到CDN域名,并最终由CDN厂商的GSLB来分配IP。此时,整体的访问流程变成如下所示,客户端将获取到CDN节点的IP,并进行资源访问。 CDN的加速功能实现,主要由GSLB(全局负载均衡器)与缓存系统两个主要功能系统来处理。 1. GSLB GSLB系统可以基于智能的DNS技术来实现,相比于传统DNS具有功能更加强大、更加智能的特点。GSLB根据预先配置好的策略,为用户分配最适合的节点地址。 2. 缓存系统 缓存系统最基本的工作单元就是许许多多的Cache节点(缓存服务器),Cache节点负责直接响应最终用户的访问请求,把缓存在本地的内容快速提供给用户。同时 ,Cache节点也会与源站进行内容同步,把更新的内容以及本地没有的内容从源站点获取并保存在本地。 四. CDN的应用场景 1. 网站加速 主要针对门户网站、电商等业务场景,如网易、淘宝等站点。这类站点往往有着非常多的的静态内容文件(文本、图片等),CDN可对其进行加速处理,从而显著改善页面响应时间,提升用户的使用体验。 2. 文件下载加速 文件下载加速是CDN的一项重要功能,常见的场景有软件补丁包发布、游戏安装包获取等,这类文件容量大,下载的过程中容易给源站带来性能和带宽压力。通过CDN的方式,可以有效分担这些压力,并提高客户端的下载效率。 3. 流媒体加速 流媒体加速的方式是通过将流媒体内容推送到离用户最近的边缘节点,使得用户可以就近获取内容,从而提高视频观看质量,源站点网络的流量。流媒体加速包含直播和点播两种,此类模式适用于各类音视频网站和应用,如:抖音、爱奇艺等。 4. 全站加速 主要针对动态内容较多的站点,通过智能路由、协议优化等动态加速技术,提升客户端到源站的网络效率,便于快速获取动态资源。 附录:CDN相关术语 加速域名:指使用CDN加速服务的域名。 边缘节点:提供给用户就近访问的缓存服务器。 命中率:CDN为静态文件提供加速的方式主要通过缓存技术来实现,当客户端请求到达CDN节点时,如果请求的内容文件已缓存,则会直接在缓存获取并返回给客户端。如果没有缓存的情况,CDN节点则是回到源站去拉取文件。命中率代表客户的请求命中CDN缓存的比例。 回源:在没有命中缓存的情 况下,CDN节点将返回源站获取资源,这个过程称为回源。 预热:提前将指定资源加载到CDN服务器。 刷新:删除CDN节点上缓存的资源,当用户访问对应资源时,直接回源接取新资源返回组用户,并重新缓存。

Linux 查询端口被占用命令

Linux 查询端口被占用命令 1、lsof -i:端口号 用于查看某一端口的占用情况,比如查看8000端口使用情况,lsof -i:8000 lsof -i:8080:查看8080端口占用 lsof abc.txt:显示开启文件abc.txt的进程 lsof -c abc:显示abc进程现在打开的文件 lsof -c -p 1234:列出进程号为1234的进程所打开的文件 lsof -g gid:显示归属gid的进程情况 lsof +d /usr/local/:显示目录下被进程开启的文件 lsof +D /usr/local/:同上,但是会搜索目录下的目录,时间较长 lsof -d 4:显示使用fd为4的进程 lsof -i -U:显示所有打开的端口和UNIX domain文件 # 使用 kill -9 【pid】 结束进程 2、netstat -tunlp |grep 端口号,例如查看指定8080端口: 用于查看指定的端口号的进程情况,如查看8080端口的情况,netstat -tunlp |grep 8080 常用命令: netstat -ntlp //查看当前所有tcp端口 netstat -ntulp | grep 80 //查看所有80端口使用情况 netstat -ntulp | grep 3306 //查看所有3306端口使用情况 参数介绍: -t (tcp) 仅显示tcp相关选项 -u (udp)仅显示udp相关选项

STM32 | 零基础 STM32 第一天

零基础 STM32 第一天 一、认知STM32 1、STM32概念 STM32:意法半导体基于ARM公司的Cortex-M内核开发的32位的高性能、低功耗单片机。 ST:意法半导体 M:基于ARM公司的Cortex-M内核的高性能、低功耗单片机 32:32位单片机 2、STM32开发的产品 STM32开发的产品:无人机、扫地机器人、3D打印机、平衡机、智能手环等 3、学习STM32对应的招聘职位 招聘职位:单片机开发工程师、单片机软件工程师、STM32开发工程师、嵌入式开发工程师、嵌入式软件工程师。 二、ARM与STM32 嵌入式系统 以应用为中心,以计算机技术为基础,软硬件可裁减,以适应应用系统对功能、可靠性、成本、体积和功耗等有严格要求的专用计算机系统。(笔试) 嵌入式系统的特性 硬件特性 体积小、集成效率高。 面向特定的应用。 功耗低、电磁兼容性好。 软件特性 嵌入式软件的开发与硬件紧密相关。 软件代码要求高效率和高可靠性。 软件一般固化在Flash或Rom中。 软件系统具有高实时性。 一般采用C语言开发。 1、ARM与STM32 ARM--Advanced RISC Machine ARM是英国一家电子公司的名字 ARM敢为天下先,首创了chipless的生产模式,即该公司既不生产芯片,也不设计芯片,而是设计出高效的IP(知识产权)内核,授权给半导体公司使用。 ARM提供一系列内核、体系扩展、微处理器和系统芯片方案 ARM是一种通用的32位RISC处理器 ARM是一种功耗很低的高性能处理器 ARM芯片四大内核:Cortex-X1、Cortex-A、Cortex-R、Cortex-M ARM Cortex™-A 系列为应用型处理器 ARM在Cortex-A系列处理器大体上可以排序为: Cortex-A78处理器、 Cortex-A77处理器、 Cortex-A76处理器、 Cortex-A57处理器、 Cortex-A53处理器、 Cortex-A15处理器、 Cortex-A9处理器、 Cortex-A8处理器、 Cortex-A7处理器、 Cortex-A5处理器、 ARM11处理器、 ARM9处理器、 ARM7处理器 产品:手机、平板、电视、智能音箱等 ARM Cortex-R为实时处理器 要求可靠性、高可用性、容错功能、可维护性和实时响应的嵌入式系统提供高性能计算解决方案。 高性能:与高时钟频率相结合的快速处理能力 实时:处理能力在所有场合都符合硬实时限制 安全:具有高容错能力的可靠且可信的系统 经济:可实现最佳性能、功耗和面积的功能。 ARM Cortex™-M处理器系列 ARM Cortex™-M处理器系列是一系列可向上兼容的高能效、易于使用的处理器,帮助开发人员满足将来的嵌入式应用的需要。用更低的成本提供更多功能、不断增加连接、改善代码重用和提高能效。 功耗更低 代码更小 使用更方便

sqlserver 改变decimal 精度

遇到需要修改精度的业务场景: 可能是数据库存的精度和小数位太多,需要减少: 比较全能的CAST转换: CAST(你的字段 AS DECIMAL(38,10)) ↓ CAST(你的字段 AS DECIMAL(38,2)) 在 SQL Server 中,decimal 数据类型通常使用两个参数来定义其精度和小数位数。这两个参数分别是 precision(精度)和 scale(小数位数),它们以如下格式表示:decimal(precision, scale)。 Precision(精度):表示数字的总位数,即包括小数点前后的所有数字位数。Scale(小数位数):表示小数点后面的位数,即小数部分的位数。 例如,在 decimal(10, 2) 中: Precision(精度)为 10,表示这个数值可以存储的总位数为 10 位。Scale(小数位数)为 2,表示小数点后面可以存储的位数为 2 位。

PYTHON+EXCEL学习笔记1:glob查找

开始学习台湾知名IT作家洪锦魁的新书《python玩转excel,轻松实现高效办公》的书。 glob模块可以列出特定文件夹的内容(不包括子文件夹),可以使用通配符*,比如: # ch1_7.py import glob print("方法1:列出\\Python\\ch1文件夹的所有Excel档案") for file in glob.glob('D:\\Python_Excel\\ch1\*.xlsx'): print(file) print("方法2:列出目前文件夹的Excel档案") for file in glob.glob('*.xlsx'): print(file) print("方法3:列出目前文件夹out1开头的Excel档案") for file in glob.glob('out1*.xlsx'): print(file) print("方法4:列出目前文件夹out1_开头的Excel档案") for file in glob.glob('out1_?.xlsx'): print(file) 比如列出目前文件夹中所有OUT开头的EXCEL文件 files = glob.glob('out1*.xlsx') for file in files: wb = openpyxl.load_workbook(file) print(f'下载 {file} 成功') print(f'{file} = {wb.sheetnames}') 又比如可以根据关键词查找工作簿: key = input('请输入关键词 : ') keyword = '*' + key + '*.xlsx' # 组成关键词的字符串 files = glob.glob(keyword) for fn in files: print(fn)

【自然语言处理五-注意力其他--多头注意力&位置编码等】

自然语言处理五-self attention的其他问题(多头注意力&位置编码)等 多头注意力 multi-head attention多头注意力的意义是什么?多头注意力的运作流程 位置编码postion encoding 之前用四篇博客说明了注意力以及自注意力的运作流程,下面来介绍剩余点。 多头注意力、位置编码 多头注意力 multi-head attention 单头的注意力是这样的: 而多头的矩阵是这样的: 也就是说我们由输入生成的q k v矩阵是多组,上面的图就显示2头注意力的示意图。 多头注意力的意义是什么? 事物之间的关系,往往不止一种,多头就意味着多种不同类型的相关性 多头注意力的运作流程 单头的注意力的过程是这样的: 而多头的注意力,计算注意力分数、softmax等操作都是相同的,只不过会有两次这样的操作,最终每一个输入对应的bi会生成多个,以两头注意力为例子: 第一次生成bi,1,第二次生成bi,2,下面是示例了生成bi,2的过程: 而注意力层最终的输出是将(bi,1,bi,2)又做了一次矩阵乘法 整体注意力层对外的输出的bi就整合了多头(bi,1,bi,2)的信息了。 位置编码postion encoding 前面讲的自注意力其实缺少了一部分,没有任何关于位置的信息。 但是在自然语言处理领域,位置信息有时候很重要,比如词性识别的时候,动词在开头的概率一般很小。因此self attention中又加入了位置信息编码: postion encoding,具体的做法就是在输入加上一个位置信息向量ei,Q K V的信息中就包括了位置的信息,如下图: 这个ei的生成有多重方法: 1.transformer论文中 用sin和cos的函数 2.手动设置 3.其他。在其他的论文中还有很多种做法

PMOS 应用电路

用MOS做高侧开关时,PMOS比NMOS更便于控制: 1、不用额外的电荷泵升压; 2、只要将栅极拉低和置高就能控制通断。随着半导体工艺的进步,PMOS在导通内阻上的参数也逐渐好转,使得PMOS在电流不是特别大、对压降不是特别敏感的高侧开关场合,拓宽了应用。 PMOS防电源反接 上述两张图的电路可用于防电源反接,但不防电源倒灌,来分析这个电路: 1、电源从左侧正常输入时: 当VCC有效时,PMOS的体二极管率先导通,随后S极的电压由先前的0V变成了(VCC-0.7),此时Vgs = 0 -(VCC-0.7)= -VCC+0.7。 一般PMOS的G极导通阀值为-1~2V,而绝大多数的电源电压差都要超过这个值。故Vgs超出G极导通阀值,Q1完全导通。 随着Q1完全导通,Q1的DS两端的电位差被拉低到 (此时的导通内阻 x 流过的电流),这个值一般都很小,远小于0.7V,Q1的体二极管被短路关断,并且Q1持续导通。 之后VCC向负载正常供电。负载的电压取决于MOS的压降,压降为 MOS的导通内阻 x DS电流。较小的导通内阻可获得很低的压降、很低的发热、很高的负载效率。 因为MOS的导通内阻通常为几mΩ~几十mΩ,在几A的电流下压降仅仅0.0x ~ 0.xV,比肖特基二极管的0.3V更为高效。(并且二极管的压降并不是固定的,根据二极管的特性曲线得知,电流越大压降也会变得越大,所以现在的高效率电路都在用MOS来替代二极管,如DCDC的同步整流方案:省略了外部的二极管,降低了整体发热,提高了输出效率,提高了可输出电流,便于集成为单芯片转换器,减少了占地面积) 因为MOS的开通速度非常迅速,所以不用担心体二极管因电流过大造成损坏,器件的电流上升都有一个过程,而在过程刚开始的几ns,可能PMOS就已完全导通,体二极管之后就会被短路关断。 注意:图上的稳压管D1,是为了防止VCC>12V,造成MOS的G极损坏。分析电路时,可去掉稳压管来分析。 2、VCC和GND反接,电路保护: 因为Q1的体二极管反接,始终处于关断状态,即使负载为0Ω的通路,S极的电位也始终保持与G极相等,Q1始终处于关断状态。电路关断,起到电源反接保护的作用。 固态继电器电路(防倒灌,需要一个I/O额外控制开关) 通过增加一控制I/O,控制开通。并且能在主动关断时,防止倒灌。 如上这个电路,这个电路广泛使用在 电源管理、充电控制上。 这个电路好就好在它是个双向开关,而且可完全控制开通/关断,完全可以替代机械继电器来做固态继电器(前提是输入的信号电压不能太低,起码超出PMOS的G极导通电压范围)。 下面来分析原理: CONTROL电平为高,电路开通,双向导通: 如CONTROL电平为高,则Q4 NMOS开通,Q2、Q3的G极电位均被拉低到0V。 Q2的体二极管率先导通,Q2的S极电平为VCC-0.7V,因为G极电平为0,所以满足开通条件,Q2完全导通。 而Q3此时的S极与Q2的S极相连,电位相同,均为VCC。并且G极电平为0,也满足开通条件,Q3也完全导通。之后VCC向负载正常供电。 反过来,如果VCC=0,而负载是电压源,也同样导通,只不换成了Q3的体二极管先导通,然后再轮到Q2。 CONTROL电平为低,电路完全关断: CONTROL电平为低,Q2、Q3都会被关断,并且R2持续上拉,保持Vgs=0,两个PMOS全部处于完全关断状态。并且因为Q2、Q3的体二极管是反向串联的,所以无论从左还是从右侧,流经DS的电流只有反向漏电流,几乎是没有的。

python实战项目 学生管理系统

目录 前言: 1学生管理系统项目重要性: 1.1教育管理效率提升 1.2数据驱动的决策支持 1.3实践编程和软件开发技能 1.4理解面向对象编程(OOP) 1.5学习项目管理和团队合作 1.6提升问题解决能力 2.项目背景 3.项目目标 4.技术选型 5.开发环境 5.学习收益 6.代码实现 6.1student.py 6.1.1代码实现: 6.1.2代码详细解析: 6.1.2.1封装学生信息 6.1.2.2提供初始化学生信息的方法 6.1.2.3定义学生信息的字符串表示 6.1.2.4示例用途 6.2 managersystem.py 6.2.1代码实现 6.2.2代码详细解析 6.2.2.1 __init__方法 6.2.2.2 run方法 6.2.2.3 show_menu静态方法 6.2.2.4学员信息管理方法 6.2.2.5系统功能流程 6.3 main.py 6.3.1代码实现 6.3.2代码详细解析 致谢: 前言: 在构建一个学生管理系统的实战项目中,我们将通过Python语言来实现一个简单但功能完备的系统。这个项目旨在帮助开发者理解和掌握Python编程的基础知识,同时学习如何设计和实现一个实际应用程序。在这个过程中,我们会涉及到数据结构、面向对象编程、文件操作等多个重要的编程概念。 1学生管理系统项目重要性: 1.1教育管理效率提升 学生管理系统能够有效地管理学生信息、成绩、考勤以及其他相关数据,极大地减少了手工操作的需求,提升了数据处理的速度和准确性。这对于教育机构来说是一个巨大的进步,因为它可以释放教职工的时间,让他们更多地专注于教学和学生发展。 1.2数据驱动的决策支持 通过集中管理和分析学生数据,学生管理系统可以为校方提供数据支持,帮助他们做出更加科学和合理的决策。例如,通过分析成绩数据,学校可以识别出需要额外支持的学生或课程,并据此调整教学资源的分配。 1.3实践编程和软件开发技能 对于开发者而言,参与学生管理系统的设计和开发是一种宝贵的学习经历。这个项目不仅需要运用到编程语言知识,还包括数据库管理、前端与后端开发、用户界面设计等多个方面。这为开发者提供了一个全面实践软件开发技能的机会。 1.4理解面向对象编程(OOP) 学生管理系统项目通常涉及到复杂的数据模型和业务逻辑,这要求开发者使用面向对象的编程方法来组织代码。通过这样的项目实践,开发者可以深入理解OOP的概念,如类、对象、继承、封装和多态等。 1.5学习项目管理和团队合作 在大型的学生管理系统项目中,开发者需要学习如何在团队环境中工作,包括使用版本控制系统(如Git)、遵循编码标准、进行有效的沟通和协作等。这些技能对于任何希望在IT行业发展的人来说都是极其重要的。 1.6提升问题解决能力 在设计和开发学生管理系统的过程中,开发者将面临各种问题和挑战,如性能优化、数据一致性保障、用户体验改进等。通过解决这些问题,开发者可以锻炼自己的问题解决能力和创新思维。 总之,学生管理系统项目不仅对于教育机构来说是一项重要的技术投资,对于参与项目的开发者来说也是一个提升专业技能、理论知识应用到实践中的绝佳机会。 2.项目背景 随着信息技术的快速发展,数字化管理已经成为各行各业的标准配置。在教育领域,有效地管理学生信息对于提高教育质量和学校管理效率具有重要意义。一个合理设计的学生管理系统可以帮助教师和管理人员快速获取学生信息,进行成绩管理,以及执行其他日常管理任务,从而大幅度提升工作效率和服务质量。 3.项目目标 本项目的目标是开发一个简单的学生管理系统,实现以下基本功能: 学生信息管理:包括添加新学生信息、查询学生信息、更新学生信息以及删除学生信息等功能。 成绩管理:允许输入、查询和修改学生的成绩信息。 数据持久化:系统应能够将数据保存到文件中,以便程序重启后数据不丢失。 用户交互界面:提供一个简洁友好的命令行界面,让用户能够方便地执行上述操作。 4.技术选型 由于本项目主要面向初学者,我们将使用Python标准库中的功能来实现大部分需求,避免引入复杂的外部依赖,使得项目更容易理解和实现。具体来说,我们会用到: 数据结构:利用列表(List)和字典(Dict)来存储学生信息和成绩数据。面向对象编程:设计学生(Student)类来封装学生信息和相关操作。文件操作:使用Python的文件操作API来实现数据的读写,以实现数据的持久化存储。 5.开发环境 编程语言:Python 3.x

SQL中把datetime 转为字符串

在 SQL 中,将 datetime 类型的数据转换为字符串可以使用不同的方法,具体取决于你使用的数据库系统。以下是一些常见数据库系统中将 datetime 转换为字符串的示例: 1. MySQL 在 MySQL 中,你可以使用 DATE_FORMAT() 函数将 datetime 转换为指定格式的字符串。例如,将 datetime 转换为 "YYYY-MM-DD HH:MM:SS" 格式的字符串: SELECT DATE_FORMAT(your_datetime_column, '%Y-%m-%d %H:%i:%s') AS formatted_date FROM your_table; 2. SQL Server 在 SQL Server 中,你可以使用 CONVERT() 函数将 datetime 转换为字符串。以下是一个示例: SELECT CONVERT(varchar, your_datetime_column, 120) AS formatted_date FROM your_table; 3. PostgreSQL 在 PostgreSQL 中,你可以使用 TO_CHAR() 函数将 datetime 转换为字符串。示例如下: SELECT TO_CHAR(your_datetime_column, 'YYYY-MM-DD HH24:MI:SS') AS formatted_date FROM your_table; 4. Oracle 在 Oracle 数据库中,你可以使用 TO_CHAR() 函数将 datetime 转换为字符串。示例如下:

黑马鸿蒙学习笔记1:TEXT组件

业余时间学习下黑马鸿蒙课程,主要截取重要的PPT学习: 其实就是用$r()的方法,去调用本地化资源文件,可以做多语言了。 比如每个语言目录下都有个string.json文件,然后用键值对name,value的方式搭配,然后 app.string.XXXXX(比如上图设置了键值是width_label), 直接用法就是Text(‘XXXXXX'),里面是要显示的文字就可以了。

18、ubutnu20.04使用RTX3060硬件进行视频编解码+推流

基本思想:先进行环境配置,系统环境如下 RTX3060 ubuntu 20.04 cuda 12.2 cudnn 11.3 NVIDIA-SMI 535.146.02 tensorRT 8.6 nv-codec-headers Video_Codec_SDK_12.0.16 注意:发现一个很有意思的问题,如果我使用命令行安装的ffmpeg,似乎已经有了nvidia编码器和解码器,完全不需要下面的操作似乎,我用代码也可以调用使用,这是没安装之前的环境配置 ubuntu@ubuntu:~$ ffmpeg -codecs | grep cuvid ffmpeg version 4.2.7-0ubuntu0.1 Copyright (c) 2000-2022 the FFmpeg developers built with gcc 9 (Ubuntu 9.4.0-1ubuntu1~20.04.1) configuration: --prefix=/usr --extra-version=0ubuntu0.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-nvenc --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared libavutil 56.

Java毕业设计基于springboot的仓库管理系统

一、项目介绍 信息内容数据从传统到当今,一直在改变,忽然互联网技术让传统信息内容管理见到划时代的黎明,由于传统信息内容管理从时效性、安全系数、可执行性等多个方面,碰到互联网时代发觉弥补了从古至今的缺陷,有效提升管理效率工作能力。在传统的管理模式中,时间越长,管理具体内容越大,需要更多人梳理数据,数据归纳查看高效率非常低,数据安全性从来不会确保安全系数。融合数据具体内容管理的缺陷,在互联网时代能够得到很好的填补。融合前沿的大数据技术,开发设计满足要求的app,使数据具体内容管理可以最大程度地提升准确率,管理更科学便捷,不论是输入时效性、查询的时效性或是梳理总结的时效性。库房管理系统进行了字典管理、公告管理、老师管理、物资供应管理、物资申请管理、学生管理、等服务。设备采用关联数据库里的MySQL做为全面的数据库,合理存放数据,合理备份数据,确保数据稳定性。除此之外,程序流程还具备程序流程所需要的所有功能,大大提升了实际操作安全度,使库房管理系统软件从概念迈向实际,真真正正提升了信息资源管理效率。 关键字:信息管理,时效性,安全性,MySQL 二、开发环境 开发语言:Java 框架:springboot JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包:Maven ———————————————— 三、功能介绍 在确认管理员功能模块基础上,设计方案管理员的每一个功能,明确管理员功能的具体控制模块。管理员功能构造见下图。 图4.3 管理员功能结构图 四、核心代码 部分代码: package com.example.controller; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.SecureUtil; import com.example.common.Result; import com.example.common.ResultCode; import com.example.entity.Caiwu; import com.example.exception.CustomException; import com.example.service.CaiwuService; import com.example.utils.MapWrapperUtils; import com.example.utils.jwt.JwtUtil; import com.example.vo.CaiwuVo; import org.springframework.beans.BeanUtils; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.List; import java.util.Map; @RestController @RequestMapping(value = "/caiwu") public class CaiwuController { @Resource private CaiwuService caiwuService; @PostMapping public Result<Caiwu> add(@RequestBody CaiwuVo caiwu) { caiwuService.

git 学习之暂存区撤销和修改

1. 暂存区 每个 Git 仓库中,都有一个隐藏目录 .git 用于存放 Git 仓库的相关信息,包括暂存区(称为 stage)、自动创建的 master 分支以及指向 master 分支的 HEAD 指针。 每次提交文件时: git add 添加文件到暂存区。git commit 提交更改,把暂存区的所有内容一次性全部提交到当前分支,清空暂存区。 2. 撤销修改 因为暂存区的存在,撤销修改分为几种情况(通过 git status 查看仓库状态时会提示相关撤销修改的命令): git status 一般有三个状态: changes to be committed -- 表示,已经提交到暂存区的文件,一般是 untracked files 根据 git add 提交上来的文件 changes not staged for commit -- 表示,即在工作区又在暂存区的文件,且文件在工作区被修改,还没有提交到暂存区 untracked files -- 表示,只在工作区,没有提交到暂存区的文件,不受版本控制,需要git add 提交到暂存区,之后为 changes to be committed 状态。 changes not staged for commit 和 untracked files 都是工作区修改,不同的是

「算法」常见位运算总结

位运算符 异或 按位异或可以实现无进位相加,所谓无进位相加,就是在不考虑进位的情况下将两个数相加(后面有道题需要用到这种操作) 异或的运算律 ①a ^ 0 = a ②a ^ a = 0 ③a ^ b ^ c = a ^ ( b ^ c ) 异或实现两数交换 这是一道面试题,要求不创建中间变量tmp,交换a和b int a = 1, b = 2; a ^= b; b ^= a; a ^= b; 这个交换挺有规律的,就两个数轮流异或对方,异或三次就完成交换 有符号右移>> 将一个数的所有位向右移动指定的位数,最高位用符号位填充无符号右移>>> 也是右移,不过最高位用0填充 基操 背景:给一个数 n,我们设它二进制表示的最低位的下标是 0 确定 n 二进制表示的第 x 位是0还是1 将 n 右移 x 位,然后和 1 按位与,若为 0,则第 x 位为0;反之为 1

【代码随想录python笔记整理】第十六课 · 出现频率最高的字母

前言:本笔记仅仅只是对内容的整理和自行消化,并不是完整内容,如有侵权,联系立删。 一、哈希表初步 在之前的学习中,我们使用数组、字符串、链表等等,假如需要找到某个节点,则都要从头开始,逐一比较,直到找到为止。为了能够直接通过要查找的记录找到其存储位置,我们选择使用哈希表实现此功能。哈希表其实就是通过一个关键码 key 的值而直接进行访问的数据结构。 哈希表的作用是快速判断一个元素是否出现在集合,它通过在关键码和存储位置之间建立一个确定的对应关系 F(key) ,使得每个关键字 key 对应一个存储位置,而这个对应关系,称之为散列函数(哈希函数)。哈希表来解决问题的时候,一般选择以下三种数据结构:数组、集合、映射。 二、最简单的一个数组案例 下面我们来看一个有哈希思想的程序案例,但实质上这个程序和哈希表的应用关系不大。主要是帮助我们理解哈希表是什么,它的核心思想是什么。 对于这个问题,我们可以这样想:想要找出出现频率最高的字母,我们至少需要遍历一遍整个字符串,因此尽可能在这一遍中完成所有任务。 为了实现这个目的,我们可以将26个字母按次序存储在一个数组中,而数组的索引和字母实现了一一对应,如果把 ASCLL 码和索引的关系写出来,那就是 ASCLL - 97 = 索引。这就是一种哈希函数。所以我们也常常把数组称为是最简单的一种哈希表。 接下来,我们在遍历过程中,将遇到的每个字符都记为出现 1 次,并将其对应索引的位置数值加一。在完成遍历后,显然我们还需要找出索引位置处数值最大的是哪个字符,以及出现了多少次。为实现这一步,我们又需要重新遍历一遍字符串。 三、代码展示 n = int(input()) for _ in range(n): s = input() # 创建一个 长度为26,元素都为0的列表 temp = [0] * 26 for char in s: # 计算字符在列表中对应的索引 a = ord(char) - ord('a') # 索引对应的值 + 1 temp[a] += 1 maxFreq = 0 maxFreqChar = -1 # 遍历列表,找到最大频率字符的索引 for i in range(26): if temp[i] > maxFreq: maxFreq = temp[i] # maxFreqChar为对应的索引 maxFreqChar = i # 根据索引转换对应的字符 res = chr(ord('a') + maxFreqChar) print(res) 四、总结 本节内容我们学习到了数组(列表)作为哈希表的使用,下节课我们会学习哈希表的另外一种形式`set集合`。