PythonでのAI入門です。AIやPythonも参照のこと。
Pythonは、機械学習(AI)と科学技術計算の分野で、デファクトスタンダードになりつつある。
機械学習や科学技術計算をPythonで行いたい場合は、Anacondaと呼ばれるPythonのディストリビューションを使うことができる。ライブラリが最初から入っているため、便利である。
後日注記:WindowsでPythonによるプログラミングを学びたい場合は、Anacondaを使ってAnacondaプロンプトからPythonを実行するのが手軽です。特に以下の京都大学の教科書はPDFで公開されており参考になります。
Pythonで使われる機械学習用のライブラリは以下。
ライブラリ | 解説 |
---|---|
NumPy | 数値計算 |
SciPy | 数値解析 |
Matplotlib | グラフ描画 |
Pandas | データ解析 |
scikit-learn | 機械学習 |
(【決定版】WindowsでPythonを使って『機械学習』を学ぶための環境構築 - Qiitaを参考に執筆しました。)
NumPyとSciPyは、Pythonで数値の計算や解析を行うためのライブラリ。
以下が参考になる。
NumPyを参照のこと。
Pandasはデータ解析用のライブラリ。
Pandasを参照のこと。
scikit-learnはPythonのオープンソースな機械学習ライブラリ。
scikit-learnを参照のこと。
Chainerはオープンソースで日本製のディープラーニング用のライブラリ。
日本の機械学習系ベンチャー企業のPreferred Networksが開発を主導している。
以下のサイトからチュートリアルが参照できる。
後日注記:ディープラーニングの書籍として有名な「ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装」の著者である斎藤康毅さんはPreferred Networksの方です。
TensorFlowはGoogleによるオープンソースの機械学習・ディープラーニング用のライブラリ。
ほかにも、ディープラーニング用のライブラリとしてCaffeやTheanoなどが知られている。
Googleも参照のこと。
AIで良く使うコードを、コピペできるように掲載されているサイトがあります。
【保存版・初心者向け】独学でAIエンジニアになりたい人向けのオススメのAI勉強方法 (2019年改定版) - Qiitaというページが参考になる。
上のページはAI Academyというオンラインの学校の紹介ページだが、どんな書籍を読めば良いかが書いてあってとても参考になる。
また、僕が好きな@ITにもAI・人工知能のページができている。Pythonの入門記事もあって、AIがやりたいプログラミング初心者におすすめ。
機械学習については、Qiitaにさまざまな記事がある。特に、僕が見た限り以下のページが特に興味深い。「AIの研究はこのようにする」ということが分かる。
また、以下はなんと中学一年生の方の記事である。まだ執筆途中だが、将来の世代に期待がかかる。
機械学習やデータサイエンスは、数学的な数式や回帰アルゴリズムからデータ処理・変換・グラフ可視化モジュールまでたくさんの要素がある。全てを理解するためには途方もない時間と手間と労力が必要である。簡単に「Pythonの練習だからやりなさい」と言うわけにはいかない。本腰を据えてそれだけを勉強しても、何週間もかかるだろう。
以下のデータサイエンティストの方の講座は、数式が多く出てきて難しいですが、データサイエンスとはなんであるかを知るためにとても参考になります。おすすめです。
僕は、ディープラーニングのことを学びたいと思われている方は、書籍「ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装」を読むことをおすすめします。
この本は「ゼロから作る」とも書かれている通り、既存のライブラリやモジュールを極力使わず、ゼロから作ることを目指したディープラーニングの書籍です。
まだ僕はいくらかしか読めていませんが、この本はディープラーニングに対して「気軽に挑戦」することができる本です。掲載されている数式やプログラムは難しくなく、記述は丁寧かつざっくばらんで、用語もある程度のIT技術と基礎数学の知識があれば理解できます。
特に、「AIを作る面白さと理解するためのセンス」の書かれた、面白くAIの開発とそのための勉強ができるとても素晴らしい本だと思います。
Pythonの前提知識もあまり必要ではありません。Python初心者であっても理解出来るでしょう。それどころかこの本でPythonコードを書くセンスが身につくと思います。
(ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装を参考に執筆しました。)
パーセプトロンでは、それぞれのパラメータに「重みづけ」を行うことで、AND/NAND/ORゲートなどの論理回路を設計・実装できる。
たとえば、xに対して0.5という「重み」を掛け算し、yに対しても0.5という「重み」を掛け算し、これを足して0.7を超えた値になるかどうかを判断し、その結果を1か0として返すようなANDゲートが考えられる。
xが1で、yが0ならば、重みの和は0.5となり、0.7を超えないため、戻り値は0となる。
xが1で、yも1ならば、重みの和は1となり、0.7を超えるため、戻り値は1となる。
これで、パーセプトロンにより、ANDゲートは実装できた。NANDゲートやORゲートについても、重みパラメータを変えるだけで同様に実装できる。
基準となるのは、「バイアス + 重み1 + 重み2」の計算結果で、これが0以下であれば0を返し、0より大きければ1を返す。ANDの場合は重みの0.5に対してバイアス(発火する基準)が-0.7、NANDの場合は重みの-0.5に対してバイアスが0.7、ORの場合は重みの0.5に対してバイアスを-0.2とする。XORはこれらのゲートの組み合わせで実装できる。
だが、ここまでの実装では、パラメータの重みづけは人間の手で「0.5」とか「0.7」と決めていた。この重みを自動的にデータから学習することができるのが、ニューラルネットワークである。
ニューラルネットワークでは、判断を行う「活性化関数」を用いて、入力した信号の総和を出力する信号へと変換する。活性化関数は、入力の総和から出力が「どのような場合に発火するか」を記述した関数のこと。基本的にパーセプトロンとニューラルネットワークの違いは、活性化関数の違いだけ。
ニューラルネットワークでは、重みづけを人間の手ではなくデータから自動的に学習できる。このため、何百とか何千とか何万とか何億などといった単位でパラメータに自動的に重みづけを行うことができる。
(ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装を参考に執筆しました。)
活性化関数については、0か1かのステップ関数のほかに、次のような関数がある。
名前 | 関数 |
---|---|
シグモイド関数 | \[h(x) = \frac{1}{1 + \exp(-x)}\] \(\exp(-x)\)は\(e^{-x}\)のこと。 |
ReLU関数 | \[\begin{eqnarray}
h(x)
=
\begin{cases}
x & ( x \gt 0 ) \\
0 & ( x \leqq 0 )
\end{cases}
\end{eqnarray}\] 0よりも大きければその値を、0以下であれば0を返す。 |
ソフトマックス関数 | \[y_k = \frac{\exp(a_k)}{\displaystyle \sum^n_{i=1} \exp(a_i)}\] 入力\(a_n\)と出力\(y_n\)はn個あり、k番目の出力\(y_k\)を求める。 |
恒等関数 | 入力をそのまま出力する。 |
また、層ごとの計算においては、行列のドット積(NumPyではnp.dot)を使用する。行列の積においては、左の行列では横の列(行)、右の行列では縦の列(列)のそれぞれの要素の掛け算をし、その和を足し合わせて、新しい行列の要素にすることで行う。行列の積を使うことで、多次元配列によるニューラルネットワークの計算を極めて簡単に一度に行うことができるので、np.dotは多用する。
ソフトマックス関数は、データのクラス分類を行う分類問題において出力関数に使用する。たとえば手書きアルファベットのクラス分類をする場合、A~Zまでの文字を用意して、どれが一番確率が高いかを予想できる。また、値の予測をする回帰問題(たとえば人間の姿を見て年齢を当てる)では恒等関数を出力関数に使用する。
ここまでは、学習ではなく推論の内容。ある推論をする上では、その推論を行うためのアルゴリズムが必要となる。そのアルゴリズムを、人間が考えて実現するのではなく、データの中の「特徴量」を分析して、データを使って学習させるのが、機械学習の基本である。実際には、SVMやKNNなどの識別システムを使って、どのようなデータであっても汎用的な解析能力を実現する。これを汎化能力と呼ぶ。機械学習においては、訓練データ(教師データとも呼ばれる)を使って学習を行った上で、テストデータを使ってその判別能力がどれほどかをテストする。
また、注意すべきこととして、特定の偏ったデータセットだけに過度に学習された状態を「過学習」と呼ぶ。データの学習をする上では、過学習を避け、できるだけ偏りなくデータセットを学習させなければならない。汎化能力とは、訓練データによって培われた、まだ見ぬデータ(訓練データに含まれていないデータ)に対する能力であり、過学習によってあるデータセットだけに過度に学習させてしまうと、そのようなまだ見ぬデータを逆に解析できなくなってしまう。
ニューラルネットワークの学習には、なんらかの指標を具体的な数値で評価する「損失関数」を用いる。損失関数がもっとも最小値になる時が、最適な重みパラメータである。損失関数とは、「どれくらい識別器の性能が悪いか」を示す関数のこと。性能がよいのかではなく悪いのかで識別するのが奇妙だが、使うのはそれにマイナスを掛けた値であるため、どちらにせよやっていることは同じ。損失関数には以下のような関数が用いられる。
名前 | 関数 |
---|---|
2乗和誤差 | \[E = \frac{1}{2} \sum_k(y_k - t_k)^2\] |
交差エントロピー誤差 | \[E = -\sum_k t_k \log y_k\] |
kは次元数、\(y_k\)は出力、\(t_k\)は教師データのこと。
データがたくさんある場合、すべてのデータを計算していると時間が過剰にかかってしまう。なので、ニューラルネットワークの学習のために、たくさんのデータの中から少ないデータを無作為に選び出して学習する「ミニバッチ学習」を用いる。
損失関数を使う理由は、単に認識精度を指標にした場合、損失関数は精度が高い場合と低い場合に、それぞれの値を少しずつ変化させることができ、それによって損失関数の最小値がどこかを探ることができる。これが単に認識精度だけを指標にすると、学習内容を少し変えたところで、認識の正しさが変わることがなく、精度が高くなったか低くなったかを判断できない。微分で言えば、微分の値が多くの場合に0になってしまう。たとえば、20枚の画像が正しく判別できているとして、少し学習データを変えたぐらいでは、20枚が変動することは考えづらい。そのために、認識精度を指標にしてはいけない。どんなに二度手間に見えても損失関数を使わなければならない。
機械学習の数学には、微分も用いる。初等的な微分はひとつの変数を用いるが、機械学習では複数の変数を用いた微分も使う。これを「偏微分」と呼ぶ。偏微分は、あるひとつの変数に注目し、ほかの変数を定数と見なすことで、ひとつひとつの微分の計算をする。そして、偏微分のすべての変数の計算をベクトルにまとめたものを「勾配」と呼ぶ。そして、機械学習において勾配は、グラフ上のそれぞれの場所において、関数の値をもっとも減らすことができる方向を指し示す。そして、損失関数がいつ最小値を取るかを判断するために、勾配方向に進むことで関数の値を少しずつ減らしていく「勾配法」を用いる。勾配法は最適化問題でよく使われる。
2025.02.06-07
2025.02.11編集
僕の作ったロボット思考AIについては、ロボットを参照のこと。以下はロボットのページから転載。自分で作ったコードです。
#!/usr/bin/python # -*- coding: utf-8 -*- # 初版作成 Assy, 在導万創 import sys class Robot: def __init__(self): self.ego = 0 def msg_loop(self): while True: e = self.view() self.action(e) def action(self, msg): self.do(msg) self.think(msg) self.make_ego(msg) def do(self, msg): if msg == 0: print('晴れだ') elif msg == 1: print('雨だ') def think(self, msg): if msg == 0: print('散歩に出かけよう') elif msg == 1: print('家の中に居よう') if self.ego > 20: print('僕もそろそろ大人になったなあ') def make_ego(self, msg): #自我を作る self.ego += 1 if self.ego > 100: print('死にました') sys.exit() def view(self): #外を見て、晴れ(0)か雨(1)かを判断する #ここでは常に0 return 0 if __name__ == "__main__": rb = Robot() rb.msg_loop()
僕は、人間型のロボットを作るために必要なのは、「自分の状態」(ステート)が鍵になると思います。
ロボットが居るその環境を見ながら、変化を分析して「出来事」(イベント)を認識し、その上で「自分の状態に基づいたことを言う」ことができれば、ロボットは作れます。
出来事や状態とは、たとえば、ご飯を食べたら「おなかがいっぱいになった」とか、違う場所に行けば「この場所に来た」とか、そういうことを自分のステートとイベントに応じて言えるようにすれば良いのです。
その上で、自分の意志を持つ必要がありますが、これは単にステートの一部として意志を持つデータを格納すればいいのです。
ステートとイベントに応じたことを、上のPythonによるAIプログラムのように、永遠に考え続けることができたら、それで、外界とは全く分離されたロボットが作れます。このステートとイベントをパターン認識と分析した結果としての記憶から行えるようにすれば、きっと人間と同じロボットは作れるでしょう。鍵は「状態」です。
書籍