Day4-前馈神经网络

本文介绍了MNIST手写数字数据集,包括数据集的组成和文件内容,如训练集和测试集的图像及标签。任务是通过前馈神经网络对这个数据集进行分类识别。
摘要由CSDN通过智能技术生成

  数据集简介:

  MINST数据集是由Yann提供的手写数字数据库文件。这个数据集主要包含了60000张的训练图像和10000张的测试图像,数据库的里的图像都是28*28大小的灰度图像,每个像素的是一个八位字节(0~255)。

  数据集内容:  

  主要是下面的四个文件:

        Training set images: train-images-idx3-ubyte.gz (9.9 MB, 解压后 47 MB, 包含 60,000 个样本)
        Training set labels: train-labels-idx1-ubyte.gz (29 KB, 解压后 60 KB, 包含 60,000 个标签)
        Test set images: t10k-images-idx3-ubyte.gz (1.6 MB, 解压后 7.8 MB, 包含 10,000 个样本)
        Test set labels: t10k-labels-idx1-ubyte.gz (5KB, 解压后 10 KB, 包含 10,000 个标签)

  任务:

  利用前馈神经网络,实现手写数字集的分类识别。

import numpy as np
import scipy.special
import matplotlib.pyplot as plt
import os
import struct

# 定义前馈全连接神经网络模型
class NetworkNP:
    # 网络初始化
    def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
        """
        :param inputnodes: 网络输入节点数
        :param hiddennodes: 隐藏层 节点数
        :param outputnodes: 输出层 节点数
        :param learningrate: 学习率
        :param weit_simple:
        """
        # 网络层定义,以及初始化
        self.inodes = inputnodes
        self.hnodes = hiddennodes
        self.onodes = outputnodes
        self.lr = learningrate
        # 权重初始、偏置初始化
        self.w_ih = (np.random.rand(self.hnodes, self.inodes) - 0.5)
        self.w_ho = (np.random.rand(self.onodes, self.hnodes) - 0.5)
        # 激活函数定义Sigmoid
        self.activaltion_function = lambda x: scipy.special.expit(x)
    # 交叉熵损失函数 输入即为网络的输出结果 Y正确的类别 返回交叉熵损失值
    def cross_entropy(self, out, Y):
        # nan_to_num函数:使用0代替数组中的inf和nan值
        loss = np.sum(np.nan_to_num(-Y*np.log(out)-(1-Y)*np.log(1-out)))
        return loss
    # 多分类softmax 返回预测的概率
    def softmax(self, x):
        max_per_row = np.max(x)
        exp_scores = np.exp(x - max_per_row)
        probs = exp_scores / np.sum(exp_scores)
        return probs
    # 模型训练函数
    def train(self, inputs_list, targets_list):
        """
        训练函数
        :param inputs_list: 输入数据
        :param targets_list: 输出返回数据
        """
        ## 前向传播过程
        inputs = np.array(inputs_list, ndmin=2).T
        targets = np.array(targets_list, ndmin=2).T
        hidden_inputs = np.matmul(self.w_ih, inputs)
        hidden_outputs = self.activaltion_function(hidden_inputs)
        final_inputs = np.dot(self.w_ho, hidden_outputs)
        final_outputs = self.softmax(final_inputs)

        output_errors = targets - final_outputs
        hidden_errors = np.dot(self.w_ho.T, output_errors)
        # 反向传播更新参数
        self.w_ho += self.lr * np.dot((output_errors * final_outputs * (1.0 - final_outputs)),
                                     np.transpose(hidden_outputs))
        self.w_ih += self.lr * np.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), np.transpose(inputs))
        return self.cross_entropy(final_outputs, targets)
    # 训练之后的模型
    def query(self, inputs_list):
        inputs = np.array(inputs_list, ndmin=2).T
        hidden_inputs = np.dot(self.w_ih, inputs)
        hidden_outputs = self.activaltion_function(hidden_inputs)
        final_inputs = np.dot(self.w_ho, hidden_outputs)
        final_outputs = self.activaltion_function(final_inputs)
        return final_outputs

