注意2: TFIDF没有体现单词位置信息
。如在一段文字中。处在首句的在一篇文章中。处在首段和末段的段落比較重要。在实际应用中。能够依据不同的位置设置对应的权重。
对词频或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的列。
StringToWordVector中。默认的tokenzier。 -tokenizer weka.core.tokenizers.WordTokenizer -delimiters " \r\n\t.,;:\'\"()?!"
Tokenzier的作用就是对于一个长的String,遍历扫描一遍。按那些字符进行切分。
若须要按句子为单位进行切分,能够新建新的Tokenzier,选择- delimiters 为". ! \n ? "或中文句子结束符号“。!
?”等
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两个问题,用时注意。
參考资料:
http://en.wikipedia.org/wiki/Stemming (recommending)
http://weka.wikispaces.com/Stemmers
这一个过程最好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()函数能够看出来)
- 首先Tokenizer。依据单词切割符取出word。
若默认的
WordTokenizer 採用" \r\n\t.,;:\'\"()?!" 等英文切割符。这一部会把"boy."等后面的‘.'句号或感叹号等都去掉。也可弥补IKAnalyzer中文分词不足。
- 然后Stemming。取出词根。
- 最后在轮到Stopwords。
stopwords.is(word)做词根word在stopword的list中,则取出。应该不会对此单词进行map映射和在vector出现。
filter.setStopwords(new File(stopwordfile)); 这样设置一下,就能够将stopwordfile中的word(一行一个)当成stopword啦。
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
引用參考文献:
http://quweiprotoss.blog.163.com/blog/static/40882883201103051150347/
- StrngToWordVector默认仅仅对全部的属性进行字符串转word向量,你能够设置指定的属性进行转换。
Range m_SelectedRange 变量就是。能够在进行參数设置
- StringToWordVector会将全部的非转换的属性放在处理后的Instances的前面, 当中firstCopy 在函数中的意思是表明前面有多少个非处理的属性。
如有3个不用处理的属性。firstCopy就是3.
其它參考资料:
若自己读代码有困难。能够參考:
http://quweiprotoss.blog.163.com/blog/static/4088288320100164563922/
http://quweiprotoss.blog.163.com/blog/static/4088288320100165343974/
转载请注明出处:
http://blog.csdn.net/acema/article/details/38050839