BPニューラルネットワークが手書き数字認識を実現

BPニューラルネットワークが手書き数字認識を実現

完全なコードは最後にあり
ます1.パッケージをインポートします

import numpy as np
from sklearn.datasets import load_digits
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report,confusion_matrix
import matplotlib.pyplot as plt

ピクセル値はdigits.data.shapeから取得できます。ここでの出力は、1797枚の画像があり、各画像が64ピクセルであるため、64個の入力があることを示しています。タグの値はdigits.targetに格納され、値は0〜9です。ここに画像の説明を挿入します

2.データをインポートします

digits = load_digits()
# 数据 图片的灰度信息存在digits.data中
X = digits.data
# 标签 
y = digits.target

3.ニューラルネットワーク
64-100-10、つまり、入力層に64個のニューロン、100個の隠れ層、10個の出力層を定義します。入力層にバイアスがないのはなぜですかx 0 = 1 x_0 = 1バツ0=1.個人的な理解では、各画像にデータを追加してもトレーニング結果にはほとんど影響がなく、画像にピクセルを追加するのはあまり便利ではありませんか?

# 定义神经网络64-100-10,64像素即64通道输入,隐藏层稍多于输入层,输出层为0-9,所以是10个
# 输入层到隐藏层v,隐藏层到输出层w
V = np.random.random((64,100)) * 2 - 1
W = np.random.random((100,10)) * 2 - 1

4.データのセグメンテーションデータの
一部をテスト用に、一部をトレーニング用に数字で使用し
ます関数train_test_split()を使用します

# 数据切分 train_test_split(X,y)可以把输入数据和标签数据切分为训练集和测试集
# default: 1/4测试集,3/4训练集
X_train,X_test,y_train,y_test = train_test_split(X,y)

5.ラベルの2値化(1つのホットエンコーディング)
ニューラルネットワークの出力は0、1のみであり、0、1、2、3、4を直接表すことはできません...したがって、分類問題は2値化する必要があります
0→1000000003
→001000009
→ 000000001

# 标签二值化
# 0->100000000
# 3->001000000
# 9->000000001
label_train = LabelBinarizer().fit_transform(y_train)

6.活性化関数
定義するsidmoid関数を活性化関数として使用します

# 激活函数
def sigmoid(x):
    return 1/(1+np.exp(-x))
def dsigmoid(x):
    s = 1/(1+np.exp(-x))
    return s*(1-s)

7.トレーニングモデル
トレーニング関数にトレーニングセットを与え、このトレーニングの入力xとしてトレーニングセットからデータをランダムに抽出し、BPアルゴリズムに従って重みを更新します。
正解率は、トレーニングの1000回ごとに計算されます。計算方法は、テストセットを入力として受け取り、予測関数を呼び出し、現在のトレーニング回数でニューロン出力L 2L_2を返すことです。L2L 2 L_2L2これは、0から1までの値を持つ10次元のベクトルです。最大値は1と見なされ、その位置がフィルターで除外され、テストセットのラベル値と比較され、平均値が取得されます。正確さ。

x = np.atleast_2d(x)は、実際にはxを1次元行列に変換しています。これは、x自体がリストであり、行列演算を実行できず、行列の乗算を行うには1次元行列である必要があるためです。

# 训练模型
def train(X,y,Steps = 10000,lr = 0.12):
    global W,V
    for n in range(Steps):
        # 随机选取一个数据
        i = np.random.randint(X.shape[0])
        x = X[i]
        # 把数据变为2维数据,一维数据不能矩阵乘法
        # ?????????
        x = np.atleast_2d(x)
        
        # BP算法公式
        L1 = sigmoid(np.dot(x,V))
        L2 = sigmoid(np.dot(L1,W))
        
        # 学习信号
        L2_delta = (y[i]-L2)*dsigmoid(np.dot(L1,W))
        L1_delta = np.dot(L2_delta,W.T)*dsigmoid(np.dot(x,V))
        
        # 更新权值
        W += lr*np.dot(L1.T,L2_delta)
        V += lr*np.dot(x.T,L1_delta)
        
        #每训练1000次预测一次准确率
        if n%1000 == 0:
            output = predict(X_test)
            # predictions:最大值所在位置(0-9)->预测的标签值
            predictions = np.argmax(output,axis = 1)
            acc = np.mean(np.equal(predictions,y_test))
            print("steps:",n,"accuracy:",acc)
