深度学习--手写数字识别<一>

2023-11-12

手写字符识别数据集THE MNIST DATABASE of handwritten digits:http://yann.lecun.com/exdb/mnist/
其中训练集60000例,测试集10000例.

加载数据
1. 读取数据

#!/usr/bin/python
# coding:utf-8

import numpy as np
import cPickle
import gzip


def load_data():
    # 读取压缩文件, 返回一个描述符f
    f = gzip.open('../data/mnist.pkl.gz', 'rb')
    # 从文件中读取数据
    training_data, validation_data, test_data = cPickle.load(f)
    f.close()
    return (training_data, validation_data, test_data)


if __name__ == '__main__':
    training_set, validation_set, test_set = load_data()
    print test_set

打印结果:
可以看到数据已经被读取

(array([[ 0.,  0.,  0., ...,  0.,  0.,  0.],
       [ 0.,  0.,  0., ...,  0.,  0.,  0.],
       [ 0.,  0.,  0., ...,  0.,  0.,  0.],
       ..., 
       [ 0.,  0.,  0., ...,  0.,  0.,  0.],
       [ 0.,  0.,  0., ...,  0.,  0.,  0.],
       [ 0.,  0.,  0., ...,  0.,  0.,  0.]], dtype=float32), array([7, 2, 1, ..., 4, 5, 6]))

2 显示

import matplotlib
import matplotlib.pyplot as plt
def ShowImage():
    # 加载数据
    training_set, validation_set, test_set = load_data()
    # 获取validation_set中的data数据(validation_set中存放两个array,第0个为图像数据,第1个为labels)
    # 此时flattened_images大小为(10000*784)
    flattened_images = validation_set[0]
    # 将validation_set中每行数据(即每个图像数据)转换为(28*28)的二维NumPy数组
    images = [np.reshape(f, (-1, 28)) for f in flattened_images]
    # 显示数字图像
    for i in range(16):
        ax = plt.subplot(4, 4, i+1)
        ax.matshow(images[i], cmap = matplotlib.cm.binary)
        plt.xticks(np.array([]))
        plt.yticks(np.array([]))
    plt.show()



if __name__ == '__main__':
    # # 显示图像
    ShowImage()

显示结果:

这里写图片描述

随机梯度下降法SGD:

传统的批量梯度下降法(BGD-Batch Gradient Descent)更新每一个参数时都使用所有的样本进行更新,这样随着样本数量的增大算法会变得非常缓慢.
随机梯度下降法(SGD-Stochastic Gradient Descent)通过每次从所有训练实例中取一个小的样本(sample中包含一个或多个实例)mini-batch来估计梯度向量gradient vector,进行迭代更新.
优点:训练速度快;
缺点:准确度下降,不易于并行实现;

梯度下降法中对weights和biases的更新方式为:

这里写图片描述
这里写图片描述
由于SGD中采用的是通过训练集中的一个采样(mini_batch)对weights和biases进行更新,因此在梯度向量上应该除以采样样本的大小m:
这里写图片描述
这里写图片描述

实现:函数update_mini_batch()中,通过传入的mini_batch(即对原训练集的一个抽样)中的所有训练实例,对整个神经网络的wights和biases进行更新.然后重新选择一个mini_batch来训练.

向量化:

将训练集/验证集/测试集中的labels由[5 0 4 …, 8 4 8]转化为向量形式,即label:0对应向量为
[[ 0.]
[ 0.]
[ 0.]
[ 0.]
[ 0.]
[ 0.]
[ 0.]
[ 0.]
[ 0.]
[ 0.]]
label:1对应向量为
[[ 0.]
[ 1.]
[ 0.]
[ 0.]
[ 0.]
[ 0.]
[ 0.]
[ 0.]
[ 0.]
[ 0.]]
label:2对应向量为
[[ 0.]
[ 0.]
[ 1.]
[ 0.]
[ 0.]
[ 0.]
[ 0.]
[ 0.]
[ 0.]
[ 0.]]
依次类推;
实现:通过函数vectorized_result(j)实现,即传入一个0-9的整数j,返回一个长度为10的向量,第j位为1,其余为0.

定义神经网络结构

 # 定义神经网络结构

