多层感知器手写数字识别

概要

我们训练了一个基于MLP的分类器,用于区分手写数字图像
在这里插入图片描述

介绍

多层感知器(Multilayer Perceptron,简称MLP)是一种前馈神经网络(Feedforward Neural Network)模型,由多个神经元组成。每一层通过非线性变换将输入映射到下一层,最终输出一个非线性的预测结果。MLP可以应用于分类、回归和其他机器学习任务。

整体架构流程

1、导入需要用到的库函数

import numpy as np
from torchvision.datasets import MNIST
from scipy.special import expit
import matplotlib.pyplot as plt
import cv2

2、加载MNIST数据集

#load MNIST dataset
data_path='./data'
train_data=MNIST(data_path,train=True,download=True)
test_data=MNIST(data_path,train=False,download=True)

3、对数据集进行处理

train_list=list(train_data)
test_list=list(test_data)

4、建立多层感知器模型

# Define the Multi-Layer Perceptron (MLP) class
class MLP():
    '''Multi layer Perceptron'''
    def __init__(self,num_input_node,num_hidden_node,num_hidden_node1,num_output_node,lr=0.1):
        self.num_inpot_node=num_input_node
        self.num_hidden_node=num_hidden_node
        self.num_hidden_node1=num_hidden_node1
        self.num_output_node=num_output_node
        self.lr=lr
        self.time=list()
        self.loss=list()
        self.t=1
        #Initial weight between 
        self.wih=np.random.normal(0,pow(self.num_hidden_node,-0.5),(self.num_hidden_node,self.num_inpot_node))
        self.whh=np.random.normal(0,pow(self.num_hidden_node1,-0.5),(self.num_hidden_node1,self.num_hidden_node))
        self.who=np.random.normal(0,pow(self.num_output_node,-0.5),(self.num_output_node,self.num_hidden_node1))
        self.activation_fun=lambda x:expit(x)
    def predict(self,input):
        output_hidden=self.activation_fun(np.dot(self.wih,input))
        output_hidden1=self.activation_fun(np.dot(self.whh,output_hidden))
        result=self.activation_fun(np.dot(self.who,output_hidden1))
        result=result.argmax()
        return result
    def train(self,input,label,num_iter=3):
        for i in range(num_iter):
            # step 1:predict
            out_hidden=self.activation_fun(np.dot(self.wih,input))
            out_hidden1=self.activation_fun(np.dot(self.whh,out_hidden))
            out_output=self.activation_fun(np.dot(self.who,out_hidden1))
            # setp 2:Comput error
            self.time.append(self.t)
            self.t=self.t+1
            self.loss.append(np.mean(np.abs(out_output - label)))
            error_output=out_output-label
            error_hidden1=np.dot(self.who.T,error_output) 
            error_hidden=np.dot(self.whh.T,error_hidden1) 
            #step 3:Update weight
            self.wih+=-self.lr*np.dot(error_hidden*out_hidden*(1-out_hidden),input.T)
            self.whh+=-self.lr*np.dot(error_hidden1*out_hidden1*(1-out_hidden1),out_hidden.T)
            self.who+=-self.lr*np.dot(error_output*out_output*(1-out_output),out_hidden1.T)
            predict_result=out_output.argmax()
            groundtruth=label.argmax()
            if i%2==0:
                print('predict:{},label:{} Correct:{}'.format(predict_result,groundtruth,predict_result==groundtruth))
    def plot(self):
        plt.plot(self.time,self.loss,color='blue', linestyle='-')
        plt.xlabel('Epoch')
        plt.ylabel('Loss')
        plt.legend()
        plt.title('Loss Function Curve')
        plt.show()
        

5、设置参数

# Set parameters
num_input_node=28*28
num_hidden_node=80
num_hidden_node1=60
num_output_node=10
lr=0.001

6、训练

#train
cnt_correct=0
accuracy=list()
for i,data in enumerate(train_list):
    input=data[0]
    input=np.array(input)
    input=input.reshape(num_input_node,1)
    input=input/255.0
    label=np.zeros((num_output_node,1))
    label[int(data[1])]=1
    mlp.train(input,label)
    print("Data{}has been trained".format(i))
    if i%100==0:
        for i ,data in enumerate(test_list):
            input = data[0]
            input=np.array(input)
            input = input.reshape(num_input_node,1)
            input=input/255.0
            result = mlp.predict(input)
            if result==data[1]:
                cnt_correct+=1
        accuracy.append(cnt_correct*100.0/len(test_list))
        cnt_correct=0
mlp.plot()

训练的损失如下
在这里插入图片描述
7、训练过程中测试集的准确率

#Draw test set accuracy
plt.plot(range(1,len(accuracy)+1),accuracy,color='red', linestyle='-')
plt.xlabel('Epoch')
plt.ylabel('accuracy')
plt.legend()
plt.title('Accuracy Curve')
plt.show()

结果如下
在这里插入图片描述
8、测试

#test
cnt_correct=0
for i ,data in enumerate(test_list):
    input = data[0]
    input=np.array(input)
    input = input.reshape(num_input_node,1)
    input=input/255.0
    result = mlp.predict(input)
    print("predict:{}:laberl:{}".format(result,data[1]))
    if result==data[1]:
        cnt_correct+=1;
print("Test accuracy:{}%".format(cnt_correct*100.0/len(test_list)))

在这里插入图片描述
9、加载自己的手写数字并验证

