一、项目简介
利用大语言模型(LLMs)可以帮助我们筛选行业论文,分析行业热点,总结论文内容,从而帮助科研人员更好地把握论文核心思想。
试完成以下任务:
子任务 1:通过网络爬取的方式收集 CVPR 2024 论文(不少于 500 篇),并通过pdf解析的方式提取出论文abstract,找到其中所有能应用在智能驾驶领域相关论文,进行子领域分类,并统计每个子领域的论文数量。(子领域分类通过调用大语言模型完成,具体子领域名称不做限制,分类依据言之有理即可,子领域数量限制在 6 个以内。调用的大语言模型不限,推荐使用zhipuAI。)
子任务2:阅读论文Wei, Jason, et al. "Finetuned Language Models are Zero-Shot Learners."和Brown, Tom B., et al. “Language Models are Few-Shot Learners.”,理解zero-shot和few-shot prompt两种方式,并完成:利用大语言模型分别以 zero-shot 和 few-shot prompt 两种方式,对任意一篇以pdf形式给出的论文,以文本的形式输出其方法以及核心思想。
二、实现思路
先将任务拆解为以下步骤,再使用库一一进行实现:
- 爬取论文————request、BeautifulSoup、ThreadPoolExecutor
- 提取论文摘要————pdfminer、glob
- 筛选相关论文————transformers、shutil
- 论文子领域分类并统计数量————ZhipuAI
- 解析论文的方法以及核心思想————ZhipuAI
三、实现过程
1.爬取 CVPR 2024 论文
(1)导入需要的依赖库,并创建好保存论文的文件夹
import os
import requests
from bs4 import BeautifulSoup
if not os.path.exists('CVPR2024_Paper'):
os.makedirs('CVPR2024_Paper')
(2)向CVPR网站发送请求,检验请求状态
url = "https://openaccess.thecvf.com/CVPR2024?day=all"
response = requests.get(url)
if response.status_code == 200:
print("请求成功")
else:
print("请求失败")
soup = BeautifulSoup(response.content,'html.parser')
若运行结果显示"请求成功",则表示成功获取了该网页的所有内容
(3)解析网页:在html语言中,a标签的href代表要跳转的链接,而target表示跳转链接的方式。因此,找出所有带a的标签,并且找到其中的href,通过根据论文pdf的特性为href设置了两层判断:①结尾必须带有.pdf;②路径中应带有’papers‘(论文的补充材料supplement也是pdf,需要区分)
a = soup.findAll('a', href = True)
pdf_link = []
for link in a:
href = link['href']#子链接全部存在href属性
if href.endswith('.pdf'):#用字符串对象方法选出后缀是pdf的
if 'papers'in href:
pdf_link.append("https://openaccess.thecvf.com"+href)
pdf_link
若运行结果如下,则表示成功获取了网页中所有论文的超链接
(4)接下来就可以利用筛选出来的链接进行论文下载
for i,paper_link in enumerate(pdf_link):
response = requests.get(paper_link)
with open (f"CVPR2024_Paper/({i+1}){os.path.basename(paper_link)}","wb") as f:
f.write(response.content)
print(f"Downing Paper {i+1}/{len(pdf_link)}")
if i>499:
break
输出以下结果说明程序已经在自己读取每一个超链接然后下载保存到本地,但是平均下载一篇论文需要花费数秒到数十秒不等,总计需要花费的时间很长。
(5)利用多线程加速爬取论文
我们在爬取论文的过程其实是包括网络请求、文件读写等操作,这些任务都是属于IO密集型任务,因此选用多线程(cpu密集型任务不适用)使得cpu在不同任务间来回切换可以节约一些等待的空闲时间,从而使得下载论文的速度大大增加。这里我选择采用ThreadPoolExecutor线程池进行管理线程,代码更加简洁易懂。
但是使用多线程进行爬取论文时需要关注两点:①频繁请求可能会带来封禁,因此需要设置一些随机延迟来模拟人类行为;②防止重复下载浪费资源
#运用多线程进行加速
#注:由于每个线程只需要发送请求和读写保存,属于IO密集型任务,因此采用多线程可以有效提高效率
import time
import random
from concurrent.futures import ThreadPoolExecutor,as_completed
#下载单篇论文
def download_paper(pdf_link,i):
try:
#设置延迟,模拟人类行为
time.sleep(random.uniform(0,2))
#防止重复下载浪费资源
if not os.path.exists(f"CVPR2024_Paper/({i+1}){os.path.basename(pdf_link[i])}"):
response = requests.get(pdf_link[i],timeout=30)
with open (f"CVPR2024_Paper/({i+1}){os.path.basename(pdf_link[i])}","wb") as f:
f.write(response.content)
print(f"Downing Paper {i+1} successfully")
else:
pass
except Exception as e:
print(f'Downloading failed:{pdf_link[i]} due to {e}')
#用线程池管理下载剩余的论文
with ThreadPoolExecutor(max_workers=10) as executor:
futures = []
for i in range(len(pdf_link)):
futures.append(executor.submit(download_paper,pdf_link,i))
for future in as_completed(futures):
try:
future.result()
except Exception as e:
print(f'Error occurred:{e}')
出现以下输出说明已经成功启用线程池进行高速下载
2.解析pdf提取摘要
目前对于解析pdf的库有两个:pyPDF和PDFMiner,其中PDFMiner更适合文本解析
(1)先引入pdfminer库中的extract_text函数,该函数可以直接对pdf进行解析并提取文字,借助该函数以及CVPR论文格式构建提取摘要的函数,我们可以将论文的摘要锁定在Abstract之后直到“1.”或“Introduction”之前,用关键词定位的方式提取出摘要。
from pdfminer.high_level import extract_text
#提取论文的abstract
def extract_abstract(pdf_path):
try:
text = extract_text(pdf_path)
start_key = 'Abstract'
end_key = ['1.','Introduction']#可能存在的结束词
start_index = text.find(start_key)
if start_index == -1:
print(f"{pdf_path}: is None")
return None
else:
end_index = len(text)
for k in end_key:
idx = text.find(k,start_index)
if idx != -1 and idx <end_index:
end_index = idx
abstract = text[start_index:end_index].strip()
return abstract
except Exception as e:
print(f"Error occurred while processing {pdf_path}: {e}")
return None
extract_abstract("CVPR2024_Paper/(1)Zeng_Unmixing_Diffusion_for_Self-Supervised_Hyperspectral_Image_Denoising_CVPR_2024_paper.pdf")
以下为实例论文提取出的摘要
(2)批量对所有论文的摘要进行提取,然后使用pickle库保存成pkl格式,便于后续每次调用不需要重复进行此步骤,直接读取pkl加载数据即可
import glob
import pickle
titles = []
abstracts = []
i = 1
print("开始提取摘要")
for pdf in glob.glob('CVPR2024_Paper/*.pdf'):
abstract = extract_abstract(pdf)
abstracts.append(abstract)
titles.append(pdf)
print(f"{i}/1001")
i+=1
print("提取完毕")
#保存下来方便下次读取使用
with open ('abstracts.pkl',"wb") as f:
pickle.dump(abstracts,f)
with open ('titles.pkl',"wb") as f:
pickle.dump(titles,f)
print("保存完成")
3.筛选相关论文
本任务的目标是从一千余篇论文中找出其中与智能驾驶领域相关的论文,但如何判断一篇论文是否属于智能驾驶领域并没有一个标准的答案。而且该问题的本质是一个零样本分类问题,我们如果制作数据集并进行训练会耗时费力,故以下尝试了几种可行的办法:
①关键词匹配
②主题建模技术
③大语言模型进行零样本分类
④zhipuAI进行判断区分
每种方式找出的论文各有不同,各方法也各有优劣
方法①:首先定义足够多的、属于智能驾驶领域的关键词,只要论文摘要中含有其中的一个关键词,我们则认为该论文与智能驾驶领域有关联,将其移动到新的文件夹下
#找到所有智能驾驶领域相关的论文
#方法①:进行关键词匹配,如果摘要存在关键词则将该论文移动到新的文件夹
#结果:找到20篇左右,有些pdf会出现解析失败的问题
import glob
import shutil
import os
from concurrent.futures import ThreadPoolExecutor,as_completed
if not os.path.exists('autonomous_driving_papers'):
os.makedirs('autonomous_driving_papers')
keywords = [
"autonomous driving", "self-driving", "intelligent vehicle",
"vehicle detection", "lane detection", "collision avoidance",
"path planning", "road segmentation", "object detection in driving",
"traffic sign recognition", "vehicle-to-everything", "V2X",
"lidar-based navigation", "sensor fusion in driving", "driver assistance systems"
]
folder = 'autonomous_driving_papers'
def is_relevant(abstract,keywords):
for word in keywords:
if word.lower() in abstract.lower():
return True
return False
def get_relevant(pdf,keywords,folder):
abstract = extract_abstract(pdf)
if abstract and is_relevant(abstract,keywords):
filename = os.path.basename(pdf)
target_path = os.path.join(folder,filename)
shutil.move(pdf,target_path)
print(f'{filename} is relevant')
else:
pass
with ThreadPoolExecutor(max_workers=10) as executor:
futures = []
for pdf in glob.glob('CVPR2024_Paper/*.pdf'):
futures.append(executor.submit(get_relevant,pdf,keywords,folder))
for future in as_completed(futures):
try:
future.result()
except Exception as e:
print(f'Error occurred:{e}')
print('finish task')
使用该方式进行判断得到20篇论文与智能驾驶领域有高度相关。相对于其他方式,关键词匹配的方式能确保分类论文的高度相关性,但是也容易受关键词影响,容易将一些与智能驾驶有关但摘要不存在相同关键词的文章忽略,泛化能力差
方法②:主题建模是一种自然语言处理(NLP)技术,用于从大量文档中识别和提取隐藏的主题。这种技术在处理和分析大量文本数据时非常有用,能够帮助人们理解文档集合中的主要内容和结构。它的主要方法是潜在狄利克雷分配 (LDA):通过贝叶斯推断和吉布斯采样等方法来估计主题分布。LDA是一种生成模型,假设每个文档是由多个主题混合生成的,每个主题是由多个词汇分布生成的。优点是能够发现文档中的隐藏主题,适用于大规模文本数据集。
主题建模技术一般主题数应该在5至20个左右,通过计算困惑度来选择最佳主题数,最终提取每个主题的关键词,若出现与智能驾驶领域相关关键词则代表该主题与智能驾驶相关。然而输出结果中提取的关键词难以确定智能驾驶相关的类别,因此该方法没成功实现
#方法②尝试使用主题建模技术
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.decomposition import LatentDirichletAllocation
import matplotlib.pyplot as plt
import numpy as np
import pyLDAvis
import pyLDAvis.sklearn
# 数据预处理
abstracts = list(filter(lambda x: x is not None, abstracts))
vectorizer = CountVectorizer(stop_words='english')
X = vectorizer.fit_transform(abstracts)
# 选择主题数的范围
topic_range = range(5, 21)
perplexities = []
# 训练不同主题数的LDA模型,计算困惑度
for n_topics in topic_range:
lda = LatentDirichletAllocation(n_components=n_topics, random_state=0)
lda.fit(X)
perplexity = lda.perplexity(X)
perplexities.append(perplexity)
# 绘制困惑度曲线,选择最佳主题数
plt.plot(topic_range, perplexities)
plt.xlabel('Number of Topics')
plt.ylabel('Perplexity')
plt.title('Perplexity Scores for Different Number of Topics')
plt.show()
# 选择最佳主题数,训练最终模型
optimal_n_topics = topic_range[np.argmin(perplexities)]
lda = LatentDirichletAllocation(n_components=optimal_n_topics, random_state=0)
lda.fit(X)
# 提取每个主题的关键词
def print_top_words(model, feature_names, n_top_words):
for topic_idx, topic in enumerate(model.components_):
print(f"Topic #{topic_idx}:")
print(" ".join([feature_names[i] for i in topic.argsort()[:-n_top_words - 1:-1]]))
print()
n_top_words = 25
print_top_words(lda, vectorizer.get_feature_names_out(), n_top_words)
# 人工审查主题关键词,确定相关主题编号
related_topics = [0] # 根据关键词人工判断哪些主题与智能驾驶相关
# 筛选与智能驾驶相关的论文
relevant_papers = []
for i, topic_dist in enumerate(lda.transform(X)):
if any(topic_dist[topic] > 0.1 for topic in related_topics):
relevant_papers.append(abstracts[i])
print(f"Found {len(relevant_papers)} relevant papers.")
方法③:利用大模型进行零样本分类从Hugging Face的镜像网站中下载bart-large-mnli模型(主要按照自己的环境选择模型),然后把之前保存的摘要数据读取进来,去除掉为None的一些异常。使用零样本分类的方式计算每个摘要与设定标签之间的置信度(标签设置不宜超过十个),若其中与某一个标签的置信度超过0.5则认为论文与智能驾驶领域相关。该方法得到20篇论文,与关键词匹配得到的结果略有不同,该方法划分论文的方式更灵活多变
#方法③零样本分类
from transformers import pipeline
import os
import torch
import pickle
device = 0 if torch.cuda.is_available() else -1
# 加载预训练的零样本分类模型
classifier = pipeline("zero-shot-classification", model="bart-large-mnli",device = device)
print("链接成功")
with open("abstracts.pkl","rb") as f:
abstracts = pickle.load(f)
with open("titles.pkl","rb") as f:
titles = pickle.load(f)
for i in range(len(abstracts)):
if abstracts[i] is None:
titles.remove(titles[i])
abstracts = list(filter(lambda x: x is not None, abstracts))
import glob
import shutil
import os
from concurrent.futures import ThreadPoolExecutor,as_completed
# 定义与智能驾驶相关的标签
labels = ["intelligent driving", "autonomous driving", "self-driving" ,"intelligent vehicle",
"vehicle detection", "lane detection", "collision avoidance",
"path planning", "road segmentation", "object detection in driving"]
folder = 'intelligent_driving_papers'
if not os.path.exists(folder):
os.makedirs(folder)
# 批量处理输入文本
batch_size = 16
relevant_papers = []
for i in range(0, len(abstracts), batch_size):
batch = abstracts[i:i + batch_size]
results = classifier(batch, candidate_labels=labels)
for result in results:
if any(score > 0.5 for score in result['scores']): # 如果至少一个标签的得分超过0.5,认为是相关论文
relevant_papers.append(result['sequence'])
print(relevant_papers)
for rp in relevant_papers:
index = abstracts.index(rp)
title = titles[index]
filename = os.path.basename(title)
target_path = os.path.join(folder,filename)
shutil.move(title,target_path)
print(f'{filename} is relevant')
方法④:使用zhipiAI大模型的api,利用大模型交互的方式让大模型判断论文是否属于智能驾驶领域,调整prompt使得大模型回答存在固定关键词,再借此筛选出与智能驾驶相关的论文;但是该判断方式并不严谨,共筛选出172篇论文,其中存在较多与智能驾驶不相关的论文,准确率并不理想。但该方法改进空间大,如果将关键词匹配得到的论文转化为数据集,再利用该数据集进行模型微调,应该能提升模型分类的效果(由于数据量并不足以构建数百条优质的数据集,本次不做尝试)
from zhipuai import ZhipuAI
import glob
import os
import shutil
folder = 'zhipu_Paper'
if not os.path.exists(folder):
os.makedirs(folder)
# 设置API密钥
client = ZhipuAI(api_key="******")
# 定义分类函数
def classify_paper(abstract, labels):
prompt = f"请阅读以下论文摘要,并判断其是否明确属于智能驾驶领域且有直接较强的关联性(潜在关联性不算,需要明确提及应用在智能驾驶领域):\n\n{abstract}\n\n直接回答是yes或no,不要多余赘述"
response = client.chat.completions.create(model="glm-4",messages=[{"role": "user", "content": prompt} ])
print(response.choices[0].message.content.lower())
if "yes" in response.choices[0].message.content.lower():
return True
else:
return False
relevant_papers = []
for pdf in glob.glob('CVPR2024_Paper/*.pdf'):
abstract = extract_abstract(pdf)
if abstract is not None:
result = classify_paper(abstract,labels)
if result:
filename = os.path.basename(pdf)
target_path = os.path.join(folder,filename)
shutil.move(pdf,target_path)
print(f"{filename}")
4.论文子领域分类并统计数量
在子领域分类上首先需要确定子领域的名称,由于CVPR的论文特性,论文中与视觉、图像处理方面的论文会占据主要,如果按照智能驾驶通常的分类分为:感知、决策、控制、定位会导致大部分文章击中在感知,因此最后选定了六个跟计算机视觉相关与智能驾驶同时相关的子领域: “object detection”, “scene understanding”, “pose estimation”, “depth estimation”, “trajectory prediction”, “visual SLAM”。
同样地,在子领域分类中我也尝试了bart-large-mnli零分类和zhipuai进行分类的两种方式,有分类结果统计数量来看,两种模型对于论文的分类也略有不同
方法①:
#方法③零样本分类
from transformers import pipeline
import os
import torch
import pickle
device = 0 if torch.cuda.is_available() else -1
# 加载预训练的零样本分类模型
classifier = pipeline("zero-shot-classification", model="bart-large-mnli",device = device)
subfields = [
"object detection", "scene understanding", "pose estimation",
"depth estimation", "trajectory prediction", "visual SLAM"
]
classified_papers = {subfield: [] for subfield in subfields}
for folder in subfields:
if not os.path.exists("autonomous_driving_papers/"+folder):
os.makedirs("autonomous_driving_papers/"+folder)
for pdf in glob.glob('autonomous_driving_papers/*.pdf'):
abstract = extract_abstract(pdf)
result = classifier(abstract,subfields)
print(result['labels'],result['scores'])
field = result['labels'][result['scores'].index(max(result['scores']))]
filename = os.path.basename(pdf)
target_path = "autonomous_driving_papers/"+field
target_path = os.path.join(target_path,filename)
shutil.move(pdf,target_path)
classified_papers[field].append(result['sequence'])
#统计每个子领域的论文数量
for subfield, papers in classified_papers.items():
print(f"{subfield}: {len(papers)} papers")
方法②:
from zhipuai import ZhipuAI
import glob
import os
import shutil
# 设置API密钥
client = ZhipuAI(api_key="281f9caf0cb2d6fa224325c8eef01c4e.bBHtRXX534vbRwHQ")
# 定义子领域标签
labels = ["object detection", "scene understanding", "pose estimation",
"depth estimation", "trajectory prediction", "visual SLAM"]
# 定义分类函数
def classify_paper(abstract, labels):
prompt = f"以下是一些智能驾驶领域的子领域:{', '.join(labels)}。请阅读以下论文摘要,并将其分类到最相关的子领域:\n\n{abstract}\n\n只需要直接回答子领域名称,不要多余赘述,不要回答不属于以上六个子领域的领域"
response = client.chat.completions.create(model="glm-4",messages=[{"role": "user", "content": prompt} ])
return response.choices[0].message.content
classified_papers = {subfield: [] for subfield in labels}
for pdf in glob.glob('autonomous_driving_papers/*.pdf'):
print(pdf)
abstract = extract_abstract(pdf)
result = classify_paper(abstract,labels)
for word in labels:
if word.lower() in result.lower():
field = word
print(word)
filename = os.path.basename(pdf)
classified_papers[field].append(filename)
target_path = "autonomous_driving_papers\\"+field
target_path = os.path.join(target_path,filename)
shutil.move(pdf,target_path)
break
#统计每个子领域的论文数量
for subfield, papers in classified_papers.items():
print(f"{subfield}: {len(papers)} papers")
5.解析论文的方法以及核心思想
在CRISPE框架中:
- CR:Capacity and Role(能力与角色)。你希望 ChatGPT 扮演怎样的角色。
- I:Insight(洞察),背景信息和上下文。
- S:(陈述),你希望 ChatGPT 做什么。
- P:Personality(个性),你希望 ChatGPT 以什么风格或方式回答你。
- E:Experiment(实验),要求 ChatGPT 为你提供多个答案
zero-shot prompt只是使用CRISPE,不增加示例样本
few-shot prompt则是将示例加入 Prompt 的做法
利用zero-shot prompt方式先对一篇输出一篇论文的方法及核心思想
from zhipuai import ZhipuAI
import glob
import os
import shutil
from pdfminer.high_level import extract_text
# 提取PDF中的文本
def extract_paper(pdf_path):
try:
text = extract_text(pdf_path).strip()
return text
except Exception as e:
print(f"Error occurred while processing {pdf_path}: {e}")
return None
# 设置API密钥
client = ZhipuAI(api_key="**********************")
path = "autonomous_driving_papers/object detection/(297)Ma_HoloVIC_Large-scale_Dataset_and_Benchmark_for_Multi-Sensor_Holographic_Intersection_and_CVPR_2024_paper.pdf"
example = []
#使用CRISPE框架
def zeroshot(paper):
prompt = f"你是一个擅长智能驾驶领域的AI工程师,请阅读以下论文,并输出其方法以及核心思想,要求条理清晰,逻辑严谨,使用中文回答。以下是你需要阅读的论文:\n\n{paper}\n\n"
response = client.chat.completions.create(model="glm-4",messages=[{"role": "user", "content": prompt} ])
print(response.choices[0].message.content)
return response.choices[0].message.content
example.append([extract_paper(path),zeroshot(extract_paper(path))])
利用few-shot prompt方式,先提供一个示例,再输出论文的方法及其核心思想
def fewshot(paper,example):
prompt = f'''你是一个擅长智能驾驶领域的AI工程师,请阅读以下论文,并输出其方法以及核心思想,要求条理清晰,逻辑严谨。请参考我给出的示例:
<example>论文原文:{example[0][0]}\n\n方法与核心思想:{example[0][1]}<example>以下是你需要阅读的论文:\n\n{paper}\n\n'''
response = client.chat.completions.create(model="glm-4",messages=[{"role": "user", "content": prompt} ])
print(response.choices[0].message.content)
return response.choices[0].message.content
path = "autonomous_driving_papers/object detection/(333)Li_Multiagent_Multitraversal_Multimodal_Self-Driving_Open_MARS_Dataset_CVPR_2024_paper.pdf"
example.append([extract_paper(path),fewshot(extract_paper(path),example)])
四、总结
本项目通过爬取 CVPR 2024 会议的论文,利用大语言模型进行零样本分类,筛选出与智能驾驶领域相关的论文,并解析其方法和核心思想。整个过程包括以下几个步骤:
- 爬取论文:使用 requests 和 BeautifulSoup 库,从 CVPR 官方网站爬取了所有论文的 PDF 链接,并使用多线程下载所有论文。
- 提取论文摘要:利用 PDFMiner 库解析 PDF 文件,提取出论文的摘要,并保存为.pkl文件以便后续使用。
- 筛选相关论文:使用关键词匹配、主题建模和大语言模型进行零样本分类等方法,从提取的摘要中筛选出与智能驾驶领域相关的论文,并将其移动到新的文件夹。
- 子领域分类:使用 ZhipuAI 对筛选出的论文进行子领域分类,并统计各子领域的论文数量。
- 解析方法和核心思想:利用大语言模型对筛选出的论文进行方法和核心思想的解析,总结出每篇论文的研究方法和主要贡献。
在整个过程中,采用了多种技术和工具,包括多线程处理、PDF 解析、关键词匹配、主题建模和大语言模型等。通过这些技术手段,实现了从大量论文中高效筛选出目标领域相关文献,并对其进行深入分析。这不仅提高了文献筛选的效率,也为智能驾驶领域的研究提供了有力的支持和参考。
在阅读Wei, Jason, et al. "Finetuned Language Models are Zero-Shot Learners."和Brown, Tom B., et al. "Language Models are Few-Shot Learners."后还有以下额外收获:"Language Models are Few-Shot Learners."核心思想是:训练出GPT-3,应用时不需要微调或者梯度更新但需要通过文本交互来提供少量演示。 而"Finetuned Language Models are Zero-Shot Learners."主要讲述发现指令调优能提高大模型执行纯指令零样本任务的能力;并且指令调优有两个特性①:增加任务群数量,提高在未见过任务的性能;②:好处只出现在足够规模的模型。指令调优结合了预训练微调和提示范例,指令调优、预训练微调和提示范例三者分别可以理解为:
- 训练微调(Fine-tuning)是指在大规模预训练模型的基础上,使用特定任务的数据对模型进行进一步的训练,以优化其在该任务上的性能。例如,在一个已经预训练好的语言模型上,使用情感分析数据集进行微调,以使其更好地进行情感分析任务。
- 提示范例(Prompting)是指在使用预训练模型进行推理时,通过给模型提供任务的自然语言描述和示例来指导其生成答案。例如,给模型一个问题,并在输入中包含一些示例答案,以帮助模型理解任务并生成正确的答案。
- 指令调优(Instruction Tuning)是将训练微调和提示范例结合起来的一种方法。在指令调优过程中,模型在多个任务数据集上进行微调,每个任务通过自然语言指令描述进行微调。这种方法不仅提高了模型在已见任务上的性能,还显著提升了模型在未见任务上的零样本学习能力。