class Network(object):

    def __init__(self, sizes):
        # 获取神经网络的层数
        self.num_layers = len(sizes)
        # sizes即每层神经元的个数
        self.sizes = sizes
        # 赋随机值(服从高斯分布),对权重和偏向进行初始化
        #  bais从第2行开始
        self.biases = [np.random.randn(y, 1) for y in sizes[1:]]
        #  zip从传入的可循环的两组量中取出对应数据组成一个tuple
        self.weights = [np.random.randn(y, x) for x, y in zip(sizes[:-1], sizes[1:])]
        # print self.weights
        # print self.biases

    # 根据当前输入利用sigmoid函数来计算输出
    def feedforward(self, a):
        for b, w in zip(self.biases, self.weights):
            a = sigmoid(np.dot(w, a) + b)
        return a

    # epochs训练多少轮, mini_batch_size抽取多少实例,eta学习率
    def SGD(self, training_data, epochs, mini_batch_size, eta, test_data=None):
        # 测试集的大小
        if test_data:
            n_test = len(test_data)
        n = len(training_data)
        # j代表第几轮
        for j in xrange(epochs):
            # 将training_data中的数据随机打乱
            random.shuffle(training_data)
            # mini_batchs每次抽取mini_batch_size大小的数据作为一小块
            mini_batches = [training_data[k:k + mini_batch_size]
                # 从0到n每次间隔mini_batch_size张图片
                for k in xrange(0, n, mini_batch_size)]
            # 对取出来的mini_batchs逐个进行更新,更新weights和biases
            for mini_batch in mini_batches:
                self.update_mini_batch(mini_batch, eta)
            # 每一轮训练后进行评估
            if test_data:
                print "Epoch {0}: {1} / {2}".format(j, self.evaluate(test_data), n_test)
            else:
                print "Epoch {0} complete".format(j)

    # eta:学习率  传入单个的mini_batch,根据其x.y值,对整个神经网络的wights和biases进行更新
    def update_mini_batch(self, mini_batch, eta):
        # 初始化
        nabla_b = [np.zeros(b.shape) for b in self.biases]
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        for x, y in mini_batch:
            # 计算对应的偏导数
            delta_nabla_b, delta_nabla_w = self.backprop(x, y)
            nabla_b = [nb + dnb for nb, dnb in zip(nabla_b, delta_nabla_b)]
            nabla_w = [nw + dnw for nw, dnw in zip(nabla_w, delta_nabla_w)]
        # 权重weights更新 W'k=Wk-(eta/m)&C/&Wk
        self.weights = [w - (eta / len(mini_batch)) * nw
                        for w, nw in zip(self.weights, nabla_w)]
        # 偏向biases更新  b'k=bk-(ets/m)&C/&bk
        self.biases = [b - (eta / len(mini_batch)) * nb
                       for b, nb in zip(self.biases, nabla_b)]

    # 计算对应的偏导数
    def backprop(self, x, y):
        # 返回一个元组(nabla_b,nabla_w)代表成本函数C_x的渐变。
        # nabla_b和nabla_w是numpy数组np.array的逐层列表,类似于self.biases和self.weights.
        # 分别生成与biases weights等大小的0矩阵
        nabla_b = [np.zeros(b.shape) for b in self.biases]
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        # 激活项
        activation = x
        # 列表存储所有的激活,逐层
        activations = [x]
        # 列表存储所有中间向量z,逐层
        zs = []
        for b, w in zip(self.biases, self.weights):
            # 计算中间变量  Z=W*X+b
            z = np.dot(w, activation) + b
            # 列表存储所有中间向量z
            zs.append(z)
            # 激活activation=sigmoid(W*X+b)
            activation = sigmoid(z)
            # 列表存储所有的激活
            activations.append(activation)
        # 反向更新
        # ### 输出层
        # 计算输出层error=Oj(1-Oj)(Tj-Oj);
        # cost_derivative(activations[-1], y)即C对a的梯度:(Tj-Oj)
        # sigmoid_prime(zs[-1])即:Oj(1-Oj)
        delta = self.cost_derivative(activations[-1], y) * sigmoid_prime(zs[-1])
        # 更新输出层的nabla_b,nabla_w
        nabla_b[-1] = delta
        nabla_w[-1] = np.dot(delta, activations[-2].transpose())
        # ### 隐藏层
        # l = 1表示神经元的最后一层,l = 2是第二层,依此类推.反向更新直到初始层
        for l in xrange(2, self.num_layers):
            z = zs[-l]
            sp = sigmoid_prime(z)
            # weights[-l + 1]即下一层的权重,
            delta = np.dot(self.weights[-l + 1].transpose(), delta) * sp
            # 输出C对w,b的偏导
            nabla_b[-l] = delta
            nabla_w[-l] = np.dot(delta, activations[-l - 1].transpose())
        return (nabla_b, nabla_w)

    def evaluate(self, test_data):
        # 返回神经网络输出正确结果的测试输入的数量。 注意,神经网络的输出被假定为最终层中具有最高激活的神经元的指数。
        test_results = [(np.argmax(self.feedforward(x)), y) for (x, y) in test_data]
        return sum(int(x == y) for (x, y) in test_results)

    def cost_derivative(self, output_activations, y):
        # 返回输出激活的偏导数 partial C_x,partial a的向量。
        return (output_activations - y)


