最新消息

欢迎来到 DH Hub!

我们是 南信大 DH 互联网技术社团

在这里收集当下火热的技术文章,并且分到对应板块内,作为社团的技术积累,供历届社友学习

本站不开放注册,访客可以正常浏览

  • 由于一些解析原因,建议先在本地编辑器写完以后再上传
  • 由于服务器原因,在编辑主题 / 回复时会有一定卡顿,请谅解。

人智 《基于论文摘要的文本分类与关键词抽取挑战赛》

主题 作者
成员
荣誉成员
09
17
5

比赛相关介绍​

一、赛事背景​

医学领域的文献库中蕴含了丰富的疾病诊断和治疗信息,如何高效地从海量文献中提取关键信息,进行疾病诊断和治疗推荐,对于临床医生和研究人员具有重要意义。

二、赛事任务​

本任务分为两个子任务:
  1. 机器通过对论文摘要等信息的理解,判断该论文是否属于医学领域的文献。
  2. 提取出该论文关键词。
bc8c545638eb4200a68836ed741b6fe7d75108e9009d443b8de5b33fb8e0fa55

任务1示例:
输入:

论文信息,格式如下:
代码:
[FONT=Times New Roman]Inflammatory Breast Cancer: What to Know About This Unique, Aggressive Breast Cancer.,
[Arjun Menta, Tamer M Fouad, Anthony Lucci, Huong Le-Petross, Michael C Stauder, Wendy A Woodward, Naoto T Ueno, Bora Lim],
Inflammatory breast cancer (IBC) is a rare form of breast cancer that accounts for only 2% to 4% of all breast cancer cases. Despite its low incidence, IBC contributes to 7% to 10% of breast cancer caused mortality. Despite ongoing international efforts to formulate better diagnosis, treatment, and research, the survival of patients with IBC has not been significantly improved, and there are no therapeutic agents that specifically target IBC to date. The authors present a comprehensive overview that aims to assess the present and new management strategies of IBC.,
Breast changes; Clinical trials; Inflammatory breast cancer; Trimodality care.[/FONT]
输出:

任务2示例:
输入:

代码:
[FONT=Times New Roman]Inflammatory Breast Cancer: What to Know About This Unique, Aggressive Breast Cancer.,
[Arjun Menta, Tamer M Fouad, Anthony Lucci, Huong Le-Petross, Michael C Stauder, Wendy A Woodward, Naoto T Ueno, Bora Lim],
Inflammatory breast cancer (IBC) is a rare form of breast cancer that accounts for only 2% to 4% of all breast cancer cases. Despite its low incidence, IBC contributes to 7% to 10% of breast cancer caused mortality. Despite ongoing international efforts to formulate better diagnosis, treatment, and research, the survival of patients with IBC has not been significantly improved, and there are no therapeutic agents that specifically target IBC to date. The authors present a comprehensive overview that aims to assess the present and new management strategies of IBC.[/FONT]
输出:
[Breast changes,Clinical trials, Inflammatory breast cancer,Trimodality care]

三、评审规则​

1.数据说明​

训练集与测试集数据为CSV格式文件,各字段分别是标题、作者、摘要、关键词。

2.评估指标​

任务一采用F1-score进行评价:
20.png

任务二采用文献关键词抽取准确率进行评价:
21.png

其中N为文献总数。
最终评估指标为:任务一得分40% + 任务二得分60%

赛题解析​

实践任务 本任务分为两个子任务:
  1. 从论文标题、摘要作者等信息,判断该论文是否属于医学领域的文献。
  2. 从论文标题、摘要作者等信息,提取出该论文关键词。
第一个任务看作是一个文本二分类任务。机器需要根据对论文摘要等信息的理解,将论文划分为医学领域的文献和非医学领域的文献两个类别之一。第二个任务看作是一个文本关键词识别任务。机器需要从给定的论文中识别和提取出与论文内容相关的关键词。

