読者です 読者をやめる 読者になる 読者になる

めもめも

このブログに記載の内容は個人の見解であり、必ずしも所属組織の立場、戦略、意見を代表するものではありません。

導関数が自分自身と一致する指数関数が存在することの説明

何の話かというと

qiita.com

の3日目の記事

qiita.com

で、指数関数 f(x) = a^x において、

  f(1)=x=1のときの接線の傾きの値」

となる a をさがすと、それが a = e = 2.71828\cdots(ふなひとはちにわ)になるんだよ!

という解説があって、ほほぉー、と思いつつも・・・

「この関係は x=1 のときだけに成り立つものではありません。f(x)=e^x では、x がどんな値の時にでもこの関係式は成り立ちます。」

という部分の(なぜそうなるのかという)説明がなかったので、なぜ、すべての x で成り立つのかという説明を補足してみます。

微分の定義

先の記事では、数値微分の例で説明されていますが、一般に、点 x からちょことだけ離れた点 x+hh は0.000001ぐらいの小さい数だとしてください)を考えて、グラフ上の2点 (x,\, f(x))(x+h,\, f(x+h)) を結ぶ直線の傾きを考えてみます。

 傾き =\frac{f(x+h)-f(x)}{h}

これは、点 x における関数 f(x) の傾きの近似計算になるわけですが、ここで、h をどんどん 0 に近づけていくと、その極限として、厳密な傾きの値、つまり、微分係数が計算されます。

 f'(x) = \lim_{h\to 0}\frac{f(x+h)-f(x)}{h} ―― (1)

ちなみに、いま、「微分係数」といいましたが、(1) では、x をいろいろな値に変化させて、f'(x)x の関数とみなしています。このように、x における微分係数を表わす関数 f'(x) を「関数 f(x) の導関数」と言います。特定の定数 x における傾きが「微分係数」で、x を変数とみなしたものが「導関数」ということになります。

指数関数の微分

それでは、指数関数 f(x)=a^x の微分(導関数)を先の定義にしたがって計算するとどうなるでしょうか。

まず、傾きを表わす式の分子を計算すると、次のようになります。

 f(x+h) - f(x) = a^{x+h} - a^x = a^x(a^h - 1)

面白いことに、全体が a^x でくくれてしまいます。

したがって、これを (1) に代入すると、次のようになります。

 f'(x) = \lim_{h \to 0} \frac{a^x(a^h-1)}{h} = a^x \times \lim_{h\to 0}\frac{a^h-1}{h} ―― (2)

極限操作 h \to 0 では、h の値をだんだん小さくするという操作を考えているわけですが、a^xh に依存しない値なので、極限操作の外に取り出せてしまう所がポイントです。

そして! (2) に残った極限値  \lim_{h\to 0}\frac{a^h-1}{h} の中身をよーく見ると、どこにも変数 x が入っていません。もともと、点 x をいろいろ変化させた時に、微分係数がどのようにかわるか、という視点があったのですが、この部分は、微分(傾き)を計算する点 x に関係なく、いつも同じ値になります。

ただし、これが具体的にいくらになるのかを一般の a に対して計算するのは簡単ではありません。(分子も分母もどっちも0に近づいていく「不定形」というやつですね。)

とは言え、a の値を具体的に一つ決めてしまえば、数値計算で求めることは可能です。ちょっと、Pythonで試してみましょう。

$ python
>>> h = 0.00000000001
>>> a = 2
>>> (a ** h - 1 ) / h
0.6931566431944702

本当は、h をどんどん0に近づけるのですが、ここでは、h=0.00000000001 という極端に小さい値を用いて近似計算を行いました。

つまり、a=2 の時、f(x)=a^x の導関数は、(近似計算で)次になることがわかりました。

 f'(x) = a^x \times 0.693\cdots= f(x) \times 0.693\cdots

これは面白い事実を表しています。一般に、「指数関数 f(x) = a^x の導関数は、自分自身を定数倍したものになる」ということですね。指数関数は値が「指数的に」増えていくと同時に、傾きも「指数的に」増えていくというわけです。



・・・ここで問題です!

それでは、この定数  \lim_{h\to 0}\frac{a^h-1}{h} がぴったり 1 になる a を見つけることはできるでしょうか。

・・・がんばりました。

$ python
>>> h = 0.00000000001
>>> a = 2.71828
>>> (a ** h - 1 ) / h
1.000000082740371

・・・いえ嘘です。

答えを知っているので、それを使いました。実は、a = e = 2.71828\cdots となります。これで、

  f(x) = e^x とする時、すべての x について、f'(x) = e^x となる

ということがわかりました。

やったー。

補足説明

ちなみに、定数  \lim_{h\to 0}\frac{a^h-1}{h} がぴったり 1 になる a を見つけるということをやりましたが、よーーーーーく考えると、 \lim_{h\to 0}\frac{a^h-1}{h} は、指数関数 a^xx=0 における傾きそのものですね。非常におもしろいことに冒頭のエントリーで紹介した、「指数関数 a^xx=1 における傾きが f(1) になる a を見つける」という作業によく似ています。特定の点での傾きを決定することが、「すべての x について、f'(x) = a^x となる a」を探すという作業につながっているわけです。なかなか奥深いですねー。

Jupyter演習環境の準備手順

