u++の備忘録

仮説と可視化から新しい特徴量を作る Kaggleのタイタニックを例に

本記事では、Kaggleのタイタニックを例に、仮説と可視化から新しい特徴量を作る過程についてまとめます。

仮説と可視化から新しい特徴量を作る

予測精度に寄与する新しい特徴量を作成するに当たっては、仮説と可視化を繰り返す過程が大事です。

f:id:upura:20181025151115p:plain

  • 予測精度に寄与しそうな仮説を立てる
  • 可視化を実施する
    • 予測精度に寄与する仮説を見つけるため
    • 仮説が正しいかを検証するため

個々人や問題によって、どちらが起点になるかが変わってきます。

ケース1)ドメイン知識がある場合

例えば自分が詳しい、つまりドメイン知識を持っている分野の問題に取り組む場合、最初から仮説がいくつかあると思います。その場合は仮説を検証するような可視化を実施し、本当に予測精度に寄与するかを確認します。その可視化の結果によっては、改めて仮説を立てることになるかもしれません。

ケース2)ドメイン知識がない場合

ドメイン知識がない場合は、まずは仮説を立てるための探索的なデータ分析を実施することになるでしょう。いろいろな軸でデータを眺め、予測精度に寄与しそうな仮説を立てるのが目的になります。

Kaggleのタイタニックを題材にした具体例

ここではKaggleのタイタニックを題材に、具体例を示します。

コードの全容は、KaggleのKernelで公開しました。
www.kaggle.com

Kaggleのタイタニック

Kaggleのタイタニックとは、Kaggleのチュートリアル的な問題として認知度の高いコンペティションです。タイタニック号の乗客の属性情報(性別・年齢・チケットの種類など)から、生存したか否かを予測します。
Titanic: Machine Learning from Disaster | Kaggle

仮説と可視化

ここでは探索的なデータ分析を実施した結果、ぼんやりと「一緒に乗船した家族の人数が多い方が、生存率が低そうだ」という仮説が得られた状況を考えます。

仮説が得られたので、次はこの仮説を検証するための可視化に移ります。

新しい行「Family_Size」を作り、その大きさごとに生存したか否かを棒グラフにしました。

  • Survived == 0: 死亡
  • Survived == 1: 生存
data['Family_Size'] = data['Parch'] + data['SibSp'] + 1
train['Family_Size'] = data['Family_Size'][:len(train)]
test['Family_Size'] = data['Family_Size'][len(train):]

import matplotlib.pyplot as plt
import seaborn as sns
sns.countplot(x='Family_Size', data = train, hue = 'Survived')

f:id:upura:20181025152803p:plain

ここでFamily_Size >= 5の場合、死亡が生存を上回っており、生存率が低いことが分かります。

「一緒に乗船した家族の人数が多い方が、生存率が低そうだ」という(ぼんやりとした)仮説が、可視化を通じて、「Family_Size >= 5の場合、生存率が低いので、この特徴量は予測精度に寄与しそうだ」という確信を持った仮説に変わりました。

今回の「Family_Size」のように仮説に基づいたいろいろな集計軸で分析をして可視化してみて、予測精度に寄与しそうな集計軸か否かを確認するというのは、有効なアプローチだと思います。

更に今回、可視化を通じて、それまで持っていなかった仮説(情報)を得ることもできました。

「Family_Size == 1」の人が圧倒的に多く、かつ生存率が低いということです。

この「Family_Size == 1」であるという特徴量も予測精度に寄与しそうなので、下記のように新しく「IsAlone」という特徴量を作成しました。

data['IsAlone'] = 0
data.loc[data['Family_Size'] == 1, 'IsAlone'] = 1

train['IsAlone'] = data['IsAlone'][:len(train)]
test['IsAlone'] = data['IsAlone'][len(train):]

予測精度の比較

「Family_Size」と「IsAlone」を加えた場合の方が予測精度が高い結果となりました。(今回乱数を固定していないので、再実行した場合に多少の誤差は発生します)

「Family_Size」と「IsAlone」を加えていない場合

f:id:upura:20181025154109p:plain

「Family_Size」のみを加えた場合

f:id:upura:20181025210424p:plain

「Family_Size」と「IsAlone」を加えた場合

f:id:upura:20181025154119p:plain

「IsAlone」は一見「Family_Size」に包含されているようなので精度向上の効果はないかと思いましたが、今回の場合は多少の影響があるようでした。

