基于飞浆NLP的BERT-finetuning新闻文本分类

目录

1.数据预处理

2.加载模型

3.批训练

4.准确率

1.数据预处理

导入所需库

python 复制代码
import numpy as np
from paddle.io import DataLoader,TensorDataset
from paddlenlp.transformers import BertForSequenceClassification, BertTokenizer
from sklearn.model_selection import train_test_split
import paddle
import matplotlib.pyplot as plt
import jieba

训练集格式 标签ID+\t+标签+\t+原文标题

python 复制代码
contents=[]
datas=[]
labels=[]
with open('data/data126283/data/Train.txt',mode='r',encoding='utf-8') as f:
    contents=f.read().split('\n')
for item in contents:
    if item=='':
        continue
    labels.append(item.split('\t')[0])
    datas.append(remove_stopwords(jieba.cut(item.split('\t')[-1])))

datas=convert(datas)

去除停用词、

python 复制代码
stop=[]
with open('stop.txt',mode='r',encoding='utf-8') as f:
    stop=f.read().split('\n')
stop_word={}
for s in stop:
    stop_word[s]=True
def remove_stopwords(datas):  
    filtered_words = [text for text in datas if text not in stop_word]
    return ' '.join(filtered_words)  

进行中文分词、转换为token序列

python 复制代码
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')

def convert(datas, max_seq_length=40):
    ans=[]
    for text in datas:
        input_ids = tokenizer(text, max_seq_len=max_seq_length)['input_ids']
        input_ids = input_ids[:max_seq_length]  # 截断
        input_ids = input_ids + [tokenizer.pad_token_id] * (max_seq_length - len(input_ids))  # 填充
        ans.append(input_ids)
    return ans

导入数据,进行预处理,数据集在最后

python 复制代码
contents=[]
datas=[]
labels=[]
with open('data/data126283/data/Train.txt',mode='r',encoding='utf-8') as f:
    contents=f.read().split('\n')
for item in contents:
    if item=='':
        continue
    labels.append(item.split('\t')[0])
    datas.append(remove_stopwords(jieba.cut(item.split('\t')[-1])))

datas=convert(datas)

2.加载模型

加载预训练模型,冻结大部分参数

python 复制代码
model = BertForSequenceClassification.from_pretrained('bert-base-chinese')
model.classifier = paddle.nn.Linear(768, 14)
for name, param in model.named_parameters():
    if "classifier" not in name and 'bert.pooler.dense' not in name and 'bert.encoder.layers.11' not in name:
        param.stop_gradient = True

ps:如果只保留classifier用来训练,效果欠佳。

设置超参数,学习率初始设为0.01~0.1

python 复制代码
epochs=2
batch_size=1024*4
learning_rate=0.001

损失函数和优化器

python 复制代码
criterion = paddle.nn.CrossEntropyLoss()
optimizer = paddle.optimizer.Adam(learning_rate=learning_rate, parameters=model.parameters())

3.批训练

划分训练集和测试集

python 复制代码
datas=np.array(datas)
labels=np.array(labels)
x_train,x_test,y_train,y_test=train_test_split(datas,labels,random_state=42,test_size=0.2)
train_dataset=TensorDataset([x_train,y_train])
train_loader=DataLoader(train_dataset,shuffle=True,batch_size=batch_size)

迭代分批训练,可视化损失函数

python 复制代码
total_loss=[]
for epoch in range(epochs):
    for batch_data,batch_label in train_loader:
        batch_label=paddle.to_tensor(batch_label,dtype='int64')
        batch_data=paddle.to_tensor(batch_data,dtype='int64')
        outputs=model(batch_data)
        loss=criterion(outputs,batch_label)
        print(epoch,loss.numpy()[0])
        total_loss.append(loss.numpy()[0])
        optimizer.clear_grad()
        loss.backward()
        optimizer.step()