数据集解析 训练集与测试集数据为CSV格式文件,各字段分别是标题、作者和摘要。Keywords为任务2的标签,label为任务1的标签。训练集和测试集都可以通过pandas读取。

任务一:文本二分类​

第一个任务看作是一个文本二分类任务。机器需要根据对论文摘要等信息的理解,将论文划分为医学领域的文献和非医学领域的文献两个类别之一。
  • 一种是使用传统的特征提取方法(如TF-IDF/BOW)结合机器学习模型
  • 另一种是使用预训练的BERT模型进行建模。使用特征提取 + 机器学习的思路步骤如下:
  1. 数据预处理:首先,对文本数据进行预处理,包括文本清洗(如去除特殊字符、标点符号)、分词等操作。可以使用常见的NLP工具包(如NLTK或spaCy)来辅助进行预处理。
  2. 特征提取:使用TF-IDF(词频-逆文档频率)或BOW(词袋模型)方法将文本转换为向量表示。TF-IDF可以计算文本中词语的重要性,而BOW则简单地统计每个词语在文本中的出现次数。可以使用scikit-learn库的TfidfVectorizer或CountVectorizer来实现特征提取。
  3. 构建训练集和测试集:将预处理后的文本数据分割为训练集和测试集,确保数据集的样本分布均匀。
  4. 选择机器学习模型:根据实际情况选择适合的机器学习模型,如朴素贝叶斯、支持向量机(SVM)、随机森林等。这些模型在文本分类任务中表现良好。可以使用scikit-learn库中相应的分类器进行模型训练和评估。
  5. 模型训练和评估:使用训练集对选定的机器学习模型进行训练,然后使用测试集进行评估。评估指标可以选择准确率、精确率、召回率、F1值等。
  6. 调参优化:如果模型效果不理想,可以尝试调整特征提取的参数(如词频阈值、词袋大小等)或机器学习模型的参数,以获得更好的性能。
Baseline中我们选择使用BOW将文本转换为向量表示,选择逻辑回归模型来完成训练和评估
Python:
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import cross_val_score
import lightgbm as lgb
from warnings import simplefilter
from sklearn.exceptions import ConvergenceWarning
simplefilter("ignore", category=ConvergenceWarning)

df_train = pd.read_csv('data/train.csv')
df_test = pd.read_csv('data/test.csv')

df_train['title'] = df_train['title'].fillna('')
df_train['abstract'] = df_train['abstract'].fillna('')
df_train['text'] = df_train['title'] + ' ' + \
        df_train['author'].fillna('') + ' ' + \
        df_train['abstract'] + ' ' + \
        df_train['Keywords'].fillna('')

df_test['title'] = df_test['title'].fillna('')
df_test['abstract'] = df_test['abstract'].fillna('')
df_test['text'] = df_test['title'] + ' ' + \
        df_test['author'].fillna('') + ' ' + \
        df_test['abstract'] + ' ' + \
        df_test['Keywords'].fillna('')

X = df_train['text']  # 特征
y = df_train['label']  # 目标变量

vector = TfidfVectorizer()
X_vector = vector.fit_transform(X)

# 创建LightGBM分类器
model = lgb.LGBMClassifier()
# 训练模型
model.fit(X_vector, y)
# 进行五折交叉验证,返回每折的准确率
cv_scores = cross_val_score(model, X_vector, y, cv=5)
# 计算交叉验证的平均准确率
mean_accuracy = cv_scores.mean()
print("交叉验证平均准确率:", mean_accuracy)
# 利用模型对测试集label标签进行预测
test_vector = vector.transform(df_test['text'])
df_test['label'] = model.predict(test_vector)
# 生成任务一推测结果
df_test[['uuid', 'Keywords', 'label']].to_csv('submit_task1.csv', index=None)

任务二:关键词提取​

论文关键词划分为两类:
  • 在标题和摘要中出现的关键词
  • 没有在标题和摘要中出的关键词
