【深度学习】90.94%准确率!谷歌刷新ImageNet新纪录!Model soups:提高模型的准确性和稳健性...

丰色 发自 凹非寺
转载自:量子位(QbitAI)

如何最大限度地提升模型精度

最近,谷歌等机构发现:

性能不好的微调模型先不要扔,求一下平均权重!

就能在不增加推理时间以及内存开销的情况下,提高模型的准确性和稳健性。

比如,研究人员就使用该方法创造了ImageNet1K的新纪录:90.94%。

d86fb72e5442c24ec34e63c7b2908690.png

将它扩展到多个图像分类以及自然语言处理任务中,也能提高模型的分布外性能,并改善新下游任务的零样本性能。

e457a5c239ff982b942a55e9afc06978.png

而这个方法还有一个有趣的名字,叫Module soup——

是不是让人一下子就让人联想到了斐波那契汤的笑话(昨天的汤+前天的汤=今天的新汤)

e01ae721803da2f7ffbf10f284f06973.png

 知乎网友@hzwer,已授权

一共三种配方

回想一下在此之前,大家是如何给模型涨点的呢?

是不是先用各种超参数训练出多个微调模型,然后再挑出验证集上表现最好的那一个留下,其余丢掉

由于神经网络是非线性的,在不同的loss basin中可能有许多解,因此Module soup这一采用保留所有微调模型的权重,对其进行平均的方法就可以提高性能,还是让人有点惊讶的。

不过,最近就已有研究发现,从相同的初始化配置中中独立优化的微调模型,位于相同的误差范围内 (lie in the same basin of the error landscape)。

之前也有研究证明,沿单个训练轨迹进行权重平均,可以提高随机初始化训练模型的性能。

作者正是从这些结论中受到启发。

Module soup一共有三种“配方”(实现):统一汤(uniform soup)、贪婪汤(greedy soup)和学习汤(learned soup)。

其中greedy soup是最主要采用的实现,因为它的性能比直接均匀地平均所有权重更高。

具体来说,Greedy soup通过顺序添加每个模型作为“汤”中的潜在成分构建而成,并且只有在保持验证集上的性能有所提高时才将相应模型保留在“汤”中。

排序按验证集精度的降序排列。

b228c38ca393be4ea5681e485d1eda77.png

性能超越单个最佳微调模型

作者进行了全面的微调实验来确定Module soup的有效性。

首先是微调CLIP和ALIGN,这两个模型在图像-文本对上进行了对比损失预训练。

结果经过module soup操作后,两者在分布内和自然分布转移(distribution shifts)测试集上的表现都比最佳的单个微调模型性能更佳。

640aa6a359b571c73c0816ffc8a95a89.png

 左为CLIP,右为ALIGN

然后是在JFT数据集上预训练的ViT-G模型。

也就是它在ImageNet1K数据集实现了90.94%的精度,打破了此前CoAtNet保持的90.88%,同时在推理阶段还减少了25%的FLOPs。

a1ca921a245dabb387b30bdfbe24168d.png

在图像分类任务以外,作者在NLP领域也对module soup进行了验证。

下表是BERT和T5模型在GLUE benchmark的四个文本分类任务上的结果:

c197d2ced3ba8604d026e81de84a3270.png

可以发现,虽然改进不如图像分类中的效果明显,但在多数任务下,greedy soup都可以相较最好的单个模型提高性能。

当然,作者也指出,module soup在适用性等方面存在局限,比如现在测试的都是在大型异构数据集上预先训练的模型,在这些模型之外,效果并不是非常明显。

最后,知乎网友@宫酱手艺人表示,其实这样的模型参数平均是一个经典trick,transformer原始论文就用了。

b7031e0025561d14e18540aea4e77e6b.png

你发现了吗?

论文地址:
https://arxiv.org/abs/2203.05482

知乎@宫酱手艺人、@hzwer回答(已授权):https://www.zhihu.com/question/521497951

 
 
 
 
 
 
 
 
 
 
 
 
往期精彩回顾




