読んだ本紹介コーナー:『大規模言語モデル入門』の感想

今年の私の中でのベスト専門書オブザイヤーな書籍、『大規模言語モデル入門』について感想を述べたり、この本の魅力を伝えて布教活動をしていきたいと思い、久しぶりにブログを書こうと思います。

対象読者のイメージ

データサイエンティストとして働いている人やそれを専門にしている学生で、原理まで詳しく知りたい奇特な人が対象読者かなと思います。全国民レベルでChat-GPTが話題になった昨今、大規模言語モデルをただ使うだけでなく、仕組みや開発までの変遷などを詳しく知りたいかたにちょうど良い本です。Chat-GPTが登場して話題になった時期よりも以前に書籍の執筆を着手していると思われるので、Chat-GPTのことだけに興味がある人はそんなに満足しないのではないでしょうか。そもそもアルゴリズム自体は公開されてないですし、そういったものは書籍に求めるものではないでしょうが。

良いと思ったポイントについて

・Transformerの説明がわかりやすい
・Chat-GPTについて理解が深まるプロンプトによる言語モデルの制御について記されている
・感情分析、質問応答、固有表現抽出、要約生成、類似文書検索などの実装例が紹介されており、実務で使えそう
・個々の実装例についてファインチューニングについての記述がある
・個々の実装例についてエラー分析の記述がある
・Google Colabでも頑張れるように限られたメモリでの作法が記されている
・性能アップの強い味方であるアノテーションツールの紹介がある
・文書要約技術の概要が簡潔にまとまっている、性能指標についてもわかりやすい
・Chat-GPT APIの料金見積もりを試せるスクリプトが載っている
・外部の情報を大規模言語モデルで取り込み、その結果をChat-GPTに選ばさせるというアプリケーションの事例が載っている

Transformerの説明がわかりやすい

余談ですが、先日私の親に、「Chat-GPT」って何?と聞かれたのですが、T、つまりTransformerの説明が一番大変でした。自分が完全に的を得た説明ができているか不安だったのですが、この書籍の説明はすごくわかりやすく、自分が説明した内容と大きな相違がなかったので安心しました。

Chat-GPTについて理解が深まるプロンプトによる言語モデルの制御について記されている

zero-shot、one-shot、few-shotなどの説明から、chain-of-thought推論などプロンプトエンジニアリングについてわかりやすく解説されています。また、人間によるフィードバックのデータに関する強化学習についても記述されており、Chat-GPTの仕組みを知ることに一歩近づけます。

感情分析、質問応答、固有表現抽出、要約生成、類似文書検索などの実装例が紹介されており、実務で使えそう

大規模言語モデルを一般的な事業会社のデータサイエンティストが業務で使うとなると、類似文書検索や感情分析、固有表現抽出は使うイメージが湧きやすいです。そのため、この書籍は仕事で隣に置いておきたいと思いました。

個々の実装例についてファインチューニングについての記述がある

ゼロからモデルを訓練して学習するのは現実的ではない事業会社がほとんどだと思いますので、ファインチューニングという記載があるとグッときます。

個々の実装例についてエラー分析の記述がある

これまでの書籍でエラー分析について記されたものは中々なかった気がします。実務では必ず通る道ですので、「わかってらっしゃる」という気持ちでした。こういう実務で大事にしていることを書籍でしっかり記してもらえると、布教もしやすいので良いです。

Google Colabでも頑張れるように限られたメモリでの作法が記されている

多くの個人、事業会社がColab乞食をしていると思います。Colabの無料GPUはベーシックインカムなのではないかと思うくらいです。そのColabでも動かせるように思いやりのあるメモリ削減技術について紙面が割かれています。

性能アップの強い味方であるアノテーションツールの紹介がある

Label Studioというオープンソースのアノテーションツールの使い方について記されていました。このツールは知らなかったので、大変勉強になります。実務でアノテーションする機会は当然あって、3万件くらい一人でやったこともあります。。。

文書要約技術の概要が簡潔にまとまっている、性能指標についてもわかりやすい

文書要約自体をあまり業務で使うことがなかったので、無知だったのですが色々な要約の種類があったり、評価指標があって目から鱗でした。

Chat-GPT APIの料金見積もりを試せるスクリプトが載っている

クラウド破産にならないためにも重要な観点ですね!会社で稟議をあげて、ドキドキしながら使っている人がほとんどだと思うので、しっかり見積もっていきたいですね。

外部の情報を大規模言語モデルで取り込み、その結果をChat-GPTに選ばさせるというアプリケーションの事例が載っている

最後の章でChat-GPTと別の大規模言語モデルの合わせ技についての実装例が載っています。これは仕事で使えるかもと思える実装例だったので、色々やってみると思います。外部の情報(自社にしかない情報)を用いたChat-GPTならいろんな可能性が広がりますね。データ抜かれる可能性はゼロではないですが。

おわりに

大規模言語モデルの開発の流れやモデルを改良するためのテクニックについて十分な紙面が割かれていて、仕事で使える本だなと思いました。
あと、先日買ったライト目な本として、『大規模言語モデルは新たな知能か――ChatGPTが変えた世界 (岩波科学ライブラリー)』も良かったです。大規模言語モデルを開発した人間に関してもフォーカスしていて、そんなすごい人がいるんだと胸が高鳴りました。仕事で必ずいるわけではないですが、開発に至るまでの変遷も教養として知っておくのはいいかもしれませんね。

仕事用にTransformer/BERTの情報をまとめる


最近、『Transformerによる自然言語処理』という書籍を買って、これまであまり追いかけていなかったTransformerについて仕事でカジュアルに使えるレベルまで色々と準備してみようと思い、その過程で見つけた色々な情報をまとめてみました。

以前、『BERTによる自然言語処理入門: Transformersを使った実践プログラミング』も買って、写経しながら試していたのですが、仕事であまり使う機会がなかったのであまり身につかなかったです。その反省も込めて、仕事でそのまま使えそうなレベルで備忘録としたいです。

Transformerについて
BERTについて
BERTを使うための色々
終わりに
参考情報

Transformerについて

ここでは仕組みと該当するコードについて見てみようと思います。TransformerはTransformer Encoderと呼ばれるニューラルネットワークのことをさします。Transformer Encoderはどのようなニューラルネットワークなのかと言うと、

  • 入力(エンコーダスタック)
    • Multi-Head Attention
    • 正則化
    • フィードフォワード
    • 正則化
    • 以上をN回繰り返す
    • 出力へ渡す
  • 出力(デコーダスタック)
    • Masked Multi-Head Attention
    • 正則化
    • 入力からもらう
    • Multi-Head Attention
    • 正則化
    • 正則化
    • 以上をN回繰り返す
    • 線形変換
    • ソフトマックスで確率出力

という構造のネットワークで、Attentionという機構が特徴となっています。

詳しい説明は、『Transformerによる自然言語処理』の第1章に記されています。加えて、元となっている“Attention Is All You Need”を読むと良いと思います。

Attentionが何なのかを理解する前に、RNNやLSTMやCNNのネットワークにはあるが、今回のTransformerのネットワークにはないものが何か考えてみると、再帰的な処理がないことがわかります。
もともとRNNなどは、ネットワークの隠れ層において再帰的な構造を持つことで前の状態を再び使いながら計算して学習していました。上の図を見れば、ぐるぐるとしていないことがわかると思います。

RNNなどはぐるぐると再起的に学習をして、単語ごとの関係性を学習していきますが、2つの単語の距離が離れるほどに計算時間がかかってしまうなどの問題がありました。Attentionは単語と全ての単語の間の関係をベクトルの内積で計算し、それを考慮することでこれまで以上に深く文脈を考慮した学習ができるようにしたものです。それに加えて、ベクトルを計算すればいいだけなので、並列処理もしやすく、計算速度の改善も利点としてあげられます。

Attentionの数式は以下の通りです。

$$Attention(Q, K, V) = softmax \left ( \frac{QK^T}{\sqrt(d_k)} \right ) V $$

Qはクエリベクトルで、元の入力データ(単語ベクトル)に重み行列\(W^Q\)を掛けて手に入れることができます。意味合いとしては検索をしたいもの。
Kはキーベクトルで、元の入力データ(単語ベクトル)に重み行列\(W^K\)を掛けて手に入れることができます。意味合いとしては、検索をするクエリと入力データの近さを示すもの。
Vは値ベクトルで、元の入力データ(単語ベクトル)に重み行列\(W^V\)を掛けて手に入れることができます。意味合いとしては、検索するクエリと入力データに応じた値。
\(d_k\)は次元数で、ベクトルの次元数が増えても重みが0になりにくいように、学習が進むようにするために割るために使われています。

QとKの内積が単語ごとの関連性をつかさどります。これらの値を代入して、softmax関数で返したものがAttentionとなります。参考文献の例では64次元となっています。内積を使って関連性を表現すると言うところは非常に親近感がわいて理解が捗ります。

しかしながら、なぜQ,K,Vに分ける必要があるのかいまいち腑に落ちません。こちらのブログ(【論文】”Attention is all you need”の解説)によると、モデルの表現力を高めるためとあるようで、KとVの関係について色々な変換を通じて、人間が想像できないレベルの関係性を拾おうとしているようです。

続いて、MultiHead Attentionの数式は以下の通りです。

$$ MultiHead(Q, K, V) = Concat(hed_1, \dots, head_h) W^O \\
where \ head_i = Attention(QW_i^Q, KW_i^K, VW_i^V) $$

MultiHead Attentionでは、複数のAttentionが連結されていることがわかります。
64次元のAttentionが8つあるので、MultiHead Attentionは512次元になります。
\(W^O\)は訓練される重み行列となります。
ここで、最終的に何を訓練しているかというと、例えば、英語に対するドイツ語のような、言語のペア、つまり翻訳をするというタスクの訓練をしていることになります。
なお、もととなる研究では言語のペアに関して、Byte-Pair Encoding (BPE)を行った上で学習をしています。
BPEはこちらの記事(Byte-Pair Encoding: Subword-based tokenization algorithm)の説明がわかりやすいです。

以上より、Attentionは翻訳という機械学習を行う過程で、深いネットワークを通じて、ある単語がどの単語に対して着目するべきかの重み付け(\(W^O\)の推定)を行っているとみなすことができます。

さて、出力(デコーダー)のMaskedがなんなのかと言うと、推論する際に、「文字列の位置において未来を見ないように処理をする」という意味で、具体的には隠すという処理です。ある文字列が出てきたところまでしか情報を持ち得ないため、このような処理をしていることになります。

ソースコードに移る前に、一つだけ忘れているところがありました。位置エンコーディング(Positional Encoding:PE)です。単語ベクトルにすることで位置情報を失ってしまっているため、それを補う処理が必要となります。

PEは埋め込みの各次元iごとに、位置情報としてサイン/コサイン関数で定義されます。

