マルウェア解析できるデータサイエンティストblog

マルウェアのリバースエンジニアリング技術を持つデータサイエンティストとして、サイバーセキュリティとデータ分析/機械学習に関する情報を発信します。

nteractによってコード1行でデータをインタラクティブに可視化

バイオリンプロット
バイオリンプロット

nteractというデータ可視化ツールを使って、実際にTitanicのデータを描画してみました。

コードを1行だけで、Jupyter notebookの機能にインタラクティブなデータ可視化が追加されるため便利に使えそうな所感です。

インストール方法、利用時に感じた便利さと、注意点も含めて記事を書いていきます😃

環境

  • Windows10
  • Miniconda


インストール

① Anaconda Prompt (Miniconda3)を開きます。

Miniconda prompt
Miniconda prompt


② 以下のコマンドを実行してnteractをインストールします。

conda install -c conda-forge nteract_on_jupyter


③ 以下のコマンドを実行してnteractを起動します。

jupyter nteract

④ ブラウザでnteractが立ち上がるので、Start a new notebookにてNotebookを作成します。

フォルダ選択画面
フォルダ選択画面


実際に使ってみる

定番のTitanicのデータセットをつかって、データをインタラクティブに表示してみましょう。

以下にサンプルPythonコードを置きます。 pd.options.display.html.table_schema = Trueを入れないとインタラクティブな表示にはならないので注意です。

import pandas as pd


pd.options.display.html.table_schema = True
df = pd.read_csv('./train.csv')

上記Pythonスクリプトを実行してみると、以下のGif動画で示した通り、セル幅を変更したりカラムを昇順・降順に並び替えたりできます。

インタラクティブなテーブル表示
インタラクティブなテーブル表示

Show Filtersボタンから各カラムにフィルタをかけることもできます。PandasのDataFrameをExcelのように扱えるので便利ですね。

さらに、テーブル右のツールバーから表示形式を選択することで各種のグラフでデータを表示することもできます。

インタラクティブなテーブル表示
インタラクティブなグラフ表示

上記Gif動画の様に、MetirxにSurvivedを選択してバイオリンプロットみると、男性より女性の方が生存者の割合が多いことが瞬時に判断できますね。


nteract利用の注意点

注意点1: サイズの大きいデータでは可視化に時間がかかる

サイズの大きいデータに時間がかかるのは当たり前のことなんですけどね。

私の環境では、29.4MBのCSVを表示するのに1分16秒、テーブル表示からバイオリンプロット表示に切り替えるのに26秒が必要でした。

各種ボタンのクリック1つで簡単にインタラクティブにテーブルやグラフの表示方法を変更できるため、ギャップで表示までの待ち時間が長く感じるということだと思っています。


注意点2: テーブルやグラフ上で表示されるカラム数・行数は、通常のPandas DataFrameの表示上限に依存する

こちらも当たり前のことではあるんですけど、インタラクティブな可視化にばかり目が行っているとしばらく気づかないこともあります(私のことです😂)

以下のコードでカラム数および行数の表示上限を適切な値に設定してあげる必要があるということですね。

pd.set_option('display.max_rows', None)
pd.set_option('display.max_columns', None)


注意点3: Notebookを開いた際に画面上部のツールバーのみが表示されてセルが表示されないことがある

nteractを実行しているコマンドプロンプトをマウス/キーボード操作することで解消されました。

ただし、この記事を書くために再現試験を行ったところ事象が再発しないため、皆さんの環境でも発生し得るのか私の環境依存なのかが分からない状況です...


最後に

操作が簡単な分だけギャップとして表示変更の待ち時間を長く感じてしまいますが、データの性質を理解するのに便利なことは間違いないので継続して使っていこうと思います。

今回の記事はここまで。Kazuki Igetaでした😃

機械学習で必要となる応用数学の基礎

今回は機械学習・データサイエンスに必要な応用数学について基礎的で重要な部分のまとめを行ったので紹介していきます😃

E資格の認定プログラムであるラビットチャレンジの講義や、プログラミングのための線形代数、現場ですぐ使える時系列データ分析、言語処理のための機械学習入門といった書籍の内容を解釈に以下にまとめていきます。

目次の中で★のついた項目は、私の中で特に重要な学びを得られた部分なので重点的に説明を行います。

線形代数

★固有値・固有ベクトル

以下の式(1)を満たす数λとベクトルxを、それぞれ固有値固有ベクトルと呼びます。

\displaystyle{
A\boldsymbol{x} = \lambda \boldsymbol{x} \ \ \ where \ \boldsymbol{x} \neq \boldsymbol{0} \tag{1}
}


具体例として、以下の行列Aの固有値および固有ベクトルを求めてみましょう。

具体例1: 固有値および固有ベクトルの算出

\displaystyle{
A = \begin{pmatrix}1&4\\2&3\end{pmatrix} \\
}

まずは、式(1)を変形して固有値を求めます。n×nの正方行列の固有値はn個ありますが、同じ値の重複(重解)があり得るため実際にはn種類の値を取ります。

\displaystyle{
(A - \lambda) \boldsymbol{x} = \boldsymbol{0} \tag{2}\\
}
\displaystyle{
\begin{pmatrix}1-\lambda&4\\2&3-\lambda\end{pmatrix} \begin{pmatrix}x_1\\x_2\end{pmatrix} = \boldsymbol{0} \\
\begin{vmatrix}1-\lambda&4\\2&3-\lambda\end{vmatrix} = \boldsymbol{0} \ \ \because 式(1)より \, \boldsymbol{x} \neq \boldsymbol{0} \\
(1 - \lambda)(3 - \lambda) - 8 \\
(\lambda - 5)(\lambda +1) = \boldsymbol{0} \\
\therefore \lambda = -1, 5
}


