特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记数学公式的开始和结束。如果某条评论中出现了两个$,MathJax 会将两个$之间的内容按照数学公式进行排版,从而导致评论区格式混乱。如果大家的评论中用到了$,但是又不是为了使用数学公式,就请使用\$转义一下,谢谢。

想从头阅读该系列吗?下面是传送门:

前言##

这一篇相当于是深度学习方面的一个 Hello World 吧。深度学习目前大火,吸引了无数人。但是很多时候,想了解深度学习的人总觉得云山雾罩,怎么也看不明白。如果要是有一个能运行的简单的深度学习的例子该多好啊。我这里就来玩一玩深度学习,来一个让大家摸得着、看得见的例子,揭开深度学习的神秘面纱。语言方面,当然是选择对科学计算极度友好的 Python 啦。我当然不会从头撸代码,肯定会使用现成的库的啦。目前最流行的深度学习框架是 Keras,在 Keras 中,它又使用了大名鼎鼎的 TensorFlow 作为后端。在 Python 中,安装这几个库真的是太方便了。最后说一句,我用的是 Python3。

上一篇浮光掠影地讲了一下科学计算,并探讨了一下适合数值计算的语言需要什么样的特色。非常幸运,Python 正好具有这样的特色,准确地说,应该是 Python 中的 numpy 库正好具有这样的特色。上一篇的内容略有过时,比如 IPython Notebook,目前就已经改成 Jupyter Notebook 了。但是在这一篇中,我就不用什么 Notebook 了,我用 PyCharm。

JetBrains 大家都知道啦,JetBrains 全家桶是广大程序员的福利啦。做科学计算,使用 PyCharm 的 Community 版就足够了,没必要下载 Professional 版啦,我更加是不鼓励大家用破解版的啦。

环境安装##

到 JetBrains 的官网下载最新的 PyCharm 2018.3,正如前面所说,Community 版就够了。解压,运行之,用它创建一个 Python 项目,选择使用虚拟环境,如下图:

使用虚拟环境的好处,是可以为这个项目单独安装依赖的库,不用担心为了学一个什么东西而把系统中的 Python 搞得乱七八糟。直接打开 PyCharm 中的 Terminal,就可以进入这个项目的虚拟环境,在这个 Terminal 中运行的命令,默认就在这个项目的虚拟环境中执行。我们可以在这个 Terminal 中运行pip3 install命令安装所有需要的库。在 PyCharm 中使用pip3 install命令时,有一个令人头痛的问题,那就是从国外的源下载的速度太慢,我们可以替换成国内的源。我太懒,都是使用临时替换,只需要添加-i 源地址参数就可以了。例如,要安装 numpy,并且选择从阿里云下载,就使用pip3 install numpy -i https://mirrors.aliyun.com/pypi/simple/命令。如下图:

常用的国内源有:

新版 Ubuntu 要求使用 https 源,要注意。

在这里,我们需要安装 numpy、keras、tensorflow、matplotlib 库,numpy 用来操作向量和矩阵,matplotlib 用来画图。为了能够读取和预处理图片,我还需要使用 PIL,可惜 PIL 不支持 Python 3,不过没关系,使用 Pillow 就好了。安装这几个库只需要如下几个命令:

  1. pip3 install numpy -i https://mirrors.aliyun.com/pypi/simple/
  2. pip3 install tensorflow -i https://mirrors.aliyun.com/pypi/simple/
  3. pip3 install keras -i https://mirrors.aliyun.com/pypi/simple/
  4. pip3 install matplotlib -i https://mirrors.aliyun.com/pypi/simple/
  5. pip3 install Pillow -i https://mirrors.aliyun.com/pypi/simple/

这些库都直接安装到了我们的项目内,不会和系统中的 Python 起冲突。如下图:

PyCharm 最大的优势当然是它的自动代码提示了。不管是写一个.py文件,还是直接使用 PyCharm 中的 Python Console,就是有非常好的代码提示的。Python Console 还有一个非常棒的功能,就是可以观察每一个变量的值,真的是太方便了。如下图:

