マネジメント工学実験II: 機械学習の基礎1

ニューラルネットワークによる予測モデル構築

日本大学生産工学部MA
担当: 大前 30-509
Mail: oomae.yuuto@nihon-u.ac.jp

0. はじめに: どうしてもうまくできない人へ

本実験では、プログラミングによって、人工知能を構築する練習を行います。ただ、どうしてもパソコンやプログラミングを受け付けないという方もいると思います。このページの説明を見て、自分なりに努力しても、どうしてもうまくいかない人は、以下に示す代替の課題に取り組んでください。

MA実験2/大前分 代替課題(どうしてもわからない人のみ)

1. Google Colaboratory の設定

本授業では、プログラミング言語pythonを使用します。これは、機械学習、人工知能、統計学といったデータ分析をはじめ、webアプリケーション開発、組込みシステム開発、といったシステム開発まで、とにかくなんでもできる万能なプログラミング言語です。この勉強のために、Google Colaboratory というオンラインプログラミングを実施します。


手続き: 1
Google Colaboratoryは、Webブラウザで実行できるプログラミング環境です。ただ、あらゆるWebブラウザに対応しているわけではありません。Internet ExplorerやMicrosoft Edge では動きませんので、自分のパソコンに、Google Chromeをインストールします。Webブラウザから「Google Chrome インストール」で検索し、インストールしてください。


手続き: 2
Webブラウザ「Google Chrome」を開き、下記のページに飛んでください。Web検索で「Google Colab」と入力しても、行くことができます。

Google Colaboratory

ここに行くと、下の画像のように、右上にログインボタンがあるので、そこを押し、自分の大学のアカウントでログインしてください。Gmailアカウントであればなんでもいいので、自分で取得しているフリーのGmailアカウントでもokです。


手続き: 3
続いて、下の画像のように各セルをクリックし、ゴミ箱マークを出現させ、それを押します。これにより、初めから記載されている説明文をすべて削除していきます。

下のように、まっさらになればokです。


手続き: 4
その後「+コード」ボタンを押します。すると、プログラムの入力欄が用意されます。

試しに、以下のコードをコピペし、貼り付けて、「再生ボタン」を押してください。

In [1]:
r = 10
menseki = r * r * 3.14
print("半径が", r, "の円の面積は", menseki, "です。")
半径が 10 の円の面積は 314.0 です。

上記コードは、以下の意味を持ちます。

  • 1行目: 変数 r に、10を代入
  • 2行目: 変数 menseki に「r r 3.14」を代入
  • 3行目: 変数 r と menseki を表示

rは10ですから、10かける10かける3.14、つまり314がmensekiに代入されます。rとmensekiを表示すると、10と314が表示されることになります。


手続き: 5
続いて、もう一度「+コード」ボタンを押します。すると、2つ目のプログラムの入力欄が用意されます。今後、コードを記入していくときは、前のコードを消さずに、+コードボタンで新たな入力欄を用意して、そこに書き込むようにしてください。

2つ目の入力欄に、以下のコードをコピペしてみましょう。

In [2]:
a = 3
b = 5
c = a + b
print("c=", c)
  File "<ipython-input-2-a0c32b26bff3>", line 4
    print("c=", c)
                ^
SyntaxError: invalid character in identifier

8が表示されるかと思いきや、エラーが出ました。この理由は、全角スペースは含まれているためです。その位置は、

  • print("c=", c)

となります。「,」の後ろに全角スペースがあるわけです。このように、プログラミングでは、全角文字は使用してはいけません。注意しましょう。正しくは、

In [3]:
a = 3
b = 5
c = a + b
print("c=", c)
c= 8

となります。

さて、このままプログラミングの基礎に関する学習を進めたいところですが、本授業は、プログラミングの基礎は学習しません。あくまで、人工知能を実装する、体験学習です。したがって、プログラミングの基礎はここまでにしておきます。

###########

pythonプログラミングの勉強をしたい方:

Paizaラーニング python3 無料編

注意: これは、授業とは関係ありません。やりたい方は、自主的にやるといいです、というお話です。

###########

2. ニューラルネットワークとは

