Java软件研发工程师转行之深度学习(Deep Learning)进阶:手写数字识别+人脸识别+图像中物体分类+视频分类+图像与文字特征+猫狗分类

本文适合于对机器学习和数据挖掘有所了解,想深入研究深度学习的读者
1.对概率基本概率有所了解
2.具有微积分和线性代数的基本知识
3.有一定的编程基础(Python)

1 绪论

  1. 理解深度学习常用模型的算法
  2. 学会应用深度学习库(TheanoPyleanrn2
  3. 学会使用深度学习的方法根据数据集训练模型并开发应用
  4. 基于深度学习的方法对手写数字图片进行自动识别
  5. 基于深度学习的方法自动生成自然的符合逻辑的语句

2 监督学习(Supervised Learning)-分类(Classification)

2.1 基本概念(Basic Concepts)

2.1.1 什么是深度学习?

  • 深度学习是基于机器学习延申出来的一个新的领域,以人脑结构为启发的神经网络算法为起源,加之模型结构深度的增加发展,并伴随着大数据和计算能力的提高而产生的一系列算法。

2.1.2 深度学习是什么时间段发展起来的?

  • 由著名科学家Hinton等人在2006年和2007年于《Sciences》发表的文章被提出。

2.1.3 深度学习能用来干什么?

  • 深度学习作为机器学习延申出来的一个领域,被应用在图像处理与计算机视觉,自然语言处理及语音识别等领域
  • 2006年至今,学术界与工业界在深度学习方面的研究与应用,在以上领域取得了突破性进展。
  • ImageNet为数据库的经典图像中的物体识别竞赛为例,击败了所有传统算法,取得了前所未有的精确度。

2.1.4 深度学习目前有哪些代表性的研究机构?

  • 学术机构以多伦多大学、纽约大学、斯坦福大学为代表,工业界以GoogleFaceBook百度为代表走在深度学习研究与应用的前沿。
from sklearn.datasets import fetch_mldata

mnist = fetch_mldata('MNIST original')
print mnist.data.shape

2.1.5 深度学习范畴

在这里插入图片描述

  • 深度学习的基本模型
    在这里插入图片描述
  • 深度学习与机器学习
    在这里插入图片描述

2.2 神经网络算法(Neural Network)

2.2.1 人脑识别图像

在这里插入图片描述
在这里插入图片描述

  • 深度学习识别图像
    在这里插入图片描述
  • 计算机识别图像
    在这里插入图片描述
  • 神经元
    在这里插入图片描述
  • 实际模型更加复杂
    在这里插入图片描述
  • 与非门可以模拟任何方程
    在这里插入图片描述
    在这里插入图片描述
  • Sigmoid神经元
    在这里插入图片描述
  • 为了模拟更细微的变化,输入和输出值从01,到01之间任何数
    在这里插入图片描述
    在这里插入图片描述

2.2.2 手写数字识别

  • 假设识别一个手写数字图片
    在这里插入图片描述
  • 如果图片是64*64,输入层总共有64*64=4096个神经元
  • 如果图片是28*28,输入层总共有28*28=784个神经元
  • 如果输出层只有一个神经元,大于0.9说明是9,小于0.5说明不是9
  • FeedForward Network:神经网络中没有环,信息单向前传递
    在这里插入图片描述
    在这里插入图片描述
  • 输入层:28*28=784个神经元
  • 每个神经元代表一个像素:0.0表示全白,1.0表示全黑
  • 一个隐藏层:n个神经元,图中有15
  • 输出层:10个神经元。分别代表手写数字识别可能的0-9数字。例如,第一个神经元(代表0)的输出值为1,其他的小于1,数字被识别为0
    在这里插入图片描述
  • 训练集:6000张图片,用来训练
  • 测试集:1000张图片,用来测试准确率
  • x:训练输入,28*28=784d向量,每个值代表灰度图像的像素值
  • y=y(x)10d图像
  • 如果输入的某个图片是数字6,理想的输出:y(x)=(0,0,0,0,0,0,1,0,0,0)
  • 目标函数
    在这里插入图片描述
  • 最小化问题可以用梯度下降解决(gradient descent)
  • C(v)中v有两个变量v1,v2
    在这里插入图片描述
  • 通常可以用微积分解决,如果为v包含的变量过多,则无法用微积分解决
  • 一个变量的情况
    在这里插入图片描述
    在这里插入图片描述

2.2.3 随机梯度下降算法

  • 目标函数
    在这里插入图片描述
  • 变化量
    在这里插入图片描述
  • 以上三个公式推出
    在这里插入图片描述
  • 设定
    在这里插入图片描述
  • 所以C不断减小
    在这里插入图片描述
  • 回顾目标函数
    在这里插入图片描述
  • 权重和偏向更新方程
    在这里插入图片描述
  • 一层神经网络结构
    在这里插入图片描述
  • 两层神经网络结构:MLPMultiLayer Perceptions
    在这里插入图片描述

2.2.4 神经网络识别手写数字

neural network and deep learning

在这里插入图片描述

# coding=utf-8
import numpy as np
import random


class Network(object):
    def __init__(self, sizes):
        """
        构造函数
        :param sizes: 每层神经元的个数,net = Network([2,3,1])
        """
        self.num_layers = len(sizes)
        self.sizes = sizes
        # np.random.randn(y, 1) 随机从正太分布(均值0,方差1)中生成
        self.biases = [np.random.randn(y, 1) for y in sizes[1:]]
        # weights[1]存储连接第二层和第三层的权重
        self.weights = [np.random.randn(x, y) for x, y in zip(sizes[:-1], sizes[1:])]

    def feedforward(self, a):
        """
        return the output of the network if 'a' is input
        :param a:
        :return:
        """
        for b, w in zip(self.biases, self.weights):
            a = sigmoid(np.dot(w, a) + b)
        return a

    def SGD(self, training_data, epochs, mini_batch_size, eta, test_data=None):
        """
        Train the neural network using mini-batch stochastic gradient descent.
        随机梯度下降算法
        :param training_data: 训练集
        training_data is a list of tuples "(x,y)" representing the training inputs and the desired outputs
        :param epochs: 迭代次数
        :param mini_batch_size: 每一小块包含多少个实例
        :param eta: 学习率
        :param test_data: 测试集
        :return:
        """
        if test_data: n_test = len(test_data)
        n = len(training_data)
        for j in xrange(epochs):
            random.shuffle(training_data)  # 随机打乱
            mini_batches = [
                training_data[k:k + mini_batch_size]
                for k in xrange(0, n, mini_batch_size)]  # 从0到n,间隔为mini_batch_size
            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)

    def update_mini_batch(self, mini_batch, eta):
        """
        Update the network's weights and biases by applying gradient descent
        using back propagation to a single mini batch.
        :param mini_batch: list of tuples "(x,y)"
        :param eta: learning rate
        :return:
        """
        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)]
        self.weights = [w - (eta / len(mini_batch)) * nw for w, nw in zip(self.weights, nabla_w)]
        self.biases = [b - (eta / len(mini_batch)) * nb for b, nb in zip(self.biases, nabla_b)]


