前面一章,我们通过了梯度下降算法实现目标函数的最小化,从而学习了该神经网络的权重和偏置,但是有一个问题并没有考虑到,那就是如何计算代价函数的梯度,本章的重点就是介绍计算这些梯度的快速算法——反向传播算法,首先先介绍一下上图中以及下面文章中会出现的一些数学符号: $L$ : 表示网络层数 $b_j^l$ : 表示第$l$层的第$j$个神经元的偏置 $a_j^l$ : 表示第$l$层的第$j$个神经元的激活值 $w_{j k}^{l}$ : 表示从$l-1$层的第$k$个神经元到第$l$层的第$j$个神经元的连接上的权重 $w^l$ : 权重矩阵,其中元素表示$l-1$层连接到$l$层神经元的权重 $b^l$ : 第$l$层神经元的偏置向量 $z^l$ : 第$l$层神经元的带权输入向量 $a^l$ : 第$l$层每个神经元激活值构成的向量 $\delta_{j}^{l}$ : 第$l$层第$j$个神经元的误差 本篇文章是公式重灾区,但是涉及的知识并不高级,这也说明一个道理: 很多看似显而易见的想法只有在事后才变得显而易见。 热⾝:神经⽹络中使⽤矩阵快速计算输出的⽅法 通过第一章,我们已经知道每个神经元的激活值的计算方法,根据上面的公式,我们可以得出$a_j^l$的表达方式: \[ a_{j}^{l}=\sigma\left(\sum_{k} w_{j k}^{l} a_{k}^{l-1}+b_{j}^{l}\right) \] 举个例子:$a_3^2$表示第二层的第三个神经元的激活值,那么该输出值怎么同上一层的输出值以及权重关联起来的呢,根据激活值的计算公式,我们可以得出: \[ \begin{aligned} a_3^2 &= \sigma(w_{3 1}^{2} a_1^1 + w_{3 2}^{2} a_2^1+ w_{3 3}^{2} a_3^1 + b_3^2 ) \\ &= \sigma\left(\sum_{k=1}^3 w_{3 k}^2 a_{k}^1 + b_3^2 \right) \end{aligned} \]

Neural Networks and Deep Learning 是由 Michael Nielsen 编写的开源书籍,这本书主要讲的是如何掌握神经网络的核心概念,包括现代技术的深度学习,为你将来使⽤神经网络和深度学习打下基础,以下是我的读书笔记。 神经网络是一门重要的机器学习技术,它通过模拟人脑的神经网络来实现人工智能的目的,所以其也是深度学习的基础,了解它之后自然会受益颇多,本章主要是以识别手写字这个问题来贯穿整篇,那么,人类的视觉系统和神经网络到底在识别一个目标的时候,主要区别在哪? 人类视觉系统:通过数十亿年不断地进化与学习,最终能够极好地适应理解视觉世界的任务,从而无意识地就可以对目标进行判断识别 神经网络:通过提供的样本来推断出识别某种目标的规则,作为判断标准 本章的主要内容是介绍神经网络的基本概念以及引入一个识别手写数字的例子来加深我们的理解,你将了解到: 两个重要的人工神经元:感知器和S型神经元 神经⽹络的架构 ⼀个简单的分类⼿写数字的⽹络 标准的神经网络学习算法:随机梯度下降算法 感知器 1943年,心理学家McCulloch和数学家Pitts发表了《A logical calculus of the ideas immanent in nervous activity》,其中提出了抽象的神经元模型MP,但是在这个模型中权重都是要求提前设置好才可以输出目标值,所以很遗憾,它不可以学习,但这不影响此模型给后来者带来的影响,比如感知器: 感知器是Frank Rosenblatt提出的一个由两层神经元组成的人工神经网络,它的出现在当时可是引起了轰动,因为感知器是首个可以学习的神经网络 感知器的工作方式如下所示: $x_{1},x_{2},x_{3}$ 分别表示三个不同的二进制输入,output则是一个二进制输出,对于多种输入,可能有的输入成立有的不成立,在这么多输入的影响下,该如何判断输出output呢?Rosenblatt引入了权重来表示相应输入的重要性。 对于$x_{1},x_{2},...,x_{j}$个输入,每个输入都有对应的权重$w_{1},w_{2},...,w_{j}$,最后的输出output由每个输入与其对应的权重相乘之和与阈值之差$\sum _{j} w{_j}x{_j}$来决定,如下: 假设$b=-threshold$且$w$和$x$对应权重和输⼊的向量,即: $x=(x_{1},x_{2},...,x_{j})$ $w=(w_{1},w_{2},...,w_{j})$ 那么感知器的规则可以重写为: 这就是感知器的数学模型,是不是就像一个逻辑回归模型?只要将感知器输出规则替换为($f(x)=x$),后面我们会知道这称之为激活函数,其实这种感知器叫做线性单元。 它的出现让我们可以设计学习算法,从而实现自动调整人工神经元的权重和偏置,与此同时output也会随之改变,这就是学习!如果你有兴趣可以看我用python写的一个感知器自动学习实现与非门,代码在nndl_chapter01。 说句题外话,由于感知器是单层神经网络,它只能实现简单的线性分类任务,所以它无法对异或问题进行分类,异或的真值表如下: $x$ $y$ $output$ 0 0 0 0 1 1 1 0 1 1 1 0 可以看出来,异或问题是线性不可分的,不信你画个坐标轴试试看,那么问题来了?怎么解决,大部分都能很快地想出解决方案,既然感知器可以实现线性分类,也就是说实现与非门是没有问题的,逻辑上来说我们可以实现任何逻辑功能(比如四个与非门实现异或),但前提是为感知器加入一个隐藏层,意思就是多了一个隐藏层的神经网络之后,就可以解决异或问题。

上一次推文写了JupyterLab:程序员的笔记本神器,介绍的是如何在web端打造一个便捷的开发环境,发出后反响还不错 因此我决定再写几篇能提升程序员工作以及学习效率的文章,如果能形成一个系列那是最好~如果你有自己的效率工具以及方案,欢迎留言讨论 什么是oh-my-zsh 诸位大佬都知道,Linux下shell默认是bash,但还有一种shell,叫做zsh它比bash更加强大,功能也更加完善,zsh虽说功能强大,但是配置比较复杂导致流行度不是很高 但是好东西终究是好东西,开源界的大佬们是不会让明珠蒙尘,我等伸手党也是可以直接搭顺风车的,感谢robbyrussell大佬的开源项目 oh-my-zsh 吧,从此使用zsh也就几行命令的事情 oh-my-zsh项目目前有80k+star,贡献者超过1300,并且提供了200多个可选插件(rails,git,OSX,hub,capistrano,brew,ant,php,python等),以及超过140个主题供你选择,安装后你将享受以下特性: 首先兼容bash 自动cd:只需输入目录的名称即可 命令选项补齐,比如输入git,然后按Tab,即可显示出git都有哪些命令 目录一次性补全:比如输入Doc/doc按Tab键会自动变成Documents/document/ 插件和主题支持(插件能进一步提升效率) 安装oh-my-zsh 在安装oh-my-zsh之前,首先需要安装好zsh: yum install -y zsh 切换shell为zsh: chsh -s /bin/zsh 重启终端: # 查看当前shell echo $SHELL 输出/bin/zsh表示成功 oh-my-zsh的安装非常简单,参考官网,执行如下命令即可: # curl sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" # wegt sh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)" 输出如下表示成功: 配置oh-my-zsh 和bash不同,zsh的配置文件是~/.zshrc,实际上oh-my-zsh的默认配置也够我们使用了,但是这样其真正的强大之处并不能得到很好的体现,因此我们可以继续看看对应的插件和主题功能 关于主题 oh-my-zsh的主题非常丰富,可以用如下命令查看已有主题: ls .oh-my-zsh/themes 个人比较喜欢简单的,因此用了wedisagree主题,进入.zshrc配置文件进行修改 vim ~/.zshrc 将第11行改为ZSH_THEME="wedisagree",然后:wq保存退出,主题就自动生效 关于插件 oh-my-zsh的插件生态非常丰富,下面列出来的是我个人比较常用的插件,如果你有兴趣,可以取发掘能提高自身效率的插件~ 注意:如果操作过程中出现_arguments:448: _vim_files: function definition file not found错误,请执行:rm -f ~/.

