首页 文章 精选 留言 我的

精选列表

搜索[提高],共10005篇文章
优秀的个人博客,低调大师

【前瞻技术布局】打破"沙漏“现象→提高生成式搜索/推荐的上限

作者:京东零售 王彗木   东方若晓,莫道君行早  EMNLP 2024: Breaking the Hourglass Phenomenon of Residual Quantization: Enhancing the Upper Bound of Generative Retrieval paper链接: https://arxiv.org/abs/2407.21488v1 0 摘要 生成式搜索/推荐在搜索和推荐系统中已经成为一种创新的范式,它通过使用基于数值的标识符来提升效率和泛化能力。特别是在电子商务领域,像TIGER这样的方法使用基于残差量化的语义标识符(RQ-SID),表现出了很大的潜力。然而,RQ-SID面临一个被称为“沙漏”现象的问题,即中间码本令牌过于集中,限制了生成式搜索/推荐方法的全面发挥。本文通过研究发现,路径稀疏和长尾分布是造成这一问题的主要原因。我们通过一系列详细的实验和消融研究,分析了这些因素对码本利用率和数据分布的影响。结果表明,“沙漏”现象对RQ-SID的性能有显著影响。我们提出了一些有效的解决方案,成功改善了生成式任务在实际电子商务应用中的效果。 1 背景 在生成式搜索/推荐中,基于数值的标识符表示方法因其简单、高效和强大的泛化能力而在行业中被广泛采用,特别是在长行为序列推荐中。这些方法显著缩短了序列长度并加快了推理过程。值得注意的方法包括DSI、NCI、TIGER、GDR和GenRet。其中,TIGER方法通过残差量化(RQ)(Lee等,2022;Zeghidour等,2021)生成语义标识符(SID),有效捕捉了语义信息和层次结构。这种方法在以商品为主的电子商务场景中特别有优势,能够准确反映电子商务数据中固有的复杂层次关系和语义特征,从而显著提升推荐性能。 需要强调的是,基于RQ的方法的性能上限在很大程度上依赖于SID的生成,这也是本文分析和讨论的核心重点。 2 任务定义    基于现有常见的任务场景,定义如下任务【注意:任务形式不限于下列任务,只要是含有SID的任务均可】:该用户信息:年龄:age_2;性别:男性;会员状态:非会员。该用户的历史交互行为有:<xxx><xxx><xxx>,<xxx><xxx><xxx>……。该用户本次搜索的关键词为“XX鼠标”。请根据该用户信息、历史交互行为和本次搜索关键词,预测该用户接下来最可能购买的商品:<xxx><xxx><xxx> 3 RQ-VAE SID生成    SID生成,谷歌的TIGER方法用的比较广泛。它通过残差量化RQ生成语义标识符(SID),能够有效捕捉语义信息和层次结构。这种方法在以商品为主的电商场景中尤其有优势,因为它能够准确反映电商数据中的复杂层次关系和语义特征,从而显著提升推荐性能。 4 沙漏现象    在通过残差量化(RQ)生成的SID中,我们观察到了一种显著的“沙漏”现象。具体而言,中间层的码本过于集中,导致了一对多和多对一的映射结构。这种集中现象引发了路径的稀疏性和长尾分布问题。路径稀疏性是指匹配路径仅占总路径空间的一小部分,而长尾分布则意味着大多数SID集中在少数的头部标记上,中间层标记的分布呈现长尾特征。在具有长尾特征的数据集中,这种“沙漏”效应尤为明显,显著限制了生成式搜索推荐方法的表示能力。问题的根源在于逐步量化高维向量残差的内在特性。基于此,我们对该现象进行了深入的理论与实验分析,并提出了相应的解决方案。 4.1 沙漏现象可视化 为了生成语义ID,我们首先利用公司内部数十亿条搜索日志中的查询-商品数据,训练了双塔模型(如DSSM和BERT等)。接着,通过商品塔获取了数亿商品的嵌入向量,最终采用残差量化(RQ)方法为所有商品生成了语义ID。    生成语义ID后,对所有商品进行了聚合,并计算了三层分布图。如上图所示,可以看到第二层集中有大量路由节点,整体分布呈现“沙漏”现象。为了验证这一现象的普遍性,我们在不同参数组合下进行了多次可视化实验,沙漏效应非常显著,三层代码表中token的路径分布相对稀疏。    此外,基于上述实验,我们使用三个指标对第二层的标记分布进行了统计分析:熵、基尼系数和标准差,如图所示。结果表明,第二层的标记分布表现出低熵、高基尼系数和大标准差,表明该分布具有显著的不均匀性。 总体而言,这种沙漏现象在代码表中通过路径稀疏性和token的长尾分布得到了统计数据支持。其中, 路径稀疏性:语义ID结构导致代码表利用率低。 长尾分布:在中间层,大多数路径集中到单个token上 4.2 现象分析 为了探讨“沙漏”现象的成因,将基于残差量化(RQ)的运行机制进行深入分析和讨论。为了便于理解,考虑两种原始嵌入的分布:非均匀分布和均匀分布。接下来,使用RQ为数据X生成语义ID。    可以看到,第一层,候选点被分成M个聚类桶,token的入度相等。输入分布均匀。第二层输入为第一层的残差,分布非均匀。小残差点靠近聚类中心,异常值较大。聚类更关注异常值,形成长尾现象。第三层残差值变得一致且均匀。类似第一层的均匀分布。第二层大路由节点分散成多个小节点。整体趋势随层数增加,残差减小,聚类效应减弱。形成沙漏状结构:数据压缩再扩展,最终均匀分布。语义ID构建后,RQ量化方法的影响,加上中间层头部token的主导地位,自然导致了路径的稀疏性。类似地,对于非均匀分布(如长尾分布),残差分布变得更加不均匀,导致现象更加严重。 4.3 实际影响   为了评估这种现象的影响,我们进行了多项实验。首先,在评估过程中,我们根据第二层标记的分布将测试集分为两组:头部标记测试集和尾部标记测试集。如表所示,头部标记测试集的性能显著提升,而尾部标记测试集的性能则明显较差。这种性能差异可以归因于先前分析的路径稀疏性和标记的长尾分布,导致了结果的偏差。这一现象在不同规模的模型(如LLaMA2、Baichuan2和Qwen1.5)以及不同参数的残差量化(RQ)中均有观察到,突显出长尾标记分布和路径稀疏性对模型性能的广泛影响。 此外,为了进一步探讨“沙漏”现象对模型性能的影响,我们进行了两个关键实验:1)交换第一层和第二层的标记,2)将交换序列的第一个标记作为输入。 在仅交换第一层和第二层标记的情况下,第一层出现显著的长尾分布,导致模型难以拟合,从而效果较差。由于逐标记错误的累计,交换后的效果甚至比不交换更差。然而,当交换后给定第一个标记时,输出任务变为预测第二或第三层的SID,这使得任务变得更简单,并且长尾分布不再影响结果(因为给定了真实的SID1),因此效果显著提升。此外,在不交换第一层和第二层的条件下,给定第一个标记(第二层SID依旧是长尾分布),其结果高于基线,但低于交换后给出第一个标记的情况(如表所示)。 这一发现表明,“沙漏”现象对模型性能有着实质性的负面影响。通过上述实验,不仅确认了“沙漏”效应的存在,还阐明了其对模型性能的具体影响,从而为未来的优化提供了坚实的基础。 5 解决方法    解决沙漏现象的方法有多种,在此简单的从分布角度提出两种简单易行的方法:一种启发式的方法是直接移除第二层,从而消除长尾效应的影响。然而,这可能导致空间容量不足。需要注意的是,这里首先要生成一个L层的语义ID(SID),然后再移除第二层,这与直接生成一个两层的SID不同,因为后者可能仍然存在大的路由节点。另一种简单的方法是自适应地移除第二层的顶部tokens,使语义ID成为一个可变长度的结构。这里使用了top@K策略,并设定一个阈值p。这种方法确保了分布保持不变,同时有选择地减少了“沙漏”效应的影响。 为了进一步验证该方法的有效性,在LLaMA模型上进行了实验。结果表明,通过应用自适应token移除策略,模型性能得到了提升,同时计算成本与基础模型相近,并且在一些客观优化(如Focal Loss和Mile Loss)方面也表现出色。 具体来说,实验结果显示,使用top@400 token移除策略的模型在大多数评估指标上都优于基线模型。这表明该方法有效地减少了长尾效应的影响。随着移除的tokens数量增加,模型性能的提升会遇到瓶颈。特别是当所有tokens都被移除时,这种限制尤为明显,这可能是由于缺少长尾tokens,导致召回率下降。同时,直接移除第二层会导致一个SID对应多个项目。这种细粒度的分析为所提出方法的有效性提供了有力证据。该方法在选择性移除不太重要的tokens的同时,保留了最有信息量的tokens,即使在移除大量数据的情况下,也能提升模型性能。 6 结论 本研究系统地探讨了RQ-SID在生成式搜索/推荐的局限性,特别是发现了中间层tokens过度集中导致数据稀疏和长尾分布的“沙漏”现象。通过广泛的实验和消融研究,证明了这一现象,并分析了其根本原因在于残差特性。为了解决这个问题,提出了两种方法:移除第二层的启发式方法和自适应调整token分布的可变长度token策略。实验结果显示,两种方法都有效缓解了瓶颈效应,其中自适应token分布调整策略效果最佳。这是首次系统性地探讨RQ-SID在生成式搜索/推荐中缺陷的研究,为未来的模型优化提供了坚实的基础,并显著提升了模型性能。 7 未来规划 1、 优化SID的生产与表征方式,通过引入时效、统计类特征来辅助额外表征,让其能满足对特征极为看重的排序需求; 2、 统一稀疏表征(SID)与密集表征,让LLM可以显示的建模密集特征变化趋势,而不是稀疏表征的映射 3、 保证链路无损失实现一段式搜索。

优秀的个人博客,低调大师

文盘Rust——子命令提示,提高用户体验 | 京东云技术团队

上次我们聊到 CLI 的领域交互模式。在领域交互模式中,可能存在多层次的子命令。在使用过程中如果全评记忆的话,命令少还好,多了真心记不住。频繁 --help 也是个很麻烦的事情。如果每次按 'tab' 键就可以提示或补齐命令是不是很方便呢。这一节我们就来说说 'autocommplete' 如何实现。我们还是以interactcli-rs中的实现来解说实现过程 实现过程 其实,rustyline 已经为我们提供了基本的helper功能框架,其中包括了completer。我们来看代码,文件位置src/interact/cli.rs #[derive(Helper)] structMyHelper{ completer:CommandCompleter, highlighter:MatchingBracketHighlighter, validator:MatchingBracketValidator, hinter:HistoryHinter, colored_prompt:String, } pubfnrun(){ letconfig=Config::builder() .history_ignore_space(true) .completion_type(CompletionType::List) .output_stream(OutputStreamType::Stdout) .build(); leth=MyHelper{ completer:get_command_completer(), highlighter:MatchingBracketHighlighter::new(), hinter:HistoryHinter{}, colored_prompt:"".to_owned(), validator:MatchingBracketValidator::new(), }; letmutrl=Editor::with_config(config); //letmutrl=Editor::<()>::new(); rl.set_helper(Some(h)); ...... } 首先定义 MyHelper 结构体, 需要实现 Completer + Hinter + Highlighter + Validator trait。然后通过rustyline的set_helper函数加载我们定义好的helper。在MyHelper 结构体中,需要我们自己来实现completer的逻辑。 Sub command autocompleter实现详解 SubCmd 结构体 #[derive(Debug,Clone)] pubstructSubCmd{ publevel:usize, pubcommand_name:String, pubsubcommands:Vec<String>, } SubCmd 结构体包含:命令级别,命令名称,以及该命令包含的子命令信息,以便在实现实现 autocomplete 时定位命令和子命令的范围 在程序启动时遍历所有的command,src/cmd/rootcmd.rs 中的all_subcommand函数负责收集所有命令并转换为Vec<SubCmd> pubfnall_subcommand(app:&clap_Command,beginlevel:usize,input:&mutVec<SubCmd>){ letnextlevel=beginlevel+1; letmutsubcmds=vec![]; foriterminapp.get_subcommands(){ subcmds.push(iterm.get_name().to_string()); ifiterm.has_subcommands(){ all_subcommand(iterm,nextlevel,input); }else{ ifbeginlevel==0{ all_subcommand(iterm,nextlevel,input); } } } letsubcommand=SubCmd{ level:beginlevel, command_name:app.get_name().to_string(), subcommands:subcmds, }; input.push(subcommand); } CommandCompleter 子命令自动补充功能的核心部分 #[derive(Debug,Clone)] pubstructCommandCompleter{ subcommands:Vec<SubCmd>, } implCommandCompleter{ pubfnnew(subcmds:Vec<SubCmd>)->Self{ Self{ subcommands:subcmds, } } //获取level下所有可能的子命令 pubfnlevel_possible_cmd(&self,level:usize)->Vec<String>{ letmutsubcmds=vec![]; letcmds=self.subcommands.clone(); foritermincmds{ ifiterm.level==level{ subcmds.push(iterm.command_name.clone()); } } returnsubcmds; } //获取level下某字符串开头的子命令 pubfnlevel_prefix_possible_cmd(&self,level:usize,prefix:&str)->Vec<String>{ letmutsubcmds=vec![]; letcmds=self.subcommands.clone(); foritermincmds{ ifiterm.level==level&&iterm.command_name.starts_with(prefix){ subcmds.push(iterm.command_name); } } returnsubcmds; } //获取某level下某subcommand的所有子命令 pubfnlevel_cmd_possible_sub_cmd(&self,level:usize,cmd:String)->Vec<String>{ letmutsubcmds=vec![]; letcmds=self.subcommands.clone(); foritermincmds{ ifiterm.level==level&&iterm.command_name==cmd{ subcmds=iterm.subcommands.clone(); } } returnsubcmds; } //获取某level下某subcommand的所有prefix子命令 pubfnlevel_cmd_possible_prefix_sub_cmd( &self, level:usize, cmd:String, prefix:&str, )->Vec<String>{ letmutsubcmds=vec![]; letcmds=self.subcommands.clone(); foritermincmds{ ifiterm.level==level&&iterm.command_name==cmd{ foriiniterm.subcommands{ ifi.starts_with(prefix){ subcmds.push(i); } } } } returnsubcmds; } pubfncomplete_cmd(&self,line:&str,pos:usize)->Result<(usize,Vec<Pair>)>{ letmutentries:Vec<Pair>=Vec::new(); letd:Vec<_>=line.split('').collect(); ifd.len()==1{ ifd.last()==Some(&""){ forstrinself.level_possible_cmd(1){ letmutreplace=str.clone(); replace.push_str(""); entries.push(Pair{ display:str.clone(), replacement:replace, }); } returnOk((pos,entries)); } ifletSome(last)=d.last(){ forstrinself.level_prefix_possible_cmd(1,*last){ letmutreplace=str.clone(); replace.push_str(""); entries.push(Pair{ display:str.clone(), replacement:replace, }); } returnOk((pos-last.len(),entries)); } } ifd.last()==Some(&""){ forstrinself .level_cmd_possible_sub_cmd(d.len()-1,d.get(d.len()-2).unwrap().to_string()) { letmutreplace=str.clone(); replace.push_str(""); entries.push(Pair{ display:str.clone(), replacement:replace, }); } returnOk((pos,entries)); } ifletSome(last)=d.last(){ forstrinself.level_cmd_possible_prefix_sub_cmd( d.len()-1, d.get(d.len()-2).unwrap().to_string(), *last, ){ letmutreplace=str.clone(); replace.push_str(""); entries.push(Pair{ display:str.clone(), replacement:replace, }); } returnOk((pos-last.len(),entries)); } Ok((pos,entries)) } } implCompleterforCommandCompleter{ typeCandidate=Pair; fncomplete(&self,line:&str,pos:usize,_ctx:&Context<'_>)->Result<(usize,Vec<Pair>)>{ self.complete_cmd(line,pos) } } CommandCompleter 的实现部分比较多,大致包括两个部分,前一部分包括:获取某一级别下所有可能的子命令、获取某级别下某字符串开头的子命令、获取某级别下某个命令的所有子命令,等基本功能。这部分代码中有注释就不一一累述。 函数complete_cmd用来计算行中的位置以及在该位置的替换内容。 输入项是命令行的内容以及光标所在位置,输出项为在该位置需要替换的内容。比如,我们在提示符下输入 "root cm" root 下包含 cmd1、cmd2 两个子命令,此时如果按 'tab'键,complete_cmd 函数就会返回 (7,[cmd1,cmd2])。 作者:京东科技贾世闻 来源:京东云开发者社区 转载请注明来源

优秀的个人博客,低调大师

APISIX-Datadog 插件发布,助力用户提高系统的可观测性

随着应用开发的复杂度增加,监控成为了应用的一个重要组成部分。及时、准确的监控既能满足快速迭代的周期性需求,又能够确保应用的稳定性和流畅性。如何选择一个适合的监控,以提升应用的可观测性,成为了每个开发者都必须面临的一道难题。 Apache APISIX 将监控和可观测性从应用中解耦了出来,给开发人员带来了一个优势:在构建应用的时候,只需要关注业务逻辑,而 Apache APISIX 可以和开发人员选定的监控平台对接,处理可观测性的问题。 Apache APISIX 最近发布了一个新的插件:APISIX-Datadog,以提供与 Datadog 监控平台的集成。这篇文章介绍了 APISIX-Datadog 插件的实现原理及功能。 APISIX-Datadog plugin 工作原理 APISIX-Datadog 插件将其自定义指标推送到 DogStatsD server。而 DogStatsD server 通过 UDP 连接与 Datadog agent 捆绑在一起。DogStatsD 是 StatsD 协议的一个实现。它为 Apache APISIX agent 收集自定义指标,将其聚合成一个数据点,并将其发送到配置的 Datadog server。要了解更多关于 DogStatsD 的信息,请访问 DogStatsD 文档1。 当你启用 APISIX-Datadog 插件时,Apache APISIX agent 会在每个请求响应周期向 DogStatsD server 输出以下指标: 这些指标将被发送到 DogStatsD agent,并带有以下标签。如果任何特定的标签没有合适的值,该标签将被直接省略。 APISIX-Datadog 插件维护了一个带有 timer 的 buffer。当 timer 失效时,APISIX-Datadog 插件会将 buffer 的指标作为一个批量处理程序传送给本地运行的 DogStatsD server。这种方法通过重复使用相同的 UDP 套接字,对资源的占用较少,而且由于可以配置 timer,所以不会一直让网络过载。 启动 Datadog Agent 如果你已经在使用 Datadog,你必须在系统中安装一个 Datadog agent。它可以是一个 docker 容器,一个 pod 或二进制的包管理器。你只需要确保 Apache APISIX agent 可以到达 Datadog agent 的 8125 端口。 如果需要了解更多关于如何安装一个完整的 Datadog agent,请访问这里2。 如果你从没使用过 Datadog 首先访问 www.datadoghq.com,创建一个账户。 然后按照下面演示的步骤生成一个 API 密钥。 APISIX-Datadog 插件只需要依赖 datadog/agent的 dogstatsd 组件即可实现,因为该插件按照 statsd 协议通过标准的 UDP 套接字向 dogstatsd server 异步发送参数。我们推荐使用独立的 datadog/dogstatsd 镜像,而不是使用完整的 datadog/agent ,因为 datadog/dogstatsd 的组件大小只有大约 11 MB,更加轻量化。而完整的 datadog/agent 镜像的大小为 2.8 GB。 运行以下命令,将它作为一个容器来运行: # 拉取datadog/dogstatsd的最新镜像 docker pull datadog/dogstatsd:latest # 运行容器 docker run -d --name dogstatsd-agent -e DD_API_KEY=<Your API Key from step 2> -p 8125:8125/udp datadog/dogstatsd 如果你在生产环境中使用 Kubernetes,你可以将 dogstatsd 作为一个 Daemonset 或多容器 Pod 与 Apache APISIX agent 一起部署。 如何在 Apache APISIX 中使用 Datadog 启用 APISIX-Datadog 插件 如果你已经启动了dogstatsd/agent,只需执行一条命令,就可以为指定路由启用 APISIX-Datadog 插件。 # 为指定路由启用 APISIX-Datadog 插件 curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "plugins": { "datadog": {} }, "upstream": { "type": "roundrobin", "nodes": { "127.0.0.1:1980": 1 } }, "uri": "/hello" }' 启用 APISIX-Datadog 插件后,任何对端点 URI /hello的请求都会产生上述指标,并推送到 Datadog agent 的本地 DogStatsD server。 自定义配置 如果启用 APISIX-Datadog 插件时,使用的是默认配置,dogstatsd 服务在127.0.0.1:8125可用。如果你想更新配置,请更新插件的元数据。 元数据参数解释 要了解更多关于如何有效地编写标签,请访问这里3。 向 /apisix/admin/plugin_metadata 端点发出请求,更新元数据,如下所示。 curl http://127.0.0.1:9080/apisix/admin/plugin_metadata/datadog -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "host": "127.0.0.1", "port": 8125, "constant_tags": [ "source:apisix", "service:custom" ], "namespace": "apisix" }' 插件参数解释 与元数据类似,在启用 APISIX-Datadog 插件时,你也可以调整其他参数。 由于所有的字段都是可选的,如果你没有手动设置任何参数,APISIX-Datadog 插件将使用默认值设置这些参数。如果你需要更新任何参数,只需用更新的参数值更新所需的路由、服务或消费者。例如,下面的代码将 batch_max_size修改为 10。 '{ ... "plugins": { "datadog": { "batch_max_size": 10 } } ... }' 停用 APISIX-Datadog 插件 你只需在插件配置中删除相应的 json 配置即可停用 APISIX-Datadog 插件。由于 Apache APISIX 插件是热加载的,因此删除 json 配置后,会立即停用 APISIX-Datadog 插件,不需要重新加载。 # 为指定路由停用 APISIX-Datadog 插件 curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "uri": "/hello", "plugins": {}, "upstream": { "type": "roundrobin", "nodes": { "127.0.0.1:1980": 1 } } }' [1]:https://docs.datadoghq.com/developers/dogstatsd/?tab=hostagent [2]:https://docs.datadoghq.com/agent/ [3]:https://docs.datadoghq.com/getting_started/tagging/#defining-tags

