技术人生,  机器学习

使用numpy搭建基础的神经网络

摘要:本文使用纯numpy完成基础的神经网络搭建,并使用搭建的神经网络实现MNIST手写体数字数据集的分类。

人工神经网络可以有数层,每一层有数个神经元节点,通过训练节点间的参数来训练模型,最终可以用于解决复杂的分类问题。具体的,采用正向传递信号,反向传递误差,并使用梯度下降的方法优化参数。梯度下降即为向负梯度方向优化参数,最终使参数值趋于稳定。

本文计划搭建具有3层的人工神经网络。

注:网络模型参考自《python神经网络编程》

首先引入所需的库。

import numpy as np
import scipy.special      #引入用于使用所需的Sigmoid激活函数

首先,搭建模型类,并初始化基本参数。

class neuralNetwork:
    def __init__(self,inputnodes,hiddennodes,outputnodes,learningrate):
        #每一层节点数量
        self.inodes = inputnodes
        self.hnodes = hiddennodes
        self.onodes = outputnodes

        #设置初始权重
        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.lr = learningrate

        #定义激活函数(expit为S函数)
        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 = self.wih @ inputs
    hidden_outputs = self.activation_function(hidden_inputs)

    #输出层
    final_inputs = self.who @ hidden_outputs
    final_outputs = self.activation_function(final_inputs)

    #计算输出层误差
    output_errors = targets - final_outputs
    #计算隐藏层误差
    hidden_errors = self.who.T @ output_errors

    #隐藏与输出层间权重更新
    self.who += self.lr * ((output_errors * final_outputs * (1 - final_outputs)) @ hidden_outputs.T)
    self.wih += self.lr * ((hidden_errors * hidden_outputs * (1 - hidden_outputs)) @ inputs.T)

测试并输出函数:

def query(self, inputs_list):
    #输入层
    inputs = np.array(inputs_list, ndmin=2).T

    #计算隐藏层
    hidden_inputs = self.wih @ inputs
    hidden_outputs = self.activation_function(hidden_inputs)

    #计算输出层
    final_inputs = self.who @ hidden_outputs
    final_outputs = self.activation_function(final_inputs)

    return final_outputs

使用MNIST数据集训练和测试:

附:CSV格式的MNIST数据集下载地址

input_nodes = 784
hidden_nodes = 200
output_nodes = 10
learning_rate = 0.1

n = neuralNetwork(input_nodes,hidden_nodes,output_nodes,learning_rate)


training_data_file = open('mnist_dataset/mnist_train.csv','r')
training_data_list = training_data_file.readlines()
training_data_file.close()

epochs = 5
#训练
for e in range(epochs):
    print(e+1,'/',epochs)
    t = 0
    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
        n.train(inputs,targets)

        t += 1
        print(t,'\r', end='')


test_data_file = open('mnist_dataset/mnist_test.csv','r')
test_data_list = test_data_file.readlines()
test_data_file.close()

#测试
scorecard = []
print('test')
for record in test_data_list:
    all_values = record.split(',')
    correct_label = int(all_values[0])
    inputs = np.asfarray(all_values[1:]) / 255.0 * 0.99 + 0.01
    outputs = n.query(inputs)
    label = np.argmax(outputs)
    if label == correct_label:
        scorecard.append(1)
    else:
        scorecard.append(0)

#准确率
scorecard_array = np.asarray(scorecard)
print('准确率:', scorecard_array.sum()/scorecard_array.size)

最终运行花费约8-10分钟的时间,达到了0.9737的准确率,结果还是十分理想的。

A WindRunner. VoyagingOne

留言

您的电子邮箱地址不会被公开。 必填项已用*标注