機械学習手書きデジタル認識(人工神経ネットワークPython実現)
本論文は「Python神経ネットワークプログラミング」の関連章節を参照してください.
今人気のあるマシン学習データ集は手書きデジタルデータ集(MNIST)です.
このウェブサイトは二つのCSVファイルを提供しています.
練習セット:http://www.pjreddie.com/media/files/mnist_train.csv
テストセット:http://www.pjreddie.com/media/files/mnist_test.csv
トレーニングセットには600個のマークサンプルがあります.テストセットには10000個のマークサンプルがあります.テスト用です.
以下のウェブサイトは二つの小さいデータセットを提供しています.私達はデバッグプログラムの過程で彼らを使うことができます.
練習セット:https://raw.githubusercontent.com/makeyourownneuralnetwork/makeyourownneuralnetwork/master/mnist_dataset/mnist_トレイ100. csv
テストセット:https://raw.githubusercontent.com/makeyourownneuralnetwork/makeyourownneuralnetwork/master/mnist_dataset/mnist_test_10.csv
ファイルを開くと、次のようになります.
これは一例のデータで、最初の値はこの例のラベル(ここでは7)で、残りのデータは手書きのデジタル画像の各ピクセルポイントの色の値です.したがって、各値の取得範囲は0~255で、その数は28*28の784個です.
階調変化を用いて手書きの数字を表示します.Pythonコードは以下の通りです.
大丈夫です 階調表示で手書きの数字を見ることができます.
手書きの数字の識別方法の中で有名なK近隣(KNN)アルゴリズムは非常に簡単であり、識別効果も優れていますが、今日はこの方法を使用しません.神経ネットワークを使用します.
前のブログはすでに成熟した神経ネットワークモデルを構築しています.直接使用できます.今解決したい唯一の問題は、神経ネットワークの各層の結点個数です.
入力層、隠蔽層:入力層と隠蔽層の接合点数は同じ値をとり、各ピクセルポイントは一つの入力なので、28*28の合計784個があるはずです.
出力層:全部で10の中で可能な判断(0~9)があります.私達はコードの思想で10の結点を設定して、1に出力するその結点の位置は予測ラベルを表しています.すなわち[0,1,0,0,0,0,0,0,0,0,0,0,0]は予測1を表しています.
今はもう私たちの神経ネットワークを訓練し始めましたが、いくつかの細かい点に注意してください.
一:入力したデータ
私たちはデータをより小さい範囲(データのスケーリング)に調整したいです.ここではデータスケーリングがモデルトレーニングに与える影響を紹介しません.興味がある方は自分で関連記事を調べてください.
ここではデータを0.01~10の範囲に拡大して、0.01を最低点として選びます.0入力が重みの更新に影響がないことを避けます.
すべてのデータの取得範囲は0~255ですので、すべてのデータを255で割って0~1の入力となります.0.99で0~0.99の入力となり、最後に0.01を加えて、0.01~1.00の入力となります.
二:重みの初期化
次のレイヤーの接合点の始点を標準分散として使用して重みを初期化します.
三:歩幅
歩幅の選択は理論的には小さいほどいいですが、小さい歩幅ほど必要な訓練回数が多くなります.だから私達は適切な歩幅を選びたいです.トレーニング回数の下で最適になります.しかも変動は大きすぎません.
ここでは0.3のステップを選んで,ステップ長の選択には明確な方法がなく,実験で相対的に適切なステップサイズを決定するしかない.
Pythonの実現を見てみましょう.
コードとデータセットはすでに私のリソースにアップロードされました.https://download.csdn.net/download/qq_4139888/11232343
ファイル読み込み:
タブを変更([0,0,1,0,0,0,0,0,0,0,0,0]の形に変更):
活性化関数については、0,1の出力を生成することは不可能であり、大きな重みと飽和ネットワークの出現をもたらすので、0の代わりに0.01を使用し、0.99を使用します.
アクティブ関数のsigmoidはscipyライブラリの中のexpit(x)関数を使って、ネットでその運行速度が速くなると伝えています.結局60000サンプルです.私のコンピュータトレーニングは一回に少なくとも25分かかります.
パラメータ初期化:
トレーニングを開始する(トレーニングプロセスには何の修正も必要ではない):
テストプロセス:
10個の出力のうち0.5以上が0.5以上でない場合がありますので、予測ラベルとして10個の出力の中で最大の位置を探しています.
私たちは訓練されたパラメータをファイル形式で保存してもいいです.その後は直接使ってもいいです.もう一回訓練する必要はないです.訓練されたパラメータファイルも私のリソースにアップロードします.
最後に私達のテストセットでの予測の正確性は次の通りです.
今人気のあるマシン学習データ集は手書きデジタルデータ集(MNIST)です.
このウェブサイトは二つのCSVファイルを提供しています.
練習セット:http://www.pjreddie.com/media/files/mnist_train.csv
テストセット:http://www.pjreddie.com/media/files/mnist_test.csv
トレーニングセットには600個のマークサンプルがあります.テストセットには10000個のマークサンプルがあります.テスト用です.
以下のウェブサイトは二つの小さいデータセットを提供しています.私達はデバッグプログラムの過程で彼らを使うことができます.
練習セット:https://raw.githubusercontent.com/makeyourownneuralnetwork/makeyourownneuralnetwork/master/mnist_dataset/mnist_トレイ100. csv
テストセット:https://raw.githubusercontent.com/makeyourownneuralnetwork/makeyourownneuralnetwork/master/mnist_dataset/mnist_test_10.csv
ファイルを開くと、次のようになります.
これは一例のデータで、最初の値はこの例のラベル(ここでは7)で、残りのデータは手書きのデジタル画像の各ピクセルポイントの色の値です.したがって、各値の取得範囲は0~255で、その数は28*28の784個です.
階調変化を用いて手書きの数字を表示します.Pythonコードは以下の通りです.
import numpy as np
from matplotlib import pyplot as plt
data_file = open('mnist_test_10.csv', 'r')
data_list = data_file.readlines()
data_file.close()
all_values = data_list[0].split(',')
image_array = np.array(all_values[1:]).astype(np.int).reshape((28, 28))
plt.imshow(image_array, cmap = 'Greys', interpolation = 'None')
plt.show()
大丈夫です 階調表示で手書きの数字を見ることができます.
手書きの数字の識別方法の中で有名なK近隣(KNN)アルゴリズムは非常に簡単であり、識別効果も優れていますが、今日はこの方法を使用しません.神経ネットワークを使用します.
前のブログはすでに成熟した神経ネットワークモデルを構築しています.直接使用できます.今解決したい唯一の問題は、神経ネットワークの各層の結点個数です.
入力層、隠蔽層:入力層と隠蔽層の接合点数は同じ値をとり、各ピクセルポイントは一つの入力なので、28*28の合計784個があるはずです.
出力層:全部で10の中で可能な判断(0~9)があります.私達はコードの思想で10の結点を設定して、1に出力するその結点の位置は予測ラベルを表しています.すなわち[0,1,0,0,0,0,0,0,0,0,0,0,0]は予測1を表しています.
今はもう私たちの神経ネットワークを訓練し始めましたが、いくつかの細かい点に注意してください.
一:入力したデータ
私たちはデータをより小さい範囲(データのスケーリング)に調整したいです.ここではデータスケーリングがモデルトレーニングに与える影響を紹介しません.興味がある方は自分で関連記事を調べてください.
ここではデータを0.01~10の範囲に拡大して、0.01を最低点として選びます.0入力が重みの更新に影響がないことを避けます.
すべてのデータの取得範囲は0~255ですので、すべてのデータを255で割って0~1の入力となります.0.99で0~0.99の入力となり、最後に0.01を加えて、0.01~1.00の入力となります.
二:重みの初期化
次のレイヤーの接合点の始点を標準分散として使用して重みを初期化します.
三:歩幅
歩幅の選択は理論的には小さいほどいいですが、小さい歩幅ほど必要な訓練回数が多くなります.だから私達は適切な歩幅を選びたいです.トレーニング回数の下で最適になります.しかも変動は大きすぎません.
ここでは0.3のステップを選んで,ステップ長の選択には明確な方法がなく,実験で相対的に適切なステップサイズを決定するしかない.
Pythonの実現を見てみましょう.
コードとデータセットはすでに私のリソースにアップロードされました.https://download.csdn.net/download/qq_4139888/11232343
ファイル読み込み:
def loaddataset(filename):
fp = open(filename, 'r')
dataset = []
labelset = []
for i in fp.readlines():
a = i.strip().split(',')
#
dataset.append([(int(j) / 255.0 * 0.99 + 0.01) for j in a[1:]])
labelset.append(int(a[0]))
return np.array(dataset), np.array(labelset)
タブを変更([0,0,1,0,0,0,0,0,0,0,0,0]の形に変更):
活性化関数については、0,1の出力を生成することは不可能であり、大きな重みと飽和ネットワークの出現をもたらすので、0の代わりに0.01を使用し、0.99を使用します.
def adjustment_label(labelset):
new_labelset = []
for i in labelset:
new_label = [0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01]
new_label[i] = 0.99
new_labelset.append(new_label)
return new_labelset
アクティブ関数のsigmoidはscipyライブラリの中のexpit(x)関数を使って、ネットでその運行速度が速くなると伝えています.結局60000サンプルです.私のコンピュータトレーニングは一回に少なくとも25分かかります.
import scipy.special as spc
def sigmoid(z):
return spc.expit(z)
パラメータ初期化:
def parameter_initialization(x, y, z):
value1 = np.random.normal(0.0, pow(1, -0.5), (1, y))
value2 = np.random.normal(0.0, pow(1, -0.5), (1, z))
weight1 = np.random.normal(0.0, pow(x, -0.5), (x, y))
weight2 = np.random.normal(0.0, pow(y, -0.5), (y, z))
return weight1, weight2, value1, value2
トレーニングを開始する(トレーニングプロセスには何の修正も必要ではない):
def trainning(dataset, labelset, weight1, weight2, value1, value2, x):
for i in range(len(dataset)):
print(i)
inputset = np.mat(dataset[i])
outputset = np.mat(labelset[i])
input1 = np.dot(inputset, weight1)
output2 = sigmoid(input1 - value1)
input2 = np.dot(output2, weight2)
output3 = sigmoid(input2 - value2)
a = np.multiply(output3, 1 - output3)
g = np.multiply(a, outputset - output3)
b = np.dot(g, np.transpose(weight2))
c = np.multiply(output2, 1 - output2)
e = np.multiply(b, c)
value1_change = -x * e
value2_change = -x * g
weight1_change = x * np.dot(np.transpose(inputset), e)
weight2_change = x * np.dot(np.transpose(output2), g)
value1 += value1_change
value2 += value2_change
weight1 += weight1_change
weight2 += weight2_change
return weight1, weight2, value1, value2
テストプロセス:
10個の出力のうち0.5以上が0.5以上でない場合がありますので、予測ラベルとして10個の出力の中で最大の位置を探しています.
def testing(dataset, labelset, weight1, weight2, value1, value2):
rightcount = 0
for i in range(len(dataset)):
inputset = np.mat(dataset[i])
outputset = np.mat(labelset[i])
input1 = np.dot(inputset, weight1)
output2 = sigmoid(input1 - value1)
input2 = np.dot(output2, weight2)
output3 = sigmoid(input2 - value2)
label = np.argmax(output3)
if int(label) == int(labelset[i]):
rightcount += 1
print(" %d, %d"%(labelset[i], label))
print(" %f"%(rightcount / len(dataset)))
np.argmax()は、行ベクトルの最大値の位置を返します.私たちは訓練されたパラメータをファイル形式で保存してもいいです.その後は直接使ってもいいです.もう一回訓練する必要はないです.訓練されたパラメータファイルも私のリソースにアップロードします.
最後に私達のテストセットでの予測の正確性は次の通りです.
0.953000
[Finished in 1005.7s]
結果はかなりいいです.適切に歩幅を小さくして、練習回数を増やして正確率を上げることができます.私は実現しません.