优秀的个人博客,低调大师

演讲稿: 如何使用增强现实技术提高应用的用户体验

这是Jerry在SAP成都研究院内部用英文做的一个演讲,这里把底稿分享给大家: With the accellerated evolution of mobile hardware, application developers tend to reconsider the importance of the Augmented Reality technology ( called AR for short in this article subsequently ) in regard to satisfy their customers better with enhanced user experience. What is AR? See one explanation from Wikipedia: Augmented re

优秀的个人博客,低调大师

Android开发实用必备的几款插件,提高你的开发速度

欢迎大家告诉我更加好用的插件,工具和第三方开源库 写代码酷炫 plugins下载activate-power-mode 一些设置 Window-->activate-power-mode 设置开发工具的背景 plugins下载 SexyEditor 便于开发的插件、工具和第三方开源库 1.GsonFormat 使用方法:快捷键Alt+S也可以使用Alt+Insert选择GsonFormat,作用:速将json字符串转换成一个Java Bean,免去我们根据json字符串手写对应Java Bean的过程。 2.ButterKnife Zelezny 又叫黄油刀 使用方法:Ctrl+Shift+B 作用:快速的绑定资源的id。和findViewbuId说再见。 3.Parcelable code generator 使用方法 alt+insert 选择Parcelable 作用 :JavaBean序列化,快速实现Parcelable接口。 4.Lifecycle Sorter 使用方法 :快捷键Ctrl + alt + K 作用:可以根据Activity或者fragment的生命周期对其生命周期方法位置进行先后排序 5.findBugs-IDEA 使用方法:左下角会出现findbugs的图标 ,查找bug的插件 6.JsonOnlineViewer 使用方法:点击下面的 view 视图功能中的 JsonOnlineViewer 作用:进行 get 或 post 接口的检测 7.LeakCanary 使用方法: 在主项目main模块的build.gradle文件中添加LeakCanary相关依赖 作用:在Debug版本中监控 Activity、Fragment等的内存泄露(也使用android Studio中AndroidMonitor自带的一个工具—>memory,这个工具也可以说是非常的好用,先简单的介绍一下,memory虽然不可以分析出哪部分存在泄漏等情况,但可以很直观的看到内存的占用情况,看到内存的动态变化) 8.bugly 使用方法:去腾讯申请,然后在工程中集成 作用及简介:异常上报,应用升级&热更新。 第三方开源库 ● okhttp3 网络请求类型 项目地址:https://github.com/open-android/OkHttp3Utils ● SmartRefreshLayout 下拉刷新 上拉加载 有很多样式动画 项目地址:https://github.com/scwang90/SmartRefreshLayout ● statusbarutil 沉浸式状态栏 项目地址:https://github.com/laobie/StatusBarUtil ● easypermissions 动态权限申请 项目地址:https://github.com/googlesamples/easypermissions ● ninegridview 九宫格控件 项目地址:https://github.com/jeasonlzy/NineGridView ● calendarview 精美日历 项目地址:https://github.com/huanghaibin-dev/CalendarView ● SwipeDelMenuLayout 左滑删除效果 项目地址:https://github.com/mcxtzhang/SwipeDelMenuLayout/blob/master/README-cn.md ● FlycoTabLayout_Lib 炫酷方便简洁的Tablayout 项目地址:https://github.com/H07000223/FlycoTabLayout ● PictureSelector 非常方便实用的图片选择器 项目地址:https://github.com/LuckSiege/PictureSelector ● IdentityImageView 一个头像圆角带进度条的图片框架,同时有身份标识动能,简单易用 项目地址:https://github.com/385841539/IdentityImageView 原文发布时间为:2018-11-25 本文来自云栖社区合作伙伴“Android开发中文站”,了解相关信息可以关注“Android开发中文站”。