# sigmoid函数
def sigmoid(z):
    return 1.0 / (1.0 + np.exp(-z))

# sigmoid函数的导数
def sigmoid_prime(z):
    return sigmoid(z) * (1 - sigmoid(z))

# 向量化
def vectorized_result(j):
    e = np.zeros((10, 1))
    e[j] = 1.0
    return e

# 数据转换,将数据转换为长度为784的numpy.ndarray组成的list,将对应label向量化
def load_data_wrapper():
    tr_d, va_d, te_d = load_data()

    # # 数据转换
    # tr_d是由50000个长度为784的numpy.ndarray组成的tuple
    # 转换后的training_inputs是由50000个长度为784的numpy.ndarray组成的list
    training_inputs = [np.reshape(x, (784, 1)) for x in tr_d[0]]
    training_results = [vectorized_result(y) for y in tr_d[1]]
    # 训练集 training_data
    # zip()返回一个列表的元组,其中每个元组包含从每个参数序列的第i个元素。
    training_data = zip(training_inputs, training_results)
    validation_inputs = [np.reshape(x, (784, 1)) for x in va_d[0]]
    # 验证集 validation_data
    validation_data = zip(validation_inputs, va_d[1])
    test_inputs = [np.reshape(x, (784, 1)) for x in te_d[0]]
    # 测试集 test_data
    test_data = zip(test_inputs, te_d[1])
    return (training_data, validation_data, test_data)
if __name__ == '__main__':
    training_data, valivation_data, test_data =load_data_wrapper()

    # # 显示图像
    # ShowImage()

    net = Network([784, 30, 10])
    # 训练集training_data,训练10轮,每次取样10个作为mini_batch,学习率为3
    net.SGD(training_data, 10, 10, 3.0, test_data=test_data)

输出结果:

Epoch 0: 9106 / 10000
Epoch 1: 9220 / 10000
Epoch 2: 9286 / 10000
Epoch 3: 9313 / 10000
Epoch 4: 9378 / 10000
Epoch 5: 9381 / 10000
Epoch 6: 9414 / 10000
Epoch 7: 9418 / 10000
Epoch 8: 9435 / 10000
Epoch 9: 9419 / 10000

附:

1. BGD批量梯度下降算法/SGD随机梯度下降算法/MBGD小批量梯度下降算法 对比

2.神经网路算法Neural Network

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深度学习--手写数字识别<一> 的相关文章

  • yolo5安装配置及其目标检测

    目录 一 yolo5的下载 1 1 环境配置 1 2 下载git 1 3 下载yolo5源码 二 yolo5的安装 三 图片检测 3 1 准备工作 3 2 执行操作 3 3 结果显示 四 视频检测 4 1 准备工作 4 2 执行操作 4 3
  • AVAudioPlayer播放在线音频文件

    AVAudioPlayer播放在线音频文件 一 原里 AVAudioPlayer是不支持播放在线音频的 但是AVAudioPlayer有一个 initWithData的方法 我们可以把在线音频转换为NSdata 然后播放 二 如代码 NSD
  • kong或nginx配置前端请求跨域

    我们目前使用的是kong作为一个总的api网关 而今天出了一个问题 kong的设置默认是不支持前端跨域的 而前后端分离的项目大量的使用了跨域 前端报错 response to preflight request doesn t pass a