在标题和摘要中出现的关键词:这些关键词是文本的核心内容,通常在文章的标题和摘要中出现,用于概括和提炼文本的主题或要点。对于提取这类关键词,可以采用以下方法:
  • 词频统计:统计标题和摘要中的词频,选择出现频率较高的词语作为关键词。同时设置停用词去掉价值不大、有负作用的词语。
  • 词性过滤:根据文本的词性信息,筛选出名词、动词、形容词等词性的词语作为关键词。
  • TF-IDF算法:计算词语在文本中的词频和逆文档频率,选择TF-IDF值较高的词语作为关键词。
没有在标题和摘要中出现的关键词:这类关键词可能在文本的正文部分出现,但并没有在标题和摘要中提及。要提取这些关键词,可以考虑以下方法:
  • 文本聚类:将文本划分为不同的主题或类别,提取每个主题下的关键词。
  • 上下文分析:通过分析关键词周围的上下文信息,判断其重要性和相关性。
  • 基于机器学习/深度学习的方法:使用监督学习或无监督学习的方法训练模型,从文本中提取出未出现在标题和摘要中的关键词。
Python:
# 引入分词器
from nltk import word_tokenize, ngrams

# 定义停用词,去掉出现较多,但对文章不关键的词语
stops = [
    'will', 'can', "couldn't", 'same', 'own', "needn't", 'between', "shan't", 'very',
     'so', 'over', 'in', 'have', 'the', 's', 'didn', 'few', 'should', 'of', 'that',
     'don', 'weren', 'into', "mustn't", 'other', 'from', "she's", 'hasn', "you're",
     'ain', 'ours', 'them', 'he', 'hers', 'up', 'below', 'won', 'out', 'through',
     'than', 'this', 'who', "you've", 'on', 'how', 'more', 'being', 'any', 'no',
     'mightn', 'for', 'again', 'nor', 'there', 'him', 'was', 'y', 'too', 'now',
     'whom', 'an', 've', 'or', 'itself', 'is', 'all', "hasn't", 'been', 'themselves',
     'wouldn', 'its', 'had', "should've", 'it', "you'll", 'are', 'be', 'when', "hadn't",
     "that'll", 'what', 'while', 'above', 'such', 'we', 't', 'my', 'd', 'i', 'me',
     'at', 'after', 'am', 'against', 'further', 'just', 'isn', 'haven', 'down',
     "isn't", "wouldn't", 'some', "didn't", 'ourselves', 'their', 'theirs', 'both',
     're', 'her', 'ma', 'before', "don't", 'having', 'where', 'shouldn', 'under',
     'if', 'as', 'myself', 'needn', 'these', 'you', 'with', 'yourself', 'those',
     'each', 'herself', 'off', 'to', 'not', 'm', "it's", 'does', "weren't", "aren't",
     'were', 'aren', 'by', 'doesn', 'himself', 'wasn', "you'd", 'once', 'because', 'yours',
     'has', "mightn't", 'they', 'll', "haven't", 'but', 'couldn', 'a', 'do', 'hadn',
     "doesn't", 'your', 'she', 'yourselves', 'o', 'our', 'here', 'and', 'his', 'most',
     'about', 'shan', "wasn't", 'then', 'only', 'mustn', 'doing', 'during', 'why',
     "won't", 'until', 'did', "shouldn't", 'which'
]

# 定义方法按照词频筛选关键词
def extract_keywords_by_freq(title, abstract):
    ngrams_count = list(ngrams(word_tokenize(title.lower()), 2)) + list(ngrams(word_tokenize(abstract.lower()), 2))
    ngrams_count = pd.DataFrame(ngrams_count)
    ngrams_count = ngrams_count[~ngrams_count[0].isin(stops)]
    ngrams_count = ngrams_count[~ngrams_count[1].isin(stops)]
    ngrams_count = ngrams_count[ngrams_count[0].apply(len) > 3]
    ngrams_count = ngrams_count[ngrams_count[1].apply(len) > 3]
    ngrams_count['phrase'] = ngrams_count[0] + ' ' + ngrams_count[1]
    ngrams_count = ngrams_count['phrase'].value_counts()
    ngrams_count = ngrams_count[ngrams_count > 1]
    return list(ngrams_count.index)[:5]