优秀的个人博客,低调大师

OpenAI最新研究:通过无监督学习提高语言理解能力

我们的系统分为两个阶段:首先,我们通过无监督的方式在大数据集上训练一个迁移学习模型,训练过程中使用语言模型的训练结果作为信号,然后我们在更小的有监督数据集上对这个模型进行微调,以帮助它解决特定的任务。这个方法的开发是在我们前一个sentiment neuron(情绪神经元)的工作之后进行的,在sentiment neuron任务中我们注意到,通过利用足够的数据对模型进行训练,无监督学习可以获得令人惊讶的判别特征。在这里,我们想进一步探讨这个想法:我们能否开发一个模型,以一种无监督的方式使用大量数据对模型进行训练,然后对模型进行微调,以在不同的任务中都获得良好的性能?我们的研究结果表明,这种方法的效果出奇地好。同样的核心模型可以针对完全不同的任务进行微调,以适应任务。 本研究是基于在半监督序列学习中引入的方法,该方法展示了如何通过对L

优秀的个人博客,低调大师

几个提高工作效率的Python内置小工具

在这篇文章里,我们将会介绍4个Python解释器自身提供的小工具。这些小工具在笔者的日常工作中经常用到,减少了各种时间的浪费,然而,却很容易被大家忽略。每当有新来的同事看到我这么使用时,都忍不住感叹,原来Python还隐藏了这么好用的功能。下面就来看一下Python自带的几个小工具 一、1秒钟启动一个下载服务器 在实际工作中,时不时会有这样的一个需求:将文件传给其他同事。将文件传给同事本身并不是一个很繁琐的工作,现在的聊天工具一般都支持文件传输。但是,如果需要传送的文件较多,那么,操作起来就会比较麻烦。此外,如果文件在远程的服务器上,你要将文件传给同事,则需要先将远程服务器的文件下载到本地,然后再通过聊天工具传给同事。再或者,你并不是特别清楚要传哪几个文件给同事,所以,你们需要进行来回的交流。交流的时间成本是比较高的,会降低办事效率。

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。