(「Family_Size」よりも明示的に生存率が低い場合を示した効果かもしれませんが、詳細な検証はしていません)

おわりに

本記事では、Kaggleのタイタニックを例に、仮説と可視化から新しい特徴量を作る過程についてまとめました。

「どうやってKaggleを進めていけばよいか分からない」という方に、少しでもお役に立てれば幸いです。

[追記 20181025 21:00]
「Family_Size」のみを加えた場合の予測精度を追記しました。

Jリーグ2018年シーズンの勝ち点推移を可視化 pythonでデータ取得から可視化まで

2018年シーズンのJ1リーグでは、序盤にサンフレッチェ広島が独走していましたが、7月のW杯中断明けごろから失速。後半になって追い上げた昨年王者の川崎フロンターレに首位を譲る展開になっています。

川崎フロンターレの驚異的な追い上げがどの程度か気になってので、シーズン途中ではありますが勝ち点推移を可視化してみました。第29節までのデータを可視化に利用しています。

f:id:upura:20181020193126p:plain

処理の流れ

  1. BeautifulSoupでスクレイピング
  2. pandasで加工
  3. matplotlibで可視化

一連の流れは非常に雑なコードですが下記で確認できます。

github.com

BeautifulSoupでスクレイピング

Yahoo!のサイトからデータを取得して、節ごとにcsvで保存しました。

soccer.yahoo.co.jp

def save_result_data(setsu):
    url = 'https://soccer.yahoo.co.jp/jleague/schedule/j1/' + str(setsu) + '/all'
    html = urlopen(url)
    bsObj = BeautifulSoup(html, "html.parser")
    table = bsObj.findAll("table")[0]

    rows = table.findAll("tr")

    csvFile = open("result" + str(setsu) + ".csv", 'wt', newline = '', encoding = 'utf-8')
    writer = csv.writer(csvFile)

    try:
        for row in rows:
            csvRow = []
            for cell in row.findAll(['td', 'th']):
                csvRow.append(cell.get_text())
            writer.writerow(csvRow)
    finally:
        csvFile.close()

for setsu in range(1, 35):
    save_result_data(setsu)

pandasで加工

今回の目的に沿うようにデータを加工しました。

加工前(データの一部)

f:id:upura:20181020193134p:plain

加工後(データの一部)

f:id:upura:20181020193139p:plain

加工前は行ごとに試合の情報を保持している形式でしたが、加工後は行ごとに1チームの試合ごとに「日付」「獲得勝ち点」の情報を紐づけました。

matplotlibで可視化

あとはチームごとに勝ち点推移を可視化します。

team0 = res[res['teams'] == '川崎F']
team0 = team0.sort_values('dates')
team0['accum_scores'] = team0['scores'].cumsum()
plt.plot(team0['dates'], team0['accum_scores'], label='Kawasaki')

上のコードの1行ごとに、それぞれ下記の操作をしています。

  1. 川崎フロンターレ」のデータに絞り込む
  2. 開催日でデータをソート
  3. 各試合終了時点での累積和(勝ち点)を計算
  4. 折れ線グラフで可視化

所感

勝ち点推移の可視化に適したデータ構造の持ち方が分からず、思ったよりも苦戦しました。

【論文メモ】強化学習を用いないGANによる文生成モデル「LaTextGAN (latent-space GAN for text)」

Adversarial Text Generation Without Reinforcement Learning

どんなもの?

  • 強化学習を使用しないGANによる文生成モデル「LaTextGAN (latent-space GAN for text)」を提案
  • オートエンコーダを利用して文の低次元表現を学習させて生成器に伝播させることで、現実的なレベルでの文生成を実現

f:id:upura:20181019201219p:plain

論文リンク

https://arxiv.org/abs/1810.06640

著者/所属機関

David Donahue, Anna Rumshisky / University of Massachusetts Lowell

媒体

arxiv

投稿日付

[v1] Thu, 11 Oct 2018 22:50:38 GMT

先行研究と比べてどこがすごい?

  • テキストのシーケンスが離散的で勾配が識別器から生成器に伝播できないため、GANの訓練は自然言語処理の限られた範囲でしか成功しかなかった
  • 近年は解決法として、強化学習を使用して近似勾配を生成器に伝播させているが、これは訓練が非効率的
  • 本研究では、オートエンコーダを利用して文の低次元表現の学習させ、生成器に伝播させている

技術や手法のキモはどこ?

  • オートエンコーダを利用して文の低次元表現を学習させて生成器に伝播させることで、GANが独自のベクトルを生成するように訓練され、現実的な文生成を実現

