u++の備忘録

Pythonで動く形態素解析ツール「nagisa」を使ってみた

はじめに

PyCon2018でポスター展示があったらしく、フォロワーさんの投稿で存在を知りました。


使ってみた

インストールはこれだけ。

pip install nagisa

簡単に形態素解析ができます。

>>> import nagisa
[dynet] random seed: 1234
[dynet] allocating memory: 32MB
[dynet] memory allocation done.

>>> text = 'pythonで手軽に使えるツールです'

>>> words = nagisa.tagging(text)

>>> print(words)
python/名詞 で/助詞 手軽/形状詞 に/助動詞 使える/動詞 ツール/名詞 です/助動詞

>>> print(words.words)
['python', 'で', '手軽', 'に', '使える', 'ツール', 'です']

>>> print(words.postags)
['名詞', '助詞', '形状詞', '助動詞', '動詞', '名詞', '助動詞']

nagisaの利点

文字単位の双方向LSTMを採用しており、URLや顔文字に頑健

>>> text = 'ブログのURLはhttps://upura.hatenablog.com/です'

>>> words = nagisa.tagging(text)

>>> print(words.words)
['ブログ', 'の', 'URL', 'は', 'https://upura.hatenablog.com/', 'です']

ちなみに、MeCabMeCab.Tagger("-Owakati") を使うと、URLの中身がバラバラに分割されてしまいます。

>>> import MeCab

>>> t = MeCab.Tagger("-Owakati")

>>> result = t.parse(text)

>>> print(result)
ブログ の URL は https :// upura . hatenablog . com / です

単語分割の方法を調整できる

辞書にない固有名詞は、形態素解析ツールを使うと一般に過度に分割されます。

>>> text = '日本経済新聞を読んでいます'
>>> words = nagisa.tagging(text)
>>> print(words.words)
['日本', '経済', '新聞', 'を', '読ん', 'で', 'い', 'ます']

この時の辞書の登録方法もお手軽です。

>>> new_tagger = nagisa.Tagger(single_word_list = ['日本経済新聞'])

>>> words = new_tagger.tagging(text)

>>> print(words.words)
['日本経済新聞', 'を', '読ん', 'で', 'い', 'ます']

nagisaの課題

上記の資料によると、解析速度に課題があるとのことです。

f:id:upura:20180918203247p:plain

おわりに

インストールが簡単で手軽に使えるので、速度を必要としない解析の際には便利だと思いました。

ランダムフォレストなど木系のアンサンブルモデルの解釈性を高める「Feature Tweaking」

はじめに

今回は、ランダムフォレストなど木系のアンサンブルモデルの解釈性を高める「Feature Tweaking」について紹介します。Pythonによる実装や使い方をGitHubにて公開しています。

手法の概要

機械学習アルゴリズムは世間一般で「ブラックボックス」だと評されますが、解釈性に関する研究も盛んになっている印象があります。今回紹介する「Feature Tweaking」はKDDという著名な国際会議に2017年に採択された論文で提唱された手法で、著者はYahoo!Facebookに所属しています。

Tweakingは日本語で「微調整」の意です。「Feature Tweaking」は、木系のアンサンブルモデルの予測結果を変える方向に、入力 xを微調整します。「入力 xの中のどの変数をどう改善すれば良いかが分かる」といった意味で、解釈性が高まるといった具合です。

著者による紹介動画

www.youtube.com

日本語文献

今回の実装・記事執筆に当たって、下記2つの日本語の資料・記事を参照しました。

www.slideshare.net
setten-qb.hatenablog.com

特に後者の記事では既にPythonによる実装が公開されており、非常に参考になりました。上記で公開した私のGitHubは、こちらの記事に多少の修正と説明を加えたものになります。実装内容の理論的な概要については、こちらの記事をご参照ください。

I fixed some codes and added some explanations:

  • Fix load_iris() to datasets.load_iris() at In [2]
  • Fix rfc.fit(x, y) to rfc.fit(x_arr, y_arr) at In [3]
  • Fix aim_label = 3 to aim_label = 2 at In [7] and [22]
  • Add the usage of feature_tweaking()
  • Add featureTweakPy.py to extract functions

Quoted from featureTweakPy/README.md

「featureTweakPy」の使い方

今回、GitHubでは以下のような形で関数を読み込めるような形式にしました。

from featureTweakPy import feature_tweaking

以降、具体的な使い方を流れに沿って紹介します。

Requirements