$$PE_{position 2i} = \sin \left ( \frac{position}{10000^{\frac{2i}{d_{model}}}} \right ) $$
$$PE_{position 2i+1} = \cos \left ( \frac{position}{10000^{\frac{2i}{d_{model}}}} \right ) $$

positionは単語の位置なので3つ目なら3、10個目なら10を取る値となります。iは位置エンベッディングの次元です。\(d_{model}\)は埋め込みベクトルの次元数で今回だと512となります。偶数はサイン関数、奇数はコサイン関数で表現する流れです。

とは言うものの、腑に落ちないのでもう少し調べてみます。この処理で十分にユニークな位置の情報を表現することができるのでしょうか。

以下の情報などが参考になりました。
What is the positional encoding in the transformer model?
Visual Guide to Transformer Neural Networks – (Episode 1) Position Embeddings

そこで紹介された図が以下のものです。

どうやら、サイン・コサイン関数は循環するので何度も同じ値をとることになりますが、エンベッディングの次元ごとに値が変わっていくようになっているので、その心配はいらないようです。

このPEの値を、埋め込みベクトルに足すなどすることで位置情報を失われることなく後に続くネットワークで活用できるようになります。

$$ y_1 = dog \\
pc(dog) = y_1 \times \sqrt d_{model} + PE(3) $$

というイメージです。\(y_1\)にかかっている値は、PEの影響が消えてしまわないようにするテクニックとされています。

なんとなく、全体感がわかったところでソースコードで確かめてみたいと思います。

今回は、attention-is-all-you-need-pytorchというリポジトリを見つけたので、そこを見てみます。以上で紹介した仕組みに関しては、https://github.com/jadore801120/attention-is-all-you-need-pytorch/blob/master/transformer/Models.pyのコードで扱われています。

こちらのコードは、Transformer、Encoder、Decoder、PositionalEncodingという4つのクラスからなります。
PositionalEncodingでは先ほどのサインコサイン関数での処理がそのまま書かれています。
Encoderでは先ほどの図の左のネットワークに関する処理が書かれています。
Decoderでは先ほどの図の右のネットワークに関する処理が書かれています。左のネットワークのアウトプットを途中受け取る処理などが確認できます。
Transformerではエンコーダーとデコーダーを介して線形変換した予測値を返す処理が書かれています。

別途、get_pad_mask関数を用いたパディング処理や、上三角行列に変換することで未来の単語を見えないようにする関数get_subsequent_maskなどもあります。

以上がコードですが、計算コストに関しても論文にあったので記しておこうと思います。論文によると、84万円くらいするGPU(NVIDIA Tesla P100)を8つ使って3.5日くらい回したそうで、推定したパラメータの数は1000万は軽く超えており、最大でも2億個くらいあるようです。
とてもではないですが、個人や月並みの企業では学習に関しては取り組み難いものであるのは間違いありません。民間企業のデータサイエンティストとしては、学習済みのモデルを使って、既存のNLPタスクなどをどう解決するかを頑張る道が賢明のようです。

BERTについて

BERTは登場して久しいですが、先ほど紹介したTransformerをもとに、双方向MultiHead Attention副層が追加され、デコーダーの部分(先ほどの図の右側のネットワーク)がなくされたものがBERTとなります。双方向の字面どおり、Bidirectional Encoder Representations from Transformersで頭文字をとってBERTと呼びます。


ネットワーク層としては先ほどのTransformerの左側(エンコーダー)だけの形となります。

BERTは学習のために二つの手段を取ります。一つ目はマスク付き言語モデルです。双方向という表現は、ネットワーク間でランダムに単語をマスクして、それを予測するために学習し合うというところから来ています。二つ目は次文予測(Next Sentence Prediction)で、ある単語からなる系列の後に次なる系列が続くのかどうかを学習します。
これら二つを組み合わせてNLPタスクを解くために学習をするという流れです。具体的なタスクとしては、文章と文法のペアなどを学習用データとして、文章から文法を当てるというタスクなどです。

BERTのPyTorchでの実装は、こちらのGitHub(BERT-pytorch)にありました。詳細は記さないですが、model/bert.pyのところに、マスク付き言語モデルの部分、次文予測の部分が実装されていることが確認できます。

BERTを使うための色々

仕事で使えそうなものがいいので、学習済みのBERTを使って日本語のNLPタスクを行うためのコードをこしらえてみました。

『BERTによる自然言語処理入門: Transformersを使った実践プログラミング』という書籍の第6章に文書分類(記事のカテゴリ分類)を、日本語の学習済みBERTで実践するコードが記されていますので、困ったらこのコードを見て日々の仕事をすればいいかもしれません。
こちら(BERT_Chapter6.ipynb)は、Google Colabで写経したもので書籍にあるものと同じです。

以下、マルチラベル文章分類の7章の写経Colab(BERT_Chapter7.ipynb)と固有名詞抽出の8章の写経Colab(BERT_Chapter8.ipynb)もあるので、合わせてここぞと言う時に使いたいと思います。

他にも、BERTのハンズオン資料を見つけました。こちらも日本語のNLPタスクを行えるチュートリアルなので、業務で使う際に参考になりそうです。
huggingface transformers を使って日本語 BERT モデルをファインチューニングして感情分析 (with google colab) part01
huggingface transformers を使って日本語 BERT モデルをファインチューニングして感情分析 (with google colab) part02

終わりに

今回は、いまさらながらTransformerとBERTについて情報を色々集めてみました。推論時に十分な速度を出せるのかまだ判断がつくレベルで使っていないので、今後は色々な分析課題に適用して、Word2Vec並みにリーズナブルな分析アプローチとして業務に組み込んでいきたいですね。
Word2Vecを夜な夜な会社のパソコンで学習して2日くらいかけたのは、もう8年も前の話で非常に懐かしいです。Transformer系となると計算資源的に厳しいものがありますが、どうにか学習させてみたいとも思っています。

参考情報

Attention 機構を用いたDeep Learning モデルによるひび割れ自動検出
Transformerにおける相対位置エンコーディングを理解する。
【論文】”Attention is all you need”の解説
Transformerのデータの流れを追ってみる
A Gentle Introduction to Positional Encoding In Transformer Models, Part 1
TORCH.TRIU
huggingface transformersで使える日本語モデルのまとめ
huggingface transformers を使って日本語 BERT モデルをファインチューニングして感情分析 (with google colab) part01
huggingface transformers を使って日本語 BERT モデルをファインチューニングして感情分析 (with google colab) part02

FacebookのMMMのOSS「Robyn」のチュートリアルさわってみた

目次
Robynとは
とりあえずチュートリアルやってみる
向き合い方
参考情報

Robynとは