ある入力から、出力を推定する方法の1つにニューラルネットワークという方法があります。我々はビジネスマネジメントコースですので、ビジネス上の問題に対して、ニューラルネットワークを使用する方法について考えます。このため、以下の状況を考えます。


前提条件

いま私たちは、あるチェーン店の商品を管理する部門にいるとします。この部門では、効率の良い経営のために、需要と供給のバランスを調整することが重要と考えています。すなわち、明日の来客数を事前に予知しておくことが重要になります。

「来客数」を予想するためには、前の日に予報される「降水確率」と「予想気温」が重要なのではないかと考えました。すなわち、

  • 入力
    • X1: 降水確率(前日に知ることができる)
    • X2: 予想気温(前日に知ることができる)
  • 出力
    • Y: 来客数(当日にならないと知ることができない)

という予測モデルを構築しようと考えました。


この入出力関係を有するニューラルネットワークを図示すると、以下のようになります。

降水確率、予測気温、この2個の数字が入力され、2次元のベクトルとして表されます。これが3次元に変換され、最後に1次元の数値となります。最後に得られる1つの数字が、来客者数を意味する、ということになります。このモデルが、あたかも生物の脳にあるニューロンに流れる電気信号の伝搬に似ているため、ニューロンのネットワーク、つまり、ニューラルネットワークと呼ばれるようになりました。

3. ニューラルネットワークの実装

3.1 教師データ

ニューラルネットワークを構築する際、

  1. 教材にある問題を解く
  2. 正答率を出す
  3. 思考を変える
  4. 1に戻る(これを何度も繰り返す)
  5. 教材の問題をよく解けたら、未知の問題も解けるんじゃないの?

という過程を踏みます。これを成すには、特に、手続き1の処理において問題、手続き2の処理において正答率を求めるわけですから問題に対する答えが必要になります。これを今回の問題に当てはめてみると、降水確率と予想気温が定まったときの来客者数が知りたいわけですから、

  • 教材(教師データ)
    • 問題: 降水確率と予想気温
    • 答え: 来客者数

となります。具体的には「降水確率が20%、予想気温が30度のとき、500人のお客さんが来た」が1つの問題と答えのペアとなります。もちろん、1問だけ解けても意味がないのでたくさんの問題が必要になります。このように、問題と答えがセットになったデータのことを、教師データと呼びます。教師データがあると、手続き1, 2の処理を実行可能になります。すると、もっと頭を良くしようという理由により、手続き3として、思考を変化させます。これらを何度も繰り返すと、いろいろな問題を正しく解ける知能の形成が期待されます。

本来、何かしらの研究を行う場合は、自分で汗をかきながら、泥臭い作業として、教師データを集めねばいけませんが、今回はあくまでも、人工知能の勉強ということですので、すでにこちらで用意しておきます。これが、以下のコードとなります。

In [4]:
import numpy as np

# 降水確率
X1 = [10, 50, 90, 10, 10, 
         90, 90, 30, 70, 100 ]

# 予想気温
X2 = [21, 23, 20, 11, 35, 
         13, 36, 19, 32, 37 ]

# 来客数
Y = [910, 621, 210, 630, 610, 
         120, 90, 810, 320, 10 ]

print("### 教師データ ###")
print("")
for i in range(0, len(Y)):
    print("     ***", str(i), "日目の観測 ***")
    print("   X1: 降水確率 = ", X1[i], " [%] / X2: 予想気温 = ", X2[i], " [度] ならば Y: 来客数 = ", Y[i], " [人]")
    print("")
    
# データセットの整形
val = 100
X1n = np.reshape(X1, (len(X1), 1))/val
X2n = np.reshape(X2, (len(X2), 1))/val
X=np.concatenate([X1n, X2n], 1)

Ys = []
for i in range(len(Y)):
    Ys.append(Y[i]/val)
### 教師データ ###

     *** 0 日目の観測 ***
   X1: 降水確率 =  10  [%] / X2: 予想気温 =  21  [度] ならば Y: 来客数 =  910  [人]

     *** 1 日目の観測 ***
   X1: 降水確率 =  50  [%] / X2: 予想気温 =  23  [度] ならば Y: 来客数 =  621  [人]

     *** 2 日目の観測 ***
   X1: 降水確率 =  90  [%] / X2: 予想気温 =  20  [度] ならば Y: 来客数 =  210  [人]

     *** 3 日目の観測 ***
   X1: 降水確率 =  10  [%] / X2: 予想気温 =  11  [度] ならば Y: 来客数 =  630  [人]

     *** 4 日目の観測 ***
   X1: 降水確率 =  10  [%] / X2: 予想気温 =  35  [度] ならば Y: 来客数 =  610  [人]

     *** 5 日目の観測 ***
   X1: 降水確率 =  90  [%] / X2: 予想気温 =  13  [度] ならば Y: 来客数 =  120  [人]

     *** 6 日目の観測 ***
   X1: 降水確率 =  90  [%] / X2: 予想気温 =  36  [度] ならば Y: 来客数 =  90  [人]

     *** 7 日目の観測 ***
   X1: 降水確率 =  30  [%] / X2: 予想気温 =  19  [度] ならば Y: 来客数 =  810  [人]

     *** 8 日目の観測 ***
   X1: 降水確率 =  70  [%] / X2: 予想気温 =  32  [度] ならば Y: 来客数 =  320  [人]

     *** 9 日目の観測 ***
   X1: 降水確率 =  100  [%] / X2: 予想気温 =  37  [度] ならば Y: 来客数 =  10  [人]

課題1: 10日分の降水確率、予想気温、来客者数をすべて記入してください。また、この結果を見て、降水確率、予想気温、来客者数の関係を自由に考察してください。

3.2 実装方法

それでは次に、先ほど記録したデータを用いて、ニューラルネットワークを構築してみます。以下2つの値が出力されます。

  • 予測値: ニューラルネットワークが予測した来客者数
  • 実測値: 先ほど記録した、本当の来客者数
In [5]:
from sklearn.neural_network import MLPRegressor
import time

# あなたの学籍番号
Your_Number = 111111

# ニューラルの定義
NNmodel = MLPRegressor(
                        hidden_layer_sizes=(3, ),
                        solver='adam',
                        activation="logistic",
                        learning_rate_init=0.01, 
                        random_state=Your_Number,
                        max_iter=10000,
                        tol = pow(10, -100),
                        verbose=False)

# ニューラルの学習開始
NNmodel.fit(X, Ys)

# 結果表示
print("### ニューラルネットワークによる予測結果 ###")
Y_NN = NNmodel.predict(X)
Er = []
for i in range(0, len(Y)):
    print(str(i), "日目の予測来客者数= ", str(np.round(Y_NN[i]*100, 0)), " [人](参考: 実測=", Y[i], " [人])")
    Er.append(np.abs(Y_NN[i]-Ys[i])*100)

print("10日分の絶対誤差の平均値: ", np.round(np.mean(Er), 0))
### ニューラルネットワークによる予測結果 ###
0 日目の予測来客者数=  917.0  [人](参考: 実測= 910  [人])
1 日目の予測来客者数=  623.0  [人](参考: 実測= 621  [人])
2 日目の予測来客者数=  216.0  [人](参考: 実測= 210  [人])
3 日目の予測来客者数=  640.0  [人](参考: 実測= 630  [人])
4 日目の予測来客者数=  611.0  [人](参考: 実測= 610  [人])
5 日目の予測来客者数=  114.0  [人](参考: 実測= 120  [人])
6 日目の予測来客者数=  79.0  [人](参考: 実測= 90  [人])
7 日目の予測来客者数=  791.0  [人](参考: 実測= 810  [人])
8 日目の予測来客者数=  321.0  [人](参考: 実測= 320  [人])
9 日目の予測来客者数=  20.0  [人](参考: 実測= 10  [人])
10日分の絶対誤差の平均値:  7.0
/Users/yuto.omae/.pyenv/versions/3.7.1/lib/python3.7/site-packages/sklearn/neural_network/_multilayer_perceptron.py:585: ConvergenceWarning: Stochastic Optimizer: Maximum iterations (10000) reached and the optimization hasn't converged yet.
  % self.max_iter, ConvergenceWarning)


課題2: 課題1で作成した表に列を追加して、ニューラルネットワークによる10日分の予測値を記入し、絶対誤差を計算してください。絶対誤差とは、「実測値から予測値を引き、符号をプラスに置き換えたもの」となります。また、絶対誤差の平均値を求め、予測性能が高いか低いか、自分の感想を記載してください。