JupyterLab对于Jupyter Notebook有着完全的支持 JupyterLab是一个交互式的开发环境,是jupyter notebook的下一代产品,集成了更多的功能,等其正式版发布,相信那时就是jupyter notebook被取代的时候 通过使用JupyterLab,能够以灵活,集成和可扩展的方式处理文档和活动: 可以开启终端,用于交互式运行代码,完全支持丰富的输出 支持Markdown,Python,R,LaTeX等任何文本文件 增强notebook功能 更多插件支持 如果你在日常生活中,有以下需求,我觉得你可以安装一个JupyterLab 随时随地希望试验一些代码片段 多语言、多文档支持 有记笔记需求(文本+代码) 安装 接下来,我将以Python为默认语言来搭建JupyterLab,首先确认你安装好了Python基本环境: # 一行命令搞定 pip install jupyterlab # 安装ipython pip install ipython 如果在服务器使用的话,个人建议还是设置一下密码,配置过程如下: # 进入ipython交互环境 ipython 生成密码: from notebook.auth import passwd passwd() # 输入你自己设置登录JupyterLab界面的密码 然后会有一串输出,记得复制下来,等会配置需要使用 修改JupyterLab 配置文件: jupyter lab --generate-config 修改以下配置: c.NotebookApp.allow_root = True c.NotebookApp.open_browser = False c.NotebookApp.password = '刚才复制的一串数字粘贴到这里' 为了后续能够方便地安装插件,请先安装好node环境,假设你安装好,接下来演示一下怎么安装插件: # 以安装一个生成目录的插件为例 jupyter labextension install @jupyterlab/toc # 查看安装的插件 jupyter labextension list 安装完毕后,打开JupyterLab:

这篇文章的题目有点大,但这并不是说我自觉对Python爬虫这块有多大见解,我只不过是想将自己的一些经验付诸于笔,对于如何写一个爬虫框架,我想一步一步地结合具体代码来讲述如何从零开始编写一个自己的爬虫框架 2018年到如今,我花精力比较多的一个开源项目算是Ruia了,这是一个基于Python3.6+的异步爬虫框架,当时也获得一些推荐,比如Github Trending Python语言榜单第二,目前Ruia还在开发中,Star数目不过700+,如果各位有兴趣,欢迎一起开发,来波star我也不会拒绝哈~ 什么是爬虫框架 说这个之前,得先说说什么是框架: 是实现业界标准的组件规范:比如众所周知的MVC开发规范 提供规范所要求之基础功能的软件产品:比如Django框架就是MVC的开发框架,但它还提供了其他基础功能帮助我们快速开发,比如中间件、认证系统等 框架的关注点在于规范二字,好,我们要写的Python爬虫框架规范是什么? 很简单,爬虫框架就是对爬虫流程规范的实现,不清楚的朋友可以看上一篇文章谈谈对Python爬虫的理解,下面总结一下爬虫流程: 请求&响应 解析 持久化 这三个流程有没有可能以一种优雅的形式串联起来,Ruia目前是这样实现的,请看代码示例: 可以看到,Item & Field类结合一起实现了字段的解析提取,Spider类结合Request * Response类实现了对爬虫程序整体的控制,从而可以如同流水线一般编写爬虫,最后返回的item可以根据使用者自身的需求进行持久化,这几行代码,我们就实现了获取目标网页请求、字段解析提取、持久化这三个流程 实现了基本流程规范之后,我们继而就可以考虑一些基础功能,让使用者编写爬虫可以更加轻松,比如:中间件(Ruia里面的Middleware)、提供一些hook让用户编写爬虫更方便(比如ruia-motor) 这些想明白之后,接下来就可以愉快地编写自己心目中的爬虫框架了 如何踏出第一步 首先,我对Ruia爬虫框架的定位很清楚,基于asyncio & aiohttp的一个轻量的、异步爬虫框架,怎么实现呢,我觉得以下几点需要遵守: 轻量级,专注于抓取、解析和良好的API接口 插件化,各个模块耦合程度尽量低,目的是容易编写自定义插件 速度,异步无阻塞框架,需要对速度有一定追求 什么是爬虫框架如今我们已经很清楚了,现在急需要做的就是将流程规范利用Python语言实现出来,怎么实现,分为哪几个模块,可以看如下图示: 同时让我们结合上面一节的Ruia代码来从业务逻辑角度看看这几个模块到底是什么意思: Request:请求 Response:响应 Item & Field:解析提取 Spider:爬虫程序的控制中心,将请求、响应、解析、存储结合起来 这四个部分我们可以简单地使用五个类来实现,在开始讲解之前,请先克隆Ruia框架到本地: # 请确保本地Python环境是3.6+ git clone https://github.com/howie6879/ruia.git # 安装pipenv pip install pipenv # 安装依赖包 pipenv install --dev 然后用PyCharm打开Ruia项目: 选择刚刚pipenv配置好的python解释器: 此时可以完整地看到项目代码: 好,环境以及源码准备完毕,接下来将结合代码讲述一个爬虫框架的编写流程 Request & Response

