|
Posted on
2008-08-04 10:14
烈火123
阅读( 1359)
评论()
编辑
收藏
举报
- 原理:1、先给本聚类内的所有文档进行分词,然后用一个字典保存每个词出现的次数
- 2、遍历每个词,得到每个词在所有文档里的IDF值,和在本聚类内出现的次数(TF)相乘的值
- 3、用一个字典(key是词,value是TF*IDF权重)来保存所有的词信息,然后按value对字典排序,最后取权重排名靠前的几个词作为关键词测试输入如下
- ================================
- a 奥运 拳击 入场券 基本 分罄 邹市明 夺冠 对手 浮出 水面
- a 股民 要 清楚 自己 的 目的
- a 印花税 之 股民 四季
- a ASP.NET 自定义 控件 复杂 属性 声明 持久性 浅析
- a 运动员 行李 将 “后 上 先 下” 奥运 相关 人员 行李 实名制
- a asp.net 控件 开发 显示 控件 内容
- a 奥运 票务 网上 成功 订票 后 应 及时 到 银行 代售 网点 付款
- a 某 心理 健康 站 开张 后 首 个 咨询 者 是 位 新 股民
- a 残疾 女 青年 入围 奥运 游泳 比赛 创 奥运 历史 两 项 第一
- a 介绍 一 个 ASP.net MVC 系列 教程
- a 在 asp.net 中 实现 观察者 模式 ,或 有 更 好 的 方法 (续)
- a 输 大钱 的 股民 给 我们 启迪
- a Asp.Net 页面 执行 流程 分析
- a 杭州 股民 放 鞭炮 庆祝 印花税 下调
- ================================
- 数据还是昨天的数据,但每个文章前面都加了个a,所以这个词的IDF肯定很低,如果单村用词频来提取关键词,这个a肯定被当场关键词了,所以要乘以IDF值来调整特征提取的精度。我们要用程序把上面的文档分成3类,并提取每个类的两个关键词
- 我给TFIDFMeasure类加了一个GetKeyword的方法,第一个参数是传入几个文档id列表,第二个参数是要在这几个文档里提取几个关键词,下面是使用该方法的代码
- WawaKMeans kmeans = new WawaKMeans(data, K);
- kmeans.Start();
- WawaCluster[] clusters = kmeans.Clusters;
- StringBuilder sb = new StringBuilder();
- foreach (WawaCluster cluster in clusters)
- {
- List<int> members = cluster.CurrentMembership;
-
-
- IEnumerable<string> keywords = tf.GetKeyword(cluster.CurrentMembership, 2);
- StringBuilder sbTemp = new StringBuilder();
- sbTemp.Append("---------");
- foreach (string s in keywords)
- {
- sbTemp.AppendFormat("{0},", s);
- }
- sbTemp.Append("-------/r/n");
- Console.WriteLine(sbTemp);
-
- sb.Append(sbTemp.ToString());
- foreach (int i in members)
- {
- Console.WriteLine(docs);
- sb.AppendFormat("{0}/r/n", docs);
- }
- }
- 再看GetKeyword方法的实现
- public IEnumerable<string> GetKeyword(List<int> arr, int count)
- {
-
- List<string> allWords = new List<string>();
- foreach (int i in arr)
- {
-
- allWords.AddRange(GetDistinctWords(_tokenizer.Partition(_docs)));
- }
-
- Dictionary<string , int> tfDict = SortByDuplicateCount(allWords);
-
-
- Dictionary<string,float> tfidfDict = new Dictionary<string, float>(tfDict.Count);
- foreach (KeyValuePair<string, int> pair in tfDict)
- {
- int tremIndex;
- if(_tremIndex.TryGetValue(pair.Key,out tremIndex))
- {
- float idf = GetInverseDocumentFrequency(tremIndex);
- tfidfDict.Add(pair.Key, pair.Value * idf);
- }
- }
-
- tfidfDict = GetSortByValueDict(tfidfDict);
-
- int keywordCount = count;
- if (keywordCount > tfidfDict.Count)
- keywordCount = tfidfDict.Count;
-
-
- string[] keywordArr = new string[tfidfDict.Count];
- tfidfDict.Keys.CopyTo(keywordArr,0);
-
- List<string> result = new List<string>(keywordCount);
- int tempCount = 0;
- foreach (string str in keywordArr)
- {
- tempCount++;
- result.Add(str);
- if(tempCount >=keywordCount) break;
- }
- return result;
- }
- 这里面用到一个SortByDuplicateCount方法,是对一个集合里的元素按重复次数排序,输出一个字典,字典的key是原始元素,value是出现次数,并按出现次数从大到小排序,像 { "abcd", "ab", "b", "a", "abcd", "ab", "ab", "ab", "cd", "cd", "cd" }这样一个集合应该输入如下结果。
- ab-4
- cd-3
- abcd-2
- b-1
- a-1
- 原理是先用一个字典计算每个元素的出现次数,然后把该字典按value的大小排序,下面是实现代码
- public static Dictionary<T, int> SortByDuplicateCount<T>(IList<T> inputList)
- {
-
- Dictionary<T, int> distinctDict = new Dictionary<T, int>();
- for (int i = 0; i < inputList.Count; i++)
- {
-
- if (distinctDict.ContainsKey(inputList))
- distinctDict[inputList]++;
- else
- distinctDict.Add(inputList, 1);
- }
- Dictionary<T, int> sortByValueDict = GetSortByValueDict(distinctDict);
- return sortByValueDict;
- }
- 这里用到一个把一个字典按值的大小排序的方法GetSortByValueDict,代码如下,是泛型的
- public static Dictionary<K, V> GetSortByValueDict<K,V>(IDictionary<K, V> distinctDict)
- {
-
- V[] tempSortList = new V[distinctDict.Count];
- distinctDict.Values.CopyTo(tempSortList, 0);
- Array.Sort(tempSortList);
- Array.Reverse(tempSortList);
-
- Dictionary<K, V> sortByValueDict =
- new Dictionary<K, V>(distinctDict.Count);
- for (int i = 0; i < tempSortList.Length; i++)
- {
- foreach (KeyValuePair<K, V> pair in distinctDict)
- {
-
- if (pair.Value.Equals(tempSortList) && !sortByValueDict.ContainsKey(pair.Key))
- sortByValueDict.Add(pair.Key, pair.Value);
- }
- }
- return sortByValueDict;
- }
- 对一个文章内出现的多个词进行消重是因为如果一个文章里堆叠关键词会影响本聚类关键词提取的准确性,所以要排重,算法如下,也是泛型的
- public static IEnumerable<T> GetDistinctWords<T>(IEnumerable<T> scanKeys)
- {
- T temp = default(T);
- if (scanKeys.Equals(temp))
- return new T[0];
- else
- {
- Dictionary<T, T> fixKeys = new Dictionary<T, T>();
- foreach (T key in scanKeys)
- {
- fixKeys[key] = key;
- }
- T[] result = new T[fixKeys.Count];
- fixKeys.Values.CopyTo(result, 0);
- return result;
- }
- }
- 最后效果如下
- Iteration 0...
- Iteration 1...
- ---------asp,net,-------
- a ASP.NET 自定义 控件 复杂 属性 声明 持久性 浅析
- a asp.net 控件 开发 显示 控件 内容
- a 介绍 一 个 ASP.net MVC 系列 教程
- a 在 asp.net 中 实现 观察者 模式 ,或 有 更 好 的 方法 (续)
- a Asp.Net 页面 执行 流程 分析
- ---------股民,印花税,-------
- a 股民 要 清楚 自己 的 目的
- a 印花税 之 股民 四季
- a 某 心理 健康 站 开张 后 首 个 咨询 者 是 位 新 股民
- a 输 大钱 的 股民 给 我们 启迪
- a 杭州 股民 放 鞭炮 庆祝 印花税 下调
- ---------奥运,拳击,-------
- a 奥运 拳击 入场券 基本 分罄 邹市明 夺冠 对手 浮出 水面
- a 运动员 行李 将 “后 上 先 下” 奥运 相关 人员 行李 实名制
- a 奥运 票务 网上 成功 订票 后 应 及时 到 银行 代售 网点 付款
- a 残疾 女 青年 入围 奥运 游泳 比赛 创 奥运 历史 两 项 第一
- 可以看到,提取的关键字还是准确的,并没把a当成关键字。
|