基于飞浆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准确率,当然如果你解冻更多参数,自然可以更加精确,看运行环境的配置了,建议不要使用免费平台配置,否则比乌龟还慢。。

欢迎提出问题

数据集

相关推荐
诸葛务农几秒前
共沸脱水技术及其在光刻胶用PGMEA纯化中的应用(下)
人工智能
雪隐几秒前
AI股票小助手04-miniQMT数据采集
人工智能·后端
sugar__salt2 分钟前
从零落地 Generative AI 接口调用:Node.js 工程化最佳实践
人工智能·node.js
不要额外加糖2 分钟前
给 Codex 戴上紧箍, 治一治 AI 的过度发挥
前端·人工智能·代码规范
weixin_468466853 分钟前
空洞卷积与膨胀卷积新手入门指南
图像处理·人工智能·深度学习·ai·机器视觉·卷积·空洞卷积
小江的记录本3 分钟前
【JVM虚拟机】类加载机制:类加载器、双亲委派模型、好处、破坏双亲委派的场景(附《思维导图》+《面试高频考点清单》)
java·jvm·spring boot·后端·python·spring·面试
AI创界者4 分钟前
ComfyUI v8 极致整合包发布!Win/Mac 双平台完美适配 + 多卡并行加速,开启 AI 绘画新时代
人工智能·macos
zhangfeng11334 分钟前
本账号 自媒体 csdn 账号诊断和改进建议,记录一下
人工智能·机器学习·媒体
镭封5 分钟前
影视解说、小说推文、情感语录,分别适合什么AI声音?
人工智能
ZPC82106 分钟前
前馈补偿原理 + 分类 + 公式 + 工程实现(配合 PID 使用,从根源减轻闭环收敛压力)
人工智能·分布式·机器人