通用爬虫探索(一):适用一般网站的爬虫
By 苏剑林 | 2017-06-06 | 37982位读者 | 引用这是笔者参加今年的泰迪杯C题的论文简化版。虽然最后只评上了一个安慰奖,但个人感觉里边有些思路对爬虫工作还是有些参加价值的。所以还是放出来供大家参考一下。
简介
一个爬虫可以分为两个步骤:1.把网页下载下来;2.从网页中把所需要的信息抽取出来。这两个步骤都存在相应的技术难点。对于第一个步骤,难度在于如何应对各大网站的反爬虫措施,如访问频率过高则封IP或者给出验证码等,这需要根据不同网站的不同反爬虫措施来设计,理论上不存在通用的可能性。对于第二个步骤,传统的做法是设计对应的正则表达式,随着网站设计上日益多样化,正则表达式的写法也相应变得困难。
显然,想要得到一个通用的爬虫方案,用传统的正则表达式的方案是相当困难的。但如果我们跳出正则表达式的思维局限,从全局的思维来看网站,结合DOM树来解析,那么可以得到一个相当通用的方案。因此,本文的主要内容,是围绕着爬虫的第二个步骤进行展开。本文的工作分为两个部分进行:首先,提出了一个适用于一般网站的信息抽取方案,接着,将这个方案细化,落实到论坛的信息抽取上。
通用爬虫探索(二):落实到论坛爬取上
By 苏剑林 | 2017-06-06 | 25126位读者 | 引用前述的方案,如果爬取的页面仅仅有单一的有效区域,如博客页、新闻页等,那么基本上来说已经足够了。但是,诸如像论坛这样的具有比较明显的层次划分的网站,我们需要进一步细分。因为经过上述步骤,我们虽然能够把有效文本提取出来,但结果是把所有文本放在一块了。
深度优先
而为了给内容进一步“分块”,我们还需要利用DOM树的位置信息。如上一篇的DOM树图,我们需要给每个节点和叶子都编号,即我们需要一个遍历DOM树的方式。这里我们采用“深度优先”的方案。
深度优先搜索算法(英语:Depth-First-Search,简称DFS)是一种用于遍历或搜索树或图的算法。沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。
基于Xception的腾讯验证码识别(样本+代码)
By 苏剑林 | 2017-07-24 | 91493位读者 | 引用去年的时候,有幸得到网友提供的一批腾讯验证码样本,因此也研究了一下,过程记录在《端到端的腾讯验证码识别(46%正确率)》中。
后来,这篇文章引起了不少读者的兴趣,有求样本的,有求模型的,有一起讨论的,让我比较意外。事实上,原来的模型做得比较粗糙,尤其是准确率难登大雅之台,参考价值不大。这几天重新折腾了一下,弄了个准确率高一点的模型,同时也把样本公开给大家。
模型的思路跟《端到端的腾讯验证码识别(46%正确率)》是一样的,只不过把CNN部分换成了现成的Xception结构,当然,读者也可以换VGG、Resnet50等玩玩,事实上对验证码识别来说,这些模型都能够胜任。我挑选Xception,是因为它层数不多,模型权重也较小,我比较喜欢而已。
代码
开学啦!咱们来做完形填空~(讯飞杯)
By 苏剑林 | 2017-09-03 | 199790位读者 | 引用前言
从今年开始,CCL会议将计划同步举办评测活动。笔者这段时间在一创业公司实习,公司也报名参加这个评测,最后实现上就落在我这里,今年的评测任务是阅读理解,名曰《第一届“讯飞杯”中文机器阅读理解评测》。虽说是阅读理解,但事实上任务比较简单,是属于完形填空类型的,即一段材料中挖了一个空,从上下文中选一个词来填入这个空中。最后我们的模型是单系统排名第6,验证集准确率为73.55%,测试集准确率为75.77%,大家可以在这里观摩排行榜。(“广州火焰信息科技有限公司”就是文本的模型)
事实上,这个数据集和任务格式是哈工大去年提出的,所以这次的评测也是哈工大跟科大讯飞一起联合举办的。哈工大去年的论文《Consensus Attention-based Neural Networks for Chinese Reading Comprehension》就研究过另一个同样格式但不同内容的数据集,是用通用的阅读理解模型做的(通用的阅读理解是指给出材料和问题,从材料中找到问题的答案,完形填空可以认为是通用阅读理解的一个非常小的子集)。
虽然,在这次评测任务的介绍中,评测方总有意无意地引导我们将这个问题理解为阅读理解问题。但笔者觉得,阅读理解本身就难得多,这个就一完形填空,只要把它作为纯粹的完形填空题做就是了,所以本文仅仅是采用类似语言模型的做法来做。这种做法的好处是思路简明直观,计算量低(在笔者的GTX1060上可以跑到batch size为160),便于实验。
模型
回到模型上,我们的模型其实比较简单,完全紧扣了“从上下文中选一个词来填空”这一思想,示意图如下。
Linux下的误删大坑与简单的恢复技巧
By 苏剑林 | 2017-07-16 | 28358位读者 | 引用Keras中自定义复杂的loss函数
By 苏剑林 | 2017-07-22 | 426568位读者 | 引用Keras是一个搭积木式的深度学习框架,用它可以很方便且直观地搭建一些常见的深度学习模型。在tensorflow出来之前,Keras就已经几乎是当时最火的深度学习框架,以theano为后端,而如今Keras已经同时支持四种后端:theano、tensorflow、cntk、mxnet(前三种官方支持,mxnet还没整合到官方中),由此可见Keras的魅力。
Keras是很方便,然而这种方便不是没有代价的,最为人诟病之一的缺点就是灵活性较低,难以搭建一些复杂的模型。的确,Keras确实不是很适合搭建复杂的模型,但并非没有可能,而是搭建太复杂的模型所用的代码量,跟直接用tensorflow写也差不了多少。但不管怎么说,Keras其友好、方便的特性(比如那可爱的训练进度条),使得我们总有使用它的场景。这样,如何更灵活地定制Keras模型,就成为一个值得研究的课题了。这篇文章我们来关心自定义loss。
输入-输出设计
Keras的模型是函数式的,即有输入,也有输出,而loss即为预测值与真实值的某种误差函数。Keras本身也自带了很多loss函数,如mse、交叉熵等,直接调用即可。而要自定义loss,最自然的方法就是仿照Keras自带的loss进行改写。
RNN模型中输入的重要性的评估
By 苏剑林 | 2017-09-10 | 29425位读者 | 引用Saliency Maps for RNN
RNN是很多序列任务的不二法门,比如文本分类任务的常用方法就是“词向量+LSTM+全连接分类器”。如下图
假如这样的一个模型可以良好地工作,那么现在考虑一个任务是:如何衡量输入$w_1,\dots,w_n$对最终的分类结果的影响的重要程度(Saliency)呢?例如假设这是一个情感分类任务,那么怎么找出是哪些词对最终的分类有较为重要的影响呢?本文给出了一个较为直接的思路。
思路的原理很简单,因为我们是将RNN最后一步的状态向量(也就是绿色阴影所代表的向量)传递给后面的分类器进行分类的,因此最后一步的状态向量$\boldsymbol{h}_n$就是一个目标向量。而RNN是一个递推的过程,
浅谈神经网络中激活函数的设计
By 苏剑林 | 2017-10-26 | 45844位读者 | 引用激活函数是神经网络中非线性的来源,因为如果去掉这些函数,那么整个网络就只剩下线性运算,线性运算的复合还是线性运算的,最终的效果只相当于单层的线性模型。
那么,常见的激活函数有哪些呢?或者说,激活函数的选择有哪些指导原则呢?是不是任意的非线性函数都可以做激活函数呢?
这里探究的激活函数是中间层的激活函数,而不是输出的激活函数。最后的输出一般会有特定的激活函数,不能随意改变,比如二分类一般用sigmoid函数激活,多分类一般用softmax激活,等等;相比之下,中间层的激活函数选择余地更大一些。
浮点误差都行!
理论上来说,只要是非线性函数,都有做激活函数的可能性,一个很有说服力的例子是,最近OpenAI成功地利用了浮点误差来做激活函数,其中的细节,请阅读OpenAI的博客:
https://blog.openai.com/nonlinear-computation-in-linear-networks/
或者阅读机器之心的介绍:
https://mp.weixin.qq.com/s/PBRzS4Ol_Zst35XKrEpxdw
最近评论