随机推荐

  • 深入理解反射式dll注入技术

    前言 dll 注入技术是让某个进程主动加载指定的 dll 的技术 恶意软件为了提高隐蔽性 通常会使用 dll 注入技术将自身的恶意代码以 dll 的形式注入高可信进程 常规的 dll 注入技术使用 LoadLibraryA 函数来使被注入进
  • 实验2_前馈神经网络实验

    文章目录 实验要求 数据集定义 1 手动实现前馈神经网络解决上述回归 二分类 多分类任务 1 1手动实现前馈网络 回归任务 1 2 手动实现前馈网络 二分类任务 1 3 手动实现前馈网络 多分类 1 4 实验结果分析 2 利用torch n
  • 2022年人工智能学习路线图,清楚明确

    众所周知 人工智能时代已经融入到我们的生活的当中 不论是图像识别还是语音识别的相关产品已经开始落地 就连国家都将人工智能设为了国家战略级发展规划 人工智能开发将会是是未来技术研究的前沿 下面特别给大家整理了人工智能的学习路线 希望大家都能有
  • Dev的splitContainerControl

    1 鼠标移动到这里 鼠标变成左右双箭头此时可以选中splitContainerControl控件 也可以按下鼠标左键左右拖动可以设置分割左右panel的比例 2 SplitterPosition 设置分割的位置 如果想让两个panel左右分
  • 华为云服务器配置教程

    华为云服务器配置教程 云服务器 Xshell 宝塔 自己纯属小白一个 在这里记录一下自己的配置过程 希望像我这样的小白少走一些弯路 主要是最近想弄个服务器玩玩 正好牛客网出了个活动 购买服务器返现 一年的华为云服务器只要9块钱 于是就 白嫖
  • UNIAPP----uniapp里面页面跳转如何到tabbar页面

    在uniapp里面 页面跳转和微信小程序很相似 普通跳转到tabbar页面不报错 跳转到普通页面 定义点击事件 定义跳转地址 跳转tabbar页面 只需将uni navigateTo 更改为uni switchTab 即可
  • Expectation Algebra 期望代数

    Expectation Algebra https www kalmanfilter net background2 html I am going to extensively use the expectation algebra ru
  • LightOJ 1045 Digits of Factorial

    Problem acm hust edu cn vjudge problem visitOriginUrl action id 26765 分析 在base进制下 pow base x 表示最小的 x 1 位数 pow base x 1 表
  • ionic: ionic capacitor run android报错Android Gradle plugin requires Java 11 to run

    报错 capacitor Running Gradle build failed capacitor error capacitor FAILURE Build failed with an exception capacitor capa
  • su -切换用户时,出现-bash: et: command not found的错误,但切换成功

    在Linux下 安装Oracle时 出现如下错误 使用su oracle 切换用户时 会出现 bash et command not found的错误 但切换成功 使用su oracle 直接切换时 不会出现错误 解决办法 重新对系统环境变
  • python包介绍:GeoPandas(初识)

    1 GeoPandas介绍 GeoPandas是一个开源项目 可以更轻松地使用python处理地理空间数据 GeoPandas扩展了Pandas中使用的数据类型DataFrame 允许对几何类型进行空间操作 GeoPandas的目标是使在p
  • rdkafka应用场景和具体接口调用

    Rdkafka是一种高性能 开源 分布式的消息队列 它主要应用于大数据领域 日志收集 消息推送等场景 本文将介绍rdkafka的主要用途以及相关的接口调用方法 一 Rdkafka的应用场景 大数据领域 Rdkafka支持海量数据的高并发处理
  • QT对接百度云实现人脸注册和识别

    文章目录 目录 一 UI界面设计 1 获取Access Token 二 http协议头构造 三 对接百度云人脸注册和识别 四 json数据处理 五 数据 gt UI界面 六 效果 编辑 总结 一 UI界面设计 左上lineedit是处理后的
  • 刷脸支付以人脸为密码的支付方式蔚然成风

    在移动支付高速发展的现在 人们的每一次支付行为都与移动支付息息相关 尤其在中国 移动支付的使用率已经远远超出现金支付 人们对现金不再产生依赖 刷脸支付诞生后 人们对手机也不再产生依赖 因为出行仅靠刷脸即可 我国的移动支付水平在全国都处于领先
  • Springboot 多模块集成mybatis提示:Invalid bound statement (not found)

    1 第一步 检查提示错误信息接口namespace 文件是否对应 MyBatis 文件Mapper 接口定义与Mapper xml 文件定义一致 2 整体项目结构截图如下 从项目结构来看 包含两个子模块包含MyBatis 的mapper 文
  • Element之el-switch上显示文字

    如果我们想要在Element组件库中的switch开关组件上显示文字该怎么做 1 Html部分
  • pclint html报告,PC-lint 9 + 中文手册

    实例简介 PCLINT是一种代码检查工具 还包括中文文档 实例截图 核心代码 Pc Lint9 pclint autorun inf DOS ins choose16 exe choose exe install exe lint exe
  • ACE_Message_Block例子

    include ace OS h include ace Message Block h include ace FILE IO h include
  • 【Absible学习】Ansible常用模块---包管理模块

    yum repository模块 yum repository模块可以管理远程主机上的yum仓库 模块参数 参数 说明 name 必须参数 用于指定要操作的唯一的仓库ID 也就是 repo 配置文件中每个仓库对应的 中括号 内的仓库ID b
  • 深度学习--手写数字识别<一>

    手写字符识别数据集THE MNIST DATABASE of handwritten digits http yann lecun com exdb mnist 其中训练集60000例 测试集10000例 加载数据 1 读取数据 usr b