ニューラルネットワークでデータ分類

ニューラルネットワークでデータの分類をしてみます。
まずは、chainerの宣言をします。

1
2
3
4
import chainer.optimizers as Opt
import chainer.functions as F
import chainer.links as L
from chainer import Variable, Chain, config

次に乱数を生成します。100行2列のデータとなります。

1
2
3
4
5
6
import numpy as np
import matplotlib.pyplot as plt

D = 100
N = 2
xdata = np.random.randn(D * N).reshape(D, N).astype(np.float32)

次にデータを分割する関数とその関数で分類したデータを準備します。

1
2
3
4
def f(x):
return x * x

tdata = (xdata[:,1] > f(xdata[:,0])).astype(np.int32)

1層のニューラルネットワーク作成します。
2種類のデータが入力され、2種類のデータ出力される単純なニューラルネットワークとなります。

1
2
3
# 1層のニューラルネットワーク作成
C = 2 # 結果が2種類あるという意味
NN = Chain(l1=L.Linear(N, C))

このニューラルネットワークを使った関数を定義します。

1
2
3
def model(x):
y = NN.l1(x)
return y

上記で定義した関数でデータを分類します。

1
2
ydata = model(xdata)
ydata

乱数で生成したデータ(一部略)
正解率を検証します。

1
2
3
# 精度の検証
acc = F.accuracy(ydata, tdata)
acc

最初の正解率
結果は0.21(21%)ととても低いですが、まったく学習をしていない状態なので気にする必要はありません。

ニューラルネットワークを最適化する手法を設定します。

1
2
3
# 最適化手法の設定
optNN = Opt.SGD()
optNN.setup(NN)

結果を確認するために、誤差と正解率を記録するエリアを定義します。

1
2
3
# 学習の記録用
loss_series = []
acc_series = []

いよいよ学習してみます。処理に関してはソースコメントを参照してください。

1
2
3
4
5
6
7
8
9
10
11
12
T = 5000
for time in range(T):
config.train = True # 学習モードにする
optNN.target.zerograds() # 初期化(全ての勾配を0にする)
ydata = model(xdata) # 誤差を計算する
loss = F.softmax_cross_entropy(ydata, tdata) # 成績チェック
acc= F.accuracy(ydata, tdata) # 誤差逆伝搬
loss.backward() # ニューラルネットワークを調整
optNN.update()
# 結果の記録
loss_series.append(loss.data)
acc_series.append(acc.data)

誤差がどのように変化しているかをグラフ化します。

1
2
3
4
5
6
7
8
9
10
# 学習記録の表示(誤差)
Tall = len(loss_series)
plt.figure(figsize=(8, 6))
plt.plot(range(Tall), loss_series)
plt.title('loss function in training')
plt.xlabel('step')
plt.ylabel('loss function')
plt.xlim([0, Tall])
plt.ylim(0, 1)
plt.show()

誤差(1層のニューラルネットワーク)
0.3付近までは順調に誤差が減っていますがそこからは改善していないようです。
次に、正解率の遷移をグラフ化します。

1
2
3
4
5
6
7
8
9
10
# 学習記録の表示(正解率)
Tall = len(acc_series)
plt.figure(figsize=(8, 6))
plt.plot(range(Tall), acc_series)
plt.title('accuracy in training')
plt.xlabel('step')
plt.ylabel('accuracy')
plt.xlim([0, Tall])
plt.ylim(0, 1)
plt.show()

正解率(1層のニューラルネットワーク)
0.85(85%)付近までは上昇しますが、そこが限界のようです。

さらなる精度情報のために2層のニューラルネットワークにしてみます。
下記では、入力が2種類、中間層が4層、出力が2種類となるニューラルネットワークを定義しています。

1
2
3
# 2層のニューラルネットワークにする
C = 2
NN = Chain(l1=L.Linear(N, 4), l2=L.Linear(4 , C))

2層のニューラルネットワークの関数化ですが2つの線形変換の間に非線形変換をいれるとよいとのことです。
シグモイド関数をはさんでみました。

1
2
3
4
5
6
# 2層のニューラルネットワークの関数化
def model(x):
h = NN.l1(x) # 線形変換
h = F.sigmoid(h) # 非線形変換(シグモイド関数)
y = NN.l2(h) # 変形変換
return y

あらたにニューラルネットワークを定義したので、最適化手法を再設定します。
学習記録もいったん初期化し、学習を2万回に増やして実行します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 最適化手法の設定(再設定)
optNN = Opt.SGD()
optNN.setup(NN)

# 学習の記録用(初期化)
loss_series = []
acc_series = []

# 学習
T = 20000
for time in range(T):
config.train = True
optNN.target.zerograds()
ydata = model(xdata)
loss = F.softmax_cross_entropy(ydata, tdata)
acc= F.accuracy(ydata, tdata)
loss.backward()
optNN.update()
# 結果の記録
loss_series.append(loss.data)
acc_series.append(acc.data)

結果は下記のとおりです。
誤差(2万回)
正解率(2万回)

誤差の結果をみるとまだまだ改善するような感じなのでもう2万回 追加で学習をしてみます。
再実行するのは、ループの[学習]のところと[学習記録の表示(誤差)][学習記録の表示(正解率)]です。

誤差(4万回)

正解率(4万回)

だんだん結果がよくなっているので、もう2万回追加で実行します。

誤差(6万回)

正解率(6万回)

ほぼ100%の正解率にすることができました。
誤差が改善する見込みがある場合は、学習回数を単純に増やしていくといいみたいです。

(Google Colaboratoryで動作確認しています。)

numpyで乱数生成・データ分類・分類したデータをグラフ表示

numpyで生成した乱数を、特定関数で分類し、その分類したデータをグラフに表示します。
まずは必要なモジュールをimportします。

1
2
3
# 基本モジュールの宣言
import numpy as np
import matplotlib.pyplot as plt

次に乱数を生成します。縦100横2の配列にreshapeしています。

1
2
3
4
5
# 乱数生成(縦100,横2の配列分の乱数を生成)
D = 100
N = 2
xdata = np.random.randn(D * N).reshape(D, N).astype(np.float32)
xdata

結果(一部略)
生成した配列をx,yを表した100個のデータとみなして散布図を表示します。

1
2
3
4
5
# 散布図を表示
# xdata[:,0] <= 1列目に縦に並んでいる数字の全て
# xdata[:,1] <= 2列目に縦に並んでいる数字の全て
plt.scatter(xdata[:,0], xdata[:,1])
plt.show()

結果
分類用の関数を定義します。ここでは単純にxを2乗した数値を返しています。

1
2
3
# 関数の定義
def f(x):
return x * x

乱数の配列に対して、定義した関数の上にくるか下にくるかを判定します。
上にくる場合は1を、下にくる場合は0が返ります。
(ループで1つずつ処理しなくても入力の配列に対して、結果の配列が返ってくるのがnumpyの便利なところです。)

1
2
3
# 条件にあてはまるものを探す
tdata = (xdata[:,1] > f(xdata[:,0])).astype(np.int32)
tdata

結果
結果がTrue(1)となる配列のインデックスをndata0に、False(0)となる配列のインデックスをndata1に格納します。

1
2
3
4
5
6
# 乱数のデータを2つのグループに分ける
# True(1)とFalse(0)の場所を調べる
ndata0 = np.where(tdata==0)
ndata1 = np.where(tdata==1)
print(ndata0)
print(ndata1)

結果
最後にグループ分け関数と分類されたデータを1つのグラフとして表示します。

1
2
3
4
5
6
7
8
# 2つの種類のデータを図に示す
x = np.linspace(-2.0, 2.0, D) # -2.0から2.0の範囲でD=100個の点を用意する
plt.plot(x, f(x))

plt.scatter(xdata[ndata0, 0], xdata[ndata0, 1], marker='x')
plt.scatter(xdata[ndata1, 0], xdata[ndata1, 1], marker='o')

plt.show()

結果

(Google Colaboratoryで動作確認しています。)

3Dグラフ表示

matplitlibとjupyterで3Dグラフを書いてみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 3Dグラフ
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
%matplotlib inline

t = np.linspace(-2 * np.pi, 2 * np.pi)
x, y = np.meshgrid(t, t)
R = np.sqrt(x ** 2 + y ** 2)
z = np.sin(R)

fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(1, 1, 1, projection='3d')

ax.plot_surface(x, y, z)
plt.show()

[結果]
結果

次に曲面を描画した3Dグラフを書いてみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np
import matplotlib.pyplot as plt

from mpl_toolkits.mplot3d import Axes3D
%matplotlib inline

x = y= np.linspace(-5, 5)
X, Y = np.meshgrid(x, y)
Z = np.exp(-(X ** 2 + Y ** 2) / 2) / (2 * np.pi)

fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(1, 1, 1, projection='3d') # 3D描画機能を持ったサブプロット作成
ax.plot_surface(X, Y, Z) # 曲面を描画した3Dグラフを表示

plt.show()

結果

今度は3Dヒストグラムを書いてみます。
描画関数としてはbar3dを使用します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import numpy as np
import matplotlib.pyplot as plt

from mpl_toolkits.mplot3d import Axes3D
%matplotlib inline

fig = plt.figure(figsize=(8, 6))

ax = fig.add_subplot(111, projection="3d")

# x, y, zの位置を決める
xpos = [i for i in range(10)]
ypos = [i for i in range(10)]
zpos = np.zeros(10)

# x, y, zの増加量を決める
dx = np.ones(10)
dy = np.ones(10)
dz = [i for i in range(10)]

# 3Dヒストグラムを作成
ax.bar3d(xpos, ypos, zpos, dx, dy, dz)

plt.show()

結果

3D散布図を書いてみます。
描画関数としてはscatter3Dを使用します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import numpy as np
import matplotlib.pyplot as plt

from mpl_toolkits.mplot3d import Axes3D
%matplotlib inline

fig = plt.figure(figsize=(8, 6))

np.random.seed(0) # 乱数を固定する(毎回同じ乱数が出るようになる)
X = np.random.randn(1000)
Y = np.random.randn(1000)
Z = np.random.randn(1000)

ax = fig.add_subplot(1, 1, 1, projection='3d')
# 1次元に変換
x = np.ravel(X)
y = np.ravel(Y)
z = np.ravel(Z)

ax.scatter3D(x, y, z)
plt.show()

結果

最後にグラフの点が通る座標に応じて表示する色を変えてみます。
plot_surface関数にcmap=cm.coolwarmを指定するだけです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np
import matplotlib.pyplot as plt

from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
%matplotlib inline

t = np.linspace(-2 * np.pi, 2 * np.pi)
x, y = np.meshgrid(t, t)
r = np.sqrt(x ** 2 + y ** 2)
z = np.sin(r)

fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(1, 1, 1, projection="3d")
ax.plot_surface(x, y, z, cmap=cm.coolwarm) # カラーマップを適用

plt.show()

結果

(Google Colaboratoryで動作確認しています。)

pandas