而在系统的终端中直接运行 Python3,我们是得不到这么好的辅助功能的。如下图:

最简单的深度学习示例##

首先,我们看一个最简单的深度学习示例,就是训练一个能够识别手写数字的密集连接神经网络。在这里,我们需要一个用于训练和测试的数据集,而这个数据集就是 MNIST 数据集,该数据集包含 60000 张用于训练的 28×28 像素的手写数字图片,以及 10000 张用于训练的 28×28 像素的手写数字图片。Keras 能够自动下载该数据集。训练这个神经网络的代码如下:

  1. from keras.datasets import mnist
  2. from keras import models
  3. from keras import layers
  4. from keras.utils import to_categorical
  5. (train_images, train_labels),(test_images, test_labels) = mnist.load_data()
  6. network = models.Sequential()
  7. network.add(layers.Dense(512, activation='relu', input_shape=(28*28,)))
  8. network.add(layers.Dense(10, activation='softmax'))
  9. network.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
  10. train_images = train_images.reshape((60000, 28*28))
  11. train_images = train_images.astype('float32') / 255
  12. test_images = test_images.reshape(10000, 28*28)
  13. test_images = test_images.astype('float32') / 255
  14. train_labels = to_categorical(train_labels)
  15. test_labels = to_categorical(test_labels)
  16. network.fit(train_images, train_labels, epochs=5, batch_size=128)

把以上这几行代码逐行输入到 PyCharm 的 Python 控制台,就可以看到效果了。当输入到(train_images, train_labels),(test_images, test_labels) = mnist.load_data()这一行时,Keras 就会自动下载 MNIST 数据集,可惜的是,由于下载地址被墙的原因,经常会出现下载失败的情况。不过出现下载失败也不用着急,用搜索引擎找一下,很容易找到这个数据集的文件:mnist.npz文件,大小才 11.5M,下载很快的。把下载的这个文件放到~/.keras/datasets目录中即可。

以上所有的代码都输入完成后,就开始了训练,在这个例子中,训练速度非常快,每个周期 4 秒多就完成了,总共 5 个周期。如下图:

可以看到,这个神经网络达到了 98.9% 的精度。下面,我自己手写一个数字测试一下。先打开 Inkscape,自己随便写一个数字,如下图:

保存为~/test.png。然后,用下面的代码把该图片读入内存,并更改大小为 28×28 像素,最后转化为灰度图像。这些操作都使用 PIL 完成。PIL 操作图像那是相当的方便。

  1. from PIL import Image
  2. image = Image.open('/home/youxia/test.png').resize((28,28)).convert('L')

然后,将该图像转化为 numpy 的数组,并将其中的数据处理为 0 到 1 之间的浮点数。

  1. import numpy as np
  2. im = np.array(image)
  3. im = 255 - im
  4. im = im.astype('float32') / 255.0

可以使用 matplotlib 查看一下该图像,代码如下:

  1. import matplotlib.pyplot as plt
  2. plt.imshow(im, cmap=plt.cm.binary)

这是我们处理好之后的图像是下面这个效果,和 MNIST 自带的图像基本基本一致:

下面使用我们前面训练的神经网络来识别该图片,使用 predict 函数即可。识别时,需要将图像数据的 shape 更改为 (1,784):

  1. network.predict(im.reshape(1,784))

返回的值是一个包含是个数字的列表,代表该图片可能为数字 0-9 的概率,可以看到,其中第 6 项,也就是为数字 5 的概率最大,接近于 1:

  1. array([[2.19245143e-11, 7.56166017e-13, 2.06190620e-10, 3.12406366e-04,
  2. 1.12510295e-13, 9.99686599e-01, 8.85503199e-11, 2.70172443e-11,
  3. 2.85677032e-07, 7.55779013e-07]], dtype=float32)

如果不想自己用眼睛去判断哪个概率值最大,可以使用 numpy 的 argmax 函数,如下:

  1. np.argmax(network.predict(im.reshape(1,784)))

