深度学习:构建神经网络并识别手写数字(正确率:0.91175)

转自我自己的blog

blog.laclic.ink.

github链接

Github.

效果

可以看出(10个数据,分别是认为该数字为0-9的程度,最后取最高的那个即为结果)基本能正确识别

Z.png

但是1和7,4和9还是不太容易识别的

O.png

全代码(ipynb)

引入库

import numpy
# scipy.special for the sigmoid function expit()
import scipy.special
# library for plotting arrays
import matplotlib.pyplot
# (?) ensure the plots are inside this notebook, not an external window
# %matplotlib inline

构建神经网络类

class neuralNetwork():  # neural network class definition
    # initialize the neural network

    def __init__(self, inputNodes, hiddenNodes, outputNodes, learningRate):

        # set number of nodes in each input, hidden, output layer
        self.iNodes = inputNodes
        self.hNodes = hiddenNodes
        self.oNodes = outputNodes

        # learning rate
        self.learnRate = learningRate

        # link weight matrices, wih and who
        # weight inside the arrays are w_i_j, where link is from node i to node j in the next layer
        # w11 w21
        # w12 w22 etc
        self.wih = numpy.random.normal(
            0.0, pow(self.hNodes, -0.5), (self.hNodes, self.iNodes))
        self.who = numpy.random.normal(
            0.0, pow(self.oNodes, -0.5), (self.oNodes, self.hNodes))

        # annoymous func
        self.actiFunc = lambda x: scipy.special.expit(x)

    # train the neural network
    def train(self, inputs_list, targets_list):

        # convert inputs and targets list to 2d array
        inputs = numpy.array(inputs_list, ndmin=2).T
        targets = numpy.array(targets_list, ndmin=2).T

        # calculate signals into hidden layer
        hidden_inputs = numpy.dot(self.wih, inputs)
        # calculate the signals emerging from hidden layer
        hidden_outputs = self.actiFunc(hidden_inputs)

        # calculate signals into final output layer
        final_inputs = numpy.dot(self.who, hidden_outputs)
        # calculate the signals emerging from final output layer
        final_outputs = self.actiFunc(final_inputs)

        # error is the difference of target and output
        output_errors = targets - final_inputs
        # hidden layer error is the output_errors, split by weights, recombined at hidden nodes
        hidden_errors = numpy.dot(self.who.T, output_errors)

        # update the weights for the links between the hidden and output layers
        self.who += self.learnRate * \
            numpy.dot((output_errors*final_outputs*(1.0-final_outputs)),
                      numpy.transpose(hidden_outputs))
        """
        self.who += self.learnRate * \
            numpy.dot((output_errors*final_outputs*(1.0-final_outputs)),
                      hidden_outputs.T)"""
        # between the input and hidden layers
        self.wih += self.learnRate * \
            numpy.dot((hidden_errors*hidden_outputs *
                       (1.0 - hidden_outputs)), numpy.transpose(inputs))

    # query the neural network

    def query(self, inputs_list):

        # convert inputs list to 2d array
        inputs = numpy.array(inputs_list, ndmin=2).T

        # calculate signals into hidden layer
        hidden_inputs = numpy.dot(self.wih, inputs)
        # calculate the signals emerging from hidden layer
        hidden_outputs = self.actiFunc(hidden_inputs)

        # calculate signals into final output layer
        final_inputs = numpy.dot(self.who, hidden_outputs)
        # calculate the signals emerging from final output layer
        final_outputs = self.actiFunc(final_inputs)

        return final_outputs

网络布置

input_nodes = 784  # 28*28
hidden_nodes = 100
output_nodes = 10
learning_rate = 0.3
network = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)

打开训练数据文件

with open('train.csv', 'r') as data_file:
    data_list = data_file.readlines()[1:]  # 除首行外,全部读取到内存中
    # print(data_list)
    data_file.close()

训练神经网络

for record in data_list:
    all_values = record.split(',')
    # make data into 0.01 ~ 1.00
    """ Remains problem
    (why?)
    0.01: prevent 0.00 leading to failing to update the weight
    1.00: just preventing the output value being 1.00 is enough
    """
    inputs = (numpy.asfarray(all_values[1:])/255.0 * 0.99) + 0.01
    # create the target output values (all 0.01, except the desired label which is 0.99)
    # numpy.zeros(): use 0 to pad the array
    targets = numpy.zeros(output_nodes) + 0.01
    # all_values[0] is the label of the record
    targets[int(all_values[0])] = 0.99
    network.train(inputs, targets)

打开测试数据集

test.csv里的数据集是无标签的

# load the test data CSV file into a list
with open('test.csv', 'r') as test_data_file:
    test_data_list = test_data_file.readlines()[1:]
    test_data_file.close()

测试数据并输出

使用test.csv的数据集进行测试输出(无标签)

# from test.csv
test = test_data_list[0] # 调度第0个测试数据
test_values = test.split(',')
test_inputs = (numpy.asfarray(test_values)/255.0 * 0.99) + 0.01
print(network.query(test_inputs))
# print(test_data_list[0].strip().split(','))

使用train.csv的数据集进行测试输出(带标签)

# from train.csv
test = data_list[999]
print('Answer is', test[0])
test_values = test.split(',')
test_inputs = (numpy.asfarray(test_values[1:])/255.0 * 0.99) + 0.01
print(network.query(test_inputs))

疑难杂症

tenserflow把numpy卸载了…

没关系,会安装对应版本的numpy的

Python关于%matplotlib inline报错

这个是 jupyter notebook 或者 jupyter qtconsole 的专属代码,使用%matplotlib inline这段代码可以输出图像。但是vscode编辑器并没有这个功能。(但这并不妨碍vscode是宇宙第一编辑器的事实)

FileNotFoundError

PS F:\Programme_works\Python> python -u "f:\Programme_works\Python\DeepLearning\numRecog\neuralNetwork.py"
Traceback (most recent call last):
  File "f:\Programme_works\Python\DeepLearning\numRecog\neuralNetwork.py", line 106, in \<module\>
    with open('train.csv', 'r') as data_file:
FileNotFoundError: [Errno 2] No such file or directory: 'train.csv'

未找到文件,检查一下文件是否在命令执行时的目录(一般都是vscode打开的文件夹,或者jupyter notebook运行的文件所在的文件夹)

非jupyter编辑器输出csv图像

matplotlib.pyplot.imshow(image_array, cmap='Greys', interpolation='None')

改为

matplotlib.pyplot.imsave('temp.png', image_array, cmap='Greys')

便会保存在目录下

posted @ 2021-02-08 12:24  LacLic  阅读(326)  评论(1编辑  收藏  举报