栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

NLP竞赛参与打卡记录:汽车领域多语种迁移学习挑战赛

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

NLP竞赛参与打卡记录:汽车领域多语种迁移学习挑战赛

NLP竞赛参与打卡记录:汽车领域多语种迁移学习挑战赛

本博客为Coggle 30 Days of ML(22年7月)竞赛打卡活动记录页面,会记录本人的打卡内容。活动链接为:活动链接

任务1:比赛报名 步骤1:报名比赛

前往竞赛地址,完成账号注册和比赛的报名。
报名成果截图:

步骤2:下载比赛数据

在竞赛页面点击数据下载:

步骤3:解压比赛数据,并使用pandas进行读取

将下载下来的内容进行解压,然后调用pandas进行读取,展示
读取的代码如下:

import pandas as pd
train_cn = pd.read_excel("data/1/中文_train.xlsx")
train_en = pd.read_excel("data/1/英文_train.xlsx")
train_jp = pd.read_excel("data/1/日语_train.xlsx")

test_a = pd.read_excel("data/testA.xlsx")

要展示的话,你可以选择print或者在jupoyter notebook上直接用变量名

步骤4:查看数据类型

可以用pandas的info()来查看训练集和测试集的相关字段信息

print("cn train")
print(train_cn.info())
print("---"*10)
print("en train")
print(train_en.info())
print("---"*10)
print("jp train")
print(train_jp.info())
print("---"*10)
print("testa")
print(test_a.info())

任务2:文本分析与文本分词 步骤1:使用jieba对中文进行分词;

jieba是常用的处理中文字符的第三库,关于它的用法可自行搜索。
先用pip来安装它

pip install jieba

然后,我们可以利用jieba进行简单的中文分词

import jieba

def cutword(txt):
    return jieba.lcut(txt)

train_cn['phase'] = train_cn['原始文本'].apply(cutword)

步骤2:使用negisa对日语进行分词

对于日文的数据,我们可以使用negisa这个库来进行分词操作;具体的用法可见官方文档negisa;直接pip安装需要一定时间(视网络条件而定,这个包20m左右大小;一般还会安装其他依赖)
类似的,分词代码如下

import nagisa

def cutword_jp(txt):
    words = nagisa.tagging(txt)
    return words.words

