使用DNN实现手写数字识别
使用mnist 数据集,基于python基础库,用含一层隐藏层的神经网络训练一个简单的模型来识别手写数字。
准确率 90%以上。
并用自己的手写数字的图片验证。
加载所需的库
import sys ,os
import numpy as np
import matplotlib.pyplot as plt
sys.path.append(os.pardir) #加入当前目录,要用到mnist.py
from dataset.mnist import load_mnist
from PIL import Image
加载mnist数据集
#(训练图像,训练标签),(测试图像,测试标签)
# mnist的图像均为28*28尺寸的数据,通道为1
(x_train_origin,t_train_origin),(x_test_origin,t_test_origin) = load_mnist(normalize=True,flatten=False,one_hot_label=True)
m_train = x_train_origin.shape[0] #训练集大小
m_test = x_test_origin.shape[0] #测试集大小
num_px = x_train_origin.shape[2] #px = height = width
num_category = 10 #分类类别个数总共有10个0-9
print("number of trainning sample is :"+repr(m_train))
print("number of test sample is :"+repr(m_test))
print("shape of x_train is :"+repr(x_train_origin.shape))
print("shape of t_train is :"+repr(t_train_origin.shape))
print("shape of x_test is :"+repr(x_test_origin.shape))
print("shape of t_test is :"+repr(t_test_origin.shape))
number of trainning sample is :60000
number of test sample is :10000
shape of x_train is :(60000, 1, 28, 28)
shape of t_train is :(60000, 10)
shape of x_test is :(10000, 1, 28, 28)
shape of t_test is :(10000, 10)
reshape
将数据集的shape转变成(nx,m) ,nx为特征数量,这里即像素个数,m为数据大小.
方便神经网络的计算
train_set_x = x_train_origin.reshape(x_train_origin.shape[0],-1).T
train_set_y = t_train_origin.T
test_set_x = x_test_origin.reshape(x_test_origin.shape[0],-1).T
test_set_y = t_test_origin.T
print("shape of train_set_x is :"+repr(train_set_x.shape))
print("shape of train_set_y is :"+repr(train_set_y.shape))
print("shape of test_set_x is :"+repr(test_set_x.shape))
print("shape of test_set_y is :"+repr(test_set_y.shape))
shape of train_set_x is :(784, 60000)
shape of train_set_y is :(10, 60000)
shape of test_set_x is :(784, 10000)
shape of test_set_y is :(10, 10000)
显示图像
index = 0
plt.imshow(x_train_origin[index].reshape((28,28)),cmap = plt.cm.gray)
print("y is:"+str(np.argmax(t_train_origin[index])))
y is:5
output_8_1.png
sigmoid函数
1/(1+exp(-z))
def sigmoid(z):
"""
计算z的sigmoid 值
Arguments:
z -- 实数或任意数组
Return:
s -- 返回类型与z一致
"""
s = 1 / (1+np.exp(-z))
return s
s = sigmoid(0)
print("s is :"+str(s))
s is :0.5
初始化参数 w ,b
def initilize_params(dim,num_categories) :
"""
init w and b
Arguments:
dim -- size of w
num_categories: number of total categories
Return :
w -- shape of (dim,num_categories)
b -- shape of (num_categories,1)
"""
w = np.zeros((dim,num_categories))
b = np.zeros((num_categories,1))
assert(w.shape == (dim,num_categories))
assert(b.shape == (num_categories,1))
return w,b
前向传播与反向传播
def propagate(w,b,X,Y):
"""
Arguments:
w-- weights,numpy array of shape(num_px*num_px,num_categories)
b -- bias of shape (num_categories,1)
X -- data of shape (num_px*num_px,number of examples)
Y -- tag of shape (num_categories, number of example)
Return :
grads -- a dict ,derivative of dw,db
cost -- current cost
"""
m = X.shape[1]
#前向传播 START 计算损失
#caculate W^T*X +b
z = np.dot(w.T,X) + b #shape is:(num_categories,number of examples)
yhat = sigmoid(z) # 每个样本0-9的预测概率,shape is same as z
#计算损失
cost = -np.sum((Y * np.log(yhat) + (1-Y)*np.log(1-yhat)))/m
# 前向传播 END
# 反向传播 START
dw = np.dot(X , (yhat - Y).T)/m #shape is same with w
db = np.sum((yhat - Y),axis = 1)/m #shape is same with b
db = db.reshape(b.shape)
#反向传播 END
assert(dw.shape == w.shape)
assert(db.shape == b.shape)
grads = {"dw":dw,
"db":db}
return grads, cost
优化
def optimize(w,b,X,Y,number_iterations,learning_rate):
"""
optimize w and b by running gradient descent algorithm
Arguments:
w-- weights,numpy array of shape(num_px*num_px,num_categories)
b -- bias of shape (num_categories,1)
X -- data of shape (num_px*num_px,number of examples)
Y -- tag of shape (num_categories, number of example)
number_iterations -- number of iterate for gradient descent
learning_rate -- learning rate for gradient descent
Return :
params -- a dict ,include w ,b
grads -- a dict ,derivative of dw,db
cost -- current cost
"""
costs= []
for i in range(number_iterations):
grads, cost = propagate(w,b,X,Y)
dw = grads["dw"]
db = grads["db"]
#update w and b
w = w - learning_rate*dw
b = b -learning_rate*db
if(i % 100) == 0:
costs.append(cost)
print ("cost after iteration %i is :%f" %(i,cost))
params = {"w":w,
"b": b}
grads = {"dw":dw,
"db":db}
return params,grads,costs
预测
def predicate (X ,w ,b):
"""
predicate of data
Arguments:
w-- weights,numpy array of shape(num_px*num_px,num_categories)
b -- bias of shape (num_categories,1)
X -- data of shape (num_px*num_px,number of examples)
Return :
Y_pred_one_hot_label -- the predicate result of X,shape is :(num_categories,number of examples)
Y_pred_number -- a vector ,the predicate with a excactly number for each X
"""
m = X.shape[1]
z = np.dot(w.T,X)+b
yhats = sigmoid(z).T
Y_pred_one_hot_label = np.zeros((b.shape[0],m)) #one-hot-label
Y_pred_number =np.zeros((1,m)) #a number that it predicate
for i in range(yhats.shape[0]):
max_index = np.argmax(yhats[i])
Y_pred_one_hot_label[max_index,i] = 1
Y_pred_number[0,i] = int(max_index)
return Y_pred_one_hot_label,Y_pred_number
构建模型
把所有东西整合起来,构建模型
def nurvus_network_model(train_set_x, train_set_y, test_set_x, test_set_y, num_categories, number_iterations=2000, learning_rate=0.5):
"""
construct a model to predicate number picture
Arguments:
train_set_x-- training data,numpy array of shape(num_px*num_px,number of examples)
train_set_y -- the tag of trainning data of shape (num_categories,number of examples)
test_set_x -- test examples,numpy array of shape (num_px*num_px,number of examples)
test_set_y -- the tag of test data of shape (num_categories,number of examples)
num_categories -- number of categories
number_iterations -- the number of iterate for optimize
learning_rate --
Return :
d -- dictionary contain info for model
"""
dim = train_set_x.shape[0]
# init w and b
w, b = initilize_params(dim, num_categories)
params, grads, costs = optimize(
w, b, train_set_x, train_set_y, number_iterations=number_iterations, learning_rate=learning_rate)
w = params["w"]
b = params["b"]
Y_pred_train_one_hot_label, Y_pred_train_number = predicate(
train_set_x, w, b)
Y_pred_test_one_hot_label, Y_pred_test_number = predicate(
test_set_x, w, b)
print("train accuracy: {} %".format(
100 - np.mean(np.sum(np.abs(Y_pred_train_one_hot_label - train_set_y), axis=0)/2) * 100))
print("test accuracy: {} %".format(
100 - np.mean(np.sum(np.abs(Y_pred_test_one_hot_label - test_set_y), axis=0)/2) * 100))
d = {"w":w,
"b":b,
"costs":costs,
"Y_pred_train":Y_pred_train_number,
"Y_pred_train_one_hot":Y_pred_train_one_hot_label,
"Y_pred_test":Y_pred_test_number,
"Y_pred_test_one_hot":Y_pred_test_one_hot_label,
"learning_rate":learning_rate,
"iterations":number_iterations}
return d
number_categories = 10
d = nurvus_network_model(train_set_x,train_set_y,test_set_x,test_set_y,num_categories = 10,number_iterations=2000,learning_rate=0.6)
cost after iteration 0 is :6.931472
cost after iteration 100 is :0.903445
cost after iteration 200 is :0.813852
.......
cost after iteration 1800 is :0.656671
cost after iteration 1900 is :0.654527
train accuracy: 91.66 %
test accuracy: 91.82 %
index = 20
y_pred_test = d["Y_pred_test"]
plt.imshow(test_set_x[:,index].reshape((28,28)),cmap = plt.cm.gray)
print("y is:"+str(np.argmax(test_set_y[:,index])))
print("your predicate result is :"+str(int(y_pred_test[0,index])))
y is:9
your predicate result is :9
output_27_1.png
画出损失函数图
costs = d["costs"]
plt.plot(costs)
plt.xlabel("iterations/hundreds")
plt.ylabel("costs")
plt.show()
output_29_0.png
用自己的图片测试
import scipy
from PIL import Image
from scipy import ndimage
my_image_name = "5.jpeg"
#my_image_name = "2.jpeg"
#my_image_name = "7.jpeg"
fname = my_image_name
image_origin = Image.open(fname)
a = np.asarray(image_origin)
print(a.shape)
image = image_origin.convert(mode = "L")
image = image.resize((28,28),resample = Image.ANTIALIAS)
a = np.asarray(image)
plt.imshow(image,cmap=plt.cm.gray) #显示图像
a = 255 -a
mean = np.mean(a)
a = np.where(a < mean,0,a)
a = a/255
input_x = a.reshape((28*28,1))
onehotlabel,predicate_number = predicate(input_x, d["w"],d["b"])
print("your predicate number is :"+str(int(predicate_number[0][0])))
(28, 28, 3)
your predicate number is :5
output_31_1.png
网友评论