返回结果为几,就说明识别出的数字为几,如下:

  1. 5

从密集连接神经网络到卷积神经网络##

前面的例子使用的是密集连接神经网络,每一幅图像都转化为一个以为向量进行处理。在对图像进行深度学习时,最常用的方法是二维卷积神经网络。卷积神经网络的优点一是学到的模式具有平移不变性,在图像某一个区域学习到的模式,如果模式出现在新位置,它仍然能够识别;二是卷积神经网络可以学到模式的空间层次结构。

在 Keras 中,对卷积神经网络也提供了非常强大的支持。上一节的代码,只需要进行简单的修改,就可以构建一个二维卷积神经网络,代码如下:

  1. from keras import layers
  2. from keras import models
  3. from keras.datasets import mnist
  4. from keras.utils import to_categorical
  5. model = models.Sequential()
  6. model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
  7. model.add(layers.MaxPooling2D(2, 2))
  8. model.add(layers.Conv2D(64, (3, 3), activation='relu'))
  9. model.add(layers.MaxPooling2D(2, 2))
  10. model.add(layers.Conv2D(64, (3, 3), activation='relu'))
  11. model.add(layers.Flatten())
  12. model.add(layers.Dense(64, activation='relu'))
  13. model.add(layers.Dense(10, activation='softmax'))
  14. model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
  15. (train_images, train_labels), (test_images, test_labels) = mnist.load_data()
  16. train_images = train_images.reshape((60000, 28, 28, 1))
  17. train_images = train_images.astype('float32') / 255
  18. test_images = test_images.reshape(10000, 28, 28, 1)
  19. test_images = test_images.astype('float32') / 255
  20. train_labels = to_categorical(train_labels)
  21. test_labels = to_categorical(test_labels)
  22. model.fit(train_images, train_labels, epochs=5, batch_size=64)

主要的改变体现在以下几个方面:一是使用 Conv2D 层、MaxPooling 层和 Flatten 层修改了深度学习框架的结构,二是修改了输入数组的形状。除此之外,该深度学习框架使用的激活函数、损失函数都和前面是一样的。训练该网络,发现它比前面的网络训练起来要慢一些,但是达到了 99.3%的准确度。

使用如下代码进行验证:

  1. import numpy as np
  2. from PIL import Image
  3. im = np.array(Image.open('/home/youxia/test.png').resize((28,28)).convert('L'))
  4. im = 255 - im
  5. im = im.astype('float32') / 255.0
  6. print(np.argmax(model.predict(im.reshape(1, 28, 28, 1))))

关于深度学习的理论和实战##

深度学习的理论相对来说比较难,所以我这篇随笔里面就没有怎么介绍。如果想全面了解深度学习的理论,可以阅读这本“圣经”:

但是,光有理论而无实践,这么枯燥的知识是学不下去的。在实战方面,我觉得这本书不错:

我这里的内容,就是参考了这本书。最后,再次对 Python 点赞,用 Python 写科学计算的代码,真的是太舒服了。

版权申明##

该随笔由京山游侠在2018年12月16日发布于博客园,引用请注明出处,转载或出版请联系博主。QQ邮箱:1841079@qq.com

