代码整个运行流程

  1. 參数设置
  2. input数据,设置数据格式
  3. batchFinished(),处理数据(Tokenzier,Stemming,Stopwords)
  4. determineDictionary();  统计计算(TF,IDF)
  5. 归一化
  6. output

一些变量和方法的作用

  • m_Dictionary , m_DocsCounts  变量与 m_OutputCounts变量
    意义
public TreeMap m_Dictionary = new TreeMap();
//TreeMap类型成员变量m_Dictionary 记录<word,新属性index>对;详细类型为TreeMap<String,Integer>, 每个String 的word所映射的index。
private int[] m_DocsCounts ;
// 计算每一个单词在多少个文档中出现过,保存在这个数组。

数组index是word相应映射的index(与m_Dictionary相应)。

private boolean m_OutputCounts = false; 
 //控制m_Dictionary 中的Integer是输出0/1(表示单词是否在文档中出现),还是count单词在文档中出现的次数。

一般要将它设置为true

  • m_minTermFreq 和 m_WordsToKeep
    依据最小词频数(m_minTermFreq)和每一个类最多保留单词数(m_WordsToKeep)过滤单词;还有一种过滤单词的方法是通过stopwordlist。见以下。

  • 内部类Count 类及变量的意义

里有两个变量public int count, docCount;。count是word在一个文档中出现的次数,docCount指的是这个word在几个文档中出现过。

定义这个内部类及变量计算中间量。主要是为了计算TF*IDF方便。


  • 改动详细的TF*IDF公式:

在函数convertInstancewoDocNorm里面例如以下的两段代码中改动就可以。
// Doing TFTransform

if (m_TFTransform == true) {

.....//在这里改动。 源码为 tf(t,d)= log( f(t,d) +1 ).加一是为了防止tf(t,d)=0

}

// Doing IDFTransform
if (m_IDFTransform == true) {
.....//在这里改动, 源码是让idf(t,D)= log(
|D| / |{d \in D : t\ind}| ). D表示全部的文档集。

log(value)中的value肯定大于等于1 //当然这里需保证分母不为0,即word至少在一个文档中出现过,否则可idf(t,D)= log(
|D| / |{d \in D : t\ind}|+1 ).

....// 源码直接让val (t,d)= tf(t,d) * log(
|D| / |{d \in D : t\ind}| )  
}


注意1:这里另一个boolean变量m_OutputCounts。若要用TFIDF公式必须将m_OutputCounts设置为TRUE. 同一时候。m_TFTransform 和m_IDFTransform 一般仅仅设置当中一个为true。否则的话就是两个log相乘。

当然也能够依据须要详细改动(TFIDF详细信息wiki就可以)

经典的TF*IDF设置: 设置变量m_IDFTransform为真。更新更新contained中Key大于等于firstCopy的值为val=val*Math.log( m_NumInstances
/

(double) m_DocsCounts[index.intValue()] ),也即把原先记录的词频fij变成fij*log(文档数/该单词在多少个文档中出现过)。就是我们用的TF-IDF。

注意假设要达到这个效果仅仅有把m_IDFTransform
以及m_OutputCounts同一时候设置成true,并保持m_TFTransform为false(否则的话就是两个log相乘了)。



注意2: TFIDF没有体现单词位置信息。如在一段文字中。处在首句的在一篇文章中。处在首段和末段的段落比較重要。在实际应用中。能够依据不同的位置设置对应的权重。


  • Normalization

    对词频或TFIDF进行归一化。主要是为了消除不同文本长度的影响。