Mac OS Xを使用する場合

  • Mac OS X用のDockerが対応しているのは、Yosemite以降のバージョンです。ここで紹介する手順は、El Captitanで動作確認をしています。

はじめに、Dockerの公式Webサイトから、Mac OS X用のDockerをダウンロードします。「Getting Started with Docker」のリンクからダウンロードページを開いて、「Download Docker for Mac」をクリックすると、インストーラーファイル Docker.dmgがダウンロードできます。インストーラーを開いて、DockerアイコンをApplicationsフォルダーにコピーした後、ApplicationsフォルダーからDockerを起動します。初回の起動時は、インストール処理のポップアップが表示されますので、指示にしたがって、インストールを完了させてください。

インストールが完了してDockerが起動すると、上部のメニューバーにクジラのアイコンが表示されます。ここからDockerの管理メニューを表示して、「Preferences」を選択した後、「Advanced」のタブから「Memory」を4GB以上に設定します。「CPUs」の指定は任意ですが、サンプルコードの実行時間が極端に長くならないよう、4以上に設定することをおすすめします。最後に「Apply advanced settings」を押して、設定変更を反映します。

Mac OS Xに付属のターミナルを開いて、下記のコマンドを実行すると、Docker Hubからイメージをダウンロードして、コンテナ上でJupyterが起動します。「\」はコマンドの途中で改行する際に、入力する記号です。

$ mkdir $HOME/data
$ docker run -itd --name jupyter -p 8888:8888 -p 6006:6006 \
    -v $HOME/data:/root/notebook -e PASSWORD=passw0rd \
    enakai00/jupyter_tensorflow:latest

「-e PASSWORD」オプションには、WebブラウザーからJupyterに接続する際の認証パスワードを指定します。この例では、「passw0rd」を指定しています。この手順でコンテナを起動した場合、Jupyterで作成したノートブックのファイルは、ユーザーのホームディレクトリー(/User/<ユーザー名>)の下にある「data」ディレクトリーに保存されます。

Mac OS Xでブラウザーを起動して、URL「http://localhost:8888」にアクセスすると、ログイン画面が表示されるので前述のパスワードを入力してログインします。この後は、最後のセクションにある、動作確認に進んでください。

パブリッククラウドの仮想マシンを使用する場合

パブリッククラウドの仮想マシン上でDockerを起動して、環境を用意することも可能です。CentOS7のVMインスタンスを起動してログインした後、rootユーザーから、次の手順でコンテナを起動します。

# yum -y install docker
# systemctl enable docker.service
# systemctl start docker.service
# mkdir $HOME/data
# chcon -Rt svirt_sandbox_file_t $HOME/data
# docker run -itd --name jupyter -p 8888:8888 -p 6006:6006 \
    -v $HOME/data:/root/notebook -e PASSWORD=hogehoge \
    enakai00/jupyter_tensorflow:latest

「-e PASSWORD=」には、Jupyterにアクセスする際のパスワードを任意に指定します。ただし、通信経路の暗号化は行われないため、インターネット経由で直接にアクセスするのは危険です。SSHのトンネル機能を用いて、通信経路の暗号化を行ってください。たとえば、Windowsクライアントの環境であれば、TeratermなどのSSH端末から、次のように8888番ポートと6006番ポートの転送を指定して、SSH接続します。

Mac OS X、もしくは、Linuxクライアントであれば、次のように、-Lオプションでポート転送を指定してSSH接続します。

$ ssh -L 6006:localhost:6006 -L 8888:localhost:8888 -i .ssh/gcp_enakai enakai@xxx.xxx.xxx.xxx

この後、ローカルのブラウザーから、「http://localhost:8888」にアクセスするとSSHトンネルを経由して、Jupyterに接続することができます。ログイン画面が表示されるので前述のパスワードを入力してログインします。この後は、次のセクションにある、動作確認に進んでください。

動作確認

Jupyterにログインすると「ノートブックファイル」の一覧画面が表示されますが、今はまだノートブックファイルはありません。

右上のプルダウンメニューから「New」→「Python 2」を選択すると新しいノートブックが開きます。

ノートブック上では、セルにプログラムコードを入力して、「▶」ボタン、もしくは [Ctrl] + [Enter] で実行すると結果が表示されます。マークダウン形式のセルには説明文を記載することができます。

ノートブック全体を最初から実行し直す場合は、メニューから「Kernel」→「Restart & Clear Output」を選択して、これまでの実行内容をクリアします。

空のセルで次のコマンドを実行すると、演習用のノートブックがダウンロードできます。

!git clone https://github.com/enakai00/jupyter_ml4se

ノートブックファイル一覧画面でフォルダー「jupyter_ml4se」を開くと、ノートブックファイルが入っています。

「02-square_error.ipynb」のチェックボックスにチェック入れて、画面上部の「Duplicate」を押すと、ノートブックファイルのコピー「02-square_error-Copy1.ipynb」ができます。これをクリックして、ノートブックを開きます。

メニューから「Kernel」→「Restart & Clear Output」を選択して、これまでの実行内容をクリアした後に、メニューから「Cell」→「Run All」を選択すると、すべてのセルが上から順に自動実行されます。すべてのセルが正しく実行されることを確認しておいてください。たとえば、最後の2つのセルでは、次のようなグラフが表示されます。