次に、求めた固有値から固有ベクトルを求めます。

\displaystyle{
\lambda = -1 \ のとき\\
\begin{pmatrix}1&4\\2&3\end{pmatrix}
\begin{pmatrix}x_1\\x_2\end{pmatrix}
=
-1 \begin{pmatrix}x_1\\x_2\end{pmatrix} \\
x_1 = -2 x_2 \\
\boldsymbol{x} = \begin{pmatrix}-2\\1\end{pmatrix} \\
\therefore \, \lambda = -1 のとき \, \boldsymbol{x} = \begin{pmatrix}-2\\1\end{pmatrix} \, の定数倍

}


\displaystyle{
\lambda = 5 \ のとき\\
\begin{pmatrix}1&4\\2&3\end{pmatrix}
\begin{pmatrix}x_1\\x_2\end{pmatrix}
=
5 \begin{pmatrix}x_1\\x_2\end{pmatrix} \\
x_1 = x_2 \\
\boldsymbol{x} = \begin{pmatrix}1\\1\end{pmatrix} \\
\therefore \, \lambda = 5 のとき \, \boldsymbol{x} = \begin{pmatrix}1\\1\end{pmatrix} \, の定数倍
}


幾何学的な意味から固有値および固有ベクトルを説明すると、行列Aを固有ベクトルに掛けても伸縮が起きるだけでその方向は変化が起きません。この伸縮率が固有値となります。

https://kaorahi.bitbucket.io/anim/anim4.gif

上記画像はプログラミングのための線形代数・確率統計 非公式サポートページより

次に、固有値および固有ベクトルがどんな場面で利用されているかについて説明していきます。

固有値および固有ベクトルが利用される場面

固有値および固有ベクトルは、行列の対角化を行う際に用いられます。そして対角化は、自己回帰モデルにてよく用いられています。自己回帰モデルとは、以下のようなモデルを意味します。

  • 離散時間の例: 今日のξ(t)は、昨日のξ(t-1)、一昨日のξ(t-2)、一昨昨日のξ(t-3)と、今日のu(t)から次のように決まる。
\displaystyle{
\xi(t) = -0.5 \xi(t-1) +0.34 \xi(t-2) + 0.08\xi(t-3) + 2u(t) \tag{3} \\
初期条件 \, \xi(0) = 0.78, \, \xi(-1) = 0.8, \, \xi(-2) = 1.5
}


\displaystyle{
\boldsymbol{x}(t) = \begin{pmatrix}\xi(t)\\\xi(t-1)\\\xi(t-2)\end{pmatrix} \ とおき、u(t) = 0とすれば、以下の様に式(3)を行列で表現することができます。\\
}
\displaystyle{
\boldsymbol{x}(t) = \begin{pmatrix}-0.5&0.34&0.08\\1&0&0\\0&1&0\end{pmatrix} \boldsymbol{x}(t-1), \ \boldsymbol{x}(0) = \begin{pmatrix}0.78\\0.8\\1.5\end{pmatrix} \tag{4}\\
}


これを一般化すると、以下の式(5)が得られます。

\displaystyle{
\boldsymbol{x}(t) = A \boldsymbol{x}(t-1) \tag{5}
}


Aが対角行列である場合には、以下の様にAのt乗とx(0)で表すことができます。このとき、a, b, cいずれかの絶対値が1を超える場合にはt→∞ではx(t)が吹っ飛んで発散してしまうという判断を下すことができます。

\displaystyle{
\boldsymbol{x}(t) = \begin{pmatrix}a&0&0\\0&b&0\\0&0&c\end{pmatrix} ^ t \boldsymbol{x}(0) \tag{6}
}

一方、Aが対角行列でない場合には、上記のように単純にt→∞のときにx(t)が発散するか判断することが出来ません。これを可能とするために行われるのが行列の対角化です。以下の具体例2では対角化の手法の1つである固有値分解を使った対角化を説明していきます。

具体例2: 固有値および固有ベクトルを使った固有値分解

ここから、式(4)の行列について、固有値および固有ベクトルを用いて行列を固有値分解してみようと思います。固有値分解には以下の式(7)*1を用います。

\displaystyle{
\boldsymbol{x}(t) = P \Lambda^t P^{-1} \boldsymbol{x}(0) \tag{7}
}

まずは固有値および固有ベクトルを求めます。

\displaystyle{
A = \begin{pmatrix}-0.5&0.34&0.08\\1&0&0\\0&1&0\end{pmatrix} \\

\lambda = -0.8 \, のとき \, 固有ベクトル \, \boldsymbol{p} = \begin{pmatrix}0.447\\-0.559\\0.698\end{pmatrix} \\
\lambda = 0.5 \, のとき \, 固有ベクトル \, \boldsymbol{p} = \begin{pmatrix}0.218\\0.436\\0.873\end{pmatrix} \\
\lambda = -0.2 \, のとき \, 固有ベクトル \, \boldsymbol{p} = \begin{pmatrix}-0.039\\0.196\\-0.980\end{pmatrix} \\
}
\displaystyle{
P = \begin{pmatrix}0.44703900498169&0.21821789023599&-0.039193090083481\\-0.55879875622711&0.43643578047199&0.1959654504174\\0.69849844528389&0.87287156094397&-0.97982725208702\end{pmatrix} \\
P^{-1} = \begin{pmatrix}1.8354389916075&-0.5506316974822&-0.18354389916075\\1.2589493667461&1.2589493667461&0.20143189867937\\2.4299715851758&0.72899147555276&-0.97198863407034\end{pmatrix} \\
 \Lambda = \begin{pmatrix}-0.8&0&0\\0&0.5&0\\0&0&-0.2\end{pmatrix} \ \
}
\displaystyle{
\boldsymbol{x}(t) =
\begin{pmatrix}0.44703900498169&0.21821789023599&-0.039193090083481\\-0.55879875622711&0.43643578047199&0.1959654504174\\0.69849844528389&0.87287156094397&-0.97982725208702\end{pmatrix}
\begin{pmatrix}-0.8&0&0\\0&0.5&0\\0&0&-0.2\end{pmatrix} ^ t
\begin{pmatrix}1.8354389916075&-0.5506316974822&-0.18354389916075\\1.2589493667461&1.2589493667461&0.20143189867937\\2.4299715851758&0.72899147555276&-0.97198863407034\end{pmatrix}
\boldsymbol{x}(0)
\tag{8}
}


桁数が大きくて見づらくなってしまいましたが、Pythonなどで計算するときは気にする必要がないので、ここでも気にせずにいきます。さて、以上の式(8)にて、離散時間の例で作成した自己回帰モデルをtの値毎に計算できるようになりました。

t乗が行列Λにのみ掛かっていることから、対角行列の場合、t→∞のときにx(t)が発散するかどうかはΛの要素の絶対値が1を超えるかどうかで判断されるということが分かるかと思います。今回の例でいうと絶対値が1を超える要素がないため、発散しないという結論が得られます。これは、期待値E[x(t)]tによらず一定な、定常性を持つ時系列ということもできます。


特異値分解

固有値分解の便利さは前述したとおりですが、では、正方行列以外は対角化することはできないのでしょうか?正方行列でない行列を固有値分解するための手法が以下の特異値分解です。

\displaystyle{
M \boldsymbol{v} = \sigma \boldsymbol{u} \tag{9}
}
\displaystyle{
M^\mathrm{T} \boldsymbol{u} = \sigma \boldsymbol{v} \tag{10}
}
\displaystyle{
式(9), (10)が成立する単位ベクトル \, \boldsymbol{v}, \, \boldsymbol{u} \,が存在するとき、 \\
M = USV^\mathrm{T} \tag{11}
}

※ベクトルuおよびvを単位ベクトルとすることで、それぞれのベクトルの集まりである行列UおよびVが直行行列となるため、大きさ1となる単位ベクトルという条件が置かれています。

\displaystyle{
M V = US \ \because \, 式(9) \\
M^\mathrm{T} U = V S^\mathrm{T} \ \because \, 式(10) \\
where \ V, \, U, \, S \,はそれぞれ\boldsymbol{v}, \, \boldsymbol{u}, \, \boldsymbol{\sigma} \,を列に集めた行列 \\
}
\displaystyle{
M = U S V^\mathrm{T} \\
M^\mathrm{T} = V S^\mathrm{T} U^\mathrm{T} \\
}
\displaystyle{
M M^\mathrm{T} = U S V^\mathrm{T} V S^\mathrm{T} U^\mathrm{T} = U S S^\mathrm{T} U^\mathrm{T} \tag{12}
}


つまり、式(12)のように、長方行列Mとその転置MTの積を固有値分解すれば、その左特異ベクトルUと特異値の2乗SSTが求められるということです。

具体例3: 簡単な特異値分解

\displaystyle{
M = \begin{pmatrix}1&2&3\\3&2&1\end{pmatrix} \\
M M^\mathrm{T} = \begin{pmatrix}1&2&3\\3&2&1\end{pmatrix} \begin{pmatrix}1&3\\2&2\\3&1\end{pmatrix} = \begin{pmatrix}14&10\\14&10\end{pmatrix} \\
M M^\mathrm{T} \, を固有値分解して \\
M M^\mathrm{T} = \begin{pmatrix}14&10\\14&10\end{pmatrix} =
\begin{pmatrix}1/\sqrt{3}&1/\sqrt{2}&1/\sqrt{6}\\1/\sqrt{3}&0&-2/\sqrt{6}\\1/\sqrt{3}&-1/\sqrt{2}&1/\sqrt{6}\end{pmatrix}
\begin{pmatrix}24&0&0\\0&4&0\\0&0&0\end{pmatrix}
\begin{pmatrix}1/\sqrt{3}&1/\sqrt{2}&1/\sqrt{6}\\1/\sqrt{3}&0&-2/\sqrt{6}\\1/\sqrt{3}&-1/\sqrt{2}&1/\sqrt{6}\end{pmatrix} ^ {-1} \\
M = \begin{pmatrix}1&2&3\\3&2&1\end{pmatrix} =
\begin{pmatrix}1/\sqrt{2}&-1/\sqrt{2}\\1/\sqrt{2}&1/\sqrt{2}\end{pmatrix}
\begin{pmatrix}2\sqrt{6}&0&0\\0&2&0\end{pmatrix}
\begin{pmatrix}1/\sqrt{3}&1/\sqrt{3}&1/\sqrt{3}\\1/\sqrt{2}&0&-1/\sqrt{2}\\1/\sqrt{6}&-2/\sqrt{6}&1/\sqrt{6}\end{pmatrix}
}