pandasの基本操作を一通り試してみます。
まずは単純にpandasでcsvファイルを読み込んでみます。
[csvファイル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
date,station,temp
2018/9/1,札幌,19.5
2018/9/1,青森,21.5
2018/9/1,仙台,21.5
2018/9/1,東京,25.9
2018/9/1,福岡,25.5
2018/9/1,鹿児島,26.8
2018/9/1,那覇,27.6
2018/9/1,波照間,27.3
2018/9/1,秋田,22.2
2018/9/1,盛岡,22.0
2018/9/1,山形,20.8
2018/9/1,福島,21.9
2018/9/1,水戸,23.7
2018/9/1,千葉,27.5
2018/9/1,宇都宮,23.2
2018/9/1,さいたま,24.8
(以下略)

[コード]

1
2
3
4
5
# pandasでcsvファイルを読み込む
import pandas

df = pandas.read_csv('data.csv', encoding="Shift_JIS")
df

[結果]
結果
print関数を使わずJupyter上でdataframe型の変数を表示するといい感じのテーブルで表示してくれます。

dataframe型データの先頭数行を表示する場合はhead関数を使います。
(引数にデータ数を指定することもできます。)

1
df.head()

[結果]
結果
末尾数行を表示する場合はtail関数を使います。
(引数にデータ数を指定することもできます。)

1
df.tail()

[結果]
結果

次に変数dfをインデックス指定で分割します。
範囲指定の数字はデータ自体の順番を考えるよりもデータとデータの間の順番と考えるとわかりやすいと思います。

1
2
df_sliced = df.iloc[2:7]
df_sliced

[結果]
結果

分割したデータをさらに分割することもできます。

1
df_sliced.iloc[2:4]

[結果]
結果

今度は行ごとに指定ではなく、列ごとに指定します。
列を指定する場合は、単純に列名(カラム名)を使用します。

1
df['temp']

[結果]
結果
カラム名で指定したデータはシリーズデータになっていて最大値、最小値、合計、平均を簡単に取得することができます。

1
2
3
4
print('最大値', df['temp'].max())
print('最小値', df['temp'].min())
print('合計', df['temp'].sum())
print('平均', df['temp'].mean())

[結果]
結果
また欠損値がある場合はfillna関数を使って補完することができます。
下記は平均値で補完するサンプルコードとなります。

1
2
m = df['temp'].mean()
df['temp'] = df['temp'].fillna(m)

(Google Colaboratoryで動作確認しています。)

画像OCR(連続文字の認識)

数字がどこに書かれているかを見つける処理を実装してみます。
まずは数字が10個表示されている下記の画像を入力ファイルとします。
10個の数字(numbers.png)

実装する処理は下記の通りです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import sys
import numpy as np
import cv2

# 画像の読み込み
im = cv2.imread('numbers.png')
# グレイスケールに変換しぼかした上で二値化する
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5, 5), 0)
thresh = cv2.adaptiveThreshold(blur, 255, 1, 1, 11, 2)

# 輪郭を抽出
contours = cv2.findContours(
thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[1]

# 抽出した領域を繰り返し処理する
for cnt in contours:
x, y, w, h = cv2.boundingRect(cnt)
if h < 20: # 小さすぎるのは飛ばす
continue
red = (0, 0, 255)
cv2.rectangle(im, (x, y), (x+w, y+h), red, 2)

cv2.imwrite('result1.png', im)

結果1(result1.png)
問題なく見つけた数字を赤枠で囲むことができています。

次に100個の数字が表示されている画像を入力にしてみます。
6行目の入力ファイル名を変更するだけです。
100個の数字(numbers100.png)

結果2
結果は上記のようになり数字の中まで赤枠で囲ってしまっています。
これを改善するためには、cv2.RETR_LISTというパラメータをcv2.RETR_EXTERNAL(15行目)に変更します。
このパラメータは領域の一番外側だけを検出するという意味になります。
下記に修正したソースの全体を記載しておきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import sys
import numpy as np
import cv2

# 画像の読み込み
im = cv2.imread('numbers100.png')
# グレイスケールに変換しぼかした上で二値化する
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5, 5), 0)
thresh = cv2.adaptiveThreshold(blur, 255, 1, 1, 11, 2)

# 輪郭を抽出
contours = cv2.findContours(
thresh,
cv2.RETR_EXTERNAL, # ☆☆☆領域の一番外側だけを検出☆☆☆
cv2.CHAIN_APPROX_SIMPLE)[1]

# 抽出した領域を繰り返し処理する
for cnt in contours:
x, y, w, h = cv2.boundingRect(cnt)
if h < 20: # 小さすぎるのは飛ばす
continue
cv2.rectangle(im, (x, y), (x+w, y+h), (0,0,255), 2)
cv2.imwrite('result3.png', im)

結果3(result3.png)

今度は適切に全ての数字を認識することができました。

(Google Colaboratoryで動作確認しています。)

OpenCVで顔認識

OpenCVを使って顔認識を試してみます。
まずは、画像に写っている顔の範囲を調べます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import cv2
import sys

# 入力ファイルを指定する
image_file = "./face1.jpg"

# カスケードファイルのパスを指定 ---OpenCVをインストールするとshareディレクりに格納される
cascade_file = "haarcascade_frontalface_alt.xml"

# 画像の読み込み
image = cv2.imread(image_file)
# グレースケールに変換
image_gs = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 顔認識用特徴量ファイルを読み込む
cascade = cv2.CascadeClassifier(cascade_file)
# 顔認識の実行
face_list = cascade.detectMultiScale(image_gs,
scaleFactor=1.1,
minNeighbors=1,
minSize=(150,150)) # 顔認識の最小範囲(これ以下は無視)

if len(face_list) > 0:
# 認識した部分を囲む
print(face_list)
color = (0, 0, 255)
for face in face_list:
x,y,w,h = face
cv2.rectangle(image, (x,y), (x+w, y+h), color, thickness=8)
# 描画結果をファイルに書き込む
cv2.imwrite("facedetect-output.png", image)
else:
print("no face")

入力ファイル
顔認識結果

正常に顔の範囲が認識できました。
次に顔にモザイクをかけてみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import cv2, sys, re

# 入力ファイル
image_file = "./face1.jpg"

# 出力ファイル名
output_file = re.sub(r'\.jpg|jpeg|png$', '-mosaic.jpg', image_file)
mosaic_rate = 30

# カスケードファイルのパスを指定
cascade_file = "haarcascade_frontalface_alt.xml"

# 画像の読み込み
image = cv2.imread(image_file)
image_gs = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # グレイスケール変換

# 顔認識を実行
cascade = cv2.CascadeClassifier(cascade_file)
face_list = cascade.detectMultiScale(image_gs,
scaleFactor=1.1,
minNeighbors=1,
minSize=(100,100))

if len(face_list) == 0:
print("no face")
quit()

