自然语言处理,Datawhale 夏令营,学习笔记7.27

前言

因为大学上过商业数据分析,这个活动的任务一文本二分类,对我而言只是从几个熟悉的模型(逻辑回归、SVC、朴素贝叶斯等)里跑跑分调调参。

任务二:
                从论文标题、摘要作者等信息,提取出该论文关键词。

比较下来任务二,就是在找一堆陌生的模型,下载,复制人家代码,改数据集,试着跑以下,然后得到失望的结果。

附上7.22笔记:自然语言处理,Datawhale 夏令营,学习笔记7.22

提供的实践材料

任务二的Baseline:

# 引入分词器
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)

Baseline中使用的方法大致是:在设置停用词对文本过滤后,选取频率最高的词语作为关键词。显然,单纯以"词频"衡量一个词的重要性,不够准却。

以下是提供大模型的方法:

# 导入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)

# 读取数据集
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()] 

model = SentenceTransformer(r'xlm-r-distilroberta-base-paraphrase-v1')

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))
    
test['Keywords'] = test_words
test[['uuid', 'Keywords']].to_csv('submit_task2.csv', index=None)

使用了某个Bert模型,我最终输出分数大概0.35左右(写笔记时提交记录好像已经无了,所以除了最终分数其实都不太清楚)。我想办法测试模型效果,估计大概有0.3都是任务一lable预测的分数,和任务二预测Keywords没关系。

最终个人的方法

最终得分只有0.38784。

老实讲,做完两个比赛给的代码就不太知道怎么办了。我对大模型不太有操作的能力,只能从网上找了写关键词提取算法跑一边看看结果。想过拿预训练模型用任务一时提供的含关键词的数据集进行训练,但只是想想,并不知道怎么做,也不太知道效果。

以下是我使用忘了是哪个模型的一次尝试的测试效果的代码,首先确保导入的数据是train.csv,

for row in test[:10].iterrows():
    #从数据集keywords制作['kw1','kw2',...]
    true_keywords = row[1].Keywords.split(';')
    print(true_keywords)
    #根据情况调整的代码,结果要得到模型输出的keywords列表
    keywords = []
    for i in kw_extractor.extract_keywords(row[1].text):
        keywords.append(i[0])
    print(keywords)
    #看看效果得分
    score = 0
    for keyword in keywords:
        if keyword in true_keywords:
            score += 1
    print(score)

然后就会发现结果惨不忍睹。

我最后使用的是Yake主要是用起来简单,而且重视大写,对论文输出关键词有意外效果。

pip install git+https://github.com/LIAAD/yake
# 导入pandas用于读取表格数据
import pandas as pd

import yake

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

# 读取数据集
test = pd.read_csv('testB.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()] 

kw_extractor = yake.KeywordExtractor(top=40, n=3,stopwords = stops)

test_words = []
i = 0
for row in test.iterrows():

    keywords = []
    for kw in kw_extractor.extract_keywords(row[1].text):
        keywords.append(kw[0])
    test_words.append('; '.join( keywords))
    
    i += 1
    if i%100 == 0:
        print(i)

test['Keywords'] = test_words
test[['uuid', 'Keywords']].to_csv('submit_task2——2.4.csv', index=None)

很一般,在我对train前十条进行测试,大概5条能答出1个,另外一个都不对

你可能感兴趣的:(学习,笔记)