課題3: 課題2において、実測値と予測値を比較して、誤差を求めました。この事例に限らず、何らかの予測手法を開発した後、実際にそれを使う前に、誤差を求めるということはとても重要な作業です。なぜ重要だと思うか、あなたの考えを述べてください。


続いて、構築したニューラルネットワークを利用して、自分が予測してみたいと思う「降水確率」と「予想気温」を入力し、そのときの出力結果を得てみましょう。以下のコードのi1とi2に代入される数字を変更すれば、そのときの、ニューラルネットワークが予測する来客者数を知ることができます。

In [6]:
i1 = 50 # 降水確率(自分で値を決める)
i2 = 30 # 予想気温(自分で値を決める)
pred = NNmodel.predict([[i1/100, i2/100]])
print("予測された来客者数: ", np.round(pred[0]*100, 0), " [人]")
予測された来客者数:  595.0  [人]


課題4: 自分が独自に考えた「降水確率」と「予想気温」を5組考えて、そのときの来客者数の予測結果を記載してください。教師データにはない「降水確率」と「予想気温」を採用してください。ただし、気温が60度など、現実的にあり得ない値は使わないでください。


課題5: 上の課題において、様々な事例で予測を行えることがわかりました。あなたがお店の経営者だったとき、「降水確率」と「予想気温」から「明日の来客者数」を予測できることについて、どのような利点があると考えるか、考察してください。


これによって、学習済みのニューラルネットワークがあれば、色々なパターンで予測ができることがわかりました。

それでは次に、構築したNNがどのような思考を有しているのか、可視化してみます。これが、以下に示すコードです。

In [7]:
# メッシュデータ生成
Xmin, Ymin, Xmax, Ymax = 0, 0, 1, 1 # 空間の最小最大値
resolution = 0.01 # 細かさ
x_mesh, y_mesh = np.meshgrid(np.arange(Xmin, Xmax, resolution),
                             np.arange(Ymin, Ymax, resolution))
MeshDat = np.array([x_mesh.ravel(), y_mesh.ravel()]).T

# メッシュデータの推定
z = NNmodel.predict(MeshDat)

# データ整形
z = np.reshape(z, (len(x_mesh), len(y_mesh))) 

# 可視化
from matplotlib import pyplot as plt
fig = plt.figure(figsize=(7, 6))
plt.pcolor(x_mesh*val, y_mesh*val, z*val, cmap="hot")
plt.colorbar()
plt.xlabel('X1: Rain', size=15)
plt.ylabel('X2: Temperature', size=15)
plt.ylim([0, 50])
plt.show()
/Users/yuto.omae/.pyenv/versions/3.7.1/lib/python3.7/site-packages/ipykernel_launcher.py:17: MatplotlibDeprecationWarning: shading='flat' when X and Y have the same dimensions as C is deprecated since 3.3.  Either specify the corners of the quadrilaterals with X and Y, or pass shading='auto', 'nearest' or 'gouraud', or set rcParams['pcolor.shading'].  This will become an error two minor releases later.


課題6: 上のコードを実行して得られる図は、下記の意味を持ちます。

  • 横軸: X1 降水確率 [%]
  • 縦軸: X2 予想気温 [度]
  • 色の濃度: 予測された来店者数(白なら多く、黒なら少ない)

この図を見て、構築したニューラルネットワークは、どのような知識を形成したと思うか、自由に考察してください。また、レポート用紙にこの図を貼り付けてください。


3.3 学習係数と学習回数について

先ほどの課題をこなすことで、ニューラルネットワークがどのようなもので、どう活用できるのか、なんとなくですが、わかってきたと思います。次に、もう少し深くニューラルネットワークのことを考えてみます。

ニューラルネットワークを構築する際、重要なパラメータとして、学習回数と学習係数があります。すごくざっくりと説明すると、以下を意味します。

  • 学習回数: 人工知能の思考を何回変化させるか
  • 学習係数: 一回の学習に対する、思考の変化の大きさ

人工知能のうち、特にニューラルネットワークは、学習を繰り返して少しずつ頭をよくしていくという特徴を持ちます。この学習の仕方に関するパラメータが「学習回数」と「学習係数」を意味するわけです。