参考文献

上述の線形代数の内容は、以下の書籍を参考としています。

  • プログラミングのための線形代数
    • 「行列は写像だ」という本書決めフレーズが示すように、線形代数というものが意味の分からないただの計算としてとらえていた人に対して、実際には何のために用いられるものなのかをイメージとして持たせることに注力してくれている良書です。
  • 現場ですぐ使える時系列データ分析
    • 線形代数の考え方なしで、事前知識をほとんど必要としないシンプルかつ簡単な形で時系列データ分析を説明してくれる優れた入門書です。


確率・統計

確率には2つの異なる考え方が存在しています。

頻度確立 ベイズ確率
概要 試行を繰り返すことで、結果は現象ごとに存在する真の確率に近づく。 いま手元にあるデータが、どのようなパラメータに基づく母集団(信念の度合い)から得られたのか推定する。
パラメータ 確率変数 データ
定数 データ 確率変数

ベイズ確率とは、「あなたがインフルエンザに罹患している確率は、40%です」のような信念の度合いには真の確率というものは存在せず、思考を繰り返すこともできないようなものを、いま手元にあるデータから推定することを意味しています。


条件付き確率

ある事象が与えられたもとで得られる確率のことを、条件付確率と呼びます。

例: 雨が降っている条件下で交通事故にあう確率

\displaystyle{
 P(Y=y | X=x) = \frac{P(Y=y, \,X=x)} {P(X=x)} \tag{13}
}


以下の様に、確率変数を省略し実現値のみで記載することも実際には頻繁にあります。

\displaystyle{
 P(y | x) = \frac{P(y, \,x)} {P(x)}
}


条件付確率は、同時確立を条件となる確率で割ってあげたものになっています。そのため以下の式(14)の通り、事象が互いに独立であれば、条件は確立に対して影響を与えません。

\displaystyle{
 P(y | x) = \frac{P(y, \,x)} {P(x)}
= \frac{P(y)P(x)} {P(x)} = P(y) \tag{14}
}


ベイズの定理

ベイズの定理は、事前確率をもとに事後確率を計算することが出来るという非常に便利な定理です。

\displaystyle{
 P(y | x) = \frac{P(x|y)P(y)} {P(x)} \ \ \ where \ P(x) > 0 \tag{15}
}


P(y)は、事象xが起きる前の事象yの確率です。(事前確率) P(y|x)は、事象xが起きた後での、の事象yの確率です。(事後確率)


ベイズの定理により「飴玉をもらった子どもたちが笑顔になる確率」をもとに、「笑顔の子どもたちが飴玉をもらった確率」を求めるという具体例を以下に示します。

具体例4: ベイズの定理による確率の算出

\displaystyle{
 P(飴玉) = 1/4, \, P(笑顔|飴玉) = 1/2, \, P(笑顔) = 1/3 \\

\begin{eqnarray}
P(飴玉|笑顔) &=& \frac{P(笑顔|飴玉)P(飴玉)} {P(笑顔)} \\
&=& 3/8 \\
\end{eqnarray}

}

期待値・分散

期待値

確率変数Xが離散型の場合
\displaystyle{
E[X] = \sum_{i=1}^{n} {P(x) f(x)} \tag{16}
}
確率変数Xが連続型の場合
\displaystyle{
E[X] = \int_{-\infty}^{\infty} {f(x) \, dx} \tag{17}
}

分散

確率変数Xが離散値の場合
\displaystyle{
V[X] = \sum_{i=1}^{n} {(x_i - \mu)^2 p_i} \tag{18}
}
確率変数Xが連続値の場合
\displaystyle{
V[X] = \int_{-\infty}^{\infty} {(x - \mu)^2 f(x) \, dx} \tag{19}
}

共分散

確率変数Xが離散値の場合
\displaystyle{
Cov[X, \, Y] = \sum_{i=1}^n {(x_i- \overline{x})(y_i - \overline{y}) p_{XY}(x, \, y)} \tag{20}
}
確率変数Xが連続値の場合
\displaystyle{
Cov[X, \, Y] = \int_{-\infty}^{\infty} \int_{-\infty}^{\infty} {(x - \mu_x)(y - \mu_y) f_{XY}(x, \, y) \, dxdy} \tag{21}
}


確率分布

確率分布とは、確率変数が取る値とその値を取る確率の対応の様子のことです。

ベルヌーイ分布

ベルヌーイ分布は、コインの裏か表のように二者択一の確率変数の分布です。ベルヌーイ分布の確率密度関数、期待値、分散はそれぞれ以下の様になります。

確率密度関数
\displaystyle{
f(x)=p^x(1-p)^{1-x} \tag{22}
}
期待値
\displaystyle{
E[X] = p \tag{23}
}
分散
\displaystyle{
V[X] = p(1 - p) \tag{24}
}


なお、確率分布の期待値や分散といった特性は、確率母関数によって確率密度関数から導出することができます。統計検定準1級以上の試験範囲に含まれる内容です。

確率母関数による確率分布の特性の導出は以下の記事で説明を行っているので、興味のある方はそちらも読んでみてください。

kazukiigeta.com


情報理論

情報理論とは、情報を伝送するための理論的な基盤に関する学問のことです。


★自己情報量

以下の式(25)に自己情報量の定義を示します。自己情報量の単位は、対数の底が2のときbit、低が自然数eのときnatです。コンピュータの世界では2進数が用いられるため、bitの方が使われる場面が多いそうです。以降ではbitを用いて説明を行っていきます。