Robyn(ロビン)はFacebook(META)が開発しているMarketing-Mix-Modeling(以降、MMM)のオープンソース(https://facebookexperimental.github.io/Robyn/)です。主にR言語で開発されています。(Python版は目下開発中らしいです。)

MMMは、マーケティングの広告投資の予算を、効果を最大化するためにどこに配分するかを数理的なモデルで決めようとするものです。
そもそも、MMMにそれほど明るくない方もおられると思いますが、その際は、『データ活用のための数理モデリング入門』の100ページ目に目的やら簡単な概要が載っていますので、参考にされると良いと思います。

また、RobynにはRobyn Open Source MMM Usersというユーザーグループがあるようです。そこそこ活発に運営されているようです。

私は以前、このコミュニティーのイベント(Facebook Project Robyn Open Source MMM 2021 Community Summit)があったので聴講しました。英語が苦手なので何度も聞きなおしましたが。。

この会では、世界中のマーケターがRobynを使ってプロモーションの分析をしているのを知れました。彼らはRobynのアーリーアダプターなんだろうなと思いました。

とりあえずチュートリアルやってみる

とりあえず、Robynがどういうツールなのか知るためにチュートリアル(https://facebookexperimental.github.io/Robyn/docs/quick-start/)をやってみることにしました。

まずは、Rを最新版にします。今回は「R version 4.2.0 (2022-04-22) — “Vigorous Calisthenics”」にしました。

結構な数の依存パッケージがインストールされているようです。スクロールバーがめちゃ小さくなりました。時間もそれなりにかかるようです。

Robynパッケージを読み込み、サンプルデータを呼び出します。

モデルを作る際の入力変数の設定をします。途中でProphetが使われているようです。確かに、Prophetは時系列の分析にちょうど適したライブラリではあります。

さて、指定する入力変数は結構多くて、以下の通りです。
・データセット
・従属変数
・従属変数のタイプ
・Prophetでの周期性などのオプション
・国
・競合の情報やイベントなどのコンテキスト変数
・ペイドメディアの支出
・ペイドメディアのインプレッションやクリックなど
・オーガニックな変数
・コンテキスト変数のなかでオーガニックなもの
・期初、期末
・広告の残存効果

実務でMMMを使っているものからすると馴染み深いですので、「ああ、このデータですね」とスッと頭に入ってきます。コードでいろいろ個別にやるととっ散らかるので、こういうカタマリで処理を実行できるのはいいですね。MMMが初めての方は、扱うデータセットの概要をよく調べてから入力変数にするようにしたほうがいいと思います。

次に、ハイパーパラメータの設定を行います。『StanとRでベイズ統計モデリング (Wonderful R)』の作法に従うならば、あまりハイパーパラメータを恣意的に決めて収束させるのはやりたくないですが、明らかに符号がおかしいとかの制約は付けてもいいのかなと思います。

ハイパーパラメータを設定したら、アルゴリズムを実行します。裏側でベイズ推定をしていることから、結構時間がかかります。Prophetを動かすということはStanを動かしていることと同義ですから。

イタレーションごとのモデルの目的関数の事後分布を可視化します。徐々に収束してそうに見えます。

モデルがいろいろと求まったので、パレート最適な組み合わせの計算をします。

パレート最適な組み合わせで返された複数のモデルから一つを選びます。

選んだモデルの係数などを確認します。

この選んだモデルをもとに、最適なアロケーションを計算します。

推定した、選んだモデルでの最適な広告のアロケーション結果を出力します。予算を削った方がいい広告経路、増やした方がいい広告経路などが示されます。

続いて、支出の上限を決めた上での、7日間でのアロケーションを行います。

こちらが、出力した結果です。

続いて、特定の広告経路の目的関数に対しての影響度が支出に応じてどう変わっていくか、つまりサチっているかどうかを見てみます。

支出に関して、目的関数がサチっているかどうかを見てみます。

新しいデータで、現在のモデルをアップデートします。

アップデートした場合、先ほどと同様に、推定結果や予算に応じたアロケーションを出力します。

向き合い方

以上、チュートリアルを行いましたが、過去にMMMを実務で使ったことがあるものとしては、Robynはかなりオートマチックなツールだなぁと思いました。時系列のベイズモデリングに対してProhpetに感じた感情と似ているかもしれません。
パレート最適なものを見つけたり、アロケーションをどうするかを決めたりする関数までもが用意されており、適切にモデルを作成することさえできれば、データサイエンティストの業務時間をかなり削減することができると思います。
ただ、残存効果をカスタマイズしたり、独自のモデルをやる自由度はある程度犠牲にしていると思うので、当てはまりにこだわる場合、これまで通りStanなどで独自にアルゴリズムを書くこともあってしかるべきかなと思います。

参考情報

https://facebookexperimental.github.io/Robyn/
データ活用のための数理モデリング入門
Robyn Open Source MMM Users
Facebook Project Robyn Open Source MMM 2021 Community Summit
https://facebookexperimental.github.io/Robyn/docs/quick-start/

ディリクレNBDモデルのマーケティング分野での適用に関して色々調べてみた


どの企業のマーケティング担当者も、自分が属する市場や自分の会社の商品の需要予測ないし購買行動の予測に関心があると思います。それらを予測できる手法として、ディリクレNBDモデルが候補にあがると思います。
以前、『確率思考の戦略論 USJでも実証された数学マーケティングの力』を読んだ際に、需要のシミュレーションにディリクレNBDモデルが使えるということを知りましたが、繰り返し利用するサービスや消費財向けのアプローチなのかなと思って、自分が扱うサービスへの適用可能性の低さから距離を置いてきました。
ところが、文献によると様々な分野でディリクレNBDモデルを使って生命保険やクレジットカードなどのサービス市場需要の予測がうまくいっているケースがあるらしく、真剣に向き合ってみようと思い調べてみることにしました。

目次

歴史
理論の概要
適用例
データについて
実践するコード
参考文献

歴史

マーケティングの分野では、消費者の繰り返し購買行動やダブルジョパディの法則など様々な現象を説明するための研究と実践がなされてきました。
そのために確率的なモデルが色々と適用されていきました。

“The Dirichlet model in marketing”という論文の図を引用しますが、1952年ごろからブランドロイヤルティーの研究が始まり、1958年には線形モデルが用いられ、1959年にはNBD(Negative Binomial Distribution:負の二項分布)を用いた購買予測などがなされるようになりました。
それらのアプローチを様々な対象に適用しつつ、1975年にはBBD(Beta Binomial Distribution:ベータ二項分布)が、ついに1984年にはNBD-DirichletモデルがGoodhardtらによって考案されるに至りました。

理論の概要

本家の論文(The Dirichlet: A Comprehensive Model of Buying Behaviour)や“Calculation of Theoretical Brand Performance Measures from the Parameters of the Dirichlet Model”を読まれることをお勧めしますが、この理論が想定しているものは以下の通りです。

・各々の消費者がポワソン過程に従って、負の二項分布に従い購買行動をする。
・消費者ごとの購買率はガンマ分布に従う。
・消費者の利用可能なブランドの選択は多項分布に従う。
・ブランドの選択確率自体は様々な消費者ごとに、多変量ベータ分布、あるいはディリクレ分布に従う。

なお、ディリクレモデルは負の二項分布とディリクレ多変量分布の二つの確率密度関数の結合からなり、二つの分布はそれぞれ独立であることを想定しています。
マーケットにおける購買自体の行動をつかさどる分布(負の二項分布)と、何を選ぶかをつかさどる分布(ディリクレ多変量分布)が独立しているということになります。

まず、負の二項分布についてですが、確率密度関数は以下の通りとなります。
$$ f_{\gamma, \beta}(k) = \frac{\Gamma (\gamma + k)}{\Gamma(\gamma)k!}\frac{\beta^k}{(1+\beta)^{\gamma + k}} \\ \textrm{ for } k = 0, 1, 2,…$$

負の二項分布は二つのパラメータを持ちます。
・形状(shape)パラメータ(\(\gamma\))
・尺度(scale)パラメータ(\(\beta\))

続いて、ディリクレ多変量分布ですが、確率密度関数は以下の通りとなります。

$$ f_{\alpha_1, \alpha_2, \dots, \alpha_h}(r_1, r_2, \dots, r_h | r_1 + r_2 + \dots + r_h = k ) \\
\frac{\Gamma \left ( \sum_{j=1}^{h} \alpha_j \right ) k! }{ \Gamma \left ( \sum_{j=1}^{h} \alpha_j + k \right ) } \prod_{j=1}^{h} \frac{\Gamma \left ( \alpha_j + r_j \right ) }{r_j! \Gamma \left ( \alpha_j \right )}$$

\(r_h\)などはそのマーケットにおける特定ブランドの購買率で、ブランド数がhだけあるとしています。
なお、
$$ r_1 + r_2 + \dots + r_h = k $$
で、足し合わせるとkがマーケット自体の購買率になるようになっています。ディリクレ多変量分布はブランドの数だけ、h個の正のパラメータ\( \alpha_1,\alpha_2, \dots, \alpha_h \)を持ちます。

ディリクレモデルは、以上の負の二項分布とディリクレ多変量分布を結合したもので、確率密度関数は以下の通りになります。

$$ f_{\gamma, \beta, \alpha_1, \alpha_2, \dots, \alpha_h}(r_1, r_2, \dots, r_h ) = \\ f_{\gamma, \beta}(k) f_{\alpha_1, \alpha_2, \dots, \alpha_h}(r_1, r_2, \dots, r_h | r_1 + r_2 + \dots + r_h = k )$$

この確率密度関数に色々かけて期待値を計算することで以下のようなものを算出することができます。
・あるブランドの購買者ごとの、あるブランドの購買の数の理論値
・プロダクトクラスでの購買の数の平均値
・あるブランドのみを買う母集団の割合
・購買者の平均購買頻度

諸々の式の導出は「[確率思考の戦略論] 1.確率理論の導入とプレファレンスの数学的説明」に詳しく書かれているので、見てみることをお勧めします。
数理統計学の知識とか、ベータ関数・ガンマ関数などの知識があれば式変形などに関してスムーズに理解できると思います。

ただ、この手法自体への批判などもないわけではなく、先ほどあげた論文、“The Dirichlet model in marketing”では、消費者行動を理解するのにつながるモデルではないとか、意思決定を扱っているモデルではないとする批判などがあるようです。ただ、幅広いマーケットで予測されてきた実績もあることから、モデルの限界を知りつつ適用するマーケットを増やしていくことが実務家に求められているのかなと思われます。

適用例

ディリクレモデルが様々な市場で適用されている事例が、『ディリクレモデルの境界条件 ― サービスへの適用可能性と限界 ―』という論文に記されていました。

当初は、インスタントコーヒー市場、衣料用洗剤市場、シャンプー市場などの最寄品(計画的に購入されることが少なく、単価は低く、何度も繰り返し購入される製品・サービス)のみで近似できるとされていましたが、
近年では銀行市場、クレジットカード市場、ガソリンスタンド市場、スーパーマーケット市場、テレビ番組市場、ファーストフード市場、オーケストラ市場、フットボールリーグ市場、野球市場などのサービス業や、スポーツウェアや自動車などの比較的高額な市場においても近似できるとされています。

データについて

ディリクレモデルの理論値を計算するには、4つのデータが必要とされています。
・1.そのカテゴリを購買した人々の全体に占める割合
・2.カテゴリに占める、いずれかの製品を購買した人々に対して記録された当該製品カテゴリの購買回数の平均
・3.各ブランドを一度でも購入した人々の割合
・4.各ブランドを購買した人々による各ブランドの購買回数の平均値

これらのデータはアンケートなどで収集する必要があるため、ディリクレモデルは総じて時間もお金もかかる手法であると言うこともできると思います。先ほどあげた、『ディリクレモデルの境界条件 ― サービスへの適用可能性と限界 ―』にはWEB調査でどんなアンケートを集めるのかの詳細まで書かれているので、自社の属するマーケットでこのモデルを適用する際は、それらを参考にすると良いと思います。

実践するコード

コードに関しては、こちらのColab(2_nb.ipynb)を書かれている方がおられたので、それを試すのも良いと思います。

ライブラリに関して、2016年と決して新しくないですが、R言語ではNBDdirichletというライブラリがあります。手法が1984年のものですから別に問題はないと思います。

こちらを実行した結果は、以下の通りです。

このdirichlet関数を使うことで、データを与えるだけで、ディリクレモデルのパラメータMやKやSが簡単に求まりました。

summaryで推定した諸々の値を確認できます。引数で色々と調整するので、実際に使う際はリファレンス(Package ‘NBDdirichlet’)を見てください。頻度のカットオフ値やヘビーユーザーの域値や、ブランド重複を見る際の基準ブランドなどを指定できます。

・buy:理論的なブランド浸透度、購買率、そのブランドの買い手によるマーケット内での購買率
・freq:そのブランドの購買の数の分布(以下の場合、6以上はまとめられている)
・heavy:特定の頻度の買い手におけるマーケットでの理論的なブランド浸透度、購買率
・dup:特定のブランドの購買者が他のブランドも購買している割合

この推定結果を使って、売上がどれくらいになるかが高精度にわかるのであれば、ブランドの浸透度が上がるような施策を打つことで、あるいは競合がそれらを打つことで売上がどう変わっていくかをシミュレーションすることもできるかもしれません。
その背景にはダブルジョパディの法則などがあると思うと結構面白そうですね。

参考文献

The Dirichlet: A Comprehensive Model of Buying Behaviour
Calculation of Theoretical Brand Performance Measures from the Parameters of the Dirichlet Model
The Dirichlet model in marketing
NBDdirichlet-package: NBD-Dirichlet model of consumer buying behavior
Package ‘NBDdirichlet’
ディリクレモデルの境界条件 ― サービスへの適用可能性と限界 ―
[確率思考の戦略論] 1.確率理論の導入とプレファレンスの数学的説明
Negative Binomial distribution
Dirichlet distribution

データサイエンティストがオブジェクト指向を学んでみた際のメモ〜scikit-learnの作法を知る

はじめに

エンジニアが作ったシステムの中で、データサイエンティストが開発する際に、オブジェクト指向プログラミングで書かれたソースコードに直面し、戸惑うかたも一定数いると思います。実際に私もその一人です。まだ完全に理解ができて、オブジェクト指向プログラミングができているわけではないですが、この記事を書くことを通じてより理解を深めていきたいと思います。

今回お世話になる本はこちら(『オブジェクト指向でなぜつくるのか 第3版 知っておきたいOOP、設計、アジャイル開発の基礎知識』)です。

この本を読んで、みなさん大好きなscikit-learnのソースコードを眺めてみようと思います。

オブジェクト指向とは

オブジェクト指向とは、ソフトウェアの保守や再利用をしやすくする技術のことを指しています。
個々のパーツに着目し、パーツの独立性を高め、それらを組み上げてシステム全体の機能を実現するという考え方に基づいています。

オブジェクト指向プログラミングのキーワード

参考にしている本によると、オブジェクト指向を理解する上での重大なキーワードとして以下の三つがあげられるようです。
・クラス
・ポリモーフィズム
・継承

クラス

クラスは同種のものの集まりを、インスタンスは具体的なモノを意味します。数学の集合論で言うところの集合、インスタンスは要素と例えられます。
なお、インスタンスはクラスに属するので、クラスをまたぐことはできません。

クラスの役割
【サブルーチンと変数(インスタンス変数)をまとめる】
メソッドの名前に関して違う名前をいちいち付けなくても済むようになる。
.fit_logistic_regression、.predict_random_forest_regressionみたいな表現ではなく、.fitとか.predictだけで済むようにできます。

【クラスの内部だけで使う変数やサブルーチン(メソッド)を隠したり公開する】
変数をいろんなところで使えてしまうと、思いがけない挙動で困ることがあったり不具合の原因を特定することが困難になります。クラス内のメソッドにアクセスできる変数を限定することでそれを実現します。グローバル変数はプログラムの保守性悪化の元凶となるため避けることが推奨されています。また、変数はプライベート変数だとして、クラスやメソッド自体を様々なところから呼び出し可能にして書くことも可能です。

【1つのクラスからインスタンスをたくさん作る】
同時に様々な処理対象に対して、処理を行いたい場合は、クラスから複数のインスタンスを生成することでそれが実現できます。
標準化のためのfit、教師あり機械学習モデルのfit、教師なし機械学習のためのfitなどクラスを複数複製してシンプルな書き方でそれらを実現することができます。
ここで作られたインスタンス変数は、どこからでもアクセスできるわけではないという観点でグローバル変数とは異なり、特定のメソッド内でしか使えないわけではないという観点でローカル変数とも異なります。

ポリモーフィズム

類似したクラスに対するメソッドについて、共通にする仕組みのことをポリモーフィズムと呼びます。単語自体の訳としては「いろいろな形に変わる」という意味です。メソッドを使う側が楽をできる仕組みとされます。

共通したメソッドを定める仕組みと理解してよさそうです。
なお、ポリモーフィズムを利用するには呼び出されるメソッドの引数や戻り値の形式を統一する必要があります。
また、入力がファイルだろうとネットワークだろうと問題なく動くように作る必要もあります。

継承

クラスの共通点と相違点を体系的に整理する仕組みのことで、全体の集合をスーパークラス、部分集合をサブクラスと呼びます。
集合の話で言うと、
動物はスーパークラス
哺乳類、爬虫類、鳥類、魚類、両生類、昆虫類などはサブクラス
という理解でよいです。
共通の性質をスーパークラスに定義しておくと、サブクラスを楽に作成することができます。
変数とメソッドをまとめた共通クラスを作り、別のクラスから丸ごとそれを拝借することで開発が楽になります。つまり、コードの重複を避けることができます。
当然ながら、サブクラスはスーパークラスでのメソッドと同じ使い方になるように引数や返り値の型をスーパークラスのそれに合わせる必要があります。

scikit-learnのGitHubを眺めてオブジェクト指向の観点で見てみる

さて、オブジェクト指向で重要な概念を知ったところで、実際にscikit-learnのソースコードでそれらの概念を表しているものを眺めることでより一層の理解が深まると思います。
そこで、https://github.com/scikit-learn/scikit-learnを眺めてみることとします。

教師なし学習ではK-meansのソースコードとDBSCANについて見てみます。
sklearn/cluster/_kmeans.py
sklearn/cluster/_dbscan.py

教師あり学習ではrandom forestとbaggingについて見てみます。
sklearn/ensemble/_forest.py
sklearn/ensemble/_bagging.py

ソースコードの所感としては、手法に応じて関数(def)の記述がなされ、その後にクラス(class)の定義がなされています。手法ごとに異なるアルゴリズムの部分をこの関数部分で書き、クラス部分のメソッドに関して手法ごとでも共通になるようにしているのかなと思いました。クラスのメソッドの中に複雑な関数を書くよりかは、クラスの外に書いておこうということなのでしょうか。

まずはK-meansのソースコードを見てみます。GitHubのリンクはsklearn/cluster/_kmeans.pyです。

base.pyというファイルから以下のクラスを呼び出しており、クラスがクラスを呼び出している構図になっています。

この中ではBaseEstimatorが最もメソッドの数が多く、推定量のパラメータを得たり設定したり、特徴量の数を確認したりいろいろできるようです。

_get_param_names、get_params、set_params、__repr__、__getstate__、__setstate__、_more_tags、_get_tags、_check_n_features、_validate_data、_repr_html_、_repr_html_inner、_repr_mimebundle_

確かに、これだけのメソッドをいちいち各手法ごとに書くのは骨が折れるので、クラスからクラスを呼び出すのはリーズナブルだなぁと思いました。

さて、class KMeansの話に戻ります。メソッドとしては以下のものがあるようです。
__init__、_check_params、_validate_center_shape、_check_test_data、_check_mkl_vcomp、_init_centroids、fit、fit_predict、fit_transform、transform、_transform、predict、score、_more_tags

続いて、MiniBatchKMeansというクラスが現れますが、これは先ほど定義したKMeansを呼び出して使うため、base系のクラス→Kmeansクラス→MiniBatchKMeansクラスとより深い階層となります。

このMiniBatchKMeansクラスでのメソッドは以下の通りですが、KMeansクラスを呼び出していることから、MiniBatchKMeansクラスかつKMeansクラスのメソッドが扱えるようになっています。
__init__、_check_params、_mini_batch_convergence、_random_reassign、fit、partial_fit、predict、_more_tags

続いて、DBSCANのソースコードを見てみます。GitHubのリンクはsklearn/cluster/_dbscan.pyです。

ClusterMixinクラスとBaseEstimatorクラスを呼び出していますが、先ほど登場したので紹介はしません。
DBSCANクラスのメソッドとしては、__init__、fit、fit_predictがあります。

読み込んだクラスからメソッドを引き継いていることがわかります。

続いて、random forestを見てみます。GitHubのリンクはsklearn/ensemble/_forest.pyです。

これまでのクラスと同様にbase.pyやクラスを呼び出しています。一方で、BaseEnsembleはensemble/_base.pyのクラスとなっています。

さて、BaseForestのメソッドですが、
__init__、apply、decision_path、fit、_set_oob_score_and_attributes、_compute_oob_predictions、_validate_y_class_weight、_validate_X_predict、feature_importances_、n_features_となっております。

以下、ForestClassifierとForestRegressorについて記しますが、教師なしのクラスと同じように、base系のクラス→BaseEnsembleクラス→BaseForestクラス→ForestClassifierクラスと深い階層になっているのがわかります。

なお、ForestClassifierクラスのメソッドは以下の通りです。
__init__、_get_oob_predictions、_set_oob_score_and_attributes、_validate_y_class_weight、predict、predict_proba、predict_log_proba、_more_tags

ForestRegressorクラスのメソッドは以下の通りです。
__init__、predict、_get_oob_predictions、_set_oob_score_and_attributes、_compute_partial_dependence_recursion、_more_tags

これで終わりかと思いきや、

などのクラスがありました。これまでのクラスを引き継ぎ、__init__の部分で手法の細かいところを変更しているようです。我々がscikit-learnで呼び出しているのはこれですね。

最後にRandomTreesEmbeddingクラスがありました。教師なしで、スパースな行列を変換するためのもののようです。

メソッドとしては、__init__、_set_oob_score_and_attributes、fit、fit_transform、transformがあります。

当然ではありますが、教師ありのクラスのものとメソッドが違っているのがわかりますね。

最後に、baggingを見てみます。GitHubはsklearn/ensemble/_bagging.pyです。

RandomForestのものと同様に、BaseEnsembleクラスやABCMetaを呼び出していることがわかります。
メソッドとしては以下の通りです。
__init__、fit、_parallel_args、_fit、_set_oob_score、_validate_y、_get_estimators_indices、estimators_samples_、n_features_

いよいよくどくなってきましたが、BaggingClassifierクラスで、これはこれまでのBaseBaggingを引き継ぎます。

メソッドとしては、__init__、_validate_estimator、_set_oob_score、_validate_y、predict、predict_proba、predict_log_proba、decision_functionがあります。

最後はBaggingRegressorです。これもbase系のクラス→BaseEnsembleクラス→BaseBaggingクラスと深い階層となっています。

BaggingRegressorクラスのメソッドは__init__、predict、_validate_estimator、_set_oob_scoreです。

ここで定義されるメソッドは少ないですが、実際に呼び出してみるとクラスを引き継ぐことで多くのメソッドを使えるようになっていることがわかります。

以上から、scikit-learnにおいては、オブジェクト指向プログラミングが実践され、クラスを引き継ぐことで書くべきソースコードの量をできるだけ抑えながら多種多様なアルゴリズムが開発されているのだなと実感することができました。

おわりに

今回、オブジェクト指向プログラミングを少し学び、それがscikit-learnでどのように反映されているのかを確かめましたが、なかなか深い階層でクラスを呼び出しているものがあると思いました。理解をすればプログラミングは楽になりますが、初手で構造をしっかり理解しないと階層の深さに戸惑ってしまいますね。
これが機械学習とかではなく、Web開発のコードとかだともっと深かったりするのでしょう。

参考情報

オブジェクト指向でなぜつくるのか 第3版 知っておきたいOOP、設計、アジャイル開発の基礎知識
Get the Most out of scikit-learn with Object-Oriented Programming
Pythonの抽象クラス(ABCmeta)を詳しく説明したい

Flaskでイコちゃんペリー画像分類器の予測結果を返す

はじめに

先日の記事で作ったイコちゃんとペリー分類器ですが、今回は画像ファイルを送れば分類結果が返されるFlaskのAPIを作ってみようと思います。すごく簡単にできそうな記事を見つけたので、そこで紹介されていたコードを使います。

前回のおさらい

前回は、ペリーの画像27枚、イコちゃんの画像20枚を集めKerasでVGG16を使って分類器を作りました。テストデータもペリー9枚、イコちゃん7枚の計16枚と用意し、F1スコアは0.705くらいでした。画像を集めるのが面倒なのと、GPUを持っていないので更なる精度向上はいったん目指しておりません。

Flaskとは

FlaskとはWikipediaによると、「Python用の軽量なウェブアプリケーションフレームワークで、Djangoの次に人気がある。」とあります。学習済みモデルで推論の処理を受けつけ、その結果を返すということにしか関心がないデータサイエンティストとしては、ウェブアプリケーションフレームワークをわざわざ学びたいものではないですが、データサイエンス界隈ではしばしば見かけることから、学ばざるを得ないなと思います。
Flaskには「処理を受け付け、結果を返す」というただそれだけの関心で向き合っていく次第です。
公式ドキュメントはこちら(Welcome to Flask — Flask Documentation (2.0.x))になります。
そういえば以前、「[第3版]Python機械学習プログラミング 達人データサイエンティストによる理論と実践 (impress top gear)」という書籍でFlaskを用いたレコメンドAPIを時間制限のある無料のサーバ(PythonAnywhere)で実装したことはありましたが、CSSやHTMLを色々設定して面倒だなという印象がありあまり記憶に残っておりません(笑)。

今回の処理

この記事のソースコードはこの記事、「How to Build A Machine Learning API Using Flask」から使わせていただきました。ローカル環境で機能するAPIをFlaskで作るというものです。

ざっくりとした処理の流れとしては、
学習済みモデルの読み込みをした状態で、
入力された画像を前処理し、
推論を行い、その結果を返すというものです。

ソースコード

さて、学習済みの画像分類モデルで、画像を受け付けて推論し、結果を返すコードは以下の通りとなります。

こちらのソースコードをapp.pyのファイル名で保存して、
コンソール上で

と実行すれば、FlaskのAPIサーバが立ち上がります。
今回はローカル環境なので、ブラウザで
http://0.0.0.0:5000/
を表示すればサーバが起動しているのを見れます。
さて、肝心の画像分類ですが、
コンソール上で以下のようにcurlコマンドを叩けばローカルのサーバから推論結果が返ってきます。–formという引数で’file=@”/perry_image/test/ikochan_test_8.jpeg”‘みたいにローカルのファイル名を指定して実行する形となります。

1なので、この画像はイコちゃん判定されました。過去の記事にもあるように、正解率は11/16くらいなので、69%と微妙ですけども。
今回はローカルサーバですが、Webサーバ上で起動すれば、機械学習を用いたツール開発が実現できますね。
なにより、思ったよりも短いコードで実現できてしまうことに驚きました。推論などの処理は基本的にPOSTのところに書く感じです。

今後:本番運用に必要なことについて

仕事で使うとなると、このコードを載せるサーバとかセキュリティ周りをどうするかというのが気になります。処理回数の制限とかIP制限とか認証キーとかどうするのか。
URLが流出するかもしれないし、誰かがDOS攻撃とかしてくる人がいるかもしれないし。
データ分析をするだけのご身分ではこういったことを考えることはないですが、データサイエンティストという職種に求められるスキルが少しずつ広がっていくのは面白いとも思えるので、粛々と向き合っていきたいです。

最近、「Python FlaskによるWebアプリ開発入門 物体検知アプリ&機械学習APIの作り方」という書籍が出ていたので、ポチりました。本番で運用する観点でどういったリスクを潰しておくべきか、この本から学んで実装までいけるといいなと思います。

参考情報

[第3版]Python機械学習プログラミング 達人データサイエンティストによる理論と実践 (impress top gear)
How to Build A Machine Learning API Using Flask
GETとPOSTの違いについて

OpenCVで遊んだり、Kerasで「かものはしペリー」と「イコちゃん」の画像分類をするの巻

はじめに

正月は帰省もせずに暇だったので、普段の業務ではほとんど扱わない画像関連でブログを書いてみようと思います。
まず、よくありそうなOpenCVの適用や、DNNを用いた画像分類などを行います。扱う画像は当然、かものはしペリーのぬいぐるみです。ブログのタイトルやドメイン名になっている通り、私はかものはしペリーの愛好家です。
この記事の読者層は私で、いつか仕事で使うのをイメージして備忘録として残す感じです。
説明があまりありませんが、気分次第で追記するかもしれません。あしからず。

OpenCVで行うあれやこれや

インストールする

これで入ります。

画像を読み込んでRGBにする

明度値の書き換え

量子化

グレースケール

画像ヒストグラム


HSV変換について
・Hue:色の種類(例えば赤、青、黄色)
・Saturation:色の鮮やかさ。色の彩度の低下につれて、灰色さが顕著になり、くすんだ色が現れる。
・Brightness:色の明るさ。

明度変換

フィルタ処理

特徴点検出

画像の中から特徴的なポイントを抽出するアルゴリズム。

マッチング

特徴量抽出

・BFMatcher:Brute-Force matcher(総当たりで特徴点を比較している。類似度は数値が低いほど類似しているとみなす。)
・AKAZE:日本語の『風』から命名された手法。二つの画像のキーポイントを発見するために使われる。変化への耐性が強いとされる。非線形拡散方程式を近似的に解いて、非線形スケール空間の特徴量を検出している。

これがベースとなるペリーの画像。

以下では、このペリーとの類似度を計算している。

画像分類

ペリーとイコちゃんの画像からペリーかどうか判定したい。
今回はペリーの画像27枚、イコちゃんの画像20枚を用意しました。

今回はKerasにある、VGG16というモデルを使って分類を行います。ハイパーパラメータはAdamです。reluとかドロップアウト層とかは参考文献のまんまを使っています。

ファイルの読み込みです。
trainというディレクトリにperry_とかikochan_とかからなる画像ファイルがある想定です。

画像からの学習用のデータの作成。

学習の実行。


テストデータにモデルを当てはめて推論し、精度をみます。今回はテストデータとして別に、ペリー9枚、イコちゃん7枚の計16枚の画像を用意しました。
果たしてペリーとイコちゃんを識別することはできるのでしょうか。

・Accuracy:0.688
・Recall:0.857
・Precision:0.6
・F1:0.705

どうなんでしょう。まずまずなんでしょうか。

間違えたやつがどれか確認

仕事で使う機会があるようなないような画像の世界ですが、計算資源が大事だなと思いますね。

参考情報

テキスト・画像・音声データ分析 (データサイエンス入門シリーズ)
Display OpenCV Image in Jupyter Notebook.py
Python でグレースケール(grayscale)化
OpenCV で画像のヒストグラムを作成する方法
HSV色空間
色空間の変換
画像フィルタリング
OpenCV: 特徴点抽出とマッチング
キーポイントとマッチの描画関数
OpenCVのAKAZEで顔写真の類似度判定をやってみた
総当たりマッチングの基礎
OpenCV3でAKAZE特徴量を検出する
KAZE Features
小惑星画像の対応点決定を目的としたSIFTとAKAZEの性能比較
線形・非線形拡散方程式の差分解法と解の可視化
AI技術を魚種の画像分類に応用してみた!
ベクトルの内積や行列の積を求めるnumpy.dot関数の使い方
Python | Count of common elements in the lists
[解決!Python]リストの内包表記と「if」を組み合わせるには
Convert png to jpeg using Pillow
ValueError: Failed to convert a NumPy array to a Tensor (Unsupported object type int) in Python
Pythonで文字列のリスト(配列)の条件を満たす要素を抽出、置換
ImportError: cannot import name ‘adam’ from ‘keras.optimizers’
pandas.DataFrame
Pythonでenumerateとzipを組み合わせて同時に使う

各業界でのデータサイエンスの活用について調べてみた(随時追加)

仕事で、いろんな会社でデータサイエンスってどう使われているのですか?と聞かれることがあり、自分としてはなんとなくしか掴めていないな、知ったかぶりしたくないなと思うところがあったので、やや手厚くリサーチをしてみようと思いました。

2022/3/6の段階では11つの市場しかないですが、最終的には30市場を目指します。

【2021/11/27追記】
公開したところ、それなりにこの記事に関心を持ってくださった方が多かったようなので、少しずつ事例を埋めていこうと思います。

業界別のページ内遷移

自動車・同附属品製造業
建設
不動産
医療(医薬品の卸)
生命保険
外食
物流
BtoC-EC
電力
電気通信
スーパー

業界別にデータサイエンスの事例を集めてみる

・業界としては、市場規模マップの上位30の市場としてみる

事例の調べ方

各業界の売上1~2位の企業名とデータサイエンス系キーワードを掛け合わせGoogle検索ないしGoogle Scholar検索を行う。

  • Google検索を自動で行う。
    • 「かものはし製パン 機械学習」
    • 「かものはし製パン 人工知能」
    • 「かものはし製パン データサイエンス」
  • 30業界2社の3つのキーワードごとの検索結果上位30位を取得
    • 計5400の検索結果から求人などを除外
    • 不要なものを除外したリストから目視で精査、まとめ

検索自動化のソースコード

一応、Google Scholarの検索自動化のためのPythonコードを置いておきます。クローリングのお作法などは「Pythonクローリング&スクレイピング[増補改訂版] -データ収集・解析のための実践開発ガイド-」のような本で身につけておくと分析関連業務で楽になります。

総務省の白書に関してコメント

日本企業におけるデータ活用の現状」という総務省が出している2020年3月のアンケートに基づいたレポートがあるのですが、なかなか良い統計が載っていて、日本全体の会社におけるデータ活用度をある程度掴むことができると思いました。

どうやら大企業の半数近くは経営企画や製品企画、マーケティングにデータを活用していて、大企業の2割の企業で機械学習を用いたデータ活用を行なっており、大企業の5割の企業でデータ分析専門の部署があるようです。
データ分析が、かなり社会に浸透しているのだなと思われました。
そして、多くの企業の関心事がデータの質になってきているようです。データ分析で重要な観点にしっかり関心が高まっているのは良いことですね。

業界ごとの取り組み

以下では業界ごとに事例などをまとめていきます。結構長くなりそうです。

自動車・同附属品製造業

数理工学や群体数理、行動経済学など幅広い領域を研究対象としている。

  • シミュレーションを活用した制御ソフトの自動検証技術
    • サーチベーステスト(SBT):自律走行ロボットが充電ステーションへ帰還する際に、自己位置の推定に誤差が生じる課題を抱えていたが、SBTを用いることで推定誤差が生じる環境要件を特定してソフトの誤差80%減を実現していたりする。
  • 機械学習による性能テストの効率化
    • エンジンの燃焼に関するシミュレーションの実行時間の短縮を機械学習で行う。シミュレーションの効率化が積極的に行われている。
  • 歩行者保護性能の評価試験
    • ボンネットの設計効率化に向けて、CAE(computer-aided engineering)で構造解析を行う前に、ある程度の歩行者保護性能をAIで判定できるようにする取り組みが行われている。
  • Positive-confidence(Pconf)分類
    • アプローチとしては、正例の分布とその信頼度だけで、分類ミスによって生じる損失の期待値を最小化する手段。
    • ドライバーの心電情報から眠気を推定する際に用いた
  • 深層強化学習
    • 自動運転の際に、「ぶつからない」ことを学習する分散機械学習
  • 車内にカメラやマイク、脈拍センサーなどを置き、乗員の行動や会話、生体情報などを把握する開発
    • 自動運転車からデータを集めてAIで解析すると、人の行動や嗜好、健康状態、さらには感情まで推定
    • 感情エンジンを開発し、ドライバーの表情や声の調子からストレス状況を判断して安全運転をサポートしたり、ライフスタイルでの嗜好を学習して、状況に応じた選択肢を提案する。

建設

  • スマートハウス
    • 既存のIoT機器やWebサービス、建物内に設置するデータ収集サーバを連携し、個々の機器・サービスを統合するシステムを構築し、家電の遠隔操作や省エネアドバイスなどの生活サービスをユーザーの好みに応じてカスタマイズできるシステムや、音声認識による機器操作、情報配信等のサービスにつなげる。温度センサとエアコンや電動窓を連動し真夏の寝苦しさを解消するなども。
    • HEMS(Home Energy Management System)の規格のもと、IoTデバイスを起動させるケースが多い。音声認識を用いたアプリケーションや気象や様々なセンサーを基にした家電の最適化などが扱われる。
  • 施設内の映像解析
    • 施設内に設置したカメラ映像から利用者のマスク着用や施設内カフェテリアの混雑度を自動で検知する実証実験を行っている。モニターでリアルタイムの映像を確認できるが、個人情報保護の観点から人物はシルエット表示されないとのこと。なお、実証実験で利用するカメラ映像は2カ月間保存・利用し、期間終了後に消去する。
  • マンションにおける電力供給システムの最適化
    • 家庭向けの発電設備の稼働を、過去の電力使用データなどから最適制御を行い、遠隔でコントロールする。生活リズムごとに家庭をクラスタリングしている。
  • 在宅健康モニタリング
    • 在宅健康モニタリングと早期発見システム(Early Detection System = EDS) の推進に特化したプログラムを構築のために大学と共同研究

不動産

  • 不動産価格の算出のための機械学習システム
    • 所有マンションの推定成約価格を機械学習で算出して提示するシステムがWebサイトで提供されている。過去の制約事例のデータから予測している。
  • 賃料推定のための機械学習
    • 賃貸仲介データ等が少ない都心商業施設を対象に賃料を推定できるシステムが開発されている。
  • 間取りの検索システム
    • ユーザーに適した間取りの物件をレコメンドできるシステム。画像処理技術を間取りのデータに対して適用している。洋室や和室なども分類されている。

医療(医薬品の卸)

  • 機械学習を用いた、工場における医薬品の物流最適化(医薬品の卸の会社)
    • 商品(医薬品)の保管・払い出し・仕分けなどの作業を自動化する、ピッキングロボットを開発し、人間の2〜5倍の作業量をこなしている。
  • 医薬品の出荷予測
    • 過去数年分の医薬品の出荷データをもとにGCPで機械学習を行い、余剰在庫や欠品リスクを回避させようとしている。
  • 医薬品の配送の最適化
    • 医薬品の販売、物流、商品、需要トレンドのデータを用いて機械学習を行い、注文数や配送発生確率、納品時の滞在時間を予測できるようにした。

生命保険

  • 保障設計のレコメンドシステム
    • 保障設計予測モデルを構築し、顧客の意向に基づいて保障プランをレコメンドする。過去の大量なデータを用いて、保険において重視したい保障内容や保険料の予算をもとに、保障プランを自動生成。
  • 保険の保障見直しのためのレコメンドシステム
    • 未熟練な保険のプランナーの業務を支援するアプリケーション。年齢、性別、家族構成はもちろん、保険の保障設計書などのテキストも学習用データにしている。
  • Human in the loop
    • 機械学習システムは完璧なものではないので、人間の仕事を補助するなど、飛行機における管制システムのような存在として共存するという考え方。営業職員が多い生命保険会社では重要な観点。営業職員がベテラン層の営業職員と比肩するコンサルティングをより適切なタイミングで実施しやすくするリコメンド機能などがそれにあたる。
    • 最適な提案のタイミング、最適な活動レコメンド、最適な教材・資料探しなど、営業活動の支援のための分析に取り組む事例がそれなりになる。最適な顧客訪問、最適なメッセージなどを見つける。
  • 入院日数予測モデル
    • 保険加入時の健康状態(告知事項や健診結果など)と保険給付実績を分析し、加入時の健康状態から将来の生活習慣病における入院日数を予測するモデルを開発。このモデルを用いてリスクを評価できるようになり、これまで引き受けれなかった顧客からの申し込みを引き受けることが可能になった。
  • 営業の教育支援ツール
    • AIを相手にしたロールプレイング演習などを行い、新人の育成を支援するツールなどが作られている。
  • 保険の引き受け査定の自動化
    • 健康診断結果報告書や人間ドック成績表をもとに、OCRでデータを抽出し、それらのデータをもとに機械学習を用いて自動での医務査定を行えるように訓練。これまで2〜3日かかっていた査定業務が3分以内に完了するように。

    外食

    • 配送員向けアプリ
      • 機械学習を用いて、ベテラン配達員のデータから学習し、配送員にとって効率の良いルートを提案するアプリ。
    • 機械学習を用いたクーポン配布
      • 顧客ごとの来店確率を計算し、その確率が上位の顧客にクーポンを送付するという施策を試験的に展開している。コンバージョンレートが通常の3倍になったケースもあるとのこと。天候や気温などのデータとも連動しているとのこと。
    • 注文の需要予測
      • 過去の注文履歴を分析し、宅配需要を10分単位で予測したり、配達ルートの最適化を行う取り組み。フードロスを減らすこともモチベーションとしてある。
    • レコメンドとしてのデジタルメニュー
      • 顧客の登録情報や来店時刻や立地ないし季節・天候に応じて、客ごとにメニューが変わるようなレコメンデーションを試験導入しているとのこと。

      物流

      • 強化学習を用いた船舶の航路の最適化
        • 膨大な数の航海シミュレーションを通して、徐々に最適な避航行動を学習し、様々な状況下で安全性と経済性に優れた避航操船行動を選択できるプログラムの開発などが進められている。航路作成は人間だと3時間かかるらしい。
      • 画像解析による船舶の見張り支援システム(衝突回避のため)
        • 船上で撮影された映像に対して、サーバー上で画像を解析し機械学習を実施後、その物体との距離を求めてから、遠隔で船上ソフトウェアを更新することで、利用しながら認識率等の性能が向上する仕組み。
      • 船体の異常検知の自動化
        • IoTで航海データ・機関データを取得し、船舶の運航管理者が船舶の異常を検知できるように機械学習の導入を進めている。これまでは人間が24時間体制で管理していた。
      • 業務量の予測
        • 宅急便の拠点における、数ヶ月先の業務量を予測するため、機械学習モデルを毎月アップデートし、需要に応じた効率的な経営資源の最適配置とコスト適正化を推進することを目指している。
      • 作業員の業務日報のOCR
        • 紙の作業日報の情報のシステム入力を自動化するために、機械学習を用いたOCR技術を適用している。

      BtoC-EC

      • 商品の非構造化データを構造化データにする、あるいは商品情報の自動生成、自動判別
        • 機械学習(CNN、RNN)や自然言語処理をもちいて、商品から情報を抽出したり、レビューを分析したり、商品のカテゴリを分類したりしている。商品の画像のデータからカテゴリを予測するなども行われている。
        • 出品時に登録した商品の写真画像から、商品の内容などの入力候補を提示する機能などが開発されている。ディープラーニングとk近傍法などを組み合わせた事例がある。
      • 潜在的に購買する可能性があるユーザーの推定
        • 機械学習を用いて金融サービスを使って購買をしそうなユーザーを分類するモデルを作成し、予測スコアが一定以上のユーザーに介入するなどを行っている。
        • 機械学習を用いた独自のアルゴリズムで消費行動を解析することで、購買の見込みがあるユーザーを抽出するなどし、商品の広告配信に活かしている。
      • 動画コンテンツの翻訳
        • アテンションの伴ったRNNでの機械学習を行い、中国語を英語に変換している。
      • 商品推薦システム・パーソナライズドクーポンアルゴリズム
        • 商品データ、購買履歴データ、閲覧履歴データを対象とし、古典的な相関ルール抽出、あるいはMatrix Factorizationを適用させたり、商品やユーザなどを固定長のVector に変換して距離を計算するEmbeddingなども行い、RNNなどの深層学習アルゴリズムを適用している。
      • チャットボットによるサービス利便性の向上
        • ユーザーが知りたい問い合わせの多くにチャットボットが回答している。FAQを情報源としてNLPなどを用いてその中から一番近い答えを返している。
      • 多椀バンディットアルゴリズムを用いたABテストの最適化
        • T.B.A
      • 在庫数の最適化のための商品需要予測
        • T.B.A
      • 異常検知
        • T.B.A
      • 商品価格の推定
        • 出品された商品に対して、Factorization Machinesというレコメンドシステムでよく利用される手法の一種であるDeepFMを用いた価格の予測が行われている。機能によっては端末のアプリ側で計算を行うことから、エッジコンピューティングのためのモデル軽量化なども進められている。
      • 不正検知
        • 違反出品検知システムとして、Human-in-the-Loopを実践。人間が介入するため、判定するべき対象とその他との境界に位置するデータに対してのアノテーションを継続的に入手している。アルゴリズムとしてはDNNを用いている。

      電力

      • メッシュ単位での電力需要予測
        • メッシュ単位での気象予測データを活用して電力需要の予測精度を高めるように、スパースモデリングやアンサンブル学習の機械学習技術が使われている。解釈可能性も重視されるので、一般化加法モデルなども利用されている。なお、電力需要量は、カレンダー条件(時間帯,曜日など)と気温や日射強度などの気象条件からおおむね推定できるとされている。機械学習系の手法もあれば、周期性に着目し、状態空間モデルで予測する事例もある。
      • 機械学習による石炭火力発電所における燃焼調整の体系化
        • 運転データやオペレーションとメンテナンス(O&M)の知識をもとに、設備の燃焼効率最適化を機械学習で行う。
      • 機械学習を用いたダム操作最適化システム
        • ニューラルネットワークを利用したダム操作最適化システムの研究がされている。雨量予測、河川流量予測、ダム操作最適化の三つの領域での最適化がなされている。最適化操作のために強化学習も採用されている。学習期間の報酬を最大化するようにネットワークの重みを修正している。
      • 異常検知
        • ヘリコプターやドローンなどで撮影した送電線の動画データを基に、軽微な損傷や異物の付着といった異常を見つけ出すために深層学習が使われている。誤判定のチェックに多少の人手をかけても、十分な業務時間の短縮効果を得られるとのこと。
        • 工場設備の温度変化のデータを画像化して、CNNで特徴量を作り、不具合や異常の分析を行うなどしている。
      • 太陽光の発電量予測
        • T.B.A
        • T.B.A
      • 大量のデータを駆使しての設備の劣化予測診断
        • 高クロム鋼配管溶接部のクリープ損傷評価を深層学習(AlexNet)やサポートベクターマシンを用いて行っている。学習用のデータが少ないことから、転移学習も行っている。
        • T.B.A
      • 燃料プロセスの最適化
        • ボイラ燃焼調整の最適化等
        • 熟練技術者が半日程度かけてつくっている燃料の運用計画を数分で行えるように数理最適化などの取り組みがされている。
      • 生活リズムの変化を察知
        • スマートメーターにある電気使用量の時系列変化を捉えて、独居している人の異常を親族に通知する仕組みを構築している。
        • 高齢者を介護する負担を減らすための実証研究などが進められている。
      • 電力の需要予測
        • 特徴量としては、カレンダー情報・気象情報それらを組み合わせた相互作用項で、重回帰モデルと一般化加法モデルに対してアンサンブル手法を適用している。
        • k-nearest neighborでの距離的な離れ具合でもって、異常な需要を当てるなどの取り組みがされている。それと重回帰ベースのモデルとを合わせて予測している。

      電気通信

      • 機械学習モデルの公平性
        • 人を対象とした意思決定に関する過去の履歴(訓練データ)と、矢印(因果グラフ)によって「どんな予測が不公平か」に関する事前知識を表現したものを入力として受け取り、公平な予測を行う機械学習モデルを出力している。
      • 深層学習モデル
        • どのような条件で取得されたデータであるかがまったくわからない寄せ集めの学習データからであっても、認識モデルを学習可能な深層学習技術を実現。Data Augmentationの適用をした模様。
      • 料金未納などの連絡Bot
        • 「AI電話サービス」が対象者に対し、本人確認、支払い意思、支払日などを確認し、確認結果をCSVにて出力。電話に出ない債権者は自動で再架電話リストとして登録し、再度架電を行うとのこと。
      • 音声のノイズに関する分析
        • ロボットが受け取る人間の音声に関して、構成する音の雑音のカテゴリを機械学習で分類するという取り組みが行われている。メル周波数ケプストラム係数(MFCC)を用いて、それを元に機械学習アルゴリズムとしてDNNやSVMなどを試している。
      • 通信障害の異常検知
        • 既存の監視システムでは検知できないような通信障害を検知するために、SNSなどの情報をもとに、そのSNSの情報に機械学習を用いて分類を行い、通信に異常があるかどうかを判定する研究がなされている。アルゴリズムとしてはSVMが使われている。
      • 圧縮化技術
        • 電波の到来方向を高速で検知するために、それらに関連する情報圧縮のためにニューラルネットワークなどの機械学習を適用している。

      スーパー

      • 需要予測・発注最適化・在庫管理最適化
        • 食パン、牛乳、豆腐、冷凍食品などのデイリー品を中心に需要予測の実証実験とあり、発注にかかる時間を1/3ほど短縮できたとある。アプローチとしては機械学習に解釈可能性を持たせたものらしい。人の発注業務を支援するという観点から予測性能だけでなく、解釈可能性も大事なのだろう。
      • ATMへの機械学習の実装
        • スーパーの店内にある、各ATMの入出金予測を行っている。ここでも機械学習の解釈可能性を大事にしており、どれくらい現金を保持しておくかを人間が決めるのを支援する仕組みのようです。ちなみに、現金の補充は警備会社が行っているらしい。
      • 店内カメラの解析
        • 店舗によっては数百のカメラで解析しているらしい。売り場への立ち寄り時間などを分析して、店内レイアウトの改善に使ったり、店員の所持するアプリに困っていそうなお客さんを検知して通知を飛ばすなども行っている。また、混雑の検知などにも使われたり、映像から年齢を推定し、未成年への酒類販売を未然に防ぐなどにも活用しようとしているらしい。
      • 配送ルートの最適化
        • 運転手の割り振りや受取場所、時間を最適化するほか、注文時間などに応じて宅配料金が変動する仕組みも試しているとのこと。
      • 割引率の最適化
        • 販売実績や天候・客数などの環境条件を学習し、時間帯ごとに各商品の陳列量に応じて適切な割引率を提示するツールの開発もなされている。

      今さら”Recommendations as Treatments: Debiasing Learning and Evaluation”を読みソースコードを眺めるなど

      はじめに

      最近、『施策デザインのための機械学習入門〜データ分析技術のビジネス活用における正しい考え方』が流行っていると思いますが、私も少しずつ読んでいます。

      2019年ごろから勉強会などで知る機会のあったCountefactual Machine Learningですが、仕事で機械学習を使えば使うほどにその必要性を強く感じます。
      書籍は体系的にまとまっていて非常に良いのですが、せっかく関心を持ったのでその源流と思われる論文やソースコードを漁ってみようと思いました。

      今回、深ぼるのはこちらの論文です。
      Recommendations as Treatments: Debiasing Learning and Evaluation
      https://arxiv.org/abs/1602.05352

      情報を漁る

      arXivの方はAppendixついてなかったのでこちらの方がいいと思います。
      https://www.cs.cornell.edu/people/tj/publications/schnabel_etal_16b.pdf

      著者のスライドもありました。
      https://www.cs.cornell.edu/~schnabts/downloads/slides/schnabel2016mnar.pdf

      まずは読む

      以下に読んだ際のメモを箇条書きします。

      • レコメンドのデータは大体偏っている。偏ってアイテムの評価がされる。
      • レコメンドに因果推論のアプローチを適用する。
      • 傾向スコア(ランダムっぽさ)を用いた学習の重み付け
      • バイアスの最小化?のアプローチ
      • 行列分解による欠損値補完に対する重み付けをした。
      • 色々なデータで試した。
      • IPS(Inverse Propensity Score)で重み付けしたら誤差の不偏推定量を手に入れれる。
      • 評価方法はMAE(Mean Absolute Error)とかDCG(Discounted Cumulative Gain)など
      • 比較は一様に評価のデータが観察されると仮定したナイーブなモデルとで行う。
      • 行列分解の次元数dとか、正則化項のラムダはハイパーパラメータとして扱う。
      • 行列分解かつIPSで重みづけしたモデルはロバストに良い性能になった。

      既出の参考資料を読む

      ソースコード読む

      コーネル大学のサイトに論文のソースコードがあったので、そちらの解読を試みます。
      https://www.cs.cornell.edu/~schnabts/mnar/

      そんなにソースコードは多くなかったです。

      train.sh

      学習のバッチ処理

      train.py

      python ../bin/train.py –lambdas 0.008,25 –numdims 40 –ratings data/train.ascii –propensities data/propensities.ascii

      • コマンドライン引数たち
        • lambda:正則化パラメータ。デフォルトは’0.008,0.04,0.2,1,5,25,125′
        • numdims:行列分解の次元数。デフォルトは’5,10,20,40′
        • ratings:訓練用データの指定を行う(ASCII formatの行列)
        • propensities:傾向スコアのデータの指定を行う(ASCII formatの行列)
        • metric:デフォルトは’MSE’、MAEかMSEを選べる

      MetricsのMSE/MAE関数を呼び出し、
      Expt3のlearn関数を使って学習を実行する。

      Metrics.py

      • MSE関数
        • ITEMWISE_METRICSを呼び出している
      • MAE関数
        • ITEMWISE_METRICSを呼び出している
      • ITEMWISE_METRICS関数
        • MSEかMAEかでnumpyのデータの形式を指定している。
        • SET_PROPENSITIES関数を呼び出している
        • 観測された評価と予測した評価の差分にIPWを掛け、観測誤差とする
        • 累積の観測誤差を出す
        • IPWの合計値で累積の観測誤差を割ったglobalNormalizerを計算して返す
        • ユーザー単位での観測誤差の推定値をユーザー数で割ったuserNormalizedMetricを計算して返す
        • アイテム単位での観測誤差の推定値をアイテム数で割ったitemNormalizedMetricを計算して返す
      • SET_PROPENSITIES関数
        • IPWがあればそれを使い、ない場合は出現割合を返している
        • 観察されたデータを考慮して補間を行う(numpy.ma.arrayのmask)

      Expt3.py

      Expt2のINIT_PARAMS、MF_TRAIN、FINAL_TRAINを実行する
      MFのPREDICTED_SCORESを実行する

      • 処理の流れ
        • もろもろの引数で学習の際の設定を受け取り
        • 傾向スコアの逆数からIPWを計算し
        • そのスコアを学習用データで補間し
        • ランダムに並び替える
        • 4-foldsでのクロスバリデーションを行う
        • 学習を並列処理を行う
        • 予測スコアから一番いいスコアのモデルを選ぶ
        • 行列分解での機械学習を行う
        • 行列分解での予測値を計算する
        • 予測結果を返す

      Expt2.py

      MFのGENERATE_MATRIX、PREDICTED_SCORESを実行

      • MF_TRAIN関数
        • IPWを受け取って、上限下限などを調整
        • それをMFのGENERATE_MATRIX関数に適用
      • FINAL_TRAIN関数
        • MF_TRAIN関数と似たような処理
        • 交差検証してベストだったパラメータに適用する想定
      • INIT_PARAMS関数
        • 評価行列の欠損値を補間している
        • 行列特異値分解を行っている
        • その結果をstartTuple(初期値)として与えている

      MF.py

      • PREDICTED_SCORES関数
        • バイアスがあるかどうかで分岐
        • バイアスがあれば、元のスコアにユーザーのバイアス、アイテムのバイアス、グローバルなバイアスを足し合わせる
        • バイアスがなければそのまま返す
      • GENERATE_MATRIX関数
        • 指標がMSEかMAEかで分岐
        • MetricsのSET_PROPENSITIES関数を実行
        • ユーザー単位での標準化やアイテム単位での標準化、全体での標準化のための計算をする
        • 標準化の方法で分岐、傾向スコアを標準化する
        • バイアスのモードで分岐
        • 学習のための初期値としてのデータを設定
        • 目的関数の最適化(最小化)を行う
        • その結果を返す
      • Mat2Vec関数
        • 行列をパラメータのベクトルにする
      • Vec2Mat関数
        • パラメータベクトルを入力する
        • ユーザーベクトル、アイテムベクトル、ユーザーバイアス、アイテムバイアス、グルーバルバイアスを返す

      test.sh

      テストのバッチ処理

      test.py

      python ../bin/test.py –test data/test.ascii –completed completed_ratings.ascii

      • コマンドライン引数たち
        • test:テスト用の評価データを指定する(ASCII formatの行列)
        • completed:評価を埋めたい行列のファイル名を指定

      MSEやらMAEの結果を返す。

      所感

      まず論文の内容ですが、大体のビジネスデータはRCTな状況で生み出されたものではないので、偏って観測されるのは当然ですが、その結果としてレコメンドのアルゴリズムの性能が落ちてしまうということが論文に記されていました。性能を落とさないためにも、傾向スコアを用いた重み付けによる機械学習が大事に思いました。ただ、傾向スコアの推定自体の精度も大事に思われるので、銀の弾丸ではないですが、バイアスから抜け出るヒントをいただけたという気持ちです。
      そして、思ったよりもソースコードが長いと思ったのと、普段あまり使わないNumpyの関数を知ることができたのもよかったです。
      理論の理解だけでなく、それを実現するためのソースコードを眺めるのも大事ですね。今後も論文をただ読むだけでなくソースコードの海に飛び込んでみようと思います。

      参考リンク

      numpy.reciprocal
      maskedarray.generic
      numpy.ma.getmask
      numpy.clip
      scipy.sparse.linalg.svds
      numpy.ma.filled
      scipy.optimize.minimize

      警察庁オープンデータの前処理と死亡事故発生予測のための機械学習について

      はじめに

      先日、近所の幹線道路の信号付き横断歩道を横断しようとした際に、2メートルほど先で回避不能な速度で車が赤信号を無視して横断歩道を突っ切きるという非常に恐ろしいイベントに遭遇しました。
      そこで、私は「このイベント、何回かあったら死亡事故が起きるぞ」と思いました。警察署に近隣道路の不満について電話をしてみたのですが、「警察もちゃんと考えて取り締まっていたり対策してますので」と言われ、何の成果も獲れない電話となりました。
      そのようなモヤモヤの中、私は民間でできることは「客観的なデータでもって、エリア、曜日、天候、時間帯ごとの、死亡事故のリスクを見積もり、それを公開して注意喚起していくこと」なのではないかと思うに至りました。
      よって、警察庁が公開している交通事故のオープンデータについて、その前処理と機械学習によるエリアの死亡事故の発生予測などについて記していきます。

      前処理のためのデータやコードはこちらのGitHubにあります。
      https://github.com/KamonohashiPerry/traffic_accident_analysis
      スターを10個以上いただけて、データ作って良かったなと思いました。

      目次

      ・データについて
      ・先行研究について
      ・前処理について
      ・EDAからわかること
      ・機械学習
      ・さいごに

      データについて

      2019年と2020年の交通事故に関するデータが警察庁よりオープンデータとして公開されています。
      オープンデータ 2020年(令和2年)
      オープンデータ 2019年(平成31年/令和元年)

      どのようなデータかというと、
      それぞれ2019年と2020年の間に発生した全国の事故について、発生した状況(時、場所、天候)やその結果に関するデータからなり、項目の数としては58個とオープンデータとしてはかなり豊富な情報量となっています。

      データは本票、補充票、高速票の3つからなるのですが、今回は本票だけを用います。
      高速道路の精緻な分析をしようと思うと、高速票を繋ぐ必要がありますが、私の目的は一般道にあるので、繋がないものとします。

      先行研究について

      事故の予測に関する先行研究

      交通事故の分析に関する研究は以下のものがあり、参考にしました。
      死亡事故を予測するという問題設定として、その特徴量としては場所、時間帯、曜日、場所かつ時間、場所かつ曜日かつ時間、天候、季節、風速・風向き、車線の数、歩道の有無、制限速度などを用いていることがわかりました。
      そして、データをクラスタリングするためにDBSCANを用いたり、不均衡データであることから、アンダーサンプリングを行ったりしているようです。
      最後に、アルゴリズムはSVMやロジスティック回帰、深層学習と色々と使われているようです。

      ・Live Prediction of Traffic Accident Risks Using Machine Learning and Google Maps

      ・Data-Driven Urban TrafficAccidentAnalysis and Prediction Using
      Logit and Machine Learning-Based Pattern Recognition Models

      ・A Deep Learning Approach for Detecting Traffic
      Accidents from Social Media Data

      ・A BASIC STUDY ON TRAFFIC ACCIDENT DATA ANALYSIS USING
      SUPPORT VECTOR MACHINE

      ・Predicting Crash Injury Severity with Machine Learning Algorithm Synergized with Clustering Technique: A Promising Protocol

      ・Comparison Analysis of Tree Based and Ensembled Regression Algorithms for Traffic
      Accident Severity Prediction

      その他

      ・Taxi Demand Prediction System

      ・2019年04月号トピックス 警察庁のオープンデータを活用した独自AIによる犯罪発生予測

      前処理について

      ソースコードに関しては、GitHubに上げておりますので、
      .pyなら
      https://github.com/KamonohashiPerry/traffic_accident_analysis/blob/main/src/preprocess.py
      https://github.com/KamonohashiPerry/traffic_accident_analysis/blob/main/src/preprocess_second.py

      .ipynbなら
      https://github.com/KamonohashiPerry/traffic_accident_analysis/blob/main/Traffic_Accident_Analysis.ipynb
      を参照ください。

      基本方針

      ・天候、時間帯、曜日、平日、道路の形状、スピード制限など、事故の結果(死亡の有無)を明らかに予測できそうなもの以外を特徴量にします。
      ・メッシュ単位での過去の事故に関する情報に関する特徴量の作成(学習を行う時点よりも過去の時点のデータのみ利用)

      詳細

      ・事故の発生日時のdatetime化(列で年・月・日・時・分が分かれているため)
      ・マスタ情報(PDF)をもとにマスタのIDを名前に変換
      ・緯度経度のデータについて、度分秒から度への変換を行い、3次メッシュ(1km四方)のデータを作成
      ・メッシュ単位での特徴量として、過去の事故発生件数、死亡数などを集計
      ・メッシュ単位での特徴量として、過去に発生した事故に関するもろもろのデータの集計(そのメッシュで事故を起こした平均年齢や事故が発生してきた時間帯など)
      ・もろもろの変数のダミー変数化

      EDAからわかること

      EDAに関しては.ipynbのみで行っております。
      https://github.com/KamonohashiPerry/traffic_accident_analysis/blob/main/Traffic_Accident_Analysis.ipynb

      私がよく分析で使うのは、データの該当件数とカテゴリごとの率の可視化なのですが、以下の図の見方としては、青の棒グラフが各カテゴリの件数、赤の折れ線グラフが死亡率となっています。

      都道府県


      福井県、鳥取県、秋田県、島根県、岩手県などは死亡率が高そうです。

      道路種別


      農道(815件)や林道(88件)で起きる事故非常に死亡率が高くなるようです。

      時間帯


      夜間や明け方は死亡率が高くなるようです。

      天候


      霧の天候(294件)では死亡率が高くなるようです。

      人口密集地かどうか


      市街地ではないところでは死亡率が高くなるようです。

      道路の形状


      踏切-第一種(254件)はかなり死亡率が高くなるようです。カーブも死亡率が高くなります。そういえば実家の近くにも魔のカーブと呼ばれるところはありますし、事故も起きていました。

      信号機のタイプ


      点滅-3灯式(2566件)や点灯-押ボタン式(7703件)は死亡率が高いようです。

      道路の幅


      大きな交差点では死亡率が高い傾向にあります。単路に関しては一様な傾向ではないですが、小さい方が死亡率が高そうです。

      道路の区切り


      道路の区切りがペイントだけのケースは、中央分離帯がある場合よりも死亡率が高い傾向にあります。あと、中央線がポストコーン(チンアナゴみたいなやつ)だと死亡率が上がるようです。

      歩道との区別


      道路について歩道との区分がない場合に死亡率が高くなるようです。

      速度制限


      速度域が高くなるにつれ、死亡率が高くなるようです。あと、速度規制がされていないところも高くなっています。

      曜日


      土日の死亡率が高い。

      祝日・その前日


      祝日とその前日の死亡率は高い傾向にある。

      以上のことから、得られた考察としては、
      ・土日や祝前日の道路はいつもより危ない
      ・夜間や明け方の道路は危ない
      ・制限速度の高い道路は危ない
      ・大きな交差点は危ない
      ・点滅信号は危ない
      ・カーブは危ない
      ・霧は危ない
      でした。普段、出歩く際に意識しておくといいと思います。

      機械学習

      教師データを事故発生からの死亡有無(1or0)、特徴量を先行研究を参考にオープンデータから作れるものとして、
      基本的には、LightGBMでの学習、ハイパーパラメータ探索、モデルの訓練(メッシュ番号でグループ化したクロスバリデーション)、テストデータ(学習は2020年11月まで、テストは2020年12月以降としている)での予測、日本地図への可視化を行っています。

      ソースコードはGitHubに上げてあるので、ここでは記しません。

      .pyなら(学習のみ)
      https://github.com/KamonohashiPerry/traffic_accident_analysis/blob/main/src/train_model.py

      .ipynbなら(学習だけでなく、予測と日本地図への可視化もしている)
      https://github.com/KamonohashiPerry/traffic_accident_analysis/blob/main/Traffic_Accident_Analysis.ipynb

      10-foldのCVをメッシュ番号でグループ化して学習させた際のAUCです。高い部類に入りますが、今回は不均衡データなので、抜群に当たっている感じではないです。


      事故の死亡率は、0.9%なので、この予測の場合、2.2%が死亡すると当てれているということになります。また、予測から、全体の72%の死亡事故を当てているという結果です。
      この性能に関しては今後、もっと高めていく余地はいくらでもあると思います。

      こちらは、テストデータでの予測スコアの階級値(青い棒グラフ)と実際の死亡率(赤い線グラフ)を示したものです。スコアが高いものは信じてもいいかなぁと思いました。

      特徴量重要度の上位10件は以下の通りです。

      時間帯とか、防護策とか、信号機のタイプとか、市街地かどうかなどが予測に役立っているようです。

      死亡事故発生を予測した確率を日本地図の関東エリアにプロットしたものが以下の図になります。

      市街地のほうが死亡事故が起きやすいように見えますね。

      東京都だけに絞ってみましたが、危険なエリアは都心に点在はしていますが、郊外のほうが死亡率が高そうです。

      さいごに

      交通事故にあいかけて、その怒りの感情を警察庁のデータにぶつけてみましたが、死亡事故が起きやすい条件などがある程度見えてきたと思いました。もちろん、なんとなく思っていた傾向もあったのですが、数字でハッキリと出せるのは良いですね。今後、旅行などをする際に、確率の高いエリアを警戒して行動するようにしたいです。
      そして、地図への可視化は普段の仕事でほとんど行わないのですが、こうしてデータに触れて可視化の練習ができたのも有意義に思いました。
      この警察庁のデータは分析するまでに工数がかかるデータとも言えるので、この記事をとっかかりとして、オープンデータの分析に挑戦して安全な生活を送る上での知見をシェアしていけると良いな、というか民間としてはこれくらいしかできないなと思っています。

      参考情報

      ・[第3版]Python機械学習プログラミング 達人データサイエンティストによる理論と実践 (impress top gear)
      ・Pythonでプロットした地図を出力する
      ・Pythonで度と度分秒を相互に変換する