Linux 桌面玩家指南:15. 深度学习可以这样玩的更多相关文章

  1. Linux 桌面玩家指南:18. 我对 Docker 的使用的学习心得

    原文:Linux 桌面玩家指南:18. 我对 Docker 的使用的学习心得 特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记 ...

  2. Linux 桌面玩家指南:18. 使用 Docker 隔离自己的开发环境和部署环境

    特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记数学公式的开始和结束.如果某条评论中出现了两个$,MathJax 会将两个$之 ...

  3. Linux 桌面玩家指南:17. 在 Ubuntu 中使用 deepin-wine,解决一些依赖 Windows 的痛点问题

    特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记数学公式的开始和结束.如果某条评论中出现了两个$,MathJax 会将两个$之 ...

  4. Linux 桌面玩家指南:16. 使用 CUDA 发挥显卡的计算性能

    特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记数学公式的开始和结束.如果某条评论中出现了两个$,MathJax 会将两个$之 ...

  5. Linux 桌面玩家指南:20. 把 Linux 系统装入 U 盘打包带走

    特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记数学公式的开始和结束.如果某条评论中出现了两个$,MathJax 会将两个$之 ...

  6. Linux 桌面玩家指南:19. 深入理解 JavaScript,及其开发调试工具

    特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记数学公式的开始和结束.如果某条评论中出现了两个$,MathJax 会将两个$之 ...

  7. Linux 桌面玩家指南:14. 数值计算和符号计算

    特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记数学公式的开始和结束.如果某条评论中出现了两个$,MathJax 会将两个$之 ...

  8. Linux 桌面玩家指南:13. 使用 Git 及其和 Eclipse 的集成

    特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记数学公式的开始和结束.如果某条评论中出现了两个$,MathJax 会将两个$之 ...

  9. Linux 桌面玩家指南:08. 使用 GCC 和 GNU Binutils 编写能在 x86 实模式运行的 16 位代码

    特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记数学公式的开始和结束.如果某条评论中出现了两个$,MathJax 会将两个$之 ...

随机推荐

  1. Linux时间子系统之二:表示时间的单位和结构

    人们习惯用于表示时间的方法是:年.月.日.时.分.秒.毫秒.星期等等,但是在内核中,为了软件逻辑和代码的方便性,它使用了一些不同的时间表示方法,并为这些表示方法定义了相应的变量和数据结构,本节的内容就 ...

  2. 前端面试题总结二(js原型继承)

    今天这篇文章整理了JS原型和继承的一些知识点,面试的时候  基!本!都!会!问!还不快认真阅读下文,看看你还有哪些知识点需要掌握吧~ 1.原型链 基本思想:利用原型让一个引用类型继承另外一个引用类型的 ...

  3. Get,Post请求方式经典详解

    本文转自:http://blog.csdn.net/findsafety/article/details/47129021 前几天工作中,所有表单我都采用post方法,头儿说那样不好,大型网站上一般都 ...

  4. 【Windows】关于shift跟空格同时按无反应的解决方案

    在玩游戏中我们经常会遇到各种功能键的使用方法 例如shift跟空格,由于我以前经常要加速大跳,突然发现shift跟空格一起按没有效果,语言设置里也没有相关的快捷键设置到,所以网上查询了一番,至此,问题 ...

  5. SSH(Spring_SpringMVC_Hibernate)

    Users实体类 package com.tao.pojo; public class Users { private int id; private String name; private Str ...

  6. linux 搜索某个系统命令的位置

    Which命令 功能简述which命令的作用是在PATH变量指定的路径中搜索某个系统命令的位置并且返回第一个搜索结果.也就是说使用which命令就可以看到某个系统命令是否存在以及执行的到底是哪一个位置 ...

  7. 深入css布局篇(1) — 盒模型 & 元素分类

    深入css布局(1)-- 盒模型 & 元素分类     " 在css知识体系中,除了css选择器,样式属性等基础知识外,css布局相关的知识才是css比较核心和重要的点.今天我们来深 ...

  8. ApplicationHost.config(IIS存储配置区文件)

    对于一个刚刚创建网站,以ASP.NET MVC5为例. 我们并没有在网页的配置文件(web.config)中配置一些处理程序或模块,如处理Session的SessionStateModule模块,映射 ...

  9. 机器学习web服务化实战:一次吐血的服务化之路

    背景 在公司内部,我负责帮助研究院的小伙伴搭建机器学习web服务,研究院的小伙伴提供一个机器学习本地接口,我负责提供一个对外服务的HTTP接口. 说起人工智能和机器学习,python是最擅长的,其以开 ...

  10. 【STM32H7教程】第9章 STM32H7重要知识点数据类型,变量和堆栈

    完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=86980 第9章   STM32H7重要知识点数据类型,变量和堆栈 ...