Python 3系を使ってください。以下のパッケージを利用します。

  • numpy
  • pandas
  • scipy.stats

Download

git clone して、当該フォルダに移動します。上記で示したパッケージのインストールが必要な場合は適宜 pip install などをお願いします。

git clone git@github.com:upura/featureTweakPy.git
cd featureTweakPy

Package import

最初に、必要なパッケージをインポートします。今回は木系のアンサンブルモデルとしてランダムフォレストを、データセットとしては有名なアヤメを利用します。

import numpy as np
from sklearn import datasets
from sklearn.ensemble import RandomForestClassifier

from featureTweakPy import feature_tweaking

iris = datasets.load_iris()
x_arr = iris['data']
y_arr = iris['target']

Random Forest Prediction

「Feature Tweaking」は木系のアンサンブルモデルの予測結果を微調整する手法なので、まずは普通にモデルを学習させておく必要があります。

rfc = RandomForestClassifier()
rfc.fit(x_arr, y_arr)

Using function()

まずはハイパーパラメータの設定です。

Hyper Parameters Setting

アヤメのデータセットは3種類のラベルがあり、今回はそのうち2の付いたラベルに変化する方向に微調整させたいと思います。

class_labels = [0, 1, 2] 
aim_label = 2
epsilon = 0.1
Cost Function Setting

この手法では最も「コスト」が小さいような微調整方法を探索するので、何を「コスト」とするか定義する必要があります。コスト関数として今回は、単純にユークリッド距離を採用しました。他にもコサイン距離などが想定できます。

def cost_func(a, b):
    return np.linalg.norm(a-b)
Sample Data for Demonstration

いよいよ feature_tweaking() 関数を使います。

x = x_arr[0]
x
array([5.1, 3.5, 1.4, 0.2])
x_new = feature_tweaking(rfc, x, class_labels, aim_label, epsilon, cost_func)
x_new
array([5.1       , 2.9999999 , 4.75000038, 0.90000001])

微調整された x_new を元々の x と比べると、第一成分では変更がなく、それ以外の要素では値が変わっていると分かります。この方向に微調整すると定義した枠組みの中で最適なコストでランダムフォレストの予測結果を目的のラベル方向に変化させられるということです。

ここで、著者による紹介動画でも言及されていますが、今回の手法は「あくまでアンサンブルモデルの中の個々の決定木の結果を改善している」に過ぎず、必ずしも「ランダムフォレストとしての予測結果が目的のラベルに変わる」というわけではないことには注意が必要です。

f:id:upura:20180918193744p:plain

おわりに

ランダムフォレストをはじめとした木系のアンサンブルモデルは、手軽に高精度な予測結果を得られることから、特にテーブルデータを扱う際に頻繁に利用されています。

活躍の場はKaggleだけでなく広範に渡りつつあるかと思いますが、特にビジネスにおいては単に高精度を出すだけではなく、予測から得られた知見をどのように活用するかも同様に重要です。この手法は少し間接的な気もしますが、木系のアンサンブルモデルの解釈性を高められるという意味で、大きな価値があると思いました。

2週間のシアトル出張に行きます

明日14日から27日までの2週間、会社の都合でシアトルに出張します。弊社のR&D部署が主導する出張で、米国の最新技術動向の視察として、2週間にわたって技術系のイベント参加や現地企業訪問などを実施予定です。

私は昨年の10月に入社したので、期せずして帰国時には(ほぼ)1年在籍したことになります。

upura.hatenablog.com

もちろん若干の不安もある中での入社でしたが、1年経過した段階で「こういう案件で出張に行かせてもらえるくらいには自己発信できた」ことを素直に嬉しく思います。まだまだ力不足な点ばかりですが、今後も社内外で成果を出し続けられるよう精進します。

まずはこの2週間、英語力や技術力で苦戦する点もあるかと思いますが、多くを糧にして社に還元できるよう頑張っていきたいです。

Udemy講座「手を動かしながら2週間で学ぶAWS基本から応用まで」を修了したので感想など

Udemyの講座「手を動かしながら2週間で学ぶAWS基本から応用まで」を修了した*1ので、受講の動機や感想などをまとめます。

講座の概要

本講座は、オンライン学習プラットフォームの「Udemy」で先日*2にリリースされた講座です。タイトルの通りAWSを基礎から応用まで体系的に学ぶ内容となっています。

詳細は講師による下記ブログをご参照ください。

www.ketancho.net

