ysaz (ImanazaS) blog

最近はデータ分析や機械学習が中心。たまに音楽や書評。

Dive Into Deep Learning

UCバークレーの講義から派生したプロジェクトとして、「Dive Into Deep Learning(通称 D2L)」の執筆が進められているようです。

d2l.ai

ちらっと覗いてみましたが、数式だけでなく、コードや図を使ってわかりやすいものに仕上げていくという姿勢が感じられます。

ベーシックなNNに始まり、CNN、RNNやAttentionといったモデルの解説、
更にはコンピュータービジョン(画像からピカチュウを検出するという興味深いタスクを含む)や自然言語解析といった応用例までがカバーされているので、
比較的スムーズに読み進められそうな印象を受けました。

ただ、使われているフレームワークがKerasやPyTorchではなくMXNetなので、読む人を選びそうな気もします。
(執筆者の方々がAWSの関係者のようなので、その成り立ちを考えると当然のことなのかもしれませんが)

日本語への翻訳活動も始まっているようです。
github.com

Jupyter NotebookからJupyterLabへの移行

Jupyter Notebookにはその前身のIpython Notebook時代からお世話になっています。
そのJupyter Notebookの後継と言われるJupyterLabを今更ながらインストールし、少し試してみました。

JupyterLabとはなんぞや

Jupyterの開発をおこなっているProject Jupyterが2018年2月にBlog記事を投稿し、一般ユーザー向けにJupyterLabを公開したことを発表しました。

blog.jupyter.org

当時、この記事を目にした記憶はあるのですが、

  • どうせまだbeta版だし、ver1.0がリリースされたら使い始めよう
  • 下手に環境をいじって他のパッケージが使えなくなったら困る

といった理由で導入を見送り、大々的にリリースされるのを楽しみに待っていました。

では、なぜ今なのか

上述の通り、首を長くしてJupyterLabの続報を待っていたのですが、待てど暮せどアップデートはなく、バージョンは0.35のまま。
そんな時、Variable Inspectorという拡張機能の使用例が紹介されている下記の記事を見つけ、これは使ってみたい!と思うようになりました。

qiita.com

後でも述べますが、変数や型といった、ノートブック上で扱っているデータに関する情報が常に一覧できる点に強い魅力を感じました。

使ってみた感想

IDEとしての使い勝手が向上

<見た目>
使ってみてまず驚いたのがレイアウトです。
ファイルエクスプローラーが画面の左側に備わっていること、開いているノートブックのタブとしてWebブラウザのタブとは別のものが設けられていること、等。

一点目について、Jupyter Notebookではファイルやフォルダの整理専用にファイル構成が見える画面をノートブックとは別のタブで開いておき、作業しているノートブックと行ったり来たりすることでファイルの管理をしていました。

しかしJupyterLabのファイルエクスプローラーによって、そのようなことをする手間や煩雑さが省かれ、作業効率が向上することが期待されます。

二点目について、Jupyter NotebookのレイアウトではWebブラウザで開いている他のコンテンツ(例えばGmailとかAmazonとか)とノートブックが混在する形となってしまい、

  • タブ数がどんどん増えていくため見辛い
  • 他のコンテンツの中に埋もれてしまったが最後、必要なノートブックを探し出すのが大変

といった課題があると感じていました。

これに対しJupyterLabでは、Webブラウザのタブと異なるタブが存在することで他のコンテンツと混在することはありませんし、上述したファイルエクスプローラーを使えばどのファイルを開いているのかも一目瞭然です。

敢えて使いづらさを述べるとすると、ctrl + tabキーで実行していたタブの切替操作ができなくなったことでしょうか。

JupyterLabのデフォルトでは、ctrl + shift + [(又は ] )でタブ切替ができるので、触っていたらそのうち慣れてくることでしょう。
慣れなければショートカットを編集して別のコマンドに変更してしまえばOKです。


<機能>
コードを書いてみてまず気づいたのが、補完機能です。
Jupyter Notebookでもtabを押すと候補が表示されていたので、その点はJupyterLabも同じです。
追加されたのは、Atomなんかにも備わっている、その項目が関数なのか変数なのか等を表示している機能で、個人的にはかなり見やすい印象を受けました。