どうやって有効だと検証した?

  • 文ベクトルを可視化することで、提案モデルがオートエンコーダーの潜在空間を正しく学習していると示した
  • 人による評価とBLEUスコアの両方で、提案モデルが競合するベースラインに対して現実的なレベルでのテキスト生成ができると示した

議論はある?

  • 強化学習を用いることは、文生成タスクへGANを適用するに当たって大きな障壁となる
  • 提案モデルを通じて、コンピュータビジョン以外でのGANの普及促進を目指しています

次に読むべき論文は?

Null

github.com

独立したデータ分析チームを作るべきか否か #分析リーダーズトーク へ行って考えた

昨日開催された「Data Analyst Leaders Talk! #2」に行ってきました。

connpass.com

イベントの書き起こし的な記事は他で挙がっているので、そちらに譲ります。

www.grisoluto.com

本記事では、私がデータ分析チームについて抱いていた疑問に焦点を当て、パネルディスカッションや懇親会での話を踏まえての自分なりの結論をまとめたいと思います。

私の疑問

イベントの運営さんに拾ってもらうためにTwitterハッシュタグを付けて投稿したところ、結構「いいね」が付き、イベントに参加していない方からもリプライをいくつか頂戴しました。多くの方が関心ある質問なのかなと感じました。

少しだけ補足すると、下図のどちらが良いと思うか?という質問です。

f:id:upura:20181018121827p:plain

もちろん組織の成熟度にも依る話だと思いますが、それぞれ以下のようなメリット・デメリットがあるかと感じています。

独立のデータ分析チームを立ち上げ

メリット

チームとしての一体感があり推進力が高まる

デメリット

実際のプロダクト担当者との距離が空いてしまう

個々のチームに分析担当者を配置

メリット

実際のプロダクト担当者との距離が近い

デメリット

チームとしての一体感に欠ける

パネルディスカッションでの学び

今回のイベントの登壇者はデータ分析チームの責任者ということで、独立のデータ分析チームを立ち上げた視点での話を多く聞くことができました。

話題の中で、求められる取り組み(ミッション)として大きく分けて以下の2種類が挙げられたように感じました。前者は自分たちで分析を実施していく取り組み、後者は自分たち以外に分析やデータ利活用を促す取り組みです。

  • 意思決定につながる価値のある分析の実行(自分たちで分析を実施する)
  • データの民主化(多くの人にデータ分析に関わってもらう土台を作る)

独立のデータ分析チームを立ち上げることは、両者にメリットが有ると思いました。

前者についてチームを独立させる最大の利点は、データ分析チームのリーダーがタスクを取捨選択でき、担当者が価値のある分析に集中できる点です。パネルディスカッションの中でも「依頼を断ること」の大切さがたびたび強調されていました。

後者についても、分析の属人性を解消できる利点があります。個々のチームに分析担当者を配置する場合は、それぞれのチームにおける分析のプロフェッショナルは育成できますが「その人がいなくなった途端に誰もデータの定義が分からなくなる」のような事態が起こりがちです。ドキュメントを整備したり知見を共有したりする視点でも、独立のデータ分析チームを作っておく意味があると思いました。

懇親会での学び

パネルディスカッションを通じて独立のデータ分析チームを立ち上げるメリットを十分に把握できたので、懇親会では「プロダクト担当者との距離が空いてしまう」というデメリットについて議論したいと思い、積極的に登壇者に話しかけました。

時間が短かった関係で4人中2人の登壇者としか会話できませんでしたが、交わした議論の要点を羅列しておきます。

  • 個々のプロダクトにどっぷりと浸からないと良い分析はできない
  • そのためデータ分析チームから個々のチームに分析担当者を「派遣する」ようなやり方を実行している
  • 分析担当者がつまらないタスクに忙殺されないよう、リーダーとして仕事を管理しなければならない
  • 単純なタスクに関しては受け皿となる窓口を一元化して、必要に応じて処理するようにしている
  • 大抵は(プロダクト数)>(分析担当者数)なので、いくつかのプロダクトに注力する
    • プロダクトの選抜基準は、会社としてのプロダクトの重要性&プロダクトマネージャの分析への理解

自分なりの結論

本イベントを受けての、冒頭の問いに対する自分なりの結論を以下にまとめます。

  • 組織としてデータ利活用を推進していく上では、独立のデータ分析チームを立ち上げる方がより大きなミッションを遂行できる
  • 一方で「プロダクト担当者との距離が空いてしまう」というデメリットは間違いなく存在する
  • それを回避するため、重要ないくつかのプロダクトに分析担当者を「派遣する」ような仕組みが理想的である

問いの2択の良いとこ取りの(ズルい)回答になっている気もしますが、自分の中ではモヤモヤが晴れたような感じがしました。このような思考ができただけでも、自分にとって十分に行った価値のあるイベントだったと思います。

最後に、本イベントでは改めて(データ分析チームに限らず)リーダー自体の聡明さの大切さを感じました。私の結論も「リーダーが十分にビジョンを持ってチームをマネジメントできる」という前提のもとで成り立っています。そういったリーダーとしての素養を広く共有するという意味でも、このようなイベントの意義は大きいと思います。

次回も機会があれば、ぜひ参加したいです。

「ベースボールデータハッカソン」エンジニアリング部門で準優勝しました

昨日と本日の2日間にわたって開催された「パ・リーグ×パーソル ベースボールデータハッカソン」にて、エンジニアリング部門で準優勝しました。

techplay.jp

賞品として、パリーグ6球団タオルセットを頂きました。ありがとうございました。

f:id:upura:20181007222550j:plain

本記事では、ハッカソンの概要や私が取り組んだことなどをまとめます。外部に公開できない情報などの問題で理解が難しい部分があるかもしれませんがご了承ください。ご質問いただければ可能な範囲で対応いたします。

ハッカソンの概要

1日目の朝10時にデータが公開され、19時までに以下の2つから参加する部門を選択する形式のハッカソンでした。

  • データから予測精度を競う「エンジニアリング部門」
  • データから新しい発見を導き出す「コンサルティング部門」

今回は全32名が参加し、うち26名がエンジニアリング部門、6名がコンサルティング部門を選択しました。チーム参加も可能で、私は友人と3人チームでエンジニアリング部門を選びました。

エンジニアリング部門では、予想精度の高い上位4チームが予測手法などに関してプレゼンしました。(プレゼン内容自体は順位に関係なく、純粋に予測精度だけで順位が決まりました)

コンサルティング部門では、提出したプレゼン資料を基に選抜された上位2チームがプレゼンし、最優秀チームを決めました。

エンジニアリング部門の課題

エンジニアリング部門の課題は、「ファンクラブ会員が特定の試合に来るか否か」の予測でした。

約14万人分のうち半分の7万人についてはgame1〜45に来場したか否かの情報が、残りはgame1〜42に来場したか否かの情報が公開されました。ここで「隠されたgame43〜45に来場するか否かの値を予測する」という課題です。

f:id:upura:20181007211455p:plain

ファンクラブのマーケティングに関する情報以外に、今回は「ベースボールオペレーション」のデータが公開されたのが特徴的でした。

  • 各打者の試合ごとの個人成績
  • 各投手の試合ごとの個人成績
  • 各試合の打席ごとの結果

これらの野球のプレイデータをどのようにして来場予測に繋げるか、がハッカソンの鍵となりました。

また外部データの使用は禁止されていました。

f:id:upura:20181007212059p:plain

部門の選択

まず、データを探索的に分析しながら2つの部門のどちらに出すかを考えました。

実のところ、当初はメンバー的に強みがあるコンサルティング部門へ参加するつもりでした。しかし、下記の理由で最終的にはエンジニアリング部門への参加を決めました。

  1. 最初に立てた仮説と真逆の分析結果が出たため、チームで納得行く解釈ができなかった
  2. バックアップとして進めていたエンジニアリング部門の予測の精度がそこそこ良さそうだった

特徴量生成と予測モデル

今回、game43とgame44&45で予測方法を分割して考えました。その理由は下記の通りです。

game43〜45の来場情報が公開された7万人のうち、それぞれ何人が来場しているかを分析したところ、概ね以下のような結果になりました。

  • game43 → 7万人中5000人
  • game44 → 7万人中1000人
  • game45 → 7万人中1500人

game1〜42についても同様の分析をしたところ、ほとんどは14万人中1万人以上(つまりは7万人中5000人以上)の結果が出ていました。game44&45は過去のデータと比べて極端に数字が少ないため、過去のデータを基に予測モデルを作成しても上手くいかないと考えました。

3人の主な役割としては、game43の予測モデルを私が、game44&45を他2人のチームメンバーが担当しました。

game43について

  • 特徴量
    • ファンクラブ会員が「今季初めて参加した試合」のプレイデータの情報
  • 予測モデル