归一化主要针对TF(t,d_单词频率(单词t在文档d中出现的次数)的来进行归一化。

经常用法:


方法1:TF(t,d)= (单词t在文档d中出现的次数)/ (文档d中的总单词数); 
方法2: TF(t,d)=(单词t在文档d中出现的次数)/ (在文档d中出现次数最多的词的出现次数)。

方法3(Weka採用): TFIDF(t,d) ,即 value = value * m_AvgDocLength / docLength(d).注意这里的value是经过m_TFTransform 和m_TFTransform 作用过的值(假设设置为true的话,详细看代码就能够知道)。

当然我们也能够改动StringToWordVector代码,使其支持前两种归一化的方法。以下说下Weka中相关设置方法:
方法1:通过set方法设置
filter.setNormalizeDocLength(new SelectedTag(StringToWordVector.FILTER_NORMALIZE_ALL, StringToWordVector.TAGS_FILTER));
//FILTER_NORMALIZE_ALL 能够换位 FILTER_NORMALIZE_TEST_ONLY
或 
FILTER_NONE
方法2:通过參数字符串设置:
      String optionStr="-R first-last  -W  1000 -prune-rate -1.0 -C -I -N 1";
//-N 1 表示採用FILTER_NORMALIZE_ALL=1 归一化方法。
      filter.setOptions(Utils.splitOptions(optionStr));  

注意:StringToWordVector类中到是没有FILTER_NORMALIZE_TEST_ONLY 这个变量的详细应用。不知为什么。感觉也不是必需。

 
相关变量例如以下:

    /** normalization: No normalization. */
    public static final int FILTER_NONE = 0;  
    /** normalization: Normalize all data. */
    public static final int FILTER_NORMALIZE_ALL = 1;
    /** normalization: Normalize test data only. */

public static final int FILTER_NORMALIZE_TEST_ONLY = 2;  


很多其它关于Normalize的訪问:
weka.filters.unsupervised.attribute.Normalize -S 1.0 -T 0.0 对于数据集中的attribute进行归一化。即对某一列数值型数据进行归一化。

忽略nominal类型的列。

weka.filters.unsupervised.instance.Normalize 忽略nominal类型的列和class index的列。



  • Tokenzier
StringToWordVector中。默认的tokenzier。 -tokenizer  weka.core.tokenizers.WordTokenizer -delimiters " \r\n\t.,;:\'\"()?!"  
Tokenzier的作用就是对于一个长的String,遍历扫描一遍。按那些字符进行切分。

若须要按句子为单位进行切分,能够新建新的Tokenzier,选择- delimiters 为". ! \n ? "或中文句子结束符号“。!

?”等


  • Stemmer

In linguistic
morphology
 and information
retrieval
, stemming is
the process for reducing inflected (or sometimes derived) words to their stem,
base or rootform—generally
a written word form.  如能将cats,catlike。catty等word都转化为词根cat。


这个Stemmmer更像是中文的同义词转换。同一个此类的词包。


StringToWordVector里面的Stemmer主要有两种LovinsStemmer (writeren by Lovins 1968)和 SnowballStemmer(Written
by Martin Porter1980,extend at 2000,建议用这个。但不可直接使用,须要下载包。)两类。这Weka里面自带的Stemmer都是针对英语语言的。自己能够依据须要进行更改。

此外还有PTStemmer等,下载对应的jar包都能够使用。详细使用參考http://weka.wikispaces.com/Stemmers


经常使用的Stemming算法:
LookUp算法: 最简单的算法,建一个lookup table,如 cats -> cat. 若查询的词是cats则返回cat。

特点:简单易用,但table表量比較大。

怎样创建LookUp table: ①对于英语而言能够用构词法简单生成look up table,如将root word “run” 生成“runs,running,runned。runnly,然后查询词典。将当中invalid
derived words 去掉。

②对于汉语的话。就相当于把同义词转换为同一个词? 这样也不太好,应该是把类型”吃了吗”,“吃饭了吗”,“吃饭了没”转化为同一个词。


Affix算法: ①Suffix-stripping 算法: 依据单词的时态规则将是时态词转换为词根。

如将以ed。ing,ly结尾的词去掉其后缀,生成词根。动词的时态大部分有规则。一部分没规则,对于没规则的能够建一个lookup表。二者相结合。


当然还有其它Hybird算法和Multilingual 多语言算法。

对于Stemming也会存在UnderStemming 和 OverStemming两个问题,用时注意。

參考资料:

  • StopWords

这一个过程最好IKAnalyzer分词阶段就过滤掉。

当然对于派生词或中午近义词等。在这里进行过滤会stoplist会更短一点(由于word已经经过Stemming了)。


  • StringToWordVector默认不採用不论什么停止词。
  • 设置採用默认停止词rainbow(英文)m_useStoplist。
当然你能够通过设置变量private boolean m_useStoplist; 等于true(filter.setUseStoplist(true);),採用Weka自带的默认停止词weka.core.StopWords(英文)。 
停止词rainbow列表: http://www.cs.cmu.edu/~mccallum/bow/rainbow/可參考,也能够在程序里面查看StopWords的  public Stopwords()方法。
  • 自己定义停止词。覆盖默认停止词File m_Stopwords

通过StringToWordVector.setStopwords(new File(stopwordfile));方法能够设置自己定义的停止词。同一时候默认的停止词不在生效。

(知道这样的效果就先用着,详细实现代码待细看^_^)



  • Tokenizer、Stemming与 Stopwords的顺序:

(从determineDictionary()函数能够看出来)
  1. 首先Tokenizer。依据单词切割符取出word。

    若默认的 WordTokenizer
    採用" \r\n\t.,;:\'\"()?!"  等英文切割符。

    这一部会把"boy."等后面的‘.'句号或感叹号等都去掉。也可弥补IKAnalyzer中文分词不足。

  2. 然后Stemming。取出词根。

  3. 最后在轮到Stopwords。

    stopwords.is(word)做词根word在stopword的list中,则取出。应该不会对此单词进行map映射和在vector出现。

    filter.setStopwords(new File(stopwordfile)); 
    这样设置一下,就能够将stopwordfile中的word(一行一个)当成stopword啦。



  • SparseInstance

Sparse ARFF files are very similar to ARFF files, but data with value 0 are not be explicitly represented(but这句话的意思就是值为0的属性并不显示).

举个样例StringToWordVector生成以下这个实例集,当中index为0(第一个属性)为class属性(类别在第一列)。

{1 1,2 2,3 3,4 1,5 1,6 1,7 1}
{0 class2,8 1,9 1,10 1,11 1,12 1}

{0 class3,2 2,3 3,6 1,7 1,13 1}  

对于第1个实例(第一行)因为第一个类的名称不是class1。而是默认生产值0。即 0 class1 生成了0 0,所以不显示。以下的‘1 1’ 表示第2个字段的值为1; ‘2 2’ 表示第3个属性字段的值为3. 哈哈 明确了吗。

这里若一个属性的值是未知的missing。则应该表示为?

。 如3 ?

. Note that the omitted values in a sparse instance are 0, they are not "missing" values! If a value is unknown, you must explicitly represent it with a question mark (?).


在Weka里面,全部的string和nominal属性的数据值都会映射为数值,这样做主要是为了计算的高效性。

都会把第一个string或nominal的值存储为0。  SparseInstances这里这样表示并非一个bug,能够视为一个‘display’bug。你保存arff数据会发现和你读取的数据是一样的。


官方介绍:
http://weka.wikispaces.com/ARFF+%28book+version%29#Sparse ARFF files


引用參考文献:

  • 其它
  1. StrngToWordVector默认仅仅对全部的属性进行字符串转word向量,你能够设置指定的属性进行转换。

Range m_SelectedRange 变量就是。能够在进行參数设置

  1. StringToWordVector会将全部的非转换的属性放在处理后的Instances的前面, 当中firstCopy 在函数中的意思是表明前面有多少个非处理的属性。

    如有3个不用处理的属性。firstCopy就是3.



其它參考资料:

若自己读代码有困难。能够參考:
http://quweiprotoss.blog.163.com/blog/static/4088288320100164563922/
http://quweiprotoss.blog.163.com/blog/static/4088288320100165343974/


转载请注明出处:

Weka学习 -- StringToWordVector 源代码学习(1)的更多相关文章

  1. 贪吃蛇游戏C语言源代码学习

    源代码下载地址为:www.clang.cc 阅读学习了源代码,并做了简单的注释和修改,里面只用了链表数据结构,非常适合C语言入门者学习阅读. 程序可在VS2013下编译运行. #include< ...

  2. struts2源代码学习之初始化(一)

    看struts2源代码已有一段时日,从今天開始,就做一个总结吧. 首先,先看看怎么调试struts2源代码吧,主要是下面步骤: 使用Myeclipse创建一个webproject 导入struts2须 ...

  3. [Java] LinkedList / Queue - 源代码学习笔记

    简单地画了下 LinkedList 的继承关系,如下图.只是画了关注的部分,并不是完整的关系图.本博文涉及的是 Queue, Deque, LinkedList 的源代码阅读笔记.关于 List 接口 ...

  4. 开源中国安卓client源代码学习(一) 渐变启动界面

    开源中国安卓client源代码学习(一) 渐变启动界面 准备学习安卓开发, 看到网上有人推荐开源中国安卓client的源代码, 说里面包括了大部分技术, 于是准备好好研究研究. 特开通此系列博客来记录 ...

  5. 读Flask源代码学习Python--config原理

    读Flask源代码学习Python--config原理 个人学习笔记,水平有限.如果理解错误的地方,请大家指出来,谢谢!第一次写文章,发现好累--!. 起因   莫名其妙在第一份工作中使用了从来没有接 ...

  6. nginx源代码学习资源(不断更新)

    nginx源代码学习是一个痛苦又快乐的过程,以下列出了一些nginx的学习资源. 首先要做的当然是下载一份nginx源代码,能够从nginx官方站点下载一份最新的. 看了nginx源代码,发现这是一份 ...

  7. JDK源代码学习系列07----Stack

                                                                   JDK源代码学习系列07----Stack 1.Stack源代码很easy ...

  8. djangorestframework-jwt自带的认证视图进行用户登录验证源代码学习

    Django REST framework JWT djangorestframework-jwt自带的认证视图进行用户登录验证源代码学习 SECRET_KEY = '1)q(f8jrz^edwtr2 ...

  9. JDK源代码学习系列04----ArrayList

                                                                             JDK源代码学习系列04----ArrayList 1 ...

随机推荐

  1. js中typeof的用法汇总[转载]

    http://www.jb51.net/article/43187.htm JavaScript中的typeof其实非常复杂,它可以用来做很多事情,但同时也有很多怪异的表现.本文列举出了它的多个用法, ...

  2. scrolling 优化 避免卡顿

    让我们来瞧瞧在滚动时到底发生了什么.在理解这个问题之前,我们先简要的介绍下浏览器是如何向屏幕绘制内容的.这一切都是从 DOM 树(本质上就是页面中的所有元素)开始的.浏览器先检查拥有了样式的 DOM, ...

  3. setImmediate()

    在循环事件任务完成后马上运行指定代码 以前使用   setTimeout(fn, 0);   Since browsers clamp their timers to 4ms, it really d ...

  4. Python爬虫入门:爬虫基础了解

    有粉丝私信我想让我出更基础一些的,我就把之前平台的copy下来了,可以粗略看一下,之后都会慢慢出. 1.什么是爬虫 爬虫,即网络爬虫,大家可以理解为在网络上爬行的一直蜘蛛,互联网就比作一张大网,而爬虫 ...

  5. 关于ThinkPHP中的时间自动填充

    <?php class NewsModel extends Model{ protected $_auto = array( array('time_at','mydate','1','call ...

  6. 强大又简单的响应式框架——Foundation 网格系统

          前端框架——Foundation     简介 Foundation 用于开发响应式的 HTML, CSS and JavaScript 框架. Foundation 是一个易用.强大而且 ...

  7. 2 将mybatis配置到springmvc中

    为了更方便的连接数据库,将mybatis配置到springMVC中 1).  首先是jar包    多了3个jar  druid 这个是阿里的数据库连接包      mybatis和 mybatis- ...

  8. vue新手入门——谈谈理解

    毕业到现在大概4个月了,从java开发慢慢转到前端开发(其实是因为公司前端人不够),然后开始接触vue.所以我也只是一只小菜鸟. 首先附上vue的官网:vue官网 然后附上一些常用的vue框架,组件之 ...

  9. Java中断机制(interrupt)

    中断线程 在 run() 方法中,如果语句执行到了最会一句,或是遇到 return 方法,或是方法中出现了没有被捕获的异常,run() 方法将会执行结束.在java中,Thread中的interrup ...

  10. [转载] Java NIO教程

    转载自并发编程网 – ifeve.com http://ifeve.com/java-nio-all/ 关于通道(Channels).缓冲区(Buffers).选择器(Selectors)的故事. 从 ...