\displaystyle{
I(x) = -\log_2{\left( P(x) \right)} \tag{25}
}


自己情報量とは、ある情報を表すことが出来るON/OFFの2通りの状態を持つスイッチの最小の数というように考えることが出来ます。例えば、1/2の確率で発生する事象を表すためにはスイッチが1つが必要となります。1/4の確率で発生する事象であればスイッチ2つ、1/8の確率であればスイッチ3つ、となります。つまり、確率が低い事象ほどその事象を表すために必要な情報量(スイッチの数)が増えることになります。

-log(P(x))のグラフ
-log(P(x))のグラフ


また、2つの情報が得られたとき、情報量はその2つの情報の足し算で表現することが出来ます。

具体例5: サイコロの出た目における情報量

サイコロは1~6までの6通りの目をそれぞれ1/6の確率で出すものとします。一般的な理想のサイコロですね。このサイコロを1回振った時の情報量を、以下の2つの情報をもとに算出してみます。

  • 情報1: 出た目の数は4以上であった。

    • 取り得る目は、4, 5, 6の3通りで、その確率P1は1/2
  • 情報2: 出た目の数は偶数であった。

    • 取り得る目は、2, 4, 6の3通りで、その確率P2は1/2

情報1と情報2の同時確立Pを求めると以下の様に1/4が得られます。

\displaystyle{
P_1 = \frac{1}{2} \\
P_2 = \frac{1}{2} \\
同時確立 \, P = P_1 \times P_2 = 1/4
}


また、情報1と情報2を合わせた自己情報量Iを求めると以下の様に2が得られます。

\displaystyle{
I_1 = -\log_2{\left( \frac{1}{2} \right)} \\
I_2 = -\log_2{\left( \frac{1}{2} \right)} \\
I = I_1 + I_2 = -\log_2{\left( \frac{1}{2} \right)} + \left( -\log_2{\left( \frac{1}{2} \right)} \right) = 1 + 1 = 2
}


上記の自己情報量Iは、先ほど求めた同時確立Pから求めることもできます。

\displaystyle{
I = -\log_2{\left( P \right)} = -\log_2{\left( P_1 \times P_2 \right)} = -\left( \log_2{\left( P_1 \right)} + \log_2{\left( P_2 \right)} \right) = 2
}


シャノンエントロピー

シャノンエントロピーは、情報エントロピーとも呼ばれており確率あるいは確率分布/経験分布の「乱雑さ」を測るための尺度です。乱雑な状態とは、確率変数がどの値を取るか言い当てにくい状態を意味します。言い換えれば、確率分布が与えられたとき、その各値を取る確率が互いに大きく異なるとき乱雑さは小さく、シャノンエントロピーも小さいということになります。

以下に定義を記載します。自己情報量の期待値として定義されています。

\displaystyle{
H(x) = E[I(x)] = -E[\log_2{\left( P(x) \right)}] = -\sum_{i=0}^{n}{\left( P(x_i) \log{\left( P(x_i) \right)} \right)} \tag{26}
}


★KLダイバージェンス

KLダイバージェンスは、カルバック・ライブラー情報量、KL情報量と呼ばれることもあります。同じ事象/確率変数における2つの確率分布P, Qに対して、それらの異なり具合を測るものです。

事前情報の確率Q(x)と、実験/観測によって新しく得られた情報の確率P(x)との珍しさの差や、新しく得られた情報の量を知ることができます。

例えば、サイコロの目という同じ確率変数においては、一般的な理想的なサイコロは全ての目が1/6の確率Q(x)で出る一様分布に従うという事前情報を持っており、手元のサイコロで実験を行ったところ得られた確率P(x)との差分を見るという場合などに用いられます。

\displaystyle{
D_{KL}(P||Q) = \mathbb{E}_{x \sim P} [ \log_2{\frac{P(x)}{Q(x)}} ] = \mathbb{E}_{x~P} [ \log_2{P(x) - \log_2{Q(x)}} ] \tag{27}
}

KLダイバージェンスは実は、Q(x)の自己情報量からP(x)の自己情報量を差し引いたものをPで平均を取ったものとなっています。

\displaystyle{
I\left( Q(x) \right) - I\left( P(x) \right) = \left( -\log_2{\left( Q(x) \right)} \right) -  \left( -\log_2{\left( P(x) \right)} \right)= \log_2{\frac{P(x)}{Q(x)}}
}


交差エントロピー

KLダイバージェンスは、「Qについての自己情報量をPの分布で平均したもの」から「Pについての自己情報量をPの分布で平均したもの」を差し引いた差分として定義されていました。 一方、交差エントロピーはQについての自己情報量をPの分布で平均したものを表しています。

\displaystyle{
\begin{eqnarray}
H(P, \, Q) &=& H(P) + D_{KL}(P||Q) \\
&=& -\mathbb{E}_{x \sim P} \log_2{Q(x)} \\
&=& -\sum_{x} {P(x) \log_2{Q(x)}} \tag{28}
\end{eqnarray}
}


式(28)は、KLダイバージェンスの定義である式(27)から以下のように変形することで取り出すことが出来ます。

\displaystyle{
\begin{eqnarray}
D_{KL}(P||Q) &=& \sum_x {P(x) \left( -\log_2{\left( Q(x) \right)} \right) -  \left( -\log_2{\left( P(x) \right)} \right)} \ \because 式(27) \\
&=& H(P, \, Q) - H(P)
\end{eqnarray}
}


参考文献

上述の情報理論の内容は以下の書籍を参考にしています。

  • 言語処理のための機械学習入門
    • 数学的な予備知識は多少必要になるものの、応用数学が実際に機械学習の場面でどのように使われているかを理論として理解するための足掛かりとなる良書です。


最後に

今回の記事でまとめた応用数学の基礎を学んだことで、機械学習系の書籍を読んだ際に理解できる内容が増えてきました。良い学びを得られたのだと感じています。

次回は同様の形式で、機械学習の基礎についての記事を公開しますので興味があればそちらもぜひ読んでいただければと思います。

今回の記事はここまで。Kazuki Igetaでした😃

*1:プログラミングのための線形代数 第4章に式の導出が記されています。

データサイエンス界隈は教材が充実している

私は、データドリブンな考え方/課題解決方法をツールとして身に着けることが自分の専門性形成に必ず役立つと考え、サイバーセキュリティの世界*1 からデータサイエンスの世界に足を踏み入れてきました。

そんな中で、応用数学や機械学習などの分野は学習教材や環境が異様に充実していることを感じました。

これは、サイバーセキュリティの様に利益を攻撃者に奪われることから守るという世界から、利益を稼ぐビジネスの主戦場に足を踏み入れたことによるギャップからくるものだろうと思っています。

f:id:kazukiigeta:20210404165350j:plain

サイバーセキュリティの入門書の良書は沢山あります。

サイバーセキュリティ教材の対応レベルが低いということはなく、データサイエンス界隈の教材の対応レベルが幅広いのだろうと思っています。

最近は本屋さんに並ぶサイバーセキュリティの書籍もかなり増えてきており、教材と実戦の間の距離もどんどん縮まってきていることと思います。

それでも私は、サイバーセキュリティの書籍や資格による学習よりは、新しいマルウェアの解析を行うことや、マルウェアの解析妨害テクニックを解読し自分のバイナリとしてそのテクニックを実装してみることで得られる知見の方が自らの技術力向上には役に立つと考えていました。*2

しかし、データサイエンスの様に数学や統計学等の学問との結びつきが強く、積極的に利益を生み出すことを狙う領域では教材の充実度がとても高く、それらを活用することで体系的に学び先駆者を追いかけることで効率よく自身を高めることが出来るはずだと感じています。


今回の記事はここまで。Kazuki Igetaでした😃

*1:binarygenes.com

*2:Kernelやバイナリ等の技術領域にフォーカスした書籍から学ぶのは非常に有効と思います

確率母関数で確率分布の特性が求められる

f:id:kazukiigeta:20210331112939p:plain ベルヌーイ分布や、ポアソン分布、幾何分布などの確率分布の平均分散といった特性を自分で算出することができるのを皆さんご存じですか?

私は、統計検定準1級の勉強中にそのことを知って、ちょっとした感動を覚えました。

今まで何となく暗記していたものを、ちゃんと自分で導出できるようになるのって嬉しいですよね😆

というわけで、今回は確率分布の特性を自分で算出することができる確率母関数についての記事を書きます。


確率母関数 (Probability generating function)とは

確率密度関数から平均分散歪度尖度といった分布の特性を算出することができる関数です。

以下の式で定義されています。

\displaystyle{
G(s) = E[s^{X}] = \sum_{x} s^x f(x)
}

中身は非常に単純で、確率変数sxの期待値になっています。 f(x)は確率密度関数を意味しています。

条件

  • 確率変数Xは整数値を取る。
  • 1を含むある開区間のすべてのsに対して、右辺の和が収束すると仮定する。


確率母関数でベルヌーイ分布の期待値と分散を求めてみる

準備

まずは、確率母関数の式から期待値E[sx]を求める式を導出します。

G(s)の導関数にs=1とおいたとき、G'(1)Xの期待値を表します