爬虫也可以称为Python爬虫 不知从何时起,Python这门语言和爬虫就像一对恋人,二者如胶似漆 ,形影不离,你中有我、我中有你,一提起爬虫,就会想到Python,一说起Python,就会想到人工智能……和爬虫 所以,一般说爬虫的时候,大部分程序员潜意识里都会联想为Python爬虫,为什么会这样,我觉得有两个原因: Python生态极其丰富,诸如Request、Beautiful Soup、Scrapy、PySpider等第三方库实在强大 Python语法简洁易上手,分分钟就能写出一个爬虫(有人吐槽Python慢,但是爬虫的瓶颈和语言关系不大) 任何一个学习Python的程序员,应该都或多或少地见过甚至研究过爬虫,我当时写Python的目的就非常纯粹——为了写爬虫。所以本文的目的很简单,就是说说我个人对Python爬虫的理解与实践,作为一名程序员,我觉得了解一下爬虫的相关知识对你只有好处,所以读完这篇文章后,如果能对你有帮助,那便再好不过 什么是爬虫 爬虫是一个程序,这个程序的目的就是为了抓取万维网信息资源,比如你日常使用的谷歌等搜索引擎,搜索结果就全都依赖爬虫来定时获取 看上述搜索结果,除了wiki相关介绍外,爬虫有关的搜索结果全都带上了Python,前人说Python爬虫,现在看来果然诚不欺我~ 爬虫的目标对象也很丰富,不论是文字、图片、视频,任何结构化非结构化的数据爬虫都可以爬取,爬虫经过发展,也衍生出了各种爬虫类型: 通用网络爬虫:爬取对象从一些种子 URL 扩充到整个 Web,搜索引擎干的就是这些事 垂直网络爬虫:针对特定领域主题进行爬取,比如专门爬取小说目录以及章节的垂直爬虫 增量网络爬虫:对已经抓取的网页进行实时更新 深层网络爬虫:爬取一些需要用户提交关键词才能获得的 Web 页面 不想说这些大方向的概念,让我们以一个获取网页内容为例,从爬虫技术本身出发,来说说网页爬虫,步骤如下: 模拟请求网页资源 从HTML提取目标元素 数据持久化 什么是爬虫,这就是爬虫: """让我们根据上面说的步骤来完成一个简单的爬虫程序""" import requests from bs4 import BeautifulSoup target_url = 'http://www.baidu.com/s?wd=爬虫' # 第一步 发起一个GET请求 res = requests.get(target_url) # 第二步 提取HTML并解析想获取的数据 比如获取 title soup = BeautifulSoup(res.text, "lxml") # 输出 soup.title.text title = soup.title.text # 第三步 持久化 比如保存到本地 with open('title.