# 認識した部分にモザイクをかける
print(face_list)
color = (0, 0, 255)
for (x,y,w,h) in face_list:
# 顔を切り抜く
face_img = image[y:y+h, x:x+w]
# 切り抜いた画像を指定倍率で縮小
face_img = cv2.resize(face_img, (w//mosaic_rate, h//mosaic_rate))
# 縮小した画像を元のサイズに戻す
face_img = cv2.resize(face_img, (w, h),
interpolation=cv2.INTER_AREA)
# 元の画像に貼り付ける
image[y:y+h, x:x+w] = face_img
# 描画結果をファイルに書き込む
cv2.imwrite(output_file, image)

モザイク結果

(Google Colaboratoryで動作確認しています。)

ニューラルネットワーク(3)

前回使用したテストデータは10種ですが、次にもっと大きなデータを使ってテストするときのために正解率を表示できるようにしておきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 結果判定リスト
score = []
for data in test_data:
val = data.split(',')
answer = int(val[0])
res = n_network.query((numpy.asfarray(val[1:]) / 255.0 * 0.99) + 0.01)
# 最大値のものを算出した答えとする
res_max = numpy.argmax(res)
print('正解', answer, '算出した答え', res_max, '=&gt;', '〇' if answer == res_max else '×')

score.append(1 if answer == res_max else 0)

# 正解率
print('# 正解率 # {:5.2f}%'.format(sum(score) / len(score) * 100))

【結果】
結果

現状7割の正解率ですが学習データを増やしたり学習回数、学習率を調整してみます。

これまでは学習データ100個、テストデータ10個で簡単に動作確認してきましたが、今回は学習データ60,000個、テストデータ10,000個を使ってどのくらい正確に手書き文字を認識するかテストします。
おさらいとして、自作した完成版のニューラルネットワークを確認します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import numpy
import scipy.special
# ニューラルネットワーク(完成版)
class neural_network:
# 【初期化】
# 入力層、隠れ層、出力層のノード数を設定する。
def __init__(self, in_node, hid_node, out_node, learn_rate):
self.in_node = in_node # 入力層
self.hid_node = hid_node # 隠れ層
self.out_node = out_node # 出力層
self.learn_rate = learn_rate # 学習率

# 重み行列(処理の核となる)
# 正規分布の平均、標準偏差、配列の大きさを設定
self.weight_in_hid = numpy.random.normal(0.0, pow(self.hid_node, -0.5), (self.hid_node, self.in_node))
self.weight_hid_out = numpy.random.normal(0.0, pow(self.out_node, -0.5), (self.out_node, self.hid_node))

# 活性化関数はシグモイド関数
self.activation_func = lambda x: scipy.special.expit(x)

# 【学習】
# 学習データから重みを調整する。
def train(self, in_list, target_list):
# 入力データ(1次元)を2次元化して転置をとる。
#(横長の配列が縦長になる)
in_matrix = numpy.array(in_list, ndmin=2).T
target_matrix = numpy.array(target_list, ndmin=2).T
# -------------- 重みをかけて発火させる --------------
# 入力層→隠れ層の計算
hid_in = numpy.dot(self.weight_in_hid, in_matrix)
hid_out = self.activation_func(hid_in)

# 隠れ層→出力層の計算
final_in = numpy.dot(self.weight_hid_out, hid_out)
final_out = self.activation_func(final_in)
# -------------- 誤差の計算 --------------
# 出力層の誤差(目標出力 - 最終出力)
out_err = target_matrix - final_out
# 隠れ層の誤差は出力層の誤差をリンクの重みの割合で分配
hid_err = numpy.dot(self.weight_hid_out.T, out_err)
# -------------- 重みの更新(処理の核) --------------
# 隠れ層と出力層の間のリンクの重みを更新
self.weight_hid_out += self.learn_rate * numpy.dot((out_err * final_out * (1.0 - final_out)), numpy.transpose(hid_out))

# 入力層と隠れ層の間のリンクの重みを更新
self.weight_in_hid += self.learn_rate * numpy.dot((hid_err * hid_out * (1.0 - hid_out)), numpy.transpose(in_matrix))

# 【照会】
# 入力に対して出力層からの答えを返す。
def query(self, input_list):
# 入力リストを行列に変換
# 1次元配列は2次元配列に変換し転置をとる。
#(横長の配列が縦長になる)
in_matrix = numpy.array(input_list, ndmin=2).T

# 隠れ層に入ってくる信号の計算(入力層に重みをかける)
hid_in = numpy.dot(self.weight_in_hid, in_matrix)
# 隠れ層で結合された信号を活性化関数(シグモイド関数)により出力
# (閾値を超えたものが発火する)
hid_out = self.activation_func(hid_in)

# 出力層に入ってくる信号の計算(隠れ層に重みをかける)
final_in = numpy.dot(self.weight_hid_out, hid_out)
# 出力層で結合された信号を活性化関数(シグモイド関数)により出力
# (閾値を超えたものが発火する)
final_out = self.activation_func(final_in)

return final_out

次に今回使用する学習データ60,000個とテストデータ10,000個をダウンロードしておきます。

1
2
!wget https://www.pjreddie.com/media/files/mnist_train.csv
!wget https://www.pjreddie.com/media/files/mnist_test.csv

60,000個の学習データを学習率0.2、学習回数(エポック)1回で学習させます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 60,000個のデータを学習
import numpy
import matplotlib.pyplot
%matplotlib inline

in_node = 784 # 入力層のノード数(28 * 28)
hid_node = 200 # 隠れ層のノード数
out_node = 10 # 出力層のノード数(0~9を表す)

learn_rate = 0.2 # 学習率

# ニューラルネットワークのインスタンス生成
n_network = neural_network(in_node, hid_node, out_node, learn_rate)

# 学習データファイルを読み込んでリスト化
with open('mnist_train.csv', 'r') as f:
train_data = f.readlines()

epochs = 1 # 学習回数
for e in range(epochs):
# 学習データすべてに対して実行
for record in train_data:
val = record.split(',')
# 入力値のスケールとシフト
in_data = (numpy.asfarray(val[1:]) / 255.0 * 0.99) + 0.01
# 目標配列の生成(ラベル位置0.99、残り0.01)
target = numpy.zeros(out_node) + 0.01
target[int(val[0])] = 0.99
n_network.train(in_data, target)

10,000個のテストデータで正解率を算出します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 10,000個のテストデータで正解率を算出
with open('mnist_test.csv', 'r') as f:
test_data = f.readlines()

# 結果判定リスト
score = []
for data in test_data:
val = data.split(',')
answer = int(val[0])
res = n_network.query((numpy.asfarray(val[1:]) / 255.0 * 0.99) + 0.01)
# 最大値のものを算出した答えとする
res_max = numpy.argmax(res)

score.append(1 if answer == res_max else 0)

# 正解率
print('# 正解率 # {:5.2f}%'.format(sum(score) / len(score) * 100))

【結果】

1
# 正解率 # 95.38%

正解率をあげるため学習率や学習回数(エポック)を調整しようと考えていたのですが、もうすでに正解率95%以上と十分な正解率(認識率)となっています。
次に正解率がどう変動するのかを確認したいと思います。

学習処理と検証処理を関数化します。引数に学習率を設定すると、その学習率での正解率が返ります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import numpy

# 学習率を変えて、学習・検証ができるように関数化する。
def train_test(learn_rate):
in_node = 784 # 入力層のノード数(28 * 28)
hid_node = 200 # 隠れ層のノード数
out_node = 10 # 出力層のノード数(0~9を表す)

# ニューラルネットワークのインスタンス生成
n_network = neural_network(in_node, hid_node, out_node, learn_rate)

# 学習データファイルを読み込んでリスト化
with open('mnist_train.csv', 'r') as f:
train_data = f.readlines()

epochs = 1 # 学習回数
for e in range(epochs):
# 学習データすべてに対して実行
for record in train_data:
val = record.split(',')
# 入力値のスケールとシフト
in_data = (numpy.asfarray(val[1:]) / 255.0 * 0.99) + 0.01
# 目標配列の生成(ラベル位置0.99、残り0.01)
target = numpy.zeros(out_node) + 0.01
target[int(val[0])] = 0.99
n_network.train(in_data, target)

# 10,000個のテストデータで正解率を算出
with open('mnist_test.csv', 'r') as f:
test_data = f.readlines()

# 結果判定リスト
score = []
for data in test_data:
val = data.split(',')
answer = int(val[0])
res = n_network.query((numpy.asfarray(val[1:]) / 255.0 * 0.99) + 0.01)
# 最大値のものを算出した答えとする
res_max = numpy.argmax(res)
score.append(1 if answer == res_max else 0)

# 正解率
return sum(score) / len(score) * 100

上記で定義した関数を学習率を変化させながら実行し、その結果を折れ線グラフに表示します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
%matplotlib inline
import matplotlib.pyplot as plt

x_data = []
y_data = []
# 0.1から0.9までの学習率で、正解率を算出する。
for i in numpy.arange(0.1, 1, 0.1):
x_data.append(i)
y_data.append(train_test(i))

plt.xlabel("learn_rate") # 学習率
plt.ylabel("accuracy_rate(%)") # 正解率

plt.plot(x_data, y_data, marker='o')
plt.show()

X軸に学習率、Y軸に正解率が表示されます。
結果

上記の結果から学習率が0.1の場合が一番正解率が高いことがわかりました。
次回は学習率を0.1に固定し、学習回数(エポック)を変化させると正解率がどのように変化するかを調べてみます。

さきほど関数化したものの引数に学習回数を追加します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import numpy

# 学習率と学習回数を変えて、学習、検証ができるように関数化する。
def train_test(learn_rate, epochs):
in_node = 784 # 入力層のノード数(28 * 28)
hid_node = 200 # 隠れ層のノード数
out_node = 10 # 出力層のノード数(0~9を表す)

# ニューラルネットワークのインスタンス生成
n_network = neural_network(in_node, hid_node, out_node, learn_rate)

# 学習データファイルを読み込んでリスト化
with open('mnist_train.csv', 'r') as f:
train_data = f.readlines()

for e in range(epochs):
# 学習データすべてに対して実行
for record in train_data:
val = record.split(',')
# 入力値のスケールとシフト
in_data = (numpy.asfarray(val[1:]) / 255.0 * 0.99) + 0.01
# 目標配列の生成(ラベル位置0.99、残り0.01)
target = numpy.zeros(out_node) + 0.01
target[int(val[0])] = 0.99
n_network.train(in_data, target)

# 10,000個のテストデータで正解率を算出
with open('mnist_test.csv', 'r') as f:
test_data = f.readlines()

# 結果判定リスト
score = []
for data in test_data:
val = data.split(',')
answer = int(val[0])
res = n_network.query((numpy.asfarray(val[1:]) / 255.0 * 0.99) + 0.01)
# 最大値のものを算出した答えとする
res_max = numpy.argmax(res)
#print('正解', answer, '算出した答え', res_max, '=&gt;', '〇' if answer == res_max else '×')

score.append(1 if answer == res_max else 0)

# 正解率
#print('# 正解率 # {:5.2f}%'.format(sum(score) / len(score) * 100))
return sum(score) / len(score) * 100

上記で定義した関数を学習回数を変化させながら実行し、その結果を折れ線グラフに表示します。
(学習率は前回もっとも結果のよかった0.1を指定します。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
%matplotlib inline
import matplotlib.pyplot as plt

x_data = []
y_data = []
# 0.1から0.9までの学習率(で、正解率を算出する。
for i in numpy.arange(0.1, 1, 0.1):
x_data.append(i)
y_data.append(train_test(i))

# データをグラフに設定
plt.xlabel("learn_rate") # 学習率
plt.ylabel("accuracy_rate(%)") # 正解率

plt.plot(x_data, y_data, marker='o')
plt.show()

X軸に学習回数、Y軸に正解率が表示されます。
結果

もともと学習回数が1回でも正解率95.75%となかなかの精度がでているのですが、学習回数をふやすとやや結果がよくなっていっているのがわかります。
ただ2%以内の増減なので、処理時間がすごく増える割には効果があるとは思えませんでした。
次回は学習率を0.1、学習回数を5回に固定し、隠れ層の数を変化させると正解率がどのように変化するかを調べてみます。

関数化したものの引数に隠れ層の数を追加します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import numpy

# 学習率と学習回数を変えて、学習、検証ができるように関数化する。
def train_test(learn_rate, epochs, hid_node):
in_node = 784 # 入力層のノード数(28 * 28)
#hid_node = 200 # 隠れ層のノード数
out_node = 10 # 出力層のノード数(0~9を表す)

# ニューラルネットワークのインスタンス生成
n_network = neural_network(in_node, hid_node, out_node, learn_rate)

# 学習データファイルを読み込んでリスト化
with open('mnist_train.csv', 'r') as f:
train_data = f.readlines()

for e in range(epochs):
# 学習データすべてに対して実行
for record in train_data:
val = record.split(',')
# 入力値のスケールとシフト
in_data = (numpy.asfarray(val[1:]) / 255.0 * 0.99) + 0.01
# 目標配列の生成(ラベル位置0.99、残り0.01)
target = numpy.zeros(out_node) + 0.01
target[int(val[0])] = 0.99
n_network.train(in_data, target)

# 10,000個のテストデータで正解率を算出
with open('mnist_test.csv', 'r') as f:
test_data = f.readlines()

# 結果判定リスト
score = []
for data in test_data:
val = data.split(',')
answer = int(val[0])
res = n_network.query((numpy.asfarray(val[1:]) / 255.0 * 0.99) + 0.01)
# 最大値のものを算出した答えとする
res_max = numpy.argmax(res)
#print('正解', answer, '算出した答え', res_max, '=&gt;', '〇' if answer == res_max else '×')

score.append(1 if answer == res_max else 0)

# 正解率
#print('# 正解率 # {:5.2f}%'.format(sum(score) / len(score) * 100))
return sum(score) / len(score) * 100

上記で定義した関数を隠れ層を変化させながら実行し、その結果を折れ線グラフに表示します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 隠れ層と正解率の関係
# 引数に隠れ層数追加 0.1 5 隠れ層 100~700
# 隠れ層をX軸に、正解率をY軸にした折れ線グラフを作成
%matplotlib inline
import matplotlib.pyplot as plt

x_data = []
y_data = []
# 0.1から0.9までの学習率(で、正解率を算出する。
for i in range(100, 701, 100):
x_data.append(i)
y_data.append(train_test(0.1, 5, i))

# データをグラフに設定
plt.xlabel("hidden layer") # 学習回数
plt.ylabel("accuracy_rate(%)") # 正解率

plt.plot(x_data, y_data, marker='o')
plt.show()

X軸に隠れ層の数、Y軸に正解率が表示されます。
結果
100層から200層で1%弱の情報がありますがそれ以降はあまり変化がありません。
これまでに、学習率・学習回数・隠れ層の数と正解率の関係を見てきましたがもともとの正解率が高かったこともありほんとに微調整といった感じです。
このあたりのパラメータ調整は、正解率が低い場合には調整する意味合いが大きくなるかと思います。

(Google Colaboratoryで動作確認しています。)

ニューラルネットワーク(2)

学習メソッドtrainを実装します。前回実装した照会メソッドqueryと似ています。
重みをかけて発火させたあとに目標出力との誤差を算出しそれを学習率に応じて重みに反映する・・・これがニューラルネットワークの最重要ポイントかと思われます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import numpy
import scipy.special

class neural_network:
# 【初期化】
# 入力層、隠れ層、出力層のノード数を設定する。
def __init__(self, in_node, hid_node, out_node, learn_rate):
self.in_node = in_node # 入力層
self.hid_node = hid_node # 隠れ層
self.out_node = out_node # 出力層
self.learn_rate = learn_rate # 学習率

# 重み行列(処理の核となる)
# 正規分布の平均、標準偏差、配列の大きさを設定
self.weight_in_hid = numpy.random.normal(0.0, pow(self.hid_node, -0.5), (self.hid_node, self.in_node))
''' ↓こんな感じの配列ができる
[[ 0.37395332 0.07296579 0.36696637]
[-0.1570748 0.28908756 0.99958053]
[-0.09054778 -0.20084478 0.31981826]]
'''
self.weight_hid_out = numpy.random.normal(0.0, pow(self.out_node, -0.5), (self.out_node, self.hid_node))
''' ↓こんな感じの配列ができる
[[ 0.93304259 0.02641947 0.29506316]
[-0.74275445 0.9010841 -0.47840667]
[ 0.04494529 0.49177323 1.13985481]]
'''

# 活性化関数はシグモイド関数
self.activation_func = lambda x: scipy.special.expit(x)

# 【学習】
# 学習データから重みを調整する。
def train(self, in_list, target_list):
# 入力データ(1次元)を2次元化して転置をとる。
#(横長の配列が縦長になる)
in_matrix = numpy.array(in_list, ndmin=2).T
target_matrix = numpy.array(target_list, ndmin=2).T
# -------------- 重みをかけて発火させる --------------
# 入力層→隠れ層の計算
hid_in = numpy.dot(self.weight_in_hid, in_matrix)
hid_out = self.activation_func(hid_in)

# 隠れ層→出力層の計算
final_in = numpy.dot(self.weight_hid_out, hid_out)
final_out = self.activation_func(final_in)
# -------------- 誤差の計算 --------------
# 出力層の誤差(目標出力 - 最終出力)
out_err = target_matrix - final_out
# 隠れ層の誤差は出力層の誤差をリンクの重みの割合で分配
hid_err = numpy.dot(self.weight_hid_out.T, out_err)
# -------------- 重みの更新(処理の核) --------------
# 隠れ層と出力層の間のリンクの重みを更新
self.weight_hid_out += self.learn_rate * numpy.dot((out_err * final_out * (1.0 - final_out)), numpy.transpose(hid_out))

# 入力層と隠れ層の間のリンクの重みを更新
self.weight_in_hid += self.learn_rate * numpy.dot((hid_err * hid_out * (1.0 - hid_out)), numpy.transpose(in_matrix))

# 【照会】
# 入力に対して出力層からの答えを返す。
def query(self, input_list):
# 入力リストを行列に変換
# 1次元配列は2次元配列に変換し転置をとる。
#(横長の配列が縦長になる)
in_matrix = numpy.array(input_list, ndmin=2).T

# 隠れ層に入ってくる信号の計算(入力層に重みをかける)
hid_in = numpy.dot(self.weight_in_hid, in_matrix)
# 隠れ層で結合された信号を活性化関数(シグモイド関数)により出力
# (閾値を超えたものが発火する)
hid_out = self.activation_func(hid_in)

# 出力層に入ってくる信号の計算(隠れ層に重みをかける)
final_in = numpy.dot(self.weight_hid_out, hid_out)
# 出力層で結合された信号を活性化関数(シグモイド関数)により出力
# (閾値を超えたものが発火する)
final_out = self.activation_func(final_in)

return final_out

これで自作ニューラルネットワークが完成しました。
このクラスを使ってMNISTデータの判定を行ってみます。

まず、学習データ(100種類)とテストデータ(10種類)をダウンロードします。

1
2
!wget https://raw.githubusercontent.com/makeyourownneuralnetwork/makeyourownneuralnetwork/master/mnist_dataset/mnist_test_10.csv
!wget https://raw.githubusercontent.com/makeyourownneuralnetwork/makeyourownneuralnetwork/master/mnist_dataset/mnist_train_100.csv</pre>

データを読み込んで、どんなデータか表示してみます。

1
2
3
4
5
6
7
8
9
10
import numpy
import matplotlib.pyplot
%matplotlib inline

with open('mnist_train_100.csv', 'r') as f:
data_list = f.readlines()

val = data_list[7].split(',') # データを選ぶ(0-99の間)
img = numpy.asfarray(val[1:]).reshape((28, 28))
matplotlib.pyplot.imshow(img, cmap='Greys', interpolation='None')

結果

データを学習し、テストデータの1つを選んでどの数字と合致する確率が高いかを表示します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import numpy
import matplotlib.pyplot
%matplotlib inline

in_node = 784 # 入力層のノード数(28 * 28)
hid_node = 200 # 隠れ層のノード数
out_node = 10 # 出力層のノード数(0~9を表す)

learn_rate = 0.2 # 学習率

# ニューラルネットワークのインスタンス生成
n_network = neural_network(in_node, hid_node, out_node, learn_rate)

# 学習データファイルを読み込んでリスト化
with open('mnist_train_100.csv', 'r') as f:
train_data = f.readlines()

# 全学習データを10回学習
epochs = 10 # 学習回数
for e in range(epochs):
# 学習データすべてに対して実行
for record in train_data:
val = record.split(',')
# 入力値のスケールとシフト
in_data = (numpy.asfarray(val[1:]) / 255.0 * 0.99) + 0.01
# 目標配列の生成(ラベル位置0.99、残り0.01)
target = numpy.zeros(out_node) + 0.01
target[int(val[0])] = 0.99
n_network.train(in_data, target)

# テストデータファイルを読み込んでリスト化
with open('mnist_test_10.csv', 'r') as f:
test_data = f.readlines()

val = test_data[0].split(',') # テストデータを選択(0-9の間)
img = numpy.asfarray(val[1:]).reshape((28, 28))
matplotlib.pyplot.imshow(img, cmap='Greys', interpolation='None')

# 選択したデータをニューラルネットワークで照会
res = n_network.query((numpy.asfarray(val[1:]) / 255.0 * 0.99) + 0.01)
for a,b in enumerate(res):
print('{}の可能性 {:5.2f}%'.format(a,b[0] * 100))

結果

今回は[7]の合致率が97%以上ときちんと認識しているようです。
10種類あるテストデータをすべて試してみましたが、なかなかよい結果がでてました。
ただ人間でもよくわからないデータ(手書き数字)だとはっきり認識するのは難しいようです。(あたり前か・・・)

隠れ層のノード数、学習率、学習回数の範囲をいろいろ試してみて認識率がどうかわるかを試すのもよいかと思います。

(Google Colaboratoryで動作確認しています。)

ニューラルネットワーク(1)

ニューラルネットワークを試してみます。
まずは、基本メソッド、各層の数と学習率をもつニューラルネットワーククラスを定義します。
中身はなにもありませんが、これがニューラルネットワーク・クラスの骨格となります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# ニューラルネットワークを表すクラス
class neural_network:
# 【初期化】
# 入力層、隠れ層、出力層のノード数を設定する。
def __init__(self, in_node, hid_node, out_node, learn_rate):
self.in_node = in_node # 入力層
self.hid_node = hid_node # 隠れ層
self.out_node = out_node # 出力層
self.learn_rate = learn_rate # 学習率

# 【学習】
# 学習データから重みを調整する。
def train():
pass

# 【照会】
# 入力に対して出力層からの答えを返す。
def query():
pass

このクラスに少しずつ実装していきます。

初期化のところで重みを生成し、活性化関数にシグモイド関数を設定してます。
また照会メソッドで、入力に対し入力・隠れ層の重みをかけシグモイド関数で発火させます。
さらにその結果に隠れ・出力層の重みをかけシグモイド関数で発火させ、その結果を返しています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import numpy
import scipy.special
# Pythonでニューラルネットワーク(3)
class neural_network:
# 【初期化】
# 入力層、隠れ層、出力層のノード数を設定する。
def __init__(self, in_node, hid_node, out_node, learn_rate):
self.in_node = in_node # 入力層
self.hid_node = hid_node # 隠れ層
self.out_node = out_node # 出力層
self.learn_rate = learn_rate # 学習率

# 重み行列(処理の核となる)
# 正規分布の平均、標準偏差、配列の大きさを設定
self.weight_in_hid = numpy.random.normal(0.0, pow(self.hid_node, -0.5), (self.hid_node, self.in_node))
''' ↓こんな感じの配列ができる
[[ 0.37395332 0.07296579 0.36696637]
[-0.1570748 0.28908756 0.99958053]
[-0.09054778 -0.20084478 0.31981826]]
'''
self.weight_hid_out = numpy.random.normal(0.0, pow(self.out_node, -0.5), (self.out_node, self.hid_node))
''' ↓こんな感じの配列ができる
[[ 0.93304259 0.02641947 0.29506316]
[-0.74275445 0.9010841 -0.47840667]
[ 0.04494529 0.49177323 1.13985481]]
'''

# 活性化関数はシグモイド関数
self.activation_func = lambda x: scipy.special.expit(x)

# 【学習】
# 学習データから重みを調整する。
def train():
pass

# 【照会】
# 入力に対して出力層からの答えを返す。
def query(self, input_list):
# 入力リストを行列に変換
# 1次元配列は2次元配列に変換し転置をとる。
#(横長の配列が縦長になる)
in_matrix = numpy.array(input_list, ndmin=2).T

# 隠れ層に入ってくる信号の計算(入力層に重みをかける)
hid_in = numpy.dot(self.weight_in_hid, in_matrix)
# 隠れ層で結合された信号を活性化関数(シグモイド関数)により出力
# (閾値を超えたものが発火する)
hid_out = self.activation_func(hid_in)

# 出力層に入ってくる信号の計算(隠れ層に重みをかける)
final_in = numpy.dot(self.weight_hid_out, hid_out)
# 出力層で結合された信号を活性化関数(シグモイド関数)により出力
# (閾値を超えたものが発火する)
final_out = self.activation_func(final_in)

return final_out

上記で定義したクラスが問題なく動くか、テストするコードを簡単に書いて実行してみます。

1
2
3
4
5
6
7
8
9
10
11
in_node = 3       # 入力層のノード数
hid_node = 3 # 隠れ層のノード数
out_node = 3 # 出力層のノード数

learn_rate = 0.3 # 学習率

# ニューラルネットワークのインスタンス生成
n_network = neural_network(in_node, hid_node, out_node, learn_rate)

# まだ学習してないけど照会してみる
n_network.query([1.0, 0.5, -1.5])

【結果】

1
2
3
array([[0.55799198],
[0.51430992],
[0.30202192]])

まだ学習するメソッドを実装していないので意味のない出力ではありますが、エラーなしで動作することを確認できました。
次回は学習メソッドを実装していきます。

(Google Colaboratoryで動作確認しています。)

機械学習に関する用語集

機械学習に関する用語

用語 英語 説明
教師あり学習 Supervised Learning 正解となるデータをもとに機械学習を行う手法。データの分類や数値の予測などに使用する。
教師なし学習 Unsupervised Learning 正解が用意されていないデータに対して行う手法。データのクラスタリングなどに使用する。
強化学習 Reinforcement Learning ある環境の中での行動に対して報酬を与えて学習させる手法。ゲームや自動運転などにおいて、振る舞いを最適化するために使用する。
分類 Classification 教師あり学習でデータがどのグループに属するか(ラベル)を予測すること。
回帰 Rgression 教師あり学習でデータに対して数値を予測すること。
クラスタリング Clustering 教師なし学習で、似ているデータをグループ化すること。分類とは異なり正解が存在しない。
アルゴリズム Algorithm 機械学習ではそれぞれの機械学習を行うための手順のことを指す。主要なアルゴリズムはscikit-learnで用意されている。
アンサンブル学習 Ensemble Learning 複数のモデルの結果を組み合わせて多数決などで決定する手法。
ラベル Label 分類で、データの正解を表す値。
モデル Model 機械学習アルゴリズムが作成した予測を行うためのパラメータの集まり。予測プログラムで使用する。

教師あり学習の主な手法

用語 英語 説明
線形回帰 Linear Regression 回帰に使用するアルゴリズムの1つ。
ロジスティック回帰 Logistic Regression アルゴリズムの名前には回帰が付いているが、主に分類に使用するアルゴリズム。
サポートベクターマシン Support Vector Machine : SVM 分類、回帰に使用できるアルゴリズム。
決定木 Decision Tree データを分類するルールを定義して分類を行うアルゴリズム。
ランダムフォレスト Random Forest 複数の決定木の予測結果から、多数決で予測を行うアルゴリズム。アンサンブル学習の1つ。

精度に関する用語

用語 英語 説明
学習データ Data 学習済みモデルを作成するための機械学習アルゴリズムの入力に使用するデータの集まり。あらかじめ用意したデータを学習データとテストデータに分割する。教師データ、訓練データともいう。
テストデータ Test Data モデルの精度評価を行うために使用するデータ。
混合行列 Confusion Matrix 分類の制度を計算するために予測と正解の組み合わせを集計した表。
陽性 Positive 分類で目的としているデータの持つ性質。
陰性 Negative 分類で目的としていないデータの持つ性質。
真陽性 True Positive : TP 陽性と予測して(Positive)、予測が当たった(True)データの性質。
偽陽性 False Positive : FP 陽性と予測して(Positive)、予測が外れた(False)データの性質。
偽陰性 False Negative : FN 陰性と予測して(Negative)、予測が外れた(False)データの性質。
真陰性 True Negative : TN 陰性と予測して(Negative)、予測が当たった(True)データの性質。
正解率 Accuracy 全体のうち予測当たった割合。(TP + TN) / (TP + FP + FN + TN)
適合性 Precision 陽性と予測したうち実際に陽性だった割合。TP / (TP + FP)
再現率 Recall 陽性のデータのうち、陽性と予測した割合。TP / (TP + FN)
F値 F-Value 適合率と再現率のバランスをとった値。適合率と再現率の調和平均で求める。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×