# 对测试集提取关键词
test_words = []
for row in test.iterrows():
    # 读取第每一行数据的标题与摘要并提取关键词
    prediction_keywords = extract_keywords_by_freq(row[1].title, row[1].abstract)
    # 利用文章标题进一步提取关键词
    prediction_keywords = [x.title() for x in prediction_keywords]
    # 如果未能提取到关键词
    if len(prediction_keywords) == 0:
        prediction_keywords = ['A', 'B']
    test_words.append('; '.join(prediction_keywords))

test['Keywords'] = test_words
test[['uuid', 'Keywords', 'label']].to_csv('submit_task2.csv', index=None)
 
主题 作者
成员
荣誉成员
09
17
5

进阶方法:基于BERT的文本二分类​

导入前置依赖
Python:
import os
import pandas as pd
import torch
from torch import nn
from torch.utils.data import Dataset, DataLoader
# 用于加载bert模型的分词器
from transformers import AutoTokenizer
# 用于加载bert模型
from transformers import BertModel
from pathlib import Path
事先定义的参数
Python:
batch_size = 16 # 批次大小
epochs = 100  # 总训练的epochs数
lr = 3e-5 # 学习率
validation_ratio = 0.1  # 取多少训练集的数据作为验证集
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # 设置训练设备
log_per_step = 50 # 每多少步,打印一次loss
model_dir = Path("bert_checkpoints")  # 模型存储路径
os.makedirs(model_dir) if not os.path.exists(model_dir) else '' # 如果模型目录不存在,则创建一个

text_max_length = 128 # 文本的最大长度
原始数据预处理
Python:
# 数据集所在位置
dataset_dir = Path("/kaggle/input/abstract-text-challenge")
os.makedirs(dataset_dir) if not os.path.exists(dataset_dir) else ''
print("Device:", device)

# 读取数据集,进行数据处理
pd_train_data = pd.read_csv('/kaggle/input/abstract-text-challenge/train.csv')
pd_train_data['title'] = pd_train_data['title'].fillna('')
pd_train_data['abstract'] = pd_train_data['abstract'].fillna('')

test_data = pd.read_csv('/kaggle/input/abstract-text-challenge/test.csv')
test_data['title'] = test_data['title'].fillna('')
test_data['abstract'] = test_data['abstract'].fillna('')

pd_train_data['text'] = pd_train_data['title'].fillna('') + ' ' +  pd_train_data['author'].fillna('') + ' ' + pd_train_data['abstract'].fillna('')+ ' ' + pd_train_data['Keywords'].fillna('')
test_data['text'] = test_data['title'].fillna('') + ' ' +  test_data['author'].fillna('') + ' ' + test_data['abstract'].fillna('')+ ' ' + pd_train_data['Keywords'].fillna('')

# 从训练集中随机采样测试集
validation_data = pd_train_data.sample(frac=validation_ratio)
train_data = pd_train_data[~pd_train_data.index.isin(validation_data.index)]
构建我们的数据集
Python:
# 构建Dataset
class MyDataset(Dataset):
    # 第一步 初始化
    def __init__(self, mode='train'):
        super(MyDataset, self).__init__()
        self.mode = mode
        # 拿到对应的数据
        if mode == 'train':
            self.dataset = train_data
        elif mode == 'validation':
            self.dataset = validation_data
        elif mode == 'test':
            # 如果是测试模式,则返回内容和uuid。拿uuid做target主要是方便后面写入结果。
            self.dataset = test_data
        else:
            raise Exception("Unknown mode {}".format(mode))

  # 第二步 逐条取出数据
    def __getitem__(self, index):
        # 取第index条
        data = self.dataset.iloc[index]
        # 取其内容
        text = data['text']
        # 根据状态返回内容
        if self.mode == 'test':
            # 如果是test,将uuid做为target
            label = data['uuid']
        else:
            label = data['label']
        # 返回内容和label
        return text, lab

    # 第三步 算长度
    def __len__(self):
        return len(self.dataset)

