なみひらブログ

学んだことを日々記録する。~ since 2012/06/24 ~

Kaggle NLPコンペ参加の「はじめの一歩」の「はじめの一歩」 ※コンペ実施中

※この記事は 自然言語処理 #2 Advent Calendar 2019 - Qiita の25日目の記事です。

概要

最近、自然言語処理/機械学習をやりだし、とりあえず勢いだけでKaggleコンペに参加し始めたのでその作業メモです。
執筆時点(2019/12/25)で現在進行系のコンペなので、最終結果はありません(;´Д`)
この記事を読んでくださって、全員始めてみればいいじゃないと思っています。

※[注]BeginnerのBeginnerなので、そこらへんのチュートリアルな解説ブログよりレベルが低いです(´・ω・`)

前提

Kaggleとは(割愛。以下参照です) www.codexa.net

作業

参加対象

今回参加しているコンペは以下です。現在進行注中で2月10日締め切りなので、あと1ヶ月ちょいあります。
質問タイトルや内容、回答などのテキストをもとにラベル(の確率)を予想するコンペです。 www.kaggle.com

まずやったこと:コンペへの参加登録

  • (割愛)
  • このコンペはNotebookコンペなので、自分でサーバ(GPU含)をもっていなくても、Kaggleが提供するサーバリソースを使って計算処理できます。
  • GPUは使うように設定する

次にやったこと:提出用サンプルファイルをそのまま提出してみる。

  • コード書く
import pandas as pd
sample_submission = pd.read_csv("../input/google-quest-challenge/sample_submission.csv")
sample_submission.to_csv('submission.csv', index=False)
  • コミットする ※コミットが完了するまでなんでこんなに時間かかるの?(´・ω・`)
  • Notebook/Outputからsubmitする。

スコアは-0.03とかでかなり低いですが、とりあえずランキングには載ります。 (しかしビリではない)

次にやったこと:データの中身を見てみる

機械学習界隈だとEDA (Exploratory Data Analysis)というらしく、コンペ内で公開されている他のNotebook(タイトルにEDAとか書いてある)を参考しながら、ファイルからデータを扱える状態まで持っていく
(一部)

train = pd.read_csv(f"{DATA_DIR}/train.csv")
train.head()
...
train0 = train.iloc[0]
print('question_title : ', train0['question_title'])

csvの中身をみてみると、結局テキストを扱う問題なんだな感で少しでてきて、緊張(?)がほぐれる(´Д`)

次にやったこと:モデルを組んでみる

自然言語処理の基本構成として、テキストをベクトル化して、組んだニューラルネットのモデルに流して、学習/予測するので一番簡単そうなやつをやってみる。
テキストのベクトル化はUniversal Sentence Encoderがまず楽。モデルはDense/Dropoutあたりをとりあえず1層で用意する。
もちろん他のNotebookを参考に。
これまでモデルを組んでみたことはなかったですが、他のNotebookを見ながら組めました。

(初学者向けに作ってくれているNotebookもたくさんある)
(本とか論文とかだと部分的なコードしか出てないのに対して、Notebookは一連のデータ処理/モデルが記載されているのでコードが理解しやすい)
(都度調べつつ。勉強になる。参考になったNotebookは「いいね」を押す)
(公開されているNotebookをみんな参考にしているせいか、似たようなコードが多いことに気づく)

(一部)

def model_fn():    
    input_title = Input(shape=(1,), dtype=tf.string, name='input_title')
    embedding_title = Lambda(USEEmbedding, output_shape=(EMBEDDDING_SIZE,))(input_title)

    input_body = Input(shape=(1,), dtype=tf.string, name='input_body')
    embedding_body = Lambda(USEEmbedding, output_shape=(EMBEDDDING_SIZE,))(input_body)
    
    input_answer = Input(shape=(1,), dtype=tf.string, name='input_answer')
    embedding_answer = Lambda(USEEmbedding, output_shape=(EMBEDDDING_SIZE,))(input_answer)

    x = Concatenate()([embedding_title, embedding_body, embedding_answer])
    x = Dropout(0.5)(x)
    x = BatchNormalization()(x)
    x = Dense(512, activation=swish)(x)
    x = Dropout(0.5)(x)
    x = BatchNormalization()(x)
    output = Dense(N_CLASS, activation='sigmoid', name='output')(x)
    model = Model(inputs=[input_title, input_body, input_answer], outputs=[output])

    optimizer = optimizers.Adam(LEARNING_RATE)
    model.compile(optimizer=optimizer, loss='binary_crossentropy')
    
    return model
  • パラメータや層ありなしをいろいろ変えてみて遊ぶ。
  • 遊び飽きたら(精度が一番よかったやつ)でコミットする。
  • 提出する。
  • 少しだけランキングが上がる。※何か競争に参加している感がでる(´Д`)

イマココ

その他やったこと

次にやりたいこと(これからの予定)

  • 上記をベースにモデルの組み方を変えてみる。
  • 今は項目とテキストをそのままモデルに突っ込んでいるので、ユニークな「特徴」を見つけたい(この作業をfeature selectionというらしい)。
  • ランキング上位者は「BERTを使わないと上位いけないね」と言っているので、BERT(なにかのキャラ?)を導入してみる。
  • ランキング上位者は「アンサンブル学習(食べ物?)」の「スタッキング(楽器?)」をしているらしいので導入してみる。

結果

自分のNotebookは↓こんな感じです(随時更新中)
Google QUEST QA Simple USE Solution | Kaggle

まとめ

知識と実践の両輪を回したい(*´ω`*)