受講の動機

筆者の会社での主の業務はデータアナリストですが、合わせてAmazon API Gateway + AWS Lambdaで構築したサーバーレスアーキテクチャのエンジニアとしての業務も担当しています。

正直なところ、後者の仕事に関わるまではAWSをほとんど触ったことがない状況でした。会社での研修や開発チームの猛者の方々のサポートを受けながら業務に取り組んでいますが、業務に直結する知見だけではなく体系的にAWSを学ぶ必要があると感じていました。

そんな折に上記のブログを拝見し、1200円のクーポンも発行されていたので、体系的に学ぶ良い契機だと思い購入に至った次第です。

受講の感想

全講座を閲覧し終わっての感想は多岐にわたりますが、ここでは良かった点を3つと気になった点1つを挙げたいと思います。

良かった点

AWSへの「怖さ」が拭える

筆者の場合、最初にAWSのコンソールを触ったときの感想は「なんかゴチャゴチャしてて何をイジれば良いか分からない」「既存の設定を壊してしまわないだろうか」「この操作では課金が発生しないだろうか」というものでした。これらはAWSへの無知から生じるもので、AWSに対する名状しがたい「怖さ」があったように思います。

本講座は最初に自分自身のAWSアカウントを作成するところから始め、課金アラートの設定も実施します。ほぼ全ての画面操作を動画で確認できるので初心者でも追従でき、個人のアカウントなので好き勝手に触ることができ、課金アラートがあるので安心して講座にない設定も試すことができます。

タイトル通り、実際に「手を動かしながら」学ぶことで、AWSへの「怖さ」をある程度払拭できたと思いました。

各サービスの立ち位置が分かる

AWSを学ぶ上での障壁の一つに、サービスの豊富さがあると思います。「たくさんサービスがあるけれど、何から勉強すれば良いのだろうか」「何がどういう役目を果たしているのだろうか」と感じていました。業務で触れたサービスに関しては当然理解が深まっていくのですが、AWS全体の中で個々のサービスがどういう位置付けなのかは漠然としか把握できない状況でした。

本講座では簡単なブログサービスを作っていく流れの中で、全体の中で優先的に学ぶべきサービスは何なのか確認できます。本講座で登場するのは講師が考えた「使われるシーンが多いであろうサービス」で、2018年現在においてAWS全体を理解する上で重要な順番になっているということです。

さらに本講座の中で新しく登場するAWSの各サービスについて、これまで登場したサービスとの関係性や位置付けが丁寧に説明されている印象を受けました。例えば、最初はAmazon EC2ベースで作成し、後にマネージドサービスに置き換えていくなど、各サービスの繋がりがつかみやすい構成になっていると感じました。

Webサービスの仕組みの大枠がつかめる

本講座を受講しての「副産物」として、AWSに関する知見にとどまらず、Webサービスの仕組みの大枠もザックリと把握できたことが挙げられます。

自分で手を動かしながら簡単なブログサービスを作っていく中で、ブラウザにURLが入力されてからページが表示されるまでの流れを大まかに追うことができます。もちろん本講座で扱うのは非常に単純なブログサービスなので、説明が簡略化されている部分や省略した要素は数多くあると思いますが、DNSサーバやセキュリティグループの設定などWebサービス構築に必要な仕組みを学ぶことができました。

気になった点

ここまで、講師の回し者のような内容になっている気がしたので、気になった点についても少し言及しておきます。

Linux操作

「受講における必要条件」として「基本的な Linux の操作ができること(ls, cp, mv といったコマンド、vim 基本操作)」と記載されています。実際、本講座の中でLinuxの操作自体の解説はほとんどありませんでした。

一つの動画を多人数が閲覧するという仕様上、ある水準の知識を仮定するのは当然のことだと思います。とはいえ、もう少しLinux操作などが分からない人に向けて、せめて「検索ワード」の提供があると良いのではないかと思いました。

例えばセクション: 3「Day2: EC2を使ってサーバを立てる」において、EC2インスタンスSSH接続しミドルウェアを導入するパートがあります。ここで下記のようにパーミッション設定を変更する流れがあるのですが、パーミッションの権限の表現方法が分かっていない人や慣れていない人には、口頭での説明が不十分なように感じました。

~/project/udemy
❯ ll
total 8
-rw-r--r--@ 1 USERNAME  staff   1.7K  9  4 20:32 udemy.pem

~/project/udemy
❯ chmod 400 udemy.pem

~/project/udemy
❯ ll
total 8
-r--------@ 1 USERNAME  staff   1.7K  9  4 20:32 udemy.pem

もちろん本講座の大きな目的から考えると本筋ではないのですが、口頭で「この辺りの表現が分からない場合は、『○○○』で調べてみてください」などと補足があると、より親切なのではないかと思いました。

筆者の進め方

最後に、本講座を筆者がどのように進めたかを述べておきます。

筆者は今回、講師がブログで「おすすめの受講方法」として提案している①まずは講座を聞く②動画を流しながら手を動かすーーという2回聴講方式を実施しました。

①については、夜寝る前に横になりながらタブレットに入れたUdemyアプリで閲覧しました。音声や滑舌が明瞭なので、ほとんど2倍速で閲覧していましたが問題ありませんでした。十分に理解できていないと感じた部分は、動画コンテンツの強みを活かして何回か繰り返し確認しました。

②については、退社後の18〜21時など比較的集中してパソコンに向かえる時間帯に取り組んでいました。PC本体に動画を流し、液晶モニタではブラウザやターミナルを開いて操作していました。こちらも操作に手間取った場合には動画を巻き戻せるのがありがたかったです。

1日1セクション全14日想定のコンテンツでしたが、筆者の場合はある程度集中的に取り組みたかったこともあり、半分の7日間で修了することになりました。

おわりに

本記事では、ここ最近取り組んでいたUdemyの講座について紹介しました。端的に言って、1200円以上の価値ある知見を十分に得られたと感じています。

冒頭の「受講の動機」でも述べましたが、筆者は業務で主にAWS Lambdaをはじめとしたサーバーレスアーキテクチャを扱っています。講師のブログには「別途サーバーレスな講座も検討しています」とありましたので、ぜひ続編を期待したいと思います。

*1:特に修了試験などがあるわけではなく、単に講座を全て見終わって手を動かしたという話です

*2:筆者の確認しうる限りでは9月3日

Adversarial Validationのメモ

はじめに

下記の英語記事から要旨を抜粋して、日本語でまとめた。

fastml.com
fastml.com

Adversarial Validationとは

いつ使う?

  • TrainデータとTestデータの分布が異なる場合
  • → Trainデータから適切にValidationデータを作成するのが難しい
  • → Kaggleの場合、LocalCVとLBのスコアが一致しないなどの問題が生じる

解決策

1. 「TrainデータかTestデータかを判定する分類器」を作る
2. Trainデータを、Testデータに似ている順にソートする
3. 似ている順に、Trainデータからデータを抽出し、Validationデータとする

応用例 "stochastic adversarial blending"

KaggleのHome Credit Default Riskコンペの2nd place solutionに使われた手法。

2nd place solution ( team ikiri_DS ) | Kaggle

The process is as follows,

  1. Sample data with a sampling ratio by using adversarial validation as a sampling weight.
  2. Optimize the weights with train prediction.
  3. Iterate 1~2 process to get converged weights.

【論文メモ】29組のデータアナリストに同じデータセットと同じ質問を与えても、分析結果がバラバラだったという研究

どんなもの?

29グループ(計61人)のデータアナリストに、同じデータセットと同じ質問を与えたときの分析アプローチのバラツキを分析。質問は「サッカーの主審は、肌の白い選手に比べて肌の黒い選手にレッドカードを与える可能性が高いですか?」。

分析アプローチはチーム間で大きく異なり、オッズ比で0.89から2.93の範囲だった(中央値は1.31)。20チーム(69%)が統計的に有意な正の結果を示した一方で、9チーム(31%)は有意な関係を示さなかった。

2018-08-29 19 57 16

これらの知見は、たとえ真摯な専門家集団であっても、複雑なデータの分析結果に主観的な要素が入り込むのは避け難いことを示唆している。 分析を透明化する手段として、同じ研究課題を同時に調査するために多数の研究チームを採用する「クラウドソーシング」が有用であると提言している。

論文リンク

著者/所属機関

R. Silberzahn et.al

媒体

SAGE Journals

投稿日付

First Published August 23, 2018

所感

単純にバラツキの大きさに驚き。自分も同じデータセットで追実験して、オッズがどういう結果になるか確認したい。

データアナリストとして真摯に受け止めて熟読すべきは、論文の結論に含まれた考察部分。どうやっても完全に「客観的」はあり得ないので、その中でどうやって意思決定に値する分析をしていくかを考えさせられる論文だった。