train_dataset = MyDataset('train')
validation_dataset = MyDataset('validation')

train_dataset.__getitem__(0)

划分数据集
Python:
#获取Bert预训练模型
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")

#我们需要定义一下collate_fn,在其中完成对句子进行编码、填充、组装batch等动作:
def collate_fn(batch):
    """
    将一个batch的文本句子转成tensor,并组成batch。
    :param batch: 一个batch的句子,例如: [('推文', target), ('推文', target), ...]
    :return: 处理后的结果,例如:
             src: {'input_ids': tensor([[ 101, ..., 102, 0, 0, ...], ...]), 'attention_mask': tensor([[1, ..., 1, 0, ...], ...])}
             target:[1, 1, 0, ...]
    """
    text, label = zip(*batch)
    text, label = list(text), list(label)

    # src是要送给bert的,所以不需要特殊处理,直接用tokenizer的结果即可
    # padding='max_length' 不够长度的进行填充
    # truncation=True 长度过长的进行裁剪
    src = tokenizer(text, padding='max_length', max_length=text_max_length, return_tensors='pt', truncation=True)

    return src, torch.LongTensor(label)

train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, collate_fn=collate_fn)
validation_loader = DataLoader(validation_dataset, batch_size=batch_size, shuffle=False, collate_fn=collate_fn)

inputs, targets = next(iter(train_loader))
print("inputs:", inputs)
print("targets:", targets)

BERT模型定义
Python:
#定义预测模型,该模型由bert模型加上最后的预测层组成
class MyModel(nn.Module):

    def __init__(self):
        super(MyModel, self).__init__()

        # 加载bert模型
        self.bert = BertModel.from_pretrained('bert-base-uncased', mirror='tuna')

        # 最后的预测层
        self.predictor = nn.Sequential(
            nn.Linear(768, 256),
            nn.ReLU(),
            nn.Linear(256, 1),
            nn.Sigmoid()
        )

    def forward(self, src):
        """
        :param src: 分词后的推文数据
        """

        # 将src直接序列解包传入bert,因为bert和tokenizer是一套的,所以可以这么做。
        # 得到encoder的输出,用最前面[CLS]的输出作为最终线性层的输入
        outputs = self.bert(**src).last_hidden_state[:, 0, :]

        # 使用线性层来做最终的预测
        return self.predictor(outputs)

model = MyModel()
model = model.to(device)

#定义出损失函数和优化器。这里使用Binary Cross Entropy:
criteria = nn.BCELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=lr)

# 由于inputs是字典类型的,定义一个辅助函数帮助to(device)
def to_device(dict_tensors):
    result_tensors = {}
    for key, value in dict_tensors.items():
        result_tensors[key] = value.to(device)
    return result_tensors

#定义一个验证方法,获取到验证集的精准率和loss
def validate():
    model.eval()
    total_loss = 0.
    total_correct = 0
    for inputs, targets in validation_loader:
        inputs, targets = to_device(inputs), targets.to(device)
        outputs = model(inputs)
        loss = criteria(outputs.view(-1), targets.float())
        total_loss += float(loss)

        correct_num = (((outputs >= 0.5).float() * 1).flatten() == targets).sum()
        total_correct += correct_num

    return total_correct / len(validation_dataset), total_loss / len(validation_dataset)


# 首先将模型调成训练模式
model.train()

# 清空一下cuda缓存
if torch.cuda.is_available():
    torch.cuda.empty_cache()

# 定义几个变量,帮助打印loss
total_loss = 0.
# 记录步数
step = 0

# 记录在验证集上最好的准确率
best_accuracy = 0