适合初学者入门人工智能的路线及资料下载(图文+视频)机器学习入门系列下载中国大学慕课《机器学习》(黄海广主讲)机器学习及深度学习笔记等资料打印《统计学习方法》的代码复现专辑
AI基础下载机器学习交流qq群955171419,加入微信群请扫码:

755486ee84ab611c35d6ecd5ac50a9a7.png

在实际应用中,`requests` `BeautifulSoup` 结合使用是非常常见的做法,尤其是在网络爬虫网页数据抓取方面。为了提高效率可靠性,以下是几种优化策略: ### 1. 缓存请求结果 频繁访问相同的URL不仅浪费带宽资源还会增加服务器负担。利用缓存机制可以避免不必要的重复下载。例如,你可以通过 Python 的 `cachetools` 或者其他类似库来进行本地缓存管理;也可以考虑使用 Redis 这样的内存存储系统作为远程缓存层。 ```python import requests from bs4 import BeautifulSoup from cachetools import cached, TTLCache # 创建一个TTL(生存时间)为一小时的缓存实例 cache = TTLCache(maxsize=100, ttl=3600) @cached(cache) def fetch_page(url): response = requests.get(url) return response.text if response.status_code == 200 else None url = 'http://example.com' html_content = fetch_page(url) soup = BeautifulSoup(html_content, "lxml") ``` ### 2. 异步并发处理 对于大量页面抓取任务来说,异步 I/O 操作能显著提升整体性能。借助于 asyncio 及其协程特性,我们可以在等待 HTTP 请求完成的同时继续执行下一个请求而不必阻塞主线程。AioHttp 是一个很好的例子。 ```python import aiohttp import asyncio from bs4 import BeautifulSoup async def get_html(session, url): async with session.get(url) as resp: return await resp.text() async def main(urls): async with aiohttp.ClientSession() as session: tasks = [get_html(session, url) for url in urls] htmls = await asyncio.gather(*tasks) # 解析所有 HTML 内容 soups = [] for html in htmls: soup = BeautifulSoup(html, "lxml") soups.append(soup) if __name__ == "__main__": urls = ["https://www.example{}.com".format(i+1) for i in range(5)] loop = asyncio.get_event_loop() loop.run_until_complete(main(urls)) ``` ### 3. 设置合理的超时时间重试次数 在网络不稳定的情况下设置适当的 timeout 参数有助于防止长时间挂起的情况发生。此外还可以配置 retrying 库自动重试失败的请求直到成功或达到最大尝试次数为止。 ```python import time import requests from bs4 import BeautifulSoup from tenacity import retry, stop_after_attempt, wait_exponential @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10)) def robust_request(url): try: start_time = time.time() res = requests.get(url=url, timeout=(5, 15)) # connect and read timeouts respectively. print(f"Request took {time.time()-start_time:.2f} seconds.") return res.content.decode('utf-8') except Exception as e: raise ValueError("Failed to retrieve data from URL.") from e html_doc = robust_request('http://some_url') soup = BeautifulSoup(html_doc,"lxml") ``` ### 4. 提升解析速度 尽管 BeautifulSoup 已经很高效了,但在面对特别庞大的 DOM 树时仍然可能存在瓶颈。此时可以选择 lxml-parser 替换默认 parser ,因为前者通常更快且占用更少内存。另外只选取必要的部分进行解析也能加快整个流程。 ```python # 使用 lxml 解析器替代 python 默认的解析器 soup = BeautifulSoup(markup="<div>Hello World!</div>", features="lxml") # 预先过滤掉不需要的内容节点再传入构造函数 filtered_markup = "<root>" + ''.join([str(tag) for tag in markup.find_all(['a', 'img'])])+"</root>" fast_soup = BeautifulSoup(filtered_markup ,features='lxml') ``` --- 通过上述方法结合运用 `requests` `BeautifulSoup` 能够有效改善程序运行效果并增强稳定性。当然这些建议并非绝对必要每个项目都要采用,具体情况还需根据自身需求权衡利弊做出最佳选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值