github.com

阪神タイガース、今季初の八回から逆転勝利 昨日までの「0勝50敗」は他チームと比べ酷い数字か検証する

はじめに

本日朝、サンスポに次の記事が掲載されました。阪神タイガースは今季、「七回終了時にリードを許している試合で0勝50敗」という少し衝撃的なデータです。

www.sanspo.com

この記事に刺激されたか否かは分かりませんが、阪神は本日の試合で八回表に一挙6得点。今季初の八回からの逆転勝利を収めました。

f:id:upura:20180826173155p:plain

baseball.yahoo.co.jp

今回は「七回終了時にリードを許している試合で0勝50敗」という数字が他チームと比べてどれほど突出している数字なのか(はたまた特に驚くべき数字ではないのか)、他チームも含めたデータ分析を通じて検証してみたいと思います。

データの取得

どこかに良さげなデータベースがあるかと思い10分程度探しましたが見つからなかったので、Pythonを用いて自分で収集しました。

import pandas as pd
from tqdm import tqdm

result = []
match_id = []
for i in tqdm(range(330, 826)):
    for j in range(6):
        url = 'https://baseball.yahoo.co.jp/npb/game/20180' + str(i) + '0' + str(j+1)+ '/top' 
        try:
            fetched_dataframes = pd.io.html.read_html(url)
            result.append(fetched_dataframes[0])
            match_id.append('20180' + str(i))
        except:
            pass

データの前処理

最初に、分析に必要な情報をデータから抽出します。今回は、resultというリストにpandas.DataFrame形式でスコアボードが格納されています。

result[0]

f:id:upura:20180826174214p:plain

このデータから「七回終了時にリードを許している試合か否か」の情報を取り出します。具体的な処理については、雑なpandasの処理をしてしまったので割愛しますが、興味のある方はGitHubのipynbをご参照ください。

github.com

前処理を終えた後のDataFrameの最初の10行を、下記に示します。上から2行ずつ区切りの情報になっており、例えば最初の2行は「阪神ー巨人戦で、阪神も巨人も八回から逆転勝利しなかった(False)」という意味です。9, 10行目は「楽天ーロッテ戦で、楽天は八回から逆転勝利した(True)」ことを表しています。

f:id:upura:20180826190353p:plain

データの分析

本題の分析に入る前に、きちんと全データが抽出できているかを確認しておきます。

データをチーム名でまとめ上げて(groupby)、合計を出力した結果を、実際の試合数を比較しました。オールスター戦2試合も含めて、昨日(2018年8月25日)までの全試合の情報がデータに含まれていると確認できました。

オリックス     114
ソフトバンク    108
ヤクルト      109
ロッテ       109
中日        115
全セ          2
全パ          2
巨人        117
広島        110
日本ハム      112
楽天        112
西武        111
阪神        106
DeNA      11

f:id:upura:20180826191112p:plain

そしていよいよ、「七回終了時にリードを許していた試合」に関する情報を出してみます。ここではオールスター戦の情報は省きました。

f:id:upura:20180826191915p:plain

冒頭のサンスポの記事通り、阪神は「0勝50敗」でした。

「割合」を見ると、巨人が「1勝48敗」でワースト2位。本日阪神が1勝目を挙げたので、本日時点では阪神と並んでワーストになりました。

個人的に、広島は終盤の逆転が多いイメージがありましたが、3試合のみで割合はワースト4位でした。しかし、そもそも「七回終了時にリードを許していた試合数」が38と、他チームと比べて圧倒的に少ないです。序盤から優位に試合を進めている様子がうかがえます。

DeNAは「七回終了時にリードを許していた試合数」が64で12チーム中最多。広島の約1.7倍もありました。

楽天は55試合中8試合で八回から逆転勝利に成功。順位ではパ・リーグ最下位に沈んでいますが、逆転した試合数・割合ともに12チーム中1位になりました。

まとめ

  1. 今回は、サンスポの記事の分析結果を受けて「七回終了時にリードを許している試合」について分析しました。
  2. 他チームも含めたデータ分析を実施したところ、阪神の「0勝50敗」は巨人の「1勝48敗」と合わせて12チーム中で突出して悪い数字だと分かりました。
  3. とはいえ、一番数字が良かったのがパ・リーグ最下位の楽天で、セリーグを独走する広島は数字が良くないなど、決して一般的なチーム成績と関係ある指標ではないと示唆されました。