从HTML文件中抽取正文的简单方案 试验结果

    技术2022-05-20  59

    懒人就直接看结果吧:

    笔者的实验则到此为止,并放弃了神经网络这个解决方案——直接采用这些特征值进行阈值判断,并对一些特殊部分设定过滤规则,这似乎比神经网络的表现来的简单、有效…… 假如仍然坚持神经网络的解决方案,或许,采用: 文本长度,文本长度链接数,上一行的结果 做特征值, 采用三个弱分类器的ada-boost组合分类或许会是一个好的选择。 除此之外,实际上对正文的定义对结果也是有很大的影响。实际上,假如能根据数据化的东西定义某一个类别,那么对于该类别的划分,或许其实已经是可预知的,不如直接设计阈值处理。

    一、 简介 本文是根据alexjc的<The Easy Way to Extract Useful Text from Arbitrary HTML>一文进行实验的结果。原文见: http://ai-depot.com/articles/the-easy-way-to-extract-useful-text-from-arbitrary-html/ ——alexjc原文

    http://blog.csdn.net/lanphaday/archive/2007/08/13/1741185.aspx ——恋花蝶翻译的中英对照版本

    该文章主要内容是讲述如何利用正文相对于其他文本,正文文本与生成该正文所需的html字节码的比值较大的规律,利用神经网络识别出正文过滤过滤广告的效果。主要设计如下:

    1. 解析HTML代码并记下处理的字节数。 2. 以行或段的形式保存解析输出的文本。 3. 统计每一行文本相应的HTML代码的字节数 4. 通过计算文本相对于字节数的比率来获取文本密度 5. 最后用神经网络来决定这一行是不是正文的一部分。

    二、 设计方案 本实验相对原本alexjc设计方案有几点修改:

    1. 用RPROP(弹性BP网络)代替原文的感知器; 2. 由于原文并没有把文本长度、html字节长度做归一化,所以不采用原始文本长度、html字节长度作为特征值。相对的,对归一化后的文本长度、html字节长度,以及前向后向N行等各种组合进行试验。 3. 试验文本为任意在网上选取的10个网页,见附件。 4. 原文并没有提及,如何定义一行文本是否正文,所以这里定义了几个正文类型: a) 内容型正文,特征是有长的连续文字段,定义这些文字段为正文; b) 论坛型,有短的不连续的文字段,定义这些文字段为正文; c) 论坛帖子列表型(部分试验将会对这类型进行训练查看效果,对于论坛帖子列表是否属于正文这里不做讨论……),帖子标题为正文; d) 首页型,定义为没有正文(厄,谁能说出,新浪首页哪些是正文?)

    实验环境: 1. 语言:JAVA,JRE1.5 2. 操作系统:windows xp

    三、 实验过程: 1. 设计实现一个三层RPROP网络(令人惊讶的是,居然在这个领域没有人写一个开源的组件,apache等的开源巨头们都对neural network不感兴趣么?)。

    /* *初始化RPROP对象 * *本函数用于创建训练前的RPROP对象 *参数: * int in_num 输入层个数; * int hidden_unit_num 隐含层节点个数 * int out_num 输出层个数 * */ public RPROP(int in_num, int hidden_unit_num, int out_num)

    /* *初始化RPROP对象 * *本函数用于创建训练后的RPROP对象 *参数: * int in_num 输入层个数; * int hidden_unit_num 隐含层节点个数 * int out_num 输出层个数 * double[][] w1 隐含层权重 * double[][] w2 输出层权重 * double[] b1 隐含层偏离值 * double[] b2 输出层偏离值 */ public RPROP(int in_num, int hidden_unit_num, int out_num, double[][] w1, double[][] w2, double[] b1, double[] b2)

    /* *计算输出结果 * *参数: * double[] p 输入参数 *返回值: * double[] 输出结果 */ public double[] output(double[] p)

    /* *训练 * *参数: * double[][] p * 训练样本集 * double[][][] t * 期望结果集, t[i][j][0] 期望结果, t[i][j][1]误差放大系数 * double goal * 目标误差,注意,本网络用的是“方差”作为误差判断条件 * int epochs * 训练最大次数 */ public void train(double[][] p, double[][][] t, double goal,int epochs) 对于这个实现,有兴趣的朋友在本文最后下载附件。

    2. 选取特征值 在实验中,笔者尝试了各种特征值组合: 1) 文本密度,文本长度,html字节码长度,前后各一行的同样数值;(原文设定) 2) 文本密度,文本长度倒数(归一化),前后各两行的同样数值; 3) 文本所在的html的链接密度(全文文本长度/总链接数,用于加强判断文本类型),文本密度,文本长度/5000(归一化,大于1的当1处理,下文简称为文本长度2),前后两行相同的数值; 4) 文本所在的html的链接密度,文本密度,文本长度2,前后两行相同的数值; 5) 文本所在的html的链接密度,文本密度,文本长度2,前后一行相同的数值; 6) 文本所在的html的链接密度,文本密度,文本长度2,前一行是否正文;

    并规定,网络输出结果0为非正文,1为正文。

    在训练过程中,发现训练过的网络命中率大部分落在0值部分,这是由于论坛这种短文段类型的网页会导致0值过多,训练时对0值过拟合。为了避免这一点,对某一篇网页的某一行的误差乘以该网页的0值与1值数量的比值。

    3. 训练集获取 见附件。这是在笔者常浏览的网页中任意抽取的10个网页。对于期望输出的定义见上文。

    四、实验结果 1. 1~5的实验,任意抽取部分样本集作为训练集,对于训练集拟合的很好,但对于测试集的表现却非常糟糕(请原谅笔者并没有记录实验数据);

    这部分结果表明,以文本密度作为判断是否正文的特征值是有问题的。观察样本集的数据可以发现,即使是内容型的大段文字,也有可能文本密度很低——为了让网页变得更漂亮美观,现在有很多网站都对文字内容加了大段大段修饰用html代码…… 鉴于这一点,笔者最终放弃文本密度作为特征值。而考虑到广告都是带链接的文本,相对的正文连接数则比较少,所以笔者认为,用文本长度/链接数 作为特征值或许会是一个更好的选择。

    2. 6的实验,表现意外的非常的好(好到差点让笔者以为终于找到完美的解决方案……) 确实,即使是在测试集部分的表现也惊人好,但实际上有一个问题:每一行的计算受上一行计算的结果影响。测试集是事先定义每一行的上一行的结果,但在实际使用时,上一行的结果是实时计算出来的,所以就会出现,在某一行出错,导致后面的结果全部出错的情况……

    至此,假如仍然坚持神经网络的解决方案,或许,采用: 文本长度,文本长度链接数,上一行的结果 做特征值, 采用三个弱分类器的ada-boost组合分类或许会是一个好的选择。 除此之外,实际上对正文的定义对结果也是有很大的影响。实际上,假如能根据数据化的东西定义某一个类别,那么对于该类别的划分,或许其实已经是可预知的,不如直接设计阈值处理。

    笔者的实验则到此为止,并放弃了神经网络这个解决方案——直接采用这些特征值进行阈值判断,并对一些特殊部分设定过滤规则,这似乎比神经网络的表现来的简单、有效……

    如果有哪位朋友感兴趣,并用ada-boost进行实验,笔者将非常期待这位朋友来交流下心得:)

     


    最新回复(0)