また、pythonのメソッドや関数に関する解説を参照する際に使っていたshift + tabコマンドは健在で、Jupyter Notebookでは詳細なドキュメントを閲覧するのにこのショートカットを2回入力する必要があったのですが、JupyterLabでは一発で表示されるような仕様となっており、使い勝手が向上したと感じています。

拡張機能を導入するとより便利に

拡張機能はまだVariable Inspector以外試せていないので、今回触れるのはこの一点です。

インストールはコマンドラインを呼び出して以下を実行するだけで完了。

$ jupyter labextension install @lckr/jupyterlab_variableinspector

Variable Inspectorを作業しているノートブックと別タブで開き、ノートブックのドラッグ&ドロップ機能を使って作業ブックの右隣にでも配置しておけばOK。

f:id:nami3373:20190521202629p:plain
JupyterLab

RStudioを使っていると、現在扱っているデータのサイズや変数といった基本情報を同一画面上で確認することができるので、pythonIDEでも似たようなことができたら便利なのに、と常々思っていました。

AnacondaやRodeoといったIDEでも似たようなことはできるのですが、個人的にはJupyter Notebookの手軽さに勝るものではなく、Variable Inspector的機能は諦めていました。
拡張機能としてJupyterLabに導入できればまさに鬼に金棒。

まとめ

JupyterLab、すごく便利です。
2018年中にリリースされる予定だったver1.0が未だリリースされていないのは気になりますが、気長に待ちつつ、使い倒していきたいと思います!

プログラミング教育ブームについて感じること

プログラミング教育ブームの到来

2020年度から小学校でのプログラミング教育が必修化されるといいます。

プログラミング教育:文部科学省

デパート等のおもちゃ売り場へ行けば、論理的思考力を鍛える多種多様な知育玩具が並んでおり、インターネット上では、関連ニュースや記事を見かけることが多くなりました。

「プログラミングは現代のそろばん」と銘打った寺子屋というか学習塾も非常に人気を博しているそうで、この流れに乗り遅れないようにと、熱の入った親御さんが多いことに感心しています。

また、史上最年少で将棋のプロ入りを果たした藤井聡太さんや、囲碁の世界では史上最年少の10才でプロ棋士と仲邑菫さん等、天才少年少女の登場も、論理的思考力を育むことへ人々が関心を寄せるきっかけをつくっているようにも感じます。

かくいう私はというと、ITリテラシー現代社会を生き抜く上での必須スキルだと思っているし、子供の頃からどっぷりプログラミングに触れておけばよかったと後悔したりもするので、自分の子には幼いうちから各種デジタル技術に慣れ親しんで欲しいと思っています。

そうした意味では、早期から義務教育にプログラミングを取り入れるという文科省の方針は私の考えに沿っており、私の場合は4歳の長男には使わなくなったノートPCにEdubuntuをインストールしたものを与えることから始めていたりします。

Edubuntuについては以下の記事を参照。今後このブログでもまとめてみるかもしれません。)

mogi2fruits.net

プログラミング教育に対する(ありがちな?)勘違い

因みに私も、つい最近まで勘違いしていたのですが、何も小学生がパソコンやタブレットに向かって特定のプログラミング言語の文法を学んだり、出されたお題に対してコーディングしていく訳ではないらしいです。

確かに、国語、算数から英語、音楽、体育まで、ただでさえいろんな科目を一人で子どもたちに教えなければならない小学校の先生にプログラミング言語まで指導させるのは荷が重い話です。

学校でのIT環境を整えることもさることながら、教える側にとっての負担の大きさについても十分議論されるべきと思います。

では子どもたちは、一体何を教わるのでしょうか。

それは「プログラミング的思考」というもので、物事は手順を踏んで進めることでうまく解決できる、というふうに、筋道を立てて論理的に考えていく力のことを指します。

物事をうまく解決するために、ときには繰り返しや条件分岐といった方法を使いながら、最適な手順を探ります。

ビジネスの世界でも、「仮設構築」とか「ロジカルシンキング」とかいう言葉が持て囃されますが、聞き手を説得させる上で、理路整然とした論理展開を行うことは非常に重要なので、こうした能力の土台作りが初等教育から開始されるというのは、好ましいことだと思います。

プログラミング教育に対する批判や課題

最近目にした記事で興味深かったのが以下の記事で、「実用偏重教育に潜む大きな危険性」について触れられています。

www.mag2.com

“How to use”、つまりスマホといったツールをいかにうまく使うか、というスキルではなく、“How to see”の能力を備えた人材を育てるべきだ、とあります。

現代教育は「実用」に重きを置きすぎていて、いろんな事柄を見極めたり追求したりする力を養う機会が減っている、というのが筆者の主張です。

※ただしこの記事のタイトルはややミスリードを招くように感じます。 筆者は、子どもたちが本を読む機会が減っており、プログラミング教育という科目が増えることで人文科学への比重がさらに軽減されることに異を唱えていますが、おそらくプログラミング教育が「パソコンを使わせるようにするための教育」と勘違いされているのでは、推察します。

この記事の中で強調されている"How to see"は次のように定義されています。

例えばスマホ社会や今後のネット社会、さらにはAI等の進化をどのように捉えて、それが人々の生活やものの考え方にいかなる影響を与えてゆくかというテーマをじっくりと見つめること

確かに、日本の教育課程では、「ルールやパターンに沿って問題を解き、一義的な答えを得る」、という場面に出くわすことが多く、"How to use"のアプローチに順応しがちということも頷けます。

また、ベストセラーとなっている「AI vs. 教科書が読めない子どもたち」でも子どもの読解力低下が指摘されており、表面的なスキルだけ身につけても意味はなく、課題設定や定義付けをする能力があってこそだと論じられているようです。

※私は書店で眺め読みした程度で、まだ精読はできていません

先述したプログラミング教育も、単にツールを使いこなすだけのカリキュラムに成り下がることなく、物事を抽象化して本質を見抜く論理的思考回路を子どもたちに身につけさせる良いきっかけとなればいいなと期待しています。

Pythonで実行した処理の終了を通知してくれるツール

大規模データの処理やら機械学習やらで、演算に時間がかかるときがあります。

放ったらかしにしつつも、都度パソコンの前まで行って進捗を確認するのが面倒で、なんとかできないかと思っていたところ、以下の記事を見つけました。

 

時間のかかるデータ処理や機械学習処理が終わったら通知してくれるツールをつくった! - 焼肉が食べたい

 

なんと、メソッドの前に一行加えるだけでSlackに通知してくれるという便利もの。

 

他にもいくつか、別の人が作ったツールがあるようですが、設定含め、上記のツールが使いやすい印象です。

 

ただし、Gmailへ通知を飛ばすのはうまくいかず。セキュリティが理由でブロックされたみたい。

Slackが使えればそれで十分ですが、いずれ原因究明します。

 

あとはJupyter Notebook上で使うときに、マジックコマンドでも利用できたらベターなのですが。。。

他のツールを探すか、自分で作るか。

(続)Pandasでのデータ集計

以前に以下の記事でPythonのPandasライブラリを使った集計方法をまとめていた。
nami3373.hatenablog.com

今になって、これよりもシンプルなやり方に気づいたのでメモ。

import pandas as pd

# データフレームを適当に作成
df = pd.DataFrame(data=[('2016-04-01', 'a', 10.2, 60.3), ('2016-04-02', 'a', 16.4, 71.7), ('2016-04-01', 'b', 11.1, 65.6), ('2016-04-02', 'b', 15.1, 73.2)])
df.columns = ['date', 'id', 'temp', 'humidity']

# pivot tableで集計
df1 = df.pivot_table(index='date', columns='id', values=['temp', 'humidity']).reset_index()
df1.columns = [s1 + '_' + s2 for (s1, s2) in df1.columns]
df1.rename(columns={'date_':'date'}, inplace=True)
df1.index.name = None

df1

結果は以下の通り。

date humidity_a humidity_b temp_a temp_b
0 2016-04-01 60.3 65.6 10.2 11.1
1 2016-04-02 71.7 73.2 16.4 15.1

以前のやり方は3つのステップを踏んでいたが、1ステップで同じ結果が得られるので、こちらの方が楽かと。
カラム名を補正してやる手間は残りますが)

カテゴリカル変数のEncoding手法について

Structured Data(構造化データ)の下処理をおこなう際に避けて通れないのがFeature Engineering(特徴量エンジニアリング)。
特に悩ましいのがカテゴリ変数の扱いで、どのように扱えば良いか困ることが多く、また、使った手法もすぐに忘れてしまいがちなので、自分なりに整理して記事にまとめておきたいというのが趣旨。

1.よく使われる手法

まずはよく用いられる定番の手法から。次元を増やすかどうかで大まかに次の2つに分類できる。

・次元を増やさない場合(Label, Count, LabelCount, Target)
・次元を増やす場合(One-Hot, Entity Embedding)

これらの手法について、python上の実装例とともに見ていきたい。
用いたライブラリは主にPandas、少しScikit-Learn。

2.次元を増やさない場合

Label Encoding

最もシンプルな手法で、与えられたカテゴリ変数に数字を割り当てるもの。
たとえば、「東京」、「大阪」、「名古屋」というカテゴリに対して、
0、1、2といったようにラベルをふって単純に数値化するだけ。

以下、実行例。
Method 1はPandasを使ったもので、Method 2はScikit-Learnを使ったもの。

import pandas as pd
import numpy as np

d = {'city': ['tokyo', 'nagoya', 'osaka', 'tokyo', 'nagoya', 'osaka', 'tokyo', 'osaka', 'tokyo'],
	'target': [0, 1, 0, 1, 0, 1, 0, 1, 0]}

df = pd.DataFrame(d)
df['city'] = df['city'].astype('category')
df.dtypes

# method 1
df['label_enc'] = df['city'].cat.codes

# method 2
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
df['label_enc'] = le.fit_transform(df['city'])
Count Encoding

これも比較的シンプルな手法で、データに含まれるカテゴリ変数の出現回数を数えるもの。

以下、Pandasのgroupbyを使った実行例を2つ(Method 1, 2)。

# method 1
count_mean = df.groupby('city').target.count()
df['count_enc'] = df['city'].map(count_mean)

# method 2
df['count_enc'] = df.groupby('city')['target'].transform('count')
LabelCount (Count Rank) Encoding

次は上述したCount Encodingの応用編で、カテゴリ変数の出現回数が多い順に順位づけするもの。

以下、Pandasを使った実行例。

count_rank = df.groupby('city')['target'].count().rank(ascending=False)
df['count_rank'] = df['city'].map(count_rank)
Target Encoding

Mean EncodingやLikelihood Encodingとも呼ばれる手法で、目的変数(Target)に対してカテゴリ変数の処理をおこなう。
Kaggle等の機械学習コンペで頻繁に用いられている。

やり方としては、目的変数が2値のみをとるブーリアン型であればカテゴリ毎の確率を、目的変数が数値であればカテゴリ毎の平均を取るというもの。

ただし、データセットが学習データとテストデータに分かれている場合、テストデータの目的変数は未知であるため、演算は学習データに対しておこない、得られた特徴量をテストデータ内のカテゴリへ適用する。

この部分に注意しないと、Cross Validation をおこなったときにデータがリークすることになってしまう。

以下、Pandasのgroupbyを使った実行例を2つ(Method 1, 2)。

# method 1
target_mean = df.groupby('city').target.mean()
df['target_enc'] = df['city'].map(target_mean)

# method 2
df['target_enc'] = df.groupby('city')['target'].transform('mean')

3.次元を増やす場合

One hot encoding

データ中に存在するカテゴリ変数の数だけ次元(構造化データでいうと、新しい列)を用意して、各行に含まれているカテゴリ変数に対応する次元を1に、それ以外を0にする方法。
これにより、カテゴリ変数を単に連続する数としてではなく、独立する値として扱うことが可能となる。

以下、実行例。
Method 1はPandasを使ったもので、Method 2はScikit-Learnを使ったもの。
ただしMethod 2ではカラム名が自動で返ってこないため、何らかの形で指定してあげる必要がある。

# method 1
oh_enc = pd.get_dummies(df['city'])
df = pd.concat([df, oh_enc], axis=1)

# method 2
from sklearn.preprocessing import OneHotEncoder
oh_enc = OneHotEncoder(sparse=False)
df[['nagoya', 'osaka', 'tokyo']] = oh_enc.fit_transform(df.label_enc.reshape(len(df.label_enc), 1))


ここまでの実行結果は下表の通り。

city target label_end count_enc count_rank target_enc nagoya osaka tokyo
tokyo 0 2 4 1.0 0.250000 0.0 0.0 1.0
nagoya 1 0 2 3.0 0.500000 1.0 0.0 0.0
osaka 0 1 3 2.0 0.666667 0.0 1.0 0.0
tokyo 1 2 4 1.0 0.250000 0.0 0.0 1.0
nagoya 0 0 2 3.0 0.500000 1.0 0.0 0.0
Entity Embedding

KaggleのRossmannコンペで有名になった手法。
これまで挙げてきたものとはややアプローチが異なるが、ニューラルネットワークでカテゴリ変数に対応する重み行列を学習させ、その重み行列とOHEの積をとったもの(と理解している)。
最終的には数値データと合わせてニューラルネットワークの全結合層に放り込むこととなる。

KaggleのPorto Seguroコンペデータを使った実験を行い、以下Githubに公開したので、参考までに。

github.com

次のステップとして、抽出した重み行列を特徴量としてGradient Boosting Decision Tree (GBDT) にうまくまぜられないかと思案中。

4.参考記事

参考にしたのは以下のblog記事。とてもうまくまとめられており、インスパイアされるきっかけとなった。

jotkn.ciao.jp

あとは、英語だが以下の記事もEncodingについて体系的に書かれており、非常に役に立った。

pbpython.com

Entity Embeddingについてはこの記事を参照。

puyokw.hatenablog.com

最後に、最近発売されたこの本。大全というだけあって網羅的に整理されており、辞書的な使い方ができるのがよい。

機械学習や人工知能、AI関連分野を取り巻く情勢

機械学習人工知能、AI関連の記事で気になったものをピックアップし、Google Keepにメモする習慣をつけている。

 

メモに残す記事の数はだいたい一日2、3件。

(日本語英語問わずチェックしているが、ひと目見た時の情報量の多さから、日本語記事をメモに残しがち)

一ヶ月半強分のメモが貯まってきたので、どんな記事に興味を示す傾向があるのか、少し振り返ってみたい。傾向としては大きく以下の2つに分かれるようだ。

 

1.企業の活用事例

私自身が企業人であることから、世の企業がどんな風に新たな技術を取り込み、どんな商品やサービスを打ち出そうとしているのか、ビジネスを生み出そうとしているのかに関心を示すのは、自然なことと言える。

 

たとえば警察が犯罪の発生を予測するためにAI導入するとしているとか、製造業が不適合品の発見に予測モデルを適用しようとしているとか、そういう類のもの。

 

2.大企業の出資事例、ベンチャー企業の調達事例

時代の流れに乗りたい大企業は、自社で新たに技術を確立しようにも時間やお金がかかるし、そもそもそういったことができる人材が不足しているため、所謂オープン・イノベーション的なことを実現すべく、他社とのアライアンスや出資、さらにはM&Aをおこなうことが多い。

 

そもそもこうした背景には、今のAIブームのスピード感に付いていくためには、一から人を育成し事業を育てていても時間がかかるため、どんどん取り残されていくリスクが生じることがある。

他にも、世界の上場企業の中には、手元に膨大なキャッシュが積み上がっている一方で、有望な使い道が見つからないという「金余り」の状況が見受けられたりする。こうした背景から企業が投資先を積極的に探しているという事情も、ベンチャー企業への出資を後押ししていると言える。

 

一方のベンチャー企業側は、事業を拡大していく上で資金調達は必要なポイントなので、理想的なパートナーが見つかれば、出資を受け入れることを選択する。

 

日本国内でも数十億円規模の大型調達がちらほらと出ており、昨年末からの出来事を振り返っても、プリファードインフラストラクチャーの調達や、少し毛色は異なるが、FOLIOの調達案件などが話題となった。

 

こんな感じで引き続きアンテナを張って記事をチェックしていきたい。