train_jp['phase'] = train_jp['原始文本'].apply(cutword_jp

任务3:TFIDF与文本分类

任务3总的来说可以参考Coggle 给的例子。

步骤1:学习TFIDF的使用,提取语料的TFIDF特征;步骤2:使用逻辑回归结合TFIDF进行训练(所有的语言语料),并对测试集的意图进行分类

这里,两个步骤是可以合并在一起完成的,因为可以把提取特征和逻辑回归一起构建成一个pipeline,一起进行训练。
第一部分,数据预处理代码如下:

import pandas as pd 
import numpy as np 
import nagisa 

from sklearn.feature_extraction.text import TfidfVectorizer # 文本特征提取
from sklearn.linear_model import LogisticRegression # 逻辑回归
from sklearn.pipeline import make_pipeline # 组合流水线

# 读取数据
train_cn = pd.read_excel("data/1/中文_train.xlsx") # 因为test仅包含英文和中文,所以本次没有使用cn的数据来加强特征学习
train_en = pd.read_excel("data/1/英文_train.xlsx")
train_jp = pd.read_excel("data/1/日语_train.xlsx")

test_jp = pd.read_excel('data/testA.xlsx', sheet_name='日语_testA')
test_en = pd.read_excel('data/testA.xlsx', sheet_name='英文_testA')

# 文本分词
train_jp['words'] = train_jp['原始文本'].apply(lambda x: ' '.join(nagisa.tagging(x).words))
train_en['words'] = train_en['原始文本'].apply(lambda x: x.lower())
test_jp['words'] = test_jp['原始文本'].apply(lambda x: ' '.join(nagisa.tagging(x).words))
test_en['words'] = test_en['原始文本'].apply(lambda x: x.lower())

第二部分,就是简单划分一下train数据集,然后进行模型的训练;代码如下:

from sklearn.model_selection import train_test_split #y用于切分数据集

# 以8:2的比例来划分训练集和验证集
train_en1, dev_en = train_test_split(train_en, test_size=.2, random_state=2)
train_jp1, dev_jp = train_test_split(train_jp, test_size=.2, random_state=2)

# 训练TFIDF和逻辑回归
pipline = make_pipeline(
    TfidfVectorizer(),
    LogisticRegression()
)

pipline.fit(
    train_jp1['words'].tolist() + train_en1['words'].tolist(),
    train_jp1['意图'].tolist() + train_en1['意图'].tolist()
)

dev_a = dev_en['words'].tolist() + dev_jp['words'].tolist()
output_dev = pipline.predict(dev_a)
num_dev = len(dev_a)
tmp = 0
for i in range(num_dev):
    if(output_dev[i] == y_dev[i]):
        tmp += 1
acc = tmp / num_dev
print(acc)

train1 = train_en1['words'].tolist() + train_jp1['words'].tolist()
y_train = train_en1['意图'].tolist() + train_jp1['意图'].tolist()
output_train = pipline.predict(train1)
num_train = len(train1)
tmp = 0
for i in range(num_train):
    if(output_train[i] == y_train[i]):
        tmp += 1
acc_train = tmp / num_train
print(acc_train)

两个acc的结果可见截图:

额外思考

其实TfidfVectorizer()和LogisticRegression()是有很多参数提供使用的;但是在简单的测试参数的时候,发现貌似默认的情况会好一点?(当然,没有认真去调参,只是简单加几个参数,看看acc的差别)
代码如下:

# 训练TFIDF和逻辑回归
pipline = make_pipeline(
    TfidfVectorizer(ngram_range=(1,3)),
    LogisticRegression(tol=1e-5)
)

只是简单给个例子,因为参数组合比较多,不放全部组合的例子了
结果见图:

所以,目前来看,默认情况貌似会更好一丢丢~

步骤3:将步骤2预测的结果文件提交到比赛,截图分数

最终输出的不仅需要意图,很多情况还有具体的参数,比如空调调到多少度。但是这里,先完成打卡,先把这个结果提交一下(从学习的角度来看是可以的,但是如果你想要分数高一点,毕竟是竞赛,可以等任务4,再具体得到而外的输出再一起提交)

任务4:正则表达式

任务4是使用正则表达式来提取字符串中的槽值,但是这个在不同语言是不一样的,而且对于不同的意图,还要单独处理,相对来说,是不推荐使用的,但是学习是ok的。所以本博客会进行简单的正则使用, 但不会将其用于竞赛中,槽值的提取留到后面几个任务再慢慢调优。

问题

不同的文本,里面的指标是不一样的,比如数值,中文是阿拉伯数字,日语则是中文字符的数字(“一”、“二”等),英文则是one、two……



所以是比较难找到一种通用的字符串处理来应付所有的文本,所以这就是不推荐在竞赛中使用正则表达式来提取关键字的原因。

步骤1:提取连续数字

这里展示两个,一个是中文的阿拉伯数字,这个比较简单;另一个是日语中使用的“一”、“二”……;英文就不处理了(按我的写法的话,太多了苦笑)

import re

def get_num_last(txt):
    return re.findall("d+.?d*", txt)
train_cn['num_last'] = train_cn['原始文本'].apply(get_num_last)
print(train_cn)
import re

def get_num_last(txt):
    return re.findall("[一|二|三|四|五|六|七|八|九|十]+", txt)
train_jp['num_last'] = train_jp['原始文本'].apply(get_num_last)
print(train_jp)

当然这省略了上面的数据处理部分,但是正则部分已经在这里了,python的话一般使用re这个库来处理正则表达式。

步骤2:使用正则表达式进行槽值匹配(基于历史的槽值字符串)

虽然这里会有我的简单代码,但是还是要说一句,不推荐这么做;因为后面会有任务来处理槽值的,更准确且没那么麻烦(个人是怎么觉得的,虽然要搭建模型来训练也不是简洁的事)

def getcaozhi_offset(txt):
    num_l = get_num_last(txt)
    if len(num_l) > 0:
        return "offset:" + num_l[-1]
    else:
        return np.nan
train_cn['槽值_test'] = np.nan
for i in range(len(train_cn)):
    #以意图作为条件,分别进行正则,来提取槽值
    if train_cn.iloc[i, 1] == "adjust_ac_temperature_to_number":
        train_cn['槽值_test'][i] = getcaozhi_offset(train_cn.iloc[i, 0])
print(train_cn)

思路就是根据意图(train里本来就有的,或者是你用模型的预测输出也可以),来分别对待。比如是调温度的话,就调用步骤1中的提取数字的函数,因为往往最后一个数字是我们的目标温度,所以使用最后一个数字作为温度调节的槽值。

其他的有点繁琐,就不细写了……

任务5:BERT模型入门 步骤1:学习transformers库中pipline和加载模型的过程

使用Hugging Face的transformers库可以让我们快速上手nlp的模型。这个库包含了大量的目前流行的预训练模型,我们只需几行代码,便可下载并应用,后面再根据实际数据做下游任务的微调。

首先是下载模型,去Hugging Face的官网找到你要的模型,hugging face


在这里搜索你想要使用的预训练模型,比如bert,然后选一个点进去

在右上角,点击use in transformers,里面会有简单的使用案例;但是因为网络的原因,很可能你直接复制粘贴下来,会报错(因为transformers会先在服务器上找到你想要的模型,然后下载到你电脑的缓存中,再进行加载);网络问题导致不能下载的,你可以手动下载;使用如下代码:

from huggingface_hub import snapshot_download 
snapshot_download(repo_id="hfl/chinese-roberta-wwm-ext") #id填你想要下载的模型名称,要和官网上的一致

然后他就会下载到你的缓存目录了(如果库没安装,可以pip安装一下)

最后它会提示你下载到你电脑的地址,你去找,然后复制到你自己项目的地址,给他新建个文件夹,取个短点的名字(方便你后续加载使用)

然后,就可以根据要求,加载模型了

import transformers
from transformers import AutoTokenizer, AutoModelForSequenceClassification

model_path = "../model/bert-chinese"
model = AutoModelForSequenceClassification.from_pretrained(
            model_path,  # 小写的 12 层预训练模型
            num_labels=17,  # 分类数 --2 表示二分类
            # 你可以改变这个数字,用于多分类任务
            # output_attentions=False,  # 模型是否返回 attentions weights.
            # output_hidden_states=False,  # 模型是否返回所有隐层状态.
        )
tokenizer = AutoTokenizer.from_pretrained(model_path)

pipeline = transformers.TextClassificationPipeline(model=model, tokenizer = tokenizer)

print(pipeline(train_cn['原始文本'][0]))

步骤2:学习transformers库的使用:包括定义数据集,定义模型和训练模型 任务6:BERT文本分类

Todo…

任务7:BER实体抽取

Todo…

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/998528.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号