数字识别手写神经网络实现基于MNIST数据集

 MNIST数据集自行baidu下载,解压后放到项目文件里

git详细代码仓库:https://github.com/justDoForever/deep_learning/digital_recognition.py (python 2.7)

理论分析: https://www.zybuluo.com/hanbingtao/note/476663

代码如下:

# encoding:utf-8
#神经网络实现数字识别
import struct
import sys
from datetime import datetime

from fcn import Network


def transpose(param):
    pass


class Loader(object):
    #数据基础加载器
    def __init__(self,path,number):
        '''

        :param path: 数据文件路经
        :param number: 文件中样本个数
        '''
        self.path = path;
        self.number = number;

    def get_file_content(self):
        file = open(self.path,'rb')
        content = file.read()
        file.close();
        return content;

    def to_int(self,byte):
        #将unsigned char转成int
        return struct.unpack('B',byte)[0]



class ImgaeLoader(Loader):
#这里的self即指向ImageLoader基类自身也指向Loader父类
    def load(self):
        #首先得到文件内容
        content = self.get_file_content()
        data_set = []
        for i in range(self.number):
            data_set.append(self.get_one_sample(self.get_picture(content,i)))
        return data_set

    def get_picture(self, content, index):
        #获得图片二维矩阵
        #t=图片样本前16位不是标签所以要从第17位开始(content[16])
        start = index * 28 * 28 + 16;
        picture = [];
        for i in range(28):
            picture.append([])
            for j in range(28):
                picture[i].append(self.to_int(content[start + i * 28 + j]))
            #     if self.to_int(content[start + i * 28 + j]) != 0:
            #         sys.stdout.write('*')
            #     else:
            #         sys.stdout.write(' ')
            # print ' '
        return picture;

    def get_one_sample(self, picture):
        #将图片二维矩阵转为一维输入向量
        sample = [];
        for i in range(28):
            for j in range(28):
                sample.append(picture[i][j])
        return sample;


class LabelLoder(Loader):
    def load(self):
        #标签前8位不是标签所以要从第9位开始(content[8])
        content = self.get_file_content();
        label_set = [];
        for i in range(self.number):
            label_set.append(self.norm(content[i + 8]))
        return label_set;

    def norm(self,label):
        #将label值一个0到9的数字转为一个10维的输出向量
        label_vec = [];
        label_value = self.to_int(label)
        for i in range(10):
            if i == label_value:
                label_vec.append(0.9)
            else:
                label_vec.append(0.1)
        return label_vec


def get_train_data_set():
    image_loader = ImgaeLoader('train-images.idx3-ubyte',60)
    label_loader = LabelLoder('train-labels.idx1-ubyte',60)
    return image_loader.load(),label_loader.load();

def get_test_data_set():
    image_loader = ImgaeLoader('t10k-images.idx3-ubyte',10)
    label_loader = LabelLoder('t10k-labels.idx1-ubyte',10)
    return image_loader.load(),label_loader.load()


def now():
    return datetime.now().strftime("%c")


def get_result(input):
    max_value = - 1;
    max_index = -1;
    for i in range(len(input)):
        if input[i] > max_value:
            max_index = i;
            max_value = input[i]
    return max_index;

def evaluate(net, test_data_set, test_labels):
    error = 0;

    for i in range(len(test_labels)):
        #样本和预测输出的虽然都是10维的一个向量,但是不能直接比较相等来代表预测是否正确
        #因为预测值的10维向量不是0.1,0.9组成的,只能通过最大值的位置作为结果来比较
        label = get_result(test_labels[i])
        predict = get_result(net.predict(test_data_set[i]))
        if label != predict:
            error += 1;
    return float(error) / float(len(test_labels))

def train_and_evaluate():
    epoch = 1;
    last_error_ratio = 1.0;
    #获取数据集并处理
    # train_data_set,tain_labels = transpose(get_train_data_set())
    # test_data_set,test_labels = transpose(get_test_data_set())
    train_data_set, tain_labels = get_train_data_set()
    test_data_set, test_labels = get_test_data_set()

    #搭建神经网络
    net = Network([784,300,10]);

    #训练
    while True:
        net.train(tain_labels,train_data_set,1,0.01)
        epoch += 1;
        print '%s epoch: %d   \n' % (now(),epoch)

        if epoch % 10 == 0:
            #每训练10次就通过测试样本计算错误率
            error_ratio = evaluate(net,test_data_set,test_labels)
            print '%s epoch: %d  error ratio : %f\n' % (now(),epoch,error_ratio)
            #如果错误率升高就停止训练防止过拟合,否则更新last_error_ratio为最新的错误率
            if error_ratio > last_error_ratio:
                break;
            else:
                last_error_ratio = error_ratio;

if __name__ == '__main__':
    train_and_evaluate();
    # train_data_set, tain_labels = get_train_data_set()
    # print train_data_set,'   ',tain_labels
    # a = [[1,2],[4,5]]
    # print a[-1]

 

数字识别手写神经网络实现基于MNIST数据集_第1张图片

你可能感兴趣的:(深度学习)