type
Post
status
Published
date
Aug 17, 2023
slug
Datawhale_NLP_01
summary
tags
password
Property
Aug 17, 2023 12:35 PM
category
NLP学习笔记
icon
1. 赛题信息1.1 赛题链接1.2 赛事任务2. 赛题解析2.1 分析问题2.2 baseline代码详解导入库数据清洗特征工程模型训练与验证2.3 调整epoch优化版2.4 调整特征工程从BOW到TF-IDF3. 总结与感受
1. 赛题信息
1.1 赛题链接
基于论文摘要的文本分类与关键词抽取挑战赛
1.2 赛事任务
本任务分为两个子任务:
- 机器通过对论文摘要等信息的理解,判断该论文是否属于医学领域的文献。
- 提取出该论文关键词。
这里只完成了第一个任务。
2. 赛题解析
2.1 分析问题
这是一个文本二分类问题,文本二分类问题是将文本样本分为两个互斥的类别。
常见的解决方法包括以下几种:
- 特征工程和传统机器学习方法:首先,进行特征工程,将文本转化为可以供机器学习算法使用的特征表示,比如词袋模型、TF-IDF向量、n-gram特征等。然后使用传统的机器学习算法,如逻辑回归、支持向量机、朴素贝叶斯等进行建模和分类。
- 卷积神经网络(CNN):CNN在图像识别上大获成功,同样适用于文本分类。通过将文本视为一维序列,使用卷积层和池化层来提取局部特征,并通过全连接层进行分类。
- 循环神经网络(RNN):RNN通过处理序列数据的上下文信息,适用于处理自然语言处理任务,如文本分类。长短时记忆网络(LSTM)和门控循环单元(GRU)是常用的RNN变体。
- Transformer模型:Transformer模型在机器翻译任务上取得了很大成功,也可以用于文本分类。它将文本编码为自注意力机制和位置编码,能够建模长距离依赖关系,有效地捕获全局语义信息。
- 预训练模型(如BERT)微调:预训练模型,如BERT(Bidirectional Encoder Representations from Transformers),通过大规模无标签数据的预训练学习语言表示。然后,可以将其微调到特定的文本二分类任务上,以获得更好的性能。
这里采用第一种:特征工程和传统机器学习方法。
2.2 baseline代码详解
baseline 代码采用BOW(词袋模型)进行特征工程,将文本转化成向量。采用逻辑回归模型进行分类。
导入库
# 导入pandas用于读取表格数据 import pandas as pd # 导入BOW(词袋模型),可以选择将CountVectorizer替换为TfidfVectorizer(TF-IDF(词频-逆文档频率)),注意上下文要同时修改,亲测后者效果更佳 from sklearn.feature_extraction.text import CountVectorizer # 导入LogisticRegression回归模型 from sklearn.linear_model import LogisticRegression # 过滤警告消息 from warnings import simplefilter from sklearn.exceptions import ConvergenceWarning simplefilter("ignore", category=ConvergenceWarning)
数据清洗
将脏数据转化为满足数据质量要求的数据。主要包括缺失值处理、异常值处理、数据分桶、特征归一化/标准化等流程。
这里采用fillna()函数将缺失的值填充为空字符串’’,然后将多列文本合并成text。
# 读取数据集 train = pd.read_csv('/home/aistudio/data/data231041/train.csv') train['title'] = train['title'].fillna('') train['abstract'] = train['abstract'].fillna('') test = pd.read_csv('/home/aistudio/data/data231041/testB.csv') test['title'] = test['title'].fillna('') test['abstract'] = test['abstract'].fillna('') # 提取文本特征,生成训练集与测试集 train['text'] = train['title'].fillna('') + ' ' + train['author'].fillna('') + ' ' + train['abstract'].fillna('')+ ' ' + train['Keywords'].fillna('') test['text'] = test['title'].fillna('') + ' ' + test['author'].fillna('') + ' ' + test['abstract'].fillna('')
特征工程
BOW(Bag of Words)模型是一种基于词频的文本特征表示方法。它将文本数据表示为一个词汇表中的所有单词的统计信息,忽略了单词之间的顺序和语法结构。其基本思想是将每个文本样本看作一个由单词组成的袋子,统计每个单词在文本中出现的次数或使用其他统计量进行表示。
BOW模型的步骤如下:
- 构建词汇表:首先,从训练集中提取出所有的单词,并构建一个词汇表,即包含训练集中所有单词的集合。
- 特征提取:将每个文本样本转化为一个向量表示,其中向量的维度为词汇表中所有单词的数量。对于每个文本样本,统计在词汇表中每个单词的出现次数,这样就得到了一个由词频构成的特征向量。
在代码中,使用CountVectorizer类从文本数据中提取特征。首先,通过fit方法构建词汇表,然后使用transform方法将文本数据转化为特征向量。训练集和测试集都进行了特征提取。
需要注意的是,BOW模型忽略了单词的顺序和句法结构,可能丢失了一些重要的语义信息。如果需要更好地捕捉单词之间的关系和上下文信息,可以考虑使用基于词嵌入的方法,如Word2Vec、GloVe等。
print(train['text']) vector = CountVectorizer().fit(train['text']) train_vector = vector.transform(train['text']) test_vector = vector.transform(test['text']) print(train_vector)
比如,通过打印训练数据特征过程之前和之后的值可以发现,总共有6000个文本样本,刚开始,每一个文本样本里是一段文字,特征过程之后每个文本样本里是一个向量,表示着单词在词汇表里的索引和单词出现的次数。
0 Accessible Visual Artworks for Blind and Visua... 1 Seizure Detection and Prediction by Parallel M... 2 Fast ScanNet: Fast and Dense Analysis of Multi... 3 Long-Term Effectiveness of Antiretroviral Ther... 4 Real-Time Facial Affective Computing on Mobile... ... 5995 ADAPT: A Write Disturbance-Aware Programming T... 5996 Oxy-fuel combustion technology for cement prod... 5997 Ultrasonic‑assisted molten salt hydrates pretr... 5998 Transcriptional Profiling of Pseudomonas aerug... 5999 Deep Learning Architectures for Navigation Usi... Name: text, Length: 6000, dtype: object (0, 1469) 1 (0, 2345) 2 (0, 2348) 1 (0, 2349) 4 (0, 3869) 1 (0, 4268) 1 (0, 4382) 15 (0, 5112) 3 (0, 5290) 1 (0, 5505) 5 (0, 5575) 1 (0, 5585) 1 (0, 5586) 4 (0, 5891) 1 (0, 6096) 3 (0, 6106) 1 (0, 6224) 1 (0, 6545) 1 (0, 7019) 1 (0, 7233) 1 (0, 8463) 3 (0, 9710) 3 (0, 10087) 2 (0, 10744) 1 (0, 11255) 1 : : (5999, 55787) 1 (5999, 55793) 1 (5999, 56524) 7 (5999, 56803) 1 (5999, 57397) 2 (5999, 58547) 1 (5999, 59648) 1 (5999, 60106) 1 (5999, 60119) 12 (5999, 60238) 1 (5999, 60322) 1 (5999, 60382) 1 (5999, 60799) 3 (5999, 61251) 1 (5999, 61262) 2 (5999, 61385) 2 (5999, 62124) 1 (5999, 62597) 2 (5999, 63062) 1 (5999, 63083) 6 (5999, 65034) 1 (5999, 65276) 2 (5999, 65404) 1 (5999, 66915) 1 (5999, 67033) 1
模型训练与验证
# 引入模型 model = LogisticRegression() # 开始训练,这里可以考虑修改默认的batch_size与epoch来取得更好的效果 model.fit(train_vector, train['label']) # 利用模型对测试集label标签进行预测 test['label'] = model.predict(test_vector) test['Keywords'] = test['title'].fillna('') test[['uuid','Keywords','label']].to_csv('submit_task1.csv', index=None)
2.3 调整epoch优化版
那为什么要调整epoch(迭代次数)呢?
epoch是指模型在训练集上迭代的次数。增加epoch可以增加模型在训练集上的学习次数,有助于模型更好地拟合训练数据。但是,如果epoch设置得过大,模型可能会过拟合训练数据,导致过高的训练误差和泛化能力下降。相反,如果epoch太小,模型可能没有充分学习训练数据的特征。
因此我通过在[10,40]之间变化epoch取值,观察准确率随epoch的变化趋势,从而获得最佳epoch。
输出结果为:
最大准确度:0.9825,对应的epoch:28
import pandas as pd from sklearn.feature_extraction.text import CountVectorizer from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split import matplotlib.pyplot as plt import numpy as np # 读取训练集数据 train = pd.read_csv('train.csv') # 数据处理 train['text'] = train['title'].fillna('') + ' ' + train['author'].fillna('') + ' ' + train['abstract'].fillna('') vector = CountVectorizer().fit(train['text']) train_vector = vector.transform(train['text']) epochs = range(10, 40) # 调整的epoch范围 # 记录预测准确率 accuracies = [] # 划分训练集和验证集 X_train, X_val, y_train, y_val = train_test_split(train_vector, train['label'], test_size=0.2, random_state=42) # 调整epoch for epoch in epochs: model = LogisticRegression(max_iter=epoch) model.fit(X_train, y_train) accuracy = model.score(X_val, y_val) accuracies.append(accuracy) # 找到最大准确度和对应的epoch max_accuracy = max(accuracies) max_epoch = epochs[accuracies.index(max_accuracy)] # 打印最大准确度对应的epoch print(f"最大准确度:{max_accuracy},对应的epoch:{max_epoch}") # 绘制准确率随epoch变化的趋势图 plt.plot(epochs, accuracies, marker='o') plt.xlabel('Epochs') plt.ylabel('Accuracy') plt.title('Accuracy vs Epochs') # plt.xticks(np.arange(min(epochs), max(epochs)+1, 1)) plt.show()
2.4 调整特征工程从BOW到TF-IDF
from sklearn.feature_extraction.text import TfidfVectorizer
引入库后将代码里的
vector = CountVectorizer().fit(train['text']) 改成 vector =TfidfVectorizer().fit(train['text'])
3. 总结与感受
从3到1依次是baseline版本,epoch=28版本,特征工程选取了TF-IDF版本。(最后一个忘写备注了)
总的来说,我学到了很多!这得益于群里很好的交流氛围,还有夏令营里的资料真的非常详细,助教也很耐心解答。通过这个项目,我学会了
- 机器学习解决问题的一般流程(数据清洗——>特征工程——>模型训练)。
- 通过自己摸索了解了BOW模型的工作原理(建立词汇表——>构建词在词汇表里的唯一索引——>将文本转化成向量)。
- 了解了逻辑回归模型的工作原理(训练:不断迭代训练使得损失函数越来越小从而确定权重和偏置值。预测:输出值=权重*输入值+权重,然后经过sigmod函数转化成[0,1]区间里的值,与阈值比较大小判断是或否),之前有听说到损失函数这些,但没弄懂过,这次让我对之前的知识有了连接~
- 自己尝试优化。(尝试改变epoch参数:在[10,40]之间变化epoch取值,观察准确率随epoch的变化趋势,从而获得最佳epoch。尝试改变特征工程:使用TF-IDF代替BOW),优化都有一定但不明显的效果改进。
- 希望能学到更多提升竞赛分数的解决方法,看着分数一点点提升真的很有成就感!
- Author:crystal
- URL:https://blog-crystal520.vercel.app/article/Datawhale_NLP_01
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!