import cv2
import matplotlib.pyplot as plt
input=np.array(cv2.imread("./image/2.jpg"))
input=input[:,:,0]
for i in range (28):
    for j in range(28):
        if(input[i][j]>120):
            input[i][j]=255
        else:
            input[i][j]=0
plt.imshow(input)
input = input.reshape(num_input_node,1)
result = mlp.predict(input)
print("The predicted result is {}".format(result))

在这里插入图片描述

完整代码

import numpy as np
from torchvision.datasets import MNIST
from scipy.special import expit
import cv2

#load MNIST dataset
data_path='./data'
train_data=MNIST(data_path,train=True,download=True)
test_data=MNIST(data_path,train=False,download=True)

train_list=list(train_data)
# train_list = train_list[:2000]
test_list=list(test_data)

class MLP():
    '''Multi layer Perceptron'''
    def __init__(self,num_input_node,num_hidden_node,num_hidden_node1,num_output_node,lr=0.1):
        '''
            Initial
        :param  num_input_node: Number of input nodes
        :param  num_input_node: Number of output nodes
        '''
        self.num_inpot_node=num_input_node
        self.num_hidden_node=num_hidden_node
        self.num_hidden_node1=num_hidden_node1
        self.num_output_node=num_output_node
        self.lr=lr
        #Initial weight between
        self.wih=np.random.normal(0,pow(self.num_hidden_node,-0.5),(self.num_hidden_node,self.num_inpot_node))
        self.whh=np.random.normal(0,pow(self.num_hidden_node1,-0.5),(self.num_hidden_node1,self.num_hidden_node))
        self.who=np.random.normal(0,pow(self.num_output_node,-0.5),(self.num_output_node,self.num_hidden_node1))
        # self.activation_fun=lambda x:expit(x)
        self.activation_fun=lambda x:expit(x)
    def predict(self,input):
        output_hidden=self.activation_fun(np.dot(self.wih,input))
        output_hidden1=self.activation_fun(np.dot(self.whh,output_hidden))
        result=self.activation_fun(np.dot(self.who,output_hidden1))
        result=result.argmax()
        # print("input:{} predict:{}".format(input[1],result))
        return result
    def train(self,input,label,num_iter=4):
        for i in range(num_iter):
            # step 1:predict
            out_hidden=self.activation_fun(np.dot(self.wih,input)) #80,1
            out_hidden1=self.activation_fun(np.dot(self.whh,out_hidden)) #80,1
            out_output=self.activation_fun(np.dot(self.who,out_hidden1)) #10,1
            # setp 2:Comput error
            error_output=out_output-label #10,1
            error_hidden1=np.dot(self.who.T,error_output) #80,1
            error_hidden=np.dot(self.whh.T,error_hidden1) #80,1
            #step 3:Update weight
            self.wih+=-self.lr*np.dot(error_hidden*out_hidden*(1-out_hidden),input.T)
            self.whh+=-self.lr*np.dot(error_hidden1*out_hidden1*(1-out_hidden1),out_hidden.T)
            self.who+=-self.lr*np.dot(error_output*out_output*(1-out_output),out_hidden1.T)
            predict_result=out_output.argmax()
            groundtruth=label.argmax()
            if i%2==0:

                print('predict:{},label:{} Correct:{}'.format(predict_result,groundtruth,predict_result==groundtruth))
                # print(self.lr*np.dot(error_hidden*out_hidden*(1-out_hidden),input.T))

num_input_node=28*28
num_hidden_node=150
num_hidden_node1=120
num_output_node=10
lr=0.001

mlp=MLP(num_input_node,num_hidden_node,num_hidden_node1,num_output_node,lr)

#train
for i,data in enumerate(train_list):
    input=data[0]
    input=np.array(input)
    input=input.reshape(num_input_node,1)
    label=np.zeros((num_output_node,1))
    label[int(data[1])]=1
    mlp.train(input,label)
    print("Data{}has been trained".format(i))

#test
cnt_correct=0
for i ,data in enumerate(test_list):
    input = data[0]
    input=np.array(input)
    input = input.reshape(num_input_node,1)
    result = mlp.predict(input)
    print("result{}:pre{}".format(result,data[1]))
    if result==data[1]:
        cnt_correct+=1;
print("Test accuracy:{}%".format(cnt_correct*100.0/len(test_list)))

小结

我们首先对MNIST数据集进行了加载和预处理,将像素值转换为0到1之间的浮点数,并将数据集分为60000个训练集和10000个测试集。接着,我们构建了一个基于MLP的分类器,它包含了三个隐藏层和一个输出层。使用Sigmoid激活函数,而输出层包含了10个神经元,对应于0到9的10个数字类别。 MLP使用梯度下降法法训练,在每个批次上对权重进行更新,以最小化损失函数,同时根据每次训练完后的损失值画出损失函数图像。我们对MLP模型进行了超参数调整,包括隐藏层数和神经元个数,同时也对数据进行了归一化处理。我们发现,当我们增加隐藏层数时,模型能够更好地区分数字,但是也需要更多的时间进行训练。我们还发现,增加每个隐藏层中的神经元数可以提高模型的精度,但也需要更长的训练时间。最后,在测试集上对模型进行评估,我们发现该模型的准确率可以达到90.8%。结合实验结果,我们可以得出结论:MLP是一种灵活且有效的分类器,可以用于各种分类问题中

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值