import numpy as np
import scipy.special
import matplotlib.pyplot as plt
from PIL import Image
class neuralNetwork :
# 用於神經網絡初始化
def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
# 輸入層節點數
self.inodes = inputnodes
# 隱層節點數
self.hnodes = hiddennodes
# 輸出層節點數
self.onodes = outputnodes
# 學習率
self.lr = learningrate
# 初始化輸入層與隱層之間的權重
self.wih = np.random.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes, self.inodes))
# 初始化隱層與輸出層之間的權重
self.who = np.random.normal(0.0, pow(self.onodes, -0.5), (self.onodes, self.hnodes))
# 激活函數(S函數)
self.activation_function = lambda x: scipy.special.expit(x)
# 逆激活函數
self.iactivation_function = lambda y: scipy.special.logit(y)
# 設置權重
def setweights(self, wih, who):
self.wih = wih
self.who = who
# 神經網絡學習訓練
def train(self, inputs_list, targets_list):
# 將輸入數據轉化成二維矩陣
inputs = np.array(inputs_list, ndmin=2).T
# 將輸入標籤轉化成二維矩陣
targets = np.array(targets_list, ndmin=2).T
# 計算隱層的輸入
hidden_inputs = np.dot(self.wih, inputs)
# 計算隱層的輸出
hidden_outputs = self.activation_function(hidden_inputs)
# 計算輸出層的輸入
final_inputs = np.dot(self.who, hidden_outputs)
# 計算輸出層的輸出
final_outputs = self.activation_function(final_inputs)
# 計算輸出層誤差
output_errors = targets - final_outputs
# 計算隱層誤差
hidden_errors = np.dot(self.who.T, output_errors)
# 更新隱層與輸出層之間的權重
self.who += self.lr * np.dot((output_errors * final_outputs * (1.0 - final_outputs)), np.transpose(hidden_outputs))
# 更新隱層與輸出層之間的權重
self.wih += self.lr * np.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), np.transpose(inputs))
# 根據標籤逆向生成圖片
def makeinput(self, outputs_list):
# 將標記數據(輸出層的輸出)轉化成二維矩陣
final_outputs = np.array(outputs_list, ndmin=2).T
# 計算輸出層的輸入
final_inputs = self.iactivation_function(final_outputs)
# 計算隱層的輸出
hidden_outputs = np.dot(self.who.T, final_inputs)
# 處理下限使得下限爲0
hidden_outputs -= np.min(hidden_outputs)
# 處理上限使得上限爲1
hidden_outputs /= np.max(hidden_outputs)
hidden_outputs *= 0.98
hidden_outputs += 0.01
# 計算隱層的輸入
hidden_inputs = self.iactivation_function(hidden_outputs)
# 計算輸入層的數據
inputs = np.dot(self.wih.T, hidden_inputs)
inputs -= np.min(inputs)
inputs /= np.max(inputs)
inputs *= 255
print(inputs)
return inputs
# 神經網絡測試
def test(self, inputs_list):
# 將輸入數據轉化成二維矩陣
inputs = np.array(inputs_list, ndmin=2).T
# 計算隱層的輸入
hidden_inputs = np.dot(self.wih, inputs)
# 計算隱層的輸出
hidden_outputs = self.activation_function(hidden_inputs)
# 計算輸出層的輸入
final_inputs = np.dot(self.who, hidden_outputs)
# 計算輸出層的輸出
final_outputs = self.activation_function(final_inputs)
return final_outputs
# 訓練神經網絡
def train_neuralnetwork():
# 初始化 784(28 * 28)個輸入節點,100個隱層節點,10個輸出節點(0~9)
input_nodes = 784
hidden_nodes = 200
output_nodes = 10
# 學習率0.3
learning_rate = 0.1
# 訓練次數
epochs = 5
# 初始化神經網絡實例
n = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
# 讀取訓練集
training_data_file = open('mnist_dataset/mnist_train.csv', 'r')
training_data_list = training_data_file.readlines()
training_data_file.close()
# 訓練數據
for e in range(epochs):
for record in training_data_list:
all_values = record.split(',')
# 輸入數據範圍(0.01~1)
inputs = np.asfarray(all_values[1:]) / 255.0 * 0.99 + 0.01
# 標記數據(相應標記爲0.99,其餘0.01)
targets = np.zeros(output_nodes) + 0.01
targets[int(all_values[0])] = 0.99
n.train(inputs, targets)
np.savetxt('weights/who_60000.csv', n.who, delimiter=',')
np.savetxt('weights/wih_60000.csv', n.wih, delimiter=',')
# 驗證性能
def pre_acc():
# 初始化 784(28 * 28)個輸入節點,100個隱層節點,10個輸出節點(0~9)
input_nodes = 784
hidden_nodes = 200
output_nodes = 10
# 學習率0.1
learning_rate = 0.1
# 初始化神經網絡實例
n = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
# 讀取測試數據
test_data_file = open('mnist_dataset/mnist_test.csv', 'r')
test_data_list = test_data_file.readlines()
test_data_file.close()
# 性能分析(正確率)
wih = np.loadtxt(open('weights/wih_60000.csv'), delimiter=",", skiprows=0)
who = np.loadtxt(open('weights/who_60000.csv'), delimiter=",", skiprows=0)
n.setweights(wih, who)
scorecard = []
for record in test_data_list:
# 讀取測試集中的每個數據,進行預測
test_data = record.split(',')
correct_label = int(test_data[0])
outputs = n.test(np.asfarray(test_data[1:]) / 255.0 * 0.99 + 0.01)
# 找到每次預測結果中最大值的索引(即,預測的標籤)
pre_label = np.argmax(outputs)
# 如果預測正確,則得1分,否則得0分
if pre_label == correct_label:
scorecard.append(1)
else:
scorecard.append(0)
print(scorecard)
# 計算正確率
scorecard_array = np.asarray(scorecard)
accuracy = scorecard_array.sum() / scorecard_array.size
print(accuracy)
# 單個預測
def pre_one():
# 初始化 784(28 * 28)個輸入節點,100個隱層節點,10個輸出節點(0~9)
input_nodes = 784
hidden_nodes = 200
output_nodes = 10
# 學習率0.1
learning_rate = 0.1
# 初始化神經網絡實例
n = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
# 讀取測試數據
test_data_file = open('mnist_dataset/mnist_test_10.csv', 'r')
test_data_list = test_data_file.readlines()
test_data_file.close()
# 打印測試數據標籤
test_data = test_data_list[0].split(',')
print('原標籤:', test_data[0])
# 生成標籤圖片
image_array = np.asfarray(test_data[1:]).reshape(28, 28)
plt.imshow(image_array, cmap='Greys', interpolation='None')
plt.show()
# 利用神經網絡預測
wih = np.loadtxt(open('weights/wih_60000.csv'), delimiter=",", skiprows=0)
who = np.loadtxt(open('weights/who_60000.csv'), delimiter=",", skiprows=0)
n.setweights(wih, who)
results = n.test(np.asfarray(test_data[1:]) / 255.0 * 0.99 + 0.01)
pre_label = np.argmax(results)
print('預測結果:', pre_label)
print(results)
# 根據標籤逆向生成圖片
def pre_imakepic():
# 初始化 784(28 * 28)個輸入節點,100個隱層節點,10個輸出節點(0~9)
input_nodes = 784
hidden_nodes = 200
output_nodes = 10
# 學習率0.1
learning_rate = 0.1
# 初始化神經網絡實例
n = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
# 要製作的標籤
want_label = 0
# 生成相應的輸出層的輸出數據
label_data = np.zeros(output_nodes) + 0.01
label_data[int(want_label)] = 0.99
wih = np.loadtxt(open('weights/wih_60000.csv'), delimiter=",", skiprows=0)
who = np.loadtxt(open('weights/who_60000.csv'), delimiter=",", skiprows=0)
n.setweights(wih, who)
res_inputs = n.makeinput(label_data)
# 生成標籤圖片
image_array = np.asfarray(res_inputs).reshape(28, 28)
plt.imshow(image_array, cmap='Greys', interpolation='None')
plt.show()
# 手寫照片識別
def pre_pic():
# 初始化 784(28 * 28)個輸入節點,100個隱層節點,10個輸出節點(0~9)
input_nodes = 784
hidden_nodes = 200
output_nodes = 10
# 學習率0.1
learning_rate = 0.1
# 初始化神經網絡實例
n = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
# 讀取帶預測圖片
img = Image.open('picture/2.jpg').convert('L')
newimg = img.resize((28, 28), Image.ADAPTIVE)
# newimg.save('picture/2_resize.jpg')
test_pic = np.array(newimg)
# 利用神經網絡預測
wih = np.loadtxt(open('weights/wih_60000.csv'), delimiter=",", skiprows=0)
who = np.loadtxt(open('weights/who_60000.csv'), delimiter=",", skiprows=0)
n.setweights(wih, who)
# 正常255表示白色,但mnist數據集255表示黑色,所以現實圖片顏色應該翻轉一下
results = n.test(np.asfarray(255.0 - test_pic.flatten()) / 255.0 * 0.99 + 0.01)
pre_label = np.argmax(results)
print('預測結果:', pre_label)
print(results)
if __name__ == "__main__":
# train_neuralnetwork()
pre_pic()
# pre_imakepic()
# pre_one()
# pre_acc()
注:代碼是對《Python神經網絡編程》中代碼的擴展。