亲宝软件园·资讯

展开

微博立场检测 60分Baseline

数学家是我理想 人气:1
AI研习社最近举办了一个比赛——[微博立场检测](https://god.yanxishe.com/44),实际上就是一个NLP文本分类的比赛 ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9zMS5heDF4LmNvbS8yMDIwLzAzLzE0Lzhselowcy5wbmc?x-oss-process=image/format,png#shadow) ### Baseline—FastText 我的Baseline方法用的是pkuseg分词+FastText,最好成绩是60,下面是我几次提交的得分截图 ![](https://img-blog.csdnimg.cn/20200316101419790.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3MjM2NzQ1,size_16,color_FFFFFF,t_70) #### Load Data & Preprocess 先import之后要用到的库 ```python import pkuseg import random import pandas as pd import fasttext ``` ```python df = pd.read_csv('train.csv', delimiter='\t') ``` 官方给的数据,虽然是csv文件,但是字段之间用的是`\t`隔开的,所以读取的时候注意一下就行了。数据样式如下 ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9zMS5heDF4LmNvbS8yMDIwLzAzLzE0LzhseE82ZS5wbmc?x-oss-process=image/format,png#shadow) `stance`字段有三类,分别是`FAVOR`、`AGAINST`、`NONE`,这也是你需要最终预测的值。但是通过仔细分析数据可以发现,`stance`字段除了上面三个值以外还有别的值,所以要先把其它的数据剔除掉 ```python drop_list = [] for i in range(len(df)): if df.stance[i] != 'FAVOR' and df.stance[i] != 'AGAINST' and df.stance[i] != 'NONE': drop_list.append(i) df.drop(drop_list, inplace=True) ``` FastText读取的数据应该满足`__lable__xx text`,例如 ``` __label__A 我 喜欢 打 篮球 __label__B 我 喜欢 鲲鲲 __label__A 我 喜欢 踢 足球 ``` 也就是说,每一行表示一个样本,并且标签在前,文本在后,两者之间用空格隔开。标签必须以`__label__`开头。所以我们要先把原始数据的标签进行一个转换,即`FAVOR`变成`__label__A`,`AGAINST`变成`__label__B`,`NONE`变成`__label__C` ```python mapping = {'FAVOR':'__label__A', 'AGAINST':'__label__B', 'NONE':'__label__C'} df['stance'] = df['stance'].map(mapping) ``` 这些都做完以后最好shuffle一下数据 ```python df = df.sample(frac=1) ``` `sample(frac=p)`其中$p\in[0,1]$,意思是随机sample出原始数据的百分之多少,如果$p=1$,则表示随机sample出原始数据的全部,并且由于是随机sample的,所以原始数据的顺序就被打乱了 #### Split Train & Validation Data 这里我以7:3的比例将数据集拆分成Train Data和Valid Data ```python train_len = int(len(df) * 0.7) df_train = df.loc[:train_len] df_val = df.loc[train_len:] ``` #### Word Segmentation 从FastText读取数据的样式可以看出,我们需要对一句话进行分词。这里我用的是pkuseg,因为我看它官方API介绍的时候,里面提到它有一个web语料库 在分词前,我先从网上找了一些常见的中英文停用词 ```python stopwords = [] for line in open('stopwords.txt', encoding='utf-8'): stopwords.append(line) stopwords.append('\n') stopwords = set(stopwords) ``` 停用词表我就不提供了,网上有很多,自己下载即可 然后是一行一行读取数据并分词,分完词再过滤。这些都做完以后,按照FastText要求的格式,拼接字符串,保存到文件中 ```python def dump_file(df, filename, mode='train'): seg = pkuseg.pkuseg(model_name='web') with open(filename, 'w',encoding='utf-8') as f: for i in df.index.values: segs = seg.cut(df.text[i]) segs = filter(lambda x:x not in stopwords, segs) #去掉停用词 # segs = filter(lambda x:len(x)>1,segs) segs = filter(lambda x:x.startswith('http')==False, segs) segs = filter(lambda x:x.startswith('.')==False, segs) segs = filter(lambda x:x.startswith('-')==False, segs) segs = filter(lambda x:x.startswith(',')==False, segs) segs = filter(lambda x:x.startswith('。')==False, segs) segs = filter(lambda x:x.startswith('…')==False, segs) segs = filter(lambda x:x.startswith('/')==False, segs) segs = filter(lambda x:x.startswith('—')==False, segs) segs = filter(lambda x:x.startswith('、')==False, segs) segs = filter(lambda x:x.startswith(':')==False, segs) segs = filter(lambda x:x.startswith('~')==False, segs) segs = filter(lambda x:x.startswith('[')==False, segs) segs = filter(lambda x:x.startswith(']')==False, segs) segs = filter(lambda x:(x.isalpha() and len(x) == 7) == False, segs) string = '' for j in segs: string = string + ' ' + j if mode == 'test': string = string.lstrip() else: string = df.stance[i] + ' ' + string string = string.lstrip() f.write(string + '\n') ``` ```python dump_file(df_train, 'train.txt', 'train') dump_file(df_val, 'val.txt', 'train') ``` #### FastText 首先从它官方的github仓库中clone dev版本(直接使用pip install fasttext是稳定版) ```shell $ git clone https://github.com/facebookresearch/fastText.git $ cd fastText $ pip install . ``` 因为最新的dev版本中有一个参数`autotuneValidationFile`可以在训练过程中自动搜索使得acc最大的参数。fastText使用也很简单 ```python clf = fasttext.train_supervised(input='train.txt', autotuneValidationFile='val.txt') ``` 指定训练集以及用于帮助寻找最优参数的测试集的路径即可。如果要保存模型就用 ```python clf.save_model('fasttext_model') ``` #### Predict & Submit 基本上如果你按照我的方法一路做下来,到现在为止在验证集上的最大分数也就60左右 然后就是对test集进行预测,预测完了提交就行了 ```python test = pd.read_csv('test.csv', delimiter='\t') dump_file(test, 'test.txt', 'test') labels = [] for line in open('test.txt', encoding='utf-8'): if line != '': line = line.strip('\n') labels.append(clf.predict(line)[0][0]) test['idx'] = range(len(test)) test['stance'] = labels mapping = {'__label__A':'FAVOR','__label__B':'AGAINST','__label__C':'NONE'} test['stance'] = test['stance'].map(mapping) test = test.drop(['target', 'text'], axis=1) test.to_csv('test_pred.csv',index=False,header=False) ``` ### Improve 1. 我的做法只用了`text`和`stance`这两列,`target`我觉得可以用也可以不用 2. 仔细观察数据集会发现,其实样本分布及其不均匀,`stance`列中`FAVOR`和`AGAINST`两个值特别多,`NONE`特别少,这就涉及到不均衡样本的训练问题,可以通过sample,将它们的比例设置的比较均衡了再训练 3. 过滤词设置的更详细一点。如果你仔细查看了分词后的数据集,你应该能发现里面其实还有很多垃圾词,比方说网址、7位验证码、表情之类的 4. 直接上BERT

加载全部内容

相关教程
猜你喜欢
用户评论