私のチームが作った特徴量として独自性があったのは、ファンクラブ会員が「今季初めて参加した試合」のプレイデータの情報だと思います。

ファンクラブ会員が(特定の試合に限らず)来場するか否かは、今季初めて参加した試合での「良質な体験」が利いてくると仮説を立てました。良質な体験とは「得点がたくさん入る」「ホームランがたくさん出る」「奪三振が多い」などを指します。

どういうものが良質な体験かを考えるのは機械学習に任せるのが良いと思考停止で思ったので、「ベースボールオペレーション」の3データについてそれぞれpandasのgroup byで大量に特徴を作成しました。

あとは勾配ブースティング分類器に突っ込み、ハイパーパラメータを調整しアンサンブルといった流れです。

game44&45について

上述した通り、game44&45は来場者が非常に少ないことが予想されます。さらに、過去のデータを活用した予測モデルの作成は困難でした。

そこで、無理に来場を予測することで精度を下げるリスクは取らず、「過去全試合に来場している人」など絶対に来そうな人だけを人力で確認する方針を取りました。具体的には7万人のうち、ほぼ全員を来場しないと予測し、5人だけを来場と予測しました。

予測対象の3分の2に当たるgame44&45のデータについて「機械学習を全く使わない」という戦略は、プレゼンで結構ウケました。無理に機械学習に頼らず人力に頼るのが大切な場面もあるなと感じました。


感想

率直な感想として、野球という自分が関心を持っているデータを触れるのは純粋に楽しかったです。

上位4チームに入りプレゼンができたこともあり、懇親会では多くの方と交流できました。こちらも実りある体験でした。プレゼンを多くの方に褒めていただき「データ分析を楽しんでいるのが伝わってきました」と言ってもらえたのが非常に嬉しかったです。

今回、game43の予測には機械学習を、game44&45では人間の力を大いに活用しました。イベントに関連したパネルディスカッションの中で「Data drivenとKnowledge drivenの関係性」のような話がありましたが、課題に応じて両者を適切に使い分けるのが大事だなと改めて実感する機会になりました。

最後に順位について。2位という結果は満足できるものではありますが、勝ち切ることができなかった経験を糧に今後も邁進していきたいと思います。

これからもデータ分析を楽しみながら、精進していきたいです。

技術書典5で弊社の機械学習活用事例を紹介します

2018年10月8日に池袋サンシャインシティで開催される技術書典5に、弊社のエンジニア有志で執筆した書籍を頒布します。

techbookfest.org

私は第1章「機械学習を用いた日経電子版Proのユーザ分析」を担当しました。

私は弊社にて、営業・マーケティング向けのデータ分析や、業務効率化のための環境整備を担当しています。

本章では、機械学習を用いた「日経電子版Pro」のユーザ分析事例を紹介しました。課題設定から始め、データの前処理や予測モデルの構築など一連の過程を、Pythonのコードと合わせて掲載しています。

pr.nikkei.com

以下のような読者を想定して執筆しました。Kaggleでテーブルデータを処理するような過程が含まれているので、Kaggleに興味がある方なら楽しんでお読みいただける内容になっていると考えています。

  • データ分析に興味がある
  • PythonのPandasを使ったことがある
  • データアナリストが実際に会社でどんなことをやっているか知りたい

場所は「き18」です。当日は私も売り子をやるので、ぜひブースまでお越しください!
※ 弊社の規定で決済方法は「かんたん後払い」のみとなります。お手数ですが事前にご準備いただければ幸いです。

↓よろしければ、はてなブックマークや拡散をお願いしますm(_ _)m

【Mac, 2018】pyenv/minicondaでのpytorch利用環境構築のメモ

『現場で使える!PyTorch開発入門 深層学習モデルの作成とアプリケーションへの実装』に取り組むに当たって、自分なりの環境構築のメモ。
www.shoeisha.co.jp

minicondaのインストール

pyenv install miniconda-latest
pyenv local miniconda-latest

パッケージのインストール

conda install pandas jupyter matplotlib scipy scikit-learn pillow tqdm cython
conda install pytorch=0.4 torchvision -c pytorch//
pip install flask smart_getenv gunicorn
conda install -c caffe2 caffe2 protobuf
sudo apt install git build-essential g++ cmake

確認

f:id:upura:20180923122731p:plain

import numpy as np
import torch
t = torch.tensor([[1, 2], [3, 4.]])
t