开始训练
Python:
# 开始训练
for epoch in range(epochs):
    model.train()
    for i, (inputs, targets) in enumerate(train_loader):
        # 从batch中拿到训练数据
        inputs, targets = to_device(inputs), targets.to(device)
        # 传入模型进行前向传递
        outputs = model(inputs)
        # 计算损失
        loss = criteria(outputs.view(-1), targets.float())
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()

        total_loss += float(loss)
        step += 1

        if step % log_per_step == 0:
            print("Epoch {}/{}, Step: {}/{}, total loss:{:.4f}".format(epoch+1, epochs, i, len(train_loader), total_loss))
            total_loss = 0

        del inputs, targets

    # 一个epoch后,使用过验证集进行验证
    accuracy, validation_loss = validate()
    print("Epoch {}, accuracy: {:.4f}, validation loss: {:.4f}".format(epoch+1, accuracy, validation_loss))
    torch.save(model, model_dir / f"model_{epoch}.pt")

    # 保存最好的模型
    if accuracy > best_accuracy:
        torch.save(model, model_dir / f"model_best.pt")
        best_accuracy = accuracy

预测
Python:
#加载最好的模型,然后进行测试集的预测
model = torch.load(model_dir / f"model_best.pt")
model = model.eval()

test_dataset = MyDataset('test')
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False, collate_fn=collate_fn)

results = []
for inputs, ids in test_loader:
    outputs = model(inputs.to(device))
    outputs = (outputs >= 0.5).int().flatten().tolist()
    ids = ids.tolist()
    results = results + [(id, result) for result, id in zip(outputs, ids)]


test_label = [pair[1] for pair in results]
test_data['label'] = test_label
test_data[['uuid', 'Keywords', 'label']].to_csv('submit_task1.csv', index=None)

进阶方法:基于BERT的文本关键词提取​

导入前置依赖
Python:
# 导入pandas用于读取表格数据
import pandas as pd

# 导入BOW(词袋模型),可以选择将CountVectorizer替换为TfidfVectorizer(TF-IDF(词频-逆文档频率)),注意上下文要同时修改,亲测后者效果更佳
from sklearn.feature_extraction.text import TfidfVectorizer
# 导入Bert模型
from sentence_transformers import SentenceTransformer

# 导入计算相似度前置库,为了计算候选者和文档之间的相似度,我们将使用向量之间的余弦相似度,因为它在高维度下表现得相当好。
from sklearn.metrics.pairwise import cosine_similarity

# 过滤警告消息
from warnings import simplefilter
from sklearn.exceptions import ConvergenceWarning
simplefilter("ignore", category=ConvergenceWarning)

读取数据集并处理
Python:
# 读取数据集
test = pd.read_csv('./基于论文摘要的文本分类与关键词抽取挑战赛公开数据/test.csv')
test['title'] = test['title'].fillna('')
test['abstract'] = test['abstract'].fillna('')
test['text'] = test['title'].fillna('') + ' ' +test['abstract'].fillna('')

# 定义停用词,去掉出现较多,但对文章不关键的词语
stops =[i.strip() for i in open(r'stop.txt',encoding='utf-8').readlines()]
Bert预训练模型方面,这里我们使用distiluse-base-multilingual-cased,因为它在相似性任务中表现出了很好的性能,这也是我们对关键词/关键短语提取的目标!
由于transformer模型有token长度限制,所以在输入大型文档时,可能会遇到一些错误。在这种情况下,可以考虑将文档分割成几个小的段落,并对其产生的向量进行平均池化(mean pooling ,要取平均值)。
Python:
model = SentenceTransformer(r'xlm-r-distilroberta-base-paraphrase-v1')

