前回の記事を書いて以降、いくつか改善策を練った結果、精度が 74.539 % → 78.425 % に上がったため、その内容を書いておきます。

改善点

今回の改善点は主に4つ

  1. 人物系単語、地名系単語、@付き単語、リンクをまとめる
  2. 出現頻度の少ない単語は<unk>(辞書に存在しない単語)として扱う
  3. モデルをCNNに変更
  4. 学習時の<unk>含有率をテストデータに合わせる

trainデータを見てみると、@付き単語の種類数は2328に対して、@付き単語の出現回数は2759であり、ほとんどの出現回数は1回でした。もっとも使われている@付き単語は@YouTube(YouTube動画共有時についているやつ)で、82回でした。
今回、@付きアカウントは以下のように割り振りました。

1
2
3
4
5
<youtube> : @YouTube
<news> : ニュースアカウント
<social> : 政府や組織のアカウント
<media> : メディア雑誌系アカウント
<reply> : others

リンクは<link>、地名は<location>、人物名は、出現頻度の多い政治家・歌手等を除いて、<person>にまとめました。

出現回数が1度のみの単語は、おそらくtestデータ中にも出現しにくいと考えられるため全て<unk>にまとめました。(<unk>は元々、テストデータの単語が学習データ中に存在しない時に変換する文字)

今回まとめた単語は以上ですが、これら以外にも、出現頻度が少ない単語を、ある一定のグループ名にまとめると、精度が上がるのではないかと思います。日が昇ってきたので前処理はこの辺で切り上げました

1.2.に関して、これら以外にも不要な記号等を削除した結果、25,000程度あった単語の種類が、6,000程度に減りました。

3.に関しては単純なCNNです。前回のモデルよりも、正解率が率が高くなりました。構造は以下のように、単純なものです。埋め込み次元は18次元としています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class CNN(nn.Module):
def __init__(self,depth_source,depth_key,batch_size,maxlen,d_model,d_key,device='cuda'):
super().__init__()
self.device = device
self.embedding = nn.Embedding(depth_source,d_model, padding_idx=0)
self.d_model=d_model
self.maxlen=maxlen

self.c1 = nn.Conv2d(1, 8, 3)
self.a1 = nn.ReLU()
self.p1 = nn.MaxPool2d(2,2)
self.d1 = nn.Dropout(p=0.4)

self.c2 = nn.Conv2d(8,16, 3)
self.a2 = nn.ReLU()
self.p2 = nn.MaxPool2d(2, 2)
self.d2 = nn.Dropout(p=0.4)

self.linear_out = nn.Linear(1824, 1)
self.activation_out = nn.Sigmoid()
nn.init.xavier_normal_(self.linear_out.weight)

def forward(self,x, key):
x = self.embedding(x)
x=x.reshape(x.shape[0],1,x.shape[1],x.shape[2])
y=self.c1(x)
y=self.p1(y)
y=self.a1(y)
y=self.d1(y)


y=self.c2(y)
y=self.p2(y)
y=self.a2(y)
y=self.d2(y)
a_out=y.reshape(y.shape[0],y.shape[1]*y.shape[2]*y.shape[3])
out = self.linear_out(a_out)
out = self.activation_out(out)
return out

4.に関しては、学習データ中のunk含有率:0.04140461215932914 テストデータ中のunk含有率:6.409214826048494 % この差分に近い、2.26%だけ<unk>をランダムで学習データに追加しました。

学習結果は以下の通りです。validationデータに対する正解率は0.77付近にいます。
損失関数
正解率の推移

提出結果は以下の通りです。
kaggleの提出結果

おわりに

前回はデータをそのまま学習させていたため、今回はデータをいくつか前処理でまとめてみました。時間もかかって大変ですけど、データ数を減らすことで、結果的に学習時間を削減できましたので、もっと積極的にすべきですね..