AI Instituteは最近、コンテスト-Weibo位置検出を組織しました。これは、実際にはNLPテキスト分類コンテストです。
ベースラインFasttext
私のベースラインメソッドはpkuseg単語セグメンテーション+ FastTextを使用しています。最高のスコアは60です。以下は、私が何度か送信したスコアのスクリーンショットです
データの読み込みと前処理
インポート後に使用するライブラリ
import pkuseg
import random
import pandas as pd
import fasttext
df = pd.read_csv('train.csv', delimiter='\t')
公式データですがcsvファイルですがフィールドが\t
分かれているので注意して読んでください。データスタイルは以下の通りです
stance
三つのフィールドがあり、すなわちFAVOR
、AGAINST
、NONE
これはあなたが最終的な値を予測するために必要なものです。ただし、データを注意深く分析すると、stance
フィールドに上記の3つの値に加えて他の値があることがわかるため、最初に他のデータを削除する必要があります。
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
mapping = {'FAVOR':'__label__A', 'AGAINST':'__label__B', 'NONE':'__label__C'}
df['stance'] = df['stance'].map(mapping)
これらが完了したら、データをシャッフルするのが最善です
df = df.sample(frac=1)
sample(frac=p)
どこに
は、元のデータの何パーセントがランダムにサンプリングされるかを意味します。
、つまり、すべての元のデータがランダムにサンプリングされ、ランダムなサンプルであるため、元のデータの順序が乱されます
列車と検証データの分割
ここで、データセットを7の比率でトレーニングデータと有効データに分割します。3
train_len = int(len(df) * 0.7)
df_train = df.loc[:train_len]
df_val = df.loc[train_len:]
単語セグメンテーション
データを読み取るFastTextのスタイルから、文をセグメント化する必要があることがわかります。ここではpkusegを使用します。公式のAPIの紹介を見て、ウェブコーパスがあると述べたからです。
単語を分割する前に、インターネットから中国語と英語の一般的なストップワードを最初に見つけました
stopwords = []
for line in open('stopwords.txt', encoding='utf-8'):
stopwords.append(line)
stopwords.append('\n')
stopwords = set(stopwords)
ストップワードは提供しません。オンラインにはたくさんあります。自分でダウンロードできます。
次に、データを1行ずつ読み取り、単語をセグメント化してから、単語をフィルタリングします。これらがすべて完了したら、FastTextで必要な形式に従って、文字列を連結してファイルに保存します
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')
dump_file(df_train, 'train.txt', 'train')
dump_file(df_val, 'val.txt', 'train')
Fasttext
まず、公式のgithubリポジトリからクローンバージョンをクローンします(pip install fasttextを直接使用すると、安定したバージョンになります)。
$ git clone https://github.com/facebookresearch/fastText.git
$ cd fastText
$ pip install .
最新のdevバージョンには、autotuneValidationFile
トレーニング中にaccを最大化するパラメーターを自動的に検索できるパラメーターがあるためです。fastTextも非常に使いやすい
clf = fasttext.train_supervised(input='train.txt', autotuneValidationFile='val.txt')
最適なパラメーターを見つけるために、トレーニングセットとテストセットのパスを指定するだけで十分です。モデルを保存する場合に使用します
clf.save_model('fasttext_model')
予測して送信
基本的に、私の方法に従って最後まで行うと、これまでの検証セットの最大スコアは約60になります。
次に、テストセットを予測します。予測が完了したら、送信するだけで十分です。
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)
改善する
- 私は使用の練習
text
とstance
2列、target
私たちは使用しなくてもよいことができると思います - 注意深い観察データセットは、実際には、発見され、サンプルの偏在、
stance
列FAVOR
とAGAINST
二つの値は、特に大規模な、NONE
非常にまれな、学習サンプル問題の不均衡を伴う、あなたが試すことができ、よりバランスがそれらの割合を設定しました再訓練 - フィルターワードの設定はもう少し詳細です。単語のセグメンテーション後にデータセットを詳しく見ると、URL、7桁の確認コード、絵文字など、実際に多くの不要な単語があることがわかります。
- BERTに直接行く