paddle.save({'model':model.state_dict()},'model.param')
paddle.save({'optimizer':optimizer.state_dict()},'optimizer.param')
plt.plot(range(len(total_loss)),total_loss)
plt.show()

4.准确率

在测试集上如法炮制,查看准确率

python 复制代码
total_loss=[]
x_test=np.array(x_test)
y_test=np.array(y_test)
test_dataset=TensorDataset([x_test,y_test])
test_loader=DataLoader(test_dataset,shuffle=True,batch_size=batch_size)

with paddle.no_grad():
    for batch_data,batch_label in test_loader:
        batch_label=paddle.to_tensor(batch_label,dtype='int64')
        batch_data=paddle.to_tensor(batch_data,dtype='int64')
        outputs=model(batch_data)
        loss=criterion(outputs,batch_label)
        print(loss)
        outputs=paddle.argmax(outputs,axis=1)
        total_loss.append(loss.numpy()[0])
        score=0
        for predict,label in zip(outputs,batch_label):
            if predict==label:
                score+=1
        print(score/len(batch_label))
plt.plot(range(len(total_loss)),total_loss)
plt.show()

最后在验证集上输出要求的类别

python 复制代码
arr=['财经','彩票','房产','股票','家居','教育','科技','社会','时尚','时政','体育','星座','游戏','娱乐']
evals=[]
contetns=[]
with open('data/data126283/data/Test.txt',mode='r',encoding='utf-8') as f:
    contents=f.read().split('\n')
for item in contents:
    if item=='':
        continue
    evals.append(item)
evals=convert(evals)
evals=np.array(evals)
with paddle.no_grad():
    for i in range(0,len(evals),2048):
        i=min(len(evals),i)
        batch_data=evals[i:i+2048]
        batch_data=paddle.to_tensor(batch_data,dtype='int64')
        predict=model(batch_data)
        predict=list(paddle.argmax(predict,axis=1))
        print(i,len(predict))
        for j in range(len(predict)):
            predict[j]=arr[predict[j]]
        with open('result.txt',mode='a',encoding='utf-8') as f:
            f.write('\n'.join(predict))
            f.write('\n')

ps:注意最后的f.write('\n'),否则除第一次,每次打印少一行,很坑

最后损失函数收敛在0.2或0.1左右比较正常,四舍五入差不多90准确率,当然如果你解冻更多参数,自然可以更加精确,看运行环境的配置了,建议不要使用免费平台配置,否则比乌龟还慢。。

欢迎提出问题

数据集

相关推荐
☆璇42 分钟前
【数据结构】排序
c语言·开发语言·数据结构·算法·排序算法
ATM0061 小时前
人机协作系列(四)AI编程的下一个范式革命——看Factory AI如何重构软件工程?
人工智能·大模型·agent·人机协作·人机协同
读创商闻2 小时前
极狐GitLab CEO 柳钢——极狐 GitLab 打造中国企业专属 AI 编程平台,引领编程新潮流
人工智能·gitlab
kailp2 小时前
语言模型玩转3D生成:LLaMA-Mesh开源项目
人工智能·3d·ai·语言模型·llama·gpu算力
marteker2 小时前
弗兰肯斯坦式的人工智能与GTM策略的崩溃
人工智能·搜索引擎
无心水2 小时前
大语言模型零样本情感分析实战:无需机器学习训练,96%准确率实现指南
人工智能·机器学习·语言模型
来自于狂人2 小时前
AI大模型训练的云原生实践:如何用Kubernetes指挥千卡集群?
人工智能·云原生·kubernetes
艾莉丝努力练剑4 小时前
【LeetCode&数据结构】单链表的应用——反转链表问题、链表的中间节点问题详解
c语言·开发语言·数据结构·学习·算法·leetcode·链表
_殊途5 小时前
《Java HashMap底层原理全解析(源码+性能+面试)》
java·数据结构·算法
橡晟7 小时前
深度学习入门:让神经网络变得“深不可测“⚡(二)
人工智能·python·深度学习·机器学习·计算机视觉