# sizes = [2, 3, 1]
# print sizes[1:]
# bias = [np.random.randn(y, 1) for y in sizes[1:]]
# print bias
# for x, y in zip(sizes[:-1], sizes[1:]):
#     print (x, y)

net = Network([2, 3, 1])
print net.num_layers
print net.sizes
print net.biases
print net.weights

  • Demo Application
# coding=utf-8
import mnist_loader  # 下载数据
import network  # 神经网络


def main():
    """
    training_data 训练集 50k
    validation_data 验证集 10k
    test_data 测试集 10k
    """
    training_data, validation_data, test_data = mnist_loader.load_data_wrapper()
    print 'training data'
    print 'type:', type(training_data)
    print 'len:', len(training_data)
    print training_data[0][0].shape  # 输入
    print training_data[0][1].shape  # 输出

    print 'validation_data'
    print 'len:', len(validation_data)

    print 'test_data'
    print 'len:', len(test_data)

    '''
    输入层:784个神经元
    隐藏层:30个神经元
    输出层:10个神经元
    training_data:训练集
    epochs:30 迭代次数
    mini_batch_size:10 每次训练实例个数
    eta:3.0 学习率
    test_data:测试集
    '''
    net = network.Network([784, 30, 10])
    net.SGD(training_data, 30, 10, 3.0, test_data=test_data)

    # net = network.Network([784, 100, 10])
    # net.SGD(training_data, 30, 10, 3.0, test_data=test_data)

    # net = network.Network([784, 10])
    # net.SGD(training_data, 30, 10, 3.0, test_data=test_data)


if __name__ == '__main__':
    main()

  • 结果
    在这里插入图片描述
  • 随着每一轮的迭代,手写数字识别的准确率大概在94.76%

2.2.5 基于机器学习手写数字识别

第一种 基于灰度值手写数字识别

  • 核心代码
from collections import defaultdict

# My libraries
import mnist_loader


def main():
    training_data, validation_data, test_data = mnist_loader.load_data()
    # training phase: compute the average darknesses for each digit,
    # based on the training data
    avgs = avg_darknesses(training_data)
    # testing phase: see how many of the test images are classified
    # correctly
    num_correct = sum(int(guess_digit(image, avgs) == digit)
                      for image, digit in zip(test_data[0], test_data[1]))
    print "Baseline classifier using average darkness of image."
    print "%s of %s values correct." % (num_correct, len(test_data[1]))


def avg_darknesses(training_data):
    """ Return a defaultdict whose keys are the digits 0 through 9.
    For each digit we compute a value which is the average darkness of
    training images containing that digit.  The darkness for any
    particular image is just the sum of the darknesses for each pixel."""
    digit_counts = defaultdict(int)
    darknesses = defaultdict(float)
    for image, digit in zip(training_data[0], training_data[1]):
        digit_counts[digit] += 1
        darknesses[digit] += sum(image)
    avgs = defaultdict(float)
    for digit, n in digit_counts.iteritems():
        avgs[digit] = darknesses[digit] / n
    return avgs


def guess_digit(image, avgs):
    """Return the digit whose average darkness in the training data is
    closest to the darkness of ``image``.  Note that ``avgs`` is
    assumed to be a defaultdict whose keys are 0...9, and whose values
    are the corresponding average darknesses across the training data."""
    darkness = sum(image)
    distances = {k: abs(v - darkness) for k, v in avgs.iteritems()}
    return min(distances, key=distances.get)


if __name__ == "__main__":
    main()

  • 识别的准确率只有22.5%
    在这里插入图片描述

第二种 基于SVM手写数字识别

  • 核心代码
def svm_baseline():
    training_data, validation_data, test_data = mnist_loader.load_data()
    # train
    clf = svm.SVC()
    clf.fit(training_data[0], training_data[1])
    # test
    predictions = [int(a) for a in clf.predict(test_data[0])]
    num_correct = sum(int(a == y) for a, y in zip(predictions, test_data[1]))
    print "Baseline classifier using an SVM."
    print "%s of %s values correct." % (num_correct, len(test_data[1]))


if __name__ == "__main__":
    svm_baseline()

  • 识别的准确率只有32.5%

2.2.6 Backpropagation算法

  1. 通过迭代来处理训练集中的实例
  2. 对比经过神经网络后输入层预值(predict value)与真实值(target value)之间
  3. 反方向(从输出层 --> 隐藏层 --> 输入层
  4. 算法详细介绍
  • 输入:数据集,学习率(Learning Rate),一个多层前向神经网络
  • 输出:一个训练好的神经网络(a trained neural network
  • 初始化权重(weights)和偏向(bias):随机初始化到-1或者1之间,或者-0.5到0.5之间,每个单元都有一个偏向
  • 对于每一个训练实例X,执行以下步骤:
    在这里插入图片描述
    在这里插入图片描述
  • 根据误差反向传送
    在这里插入图片描述
  • 终止条件:权重的更新低于某个阈值 预测的错误率低于某个阈值 达到一定的循环次数
  • Overfitting:在训练集上表现好,但是不能泛化到测试集,测试集表现差

2.3 梯度下降(Gradient Descent)

2.4 卷积神经网络(Convolutional Neural Network)

人脸识别

2.5 深度卷积神经网络(Deep Convolutional Neural Network)

视频分类

3 非监督学习(Unsupervised Learning)

3.1 限制波尔兹曼机(Restricted Boltzman Machine)

图像与文字特征合并应用对图像分类

3.2 自动编码(Autoencoder)

图像中的物体识别

3.3 深度信念网络(Deep Belief Network)

猫狗分类

4 小结

持续更新中. . .

猜你喜欢

转载自blog.csdn.net/qq_40507857/article/details/107302887
今日推荐