提取关键词
Python:
[B]test_words = []
for row in test.iterrows():
    # 读取第每一行数据的标题与摘要并提取关键词
    # 修改n_gram_range来改变结果候选词的词长大小。例如,如果我们将它设置为(3,3),那么产生的候选词将是包含3个关键词的短语。
    n_gram_range = (2,2)
    # 这里我们使用TF-IDF算法来获取候选关键词
    count = TfidfVectorizer(ngram_range=n_gram_range, stop_words=stops).fit([row[1].text])
    candidates = count.get_feature_names_out()
    # 将文本标题以及候选关键词/关键短语转换为数值型数据(numerical data)。我们使用BERT来实现这一目的
    title_embedding = model.encode([row[1].title])

    candidate_embeddings = model.encode(candidates)

    # 通过修改这个参数来更改关键词数量
    top_n = 15
    # 利用文章标题进一步提取关键词
    distances = cosine_similarity(title_embedding, candidate_embeddings)
    keywords = [candidates[index] for index in distances.argsort()[0][-top_n:]]

    if len( keywords) == 0:
         keywords = ['A', 'B']
    test_words.append('; '.join( keywords))[/B]

预测
Python:
[B]test['Keywords'] = test_words
test[['uuid', 'Keywords']].to_csv('submit_task2.csv', index=None)[/B]
 
主题 作者
成员
荣誉成员
09
17
5

进阶方法:微调ChatGLM2-6b模型解决文本二分类任务​

导入数据​

Python:
import pandas as pd

train_df = pd.read_csv('./csv_data/train.csv')
test_df = pd.read_csv('./csv_data/test.csv')

制作数据集​

Python:
res = []

for i in range(len(train_df)):
    paper_item = train_df.loc[i]
    tmp = {
    "instruction": "Please judge whether it is a medical field paper according to the given paper title and abstract, output 1 or 0, the following is the paper title, author and abstract -->",
    "input": f"title:{paper_item[1]},abstract:{paper_item[3]}",
    "output": str(paper_item[5])
  }
    res.append(tmp)

import json

with open('paper_label.json', mode='w', encoding='utf-8') as f:
    json.dump(res, f, ensure_ascii=False, indent=4)
微调大模型
  • 首先需要clone微调脚本:git clone ``https://github.com/KMnO4-zx/huanhuan-chat.git
  • 进入目录安装环境:cd ./huanhuan-chat;pip install -r requirements.txt
  • 将脚本中的model_name_or_path更换为你本地的chatglm2-6b模型路径,然后运行脚本:sh xfg_train.sh
  • 微调过程大概需要两个小时(我使用阿里云A10-24G运行了两个小时左右),微调过程需要18G的显存,推荐使用24G显存的显卡,比如3090,4090等。
  • 当然,我们已经把训练好的lora权重放在了仓库里,您可以直接运行下面的代码。
  • 更多微调的细节我们会持续在这个仓库更新,欢迎关注star!https://github.com/KMnO4-zx/huanhuan-chat.git

加载训练好的LoRA权重,进行预测​

Python:
from peft import PeftModel
from transformers import AutoTokenizer, AutoModel, GenerationConfig, AutoModelForCausalLM

model_path = "chatglm2-6b"
model = AutoModel.from_pretrained(model_path, trust_remote_code=True).half().cuda()
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
# 加载lora权重
model = PeftModel.from_pretrained(model, 'huanhuan-chat/output/label_xfg').half()
model = model.eval()
response, history = model.chat(tokenizer, "你好", history=[])
response

# 预测函数
def predict(text):
    response, history = model.chat(tokenizer, f"Please judge whether it is a medical field paper according to the given paper title and abstract, output 1 or 0, the following is the paper title, author and abstract -->{text}", history=[],
    temperature=0.01)
    return response

制作submit​

Python:
# 预测测试集
from tqdm import tqdm

label = []

for i in tqdm(range(len(test_df))):
    test_item = test_df.loc[i]
    test_input = f"title:{test_item[1]},author:{test_item[2]},abstract:{test_item[3]}"
    label.append(int(predict(test_input)))

test_df['label'] = label
submit = test_df[['uuid', 'Keywords', 'label']]
submit.to_csv('submit.csv', index=False)
 
顶部