柚子快報(bào)激活碼778899分享:手寫神經(jīng)網(wǎng)絡(luò)實(shí)現(xiàn)手寫數(shù)字識(shí)別
柚子快報(bào)激活碼778899分享:手寫神經(jīng)網(wǎng)絡(luò)實(shí)現(xiàn)手寫數(shù)字識(shí)別
一、網(wǎng)絡(luò)結(jié)構(gòu)
?????? 一個(gè)輸入層,兩個(gè)隱藏層,一個(gè)輸出層。輸入層有64個(gè)神經(jīng)元,第一個(gè)隱藏層有256個(gè)神經(jīng)元,第二個(gè)隱藏層有64個(gè)神經(jīng)元,最終的輸出層有10個(gè)神經(jīng)元。
二、處理數(shù)據(jù)集
2.1 數(shù)據(jù)集介紹
采用的手寫數(shù)字?jǐn)?shù)據(jù)集是從sk-learn庫(kù)里直接加載的。
digits = load_digits
2.2 數(shù)據(jù)集預(yù)處理
1、先把數(shù)據(jù)和標(biāo)簽分別拿出來(lái):
?????? data=digits.data ?????? ?#這里的data是64維的,8*8
labels=digits.target??? #labels是10類
2、標(biāo)準(zhǔn)化一下輸入
?????? scaler = StandardScaler()
data = scaler.fit_transform(data) ???# 數(shù)據(jù)預(yù)處理:標(biāo)準(zhǔn)化輸入特征
3、構(gòu)造訓(xùn)練集和測(cè)試集
# 將數(shù)據(jù)集劃分為訓(xùn)練集和測(cè)試集
#這里是按照8/2分?jǐn)?shù)據(jù)集,隨機(jī)生成(0,1)內(nèi)的隨機(jī)數(shù),隨機(jī)數(shù)小于0.8,就放到訓(xùn)練集,大于等于0.8就放到測(cè)試集里。得到訓(xùn)練集和測(cè)試集的數(shù)據(jù)以及標(biāo)簽。
4、獨(dú)熱編碼
?????? 因?yàn)槭嵌喾诸悊?wèn)題,所以對(duì)標(biāo)簽采用獨(dú)熱編碼
# 將標(biāo)簽進(jìn)行獨(dú)熱編碼,標(biāo)簽對(duì)應(yīng)值的位置為1,其余位置為0
三、定義網(wǎng)絡(luò)結(jié)構(gòu)以及網(wǎng)絡(luò)初始化
1、網(wǎng)絡(luò)結(jié)構(gòu)
2、初始化權(quán)重和偏置
這里需要初始化的參數(shù)各層之間的權(quán)重和偏置,輸入到第一個(gè)隱藏層,第一個(gè)隱藏層到第二個(gè)隱藏層,第二個(gè)隱藏層到輸出層。采用的是高斯初始化,均值為0,方差為0.01,大小就是每層之間的參數(shù)。
3、定義激活函數(shù)、激活函數(shù)的導(dǎo)數(shù)以及交叉熵?fù)p失函數(shù)
四、訓(xùn)練網(wǎng)絡(luò)
1、設(shè)置超參數(shù)
學(xué)習(xí)率為0.01,訓(xùn)練輪次為500次,采用小批量梯度下降法,批量大小為16。
2、打亂訓(xùn)練集
3、前向傳播
?????? 先獲取當(dāng)前批次大小的數(shù)據(jù)集,然后前向傳播,輸入層的數(shù)據(jù)就是批次大小數(shù)據(jù),得到第一個(gè)隱藏層的輸入為X_batch和權(quán)重做點(diǎn)積再加上偏置,再通過(guò)sigmoid函數(shù),得到第一個(gè)隱藏層的輸出。以此類推,知道輸出層。
4、計(jì)算損失函數(shù)
?????? 用的交叉熵?fù)p失函數(shù)
5、反向傳播
?????? 從后往前,先計(jì)算誤差函數(shù),再求出對(duì)權(quán)重和偏置的梯度大小,再用梯度去反向更新權(quán)重和偏置。
6、打印損失
五、評(píng)估模型
用測(cè)試集評(píng)估模型的性能,把測(cè)試集放到網(wǎng)絡(luò)中前向傳播一遍,得到輸出結(jié)果,對(duì)比標(biāo)簽值,從而計(jì)算準(zhǔn)確率。
?????? 每10個(gè)epoch繪制一下loss曲線、訓(xùn)練集準(zhǔn)確度和測(cè)試集準(zhǔn)確度,得到下圖:
最終測(cè)試集準(zhǔn)確率達(dá)到了99.09%,測(cè)試集準(zhǔn)確率達(dá)到了96.45%,效果還是可以的。但是由于沒(méi)有使用自適應(yīng)學(xué)習(xí)率,loss曲線在200次迭代之后有明顯震蕩。
源代碼:
import numpy as np
from sklearn.datasets import load_digits
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
# 加載手寫數(shù)字?jǐn)?shù)據(jù)集
digits = load_digits()
data=digits.data
#這里的data是64維的,8*8
labels=digits.target
#labels是10類
scaler = StandardScaler()
data = scaler.fit_transform(data)
# 數(shù)據(jù)預(yù)處理:標(biāo)準(zhǔn)化輸入特征
train_data=[]
train_labels=[]
test_data=[]
test_labels=[]
for i in range(len(labels)):
if np.random.rand(1)<0.8:
train_data.append(data[i])
train_labels.append(labels[i])
else:
test_data.append(data[i])
test_labels.append(labels[i])
#這里是按照8/2分?jǐn)?shù)據(jù)集,隨機(jī)生成(0,1)內(nèi)的隨機(jī)數(shù),隨機(jī)數(shù)小于0.8,就放到訓(xùn)練集,
# 大于等于0.8就放到測(cè)試集里。得到訓(xùn)練集和測(cè)試集的數(shù)據(jù)以及標(biāo)簽。
# 將標(biāo)簽進(jìn)行獨(dú)熱編碼
def one_hot_encode(labels, num_classes):
one_hot_labels = np.zeros((len(labels), num_classes))
for i, label in enumerate(labels):
one_hot_labels[i, label] = 1
return one_hot_labels
# 將數(shù)據(jù)集劃分為訓(xùn)練集和測(cè)試集
X_train, X_test, y_train, y_test = train_data,test_data,train_labels,test_labels
X_train=np.array(X_train)
X_test=np.array( X_test)
y_train=np.array(y_train)
y_test=np.array(y_test)
# 獨(dú)熱編碼標(biāo)簽
num_classes = len(np.unique(labels))
y_train_onehot = one_hot_encode(y_train, num_classes)
y_test_onehot = one_hot_encode(y_test, num_classes)
# 定義神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)
input_size = X_train.shape[1]
layer1_size=256
layer2_size=64
output_size = num_classes
# 初始化權(quán)重和偏置
np.random.seed(42)
weights_input_layer1 = np.random.normal(loc=0, scale=0.01, size=(input_size, layer1_size))
bias_input_layer1 =np.random.normal(loc=0, scale=0.01, size=(1, layer1_size))
weights_layer1_layer2 = np.random.normal(loc=0, scale=0.01, size=(layer1_size, layer2_size))
bias_layer1_layer2 = np.random.normal(loc=0, scale=0.01, size=(1, layer2_size))
weights_layer2_output = np.random.normal(loc=0, scale=0.01, size=(layer2_size,output_size))
bias_layer2_output =np.random.normal(loc=0, scale=0.01, size=(1, output_size))
# 定義激活函數(shù)(sigmoid)
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# 定義激活函數(shù)的導(dǎo)數(shù)
def sigmoid_derivative(x):
return x * (1 - x)
# 定義損失函數(shù)(交叉熵)
def cross_entropy_loss(predictions, targets):
epsilon = 1e-15
predictions = np.clip(predictions, epsilon, 1 - epsilon)
loss = -np.sum(targets * np.log(predictions)) / len(targets)
return loss
# 設(shè)置超參數(shù)
learning_rate = 0.01
epochs = 500
batch_size = 16 # 每個(gè)小批次的大小
# 訓(xùn)練神經(jīng)網(wǎng)絡(luò)
loss_all=[]
epoch_all=[]
train_acc=[]
test_acc=[]
for epoch in range(epochs):
# 將訓(xùn)練集打亂順序
permutation = np.random.permutation(len(X_train))
X_train_shuffled = X_train[permutation]
y_train_shuffled = y_train_onehot[permutation]
for i in range(0, len(X_train_shuffled), batch_size):
# 獲取當(dāng)前批次
X_batch = X_train_shuffled[i:i+batch_size]
y_batch = y_train_shuffled[i:i+batch_size]
# 前向傳播
layer1_input = np.dot(X_batch, weights_input_layer1) + bias_input_layer1
layer1_output = sigmoid(layer1_input)
layer2_input = np.dot(layer1_output, weights_layer1_layer2) + bias_layer1_layer2
layer2_output = sigmoid(layer2_input)
output_layer_input = np.dot(layer2_output , weights_layer2_output) + bias_layer2_output
output_layer_output = sigmoid(output_layer_input)
# 計(jì)算損失,交叉熵
loss = cross_entropy_loss(output_layer_output, y_batch)
# 反向傳播
output_error = output_layer_output - y_batch
#求誤差
output_delta = output_error * sigmoid_derivative(output_layer_output)
#求梯度
layer2_error = output_delta.dot(weights_layer2_output.T)
layer2_delta = layer2_error * sigmoid_derivative(layer2_output)
layer1_error = layer2_delta.dot(weights_layer1_layer2.T)
layer1_delta = layer1_error * sigmoid_derivative(layer1_output)
# 更新權(quán)重和偏置,用梯度下降更新
weights_layer2_output -= (layer2_output).T.dot(output_delta) * learning_rate
bias_layer2_output -= np.sum(output_delta, axis=0, keepdims=True) * learning_rate
weights_layer1_layer2 -= (layer1_output).T.dot(layer2_delta) * learning_rate
bias_layer1_layer2-= np.sum(layer2_delta, axis=0, keepdims=True) * learning_rate
weights_input_layer1 -= X_batch.T.dot(layer1_delta) * learning_rate
bias_input_layer1 -= np.sum(layer1_delta, axis=0, keepdims=True) * learning_rate
#計(jì)算訓(xùn)練集準(zhǔn)確率和測(cè)試集準(zhǔn)確率
# 打印損失
if epoch % 10 == 0:
print(f"Epoch {epoch}, Loss: {loss}")
loss_all.append(loss)
epoch_all.append(epoch)
# 在訓(xùn)練集上評(píng)估模型
layer1_input = np.dot(X_train, weights_input_layer1) + bias_input_layer1
layer1_output = sigmoid(layer1_input)
layer2_input = np.dot(layer1_output, weights_layer1_layer2) + bias_layer1_layer2
layer2_output = sigmoid(layer2_input)
output_layer_input = np.dot(layer2_output , weights_layer2_output) + bias_layer2_output
output_layer_output = sigmoid(output_layer_input)
# 預(yù)測(cè)結(jié)果
predictions = np.argmax(output_layer_output, axis=1)
accuracy = np.mean(predictions == y_train)
print("訓(xùn)練集的準(zhǔn)確率:", accuracy)
train_acc.append(accuracy)
# 在測(cè)試集上評(píng)估模型
layer1_input = np.dot(X_test, weights_input_layer1) + bias_input_layer1
layer1_output = sigmoid(layer1_input)
layer2_input = np.dot(layer1_output, weights_layer1_layer2) + bias_layer1_layer2
layer2_output = sigmoid(layer2_input)
output_layer_input = np.dot(layer2_output , weights_layer2_output) + bias_layer2_output
output_layer_output = sigmoid(output_layer_input)
# 預(yù)測(cè)結(jié)果
predictions = np.argmax(output_layer_output, axis=1)
accuracy = np.mean(predictions == y_test)
print("測(cè)試集的準(zhǔn)確率:", accuracy,"\n")
test_acc.append(accuracy)
plt.plot(epoch_all,loss_all,label="loss")
plt.plot(epoch_all,train_acc,label="train_acc")
plt.plot(epoch_all,test_acc,label="test_acc")
plt.xlabel('epoch')
plt.ylabel('loss_value and accuracy')
plt.legend()
plt.show()
?
?
柚子快報(bào)激活碼778899分享:手寫神經(jīng)網(wǎng)絡(luò)實(shí)現(xiàn)手寫數(shù)字識(shí)別
參考鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。