def predict(x):
    L1 = sigmoid(np.dot(x,V))
    L2 = sigmoid(np.dot(L1,W))
    return L2

8.20000回トレーニングする

train(X_train,label_train,20000)

完全なコードと結果

import numpy as np
from sklearn.datasets import load_digits
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report,confusion_matrix
import matplotlib.pyplot as plt

digits = load_digits()
# 数据 图片的灰度信息存在digits.data中
X = digits.data
# 标签 
y = digits.target

# 定义神经网络64-100-10,64像素即64通道输入,隐藏层稍多于输入层,输出层为0-9,所以是10个
# 输入层到隐藏层v,隐藏层到输出层w
V = np.random.random((64,100)) * 2 - 1
W = np.random.random((100,10)) * 2 - 1

# 数据切分 train_test_split(X,y)可以把输入数据和标签数据切分为训练集和测试集
# default: 1/4测试集,3/4训练集
X_train,X_test,y_train,y_test = train_test_split(X,y)

# 标签二值化
# 0->100000000
# 3->001000000
# 9->000000001
label_train = LabelBinarizer().fit_transform(y_train)

# 激活函数
def sigmoid(x):
    return 1/(1+np.exp(-x))
def dsigmoid(x):
    s = 1/(1+np.exp(-x))
    return s*(1-s)

# 训练模型
def train(X,y,Steps = 10000,lr = 0.12):
    global W,V
    for n in range(Steps):
        # 随机选取一个数据
        i = np.random.randint(X.shape[0])
        x = X[i]
        # 把数据变为2维数据,一维数据不能矩阵乘法
        # ?????????
        x = np.atleast_2d(x)
        
        # BP算法公式
        L1 = sigmoid(np.dot(x,V))
        L2 = sigmoid(np.dot(L1,W))
        
        # 学习信号
        L2_delta = (y[i]-L2)*dsigmoid(np.dot(L1,W))
        L1_delta = np.dot(L2_delta,W.T)*dsigmoid(np.dot(x,V))
        
        # 更新权值
        W += lr*np.dot(L1.T,L2_delta)
        V += lr*np.dot(x.T,L1_delta)
        
        #每训练1000次预测一次准确率
        if n%1000 == 0:
            output = predict(X_test)
            # predictions:最大值所在位置(0-9)->预测的标签值
            predictions = np.argmax(output,axis = 1)
            acc = np.mean(np.equal(predictions,y_test))
            print("steps:",n,"accuracy:",acc)
def predict(x):
    L1 = sigmoid(np.dot(x,V))
    L2 = sigmoid(np.dot(L1,W))
    return L2

train(X_train,label_train,20000)

結果

steps: 0 accuracy: 0.06888888888888889
steps: 1000 accuracy: 0.6066666666666667
steps: 2000 accuracy: 0.7733333333333333
steps: 3000 accuracy: 0.8022222222222222
steps: 4000 accuracy: 0.8222222222222222
steps: 5000 accuracy: 0.8488888888888889
steps: 6000 accuracy: 0.84
steps: 7000 accuracy: 0.86
steps: 8000 accuracy: 0.8422222222222222
steps: 9000 accuracy: 0.86
steps: 10000 accuracy: 0.8666666666666667
steps: 11000 accuracy: 0.8533333333333334
steps: 12000 accuracy: 0.8666666666666667
steps: 13000 accuracy: 0.8644444444444445
steps: 14000 accuracy: 0.8644444444444445
steps: 15000 accuracy: 0.8688888888888889
steps: 16000 accuracy: 0.9044444444444445
steps: 17000 accuracy: 0.94
steps: 18000 accuracy: 0.9444444444444444
steps: 19000 accuracy: 0.94

おすすめ

転載: blog.csdn.net/weixin_44823313/article/details/112427745