python神经网络实现手写数字识别实验

     手写数字识别实验是机器学习中最常见的一个示例,可以有很多种办法实现,最基础的其实就是利用knn算法,根据数字图片对应矩阵与经过训练的数字进行距离计算,最后这个距离最短,那么就认为它是哪个数字。

     这里直接通过神经网络的办法来进行手写数字识别实验。不借助其他框架,编写网络,然后进行测试。这个代码其实网上有很多,并不是原创。

     这里有必要说明一下手写数字的数据集,这里采用的是mnist_dataset/mnist_train.csv数据集,数据地址: https://www.kaggle.com/datasets/oddrationale/mnist-in-csv。下载之后是一个压缩包,里面包含mnist_train.csv,mnist_test.csv。

    我们可以看看mnist_train.csv的部分数据:

python神经网络实现手写数字识别实验_第1张图片 

    上图中,①处表示 第一行内容 其实是标题,我们在数据处理的时候需要过滤这一行。② 表示的是label内容,也就是真实数字,它由0-9组成,也就是10个分类。③ 处表示的28 * 28矩阵,这个数字由784个数字组成。 

    实验过程,先使用mnist_train.csv数据训练网络,然后利用我们自己手写的数字进行测试。这里没有使用mnist_test.csv进行测试,主要是它本身就是人家进行测试的数据,我们这里自己测试。

    我自己准备的数字图片如下所示:

python神经网络实现手写数字识别实验_第2张图片

    这些图片都是根据这里测试数据mnist_train.csv数据格式的要求进行绘制的28*28像素的图片,这个图片很小,但是可以借助windows系统paint绘图工具,选择28*28像素画布,然后进行放大,最后可以在编辑区域画出这些数字。

     

     下面给出代码:

import os
import numpy as np
import scipy.special
import imageio

image_path = 'number_images'


# 加载图片
def load_img_number(root_dir):
    files = os.listdir(root_dir)
    file_list = []
    for file in files:
        file_path = os.path.join(root_dir, file)
        file_list.append(file_path)
    return file_list


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)))
        # 激活函数
        self.activation_function = lambda x: scipy.special.expit(x)

    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 query(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


input_nodes = 784
hidden_nodes = 200
output_nodes = 10
learning_rate = 0.2
# 构建模型
model = neuralnetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
# 准备训练数据
training_data_file = open('mnist/mnist_train.csv', 'r')
training_data_list = training_data_file.readlines()
# 去掉第一行标题
training_data_list = training_data_list[1:]
training_data_file.close()

# 训练
for record in training_data_list:
    all_values = record.split(',')
    inputs = (np.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01
    targets = np.zeros(output_nodes) + 0.01
    targets[int(all_values[0])] = 0.99
    model.train(inputs, targets)
    pass

img_list = load_img_number(image_path)

for i in range(len(img_list)):
    img_name = img_list[i]
    img_arr = imageio.v2.imread(img_name, mode='L')
    img_data = 255.0 - img_arr.reshape(784)
    inputs = (img_data / 255.0 * 0.99) + 0.01
    outputs = model.query(inputs)
    label = np.argmax(outputs)
    print(f'{img_name} 识别结果是 {label}')

    运行代码,打印结果:

python神经网络实现手写数字识别实验_第3张图片 

    1、识别率很感人,其实很多都识别错误。 

    2、多次运行,结果也不一样。

    3、识别不正确的基本会认为6或者8。不知道怎么会有这种奇怪的结果。

   最后,给出本示例的代码和资源:https://gitee.com/buejee/aitutorial

你可能感兴趣的:(人工智能,python,神经网络,机器学习,手写数字识别,mnist)