\displaystyle{
        G^{'}(s) = E[Xs^{X-1}]
    }
\displaystyle{
        G^{'}(1) = E[X]
    }


G(s)の2次導関数にs=1とおいたとき、G''(1) + G'(1)X2の期待値を表します。

\displaystyle{
        G^{''}(s) = E[X(X-1)s^{X-2}]
    }
\displaystyle{
        G^{''}(1) = E[X(X-1)] = E[X^2] - E[X]
    }


したがって、G''(1)G'(1)を使ってXの分散を求めることが出来ます

\displaystyle{
        G^{''}(1) + G^{'}(1) + \{G^{'}(1)\}^2 = E[X^2] - \{E[X]\}^2 = V[X]
    }


ベルヌーイ分布に適用

ここからは、確率母関数を用いる実例として、ベルヌーイ分布の期待値と分散を求めてみることにします。

確率母関数を利用するためには、分布の確率密度関数が必要となるため、以下に記載します。

ベルヌーイ分布の確率密度関数
\displaystyle{
f(x)=p^x(1-p)^{1-x}
}


ベルヌーイ分布の確率母関数G(s)は、以下の様になります。

\displaystyle{
        G(s) = E[s^{X}] = \sum_{x} s^x f(x) = \sum_{x} s^x p^x(1-p)^{1-x}
    }


ベルヌーイ分布の確率変数Xは0か1の2値のみを取り得る(x∈{0, 1})ため、それぞれ代入して和を取ると以下の様になります。

\displaystyle{
        G(s) = \sum_{x∈\{0, 1\}} s^x p^x(1-p)^{1-x} = 1 - p + sp
    }


以上より、次のように期待値E[X]と分散V[X]を求めることが出来ます。

\displaystyle{
        G^{'}(s) = p
    }
\displaystyle{
        G^{''}(s) = 0
    }
\displaystyle{
        G^{'}(1) = p
    }
\displaystyle{
        G^{''}(1) = 0
    }
\displaystyle{
        E[X] = G^{'}(1) = p
    }
\displaystyle{
        V[X] = G^{''}(1) + G^{'}(1) + \{G^{'}(1)\}^2 = 0 + p - p^2 = p(1 - p)
    }

補足

確率母関数は正の整数にのみ利用可能ですが、モーメント母関数を使えば連続確率変数で対しても同じように分布の特性を求めることができるようになります。

また、確率母関数はk階微分を行うとE[X(X-1)(X-2)...(X-k+1)]のようにk次階乗モーメントを容易に求められるという点でメリットがあるそうです。 一方で、ただ期待値(1次モーメント)と分散(2次モーメント)を算出したいだけなら実はモーメント母関数を使った方が算出が簡単になります。

日本統計学会公式認定 統計検定準1級対応 統計学実践ワークブックには、確率母関数とモーメント母関数さらには特性関数なんてものまで紹介されていました。

https://www.amazon.co.jp/%E6%97%A5%E6%9C%AC%E7%B5%B1%E8%A8%88%E5%AD%A6%E4%BC%9A%E5%85%AC%E5%BC%8F%E8%AA%8D%E5%AE%9A-%E7%B5%B1%E8%A8%88%E6%A4%9C%E5%AE%9A%E6%BA%961%E7%B4%9A%E5%AF%BE%E5%BF%9C-%E7%B5%B1%E8%A8%88%E5%AD%A6%E5%AE%9F%E8%B7%B5%E3%83%AF%E3%83%BC%E3%82%AF%E3%83%96%E3%83%83%E3%82%AF-%E6%97%A5%E6%9C%AC%E7%B5%B1%E8%A8%88%E5%AD%A6%E4%BC%9A/dp/478060852X/ref=asc_df_478060852X/?tag=jpgo-22&linkCode=df0&hvadid=342414341173&hvpos=&hvnetw=g&hvrand=12426885836471452873&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009332&hvtargid=pla-912476174347&psc=1&th=1&psc=1www.amazon.co.jp

最後に

データ分析や機械学習の手法など直接的にすぐ活用できる技術・知識だけでなく、それらを支える数学/統計の基礎知識についても少しずつ学んでいき、データサイエンティストとして成長していけたらと思います。

今回の記事はここまで。Kazuki Igetaでした😃

データサイエンス界隈で覚えておくべき英単語集【2021/04/15更新】

f:id:kazukiigeta:20210321214049p:plain

データサイエンス界隈でグローバルに活躍したいと思ったら、英語で論文も読む必要があるしコミュニケーションをとる必要も出てくるかと思います。

でも、数学用語とかその他テクニカルタームって簡単な意味の単語でも英語になった途端、まったく分からなくなることって多くないですか?

(私は中学生レベルの数学用語でも英語になると、どう表したらよいのか分からなくなることがあります...😂)

そこで、データサイエンス界隈でよく使われているけど自分が知らなかった英単語/フレーズを中心に、この記事にまとめていきます。

こだわりポイントとしては、意味と一緒に発音記号を載せておくことで発音と意味をセットで覚えられるようにしたところです。

まだまだ数は少ないですが、少しずつ更新していきます。

数学系

英語 意味 発音
convex 凸状の kὰnvéks convex function (凸関数)
concave 凸状の kὰnkéɪv concave function (凹関数)
intersection 積集合; 共通部分 ìnṭɚsékʃən the intersection of the sets (2つの集合の積集合)
perpendicular 垂直の p`ɚːpəndíkjʊlɚ perpendicular line (垂線)
orthogonal 直交の ɔːˈθɒɡənəl orthogonal system (直交系)
cartesian デカルトの kɑɚtíːʒən cartesian coordinate (デカルト座標)
euclidean ユークリッドの juːklídiən euclidean distance (ユークリッド距離)
pythagorean ピタゴラスの pɪθ`ægəríːən pythagorean theorem (ピタゴラスの定理)
magnitude 大きさ mˈægnət(j)ùːd the magnitude of the vectors (ベクトルの大きさ)
dimensionality 次元数 dɪˌmɛnʃʌˈnælʌti the curse of dimensionality (次元の呪い)
logarithm 対数 lˈɔːgərìðm logarithm of A to base B (Bを底とする対数A)
spurious 見かけ上の spjˈʊ(ə)riəs spurious correlation (疑似相関)
tangent 接線 tˈændʒənt the slope of the tagent (接線の傾き)
derivative 導関数 dɪrívəṭɪv partial derivative (偏導関数)
contour 輪郭 kάntʊɚ contour plot (等高線図)
convergence 収束 kənvˈɚːdʒəns repeat utill convergence (収束するまで繰り返し)
surjection 全射 sərˈdʒɛk ʃən the function is a surjection (その関数は全射です)
injection 単射 ɪndʒékʃən the composition of two injections is also an injection (二つの単射の組合せもまた一つの単射です)
bijection 全単射 baɪˈdʒɛk ʃən a bijection is an invertible transformation (全単射は可逆な変換です)

この記事を更新しながらデータサイエンス界隈で必要な英語を身に着けていこうと思います。

今回の記事はここまで。Kazuki Igetaでした😃

データサイエンス案件でプロトタイプを素早く作るにはipywidgetsが良さそう

f:id:kazukiigeta:20210320091211p:plain

データサイエンスや機械学習の案件を進めるとき、皆さんはプロトタイプ開発に何を使ってますか?

PyQt5やTkinterなど、選択肢はいろいろあるかと思います。

私は、分析やモデル作成はJupyterlab上をやっているなら、そのままJupyterlab上でお客様に見せられるような簡易的なGUIが素早く作れたら楽だと思いました。

UI/UXを考えるのは、プロトタイプ作成⇔相手との認識合わせを繰り返してからでも良さそうだという考えです。

そこで、Jupyterlab上でインタラクティブな簡易GUIを作成できるipywidgetsを使ってみました。

今回は、ipywidgetsによるJupyterlab上での簡易GUI作成について紹介します😃

簡易GUI

今回のポイントは2点です。

  1. Jupyterlab上の余計なコードを隠す(余計な情報で相手を混乱させないための配慮)

  2. ipywidgetsで成果物の動作を見せる(実際に動かすことでお互いの認識をしっかりと合わせるため)

それぞれのやり方をこれから説明していきます。

1. Jupyterlab上の余計なコードを隠す

Jupyterlabのコードを表示/非表示できるボタン
Jupyterlabのコードを表示/非表示できるボタン

JupyterlabのIssue上で紹介されていた方法を採用して、ボタンの1クリックでコードの表示/非表示を切り替えることが出来ました。

方法は簡単で、以下のコードをエディターの先頭の方のセルに記載するだけです。

from IPython.display import HTML

HTML('''
<script src='//code.jquery.com/jquery-3.6.0.min.js'></script>
<script>
code_show=true; 
function code_toggle() {
 if (code_show){
 $('div.input').hide();
 $('div .jp-CodeCell .jp-Cell-inputWrapper').hide();
 } else {
 $('div.input').show();
 $('div .jp-CodeCell .jp-Cell-inputWrapper').show();
 }
 code_show = !code_show
}
$( document ).ready(code_toggle);
</script>
<form action="javascript:code_toggle()"><input type="submit" value="Code on/off"></form>''')

なお、jqueryのバージョンはオリジナルのv3.3.1から現時点での最新v3.6.0へ書き換えてあります。

v3.5.0でXSSの脆弱性の修正が入っていました。

攻撃者がJupyterlabにアクセスできてしまう状況であればXSSを利用するまでもなく様々な攻撃を実施することができてしまうので、この修正自体が直接このプロトタイプ開発のセキュリティを向上することはなさそうです。

しかし、データ分析の案件では機密データを扱う場面も多くあるので、セキュリティの観点から動作上問題がなければ今回に限らず最新バージョンを使うことを心掛ける必要があると思っています🔐

2. ipywidgetsで成果物の動作を見せる

ipywidgetsによる簡易GUI表示
ipywidgetsによる簡易GUI表示

こんな感じに、Jupyterlab上で素早く簡易的なGUIを作成することができます。

GIF動画で表示したGUIのサンプルコードを以下に置いておきます。

import ipywidgets as widgets
import pandas as pd
import matplotlib.pyplot as plt
from IPython.display import display


class GUI():
    def __init__(self):
        item_layout = widgets.Layout(margin='0 0 50px 0')

        self.output = widgets.Output()
        self.output.clear_output()

        self.fruits_nature = widgets.Output()
        self.fruits_nature.clear_output()

        self.button_run = widgets.Button(description='実行', button_style='danger')

        self.picked_fruits = widgets.SelectMultiple(
                        options=['りんご', 'みかん', 'ぶどう'],
                        value=['ぶどう'],
                        description='果物',
                        disabled=False,
                    ) 

        self.picked_clock = widgets.Dropdown(
                        options=['09:00', '12:00', '15:00'],
                        value='15:00',
                        description='収穫時刻',
                        disabled=False,
                    )

        self.picked_target_date = widgets.DatePicker(
                        description='予測対象日',
                        disabled=False,
                    )
    
        target_widgets = widgets.HBox(
                        [self.picked_clock, self.picked_target_date],
                        layout=item_layout)

        button_widgets = widgets.HBox(
                        [self.button_run],
                        layout=item_layout)

        tab = widgets.Tab([self.output, self.fruits_nature])
        tab.set_title(0, '予測結果')
        tab.set_title(1, '果実特性')
    
        self.dashboard = widgets.VBox([
            target_widgets, tab, button_widgets])


    def _run(self, obj):
        self.output.clear_output()
        self.fruits_nature.clear_output()

        with self.fruits_nature:
            print('収穫時刻:', self.picked_clock.value)
            x = list(range(5))
            y = [1, 5, 2, 7, 4]

            plt.plot(x, y)
            plt.show()
            
        with self.output:
            df_out = pd.DataFrame(
                {
                    'fruit': ['りんご', 'みかん', 'ぶどう'],
                    'clock': [self.picked_clock.value] * 3,
                    'yield': [54, 22, 19],
                }, index=[self.picked_target_date.value]*3)
            display(df_out)


    def display(self):
        display(self.dashboard)
        self.button_run.on_click(self._run)

GUI().display()

ドロップダウンや複数選択、チェックボックスなど、ウィジェットの種類とその呼び出し方はipywidgetsの公式ドキュメントを確認すると良いです。

最後に

ipywidgetsは、他人に分析結果を見せるとき以外にも、自分の分析用に条件をいろいろ変えながらデータを眺めるときにも便利なのでこれからちゃんと使っていこうと思います。

今回の記事はここまで。Kazuki Igetaでした😃