# 读取MNIST数据集函数,提前下载好数据集
def load_mnist(path, kind='train'):
    """Load MNIST data from `path`"""
    labels_path = os.path.join(path,
                               '%s-labels.idx1-ubyte'
                               % kind)
    images_path = os.path.join(path,
                               '%s-images.idx3-ubyte'
                               % kind)
    with open(labels_path, 'rb') as lbpath:
        magic, n = struct.unpack('>II',
                                 lbpath.read(8))
        labels = np.fromfile(lbpath,
                             dtype=np.uint8)

    with open(images_path, 'rb') as imgpath:
        magic, num, rows, cols = struct.unpack('>IIII',
                                               imgpath.read(16))
        images = np.fromfile(imgpath,
                             dtype=np.uint8).reshape(len(labels), 784)
    # 返回MNIST图像序列,以及label
    return images, labels

# 1 定义网络参数
input_nodes = 784   # 图像大小为28*28
hidden_nodes = 200  # 隐藏层,200个节点
output_nodes = 10   # 输出层,10个节点分别表示0-9 10个数字
learning_rate = 0.2 # 学习率
# 2 调用神经网络
n = NetworkNP(input_nodes, hidden_nodes, output_nodes, learning_rate)
# 3 读取数据,训练集、测试集
X_train, Y_train = load_mnist(".\\MNIST\\", "train")
X_test, Y_test = load_mnist(".\\MNIST\\", "t10k")
print("训练数据维度为:", X_train.shape, Y_train.shape)
print("测试数据维度为:", X_test.shape, Y_test.shape)

# 4 一部分数据集可视化
fig, ax = plt.subplots(
    nrows = 2,
    ncols = 5,
    sharex = True,
    sharey = True, )
ax = ax.flatten()
for i in range(10):
    img = X_train[Y_train == i][0].reshape(28, 28)
    ax[i].imshow(img, cmap='Greys', interpolation='nearest')
ax[0].set_xticks([]) #去掉坐标轴
ax[0].set_yticks([])
plt.tight_layout() # 布局调整为合适大小
plt.show()

# 5 设置迭代轮数,进行训练
epochs = 1
for e in range(epochs):
    cnt = 0
    err = 0.0
    cnt_true = 0
    for record in zip(X_train, Y_train):
        correct_label = int(record[1])
        inputs = (np.array(record[0]).astype(np.float) / 255.0 * 0.99) + 0.01 # 数据初始化, 把图像归一化到0-1
        outputs = n.query(inputs) # 经过当模型训练之后的预测结果
        label = np.argmax(outputs) # 当前图像被预测的数字值
        if (label == correct_label): #统计正确预测的图像个数
            cnt_true += 1
        targets = np.zeros(output_nodes) + 0.01 # One-hot编码
        targets[int(record[1])] = 0.99
        error = n.train(inputs, targets) # 一次训练损失
        err += error # 当前轮次总损失,以1000个训练样本为一轮
        cnt += 1 # 当前训练样本数
        if cnt % 1000 == 0:
            print("[Epoch %d/%d] 训练准确度为 %.6f"%(cnt, X_train.shape[0], cnt_true/1000))
            err = 0 # 上轮误差归零
            cnt_true = 0 #上轮正确分类样本数清零

    print("Epoch %d 完成训练"%(e+1))
# 6 计算测试集上神经网络准确率
cnt = 0
for record in zip(X_test, Y_test):
    correct_label = int(record[1])
    inputs = (np.array(record[0]) / 255.0 * 0.99) + 0.01
    outputs = n.query(inputs)
    label = np.argmax(outputs)
    if (label == correct_label):
        cnt += 1
print("测试集 准确率为:= ", cnt / float(len(Y_test)))

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值