ここでは、学習回数と学習係数が知能の形成にどのような影響を及ぼすのか、実験で確かめてみます。

以下のコード、Num_iterations と Learning_rate に代入させる値を変化させることで、学習回数と学習係数を変化させることができます。また、そのときの絶対誤差の平均値を求めてくれる機能も有しています。

In [8]:
### 以下を変更していくこと ###
Num_iterations = 100 # 学習回数
Learning_rate = 0.01 # 学習係数
Your_Number = 111111 # あなたの学籍番号
#######################

# ニューラルの定義
NNmodel_test = MLPRegressor(
                        hidden_layer_sizes=(3, ),
                        solver='adam',
                        activation="logistic",
                        learning_rate_init=Learning_rate, 
                        random_state=Your_Number,
                        max_iter=Num_iterations,
                        tol = pow(10, -100),
                        verbose=False)

# ニューラルの学習開始
NNmodel_test.fit(X, Ys)

# 結果表示
print("### ニューラルネットワークによる予測結果 ###")
Y_NN = NNmodel_test.predict(X)
Er = []
for i in range(0, len(Y)):
    print(str(i), "日目の予測来客者数= ", str(np.round(Y_NN[i]*100, 0)), " [人](参考: 実測=", Y[i], " [人])")
    Er.append(np.abs(Y_NN[i]-Ys[i])*100)

print("")
print(" → 絶対誤差(平均値): ", np.round(np.mean(Er), 0))
### ニューラルネットワークによる予測結果 ###
0 日目の予測来客者数=  324.0  [人](参考: 実測= 910  [人])
1 日目の予測来客者数=  335.0  [人](参考: 実測= 621  [人])
2 日目の予測来客者数=  343.0  [人](参考: 実測= 210  [人])
3 日目の予測来客者数=  317.0  [人](参考: 実測= 630  [人])
4 日目の予測来客者数=  331.0  [人](参考: 実測= 610  [人])
5 日目の予測来客者数=  340.0  [人](参考: 実測= 120  [人])
6 日目の予測来客者数=  349.0  [人](参考: 実測= 90  [人])
7 日目の予測来客者数=  328.0  [人](参考: 実測= 810  [人])
8 日目の予測来客者数=  344.0  [人](参考: 実測= 320  [人])
9 日目の予測来客者数=  352.0  [人](参考: 実測= 10  [人])

 → 絶対誤差(平均値):  292.0
/Users/yuto.omae/.pyenv/versions/3.7.1/lib/python3.7/site-packages/sklearn/neural_network/_multilayer_perceptron.py:585: ConvergenceWarning: Stochastic Optimizer: Maximum iterations (100) reached and the optimization hasn't converged yet.
  % self.max_iter, ConvergenceWarning)


課題7: 以下の学習係数、学習回数の組み合わせで、ニューラルネットワークを構築し、そのときの絶対誤差の平均値を記録してください。絶対誤差の平均値は、自動的に計算してくれるので、出力の一番下をみて、それを記入すればokです。

  • 学習係数0.1, 学習回数 1, 10, 100, 1000, 10000, 100000
  • 学習係数0.01, 学習回数 1, 10, 100, 1000, 10000, 100000


課題8: 学習回数が誤差に与える影響を考察してください。


課題9: 学習係数が誤差に与える影響を考察してください。


課題10: 学習係数0.1、学習回数10のときの予測結果を記録し、正しく予測を行えているかどうかを判断し、その理由を考察してください。

以上でこの実験は終了となります。ニューラルネットワークは様々なところで使用されている。分析手法です。今回はかなりざっくりとした説明に終始しましたが、もし興味がある人がいれば、人工知能の学習を本格的に初めて見るのも良いかもしれません。

最後に、下記の課題を終えたら、本実験は終了となります。


課題11: 以下の論文の中から1つ選択肢し、下記の問題に取り組んでください。

文献リスト:

問題:

  • (1) どの文献を選択したか、1つ記載してください。
  • (2) 何を入力すると、何を出力してくれるニューラルネットワークでしょうか?
  • (3) そのニューラルネットワークは、どのような場面で、どう活用できるでしょうか。