您的位置:首页 > 其它

文本分类之特征简约

2011-07-27 09:20 239 查看
转自:http://hi.baidu.com/algorithms/blog/item/565243d9c5c009e238012f1e.html

feature reduce(特征简约)在classify(分类)中是一个常见的技术。它的主要目的是降维。
在文本分类中,所谓的降维就是减少词语的个数。
而一个好的降维算法,必须能够保留大部分有效信息,而删除大部分无效信息。(即所谓的召回率和准确率)

降维算法有很多,我们这里考虑的是基于样本的降维。
举例来说,现在已知有4个类,而现在4个词语。把每个类包含的词语个数向量组合在一起,构造一个矩阵,
假设为:
1 1 1 1
2 2 1 1
1 1 0 0
1 0 0 0
1 1 1 0
这里,第一行表示第一个词语在每个类中都出现了一次,
第二行表示第二个词语在前面2个类中出现了2次,在后面2个类中各出现了1次。

直观上面来说,我们根据上面的矩阵,可以了解到如下信息:
1、第一个词语没有任何分离度,它不包含啥有效信息;因为它在每个类中出现的次数一样;
我们给它的参考分值为0;
2、第二个词语有一定分离度,它具有明显的偏向性。
我们给它的参考分值为0.4;
3、第三个词语分离度较高,可以把4个类划分为2部分。
我们给它的参考分值为0.45;
4、第四个词语区分度很高,有它存在的文档几乎可以认为就是属于第一个分类了。
我们给它的参考分值为0.8;
5、第五个词语的分离度也很高,没有它的时候,有一定概率属于第4个分类。
我们给它的参考分值为0.45;
基于以上假设和直观,我们测试了常见的几种算法,包括:
1、df: 文档出现频率;
2、IG: 信息增益;
3、MI:
4、CHI:
5、SD: 标准差;
6、DF*IDF:
7、DF*IDF*SD:
我们最终得到的结果是:
CHI和DF*IDF*SD的效果好于其他算法。
我们对近4千万商品数据进行的实际计算也表明了CHI和DF*IDF*SD算法和人的思维
比较接近,而CHI/MI等其他流行算法效果很差。
下面是比较算法时候的java代码(为啥不用c++?因为java容易写啊)

/**
* 测试特征简约的各种算法效果 <br>
* 结果分析:
* <ol>
* <li>CHI和DF*IDF*SD的效果好于其他算法</li>
* </ol>
* 参考文献:
* <ul>
* <li>[97][Yiming Yang, Jan O. Pedersen] A comparative study on feature
* selection in text categorization </li>
* <li>[08][熊忠阳, 黎刚, 陈小莉, 陈伟] 文本分类中词语权重计算方法的改进与应用 </li>
* </ul>
*
* @author goodzhu
*
*/
public class TestFeatureReduce {
static double one = 10; // 每个类的文档个数
static double total = one * 4; // 总文档个数
static int[][] tfss = {
{ 1, 1, 1, 1 }, // 每个类里面包含本词语的文档个数。建议分数:0
{ 2, 2, 1, 1 }, // 建议分数:0.4
{ 1, 1, 0, 0 }, // 建议分数:0.45
{ 1, 0, 0, 0 }, // 建议分数:0.8
{ 1, 1, 1, 0 } // 建议分数:0.5
};
// df
public static void testDF() {
System.out.println("df: ");
for (int[] tfs : tfss) {
double pt = 0; // p(t)
for (int tf : tfs) {
if (tf == 0)
continue;
pt += tf;
}
System.out.println(pt / total);
}
}
// ig
public static void testIG() {
System.out.println("ig: ");
for (int[] tfs : tfss) {
double pt = 0; // p(t)
double pct = 0;
double pnotct = 0;
for (int tf : tfs) {
if (tf == 0)
continue;
pt += tf;
pct += tf / one * Math.log(tf / one);
pnotct += (1 - tf / one) * Math.log(1 - tf / one);
}
double p = 1 + pt / total * pct + (1 - pt / total) * pnotct;
System.out.println(p);
}
}
// mi
public static void testMI() {
System.out.println("mi: ");
for (int[] tfs : tfss) {
double pt = 0; // p(t)
for (int tf : tfs)
pt += tf;
double avgItc = 0;
for (int tf : tfs) {
if (tf == 0)
continue;
double itc = Math.log(tf / one / (pt / total * one / total));
// double itc = Math.log(tf * total / one * pt);
avgItc += itc * (one / total);
}
System.out.println(avgItc);
}
}
// chi
public static void testCHI() {
System.out.println("chi: ");
for (int[] tfs : tfss) {
double pt = 0; // p(t)
for (int tf : tfs)
pt += tf;
double avgX2tc = 0;
for (int tf : tfs) {
double A = tf;
double B = pt - tf;
double C = one - tf;
double D = total - (pt - tf) - one;
double N = total;
avgX2tc += N * (A * D - C * B) * (A * D - C * B)
/ ((A + C) * (B + D) * (A + B) * (C + D))
* (one / total);
}
System.out.println(avgX2tc);
}
}

// sd 标准差
public static void testSD()
{
System.out.println("sd: ");
for (int[] tfs : tfss) {
double avg = 0;
for (int tf : tfs)
avg += tf;
avg /= tfs.length;

double st = 0;
for (int tf : tfs) {
st += (tf - avg) * (tf - avg);
}

st = Math.sqrt(st / (tfs.length - 1) );
System.out.println(st);
}
}

// df * idf
public static void testDFIDF()
{
System.out.println("df * idf: ");
for (int[] tfs : tfss) {
double df = 0;
for (int tf : tfs)
{
if(tf > 0)
df ++;
}
double dfidf = df * Math.log(tfs.length / df + 0.1);
System.out.println(dfidf);
}
}

// df * idf * sd
public static void testDFIDFSD()
{
System.out.println("df * idf * sd: ");
for (int[] tfs : tfss) {
double df = 0;
for (int tf : tfs)
{
if(tf > 0)
df ++;
}

double dfidf = df * Math.log(tfs.length / df + 0.1);

double avg = 0;
for (int tf : tfs)
avg += tf;
avg /= tfs.length;
double sd = 0;
for (int tf : tfs) {
sd += (tf - avg) * (tf - avg);
}

sd = Math.sqrt(sd / (tfs.length - 1) );

double dfidfsd = dfidf * sd;
System.out.println(dfidfsd);
}
}
public static void main(String[] args) {
testDF();
testIG();
testMI();
testCHI();
testSD();
testDFIDF();
testDFIDFSD();
}
}
// 备注:
// 1) 需要考虑文档里面包含的词语t的个数
// 2) 对分类还可以进一步粗略化,当分类是一个层次的时候,粗略化应该会分级别
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: